From 2923c43f8f8790b1fcdd6b1a4fe269f78044f3e5 Mon Sep 17 00:00:00 2001 From: chirpy <50025123+waytotheweb@users.noreply.github.com> Date: Thu, 28 Aug 2025 15:15:56 +0100 Subject: [PATCH] GPL v3 Release --- COPYING.md | 16 + LICENSE.txt | 674 + README.md | 51 +- cmc.tgz | Bin 0 -> 211489 bytes cmc/INSTALL.txt | 43 + cmc/changelog.txt | 173 + cmc/cmc.cgi | 1454 ++ cmc/cmc.conf | 27 + cmc/cmc.tmpl | 29 + cmc/cmc/bootstrap/css/bootstrap.min.css | 6 + .../fonts/glyphicons-halflings-regular.eot | Bin 0 -> 20127 bytes .../fonts/glyphicons-halflings-regular.svg | 288 + .../fonts/glyphicons-halflings-regular.ttf | Bin 0 -> 45404 bytes .../fonts/glyphicons-halflings-regular.woff | Bin 0 -> 23424 bytes .../fonts/glyphicons-halflings-regular.woff2 | Bin 0 -> 18028 bytes cmc/cmc/bootstrap/js/bootstrap.min.js | 7 + cmc/cmc/cmc.png | Bin 0 -> 1691 bytes cmc/cmc/configserver.css | 123 + cmc/cmc/jquery.min.js | 5 + cmc/cmc/minus.png | Bin 0 -> 142 bytes cmc/cmc/plus.png | Bin 0 -> 150 bytes cmc/cmcversion.txt | 1 + cmc/cmcwrap.pl | 159 + cmc/downloadservers | 2 + cmc/install.sh | 63 + cmc/license.txt | 674 + cmc/uninstall.sh | 39 + cmc/upgrade.sh | 29 + cmm.tgz | Bin 0 -> 221778 bytes cmm/CHANGELOG.txt | 215 + cmm/INSTALL.txt | 22 + cmm/cmm.cgi | 1733 +++ cmm/cmm.conf | 27 + cmm/cmm.conf.old | 23 + cmm/cmm.tmpl | 29 + cmm/cmm/bootstrap/css/bootstrap.min.css | 6 + .../fonts/glyphicons-halflings-regular.eot | Bin 0 -> 20127 bytes .../fonts/glyphicons-halflings-regular.svg | 288 + .../fonts/glyphicons-halflings-regular.ttf | Bin 0 -> 45404 bytes .../fonts/glyphicons-halflings-regular.woff | Bin 0 -> 23424 bytes .../fonts/glyphicons-halflings-regular.woff2 | Bin 0 -> 18028 bytes cmm/cmm/bootstrap/js/bootstrap.min.js | 7 + cmm/cmm/cmm.png | Bin 0 -> 1950 bytes cmm/cmm/cmm.svg | 64 + cmm/cmm/configserver.css | 128 + cmm/cmm/jquery.min.js | 5 + cmm/cmmversion.txt | 1 + cmm/downloadservers | 2 + cmm/install.sh | 81 + cmm/license.txt | 674 + cmm/{cmm_uninstall.sh => uninstall.sh} | 0 cmm/upgrade.sh | 11 + cmq.tgz | Bin 0 -> 223906 bytes cmq/CHANGELOG.txt | 185 + cmq/INSTALL.txt | 14 + cmq/Modules/ConfigServer/cmqUI.pm | 1029 ++ cmq/cmq.c | 57 + cmq/cmq/admin_icon.svg | 90 + cmq/cmq/bootstrap/css/bootstrap.min.css | 6 + .../fonts/glyphicons-halflings-regular.eot | Bin 0 -> 20127 bytes .../fonts/glyphicons-halflings-regular.svg | 288 + .../fonts/glyphicons-halflings-regular.ttf | Bin 0 -> 45404 bytes .../fonts/glyphicons-halflings-regular.woff | Bin 0 -> 23424 bytes .../fonts/glyphicons-halflings-regular.woff2 | Bin 0 -> 18028 bytes cmq/cmq/bootstrap/js/bootstrap.min.js | 7 + cmq/cmq/cmq.js | 129 + cmq/cmq/cmq.png | Bin 0 -> 1571 bytes cmq/cmq/cmq.svg | 25 + cmq/cmq/configserver.css | 76 + cmq/cmq/jquery.min.js | 5 + cmq/cmq/minus.png | Bin 0 -> 911 bytes cmq/cmq/plus.png | Bin 0 -> 951 bytes cmq/cmqversion.txt | 1 + cmq/cpanel/cmq.cgi | 140 + cmq/cpanel/cmq.conf | 27 + cmq/cpanel/cmq.tmpl | 29 + cmq/da/admin/index.html | 31 + cmq/da/admin/index.raw | 7 + cmq/da/exec/da_cmq.cgi | 147 + cmq/da/hooks/admin_img.html | 4 + cmq/da/hooks/admin_txt.html | 1 + cmq/da/plugin.conf | 8 + cmq/da/scripts/install.sh | 5 + cmq/da/scripts/uninstall.sh | 5 + cmq/da/scripts/update.sh | 5 + cmq/downloadservers | 2 + cmq/install.cpanel.sh | 64 + cmq/install.directadmin.sh | 58 + cmq/install.sh | 30 + cmq/license.txt | 674 + cmq/uninstall.sh | 56 + cmq/upgrade.sh | 11 + cse.tgz | Bin 0 -> 214154 bytes cse/CHANGELOG.txt | 102 + cse/INSTALL.txt | 22 + cse/cse.cgi | 1515 ++ cse/cse.conf | 27 + cse/cse.conf.old | 23 + cse/cse.tmpl | 29 + cse/cse/bootstrap/css/bootstrap.min.css | 6 + .../fonts/glyphicons-halflings-regular.eot | Bin 0 -> 20127 bytes .../fonts/glyphicons-halflings-regular.svg | 288 + .../fonts/glyphicons-halflings-regular.ttf | Bin 0 -> 45404 bytes .../fonts/glyphicons-halflings-regular.woff | Bin 0 -> 23424 bytes .../fonts/glyphicons-halflings-regular.woff2 | Bin 0 -> 18028 bytes cse/cse/bootstrap/js/bootstrap.min.js | 7 + cse/cse/configserver.css | 128 + cse/cse/cse.png | Bin 0 -> 2170 bytes cse/cse/cse.svg | 59 + cse/cse/jquery.min.js | 5 + cse/cseversion.txt | 1 + cse/downloadservers | 2 + cse/install.sh | 65 + cse/license.txt | 674 + cse/{cse_uninstall.sh => uninstall.sh} | 0 cse/upgrade.sh | 11 + csf.tgz | Bin 0 -> 2297087 bytes csf/ConfigServer/AbuseIP.pm | 100 + csf/ConfigServer/CheckIP.pm | 160 + csf/ConfigServer/CloudFlare.pm | 533 + csf/ConfigServer/Config.pm | 457 + csf/ConfigServer/DisplayResellerUI.pm | 241 + csf/ConfigServer/DisplayUI.pm | 2954 ++++ csf/ConfigServer/GetEthDev.pm | 170 + csf/ConfigServer/GetIPs.pm | 95 + csf/ConfigServer/KillSSH.pm | 107 + csf/ConfigServer/Logger.pm | 83 + csf/ConfigServer/LookUpIP.pm | 439 + csf/ConfigServer/Messenger.pm | 1290 ++ csf/ConfigServer/Ports.pm | 226 + csf/ConfigServer/RBLCheck.pm | 255 + csf/ConfigServer/RBLLookup.pm | 116 + csf/ConfigServer/RegexMain.pm | 1028 ++ csf/ConfigServer/Sanity.pm | 86 + csf/ConfigServer/Sendmail.pm | 179 + csf/ConfigServer/ServerCheck.pm | 1775 +++ csf/ConfigServer/ServerStats.pm | 3560 +++++ csf/ConfigServer/Service.pm | 131 + csf/ConfigServer/Slurp.pm | 68 + csf/ConfigServer/URLGet.pm | 305 + csf/ConfigServer/cseUI.pm | 1042 ++ csf/Crypt/Blowfish_PP.pm | 519 + csf/Crypt/CBC.pm | 1064 ++ csf/HTTP/Tiny.pm | 2425 ++++ csf/JSON/Tiny.pm | 306 + csf/Module/Installed/Tiny.pm | 223 + csf/Net/CIDR/Lite.pm | 685 + csf/Net/IP.pm | 2679 ++++ csf/accounttracking.txt | 9 + csf/alert.txt | 13 + csf/apache.http.txt | 35 + csf/apache.https.txt | 43 + csf/apache.main.txt | 0 csf/apf_stub.pl | 43 + csf/auto.cwp.pl | 605 + csf/auto.cyberpanel.pl | 589 + csf/auto.directadmin.pl | 618 + csf/auto.generic.pl | 589 + csf/auto.interworx.pl | 589 + csf/auto.pl | 1252 ++ csf/auto.vesta.pl | 605 + csf/changelog.txt | 6142 +++++++++ csf/connectiontracking.txt | 11 + csf/consolealert.txt | 5 + csf/cpanel.allow | 100 + csf/cpanel.comodo.allow | 56 + csf/cpanel.comodo.ignore | 36 + csf/cpanel.ignore | 35 + csf/cpanel/Driver/ConfigServercsf.pm | 51 + csf/cpanel/Driver/ConfigServercsf/META.pm | 46 + csf/cpanel/csf.cgi | 340 + csf/cpanel/csf.conf | 28 + csf/cpanel/csf.tmpl | 29 + csf/cpanel/upgrade.sh | 12 + csf/cpanelalert.txt | 11 + csf/csf.1.txt | 284 + csf/csf.allow | 33 + csf/csf.blocklists | 116 + csf/csf.c | 85 + csf/csf.cloudflare | 63 + csf/csf.conf | 2825 ++++ csf/csf.cwp.allow | 30 + csf/csf.cwp.conf | 2685 ++++ csf/csf.cwp.ignore | 25 + csf/csf.cwp.pignore | 116 + csf/csf.cyberpanel.allow | 30 + csf/csf.cyberpanel.conf | 2679 ++++ csf/csf.cyberpanel.ignore | 25 + csf/csf.cyberpanel.pignore | 108 + csf/csf.deny | 31 + csf/csf.directadmin.allow | 30 + csf/csf.directadmin.conf | 2739 ++++ csf/csf.directadmin.ignore | 25 + csf/csf.directadmin.pignore | 95 + csf/csf.dirwatch | 27 + csf/csf.div | 230 + csf/csf.dyndns | 31 + csf/csf.fignore | 41 + csf/csf.generic.allow | 30 + csf/csf.generic.conf | 2678 ++++ csf/csf.generic.ignore | 25 + csf/csf.generic.pignore | 81 + csf/csf.help | 222 + csf/csf.ignore | 28 + csf/csf.interworx.allow | 30 + csf/csf.interworx.conf | 2686 ++++ csf/csf.interworx.ignore | 25 + csf/csf.interworx.pignore | 101 + csf/csf.logfiles | 49 + csf/csf.logignore | 88 + csf/csf.mignore | 22 + csf/csf.pignore | 158 + csf/csf.pl | 6009 ++++++++ csf/csf.rblconf | 35 + csf/csf.rbls | 41 + csf/csf.redirect | 47 + csf/csf.resellers | 60 + csf/csf.rignore | 53 + csf/csf.service | 13 + csf/csf.sh | 103 + csf/csf.signore | 20 + csf/csf.sips | 22 + csf/csf.smtpauth | 25 + csf/csf.suignore | 20 + csf/csf.syslogs | 103 + csf/csf.syslogusers | 79 + csf/csf.uidignore | 22 + csf/csf.vesta.allow | 30 + csf/csf.vesta.conf | 2685 ++++ csf/csf.vesta.ignore | 25 + csf/csf.vesta.pignore | 118 + csf/csf/LICENSE.txt | 14 + csf/csf/admin_icon.svg | 25 + csf/csf/bootstrap-chosen.css | 346 + csf/csf/bootstrap/css/bootstrap.min.css | 6 + csf/csf/bootstrap/css/bootstrap.min.css.map | 1 + .../fonts/glyphicons-halflings-regular.eot | Bin 0 -> 20127 bytes .../fonts/glyphicons-halflings-regular.svg | 288 + .../fonts/glyphicons-halflings-regular.ttf | Bin 0 -> 45404 bytes .../fonts/glyphicons-halflings-regular.woff | Bin 0 -> 23424 bytes .../fonts/glyphicons-halflings-regular.woff2 | Bin 0 -> 18028 bytes csf/csf/bootstrap/js/bootstrap.min.js | 7 + csf/csf/chosen-sprite.png | Bin 0 -> 646 bytes csf/csf/chosen-sprite@2x.png | Bin 0 -> 872 bytes csf/csf/chosen.min.css | 11 + csf/csf/chosen.min.js | 3 + csf/csf/configserver.css | 193 + csf/csf/csf-loader.gif | Bin 0 -> 3951 bytes csf/csf/csf.svg | 25 + csf/csf/csf_small.png | Bin 0 -> 2211 bytes csf/csf/jquery.min.js | 5 + csf/csf/loader.gif | Bin 0 -> 3951 bytes csf/csf/reseller_icon.svg | 25 + csf/csfajaxtail.js | 145 + csf/csfcron.sh | 1 + csf/csftest.pl | 181 + csf/csget.pl | 103 + csf/cwp/ajax_csfframe.php | 22 + csf/cwp/configserver.php | 22 + csf/cwp/csf.pl | 208 + csf/cwp/csfofficial.php | 9 + csf/cyberpanel/configservercsf/__init__.py | 1 + csf/cyberpanel/configservercsf/admin.py | 6 + csf/cyberpanel/configservercsf/apps.py | 10 + csf/cyberpanel/configservercsf/config | 0 csf/cyberpanel/configservercsf/meta.xml | 7 + .../configservercsf/migrations/__init__.py | 0 csf/cyberpanel/configservercsf/models.py | 6 + csf/cyberpanel/configservercsf/signals.py | 13 + .../templates/configservercsf/index.html | 17 + .../templates/configservercsf/menu.html | 25 + csf/cyberpanel/configservercsf/tests.py | 6 + csf/cyberpanel/configservercsf/urls.py | 8 + csf/cyberpanel/configservercsf/views.py | 64 + csf/cyberpanel/cyberpanel.pl | 218 + csf/da/admin/index.html | 31 + csf/da/admin/index.raw | 7 + csf/da/exec/da_csf.cgi | 321 + csf/da/exec/da_csf_reseller.cgi | 315 + csf/da/hooks/admin_img.html | 4 + csf/da/hooks/admin_txt.html | 1 + csf/da/hooks/reseller_img.html | 4 + csf/da/hooks/reseller_txt.html | 1 + csf/da/images/LICENSE.txt | 14 + csf/da/images/admin_icon.svg | 25 + csf/da/images/bootstrap-chosen.css | 346 + csf/da/images/bootstrap/css/bootstrap.min.css | 6 + .../bootstrap/css/bootstrap.min.css.map | 1 + .../fonts/glyphicons-halflings-regular.eot | Bin 0 -> 20127 bytes .../fonts/glyphicons-halflings-regular.svg | 288 + .../fonts/glyphicons-halflings-regular.ttf | Bin 0 -> 45404 bytes .../fonts/glyphicons-halflings-regular.woff | Bin 0 -> 23424 bytes .../fonts/glyphicons-halflings-regular.woff2 | Bin 0 -> 18028 bytes csf/da/images/bootstrap/js/bootstrap.min.js | 7 + csf/da/images/chosen-sprite.png | Bin 0 -> 646 bytes csf/da/images/chosen-sprite@2x.png | Bin 0 -> 872 bytes csf/da/images/chosen.min.css | 11 + csf/da/images/chosen.min.js | 3 + csf/da/images/configserver.css | 193 + csf/da/images/csf-loader.gif | Bin 0 -> 3951 bytes csf/da/images/csf.svg | 25 + csf/da/images/csf_small.png | Bin 0 -> 2211 bytes csf/da/images/jquery.min.js | 5 + csf/da/images/loader.gif | Bin 0 -> 3951 bytes csf/da/images/reseller_icon.svg | 25 + csf/da/plugin.conf | 8 + csf/da/reseller/index.html | 31 + csf/da/reseller/index.raw | 7 + csf/da/scripts/install.sh | 5 + csf/da/scripts/uninstall.sh | 5 + csf/da/scripts/update.sh | 5 + csf/downloadservers | 2 + csf/exploitalert.txt | 7 + csf/filealert.txt | 9 + csf/forkbombalert.txt | 10 + csf/install.cpanel.sh | 580 + csf/install.cwp.sh | 556 + csf/install.cyberpanel.sh | 549 + csf/install.directadmin.sh | 534 + csf/install.generic.sh | 528 + csf/install.interworx.sh | 553 + csf/install.sh | 53 + csf/install.txt | 106 + csf/install.vesta.sh | 536 + csf/integrityalert.txt | 9 + .../Ctrl/Nodeworx/Configservercsf.php | 49 + csf/interworx/Plugin/Configservercsf.php | 147 + csf/interworx/images/LICENSE.txt | 14 + csf/interworx/images/admin_icon.svg | 25 + csf/interworx/images/bootstrap-chosen.css | 346 + .../images/bootstrap/css/bootstrap.min.css | 6 + .../bootstrap/css/bootstrap.min.css.map | 1 + .../fonts/glyphicons-halflings-regular.eot | Bin 0 -> 20127 bytes .../fonts/glyphicons-halflings-regular.svg | 288 + .../fonts/glyphicons-halflings-regular.ttf | Bin 0 -> 45404 bytes .../fonts/glyphicons-halflings-regular.woff | Bin 0 -> 23424 bytes .../fonts/glyphicons-halflings-regular.woff2 | Bin 0 -> 18028 bytes .../images/bootstrap/js/bootstrap.min.js | 7 + csf/interworx/images/chosen-sprite.png | Bin 0 -> 646 bytes csf/interworx/images/chosen-sprite@2x.png | Bin 0 -> 872 bytes csf/interworx/images/chosen.min.css | 11 + csf/interworx/images/chosen.min.js | 3 + csf/interworx/images/configserver.css | 193 + csf/interworx/images/csf-loader.gif | Bin 0 -> 3951 bytes csf/interworx/images/csf.svg | 25 + csf/interworx/images/csf_small.png | Bin 0 -> 2211 bytes csf/interworx/images/jquery.min.js | 5 + csf/interworx/images/loader.gif | Bin 0 -> 3951 bytes csf/interworx/images/reseller_icon.svg | 25 + csf/interworx/lib/index.pl | 213 + csf/interworx/lib/reseller.pl | 241 + csf/interworx/plugin.ini | 5 + csf/interworx/templates/admin.tpl | 10 + csf/interworx/templates/reseller.tpl | 10 + csf/lfd.logrotate | 12 + csf/lfd.pl | 11384 ++++++++++++++++ csf/lfd.service | 12 + csf/lfd.sh | 115 + csf/lfdcron.directadmin.sh | 2 + csf/lfdcron.sh | 2 + csf/license.txt | 674 + csf/litespeed.http.txt | 15 + csf/litespeed.https.txt | 32 + csf/litespeed.main.txt | 0 csf/loadalert.txt | 55 + csf/logalert.txt | 5 + csf/logfloodalert.txt | 6 + csf/messenger/en.php | 15 + csf/messenger/index.html | 195 + csf/messenger/index.php | 212 + csf/messenger/index.recaptcha.html | 229 + csf/messenger/index.recaptcha.php | 273 + csf/messenger/index.text | 4 + csf/migratedata.sh | 257 + csf/modsecipdbalert.txt | 9 + csf/netblock.txt | 10 + csf/os.pl | 185 + csf/perf.sh | 9 + csf/permblock.txt | 10 + csf/portknocking.txt | 7 + csf/portscan.txt | 11 + csf/processtracking.txt | 31 + csf/profiles/block_all_perm.conf | 32 + csf/profiles/block_all_temp.conf | 32 + csf/profiles/disable_alerts.conf | 38 + csf/profiles/protection_high.conf | 61 + csf/profiles/protection_low.conf | 60 + csf/profiles/protection_medium.conf | 62 + csf/pt_deleted_action.pl | 39 + csf/queuealert.txt | 7 + csf/readme.txt | 1747 +++ csf/recaptcha.txt | 8 + csf/regex.custom.pm | 63 + csf/relayalert.txt | 12 + csf/remove_apf_bfd.sh | 22 + csf/resalert.txt | 12 + csf/reselleralert.txt | 10 + csf/restricted.txt | 105 + csf/sanity.txt | 232 + csf/scriptalert.txt | 15 + csf/sshalert.txt | 12 + csf/sualert.txt | 12 + csf/sudoalert.txt | 12 + csf/syslogalert.txt | 8 + csf/tracking.txt | 12 + csf/ui/images/LICENSE.txt | 14 + csf/ui/images/admin_icon.svg | 25 + csf/ui/images/bootstrap-chosen.css | 346 + csf/ui/images/bootstrap/css/bootstrap.min.css | 6 + .../bootstrap/css/bootstrap.min.css.map | 1 + .../fonts/glyphicons-halflings-regular.eot | Bin 0 -> 20127 bytes .../fonts/glyphicons-halflings-regular.svg | 288 + .../fonts/glyphicons-halflings-regular.ttf | Bin 0 -> 45404 bytes .../fonts/glyphicons-halflings-regular.woff | Bin 0 -> 23424 bytes .../fonts/glyphicons-halflings-regular.woff2 | Bin 0 -> 18028 bytes csf/ui/images/bootstrap/js/bootstrap.min.js | 7 + csf/ui/images/chosen-sprite.png | Bin 0 -> 646 bytes csf/ui/images/chosen-sprite@2x.png | Bin 0 -> 872 bytes csf/ui/images/chosen.min.css | 11 + csf/ui/images/chosen.min.js | 3 + csf/ui/images/configserver.css | 193 + csf/ui/images/csf-loader.gif | Bin 0 -> 3951 bytes csf/ui/images/csf.svg | 25 + csf/ui/images/csf_small.png | Bin 0 -> 2211 bytes csf/ui/images/jquery.min.js | 5 + csf/ui/images/loader.gif | Bin 0 -> 3951 bytes csf/ui/images/reseller_icon.svg | 25 + csf/ui/server.crt | 20 + csf/ui/server.key | 28 + csf/ui/ui.allow | 0 csf/ui/ui.ban | 0 csf/uialert.txt | 9 + csf/uidscan.txt | 10 + csf/{uninstall.cpanel.sh => uninstall.sh} | 0 csf/upgrade.txt | 35 + csf/usertracking.txt | 11 + csf/version.txt | 1 + csf/version/version.pm | 126 + csf/version/version/regex.pm | 117 + csf/version/version/vpp.pm | 1037 ++ csf/vestacp/csf.pl | 207 + csf/vestacp/frame.php | 30 + csf/vestacp/index.php | 34 + csf/watchalert.txt | 10 + csf/webmin/csf/images/LICENSE.txt | 14 + csf/webmin/csf/images/admin_icon.svg | 25 + csf/webmin/csf/images/bootstrap-chosen.css | 346 + .../images/bootstrap/css/bootstrap.min.css | 6 + .../bootstrap/css/bootstrap.min.css.map | 1 + .../fonts/glyphicons-halflings-regular.eot | Bin 0 -> 20127 bytes .../fonts/glyphicons-halflings-regular.svg | 288 + .../fonts/glyphicons-halflings-regular.ttf | Bin 0 -> 45404 bytes .../fonts/glyphicons-halflings-regular.woff | Bin 0 -> 23424 bytes .../fonts/glyphicons-halflings-regular.woff2 | Bin 0 -> 18028 bytes .../csf/images/bootstrap/js/bootstrap.min.js | 7 + csf/webmin/csf/images/chosen-sprite.png | Bin 0 -> 646 bytes csf/webmin/csf/images/chosen-sprite@2x.png | Bin 0 -> 872 bytes csf/webmin/csf/images/chosen.min.css | 11 + csf/webmin/csf/images/chosen.min.js | 3 + csf/webmin/csf/images/configserver.css | 193 + csf/webmin/csf/images/csf-loader.gif | Bin 0 -> 3951 bytes csf/webmin/csf/images/csf.svg | 25 + csf/webmin/csf/images/csf_small.png | Bin 0 -> 2211 bytes csf/webmin/csf/images/jquery.min.js | 5 + csf/webmin/csf/images/loader.gif | Bin 0 -> 3951 bytes csf/webmin/csf/images/reseller_icon.svg | 25 + csf/webmin/csf/index.cgi | 249 + csf/webmin/csf/module.info | 3 + csf/webminalert.txt | 11 + csf/x-arf.txt | 45 + .../MailScanner}/msuninstall.pl | 19 +- .../MailScanner}/msuninstall.sh | 19 +- uninstallers/README.md | 52 + {cmc => uninstallers/cmc}/cmc_uninstall.sh | 19 +- uninstallers/cmm/cmm_uninstall.sh | 37 + {cmq => uninstallers/cmq}/cmq_uninstall.sh | 19 +- uninstallers/cse/cse_uninstall.sh | 37 + uninstallers/csf/uninstall.cpanel.sh | 77 + uninstallers/csf/uninstall.cwp.sh | 61 + uninstallers/csf/uninstall.cyberpanel.sh | 70 + uninstallers/csf/uninstall.directadmin.sh | 61 + uninstallers/csf/uninstall.generic.sh | 58 + uninstallers/csf/uninstall.interworx.sh | 64 + uninstallers/csf/uninstall.vesta.sh | 61 + {cxs => uninstallers/cxs}/uninstall.cpanel.sh | 0 {cxs => uninstallers/cxs}/uninstall.cwp.sh | 0 .../cxs}/uninstall.cyberpanel.sh | 0 .../cxs}/uninstall.directadmin.sh | 0 .../cxs}/uninstall.generic.sh | 0 .../cxs}/uninstall.interworx.sh | 0 {cxs => uninstallers/cxs}/uninstall.plesk.sh | 0 .../cxs}/uninstall.vestacp.sh | 0 {osm => uninstallers/osm}/uninstall.cpanel.sh | 0 .../osm}/uninstall.directadmin.sh | 0 494 files changed, 106870 insertions(+), 58 deletions(-) create mode 100644 COPYING.md create mode 100644 LICENSE.txt create mode 100644 cmc.tgz create mode 100644 cmc/INSTALL.txt create mode 100644 cmc/changelog.txt create mode 100644 cmc/cmc.cgi create mode 100644 cmc/cmc.conf create mode 100644 cmc/cmc.tmpl create mode 100644 cmc/cmc/bootstrap/css/bootstrap.min.css create mode 100644 cmc/cmc/bootstrap/fonts/glyphicons-halflings-regular.eot create mode 100644 cmc/cmc/bootstrap/fonts/glyphicons-halflings-regular.svg create mode 100644 cmc/cmc/bootstrap/fonts/glyphicons-halflings-regular.ttf create mode 100644 cmc/cmc/bootstrap/fonts/glyphicons-halflings-regular.woff create mode 100644 cmc/cmc/bootstrap/fonts/glyphicons-halflings-regular.woff2 create mode 100644 cmc/cmc/bootstrap/js/bootstrap.min.js create mode 100644 cmc/cmc/cmc.png create mode 100644 cmc/cmc/configserver.css create mode 100644 cmc/cmc/jquery.min.js create mode 100644 cmc/cmc/minus.png create mode 100644 cmc/cmc/plus.png create mode 100644 cmc/cmcversion.txt create mode 100644 cmc/cmcwrap.pl create mode 100644 cmc/downloadservers create mode 100644 cmc/install.sh create mode 100644 cmc/license.txt create mode 100644 cmc/uninstall.sh create mode 100644 cmc/upgrade.sh create mode 100644 cmm.tgz create mode 100644 cmm/CHANGELOG.txt create mode 100644 cmm/INSTALL.txt create mode 100644 cmm/cmm.cgi create mode 100644 cmm/cmm.conf create mode 100644 cmm/cmm.conf.old create mode 100644 cmm/cmm.tmpl create mode 100644 cmm/cmm/bootstrap/css/bootstrap.min.css create mode 100644 cmm/cmm/bootstrap/fonts/glyphicons-halflings-regular.eot create mode 100644 cmm/cmm/bootstrap/fonts/glyphicons-halflings-regular.svg create mode 100644 cmm/cmm/bootstrap/fonts/glyphicons-halflings-regular.ttf create mode 100644 cmm/cmm/bootstrap/fonts/glyphicons-halflings-regular.woff create mode 100644 cmm/cmm/bootstrap/fonts/glyphicons-halflings-regular.woff2 create mode 100644 cmm/cmm/bootstrap/js/bootstrap.min.js create mode 100644 cmm/cmm/cmm.png create mode 100644 cmm/cmm/cmm.svg create mode 100644 cmm/cmm/configserver.css create mode 100644 cmm/cmm/jquery.min.js create mode 100644 cmm/cmmversion.txt create mode 100644 cmm/downloadservers create mode 100644 cmm/install.sh create mode 100644 cmm/license.txt rename cmm/{cmm_uninstall.sh => uninstall.sh} (100%) create mode 100644 cmm/upgrade.sh create mode 100644 cmq.tgz create mode 100644 cmq/CHANGELOG.txt create mode 100644 cmq/INSTALL.txt create mode 100644 cmq/Modules/ConfigServer/cmqUI.pm create mode 100644 cmq/cmq.c create mode 100644 cmq/cmq/admin_icon.svg create mode 100644 cmq/cmq/bootstrap/css/bootstrap.min.css create mode 100644 cmq/cmq/bootstrap/fonts/glyphicons-halflings-regular.eot create mode 100644 cmq/cmq/bootstrap/fonts/glyphicons-halflings-regular.svg create mode 100644 cmq/cmq/bootstrap/fonts/glyphicons-halflings-regular.ttf create mode 100644 cmq/cmq/bootstrap/fonts/glyphicons-halflings-regular.woff create mode 100644 cmq/cmq/bootstrap/fonts/glyphicons-halflings-regular.woff2 create mode 100644 cmq/cmq/bootstrap/js/bootstrap.min.js create mode 100644 cmq/cmq/cmq.js create mode 100644 cmq/cmq/cmq.png create mode 100644 cmq/cmq/cmq.svg create mode 100644 cmq/cmq/configserver.css create mode 100644 cmq/cmq/jquery.min.js create mode 100644 cmq/cmq/minus.png create mode 100644 cmq/cmq/plus.png create mode 100644 cmq/cmqversion.txt create mode 100644 cmq/cpanel/cmq.cgi create mode 100644 cmq/cpanel/cmq.conf create mode 100644 cmq/cpanel/cmq.tmpl create mode 100644 cmq/da/admin/index.html create mode 100644 cmq/da/admin/index.raw create mode 100644 cmq/da/exec/da_cmq.cgi create mode 100644 cmq/da/hooks/admin_img.html create mode 100644 cmq/da/hooks/admin_txt.html create mode 100644 cmq/da/plugin.conf create mode 100644 cmq/da/scripts/install.sh create mode 100644 cmq/da/scripts/uninstall.sh create mode 100644 cmq/da/scripts/update.sh create mode 100644 cmq/downloadservers create mode 100644 cmq/install.cpanel.sh create mode 100644 cmq/install.directadmin.sh create mode 100644 cmq/install.sh create mode 100644 cmq/license.txt create mode 100644 cmq/uninstall.sh create mode 100644 cmq/upgrade.sh create mode 100644 cse.tgz create mode 100644 cse/CHANGELOG.txt create mode 100644 cse/INSTALL.txt create mode 100644 cse/cse.cgi create mode 100644 cse/cse.conf create mode 100644 cse/cse.conf.old create mode 100644 cse/cse.tmpl create mode 100644 cse/cse/bootstrap/css/bootstrap.min.css create mode 100644 cse/cse/bootstrap/fonts/glyphicons-halflings-regular.eot create mode 100644 cse/cse/bootstrap/fonts/glyphicons-halflings-regular.svg create mode 100644 cse/cse/bootstrap/fonts/glyphicons-halflings-regular.ttf create mode 100644 cse/cse/bootstrap/fonts/glyphicons-halflings-regular.woff create mode 100644 cse/cse/bootstrap/fonts/glyphicons-halflings-regular.woff2 create mode 100644 cse/cse/bootstrap/js/bootstrap.min.js create mode 100644 cse/cse/configserver.css create mode 100644 cse/cse/cse.png create mode 100644 cse/cse/cse.svg create mode 100644 cse/cse/jquery.min.js create mode 100644 cse/cseversion.txt create mode 100644 cse/downloadservers create mode 100644 cse/install.sh create mode 100644 cse/license.txt rename cse/{cse_uninstall.sh => uninstall.sh} (100%) create mode 100644 cse/upgrade.sh create mode 100644 csf.tgz create mode 100644 csf/ConfigServer/AbuseIP.pm create mode 100644 csf/ConfigServer/CheckIP.pm create mode 100644 csf/ConfigServer/CloudFlare.pm create mode 100644 csf/ConfigServer/Config.pm create mode 100644 csf/ConfigServer/DisplayResellerUI.pm create mode 100644 csf/ConfigServer/DisplayUI.pm create mode 100644 csf/ConfigServer/GetEthDev.pm create mode 100644 csf/ConfigServer/GetIPs.pm create mode 100644 csf/ConfigServer/KillSSH.pm create mode 100644 csf/ConfigServer/Logger.pm create mode 100644 csf/ConfigServer/LookUpIP.pm create mode 100644 csf/ConfigServer/Messenger.pm create mode 100644 csf/ConfigServer/Ports.pm create mode 100644 csf/ConfigServer/RBLCheck.pm create mode 100644 csf/ConfigServer/RBLLookup.pm create mode 100644 csf/ConfigServer/RegexMain.pm create mode 100644 csf/ConfigServer/Sanity.pm create mode 100644 csf/ConfigServer/Sendmail.pm create mode 100644 csf/ConfigServer/ServerCheck.pm create mode 100644 csf/ConfigServer/ServerStats.pm create mode 100644 csf/ConfigServer/Service.pm create mode 100644 csf/ConfigServer/Slurp.pm create mode 100644 csf/ConfigServer/URLGet.pm create mode 100644 csf/ConfigServer/cseUI.pm create mode 100644 csf/Crypt/Blowfish_PP.pm create mode 100644 csf/Crypt/CBC.pm create mode 100644 csf/HTTP/Tiny.pm create mode 100644 csf/JSON/Tiny.pm create mode 100644 csf/Module/Installed/Tiny.pm create mode 100644 csf/Net/CIDR/Lite.pm create mode 100644 csf/Net/IP.pm create mode 100644 csf/accounttracking.txt create mode 100644 csf/alert.txt create mode 100644 csf/apache.http.txt create mode 100644 csf/apache.https.txt create mode 100644 csf/apache.main.txt create mode 100644 csf/apf_stub.pl create mode 100644 csf/auto.cwp.pl create mode 100644 csf/auto.cyberpanel.pl create mode 100644 csf/auto.directadmin.pl create mode 100644 csf/auto.generic.pl create mode 100644 csf/auto.interworx.pl create mode 100644 csf/auto.pl create mode 100644 csf/auto.vesta.pl create mode 100644 csf/changelog.txt create mode 100644 csf/connectiontracking.txt create mode 100644 csf/consolealert.txt create mode 100644 csf/cpanel.allow create mode 100644 csf/cpanel.comodo.allow create mode 100644 csf/cpanel.comodo.ignore create mode 100644 csf/cpanel.ignore create mode 100644 csf/cpanel/Driver/ConfigServercsf.pm create mode 100644 csf/cpanel/Driver/ConfigServercsf/META.pm create mode 100644 csf/cpanel/csf.cgi create mode 100644 csf/cpanel/csf.conf create mode 100644 csf/cpanel/csf.tmpl create mode 100644 csf/cpanel/upgrade.sh create mode 100644 csf/cpanelalert.txt create mode 100644 csf/csf.1.txt create mode 100644 csf/csf.allow create mode 100644 csf/csf.blocklists create mode 100644 csf/csf.c create mode 100644 csf/csf.cloudflare create mode 100644 csf/csf.conf create mode 100644 csf/csf.cwp.allow create mode 100644 csf/csf.cwp.conf create mode 100644 csf/csf.cwp.ignore create mode 100644 csf/csf.cwp.pignore create mode 100644 csf/csf.cyberpanel.allow create mode 100644 csf/csf.cyberpanel.conf create mode 100644 csf/csf.cyberpanel.ignore create mode 100644 csf/csf.cyberpanel.pignore create mode 100644 csf/csf.deny create mode 100644 csf/csf.directadmin.allow create mode 100644 csf/csf.directadmin.conf create mode 100644 csf/csf.directadmin.ignore create mode 100644 csf/csf.directadmin.pignore create mode 100644 csf/csf.dirwatch create mode 100644 csf/csf.div create mode 100644 csf/csf.dyndns create mode 100644 csf/csf.fignore create mode 100644 csf/csf.generic.allow create mode 100644 csf/csf.generic.conf create mode 100644 csf/csf.generic.ignore create mode 100644 csf/csf.generic.pignore create mode 100644 csf/csf.help create mode 100644 csf/csf.ignore create mode 100644 csf/csf.interworx.allow create mode 100644 csf/csf.interworx.conf create mode 100644 csf/csf.interworx.ignore create mode 100644 csf/csf.interworx.pignore create mode 100644 csf/csf.logfiles create mode 100644 csf/csf.logignore create mode 100644 csf/csf.mignore create mode 100644 csf/csf.pignore create mode 100644 csf/csf.pl create mode 100644 csf/csf.rblconf create mode 100644 csf/csf.rbls create mode 100644 csf/csf.redirect create mode 100644 csf/csf.resellers create mode 100644 csf/csf.rignore create mode 100644 csf/csf.service create mode 100644 csf/csf.sh create mode 100644 csf/csf.signore create mode 100644 csf/csf.sips create mode 100644 csf/csf.smtpauth create mode 100644 csf/csf.suignore create mode 100644 csf/csf.syslogs create mode 100644 csf/csf.syslogusers create mode 100644 csf/csf.uidignore create mode 100644 csf/csf.vesta.allow create mode 100644 csf/csf.vesta.conf create mode 100644 csf/csf.vesta.ignore create mode 100644 csf/csf.vesta.pignore create mode 100644 csf/csf/LICENSE.txt create mode 100644 csf/csf/admin_icon.svg create mode 100644 csf/csf/bootstrap-chosen.css create mode 100644 csf/csf/bootstrap/css/bootstrap.min.css create mode 100644 csf/csf/bootstrap/css/bootstrap.min.css.map create mode 100644 csf/csf/bootstrap/fonts/glyphicons-halflings-regular.eot create mode 100644 csf/csf/bootstrap/fonts/glyphicons-halflings-regular.svg create mode 100644 csf/csf/bootstrap/fonts/glyphicons-halflings-regular.ttf create mode 100644 csf/csf/bootstrap/fonts/glyphicons-halflings-regular.woff create mode 100644 csf/csf/bootstrap/fonts/glyphicons-halflings-regular.woff2 create mode 100644 csf/csf/bootstrap/js/bootstrap.min.js create mode 100644 csf/csf/chosen-sprite.png create mode 100644 csf/csf/chosen-sprite@2x.png create mode 100644 csf/csf/chosen.min.css create mode 100644 csf/csf/chosen.min.js create mode 100644 csf/csf/configserver.css create mode 100644 csf/csf/csf-loader.gif create mode 100644 csf/csf/csf.svg create mode 100644 csf/csf/csf_small.png create mode 100644 csf/csf/jquery.min.js create mode 100644 csf/csf/loader.gif create mode 100644 csf/csf/reseller_icon.svg create mode 100644 csf/csfajaxtail.js create mode 100644 csf/csfcron.sh create mode 100644 csf/csftest.pl create mode 100644 csf/csget.pl create mode 100644 csf/cwp/ajax_csfframe.php create mode 100644 csf/cwp/configserver.php create mode 100644 csf/cwp/csf.pl create mode 100644 csf/cwp/csfofficial.php create mode 100644 csf/cyberpanel/configservercsf/__init__.py create mode 100644 csf/cyberpanel/configservercsf/admin.py create mode 100644 csf/cyberpanel/configservercsf/apps.py create mode 100644 csf/cyberpanel/configservercsf/config create mode 100644 csf/cyberpanel/configservercsf/meta.xml create mode 100644 csf/cyberpanel/configservercsf/migrations/__init__.py create mode 100644 csf/cyberpanel/configservercsf/models.py create mode 100644 csf/cyberpanel/configservercsf/signals.py create mode 100644 csf/cyberpanel/configservercsf/templates/configservercsf/index.html create mode 100644 csf/cyberpanel/configservercsf/templates/configservercsf/menu.html create mode 100644 csf/cyberpanel/configservercsf/tests.py create mode 100644 csf/cyberpanel/configservercsf/urls.py create mode 100644 csf/cyberpanel/configservercsf/views.py create mode 100644 csf/cyberpanel/cyberpanel.pl create mode 100644 csf/da/admin/index.html create mode 100644 csf/da/admin/index.raw create mode 100644 csf/da/exec/da_csf.cgi create mode 100644 csf/da/exec/da_csf_reseller.cgi create mode 100644 csf/da/hooks/admin_img.html create mode 100644 csf/da/hooks/admin_txt.html create mode 100644 csf/da/hooks/reseller_img.html create mode 100644 csf/da/hooks/reseller_txt.html create mode 100644 csf/da/images/LICENSE.txt create mode 100644 csf/da/images/admin_icon.svg create mode 100644 csf/da/images/bootstrap-chosen.css create mode 100644 csf/da/images/bootstrap/css/bootstrap.min.css create mode 100644 csf/da/images/bootstrap/css/bootstrap.min.css.map create mode 100644 csf/da/images/bootstrap/fonts/glyphicons-halflings-regular.eot create mode 100644 csf/da/images/bootstrap/fonts/glyphicons-halflings-regular.svg create mode 100644 csf/da/images/bootstrap/fonts/glyphicons-halflings-regular.ttf create mode 100644 csf/da/images/bootstrap/fonts/glyphicons-halflings-regular.woff create mode 100644 csf/da/images/bootstrap/fonts/glyphicons-halflings-regular.woff2 create mode 100644 csf/da/images/bootstrap/js/bootstrap.min.js create mode 100644 csf/da/images/chosen-sprite.png create mode 100644 csf/da/images/chosen-sprite@2x.png create mode 100644 csf/da/images/chosen.min.css create mode 100644 csf/da/images/chosen.min.js create mode 100644 csf/da/images/configserver.css create mode 100644 csf/da/images/csf-loader.gif create mode 100644 csf/da/images/csf.svg create mode 100644 csf/da/images/csf_small.png create mode 100644 csf/da/images/jquery.min.js create mode 100644 csf/da/images/loader.gif create mode 100644 csf/da/images/reseller_icon.svg create mode 100644 csf/da/plugin.conf create mode 100644 csf/da/reseller/index.html create mode 100644 csf/da/reseller/index.raw create mode 100644 csf/da/scripts/install.sh create mode 100644 csf/da/scripts/uninstall.sh create mode 100644 csf/da/scripts/update.sh create mode 100644 csf/downloadservers create mode 100644 csf/exploitalert.txt create mode 100644 csf/filealert.txt create mode 100644 csf/forkbombalert.txt create mode 100644 csf/install.cpanel.sh create mode 100644 csf/install.cwp.sh create mode 100644 csf/install.cyberpanel.sh create mode 100644 csf/install.directadmin.sh create mode 100644 csf/install.generic.sh create mode 100644 csf/install.interworx.sh create mode 100644 csf/install.sh create mode 100644 csf/install.txt create mode 100644 csf/install.vesta.sh create mode 100644 csf/integrityalert.txt create mode 100644 csf/interworx/Ctrl/Nodeworx/Configservercsf.php create mode 100644 csf/interworx/Plugin/Configservercsf.php create mode 100644 csf/interworx/images/LICENSE.txt create mode 100644 csf/interworx/images/admin_icon.svg create mode 100644 csf/interworx/images/bootstrap-chosen.css create mode 100644 csf/interworx/images/bootstrap/css/bootstrap.min.css create mode 100644 csf/interworx/images/bootstrap/css/bootstrap.min.css.map create mode 100644 csf/interworx/images/bootstrap/fonts/glyphicons-halflings-regular.eot create mode 100644 csf/interworx/images/bootstrap/fonts/glyphicons-halflings-regular.svg create mode 100644 csf/interworx/images/bootstrap/fonts/glyphicons-halflings-regular.ttf create mode 100644 csf/interworx/images/bootstrap/fonts/glyphicons-halflings-regular.woff create mode 100644 csf/interworx/images/bootstrap/fonts/glyphicons-halflings-regular.woff2 create mode 100644 csf/interworx/images/bootstrap/js/bootstrap.min.js create mode 100644 csf/interworx/images/chosen-sprite.png create mode 100644 csf/interworx/images/chosen-sprite@2x.png create mode 100644 csf/interworx/images/chosen.min.css create mode 100644 csf/interworx/images/chosen.min.js create mode 100644 csf/interworx/images/configserver.css create mode 100644 csf/interworx/images/csf-loader.gif create mode 100644 csf/interworx/images/csf.svg create mode 100644 csf/interworx/images/csf_small.png create mode 100644 csf/interworx/images/jquery.min.js create mode 100644 csf/interworx/images/loader.gif create mode 100644 csf/interworx/images/reseller_icon.svg create mode 100644 csf/interworx/lib/index.pl create mode 100644 csf/interworx/lib/reseller.pl create mode 100644 csf/interworx/plugin.ini create mode 100644 csf/interworx/templates/admin.tpl create mode 100644 csf/interworx/templates/reseller.tpl create mode 100644 csf/lfd.logrotate create mode 100644 csf/lfd.pl create mode 100644 csf/lfd.service create mode 100644 csf/lfd.sh create mode 100644 csf/lfdcron.directadmin.sh create mode 100644 csf/lfdcron.sh create mode 100644 csf/license.txt create mode 100644 csf/litespeed.http.txt create mode 100644 csf/litespeed.https.txt create mode 100644 csf/litespeed.main.txt create mode 100644 csf/loadalert.txt create mode 100644 csf/logalert.txt create mode 100644 csf/logfloodalert.txt create mode 100644 csf/messenger/en.php create mode 100644 csf/messenger/index.html create mode 100644 csf/messenger/index.php create mode 100644 csf/messenger/index.recaptcha.html create mode 100644 csf/messenger/index.recaptcha.php create mode 100644 csf/messenger/index.text create mode 100644 csf/migratedata.sh create mode 100644 csf/modsecipdbalert.txt create mode 100644 csf/netblock.txt create mode 100644 csf/os.pl create mode 100644 csf/perf.sh create mode 100644 csf/permblock.txt create mode 100644 csf/portknocking.txt create mode 100644 csf/portscan.txt create mode 100644 csf/processtracking.txt create mode 100644 csf/profiles/block_all_perm.conf create mode 100644 csf/profiles/block_all_temp.conf create mode 100644 csf/profiles/disable_alerts.conf create mode 100644 csf/profiles/protection_high.conf create mode 100644 csf/profiles/protection_low.conf create mode 100644 csf/profiles/protection_medium.conf create mode 100644 csf/pt_deleted_action.pl create mode 100644 csf/queuealert.txt create mode 100644 csf/readme.txt create mode 100644 csf/recaptcha.txt create mode 100644 csf/regex.custom.pm create mode 100644 csf/relayalert.txt create mode 100644 csf/remove_apf_bfd.sh create mode 100644 csf/resalert.txt create mode 100644 csf/reselleralert.txt create mode 100644 csf/restricted.txt create mode 100644 csf/sanity.txt create mode 100644 csf/scriptalert.txt create mode 100644 csf/sshalert.txt create mode 100644 csf/sualert.txt create mode 100644 csf/sudoalert.txt create mode 100644 csf/syslogalert.txt create mode 100644 csf/tracking.txt create mode 100644 csf/ui/images/LICENSE.txt create mode 100644 csf/ui/images/admin_icon.svg create mode 100644 csf/ui/images/bootstrap-chosen.css create mode 100644 csf/ui/images/bootstrap/css/bootstrap.min.css create mode 100644 csf/ui/images/bootstrap/css/bootstrap.min.css.map create mode 100644 csf/ui/images/bootstrap/fonts/glyphicons-halflings-regular.eot create mode 100644 csf/ui/images/bootstrap/fonts/glyphicons-halflings-regular.svg create mode 100644 csf/ui/images/bootstrap/fonts/glyphicons-halflings-regular.ttf create mode 100644 csf/ui/images/bootstrap/fonts/glyphicons-halflings-regular.woff create mode 100644 csf/ui/images/bootstrap/fonts/glyphicons-halflings-regular.woff2 create mode 100644 csf/ui/images/bootstrap/js/bootstrap.min.js create mode 100644 csf/ui/images/chosen-sprite.png create mode 100644 csf/ui/images/chosen-sprite@2x.png create mode 100644 csf/ui/images/chosen.min.css create mode 100644 csf/ui/images/chosen.min.js create mode 100644 csf/ui/images/configserver.css create mode 100644 csf/ui/images/csf-loader.gif create mode 100644 csf/ui/images/csf.svg create mode 100644 csf/ui/images/csf_small.png create mode 100644 csf/ui/images/jquery.min.js create mode 100644 csf/ui/images/loader.gif create mode 100644 csf/ui/images/reseller_icon.svg create mode 100644 csf/ui/server.crt create mode 100644 csf/ui/server.key create mode 100644 csf/ui/ui.allow create mode 100644 csf/ui/ui.ban create mode 100644 csf/uialert.txt create mode 100644 csf/uidscan.txt rename csf/{uninstall.cpanel.sh => uninstall.sh} (100%) create mode 100644 csf/upgrade.txt create mode 100644 csf/usertracking.txt create mode 100644 csf/version.txt create mode 100644 csf/version/version.pm create mode 100644 csf/version/version/regex.pm create mode 100644 csf/version/version/vpp.pm create mode 100644 csf/vestacp/csf.pl create mode 100644 csf/vestacp/frame.php create mode 100644 csf/vestacp/index.php create mode 100644 csf/watchalert.txt create mode 100644 csf/webmin/csf/images/LICENSE.txt create mode 100644 csf/webmin/csf/images/admin_icon.svg create mode 100644 csf/webmin/csf/images/bootstrap-chosen.css create mode 100644 csf/webmin/csf/images/bootstrap/css/bootstrap.min.css create mode 100644 csf/webmin/csf/images/bootstrap/css/bootstrap.min.css.map create mode 100644 csf/webmin/csf/images/bootstrap/fonts/glyphicons-halflings-regular.eot create mode 100644 csf/webmin/csf/images/bootstrap/fonts/glyphicons-halflings-regular.svg create mode 100644 csf/webmin/csf/images/bootstrap/fonts/glyphicons-halflings-regular.ttf create mode 100644 csf/webmin/csf/images/bootstrap/fonts/glyphicons-halflings-regular.woff create mode 100644 csf/webmin/csf/images/bootstrap/fonts/glyphicons-halflings-regular.woff2 create mode 100644 csf/webmin/csf/images/bootstrap/js/bootstrap.min.js create mode 100644 csf/webmin/csf/images/chosen-sprite.png create mode 100644 csf/webmin/csf/images/chosen-sprite@2x.png create mode 100644 csf/webmin/csf/images/chosen.min.css create mode 100644 csf/webmin/csf/images/chosen.min.js create mode 100644 csf/webmin/csf/images/configserver.css create mode 100644 csf/webmin/csf/images/csf-loader.gif create mode 100644 csf/webmin/csf/images/csf.svg create mode 100644 csf/webmin/csf/images/csf_small.png create mode 100644 csf/webmin/csf/images/jquery.min.js create mode 100644 csf/webmin/csf/images/loader.gif create mode 100644 csf/webmin/csf/images/reseller_icon.svg create mode 100644 csf/webmin/csf/index.cgi create mode 100644 csf/webmin/csf/module.info create mode 100644 csf/webminalert.txt create mode 100644 csf/x-arf.txt rename {MailScanner => uninstallers/MailScanner}/msuninstall.pl (83%) rename {MailScanner => uninstallers/MailScanner}/msuninstall.sh (63%) create mode 100644 uninstallers/README.md rename {cmc => uninstallers/cmc}/cmc_uninstall.sh (54%) create mode 100644 uninstallers/cmm/cmm_uninstall.sh rename {cmq => uninstallers/cmq}/cmq_uninstall.sh (63%) create mode 100644 uninstallers/cse/cse_uninstall.sh create mode 100644 uninstallers/csf/uninstall.cpanel.sh create mode 100644 uninstallers/csf/uninstall.cwp.sh create mode 100644 uninstallers/csf/uninstall.cyberpanel.sh create mode 100644 uninstallers/csf/uninstall.directadmin.sh create mode 100644 uninstallers/csf/uninstall.generic.sh create mode 100644 uninstallers/csf/uninstall.interworx.sh create mode 100644 uninstallers/csf/uninstall.vesta.sh rename {cxs => uninstallers/cxs}/uninstall.cpanel.sh (100%) rename {cxs => uninstallers/cxs}/uninstall.cwp.sh (100%) rename {cxs => uninstallers/cxs}/uninstall.cyberpanel.sh (100%) rename {cxs => uninstallers/cxs}/uninstall.directadmin.sh (100%) rename {cxs => uninstallers/cxs}/uninstall.generic.sh (100%) rename {cxs => uninstallers/cxs}/uninstall.interworx.sh (100%) rename {cxs => uninstallers/cxs}/uninstall.plesk.sh (100%) rename {cxs => uninstallers/cxs}/uninstall.vestacp.sh (100%) rename {osm => uninstallers/osm}/uninstall.cpanel.sh (100%) rename {osm => uninstallers/osm}/uninstall.directadmin.sh (100%) diff --git a/COPYING.md b/COPYING.md new file mode 100644 index 0000000..17cd8ac --- /dev/null +++ b/COPYING.md @@ -0,0 +1,16 @@ +Copyright (C) 2006-2025 Jonathan Michaelson + +https://github.com/waytotheweb/scripts + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 3 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +details. + +You should have received a copy of the GNU General Public License along with +this program; if not, see . diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..f288702 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/README.md b/README.md index 225579b..b50eb38 100644 --- a/README.md +++ b/README.md @@ -1,52 +1,11 @@ -# Scripts for Way to the Web Limited Products +# Way to the Web Limited Scripts -### The scripts in this repository will uninstall each product +### All files within this repository are subject to the [GPL license](LICENSE.txt) as outlined in [COPYING.md](COPYING.md) -## MailScanner and MSFE (MailScanner Front-End): +These are the final copies of the scripts. -``` -curl -sL -o msuninstall.pl https://github.com/waytotheweb/scripts/blob/main/MailScanner/msuninstall.pl?raw=true -curl -sL https://github.com/waytotheweb/scripts/blob/main/MailScanner/msuninstall.sh?raw=true | bash -``` +There is no intention to update any of these files, so any PR's or other contact will not receive a response. -## cxs: +For uninstallation of any of our scripts, go to the [uninstallers](uninstallers) directory. -``` -bash /etc/cxs/uninstall.sh -``` -## osm: - -``` -bash /etc/osm/uninstall.sh -``` - -## csf: - -``` -bash /etc/csf/uninstall.sh -``` - -## cmc: - -``` -curl -sL https://github.com/waytotheweb/scripts/blob/main/cmc/cmc_uninstall.sh?raw=true | bash -``` - -## cmm: - -``` -curl -sL https://github.com/waytotheweb/scripts/blob/main/cmm/cmm_uninstall.sh?raw=true | bash -``` - -## cmq: - -``` -curl -sL https://github.com/waytotheweb/scripts/blob/main/cmq/cmq_uninstall.sh?raw=true | bash -``` - -## cse: - -``` -curl -sL https://github.com/waytotheweb/scripts/blob/main/cse/cse_uninstall.sh?raw=true | bash -``` diff --git a/cmc.tgz b/cmc.tgz new file mode 100644 index 0000000000000000000000000000000000000000..87f9c22a635daa361e5c7867acacdb33872ea96c GIT binary patch literal 211489 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%0D=yVo$wU$)l4gCtMkD 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 Q^Z5Dy0pXBOumE5Q0I#b8EdT%j literal 0 HcmV?d00001 diff --git a/cmc/INSTALL.txt b/cmc/INSTALL.txt new file mode 100644 index 0000000..a46b270 --- /dev/null +++ b/cmc/INSTALL.txt @@ -0,0 +1,43 @@ +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### + +1. Download and install cmc: + +cd /usr/src +rm -fv /usr/src/cmc.tgz +wget http://download.configserver.com/cmc.tgz +tar -xzf cmc.tgz +cd cmc +sh install.sh +rm -Rfv /usr/src/cmc* + +2. Login to WHM and scroll to the bottom of the left hand menu and you should see "ConfigServer ModSecurity Control" + + +If you want to uninstall, simply: + +cd /usr/src +rm -fv /usr/src/cmc.tgz +wget http://download.configserver.com/cmc.tgz +tar -xzf cmc.tgz +cd cmc +sh uninstall.sh +rm -Rfv /usr/src/cmc* + +Note: This won't remove the mod_security files and rules which you will need to do manually within /usr/local/apache/conf/ diff --git a/cmc/changelog.txt b/cmc/changelog.txt new file mode 100644 index 0000000..d5176d6 --- /dev/null +++ b/cmc/changelog.txt @@ -0,0 +1,173 @@ +ChangeLog: + +4.00 - Changed license to GPLv3 + +3.03 - Ensure UI errors are displayed in browser to avoid blank pages + + Added workaround for iOS issue with bootstrap modals + +3.02 - Added routine to select from multiple download servers for script + updates + +3.01 - Updated license terms for GDPR compliance + +3.00 - Modified and simplified output to use both top-level and LocationMatch + wildcard SecRuleRemoveById statements to cover both types of rule. + Existing conf files are only updated once they have been changed via + the UI + + Added warning to files that cmc creates to not modify them manually and + then use cmc, as they will be overwritten + + Removed old migration code + + Updated cPanel Documentation URL in Help to point to EA4 information + +2.13 - Configured UI to fully integrate with cPanel templates without using + iframes + + Configured UI to display full cPanel breadcrumbs + + Configured UI to support cPanel v66 WHM UI changes + +2.12 - Modified HTML to cater for major change in cPanel v66 + +2.11 - Improvements to use of cPanel templates for v64+ + +2.10 - Modify UI to use cPanel templates for v64+ + + Modified cmc ModSecurity blocks to no longer use + wrapper so that cmc rules apply through all ModSecurity phases. On + existing servers, this modification happens when a file is next updated + + Modified wrapper to always appear at the + start and then close at the end of the file. On existing servers, this + modification happens when a file is next updated + + Removed link to modsec2.whitelist.conf in modsec2.user.conf on EA4 + servers as it is now included via a wildcard entry in httpd.conf + +2.09 - UI HTML changes + +2.08 - Fixed UI issue + +2.07 - Redesigned UI based on Bootstrap + +2.06 - Fixed bareword file handles causing duplicate entry data in + modsec2.user.conf + +2.05 - Removed use of Cpanel::cPanelFunctions as it is now being withdrawn + + Updated common ConfigServer UI + +2.04 - Fixed incorrect shebang in install.sh + +2.03 - Modified location of modsec2.user.conf on EA4 as cPanel has moved some + files to a different directory + +2.02 - Improved detection of ruid2_module and mpm_itk_module for reading the + correct ModSecurity logs + +2.01 - Code review - started addressing perl critic suggestions in all + scripts and modules + + Ensure all file opens are properly flocked + + Removed Bareword file handles + + Localised SIGNALs + + Enabled strict module + + Newly modified modsec.conf files are now wrapped within + + + Installer checks existing modsec.conf files and wraps them as above + + Updated cPanel documentation link in cmc help + +2.00 - Added Easyapache v4 support + + Removed references to modsecparse.pl as it is no longer used by cPanel + + Fixed modify file list to only list actual files + +1.18 - Removed redundant code + + Modified to cater for /usr/local/apache/conf/userdata/(std|ssl)/2_4 + paths when Apache v2.4 is used + + Additional input validation from forms + + Added Migrate button to move modsec.conf files from older Apache data + structures to the current valid one + +1.17 - Modified httpd graceful restarts to cater for systemd + + Updated INSTALL.txt + +1.16 - Updated scripts to use https://download.configserver.com + +1.15 - Updated scripts to use download.configserver.com + +1.14 - Modified cmc map to only show users and domains with actual exceptions + +1.13 - Added support for Concurrent logs stored in the cPanel directory: + /usr/local/apache/logs/modsec_audit/ + + Added cmc user/domain configuration map + +1.12 - Fixes to feature to Enable/Disable modsecparse.pl + +1.11 - Fixes to feature to Enable/Disable modsecparse.pl + + Added full pseudo-breadcrumbs to cPanel cmc UI + +1.10 - UI updates + +1.09 - Added new feature - Ability to use DirectoryMatch ModSecurity disabling + and whitelisting + + Parameterise Open3 calls + +1.08 - UI button style modifications + +1.07 - If /etc/csuibuttondisable exists then the UI buttons will revert for + those that cannot cope with the themed ones + +1.06 - UI Changes + +1.05 - Added support for cPanel v11.38.1+ AppConfig addon registration + + NOTE: In accordance with the new conventions for v11.38.1+ AppConfig + the url to the cmc WHM plugin will change from /cgi/addon_cmc.cgi to + /cgi/configserver/cmc.cgi. This will only happen with cmc v1.05+ and + cPanel v11.38.1+. Older version of cmc will continue to use the old + URL. This has no particular relevance to users accessing through WHM, + but will affect direct URL access by users or third party + applications + +1.04 - Ensure that modsec2.whitelist.conf is always included at the bottom of + modsec2.user.conf rather than at the top. This is done whenever the UI + is accessed via WHM + +1.03 - Updated to use the new cPanel 11.36+ integrated perl binary if exists + +1.02 - Create/modify /scripts/posteasyapache to rename the script + /etc/cron.hourly/modsecparse.pl out of the way if the option to Disable + it is used (you may need to enable and disable the option on existing + installations to create the /scripts/posteasyapache entry) + + Added a timed refresh to the ModSecurity Log view + +1.01 - Fixed broken image icon in the WHM header + + Switched to a proportional font to display the mod_security log entries + to better fit the browser window + + Increased the lines per mod_security log lines to display from 40 to + 200 + + Fixed a display formatting issue with the mod_security log entries + +1.00 - Initial public release diff --git a/cmc/cmc.cgi b/cmc/cmc.cgi new file mode 100644 index 0000000..6492cf6 --- /dev/null +++ b/cmc/cmc.cgi @@ -0,0 +1,1454 @@ +#!/usr/local/cpanel/3rdparty/bin/perl +#WHMADDON:addonupdates:ConfigServer ModSec Control +#ACLS:configserver +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +## no critic (RequireUseWarnings, ProhibitExplicitReturnUndef, ProhibitMixedBooleanOperators, RequireBriefOpen) +use strict; +use CGI::Carp qw(fatalsToBrowser); + +use File::Basename; +use File::Path; +use File::Copy; +use File::Find; +use Fcntl qw(:DEFAULT :flock); +use IPC::Open3; + +use lib '/usr/local/cpanel'; +require Cpanel::Form; +require Cpanel::Config; +require Cpanel::Version::Tiny; +require Whostmgr::ACLS; +require Cpanel::Rlimit; +require Cpanel::Template; +############################################################################### +# start main + +our ($images, $myv, $script, $versionfile, %FORM, $downloadserver); + +%FORM = Cpanel::Form::parseform(); + +Whostmgr::ACLS::init_acls(); +if (!Whostmgr::ACLS::hasroot()) { + print "Content-type: text/html\r\n\r\n"; + print "You do not have access to ConfigServer ModSecurity Control.\n"; + exit(); +} + +Cpanel::Rlimit::set_rlimit_to_infinity(); + +$script = "cmc.cgi"; +$images = "cmc"; +$versionfile = "/usr/local/cpanel/whostmgr/docroot/cgi/configserver/cmc/cmcversion.txt"; +local $| = 1; + +$downloadserver = &getdownloadserver; + +my $thisapp = "cmc"; +my $reregister; +my $modalstyle; +if ($Cpanel::Version::Tiny::major_version >= 65) { + if (-e "/usr/local/cpanel/whostmgr/docroot/cgi/configserver/${thisapp}/${thisapp}.conf") { + sysopen (my $CONF, "/usr/local/cpanel/whostmgr/docroot/cgi/configserver/${thisapp}/${thisapp}.conf", O_RDWR | O_CREAT); + flock ($CONF, LOCK_EX); + my @confdata = <$CONF>; + chomp @confdata; + for (0..scalar(@confdata)) { + if ($confdata[$_] =~ /^target=mainFrame/) { + $confdata[$_] = "target=_self"; + $reregister = 1; + } + } + if ($reregister) { + seek ($CONF, 0, 0); + truncate ($CONF, 0); + foreach (@confdata) { + print $CONF "$_\n"; + } + &printcmd("/usr/local/cpanel/bin/register_appconfig","/usr/local/cpanel/whostmgr/docroot/cgi/configserver/${thisapp}/${thisapp}.conf"); + $reregister = "

Updated application. The next time you login to WHM this will open within the native WHM main window instead of launching a separate window

\n"; + } + close ($CONF); + } +} + +print "Content-type: text/html\r\n\r\n"; +#if ($Cpanel::Version::Tiny::major_version < 65) {$modalstyle = "style='top:120px'"} + +our (@files); +open (my $IN, "<", $versionfile) or die $!; +flock ($IN, LOCK_SH); +$myv = <$IN>; +close ($IN); +chomp $myv; + +my $bootstrapcss = ""; +my $jqueryjs = ""; +my $bootstrapjs = ""; + +my $templatehtml; +my $SCRIPTOUT; +unless ($FORM{action} eq "help") { + open ($SCRIPTOUT, '>', \$templatehtml); + select $SCRIPTOUT; + + print < + + $jqueryjs + $bootstrapjs +EOF +} else { + print < + + + $bootstrapcss + + $jqueryjs + $bootstrapjs + + +
+EOF +} + +print <

+
+

ConfigServer ModSecurity Control - cmc v$myv

+EOF +if ($reregister ne "") {print $reregister} + +print "

This script creates and rewrites modsec2.whitelist.conf and userdata modsec.conf files

\n"; +print "

Do not use cmc if you have made manual modifications to these files as they will be removed by cmc

\n"; + +my $is_ea4 = 0; +my $apachepath = "/usr/local/apache/conf"; +my $modsecpath = "/usr/local/apache/conf"; +my $apachebin = "/usr/local/apache/bin/httpd"; +my $apachectl = "/usr/local/apache/bin/apachectl"; +my $apachelogs = "/usr/local/apache/logs"; +if (-e "/usr/local/cpanel/version" and -e "/etc/cpanel/ea4/is_ea4" and -e "/etc/cpanel/ea4/paths.conf") { + $is_ea4 = 1; + $apachepath = "/etc/apache2/conf.d"; + $apachebin = "/usr/sbin/httpd"; + $apachectl = "/usr/sbin/apachectl"; + $apachelogs = "/etc/apache2/logs"; + open (my $IN, "<", "/etc/cpanel/ea4/paths.conf"); + flock ($IN, LOCK_SH); + my @file = <$IN>; + close ($IN); + chomp @file; + foreach my $line (@file) { + if ($line =~ /^(\s|\#|$)/) {next} + if ($line !~ /=/) {next} + my ($name,$value) = split (/=/,$line,2); + $value =~ s/^\s+//g; + $value =~ s/\s+$//g; + if ($name eq "dir_conf") {$apachepath = $value} + if ($name eq "bin_httpd") {$apachebin = $value} + if ($name eq "bin_apachectl") {$apachectl = $value} + if ($name eq "dir_logs") {$apachelogs = $value} + } + $modsecpath = $apachepath."/modsec"; +} + +my $httpv = "2"; +my $mypid; +my ($childin, $childout); +$mypid = open3($childin, $childout, $childout, "$apachebin","-v"); +my @version = <$childout>; +waitpid ($mypid, 0); +chomp @version; +$version[0] =~ /Apache\/(\d+)\.(\d+)\.(\d+)/; +my $mas = $1; +my $maj = $2; +my $min = $3; +$httpv = "$mas.$maj"; + +my $stdpath = "$apachepath/userdata/std/2"; +my $sslpath = "$apachepath/userdata/ssl/2"; +my $oldstdpath; +my $oldsslpath; +if ($httpv eq "2.2") { + $oldstdpath = $stdpath; + $oldsslpath = $sslpath; + $stdpath = "$apachepath/userdata/std/2_2"; + $sslpath = "$apachepath/userdata/ssl/2_2"; +} +if ($httpv eq "2.4") { + $oldstdpath = $stdpath; + $oldsslpath = $sslpath; + $stdpath = "$apachepath/userdata/std/2_4"; + $sslpath = "$apachepath/userdata/ssl/2_4"; +} + +my $truefile; +if ($FORM{template} ne "") { + my ($tfile, $tdir) = fileparse("$apachepath/$FORM{template}"); + $truefile = "$tdir$tfile"; +} + +if (($FORM{template} ne "") and ($truefile !~ m[^$apachepath/])) { + print "[$FORM{template}] is not a valid file"; +} +elsif (($FORM{domain} ne "") and ($FORM{domain} !~ /^[a-zA-Z0-9\-\_\.]+$/)) { + print "[$FORM{domain}] is not a valid domain"; +} +elsif (($FORM{user} ne "") and ($FORM{user} !~ /^[a-zA-Z0-9\-\_\.\@\%\+]+$/)) { + print "[$FORM{user}] is not a valid user"; +} +elsif ($FORM{action} eq "upgrade") { + print "Retrieving new cmc package...\n"; + print "
";
+	&printcmd("rm -Rfv /usr/src/cmc* ; cd /usr/src ; wget -q https://$downloadserver/cmc.tgz 2>&1");
+	print "
"; + if (! -z "/usr/src/cmc.tgz") { + print "Unpacking new cmc package...\n"; + print "
";
+		&printcmd("cd /usr/src ; tar -xzf cmc.tgz ; cd cmc ; sh install.sh 2>&1");
+		print "
"; + print "Tidying up...\n"; + print "
";
+		&printcmd("rm -Rfv /usr/src/cmc*");
+		print "
"; + print "...All done.\n"; + } + + open (my $IN, "<",$versionfile) or die $!; + flock ($IN, LOCK_SH); + $myv = <$IN>; + close ($IN); + chomp $myv; + + print "

\n"; +} +elsif ($FORM{action} eq "ms_list") { + &modsec; +} +elsif ($FORM{action} eq "ms_config") { + sysopen (my $IN, "$apachepath/$FORM{template}", O_RDWR | O_CREAT); + flock ($IN, LOCK_SH); + my @confdata = <$IN>; + close ($IN); + chomp @confdata; + + print "
\n"; + print "\n"; + print "\n"; + print "
Edit $FORM{template}\n"; + print "\n"; + print "
\n"; + print "

\n"; + print "
\n"; + print "

\n"; +} +elsif ($FORM{action} eq "savems_config") { + $FORM{formdata} =~ s/\r//g; + sysopen (my $OUT, "$apachepath/$FORM{template}", O_WRONLY | O_CREAT); + flock ($OUT, LOCK_EX); + seek ($OUT, 0, 0); + truncate ($OUT, 0); + if ($FORM{formdata} !~ /\n$/) {$FORM{formdata} .= "\n"} + print $OUT $FORM{formdata}; + close ($OUT); + + print "\n"; + print ""; + print "\n"; + print "
ModSecurity save $FORM{template}
Rebuilding and restarting Apache:
"; + print "
";
+	&printcmd("/usr/local/cpanel/bin/build_apache_conf");
+	&printcmd("$apachectl","graceful");
+	print "\n..Done
"; + print "
\n"; + print "

\n"; +} +elsif ($FORM{action} eq "Modify user whitelist") { + if ($FORM{user}) { + my %ids; + my $off = 0; + if (-d "$stdpath/$FORM{user}/") { + if (-e "$stdpath/$FORM{user}/modsec.conf") { + open (my $FH, "<", "$stdpath/$FORM{user}/modsec.conf"); + flock ($FH, LOCK_SH); + my @data = <$FH>; + close ($FH); + chomp @data; + foreach my $line (@data) { + if ($line =~ /SecRuleRemoveById\s+(\d*)/) {$ids{$1} = 1} + if ($line =~ /SecRuleEngine\s+Off/) {$off = 1} + } + } + } else { + mkpath("$stdpath/$FORM{user}"); + } + unless (-d "$sslpath/$FORM{user}") {mkpath("$sslpath/$FORM{user}")} + my @domains; + open (my $IN, "<","/var/cpanel/users/$FORM{user}"); + flock ($IN, LOCK_SH); + my @userdata = <$IN>; + close ($IN); + chomp @userdata; + foreach my $line (@userdata) { + if ($line =~ /^DNS(\d*)=(.*)$/) { + my $domain = $2; + $domain =~ s/\s//g; + push @domains,$domain; + unless (-d "$stdpath/$FORM{user}/$domain") { + mkdir ("$stdpath/$FORM{user}/$domain"); + } + unless (-d "$sslpath/$FORM{user}/$domain") { + mkdir ("$sslpath/$FORM{user}/$domain"); + } + } + } + @domains = sort @domains; + + if ($off) { + print "\n"; + print ""; + print "\n"; + print "
ModSecurity whitelist for $FORM{user}
Off On

You can completely disable ModSecurity for all domains owned by this user by setting this to Off and clicking the Select button:

\n"; + } else { + print "\n"; + print ""; + print "\n"; + print "\n"; + print "\n"; + print "
ModSecurity whitelist for $FORM{user}
Off On

You can completely disable ModSecurity for all domains owned by this user by setting this to Off and clicking the Select button:

ModSecurity rule ID list:

You can add ModSecurity rule ID numbers that you want to be disabled for all domains owned by this user.

You should place one ID number per line. When you have clicked the Save whitelist for all $FORM{user} domains button: the relevant lines will be added to:

$stdpath/$FORM{user}/modsec.conf
$sslpath/$FORM{user}/modsec.conf

Then httpd.conf will be rebuilt and apache will be gracefully restarted.

Alternatively, you can disable rules on a per domain basis by selecting a domain and then clicking:

\n"; + } + } else { + print "

No user selected

\n"; + } + print "


\n"; +} +elsif ($FORM{action} eq "onoff") { + &onoff("$stdpath/$FORM{user}/modsec.conf"); + &onoff("$sslpath/$FORM{user}/modsec.conf"); + + print "\n"; + print ""; + print "\n"; + print "\n"; + print "
ModSecurity whitelist for $FORM{user}: "; + if ($FORM{choose}) { + print "On"; + } else { + print "Off"; + } + print "
Rebuilding and restarting Apache:
"; + print "
";
+	&printcmd("/usr/local/cpanel/bin/build_apache_conf");
+	&printcmd("$apachectl","graceful");
+	print "\n..Done
"; + print "
\n"; + print "

\n"; +} +elsif ($FORM{action} eq "thisuser") { + &ids("$stdpath/$FORM{user}/modsec.conf"); + &ids("$sslpath/$FORM{user}/modsec.conf"); + + print "\n"; + print ""; + print "\n"; + print "\n"; + print "
ModSecurity whitelist for $FORM{user} saved"; + print "
Rebuilding and restarting Apache:
"; + print "
";
+	&printcmd("/usr/local/cpanel/bin/build_apache_conf");
+	&printcmd("$apachectl","graceful");
+	print "\n..Done
"; + print "
\n"; + print "

\n"; +} +elsif ($FORM{action} eq "domain") { + if ($FORM{user} and $FORM{domain}) { + my %ids; + my $off = 0; + if (-d "$stdpath/$FORM{user}/$FORM{domain}/") { + if (-e "$stdpath/$FORM{user}/$FORM{domain}/modsec.conf") { + open (my $FH, "<", "$stdpath/$FORM{user}/$FORM{domain}/modsec.conf"); + flock ($FH, LOCK_SH); + my @data = <$FH>; + close ($FH); + chomp @data; + foreach my $line (@data) { + if ($line =~ /SecRuleRemoveById\s+(\d*)/) {$ids{$1} = 1} + if ($line =~ /SecRuleEngine\s+Off/) {$off = 1} + } + } + } + if ($off) { + print "\n"; + print ""; + print "\n"; + print "\n"; + print "
ModSecurity whitelist for $FORM{domain}
Off On

You can completely disable ModSecurity on this domain by setting this to Off and clicking the Select button:

\n"; + } else { + print "\n"; + print ""; + print "\n"; + print "\n"; + print "\n"; + print "
ModSecurity whitelist for $FORM{domain}
Off On

You can completely disable ModSecurity on this domain by setting this to Off and clicking the Select button:

ModSecurity rule ID list:

You can add ModSecurity rule ID numbers that you want to be disabled for this domain.

You should place one ID number per line. When you have clicked the Save whitelist for $FORM{domain} button: the relevant lines will be added to:

$stdpath/$FORM{user}/$FORM{domain}/modsec.conf
$sslpath/$FORM{user}/$FORM{domain}/modsec.conf

Then httpd.conf will be rebuilt and apache will be gracefully restarted.

\n"; + } + } else { + print "

No domain selected

\n"; + } + print "


\n"; +} +elsif ($FORM{action} eq "donoff") { + &onoff("$stdpath/$FORM{user}/$FORM{domain}/modsec.conf"); + &onoff("$sslpath/$FORM{user}/$FORM{domain}/modsec.conf"); + + print "\n"; + print ""; + print "\n"; + print "\n"; + print "
ModSecurity whitelist for $FORM{domain}: "; + if ($FORM{choose}) { + print "On"; + } else { + print "Off"; + } + print "
Rebuilding and restarting Apache:
"; + print "
";
+	&printcmd("/usr/local/cpanel/bin/build_apache_conf");
+	&printcmd("$apachectl","graceful");
+	print "\n..Done
"; + print "
\n"; + print "

\n"; +} +elsif ($FORM{action} eq "thisdomain") { + &ids("$stdpath/$FORM{user}/$FORM{domain}/modsec.conf"); + &ids("$sslpath/$FORM{user}/$FORM{domain}/modsec.conf"); + + print "\n"; + print ""; + print "\n"; + print "\n"; + print "
ModSecurity whitelist for $FORM{domain} saved"; + print "
Rebuilding and restarting Apache:
"; + print "
";
+	&printcmd("/usr/local/cpanel/bin/build_apache_conf");
+	&printcmd("$apachectl","graceful");
+	print "\n..Done
"; + print "
\n"; + print "

\n"; +} +elsif ($FORM{action} eq "gonoff") { + &onoff("$apachepath/modsec2.whitelist.conf"); + + print "\n"; + print ""; + print "\n"; + print "
ModSecurity global whitelist: "; + if ($FORM{choose}) { + print "On"; + } else { + print "Off"; + } + print "
Restarting Apache:
"; + print "
";
+	&printcmd("$apachectl","graceful");
+	print "\n..Done
"; + print "
\n"; + print "

\n"; +} +elsif ($FORM{action} eq "dironoff") { + my $file = "$apachepath/modsec2.whitelist.conf"; + open (my $FH, "<", $file); + flock ($FH, LOCK_SH); + my @data = <$FH>; + close ($FH); + chomp @data; + my $start = 0; + my $done = 0; + my $directorymatch = quotemeta($FORM{directorymatch}); + open (my $OUT, ">", $file); + flock ($OUT, LOCK_EX); + print $OUT "\n"; + foreach my $line (@data) { + if ($line =~ /^\s*/) {next} + if ($line =~ /^\s*<\/IfModule>/) {next} + if ($line =~ //) {$start = 1} + if ($start and $line =~ /SecRuleEngine\s/) {next} + if ($line =~ /<\/DirectoryMatch>/ and $start) { + $start = 0; + if ($FORM{choose}) { + } else { + print $OUT "\tSecRuleEngine Off\n"; + } + $done = 1; + } + print $OUT "$line\n"; + } + unless ($done) { + print $OUT "\n"; + if ($FORM{choose}) { + } else { + print $OUT "\tSecRuleEngine Off\n"; + } + print $OUT "\n"; + } + print $OUT "\n"; + close ($OUT); + + print "\n"; + print ""; + print "\n"; + print "
ModSecurity DirectoryMatch ($FORM{directorymatch}) whitelist: "; + if ($FORM{choose}) { + print "On"; + } else { + print "Off"; + } + print "
Restarting Apache:
"; + print "
";
+	&printcmd("$apachectl","graceful");
+	print "\n..Done
"; + print "
\n"; + print "

\n"; +} +elsif ($FORM{action} eq "global") { + &ids("$apachepath/modsec2.whitelist.conf"); + + print "\n"; + print ""; + print "\n"; + print "
ModSecurity global whitelist saved"; + print "
Restarting Apache:
"; + print "
";
+	&printcmd("$apachectl","graceful");
+	print "\n..Done
"; + print "
\n"; + print "

\n"; +} +elsif ($FORM{action} eq "thisdirectorymatch") { + my $file = "$apachepath/modsec2.whitelist.conf"; + my @ids = split(/\n|\r/,$FORM{ids}); + chomp @ids; + open (my $FH, "<", $file); + flock ($FH, LOCK_SH); + my @data = <$FH>; + close ($FH); + chomp @data; + my $start = 0; + my $done = 0; + my $directorymatch = quotemeta($FORM{directorymatch}); + open (my $OUT, ">", $file); + flock ($OUT, LOCK_EX); + print $OUT "\n"; + foreach my $line (@data) { + if ($line =~ /^\s*/) {next} + if ($line =~ /^\s*<\/IfModule>/) {next} + if ($line =~ /<\/DirectoryMatch>/ and $start) { + $start = 0; + foreach my $id (@ids) { + if ($id =~ /^\d+$/) {print $OUT "\tSecRuleRemoveById $id\n"} + } + $done = 1; + } + if ($start) {next} + if ($line =~ //) {$start = 1} + print $OUT "$line\n"; + } + unless ($done) { + print $OUT "\n"; + foreach my $id (@ids) { + if ($id =~ /^\d+$/) {print $OUT "\tSecRuleRemoveById $id\n"} + } + print $OUT "\n"; + } + print $OUT "\n"; + close ($OUT); + + print "\n"; + print ""; + print "\n"; + print "
ModSecurity DirectoryMatch ($FORM{directorymatch}) whitelist saved"; + print "
Restarting Apache:
"; + print "
";
+	&printcmd("$apachectl","graceful");
+	print "\n..Done
"; + print "
\n"; + print "

\n"; +} +elsif ($FORM{action} eq "Remove DirectoryMatch") { + my $file = "$apachepath/modsec2.whitelist.conf"; + my @ids = split(/\n|\r/,$FORM{ids}); + chomp @ids; + open (my $FH, "<", $file); + flock ($FH, LOCK_SH); + my @data = <$FH>; + close ($FH); + chomp @data; + my $start = 0; + my $done = 0; + my $directorymatch = quotemeta($FORM{directorymatch}); + open (my $OUT, ">", $file); + flock ($OUT, LOCK_EX); + print $OUT "\n"; + foreach my $line (@data) { + if ($line =~ /^\s*/) {next} + if ($line =~ /^\s*<\/IfModule>/) {next} + if ($line =~ /<\/DirectoryMatch>/ and $start) {next} + if ($start) {next} + if ($line =~ //) { + $start = 1; + next; + } + print $OUT "$line\n"; + } + print $OUT "\n"; + close ($OUT); + + print "\n"; + print ""; + print "\n"; + print "
ModSecurity DirectoryMatch ($FORM{directorymatch}) whitelist removed"; + print "
Restarting Apache:
"; + print "
";
+	&printcmd("$apachectl","graceful");
+	print "\n..Done
"; + print "
\n"; + print "

\n"; +} +elsif ($FORM{action} eq "Modify by DirectoryMatch") { + if ($FORM{directorymatch} eq "" or $FORM{directorymatch} eq "New DirectoryMatch") { + print "\n"; + print ""; + print "\n"; + print "
ModSecurity DirectoryMatch whitelist

Add a DirectoryMatch Apache directive (do not use quotes). This should be a regular expression. Examples:
^/home/someuser/public_html/ignore/me/index\\.php
^/home/someuser/public_html/ignore/path/
/wp-admin/index\\.php

\n"; + } else { + my %ids; + my $off = 0; + if (-e "$apachepath/modsec2.whitelist.conf") { + open (my $FH, "<", "$apachepath/modsec2.whitelist.conf"); + flock ($FH, LOCK_SH); + my @data = <$FH>; + close ($FH); + chomp @data; + my $start = 0; + my $directorymatch = quotemeta($FORM{directorymatch}); + foreach my $line (@data) { + if ($line =~ //) {$start = 1} + if ($start and $line =~ /SecRuleRemoveById\s+(\d*)/) {$ids{$1} = 1} + if ($start and $line =~ /SecRuleEngine\s+Off/) {$off = 1} + if ($line =~ /<\/DirectoryMatch>/) {$start = 0} + } + } + + if ($off) { + print "\n"; + print ""; + print "\n"; + print "
ModSecurity whitelist for DirectoryMatch: $FORM{directorymatch}
Off On

You can completely disable ModSecurity for this DirectoryMatch by setting this to Off and clicking the Select button:

\n"; + } else { + print "\n"; + print ""; + print "\n"; + print "\n"; + print "\n"; + print "
ModSecurity whitelist for DirectoryMatch: $FORM{directorymatch}
Off On

You can completely disable ModSecurity for this DirectoryMatch by setting this to Off and clicking the Select button:

ModSecurity rule ID list:

You can add ModSecurity rule ID numbers that you want to be disabled for this DirectoryMatch.

You should place one ID number per line. When you have clicked the Save Whitelist button:

Then apache will be gracefully restarted.

\n"; + } + } + print "

\n"; + print "

\n"; +} +elsif ($FORM{action} eq "map") { + print "\n"; + &showmap; + print "
\n"; + print "

Note: Only users or domain with a modsec.conf containing cmc exceptions will be listed here

\n"; + print "

\n"; +} +elsif ($FORM{action} eq "help") { + print "\n"; + print ""; + print "\n"; + print "
ConfigServer ModSecurity Help
"; + print <This utility allows you to: +
    +
  • Disable ModSecurity rules that have unique ID numbers on a global, per cPanel user or per hosted domain level.
  • +
  • Disable ModSecurity entirely, also on a global, per cPanel user or per hosted domain level.
  • +
  • Edit files containing ModSecurity configuration settings in $apachepath
  • +
  • View the latest ModSecurity log entries
  • +
+

+

The requirements for this utility are: +

    +
  • Apache v2+
  • +
  • ModSecurity v2.5+ installed via Easyapache
  • +
  • A set of ModSecurity rules each of which uses a unique ID
  • +
  • ModSecurity logging that uses "SecAuditLogParts A...Z"
  • +
+

+

ModSecurity logs will be detected in the following order, the last found being the one that will be used. If the wrong logs are being shown the other logs should be removed: +

    +
  • $apachelogs/audit_log
  • +
  • $apachelogs/modsec_audit.log
  • +
  • $apachelogs/modsec_audit/ (used under mod_ruid2 and mpm_itk)
  • +
+

+

This utility uses concepts explained in this section of the cPanel documentation.

+EOH + print "

\n"; +} +else { + my @modsecfiles; + my @modsecdirfiles; + + my %ids; + my @alt; + my $off = 0; + if (-e "$apachepath/modsec2.whitelist.conf") { + open (my $FH, "<", "$apachepath/modsec2.whitelist.conf"); + flock ($FH, LOCK_SH); + my @data = <$FH>; + close ($FH); + chomp @data; + my $start = 0; + foreach my $line (@data) { + if ($line =~ //) {push @alt,$1; $start = 1} + if (!$start and $line =~ /SecRuleRemoveById\s+(\d*)/) {$ids{$1} = 1} + if (!$start and $line =~ /SecRuleEngine\s+Off/) {$off = 1} + if ($line =~ /^\s*(<\/DirectoryMatch>)/) {$start = 0} + } + } else { + open (my $FH,">","$apachepath/modsec2.whitelist.conf"); + flock ($FH, LOCK_SH); + print $FH "\# ConfigServer ModSecurity whitelist file\n"; + close ($FH); + } + + sysopen (my $FH, "$modsecpath/modsec2.user.conf", O_RDWR | O_CREAT); + flock ($FH, LOCK_EX); + my @data = <$FH>; + chomp @data; + if ($is_ea4) { + if (grep {$_ =~ /^\s*Include\s+$apachepath\/modsec2\.whitelist\.conf/} @data) { + seek ($FH, 0, 0); + truncate ($FH, 0); + foreach my $line (@data) { + if ($line =~ /^\s*Include\s+$apachepath\/modsec2\.whitelist\.conf/) {next} + if ($line =~ /^\# ConfigServer ModSecurity whitelist file/) {next} + print $FH "$line\n"; + } + print "

Removing modsec2.whitelist.conf in modsec2.user.conf (not needed in EA4) and gracefully restarting Apache..."; + &printcmd("$apachectl","graceful"); + print "Done

\n"; + } + } else { + unless ($data[-1] =~ /^\s*Include\s+$apachepath\/modsec2\.whitelist\.conf/) { + seek ($FH, 0, 0); + truncate ($FH, 0); + foreach my $line (@data) { + if ($line =~ /^\s*Include\s+$apachepath\/modsec2\.whitelist\.conf/) {next} + if ($line =~ /^\# ConfigServer ModSecurity whitelist file/) {next} + print $FH "$line\n"; + } + print $FH "Include $apachepath/modsec2.whitelist.conf\n"; + print "

Adding/Relocating modsec2.whitelist.conf in modsec2.user.conf and gracefully restarting Apache..."; + &printcmd("$apachectl","graceful"); + print "Done

\n"; + } + } + close ($FH); + + opendir (DIR, "$apachepath/"); + while (my $file = readdir (DIR)) { + if ($file =~ /^(mod_sec|modsec).*\.conf$/i) { + push @modsecfiles, $file; + } + if (-d "$apachepath/$file" and ($file =~ /^(mod_sec|modsec)/i)) { + opendir (MODDIR, "$apachepath/$file"); + while (my $modfile = readdir (MODDIR)) { + if ($modfile =~ /^\.|\.\.$/) {next} + push @modsecdirfiles, "$file/$modfile"; + } + closedir (MODDIR); + } + } + closedir (DIR); + @modsecfiles = sort @modsecfiles; + @modsecdirfiles = sort @modsecdirfiles; + + my @users; + my %domains; + opendir (DIR, "/var/cpanel/users") or die $!; + while (my $user = readdir (DIR)) { + if ($user =~ /^\./) {next} + my (undef,undef,undef,undef,undef,undef,undef,$homedir,undef,undef) = getpwnam($user); + $homedir =~ /(.*)/; + $homedir = $1; + if ($homedir eq "") {next} + if (not -d "$homedir") {next} + open (my $IN, "<","/var/cpanel/users/$user"); + flock ($IN, LOCK_SH); + my @userdata = <$IN>; + close ($IN); + chomp @userdata; + my $domain; + foreach my $line (@userdata) { + if ($line =~ /^DNS=(.*)/) { + $domains{$user} = $1; + last; + } + } + push (@users, $user); + } + closedir (DIR); + @users = sort @users; + + print "\n"; + print "\n"; + + if ($off) { + print "\n"; + } else { + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + } + print "
ConfigServer ModSecurity Control Help
Off On

You can completely disable ModSecurity on the server by setting this to Off and clicking the Select button:

Off On

You can completely disable ModSecurity on the server by setting this to Off and clicking the Select button:

ModSecurity rule ID list:

You can add ModSecurity rule ID numbers that you want to be globally disabled.

\n"; + print "

You should place one ID number per line. When you have clicked the Save global whitelist button: the relevant lines will be added to $apachepath/modsec2.whitelist.conf which has already been added to the top of $modsecpath/modsec2.user.conf. Then httpd.conf will be rebuilt and apache will be gracefully restarted.

Alternatively, you can disable rules on a per cPanel account or per domain basis by selecting a user and then clicking:

You can disable rules by DirectoryMatch (e.g. ^/home/someuser/public_html/ignore/some/path/)

Display cmc user/domain configuration map

\n"; + + print "\n"; + print ""; + print "\n"; + print "\n"; + print "
ConfigServer ModSecurity Tools
View the last entries in the ModSecurity log file and auto-refresh the log view\n"; + print "

Note: If your audit_log file is very large it may take some time to process it.

Edit files containing ModSecurity configuration settings in $apachepath/. After a file has been edited httpd.conf will be rebuilt and apache gracefully restarted.

Note: Files or directories must be prefixed modsec* or mod_sec* to be detected.


\n"; + + print "\n"; + my ($status, $text) = &urlget("https://$downloadserver/cmc/cmcversion.txt"); + my $actv = $text; + my $up = 0; + + print ""; + if ($actv ne "") { + if ($actv =~ /^[\d\.]*$/) { + if ($actv > $myv) { + print "\n"; + } else { + print "\n"; + } + $up = 1; + } + } + unless ($up) { + print "\n"; + } + print "
Upgrade
A new version of cmc (v$actv) is available. Upgrading will retain your settings
View ChangeLog
You appear to be running the latest version of cmc. An Upgrade button will appear here if a new version becomes available
Failed to determine the latest version of cmc. An Upgrade button will appear here if new version is detected

\n"; + print "\n"; + print "\n"; +} + +print "
cmc: v$myv
"; +print "
\n"; +print < + \$("#loader").hide(); + \$("#docs-link").hide(); + +EOF +unless ($FORM{action} eq "help") { + close $SCRIPTOUT; + select STDOUT; + Cpanel::Template::process_template( + 'whostmgr', + { + "template_file" => "${thisapp}.tmpl", + "${thisapp}_output" => $templatehtml, + "print" => 1, + } + ); +} else { + print "\n"; + print "\n"; + print "\n"; +} + +# end main +############################################################################### +# start showmap +sub showmap { + if (-e "$apachepath/modsec2.whitelist.conf") { + my %ids; + open (my $FH, "<", "$apachepath/modsec2.whitelist.conf"); + flock ($FH, LOCK_SH); + my @data = <$FH>; + close ($FH); + chomp @data; + my $start = 0; + foreach my $line (@data) { + if ($line =~ /^\s*()|(# Start cmc block)/) {$start = 1} + if ($start and $line =~ /SecRuleRemoveById\s+(\d*)/) {$ids{$1} = 1} + if ($line =~ /^\s*(<\/LocationMatch>)|(# End cmc block)/) {$start = 0} + } + if (%ids) { + print "Global Disabled ID:"; + foreach my $id (sort keys %ids) {print " $id"} + print "\n"; + } + } + foreach my $userdir (glob "$stdpath/*") { + if (-d $userdir) { + my ($user, $filedir) = fileparse($userdir); + unless (-f "/var/cpanel/users/$user") {next} + my $off = 0; + if (-f "$userdir/modsec.conf") { + my $start = 0; + my %ids; + open (my $FH, "<", "$userdir/modsec.conf"); + flock ($FH, LOCK_SH); + my @data = <$FH>; + close ($FH); + chomp @data; + foreach my $line (@data) { + if ($line =~ /^\s*()|(# Start cmc block)/) {$start = 1} + if ($start and $line =~ /SecRuleRemoveById\s+(\d*)/) {$ids{$1} = 1} + if ($start and $line =~ /SecRuleEngine\s+Off/) {$off = 1} + if ($line =~ /^\s*(<\/LocationMatch>)|(# End cmc block)/) {$start = 0} + } + if ($off) { + print "$userModSecurity disabled \n"; + } + elsif (%ids) { + print "$userModSecurity enabled \n"; + print " User Disabled ID:"; + foreach my $id (keys %ids) {print " $id"} + print " \n"; + } + } + unless ($off) { + foreach my $domaindir (glob "$userdir/*") { + if (-d $domaindir) { + my ($domain, $filedir) = fileparse($domaindir); + if (-f "$domaindir/modsec.conf") { + my $start = 0; + my $off = 0; + my %ids; + open (my $FH, "<", "$domaindir/modsec.conf"); + flock ($FH, LOCK_SH); + my @data = <$FH>; + close ($FH); + chomp @data; + foreach my $line (@data) { + if ($line =~ /^\s*()|(# Start cmc block)/) {$start = 1} + if ($start and $line =~ /SecRuleRemoveById\s+(\d*)/) {$ids{$1} = 1} + if ($start and $line =~ /SecRuleEngine\s+Off/) {$off = 1} + if ($line =~ /^\s*(<\/LocationMatch>)|(# End cmc block)/) {$start = 0} + } + if ($off) { + print " $domainModSecurity disabled\n"; + } + elsif (%ids) { + print " $domainDomain Disabled ID:"; + foreach my $id (sort keys %ids) {print " $id"} + print "\n"; + } + } + } + } + } + } + } + return; +} +# end showmap +############################################################################### +sub wanted { + if (-f $File::Find::name) {push @files,$File::Find::name} + return; +} +############################################################################### +sub modsec { + my $start = 0; + my $entry; + my @requests; + my $log = "$apachelogs/modsec_audit.log"; + my $ruid2_itk = 0; + + my ($childin, $childout); + my $mypid = open3($childin, $childout, $childout, $apachebin,"-M"); + my @modules = <$childout>; + waitpid ($mypid, 0); + chomp @modules; + if (my @ls = grep {$_ =~ /ruid2_module|mpm_itk_module/} @modules) { + $ruid2_itk = 1; + $log = "$apachelogs/modsec_audit/*"; + } + + if ($ruid2_itk) { + print "

Displaying logs from $apachelogs/modsec_audit/

\n"; + find(\&wanted, "$apachelogs/modsec_audit"); + @files = sort { -M $a <=> -M $b } @files; + @files = reverse @files; + foreach my $log (@files) { + sysopen (my $IN, $log, O_RDWR | O_CREAT); + flock ($IN, LOCK_SH); + while (my $line = <$IN>) { + chomp $line; + if ($line =~ /^\=\=(\w*)\=*$/) { + $start = $1; + $entry = ""; + } + elsif ($line =~ /^\-\-(\w*)\-A\-\-$/) { + $start = $1; + $entry = ""; + } + elsif ($line =~ /^\-\-$start\-\-$/ and $start) { + push @requests, $entry; + $start = 0; + $entry = ""; + } + elsif ($line =~ /^\-\-$start-Z\-\-$/ and $start) { + push @requests, $entry; + $start = 0; + $entry = ""; + } + elsif ($start) { + $entry .= "$line\n"; + } + } + close ($IN); + } + } else { + print "

Displaying logs from $log

\n"; + sysopen (my $IN, $log, O_RDWR | O_CREAT); + flock ($IN, LOCK_SH); + while (my $line = <$IN>) { + chomp $line; + if ($line =~ /^\=\=(\w*)\=*$/) { + $start = $1; + $entry = ""; + } + elsif ($line =~ /^\-\-(\w*)\-A\-\-$/) { + $start = $1; + $entry = ""; + } + elsif ($line =~ /^\-\-$start\-\-$/ and $start) { + push @requests, $entry; + $start = 0; + $entry = ""; + } + elsif ($line =~ /^\-\-$start-Z\-\-$/ and $start) { + push @requests, $entry; + $start = 0; + $entry = ""; + } + elsif ($start) { + $entry .= "$line\n"; + } + } + close ($IN); + } + if ($FORM{refresh}) { +print < + +//Refresh page script- By Brett Taylor (glutnix\@yahoo.com.au) +//Modified by Dynamic Drive for NS4, NS6+ +//Visit http://www.dynamicdrive.com for this script + +//configure refresh interval (in seconds) +var countDownInterval=10; +//configure width of displayed text, in px (applicable only in NS4) +var c_reloadwidth=200 +var page_url = "$script?action=ms_list&lines=$FORM{lines}&refresh=$FORM{refresh}"; + + + + + + +EOF + } + + if (@requests > 0) { + my $start = 0; + if ($FORM{lines} < @requests) {$start = @requests - $FORM{lines}} + my $divcnt = 0; + my $expcnt = @requests - $start; + + print "\n"; + print "\n"; + print "\n"; + print "\n"; + for (my $x = @requests -1; $x > $start - 1; $x--) { + $divcnt++; + $requests[$x] =~ s/\&/\&\;/g; + $requests[$x] =~ s/>/\>\;/g; + $requests[$x] =~ s/"; + + my $host; + my $id; + if (my @ls = grep {$_ =~ /^Host: /} @lines) { + if ($ls[0] =~ /^Host: (.*)$/) {$host = $1} + } + if ($host eq "") {$host = $data[5]} + + if (my @ls = grep {$_ =~ /\s\[id \"\d+\"\]\s/} @lines) { + if ($ls[0] =~ /\s\[id \"(\d+)\"\]\s/) {$id = $1} + } + if ($id eq "") {$id = "unknown"} + + print "\n"; + + my $entry = "\n"; + if ($modsec =~ /\w*\.\s(.*)$/) {$modsec = $1} + $modsec = &splitlines($modsec); + print "\n"; + } + print "
ConfigServer ModSecurity Log Entries\n"; + print "\n"; + print "
DomainSource IPRule IDDate Stamp
$host$data[3]$id$data[0] $data[1] $span
$modsec$entry
\n"; + } else { + print "

No entries found in $log

\n"; + } + print "

\n"; + return; +} +############################################################################### +# start printcmd +sub printcmd { + my @command = @_; + my ($childin, $childout); + my $pid = open3($childin, $childout, $childout, @command); + while (<$childout>) {print $_} + waitpid ($pid, 0); + return; +} +# end printcmd +############################################################################### +# start onoff +sub onoff { + my $file = shift; + + open (my $FH, "<", $file); + flock ($FH, LOCK_SH); + my @data = <$FH>; + close ($FH); + chomp @data; + + my $start = 0; + my $dmstart = 0; + open (my $OUT, ">", $file); + flock ($OUT, LOCK_EX); + print $OUT "# Do not modify this file directly as it will be overwritten by cmc\n"; + print $OUT "\n"; + + unless ($FORM{choose}) {print $OUT "SecRuleEngine Off\n"} + + foreach my $line (@data) { + if ($line =~ /^\#/) {next} + if ($line =~ /^\s*\n"; + + close ($OUT); + + return; +} +# end onoff +############################################################################### +# start ids +sub ids { + my $file = shift; + my @ids = split(/\n|\r/,$FORM{ids}); + chomp @ids; + + open (my $FH, "<", $file); + flock ($FH, LOCK_SH); + my @data = <$FH>; + close ($FH); + chomp @data; + + my $start = 0; + open (my $OUT, ">", $file); + flock ($OUT, LOCK_EX); + print $OUT "# Do not modify this file directly as it will be overwritten by cmc\n"; + print $OUT "\n"; + + foreach my $line (@data) { + if ($line =~ /^\s*\n"; + foreach my $id (@ids) { + if ($id =~ /^\d+$/) {print $OUT "\tSecRuleRemoveById $id\n"} + } + print $OUT "\n"; + + print $OUT "\n"; + close ($OUT); + + return; +} +# end ids +############################################################################### +# start splitlines +sub splitlines { + my $line = shift; + my $cnt = 0; + my $newline; + for (my $x = 0;$x < length($line) ;$x++) { + if ($cnt > 120) { + $cnt = 0; + $newline .= ""; + } + my $letter = substr($line,$x,1); + if ($letter =~ /\s/) { + $cnt = 0; + } else { + $cnt++; + } + $newline .= $letter; + } + + return $newline; +} +# end splitlines +############################################################################### + +############################################################################### +# start urlget (v1.3) +# +# Examples: +#my ($status, $text) = &urlget("http://prdownloads.sourceforge.net/clamav/clamav-0.92.tar.gz","/tmp/clam.tgz"); +#if ($status) {print "Oops: $text\n"} +# +#my ($status, $text) = &urlget("http://www.configserver.com/free/msfeversion.txt"); +#if ($status) {print "Oops: $text\n"} else {print "Version: $text\n"} +# +sub urlget { + my $url = shift; + my $file = shift; + my $status = 0; + my $timeout = 1200; + local $SIG{PIPE} = 'IGNORE'; + + use LWP::UserAgent; + my $ua = LWP::UserAgent->new; + $ua->timeout(30); + my $req = HTTP::Request->new(GET => $url); + my $res; + my $text; + + ($status, $text) = eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die "Download timeout after $timeout seconds"}; + alarm($timeout); + if ($file) { + local $|=1; + my $expected_length; + my $bytes_received = 0; + my $per = 0; + my $oldper = 0; + open (my $OUT, ">", "$file\.tmp") or return (1, "Unable to open $file\.tmp: $!"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print "...0\%\n"; + $res = $ua->request($req, + sub { + my($chunk, $res) = @_; + $bytes_received += length($chunk); + unless (defined $expected_length) {$expected_length = $res->content_length || 0} + if ($expected_length) { + my $per = int(100 * $bytes_received / $expected_length); + if ((int($per / 5) == $per / 5) and ($per != $oldper)) { + print "...$per\%\n"; + $oldper = $per; + } + } else { + print "."; + } + print $OUT $chunk; + }); + close ($OUT); + print "\n"; + } else { + $res = $ua->request($req); + } + alarm(0); + if ($res->is_success) { + if ($file) { + rename ("$file\.tmp","$file") or return (1, "Unable to rename $file\.tmp to $file: $!"); + return (0, $file); + } else { + return (0, $res->content); + } + } else { + return (1, "Unable to download: ".$res->message); + } + }; + alarm(0); + if ($@) { + return (1, $@); + } + if ($text) { + return ($status,$text); + } else { + return (1, "Download timeout after $timeout seconds"); + } +} +# end urlget +############################################################################### +## start getdownloadserver +sub getdownloadserver { + my @servers; + my $downloadservers = "/usr/local/cpanel/whostmgr/docroot/cgi/configserver/cmc/downloadservers"; + my $chosen; + if (-e $downloadservers) { + open (my $DOWNLOAD, "<", $downloadservers); + flock ($DOWNLOAD, LOCK_SH); + my @data = <$DOWNLOAD>; + close ($DOWNLOAD); + chomp @data; + foreach my $line (@data) { + if ($line =~ /^download/) {push @servers, $line} + } +## foreach my $line (slurp($downloadservers)) { +## $line =~ s/$cleanreg//g; +## if ($line =~ /^download/) {push @servers, $line} +## } + $chosen = $servers[rand @servers]; + } + if ($chosen eq "") {$chosen = "download.configserver.com"} + return $chosen; +} +## end getdownloadserver +############################################################################### + +1; diff --git a/cmc/cmc.conf b/cmc/cmc.conf new file mode 100644 index 0000000..9fa1264 --- /dev/null +++ b/cmc/cmc.conf @@ -0,0 +1,27 @@ +# name +name=cmc + +# Service that will serve this app +service=whostmgr + +# Physical path: /usr/local/cpanel/3rdparty/Foo.php +# Literal URL path: $server:$port/$cpsession/3rdparty/Foo.php +url=/cgi/configserver/cmc.cgi + +# System user to run process as +user=root + +# Required acls +acls=all + +# Display name as show in the service ui +displayname=ConfigServer ModSec Control + +# Url to show in the service ui (relative to install path for whm this is cgi/) +entryurl=configserver/cmc.cgi + +upgradecall=/usr/local/cpanel/whostmgr/docroot/cgi/configserver/cmc/upgrade.sh + +icon=cmc.png + +target=_self diff --git a/cmc/cmc.tmpl b/cmc/cmc.tmpl new file mode 100644 index 0000000..223d3d5 --- /dev/null +++ b/cmc/cmc.tmpl @@ -0,0 +1,29 @@ +[% +USE Whostmgr; +USE JSON; + +WRAPPER 'master_templates/master.tmpl' + header = 'ConfigServer ModSecurity Control' + skipsupport = 1 + skipheader = 1 + hide_license_warnings = 1 + theme='bootstrap' + breadcrumbdata = { + previous = [ + { + name = "Home", + url = "/scripts/command?PFILE=main", + }, + { + name = "Plugins", + url = "/scripts/command?PFILE=Plugins", + } + ], + name = 'ConfigServer ModSecurity Control', + url = '/cgi/configserver/cmc.cgi', + }; +%] + +[% cmc_output %] + +[% END %] diff --git a/cmc/cmc/bootstrap/css/bootstrap.min.css b/cmc/cmc/bootstrap/css/bootstrap.min.css new file mode 100644 index 0000000..ed3905e --- /dev/null +++ b/cmc/cmc/bootstrap/css/bootstrap.min.css @@ -0,0 +1,6 @@ +/*! + * Bootstrap v3.3.7 (http://getbootstrap.com) + * Copyright 2011-2016 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,:after,:before{color:#000!important;text-shadow:none!important;background:0 0!important;-webkit-box-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff2) format('woff2'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\002a"}.glyphicon-plus:before{content:"\002b"}.glyphicon-eur:before,.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:focus,a:hover{color:#23527c;text-decoration:underline}a:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.carousel-inner>.item>a>img,.carousel-inner>.item>img,.img-responsive,.thumbnail a>img,.thumbnail>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;max-width:100%;height:auto;padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role=button]{cursor:pointer}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1;color:#777}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}.small,small{font-size:85%}.mark,mark{padding:.2em;background-color:#fcf8e3}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:focus,a.text-primary:hover{color:#286090}.text-success{color:#3c763d}a.text-success:focus,a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:focus,a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:focus,a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:focus,a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:focus,a.bg-primary:hover{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:focus,a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:focus,a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:focus,a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:focus,a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ol,ul{margin-top:0;margin-bottom:10px}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;margin-left:-5px;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-top:0;margin-bottom:20px}dd,dt{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[data-original-title],abbr[title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child{margin-bottom:0}blockquote .small,blockquote footer,blockquote small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote .small:before,blockquote footer:before,blockquote small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eee;border-left:0}.blockquote-reverse .small:before,.blockquote-reverse footer:before,.blockquote-reverse small:before,blockquote.pull-right .small:before,blockquote.pull-right footer:before,blockquote.pull-right small:before{content:''}.blockquote-reverse .small:after,.blockquote-reverse footer:after,.blockquote-reverse small:after,blockquote.pull-right .small:after,blockquote.pull-right footer:after,blockquote.pull-right small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{margin-right:-15px;margin-left:-15px}.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>td,.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>td,.table>thead:first-child>tr:first-child>th{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>tbody>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>thead>tr>th{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #ddd}.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*=col-]{position:static;display:table-column;float:none}table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;float:none}.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>thead>tr>td.active,.table>thead>tr>th.active{background-color:#f5f5f5}.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover{background-color:#e8e8e8}.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{background-color:#dff0d8}.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6}.table>tbody>tr.info>td,.table>tbody>tr.info>th,.table>tbody>tr>td.info,.table>tbody>tr>th.info,.table>tfoot>tr.info>td,.table>tfoot>tr.info>th,.table>tfoot>tr>td.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>thead>tr.info>th,.table>thead>tr>td.info,.table>thead>tr>th.info{background-color:#d9edf7}.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover{background-color:#c4e3f3}.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fcf8e3}.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc}.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#f2dede}.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc}.table-responsive{min-height:.01%;overflow-x:auto}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=checkbox],input[type=radio]{margin:4px 0 0;margin-top:1px\9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[type=checkbox]:focus,input[type=radio]:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control::-ms-expand{background-color:transparent;border:0}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}input[type=search]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type=date].form-control,input[type=time].form-control,input[type=datetime-local].form-control,input[type=month].form-control{line-height:34px}.input-group-sm input[type=date],.input-group-sm input[type=time],.input-group-sm input[type=datetime-local],.input-group-sm input[type=month],input[type=date].input-sm,input[type=time].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm{line-height:30px}.input-group-lg input[type=date],.input-group-lg input[type=time],.input-group-lg input[type=datetime-local],.input-group-lg input[type=month],input[type=date].input-lg,input[type=time].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg{line-height:46px}}.form-group{margin-bottom:15px}.checkbox,.radio{position:relative;display:block;margin-top:10px;margin-bottom:10px}.checkbox label,.radio label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{position:absolute;margin-top:4px\9;margin-left:-20px}.checkbox+.checkbox,.radio+.radio{margin-top:-5px}.checkbox-inline,.radio-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px}fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox].disabled,input[type=checkbox][disabled],input[type=radio].disabled,input[type=radio][disabled]{cursor:not-allowed}.checkbox-inline.disabled,.radio-inline.disabled,fieldset[disabled] .checkbox-inline,fieldset[disabled] .radio-inline{cursor:not-allowed}.checkbox.disabled label,.radio.disabled label,fieldset[disabled] .checkbox label,fieldset[disabled] .radio label{cursor:not-allowed}.form-control-static{min-height:34px;padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}select[multiple].input-sm,textarea.input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm select[multiple].form-control,.form-group-sm textarea.form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}select[multiple].input-lg,textarea.input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:46px;line-height:46px}.form-group-lg select[multiple].form-control,.form-group-lg textarea.form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.form-group-lg .form-control+.form-control-feedback,.input-group-lg+.form-control-feedback,.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.form-group-sm .form-control+.form-control-feedback,.input-group-sm+.form-control-feedback,.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .checkbox,.has-success .checkbox-inline,.has-success .control-label,.has-success .help-block,.has-success .radio,.has-success .radio-inline,.has-success.checkbox label,.has-success.checkbox-inline label,.has-success.radio label,.has-success.radio-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .checkbox,.has-warning .checkbox-inline,.has-warning .control-label,.has-warning .help-block,.has-warning .radio,.has-warning .radio-inline,.has-warning.checkbox label,.has-warning.checkbox-inline label,.has-warning.radio label,.has-warning.radio-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .checkbox,.has-error .checkbox-inline,.has-error .control-label,.has-error .help-block,.has-error .radio,.has-error .radio-inline,.has-error.checkbox label,.has-error.checkbox-inline label,.has-error.radio label,.has-error.radio-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .form-control,.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .checkbox,.form-inline .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .checkbox label,.form-inline .radio label{padding-left:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .checkbox,.form-horizontal .radio{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:11px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:none;border:1px solid transparent;border-radius:4px}.btn.active.focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn:active:focus,.btn:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.focus,.btn:focus,.btn:hover{color:#333;text-decoration:none}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none;opacity:.65}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default.focus,.btn-default:focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.btn-default:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active.focus,.btn-default.active:focus,.btn-default.active:hover,.btn-default:active.focus,.btn-default:active:focus,.btn-default:active:hover,.open>.dropdown-toggle.btn-default.focus,.open>.dropdown-toggle.btn-default:focus,.open>.dropdown-toggle.btn-default:hover{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled.focus,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled].focus,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#286090;border-color:#122b40}.btn-primary:hover{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active.focus,.btn-primary.active:focus,.btn-primary.active:hover,.btn-primary:active.focus,.btn-primary:active:focus,.btn-primary:active:hover,.open>.dropdown-toggle.btn-primary.focus,.open>.dropdown-toggle.btn-primary:focus,.open>.dropdown-toggle.btn-primary:hover{color:#fff;background-color:#204d74;border-color:#122b40}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled.focus,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled].focus,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#449d44;border-color:#255625}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active.focus,.btn-success.active:focus,.btn-success.active:hover,.btn-success:active.focus,.btn-success:active:focus,.btn-success:active:hover,.open>.dropdown-toggle.btn-success.focus,.open>.dropdown-toggle.btn-success:focus,.open>.dropdown-toggle.btn-success:hover{color:#fff;background-color:#398439;border-color:#255625}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled.focus,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled].focus,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active.focus,.btn-info.active:focus,.btn-info.active:hover,.btn-info:active.focus,.btn-info:active:focus,.btn-info:active:hover,.open>.dropdown-toggle.btn-info.focus,.open>.dropdown-toggle.btn-info:focus,.open>.dropdown-toggle.btn-info:hover{color:#fff;background-color:#269abc;border-color:#1b6d85}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled.focus,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled].focus,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning.focus,.btn-warning:focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active.focus,.btn-warning.active:focus,.btn-warning.active:hover,.btn-warning:active.focus,.btn-warning:active:focus,.btn-warning:active:hover,.open>.dropdown-toggle.btn-warning.focus,.open>.dropdown-toggle.btn-warning:focus,.open>.dropdown-toggle.btn-warning:hover{color:#fff;background-color:#d58512;border-color:#985f0d}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled.focus,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled].focus,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c9302c;border-color:#761c19}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active.focus,.btn-danger.active:focus,.btn-danger.active:hover,.btn-danger:active.focus,.btn-danger:active:focus,.btn-danger:active:hover,.open>.dropdown-toggle.btn-danger.focus,.open>.dropdown-toggle.btn-danger:focus,.open>.dropdown-toggle.btn-danger:hover{color:#fff;background-color:#ac2925;border-color:#761c19}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled.focus,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled].focus,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#337ab7;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#777;text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-group-sm>.btn,.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-xs>.btn,.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:height,visibility;-o-transition-property:height,visibility;transition-property:height,visibility}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid\9;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown,.dropup{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;background-color:#337ab7;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#777}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px dashed;border-bottom:4px solid\9}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;float:left}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-left-radius:0;border-top-right-radius:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group .form-control:focus{z-index:3}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn,textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn,textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group .form-control,.input-group-addon,.input-group-btn{display:table-cell}.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn-group:not(:last-child)>.btn,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:first-child>.btn-group:not(:first-child)>.btn,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:focus,.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:focus,.nav>li.disabled>a:hover{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:focus,.nav .open>a:hover{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:focus,.nav-tabs>li.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:focus,.nav-pills>li.active>a:hover{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;-webkit-overflow-scrolling:touch;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1)}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:200px}}.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;height:50px;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1)}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .form-control,.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .checkbox label,.navbar-form .radio label{padding-left:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:focus,.navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:focus,.navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:focus,.navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:focus,.navbar-default .navbar-nav>.open>a:hover{color:#555;background-color:#e7e7e7}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:focus,.navbar-default .btn-link:hover{color:#333}.navbar-default .btn-link[disabled]:focus,.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:focus,fieldset[disabled] .navbar-default .btn-link:hover{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:focus,.navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:focus,.navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:focus,.navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:focus,.navbar-inverse .navbar-toggle:hover{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{color:#fff;background-color:#080808}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:focus,.navbar-inverse .btn-link:hover{color:#fff}.navbar-inverse .btn-link[disabled]:focus,.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:focus,fieldset[disabled] .navbar-inverse .btn-link:hover{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.42857143;color:#337ab7;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:2;color:#23527c;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:3;color:#fff;cursor:default;background-color:#337ab7;border-color:#337ab7}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:focus,.pager li>a:hover{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:focus,a.label:hover{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:focus,.label-default[href]:hover{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:focus,.label-primary[href]:hover{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:focus,.label-success[href]:hover{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:focus,.label-info[href]:hover{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:focus,.label-warning[href]:hover{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:focus,.label-danger[href]:hover{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:middle;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-group-xs>.btn .badge,.btn-xs .badge{top:0;padding:1px 5px}a.badge:focus,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron .h1,.jumbotron h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{padding-right:15px;padding-left:15px;border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-right:60px;padding-left:60px}.jumbotron .h1,.jumbotron h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail a>img,.thumbnail>img{margin-right:auto;margin-left:auto}a.thumbnail.active,a.thumbnail:focus,a.thumbnail:hover{border-color:#337ab7}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-bar-striped,.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress-bar.active,.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{overflow:hidden;zoom:1}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-body,.media-left,.media-right{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}a.list-group-item,button.list-group-item{color:#555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333}a.list-group-item:focus,a.list-group-item:hover,button.list-group-item:focus,button.list-group-item:hover{color:#555;text-decoration:none;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item.disabled,.list-group-item.disabled:focus,.list-group-item.disabled:hover{color:#777;cursor:not-allowed;background-color:#eee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:focus .list-group-item-text,.list-group-item.active:hover .list-group-item-text{color:#c7ddef}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:focus,a.list-group-item-success:hover,button.list-group-item-success:focus,button.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:focus,a.list-group-item-success.active:hover,button.list-group-item-success.active,button.list-group-item-success.active:focus,button.list-group-item-success.active:hover{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:focus,a.list-group-item-info:hover,button.list-group-item-info:focus,button.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:focus,a.list-group-item-info.active:hover,button.list-group-item-info.active,button.list-group-item-info.active:focus,button.list-group-item-info.active:hover{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:focus,a.list-group-item-warning:hover,button.list-group-item-warning:focus,button.list-group-item-warning:hover{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:focus,a.list-group-item-warning.active:hover,button.list-group-item-warning.active,button.list-group-item-warning.active:focus,button.list-group-item-warning.active:hover{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:focus,a.list-group-item-danger:hover,button.list-group-item-danger:focus,button.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover,button.list-group-item-danger.active,button.list-group-item-danger.active:focus,button.list-group-item-danger.active:hover{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>.small,.panel-title>.small>a,.panel-title>a,.panel-title>small,.panel-title>small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-left-radius:0;border-top-right-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.panel-collapse>.table,.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.panel-collapse>.table caption,.panel>.table caption,.panel>.table-responsive>.table caption{padding-right:15px;padding-left:15px}.panel>.table-responsive:first-child>.table:first-child,.panel>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table:first-child>thead:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table-responsive:last-child>.table:last-child,.panel>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child td,.panel>.table>tbody:first-child>tr:first-child th{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.list-group,.panel-group .panel-heading+.panel-collapse>.panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{-webkit-appearance:none;padding:0;cursor:pointer;background:0 0;border:0}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out;-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%)}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5)}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:12px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;filter:alpha(opacity=0);opacity:0;line-break:auto}.tooltip.in{filter:alpha(opacity=90);opacity:.9}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{right:5px;bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);line-break:auto}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{content:"";border-width:10px}.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25)}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>a>img,.carousel-inner>.item>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.active.right,.carousel-inner>.item.next{left:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.carousel-inner>.item.active.left,.carousel-inner>.item.prev{left:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.carousel-inner>.item.active,.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right{left:0;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);background-color:rgba(0,0,0,0);filter:alpha(opacity=50);opacity:.5}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);background-repeat:repeat-x}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);background-repeat:repeat-x}.carousel-control:focus,.carousel-control:hover{color:#fff;text-decoration:none;filter:alpha(opacity=90);outline:0;opacity:.9}.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block;margin-top:-10px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{left:50%;margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{right:50%;margin-right:-10px}.carousel-control .icon-next,.carousel-control .icon-prev{width:20px;height:20px;font-family:serif;line-height:1}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000\9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-10px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-10px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.btn-group-vertical>.btn-group:after,.btn-group-vertical>.btn-group:before,.btn-toolbar:after,.btn-toolbar:before,.clearfix:after,.clearfix:before,.container-fluid:after,.container-fluid:before,.container:after,.container:before,.dl-horizontal dd:after,.dl-horizontal dd:before,.form-horizontal .form-group:after,.form-horizontal .form-group:before,.modal-footer:after,.modal-footer:before,.modal-header:after,.modal-header:before,.nav:after,.nav:before,.navbar-collapse:after,.navbar-collapse:before,.navbar-header:after,.navbar-header:before,.navbar:after,.navbar:before,.pager:after,.pager:before,.panel-body:after,.panel-body:before,.row:after,.row:before{display:table;content:" "}.btn-group-vertical>.btn-group:after,.btn-toolbar:after,.clearfix:after,.container-fluid:after,.container:after,.dl-horizontal dd:after,.form-horizontal .form-group:after,.modal-footer:after,.modal-header:after,.nav:after,.navbar-collapse:after,.navbar-header:after,.navbar:after,.pager:after,.panel-body:after,.row:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-lg,.visible-md,.visible-sm,.visible-xs{display:none!important}.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table!important}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table!important}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table!important}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table!important}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table!important}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}} +/*# sourceMappingURL=bootstrap.min.css.map */ \ No newline at end of file diff --git a/cmc/cmc/bootstrap/fonts/glyphicons-halflings-regular.eot b/cmc/cmc/bootstrap/fonts/glyphicons-halflings-regular.eot new file mode 100644 index 0000000000000000000000000000000000000000..b93a4953fff68df523aa7656497ee339d6026d64 GIT binary patch literal 20127 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cmc/cmc/bootstrap/fonts/glyphicons-halflings-regular.ttf b/cmc/cmc/bootstrap/fonts/glyphicons-halflings-regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..1413fc609ab6f21774de0cb7e01360095584f65b GIT binary patch literal 45404 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 G`u_lkUM?>H literal 0 HcmV?d00001 diff --git a/cmc/cmc/bootstrap/fonts/glyphicons-halflings-regular.woff2 b/cmc/cmc/bootstrap/fonts/glyphicons-halflings-regular.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..64539b54c3751a6d9adb44c8e3a45ba5a73b77f0 GIT binary patch literal 18028 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 literal 0 HcmV?d00001 diff --git a/cmc/cmc/bootstrap/js/bootstrap.min.js b/cmc/cmc/bootstrap/js/bootstrap.min.js new file mode 100644 index 0000000..9bcd2fc --- /dev/null +++ b/cmc/cmc/bootstrap/js/bootstrap.min.js @@ -0,0 +1,7 @@ +/*! + * Bootstrap v3.3.7 (http://getbootstrap.com) + * Copyright 2011-2016 Twitter, Inc. + * Licensed under the MIT license + */ +if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1||b[0]>3)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){if(a(b.target).is(this))return b.handleObj.handler.apply(this,arguments)}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.7",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a("#"===f?[]:f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.7",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c).prop(c,!0)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c).prop(c,!1))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")?(c.prop("checked")&&(a=!1),b.find(".active").removeClass("active"),this.$element.addClass("active")):"checkbox"==c.prop("type")&&(c.prop("checked")!==this.$element.hasClass("active")&&(a=!1),this.$element.toggleClass("active")),c.prop("checked",this.$element.hasClass("active")),a&&c.trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active")),this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target).closest(".btn");b.call(d,"toggle"),a(c.target).is('input[type="radio"], input[type="checkbox"]')||(c.preventDefault(),d.is("input,button")?d.trigger("focus"):d.find("input:visible,button:visible").first().trigger("focus"))}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.7",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c=this.getItemIndex(b),d="prev"==a&&0===c||"next"==a&&c==this.$items.length-1;if(d&&!this.options.wrap)return b;var e="prev"==a?-1:1,f=(c+e)%this.$items.length;return this.$items.eq(f)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(".item.active"));if(!(a>this.$items.length-1||a<0))return this.sliding?this.$element.one("slid.bs.carousel",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?"next":"prev",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){if(!this.sliding)return this.slide("next")},c.prototype.prev=function(){if(!this.sliding)return this.slide("prev")},c.prototype.slide=function(b,d){var e=this.$element.find(".item.active"),f=d||this.getItemForDirection(b,e),g=this.interval,h="next"==b?"left":"right",i=this;if(f.hasClass("active"))return this.sliding=!1;var j=f[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:h});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(f)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:h});return a.support.transition&&this.$element.hasClass("slide")?(f.addClass(b),f[0].offsetWidth,e.addClass(h),f.addClass(h),e.one("bsTransitionEnd",function(){f.removeClass([b,h].join(" ")).addClass("active"),e.removeClass(["active",h].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trigger(m)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}};a(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){var c,d=b.attr("data-target")||(c=b.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data("bs.collapse"),f=a.extend({},d.DEFAULTS,c.data(),"object"==typeof b&&b);!e&&f.toggle&&/show|hide/.test(b)&&(f.toggle=!1),e||c.data("bs.collapse",e=new d(this,f)),"string"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a('[data-toggle="collapse"][href="#'+b.id+'"],[data-toggle="collapse"][data-target="#'+b.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION="3.3.7",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0},d.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},d.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b,e=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(e&&e.length&&(b=e.data("bs.collapse"),b&&b.transitioning))){var f=a.Event("show.bs.collapse");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,"hide"),b||e.data("bs.collapse",null));var g=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[g](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var h=function(){this.$element.removeClass("collapsing").addClass("collapse in")[g](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return h.call(this);var i=a.camelCase(["scroll",g].join("-"));this.$element.one("bsTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var e=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass("in");a.attr("aria-expanded",c),b.toggleClass("collapsed",!c).attr("aria-expanded",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(d){var e=a(this);e.attr("data-target")||d.preventDefault();var f=b(e),g=f.data("bs.collapse"),h=g?"toggle":e.data();c.call(f,h)})}(jQuery),+function(a){"use strict";function b(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function c(c){c&&3===c.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=b(d),f={relatedTarget:this};e.hasClass("open")&&(c&&"click"==c.type&&/input|textarea/i.test(c.target.tagName)&&a.contains(e[0],c.target)||(e.trigger(c=a.Event("hide.bs.dropdown",f)),c.isDefaultPrevented()||(d.attr("aria-expanded","false"),e.removeClass("open").trigger(a.Event("hidden.bs.dropdown",f)))))}))}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.3.7",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=b(e),g=f.hasClass("open");if(c(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(document.createElement("div")).addClass("dropdown-backdrop").insertAfter(a(this)).on("click",c);var h={relatedTarget:this};if(f.trigger(d=a.Event("show.bs.dropdown",h)),d.isDefaultPrevented())return;e.trigger("focus").attr("aria-expanded","true"),f.toggleClass("open").trigger(a.Event("shown.bs.dropdown",h))}return!1}},g.prototype.keydown=function(c){if(/(38|40|27|32)/.test(c.which)&&!/input|textarea/i.test(c.target.tagName)){var d=a(this);if(c.preventDefault(),c.stopPropagation(),!d.is(".disabled, :disabled")){var e=b(d),g=e.hasClass("open");if(!g&&27!=c.which||g&&27==c.which)return 27==c.which&&e.find(f).trigger("focus"),d.trigger("click");var h=" li:not(.disabled):visible a",i=e.find(".dropdown-menu"+h);if(i.length){var j=i.index(c.target);38==c.which&&j>0&&j--,40==c.which&&jdocument.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&a?this.scrollbarWidth:"",paddingRight:this.bodyIsOverflowing&&!a?this.scrollbarWidth:""})},c.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:"",paddingRight:""})},c.prototype.checkScrollbar=function(){var a=window.innerWidth;if(!a){var b=document.documentElement.getBoundingClientRect();a=b.right-Math.abs(b.left)}this.bodyIsOverflowing=document.body.clientWidth
',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){if(this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(a.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusin"==b.type?"focus":"hover"]=!0),c.tip().hasClass("in")||"in"==c.hoverState?void(c.hoverState="in"):(clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show())},c.prototype.isInStateTrue=function(){for(var a in this.inState)if(this.inState[a])return!0;return!1},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);if(c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusout"==b.type?"focus":"hover"]=!1),!c.isInStateTrue())return clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide()},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var d=a.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!d)return;var e=this,f=this.tip(),g=this.getUID(this.type);this.setContent(),f.attr("id",g),this.$element.attr("aria-describedby",g),this.options.animation&&f.addClass("fade");var h="function"==typeof this.options.placement?this.options.placement.call(this,f[0],this.$element[0]):this.options.placement,i=/\s?auto?\s?/i,j=i.test(h);j&&(h=h.replace(i,"")||"top"),f.detach().css({top:0,left:0,display:"block"}).addClass(h).data("bs."+this.type,this),this.options.container?f.appendTo(this.options.container):f.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.getPosition(this.$viewport);h="bottom"==h&&k.bottom+m>o.bottom?"top":"top"==h&&k.top-mo.width?"left":"left"==h&&k.left-lg.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;jg.right&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){if(!this.$tip&&(this.$tip=a(this.options.template),1!=this.$tip.length))throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!");return this.$tip},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),b?(c.inState.click=!c.inState.click,c.isInStateTrue()?c.enter(c):c.leave(c)):c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){var a=this;clearTimeout(this.timeout),this.hide(function(){a.$element.off("."+a.type).removeData("bs."+a.type),a.$tip&&a.$tip.detach(),a.$tip=null,a.$arrow=null,a.$viewport=null,a.$element=null})};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;!e&&/destroy|hide/.test(b)||(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.3.7",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:''}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){this.$body=a(document.body),this.$scrollElement=a(a(c).is(document.body)?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",a.proxy(this.process,this)),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.3.7",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b=this,c="offset",d=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),a.isWindow(this.$scrollElement[0])||(c="position",d=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var b=a(this),e=b.data("target")||b.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[c]().top+d,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b=e[a]&&(void 0===e[a+1]||b .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),b.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),h?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu").length&&b.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),e&&e()}var g=d.find("> .active"),h=e&&a.support.transition&&(g.length&&g.hasClass("fade")||!!d.find("> .fade").length);g.length&&h?g.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),"show")};a(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.3.7",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&"top"==this.affixed)return e=a-d&&"bottom"},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=Math.max(a(document).height(),a(document.body).height());"object"!=typeof d&&(f=e=d),"function"==typeof e&&(e=d.top(this.$element)),"function"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css("top","");var i="affix"+(h?"-"+h:""),j=a.Event(i+".bs.affix");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin="bottom"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace("affix","affixed")+".bs.affix")}"bottom"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery); \ No newline at end of file diff --git a/cmc/cmc/cmc.png b/cmc/cmc/cmc.png new file mode 100644 index 0000000000000000000000000000000000000000..4e5702f45a3c8920492afbc39d6e1d48b2ae1e35 GIT binary patch literal 1691 zcmV;M24wk(P)mkJqzifBX3V{^$Jr|Ib}>!2;cD@3p?Q_g-tS zz0YqTB7?s?*w7GOpPc+daa`OlZ+GnYJ0mQtF(ou~&}c9aIFw^purt%8ZP(1`D_=!xn4?#DS(KPrheCI5bn> z6@fnl+kQDvnV5LN7!oq+t?}oKe_ytYGQz_--H%zliIr=icE$y>r0jD-$QRzhn# z2?N&co(~Bjb6gyabagp_8tv=T1&#g#_4TSY=z>mnF(C?URjM?($u?;#R?wHMEE&M$ z*cjD6ctAP(_EBF&1#h$4?KDtV=h!*}12jCfLTI;KzD$2@*}}(QtVCZ-Cazo0Hn6#- zSSJUNgY^{rxpplL)Yi&ITeGw2)w*@`V!;Ax&&hFsoSY={sZ(URc#;1<*xXF%D_2sN z*(^IzaO@b@hq2Hh5p=_b9tL0(I)GD9?~r;K5kW%?44?J!ar(dj%1W-`)|n->Mbwl1|~*E zD0lzXMVE_iAP)m7F~*vlI{58rFmaxxG0x)e+b|Jx={w($i&KRd???>tebkf=#{JNh$!j z1FRzaS*!EAJ$pE~nI_nTZ7p2DEIYu;T8mc4?y2CzHW^{duViWK*e51bvhl$|O_?(N zB1>uMg>5Zdz|0+B7mEn36Bjce(LV;eu!1=BKzWA`du^Xj0>f^286Ms!5*8gl?g(C% zn?*BFaqAYB_gJk$rzjCKC4tFCdw<6f8>bJ0nBhuSs8ER z&nk-48IWfc^5bEPDW$I#i(`dYYJGp`kdp%#C#@iV*qS=H0{XB;em*U}KX_1HA%K)p zEM|Lb>dh1vn38kn#7~P%r{7PDtr>td { + vertical-align: middle; +} +.panel-default > .panel-heading-cxs { + font-weight: bold; + background: #F4F4EA; +} +.panel-default > .panel-footer-cxs { + font-weight: bold; + background: #F4F4EA; +} +#loader { + position: absolute; + left: 50%; + top: 50%; + z-index: 1; + margin: -75px 0 0 -75px; + border: 16px solid #F4F4EA; + border-radius: 50%; + border-top: 16px solid #990000; + border-bottom: 16px solid #990000; + width: 120px; + height: 120px; + -webkit-animation: spin 2s linear infinite; + animation: spin 2s linear infinite; +} +@-webkit-keyframes spin { + 0% { -webkit-transform: rotate(0deg); } + 100% { -webkit-transform: rotate(360deg); } +} +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} +.bs-callout { + padding: 20px; + margin: 20px 0; + border: 1px solid #eee; + border-left-width: 5px; + border-radius: 3px; +} +.bs-callout h4 { + margin-top: 0; + margin-bottom: 5px; +} +.bs-callout p:last-child { + margin-bottom: 0; +} +.bs-callout code { + border-radius: 3px; +} +.bs-callout+.bs-callout { + margin-top: -5px; +} +.bs-callout-success { + border-left-color: #5cb85c; + background-color: #edf7ed; +} +.bs-callout-success h4 { + color: #5cb85c; +}.bs-callout-info { + border-left-color: #5bc0de; + background-color: #eaf7fb; +} +.bs-callout-info h4 { + color: #5bc0de; +} +.bs-callout-warning { + border-left-color: #f0ad4e; + background-color: #fdf4e8; +} +.bs-callout-warning h4 { + color: #f0ad4e; +} +.bs-callout-danger { + border-left-color: #d9534f; + background-color: #faebea; +} +.bs-callout-danger h4 { + color: #d9534f; +} diff --git a/cmc/cmc/jquery.min.js b/cmc/cmc/jquery.min.js new file mode 100644 index 0000000..e836475 --- /dev/null +++ b/cmc/cmc/jquery.min.js @@ -0,0 +1,5 @@ +/*! jQuery v1.12.4 | (c) jQuery Foundation | jquery.org/license */ +!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=a.document,e=c.slice,f=c.concat,g=c.push,h=c.indexOf,i={},j=i.toString,k=i.hasOwnProperty,l={},m="1.12.4",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return e.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:e.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a){return n.each(this,a)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(e.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor()},push:g,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(n.isPlainObject(c)||(b=n.isArray(c)))?(b?(b=!1,f=a&&n.isArray(a)?a:[]):f=a&&n.isPlainObject(a)?a:{},g[d]=n.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray||function(a){return"array"===n.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){var b=a&&a.toString();return!n.isArray(a)&&b-parseFloat(b)+1>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==n.type(a)||a.nodeType||n.isWindow(a))return!1;try{if(a.constructor&&!k.call(a,"constructor")&&!k.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(!l.ownFirst)for(b in a)return k.call(a,b);for(b in a);return void 0===b||k.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?i[j.call(a)]||"object":typeof a},globalEval:function(b){b&&n.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b){var c,d=0;if(s(a)){for(c=a.length;c>d;d++)if(b.call(a[d],d,a[d])===!1)break}else for(d in a)if(b.call(a[d],d,a[d])===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):g.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(h)return h.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,e,g=0,h=[];if(s(a))for(d=a.length;d>g;g++)e=b(a[g],g,c),null!=e&&h.push(e);else for(g in a)e=b(a[g],g,c),null!=e&&h.push(e);return f.apply([],h)},guid:1,proxy:function(a,b){var c,d,f;return"string"==typeof b&&(f=a[b],b=a,a=f),n.isFunction(a)?(c=e.call(arguments,2),d=function(){return a.apply(b||this,c.concat(e.call(arguments)))},d.guid=a.guid=a.guid||n.guid++,d):void 0},now:function(){return+new Date},support:l}),"function"==typeof Symbol&&(n.fn[Symbol.iterator]=c[Symbol.iterator]),n.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(a,b){i["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=!!a&&"length"in a&&a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ga(),z=ga(),A=ga(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+M+"))|)"+L+"*\\]",O=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+N+")*)|.*)\\)|)",P=new RegExp(L+"+","g"),Q=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),R=new RegExp("^"+L+"*,"+L+"*"),S=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),T=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),U=new RegExp(O),V=new RegExp("^"+M+"$"),W={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M+"|[*])"),ATTR:new RegExp("^"+N),PSEUDO:new RegExp("^"+O),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},X=/^(?:input|select|textarea|button)$/i,Y=/^h\d$/i,Z=/^[^{]+\{\s*\[native \w/,$=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,_=/[+~]/,aa=/'|\\/g,ba=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),ca=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},da=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(ea){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fa(a,b,d,e){var f,h,j,k,l,o,r,s,w=b&&b.ownerDocument,x=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==x&&9!==x&&11!==x)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==x&&(o=$.exec(a)))if(f=o[1]){if(9===x){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(w&&(j=w.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(o[2])return H.apply(d,b.getElementsByTagName(a)),d;if((f=o[3])&&c.getElementsByClassName&&b.getElementsByClassName)return H.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==x)w=b,s=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(aa,"\\$&"):b.setAttribute("id",k=u),r=g(a),h=r.length,l=V.test(k)?"#"+k:"[id='"+k+"']";while(h--)r[h]=l+" "+qa(r[h]);s=r.join(","),w=_.test(a)&&oa(b.parentNode)||b}if(s)try{return H.apply(d,w.querySelectorAll(s)),d}catch(y){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(Q,"$1"),b,d,e)}function ga(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ha(a){return a[u]=!0,a}function ia(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ja(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function ka(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function la(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function na(a){return ha(function(b){return b=+b,ha(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function oa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=fa.support={},f=fa.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fa.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ia(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ia(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Z.test(n.getElementsByClassName),c.getById=ia(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return"undefined"!=typeof b.getElementsByClassName&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=Z.test(n.querySelectorAll))&&(ia(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ia(function(a){var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Z.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ia(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",O)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Z.test(o.compareDocumentPosition),t=b||Z.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return ka(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?ka(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},fa.matches=function(a,b){return fa(a,null,null,b)},fa.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(T,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fa(b,n,null,[a]).length>0},fa.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fa.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fa.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fa.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fa.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fa.selectors={cacheLength:50,createPseudo:ha,match:W,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ba,ca),a[3]=(a[3]||a[4]||a[5]||"").replace(ba,ca),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fa.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fa.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return W.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&U.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ba,ca).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fa.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(P," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fa.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ha(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ha(function(a){var b=[],c=[],d=h(a.replace(Q,"$1"));return d[u]?ha(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ha(function(a){return function(b){return fa(a,b).length>0}}),contains:ha(function(a){return a=a.replace(ba,ca),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ha(function(a){return V.test(a||"")||fa.error("unsupported lang: "+a),a=a.replace(ba,ca).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Y.test(a.nodeName)},input:function(a){return X.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:na(function(){return[0]}),last:na(function(a,b){return[b-1]}),eq:na(function(a,b,c){return[0>c?c+b:c]}),even:na(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:na(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:na(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:na(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function ra(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j,k=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(j=b[u]||(b[u]={}),i=j[b.uniqueID]||(j[b.uniqueID]={}),(h=i[d])&&h[0]===w&&h[1]===f)return k[2]=h[2];if(i[d]=k,k[2]=a(b,c,g))return!0}}}function sa(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ta(a,b,c){for(var d=0,e=b.length;e>d;d++)fa(a,b[d],c);return c}function ua(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(c&&!c(f,d,e)||(g.push(f),j&&b.push(h)));return g}function va(a,b,c,d,e,f){return d&&!d[u]&&(d=va(d)),e&&!e[u]&&(e=va(e,f)),ha(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ta(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ua(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ua(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ua(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function wa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ra(function(a){return a===b},h,!0),l=ra(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[ra(sa(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return va(i>1&&sa(m),i>1&&qa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(Q,"$1"),c,e>i&&wa(a.slice(i,e)),f>e&&wa(a=a.slice(e)),f>e&&qa(a))}m.push(c)}return sa(m)}function xa(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=F.call(i));u=ua(u)}H.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&fa.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ha(f):f}return h=fa.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xa(e,d)),f.selector=a}return f},i=fa.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ba,ca),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=W.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ba,ca),_.test(j[0].type)&&oa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qa(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,!b||_.test(a)&&oa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ia(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ia(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ja("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ia(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ja("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ia(function(a){return null==a.getAttribute("disabled")})||ja(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fa}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.uniqueSort=n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},v=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},w=n.expr.match.needsContext,x=/^<([\w-]+)\s*\/?>(?:<\/\1>|)$/,y=/^.[^:#\[\.,]*$/;function z(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(y.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return n.inArray(a,b)>-1!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;e>b;b++)if(n.contains(d[b],this))return!0}));for(b=0;e>b;b++)n.find(a,d[b],c);return c=this.pushStack(e>1?n.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(z(this,a||[],!1))},not:function(a){return this.pushStack(z(this,a||[],!0))},is:function(a){return!!z(this,"string"==typeof a&&w.test(a)?n(a):a||[],!1).length}});var A,B=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=n.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||A,"string"==typeof a){if(e="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:B.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),x.test(e[1])&&n.isPlainObject(b))for(e in b)n.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}if(f=d.getElementById(e[2]),f&&f.parentNode){if(f.id!==e[2])return A.find(a);this.length=1,this[0]=f}return this.context=d,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof c.ready?c.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};C.prototype=n.fn,A=n(d);var D=/^(?:parents|prev(?:Until|All))/,E={children:!0,contents:!0,next:!0,prev:!0};n.fn.extend({has:function(a){var b,c=n(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(n.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=w.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?n.inArray(this[0],n(a)):n.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.uniqueSort(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function F(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return u(a,"parentNode")},parentsUntil:function(a,b,c){return u(a,"parentNode",c)},next:function(a){return F(a,"nextSibling")},prev:function(a){return F(a,"previousSibling")},nextAll:function(a){return u(a,"nextSibling")},prevAll:function(a){return u(a,"previousSibling")},nextUntil:function(a,b,c){return u(a,"nextSibling",c)},prevUntil:function(a,b,c){return u(a,"previousSibling",c)},siblings:function(a){return v((a.parentNode||{}).firstChild,a)},children:function(a){return v(a.firstChild)},contents:function(a){return n.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(E[a]||(e=n.uniqueSort(e)),D.test(a)&&(e=e.reverse())),this.pushStack(e)}});var G=/\S+/g;function H(a){var b={};return n.each(a.match(G)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?H(a):n.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h-1)f.splice(c,1),h>=c&&h--}),this},has:function(a){return a?n.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=!0,c||j.disable(),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().progress(c.notify).done(c.resolve).fail(c.reject):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=e.call(arguments),d=c.length,f=1!==d||a&&n.isFunction(a.promise)?d:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?e.call(arguments):d,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(d>1)for(i=new Array(d),j=new Array(d),k=new Array(d);d>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().progress(h(b,j,i)).done(h(b,k,c)).fail(g.reject):--f;return f||g.resolveWith(k,c),g.promise()}});var I;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(I.resolveWith(d,[n]),n.fn.triggerHandler&&(n(d).triggerHandler("ready"),n(d).off("ready"))))}});function J(){d.addEventListener?(d.removeEventListener("DOMContentLoaded",K),a.removeEventListener("load",K)):(d.detachEvent("onreadystatechange",K),a.detachEvent("onload",K))}function K(){(d.addEventListener||"load"===a.event.type||"complete"===d.readyState)&&(J(),n.ready())}n.ready.promise=function(b){if(!I)if(I=n.Deferred(),"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll)a.setTimeout(n.ready);else if(d.addEventListener)d.addEventListener("DOMContentLoaded",K),a.addEventListener("load",K);else{d.attachEvent("onreadystatechange",K),a.attachEvent("onload",K);var c=!1;try{c=null==a.frameElement&&d.documentElement}catch(e){}c&&c.doScroll&&!function f(){if(!n.isReady){try{c.doScroll("left")}catch(b){return a.setTimeout(f,50)}J(),n.ready()}}()}return I.promise(b)},n.ready.promise();var L;for(L in n(l))break;l.ownFirst="0"===L,l.inlineBlockNeedsLayout=!1,n(function(){var a,b,c,e;c=d.getElementsByTagName("body")[0],c&&c.style&&(b=d.createElement("div"),e=d.createElement("div"),e.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(e).appendChild(b),"undefined"!=typeof b.style.zoom&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",l.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(e))}),function(){var a=d.createElement("div");l.deleteExpando=!0;try{delete a.test}catch(b){l.deleteExpando=!1}a=null}();var M=function(a){var b=n.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b},N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(O,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}n.data(a,b,c)}else c=void 0; +}return c}function Q(a){var b;for(b in a)if(("data"!==b||!n.isEmptyObject(a[b]))&&"toJSON"!==b)return!1;return!0}function R(a,b,d,e){if(M(a)){var f,g,h=n.expando,i=a.nodeType,j=i?n.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||n.guid++:h),j[k]||(j[k]=i?{}:{toJSON:n.noop}),"object"!=typeof b&&"function"!=typeof b||(e?j[k]=n.extend(j[k],b):j[k].data=n.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[n.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[n.camelCase(b)])):f=g,f}}function S(a,b,c){if(M(a)){var d,e,f=a.nodeType,g=f?n.cache:a,h=f?a[n.expando]:n.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){n.isArray(b)?b=b.concat(n.map(b,n.camelCase)):b in d?b=[b]:(b=n.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!Q(d):!n.isEmptyObject(d))return}(c||(delete g[h].data,Q(g[h])))&&(f?n.cleanData([a],!0):l.deleteExpando||g!=g.window?delete g[h]:g[h]=void 0)}}}n.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?n.cache[a[n.expando]]:a[n.expando],!!a&&!Q(a)},data:function(a,b,c){return R(a,b,c)},removeData:function(a,b){return S(a,b)},_data:function(a,b,c){return R(a,b,c,!0)},_removeData:function(a,b){return S(a,b,!0)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=n.data(f),1===f.nodeType&&!n._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d])));n._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){n.data(this,a)}):arguments.length>1?this.each(function(){n.data(this,a,b)}):f?P(f,a,n.data(f,a)):void 0},removeData:function(a){return this.each(function(){n.removeData(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=n._data(a,b),c&&(!d||n.isArray(c)?d=n._data(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return n._data(a,c)||n._data(a,c,{empty:n.Callbacks("once memory").add(function(){n._removeData(a,b+"queue"),n._removeData(a,c)})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthh;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},Z=/^(?:checkbox|radio)$/i,$=/<([\w:-]+)/,_=/^$|\/(?:java|ecma)script/i,aa=/^\s+/,ba="abbr|article|aside|audio|bdi|canvas|data|datalist|details|dialog|figcaption|figure|footer|header|hgroup|main|mark|meter|nav|output|picture|progress|section|summary|template|time|video";function ca(a){var b=ba.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}!function(){var a=d.createElement("div"),b=d.createDocumentFragment(),c=d.createElement("input");a.innerHTML="
a",l.leadingWhitespace=3===a.firstChild.nodeType,l.tbody=!a.getElementsByTagName("tbody").length,l.htmlSerialize=!!a.getElementsByTagName("link").length,l.html5Clone="<:nav>"!==d.createElement("nav").cloneNode(!0).outerHTML,c.type="checkbox",c.checked=!0,b.appendChild(c),l.appendChecked=c.checked,a.innerHTML="",l.noCloneChecked=!!a.cloneNode(!0).lastChild.defaultValue,b.appendChild(a),c=d.createElement("input"),c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),a.appendChild(c),l.checkClone=a.cloneNode(!0).cloneNode(!0).lastChild.checked,l.noCloneEvent=!!a.addEventListener,a[n.expando]=1,l.attributes=!a.getAttribute(n.expando)}();var da={option:[1,""],legend:[1,"
","
"],area:[1,"",""],param:[1,"",""],thead:[1,"","
"],tr:[2,"","
"],col:[2,"","
"],td:[3,"","
"],_default:l.htmlSerialize?[0,"",""]:[1,"X
","
"]};da.optgroup=da.option,da.tbody=da.tfoot=da.colgroup=da.caption=da.thead,da.th=da.td;function ea(a,b){var c,d,e=0,f="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||n.nodeName(d,b)?f.push(d):n.merge(f,ea(d,b));return void 0===b||b&&n.nodeName(a,b)?n.merge([a],f):f}function fa(a,b){for(var c,d=0;null!=(c=a[d]);d++)n._data(c,"globalEval",!b||n._data(b[d],"globalEval"))}var ga=/<|&#?\w+;/,ha=/r;r++)if(g=a[r],g||0===g)if("object"===n.type(g))n.merge(q,g.nodeType?[g]:g);else if(ga.test(g)){i=i||p.appendChild(b.createElement("div")),j=($.exec(g)||["",""])[1].toLowerCase(),m=da[j]||da._default,i.innerHTML=m[1]+n.htmlPrefilter(g)+m[2],f=m[0];while(f--)i=i.lastChild;if(!l.leadingWhitespace&&aa.test(g)&&q.push(b.createTextNode(aa.exec(g)[0])),!l.tbody){g="table"!==j||ha.test(g)?""!==m[1]||ha.test(g)?0:i:i.firstChild,f=g&&g.childNodes.length;while(f--)n.nodeName(k=g.childNodes[f],"tbody")&&!k.childNodes.length&&g.removeChild(k)}n.merge(q,i.childNodes),i.textContent="";while(i.firstChild)i.removeChild(i.firstChild);i=p.lastChild}else q.push(b.createTextNode(g));i&&p.removeChild(i),l.appendChecked||n.grep(ea(q,"input"),ia),r=0;while(g=q[r++])if(d&&n.inArray(g,d)>-1)e&&e.push(g);else if(h=n.contains(g.ownerDocument,g),i=ea(p.appendChild(g),"script"),h&&fa(i),c){f=0;while(g=i[f++])_.test(g.type||"")&&c.push(g)}return i=null,p}!function(){var b,c,e=d.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(l[b]=c in a)||(e.setAttribute(c,"t"),l[b]=e.attributes[c].expando===!1);e=null}();var ka=/^(?:input|select|textarea)$/i,la=/^key/,ma=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,na=/^(?:focusinfocus|focusoutblur)$/,oa=/^([^.]*)(?:\.(.+)|)/;function pa(){return!0}function qa(){return!1}function ra(){try{return d.activeElement}catch(a){}}function sa(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)sa(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=qa;else if(!e)return a;return 1===f&&(g=e,e=function(a){return n().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=n.guid++)),a.each(function(){n.event.add(this,b,e,d,c)})}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=n.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return"undefined"==typeof n||a&&n.event.triggered===a.type?void 0:n.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(G)||[""],h=b.length;while(h--)f=oa.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=n.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=n.event.special[o]||{},l=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},i),(m=g[o])||(m=g[o]=[],m.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,l):m.push(l),n.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n.hasData(a)&&n._data(a);if(r&&(k=r.events)){b=(b||"").match(G)||[""],j=b.length;while(j--)if(h=oa.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=m.length;while(f--)g=m[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(m.splice(f,1),g.selector&&m.delegateCount--,l.remove&&l.remove.call(a,g));i&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(k)&&(delete r.handle,n._removeData(a,"events"))}},trigger:function(b,c,e,f){var g,h,i,j,l,m,o,p=[e||d],q=k.call(b,"type")?b.type:b,r=k.call(b,"namespace")?b.namespace.split("."):[];if(i=m=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!na.test(q+n.event.triggered)&&(q.indexOf(".")>-1&&(r=q.split("."),q=r.shift(),r.sort()),h=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=f?2:3,b.namespace=r.join("."),b.rnamespace=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=e),c=null==c?[b]:n.makeArray(c,[b]),l=n.event.special[q]||{},f||!l.trigger||l.trigger.apply(e,c)!==!1)){if(!f&&!l.noBubble&&!n.isWindow(e)){for(j=l.delegateType||q,na.test(j+q)||(i=i.parentNode);i;i=i.parentNode)p.push(i),m=i;m===(e.ownerDocument||d)&&p.push(m.defaultView||m.parentWindow||a)}o=0;while((i=p[o++])&&!b.isPropagationStopped())b.type=o>1?j:l.bindType||q,g=(n._data(i,"events")||{})[b.type]&&n._data(i,"handle"),g&&g.apply(i,c),g=h&&i[h],g&&g.apply&&M(i)&&(b.result=g.apply(i,c),b.result===!1&&b.preventDefault());if(b.type=q,!f&&!b.isDefaultPrevented()&&(!l._default||l._default.apply(p.pop(),c)===!1)&&M(e)&&h&&e[q]&&!n.isWindow(e)){m=e[h],m&&(e[h]=null),n.event.triggered=q;try{e[q]()}catch(s){}n.event.triggered=void 0,m&&(e[h]=m)}return b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,d,f,g,h=[],i=e.call(arguments),j=(n._data(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())a.rnamespace&&!a.rnamespace.test(g.namespace)||(a.handleObj=g,a.data=g.data,d=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==d&&(a.result=d)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&("click"!==a.type||isNaN(a.button)||a.button<1))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>-1:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h]","i"),va=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,wa=/\s*$/g,Aa=ca(d),Ba=Aa.appendChild(d.createElement("div"));function Ca(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function Da(a){return a.type=(null!==n.find.attr(a,"type"))+"/"+a.type,a}function Ea(a){var b=ya.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Fa(a,b){if(1===b.nodeType&&n.hasData(a)){var c,d,e,f=n._data(a),g=n._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)n.event.add(b,c,h[c][d])}g.data&&(g.data=n.extend({},g.data))}}function Ga(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!l.noCloneEvent&&b[n.expando]){e=n._data(b);for(d in e.events)n.removeEvent(b,d,e.handle);b.removeAttribute(n.expando)}"script"===c&&b.text!==a.text?(Da(b).text=a.text,Ea(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),l.html5Clone&&a.innerHTML&&!n.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&Z.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:"input"!==c&&"textarea"!==c||(b.defaultValue=a.defaultValue)}}function Ha(a,b,c,d){b=f.apply([],b);var e,g,h,i,j,k,m=0,o=a.length,p=o-1,q=b[0],r=n.isFunction(q);if(r||o>1&&"string"==typeof q&&!l.checkClone&&xa.test(q))return a.each(function(e){var f=a.eq(e);r&&(b[0]=q.call(this,e,f.html())),Ha(f,b,c,d)});if(o&&(k=ja(b,a[0].ownerDocument,!1,a,d),e=k.firstChild,1===k.childNodes.length&&(k=e),e||d)){for(i=n.map(ea(k,"script"),Da),h=i.length;o>m;m++)g=k,m!==p&&(g=n.clone(g,!0,!0),h&&n.merge(i,ea(g,"script"))),c.call(a[m],g,m);if(h)for(j=i[i.length-1].ownerDocument,n.map(i,Ea),m=0;h>m;m++)g=i[m],_.test(g.type||"")&&!n._data(g,"globalEval")&&n.contains(j,g)&&(g.src?n._evalUrl&&n._evalUrl(g.src):n.globalEval((g.text||g.textContent||g.innerHTML||"").replace(za,"")));k=e=null}return a}function Ia(a,b,c){for(var d,e=b?n.filter(b,a):a,f=0;null!=(d=e[f]);f++)c||1!==d.nodeType||n.cleanData(ea(d)),d.parentNode&&(c&&n.contains(d.ownerDocument,d)&&fa(ea(d,"script")),d.parentNode.removeChild(d));return a}n.extend({htmlPrefilter:function(a){return a.replace(va,"<$1>")},clone:function(a,b,c){var d,e,f,g,h,i=n.contains(a.ownerDocument,a);if(l.html5Clone||n.isXMLDoc(a)||!ua.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(Ba.innerHTML=a.outerHTML,Ba.removeChild(f=Ba.firstChild)),!(l.noCloneEvent&&l.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(d=ea(f),h=ea(a),g=0;null!=(e=h[g]);++g)d[g]&&Ga(e,d[g]);if(b)if(c)for(h=h||ea(a),d=d||ea(f),g=0;null!=(e=h[g]);g++)Fa(e,d[g]);else Fa(a,f);return d=ea(f,"script"),d.length>0&&fa(d,!i&&ea(a,"script")),d=h=e=null,f},cleanData:function(a,b){for(var d,e,f,g,h=0,i=n.expando,j=n.cache,k=l.attributes,m=n.event.special;null!=(d=a[h]);h++)if((b||M(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)m[e]?n.event.remove(d,e):n.removeEvent(d,e,g.handle);j[f]&&(delete j[f],k||"undefined"==typeof d.removeAttribute?d[i]=void 0:d.removeAttribute(i),c.push(f))}}}),n.fn.extend({domManip:Ha,detach:function(a){return Ia(this,a,!0)},remove:function(a){return Ia(this,a)},text:function(a){return Y(this,function(a){return void 0===a?n.text(this):this.empty().append((this[0]&&this[0].ownerDocument||d).createTextNode(a))},null,a,arguments.length)},append:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.appendChild(a)}})},prepend:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&n.cleanData(ea(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&n.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return Y(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(ta,""):void 0;if("string"==typeof a&&!wa.test(a)&&(l.htmlSerialize||!ua.test(a))&&(l.leadingWhitespace||!aa.test(a))&&!da[($.exec(a)||["",""])[1].toLowerCase()]){a=n.htmlPrefilter(a);try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(ea(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=[];return Ha(this,arguments,function(b){var c=this.parentNode;n.inArray(this,a)<0&&(n.cleanData(ea(this)),c&&c.replaceChild(b,this))},a)}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=0,e=[],f=n(a),h=f.length-1;h>=d;d++)c=d===h?this:this.clone(!0),n(f[d])[b](c),g.apply(e,c.get());return this.pushStack(e)}});var Ja,Ka={HTML:"block",BODY:"block"};function La(a,b){var c=n(b.createElement(a)).appendTo(b.body),d=n.css(c[0],"display");return c.detach(),d}function Ma(a){var b=d,c=Ka[a];return c||(c=La(a,b),"none"!==c&&c||(Ja=(Ja||n("\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; +} +elsif ($FORM{action} eq "deletemail") { + if (-f $FORM{file}) { + my %userdomains; + open (my $IN,"<","/etc/userdomains"); + flock ($IN, LOCK_SH); + my @localusers = <$IN>; + close ($IN); + chomp @localusers; + foreach my $line (@localusers) { + my ($domain,$user) = split(/\: /,$line,2); + $userdomains{$domain} = $user; + } + my ($file, $filedir) = fileparse($FORM{file}); + my $homedir = ( getpwnam($userdomains{$FORM{domain}}) )[7]; + if ($homedir eq "" or $filedir !~ /^$homedir/) { + print "Invalid file [$FORM{file}]"; + } else { + print "
\n"; + print ""; + unlink $FORM{file}; + my ($file, $filedir) = fileparse($FORM{file}); + if (-e "$filedir/../maildirsize") {unlink "$filedir/../maildirsize"} + print "\n"; + print "
Delete Email
Email deleted
\n"; + } + } else { + print "File [$FORM{file}] not found"; + } +} +elsif ($FORM{action} eq "emptydir") { + if (-d $FORM{file}) { + my %userdomains; + open (my $IN,"<","/etc/userdomains"); + flock ($IN, LOCK_SH); + my @localusers = <$IN>; + close ($IN); + chomp @localusers; + chomp @localusers; + foreach my $line (@localusers) { + my ($domain,$user) = split(/\: /,$line,2); + $userdomains{$domain} = $user; + } + my ($file, $filedir) = fileparse($FORM{file}); + my $homedir = ( getpwnam($userdomains{$FORM{domain}}) )[7]; + if ($homedir eq "" or $filedir !~ /^$homedir/) { + print "Invalid directory [$FORM{file}]"; + } else { + my $total = 0; + print "\n"; + print ""; + print "\n"; + print "\n"; + print "
Empty Directory [$FORM{file}]
"; + opendir (my $DIR, $FORM{file}); + while (my $file = readdir($DIR)) { + if (readlink "$FORM{file}/$file") {next} + if ((-f "$FORM{file}/$file") and ($file =~ /^\d+\./)) { + print ". "; + unlink ("$FORM{file}/$file"); + $total++; + } + } + if (-e "$FORM{file}/../maildirsize") {unlink "$FORM{file}/../maildirsize"} + closedir ($DIR); + print "

Total emails removed: $total

Directory emptied
\n"; + } + } else { + print "Directory [$FORM{file}] not found"; + } +} +elsif ($FORM{action} eq "salearn") { + if (-d $FORM{file}) { + my %userdomains; + open (my $IN,"<","/etc/userdomains"); + flock ($IN, LOCK_SH); + my @localusers = <$IN>; + close ($IN); + chomp @localusers; + foreach my $line (@localusers) { + my ($domain,$user) = split(/\: /,$line,2); + $userdomains{$domain} = $user; + } + my ($file, $filedir) = fileparse($FORM{file}); + my $homedir = ( getpwnam($userdomains{$FORM{domain}}) )[7]; + if ($homedir eq "" or $filedir !~ /^$homedir/) { + print "Invalid file [$FORM{file}]"; + } else { + $| = 1; ## no critic + print "\n"; + print ""; + print "\n"; + print "
Running sa-learn for spam against [$FORM{file}]

This may take some time depending on the number of emails and the speed of SpamAssassin:

\n
\n\# /usr/local/cpanel/3rdparty/bin/sa-learn --spam --showdots $FORM{file}\n";
+			my ($childin, $childout);
+			my $cmdpid = open3($childin, $childout, $childout, "/usr/local/cpanel/3rdparty/bin/sa-learn", "--spam", "--showdots", $FORM{file});
+			while (<$childout>) {print $_}
+			waitpid ($cmdpid, 0);
+			print "
\n
\n"; + print "\n"; + } + } else { + print "File [$FORM{file}] not found"; + } +} +elsif ($FORM{action} eq "bulkdelete") { + my $total = 0; + my $anyfile; + my %userdomains; + open (my $IN,"<","/etc/userdomains"); + flock ($IN, LOCK_SH); + my @localusers = <$IN>; + close ($IN); + chomp @localusers; + foreach my $line (@localusers) { + my ($domain,$user) = split(/\: /,$line,2); + $userdomains{$domain} = $user; + } + print "\n"; + print ""; + print "\n"; + print "
Delete Selected Mails
"; + for ($x = 1; $x <= $FORM{total} ;$x++) { + my $delfile = $FORM{"cmmdel_$x"}; + if (-f $delfile) { + my ($file, $filedir) = fileparse($delfile); + my $homedir = ( getpwnam($userdomains{$FORM{domain}}) )[7]; + if ($homedir eq "" or $filedir !~ /^$homedir/) { + print "Invalid file [$delfile]"; + } else { + unlink ($delfile); + $total++; + $anyfile = $delfile; + } + } + } + my ($file, $filedir) = fileparse($anyfile); + if (-d $filedir) { + my $homedir = ( getpwnam($userdomains{$FORM{domain}}) )[7]; + if ($homedir eq "" or $filedir !~ /^$homedir/) { + print "Invalid directory [$filedir]"; + } else { + if (-e "$filedir/../maildirsize") {unlink "$filedir/../maildirsize"} + } + } + print "

Total emails removed: $total

\n"; + print "

\n"; +} +elsif ($FORM{action} eq "changequota") { + my %userdomains; + open (my $IN,"<","/etc/userdomains"); + flock ($IN, LOCK_SH); + my @localusers = <$IN>; + close ($IN); + chomp @localusers; + foreach my $line (@localusers) { + my ($domain,$user) = split(/\: /,$line,2); + $userdomains{$domain} = $user; + } + + if (($FORM{quota} =~ /[^\d\.]/) or ($FORM{quota} == 0)) {$FORM{quota} = "unlimited"} + + print "\n"; + print ""; + print "\n"; + + print "
Change Quota for $FORM{account}\@$FORM{domain}
"; + eval { + local $) = local $(; ## no critic + local $> = local $<; ## no critic + local $ENV{'REMOTE_USER'} = $user; + &drop($userdomains{$FORM{domain}}); + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, "/usr/local/cpanel/cpanel-email", "editquota", $FORM{account}, $FORM{domain}, $FORM{quota}); + my @data = <$childout>; + waitpid ($cmdpid, 0); + chomp @data; + my $cnt = 0; + foreach my $line (@data) { + if ($line =~ /^stdin: is not a tty/) {next} + if ($line =~ /^[\r\n]/) {next} + if ($line =~ /^
/) {next} + print "
$line
\n"; + $cnt++; + } + unless ($cnt) {print "

Quota changed to $FORM{quota} MB

\n"} + }; + print "
\n"; + print "

\n"; +} +elsif ($FORM{action} eq "password") { + print "
\n"; + print "\n"; + print ""; + print "\n"; + print "\n"; + print "\n"; + print "
Change Password for $FORM{account}\@$FORM{domain}
New password
Confirm password
\n"; + print "
\n"; + print "

\n"; +} +elsif ($FORM{action} eq "Change Password") { + my %userdomains; + open (my $IN,"<","/etc/userdomains"); + flock ($IN, LOCK_SH); + my @localusers = <$IN>; + close ($IN); + chomp @localusers; + foreach my $line (@localusers) { + my ($domain,$user) = split(/\: /,$line,2); + $userdomains{$domain} = $user; + } + + print "\n"; + print ""; + if ($FORM{password} eq "") { + print "\n"; + } + elsif ($FORM{password} ne $FORM{confirmpassword}) { + print "\n"; + } + elsif ($FORM{password} =~ /\"/) { + print "\n"; + } + else { + print "
Change Password for $FORM{account}\@$FORM{domain}
Failed: Empty password field
Failed: Passwords do not match
Failed: password must not contain quotes
\n"; + eval { + local $) = local $(; ## no critic + local $> = local $<; ## no critic + local $ENV{'REMOTE_USER'} = $user; + &drop($userdomains{$FORM{domain}}); + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, "/usr/local/cpanel/cpanel-email", "passwdpop", $FORM{account}, "$FORM{password}", "0", $FORM{domain}); + my @data = <$childout>; + waitpid ($cmdpid, 0); + chomp @data; + my $cnt = 0; + foreach my $line (@data) { + if ($line =~ /^stdin: is not a tty/) {next} + print "
$line
\n"; + $cnt++; + } + unless ($cnt) {print "

Password changed

\n"} + }; + } + print "
\n"; + print "

\n"; +} +elsif ($FORM{action} eq "delete") { + print "
\n"; + print "\n"; + print ""; + print "\n"; + print "\n"; + print "
Delete Mailbox $FORM{account}\@$FORM{domain}
Are you sure that you want to irretrievably delete all email and associated files within this mailbox?
\n"; + print "
\n"; + print "

\n"; +} +elsif ($FORM{action} eq "Delete Mailbox") { + my %userdomains; + open (my $IN,"<","/etc/userdomains"); + flock ($IN, LOCK_SH); + my @localusers = <$IN>; + close ($IN); + chomp @localusers; + foreach my $line (@localusers) { + my ($domain,$user) = split(/\: /,$line,2); + $userdomains{$domain} = $user; + } + + print "\n"; + print ""; + print "
Delete Mailbox $FORM{account}\@$FORM{domain}
\n"; + eval { + local $) = local $(; ## no critic + local $> = local $<; ## no critic + local $ENV{'REMOTE_USER'} = $user; + &drop($userdomains{$FORM{domain}}); + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, "/usr/local/cpanel/cpanel-email", "delpop", $FORM{account}, "0", $FORM{domain}); + my @data = <$childout>; + waitpid ($cmdpid, 0); + chomp @data; + my $cnt = 0; + foreach my $line (@data) { + if ($line =~ /^stdin: is not a tty/) {next} + print "
$line
\n"; + $cnt++; + } + print "

Account deleted

\n"; + }; + print "
\n"; + print "

\n"; +} +elsif ($FORM{action} eq "Add Mailbox") { + my %userdomains; + open (my $IN,"<","/etc/userdomains"); + flock ($IN, LOCK_SH); + my @localusers = <$IN>; + close ($IN); + chomp @localusers; + foreach my $line (@localusers) { + my ($domain,$user) = split(/\: /,$line,2); + $userdomains{$domain} = $user; + } + + if (($FORM{quota} =~ /[^\d\.]/) or ($FORM{quota} == 0)) {$FORM{quota} = "unlimited"} + + print "\n"; + print ""; + if ($FORM{password} eq "") { + print "\n"; + } + elsif ($FORM{password} ne $FORM{confirmpassword}) { + print "\n"; + } + elsif ($FORM{password} =~ /\"/) { + print "\n"; + } + else { + print "\n"; + } + print "
Add Mailbox $FORM{account}\@$FORM{domain}
Failed: Empty password field
Failed: Passwords do not match
Failed: password must not contain quotes
\n"; + eval { + local $) = local $(; ## no critic + local $> = local $<; ## no critic + local $ENV{'REMOTE_USER'} = $user; + &drop($userdomains{$FORM{domain}}); + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, "/usr/local/cpanel/cpanel-email", "addpop", $FORM{account}, "$FORM{password}", $FORM{quota}, $FORM{domain}); + my @data = <$childout>; + waitpid ($cmdpid, 0); + chomp @data; + my $cnt = 0; + foreach my $line (@data) { + if ($line =~ /^stdin: is not a tty/) {next} + print "
$line
\n"; + $cnt++; + } + print "

Account created

\n"; + }; + print "
\n"; + print "

\n"; +} +elsif (($FORM{action} =~ /^Mail Quota Report \((.*)\)/) or ($FORM{action} eq "Manage Mail Accounts")) { + my $report = $1; + my $total = 0; + my $colspan = 5; + my $extracol = " "; + my ($tot_accounts, $tot_mails, $tot_space); + + if ($FORM{action} eq "Manage Mail Accounts") { + $FORM{dospace} = 0; + $FORM{dopercent} = 1; + $FORM{percent} = 99; + $FORM{doall} = 1; + $report = "Selected"; + $colspan = 5; + $extracol = "Action"; + print "

    

\n"; + } + + print "\n"; + print ""; + print "$extracol"; + + my @users; + my %userdomains; + open (my $IN,"<","/etc/userdomains"); + flock ($IN, LOCK_SH); + my @localusers = <$IN>; + close ($IN); + chomp @localusers; + foreach my $line (@localusers) { + my ($domain,$user) = split(/\: /,$line,2); + $userdomains{$domain} = $user; + } + + my @domains; + if ($report eq "Selected") { + push @domains, $FORM{domain}; + } else { + open (my $IN,"<","/etc/userdomains"); + flock ($IN, LOCK_SH); + while (my $entry = <$IN>) { + chomp $entry; + my ($domain,$user) = split(/:\s*/,$entry); + if ($user eq "nobody") {next} + push @domains, $domain; + } + close ($IN); + @domains = sort @domains; + } + + foreach my $domain (@domains) { + unless ($domain) {next} + if ($domain =~ /^\#/) {next} + my $homedir = ( getpwnam($userdomains{$domain}) )[7]; + unless (-e "$homedir/etc/$domain/passwd") {next} +# unless (-e "$homedir/etc/$domain/quota") {next} + + my @accounts; + open (my $IN,"<","$homedir/etc/$domain/passwd"); + flock ($IN, LOCK_SH); + my @localusers = <$IN>; + close ($IN); + chomp @localusers; + foreach my $line (@localusers) { + ($user,undef) = split(/\:/,$line,2); + if ($user) {push @accounts,$user} + } + @accounts = sort @accounts; + unshift @accounts,$userdomains{$domain}; + + open (my $QUOTA,"<","$homedir/etc/$domain/quota"); + flock ($QUOTA, LOCK_SH); + my @localquota = <$QUOTA>; + close ($QUOTA); + chomp @localquota; + + my %quotas; + foreach my $line (@localquota) { + my ($user,$quota) = split(/\:/,$line,2); + $quotas{$user} = $quota; + } + + my $first = 1; + my $lines = 0; + foreach my $key (@accounts) { + my $dir; + my $topdomain = "\@$domain"; + my $account = "${key}\@${domain}"; + my $quota = $quotas{$key}; + my $used = 0; + my $files = 0; + my $mdbox = 0; + + if ($first == -1) {$first = 0} + if ($first) { + $first = -1; + open (my $IN,"<","/var/cpanel/users/$userdomains{$domain}"); + my @userdata = <$IN>; + close ($IN); + chomp @userdata; + my $maindomain; + foreach my $line (@userdata) { + if ($line =~ /^DNS=(.*)/) {$maindomain = $1} + } + if ($maindomain ne $domain) {next} + $dir = "$homedir/mail"; + $topdomain = " ($domain cPanel user)"; + $account = "${key}"; + $quota = 0; + } else { + $dir = "$homedir/mail/$domain/$key"; + } + + if (-e "$dir/storage") { + $mdbox = 1; + $topdomain .= " mdbox"; + + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, "/usr/bin/doveadm", "mailbox", "status", "-u", "$account", "-t", "messages vsize", "*"); + my @data = <$childout>; + waitpid ($cmdpid, 0); + chomp @data; + if ($data[0] =~ /messages=(\d+)/) {$files = $1} + if ($data[0] =~ /vsize=(\d+)/) {$used = $1} + } else { + my @maildirs; + push @maildirs, $dir; + opendir (my $DIR, $dir); + while (my $file = readdir($DIR)) { + if ($file eq ".") {next} + if ($file eq "..") {next} + if (readlink "$dir/$file") {next} + if ((-d "$dir/$file") and (-d "$dir/$file/cur") and (-d "$dir/$file/new") and (-d "$dir/$file/tmp")) {push @maildirs, "$dir/$file"} + } + closedir ($DIR); + if (-e "$dir/storage") { + $mdbox = 1; + } else { + foreach my $line (@maildirs) { + foreach my $subdir ("/","/cur","/new","/tmp") { + opendir (my $DIR, "$line$subdir"); + while (my $file = readdir($DIR)) { + if ((-f "$line$subdir/$file") and ($file =~ /^\d+\./)) { + $used += (stat("$line$subdir/$file"))[7]; + $files++; + } + } + closedir ($DIR); + } + } + } + } + + my $uclass = ""; + if (($FORM{dospace}) and ($used > $FORM{space} * 1024 * 1024)) {$uclass = "warning"} + if (($FORM{dopercent}) and (($used >= $quota) or ($used / $quota >= ($FORM{percent} / 100))) and ($quota > 0)) {$uclass = "danger"} + + unless ($FORM{doall}) { + if ($uclass eq "") {next} + if ($uclass eq "") {next} + } + my $uquota = 0; + if ($quota > 0) {$uquota = int(($used / $quota) * 100)} + + $used = $used / (1024 * 1024); + + my $tused = $used; + $used = sprintf("%.02f",$used); + + $used .= " ($uquota\%)"; + + if ($quota < 1) { + $quota = "unlimited"; + } else { + $quota = int($quota / (1024 * 1024)); + } + + if ($FORM{action} eq "Manage Mail Accounts") { + $tot_accounts++; + $tot_mails+=$files; + $tot_space+=$tused; + print "\n"; + } else { + print "\n"; + } + if ($class eq "tdshade2_noborder") {$class = "tdshade1_noborder"} else {$class = "tdshade2_noborder"} + $total++; + $lines++; + } + my $info = ""; + $tot_space = sprintf("%.02f",$tot_space); + if ($FORM{action} eq "Manage Mail Accounts") {$info = ""} + if ($FORM{doall} and $lines) {print "$info\n"} + } + print "
Mail Account Quotas
AccountMailsUsed (MB)Quota (MB)
$key$topdomain$files$used"; + if ($first == -1) { + print "$quota"; + if ($files > 0 and !$mdbox) { + print " "; + print " "; + } + } else { + print ""; + print " "; + if ($files > 0 and !$mdbox) { + print " "; + print " "; + } else {print "";} + print " "; + } + print "
$key$topdomain$files$used$quota\n"; + print "
 $tot_accounts account(s)$tot_mails$tot_space 
\n"; + if ($FORM{action} eq "Manage Mail Accounts") { + print "
\n"; + print "\n"; + print "\n"; + print ""; + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, "/usr/bin/quota", "-qlu", $userdomains{$FORM{domain}}); + my @data = <$childout>; + waitpid ($cmdpid, 0); + chomp @data; + if ($data[0] =~ /Block limit reached/) { + print "\n"; + } else { + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + } + print "
Add Mailbox

cPanel account over quota - add mailbox disabled

Account\@$FORM{domain}
Password
Confirm
QuotaMB
\n"; + + print "
\n"; + print ""; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + if ($mailscanner) {print "\n"} + print "
Button Key
Change mailbox quota
Change mailbox password
View mailbox contents
Empty mailbox/Directory
Delete mailbox/Mail
sa-learn spam Directory
\n"; + print "
\n"; + } + print "
Total Accounts: $total
\n"; + print "
mdbox - Mailboxes using the cPanel v11.58+ mdbox format have limited support in this script
\n"; + print "

\n"; +} +elsif ($FORM{action} eq "Bulk Enable GreyListing") { + require Cpanel::GreyList::Client; + + print "\n"; + print "\n"; + print "
Enabled GreyListing on all domains
\n"; + my @localdomains; + open (my $IN,"<","/etc/userdomains"); + flock ($IN, LOCK_SH); + while (my $entry = <$IN>) { + chomp $entry; + my ($domain,$user) = split(/:\s*/,$entry); + if ($user eq "nobody") {next} + if ($domain eq "") {next} + if ($domain eq "*") {next} + push @localdomains, $domain; + } + close($IN); + my $client = Cpanel::GreyList::Client->new(); + $client->disable_opt_out_for_domains(\@localdomains); + print "

\n"; +} +elsif ($FORM{action} eq "Bulk Show GreyListing") { + require Cpanel::GreyList::Client; + + print "\n"; + my @localdomains; + open (my $IN,"<","/etc/userdomains"); + flock ($IN, LOCK_SH); + my @entries = <$IN>; + close ($IN); + chomp @entries; + foreach my $entry (sort @entries) { + chomp $entry; + my ($domain,$user) = split(/:\s*/,$entry); + if ($user eq "nobody") {next} + if ($domain eq "") {next} + if ($domain eq "*") {next} + my $client = Cpanel::GreyList::Client->new(); + if ($client->is_greylisting_enabled($domain)) { + print "\n"; + } else { + print "\n"; + } + } + print "
GreyListing is enabled for $domain
GreyListing is disabled for $domain
\n"; + print "

\n"; +} +elsif ($FORM{action} eq "Bulk Disable GreyListing") { + require Cpanel::GreyList::Client; + + print "\n"; + print "\n"; + print "
Disabled GreyListing on all domains
\n"; + my @localdomains; + open (my $IN,"<","/etc/userdomains"); + flock ($IN, LOCK_SH); + while (my $entry = <$IN>) { + chomp $entry; + my ($domain,$user) = split(/:\s*/,$entry); + if ($user eq "nobody") {next} + if ($domain eq "") {next} + if ($domain eq "*") {next} + push @localdomains, $domain; + } + close ($IN); + my $client = Cpanel::GreyList::Client->new(); + $client->enable_opt_out_for_domains(\@localdomains); + print "

\n"; +} +elsif ($FORM{action} eq "Show GreyListing") { + unless ($FORM{domain}) { + print "

You must select a domain!

\n"; + } else { + require Cpanel::GreyList::Client; + + print "\n"; + my $client = Cpanel::GreyList::Client->new(); + if ($client->is_greylisting_enabled($FORM{domain})) { + print "\n"; + } else { + print "\n"; + } + print "
GreyListing is enabled for $FORM{domain}
GreyListing is disabled for $FORM{domain}
\n"; + } + print "

\n"; +} +elsif ($FORM{action} eq "Enable GreyListing") { + unless ($FORM{domain}) { + print "

You must select a domain!

\n"; + } else { + require Cpanel::GreyList::Client; + + print "\n"; + print "\n"; + print "
Enabled GreyListing on $FORM{domain}
\n"; + my @domains; + my $client = Cpanel::GreyList::Client->new(); + @domains = ($FORM{domain}); + $client->disable_opt_out_for_domains(\@domains); + } + print "

\n"; +} +elsif ($FORM{action} eq "Disable GreyListing") { + unless ($FORM{domain}) { + print "

You must select a domain!

\n"; + } else { + require Cpanel::GreyList::Client; + + print "\n"; + print "\n"; + print "
Disabled GreyListing on $FORM{domain}
\n"; + my @domains; + my $client = Cpanel::GreyList::Client->new(); + @domains = ($FORM{domain}); + $client->enable_opt_out_for_domains(\@domains); + } + print "

\n"; +} +elsif ($FORM{action} eq "upgrade") { + $| = 1; ## no critic + + print "
";
+
+	if (-e "/usr/src/cmm.tgz") {unlink ("/usr/src/cmm.tgz") or die $!}
+	print "Retrieving new cmm package...\n";
+
+	my ($status, $text) = &urlget("https://$downloadserver/cmm.tgz","/usr/src/cmm.tgz");
+	if ($status) {print "Oops: $text\n"}
+
+	if (! -z "/usr/src/cmm.tgz") {
+		print "Unpacking new cmm package...\n";
+		print "
";
+		&printcmd("cd /usr/src ; tar -xzf cmm.tgz ; cd cmm ; sh install.sh 2>&1");
+		print "
"; + print "Tidying up...\n"; + print "
";
+		&printcmd("rm -Rfv /usr/src/cmm*");
+		print "
"; + print "...All done.\n"; + } + print "
"; + + open (my $IN, "<",$versionfile) or die $!; + flock ($IN, LOCK_SH); + $myv = <$IN>; + close ($IN); + chomp $myv; + + print "

\n"; +} +else { + open (my $IN, "<","/etc/userdomains"); + flock ($IN, LOCK_SH); + while (my $entry = <$IN>) { + chomp $entry; + my ($domain,$user) = split(/:\s*/,$entry); + if ($user eq "nobody") {next} + push @localdomains, $domain; + } + close ($IN); + @localdomains = sort @localdomains; + + my $domainlist; + my $domaincnt; + foreach my $domain (@localdomains) { + $domainlist .= "\n"; + $domaincnt ++; + } + + print "
\n"; + print "\n"; + print ""; + print "\n"; + + print ""; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + + print "
Mail Manage
\n"; + print "

\n"; + print "

\n"; + print "

\n"; + print "

\n"; + if (-e "/var/cpanel/greylist/enabled") { + print "

\n"; + print "

\n"; + print "

WARNING: If you disable GreyListing on a main domain cPanel forces all subdomains to be disabled until the main domain is enabled

\n"; + } + print "

Mail Domains: $domaincnt

\n"; + print "
Mail Reports
\n"; + print " Identify accounts using over MB of mailbox space
\n"; + print " Identify accounts using within or over % of the mailbox quota
\n"; + print " Show all accounts\n"; + print "

Note: These reports may take some time to run

View email account usage for the domain selected above
View email account usage for all domains
 
\n"; + print "
mdbox - Mailboxes using the cPanel v11.58+ mdbox format have limited support in this script
\n"; + + if (-e "/var/cpanel/greylist/enabled") { + print "\n"; + print ""; + print "\n"; + print "\n"; + print "\n"; + print "
GreyListing
Display GreyListing for all domains
Configure GreyListing so that all domains are enabled
Configure GreyListing so that all domains are disabled
\n"; + print "

WARNING: Using GreyListing can and will lead to lost legitimate emails. It can also cause significant problems with Password Verification systems. See this article for more information

\n"; + } + + my $retry = 0; + my $retrytime = 300; + print "\n"; + print ""; + if (-e "/usr/local/cpanel/whostmgr/docroot/cgi/cmmnocheck") { + open (my $IN, "<", "/usr/local/cpanel/whostmgr/docroot/cgi/cmmnocheck"); + flock ($IN, LOCK_SH); + my $time = <$IN>; + close ($IN); + chomp $time; + $retry = time - $time; + if ($retry > $retrytime) {unlink ("/usr/local/cpanel/whostmgr/docroot/cgi/cmmnocheck")} + } + unless (-e "/usr/local/cpanel/whostmgr/docroot/cgi/cmmnocheck") { + my ($status, $text) = &urlget("https://$downloadserver/cmm/cmmversion.txt"); + my $actv = $text; + my $up = 0; + + if ($actv ne "") { + if ($actv =~ /^[\d\.]*$/) { + if ($actv > $myv) { + print "\n"; + } else { + print "\n"; + } + $up = 1; + } + } + unless ($up) { + sysopen (my $OUT, "/usr/local/cpanel/whostmgr/docroot/cgi/cmmnocheck", O_WRONLY | O_CREAT); + flock ($OUT, LOCK_EX); + print $OUT time; + close ($OUT); + print "\n"; + } + } else { + print "\n"; + } + + print "
Upgrade
A new version of cmm (v$actv) is available. Upgrading will retain your settings
View ChangeLog
You are running the latest version of cmm.
An Upgrade button will appear here if a new version becomes available
Unable to connect to http://www.configserver.com, retry in $retrytime seconds.
An Upgrade button will appear here if new version is detected
Unable to connect to http://www.configserver.com, retry in ".($retrytime - $retry)." seconds.
An Upgrade button will appear here if new version is detected
\n"; +} + +print "
cmm: v$myv
"; +print "

©2006-2019, ConfigServer Services (Jonathan Michaelson)

\n"; +print < + \$("#loader").hide(); + \$("#docs-link").hide(); + +EOF +unless ($FORM{action} eq "viewmail") { + close SCRIPTOUT; + select STDOUT; + Cpanel::Template::process_template( + 'whostmgr', + { + "template_file" => "${thisapp}.tmpl", + "${thisapp}_output" => $templatehtml, + "print" => 1, + } + ); +} else { + print "\n"; + print "\n"; + print "\n"; +} + +# end main +############################################################################### +# start drop +sub drop { + my $user = shift; + my (undef,undef,$uid,$gid,undef,undef,undef,$home) = getpwnam($user); + if ($> == 0) { + chdir($home); + $) = $( = $gid; ## no critic + $> = $< = $uid; ## no critic + if (($) != $gid) or ($> != $uid) or ($( != $gid) or ($< != $uid)) {print "Failed to drop privileges ($uid:$gid)\n";exit} ## no critic + $ENV{'REMOTE_USER'} = $user; ## no critic + } + return +} +# end drop +############################################################################### +sub uri_escape { + my $string = shift; + $string =~ s/([^^A-Za-z0-9\-_.!~*'()])/ sprintf "%%%0x", ord $1 /eg; + return $string; +} + +############################################################################### +# start urlget (v1.3) +# +# Examples: +#my ($status, $text) = &urlget("http://prdownloads.sourceforge.net/clamav/clamav-0.92.tar.gz","/tmp/clam.tgz"); +#if ($status) {print "Oops: $text\n"} +# +#my ($status, $text) = &urlget("http://www.configserver.com/free/msfeversion.txt"); +#if ($status) {print "Oops: $text\n"} else {print "Version: $text\n"} +# +sub urlget { + my $url = shift; + my $file = shift; + my $status = 0; + my $timeout = 1200; + local $SIG{PIPE} = 'IGNORE'; + + use LWP::UserAgent; + my $ua = LWP::UserAgent->new; + $ua->timeout(30); + my $req = HTTP::Request->new(GET => $url); + my $res; + my $text; + + ($status, $text) = eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die "Download timeout after $timeout seconds"}; + alarm($timeout); + if ($file) { + $|=1; ## no critic + my $expected_length; + my $bytes_received = 0; + my $per = 0; + my $oldper = 0; + open (my $OUT, ">", "$file\.tmp") or return (1, "Unable to open $file\.tmp: $!"); + binmode ($OUT); + print "...0\%\n"; + $res = $ua->request($req, + sub { + my($chunk, $res) = @_; + $bytes_received += length($chunk); + unless (defined $expected_length) {$expected_length = $res->content_length || 0} + if ($expected_length) { + my $per = int(100 * $bytes_received / $expected_length); + if ((int($per / 5) == $per / 5) and ($per != $oldper)) { + print "...$per\%\n"; + $oldper = $per; + } + } else { + print "."; + } + print $OUT $chunk; + }); + close ($OUT); + print "\n"; + } else { + $res = $ua->request($req); + } + alarm(0); + if ($res->is_success) { + if ($file) { + rename ("$file\.tmp","$file") or return (1, "Unable to rename $file\.tmp to $file: $!"); + return (0, $file); + } else { + return (0, $res->content); + } + } else { + return (1, "Unable to download: ".$res->message); + } + }; + alarm(0); + if ($@) { + return (1, $@); + } + if ($text) { + return ($status,$text); + } else { + return (1, "Download timeout after $timeout seconds"); + } +} +# end urlget +############################################################################### +## start printcmd +sub printcmd { + my @command = @_; + my ($childin, $childout); + my $pid = open3($childin, $childout, $childout, @command); + while (<$childout>) {print $_} + waitpid ($pid, 0); + return; +} +## end printcmd +############################################################################### +## start getdownloadserver +sub getdownloadserver { + my @servers; + my $downloadservers = "/usr/local/cpanel/whostmgr/docroot/cgi/configserver/cmm/downloadservers"; + my $chosen; + if (-e $downloadservers) { + open (my $DOWNLOAD, "<", $downloadservers); + flock ($DOWNLOAD, LOCK_SH); + my @data = <$DOWNLOAD>; + close ($DOWNLOAD); + chomp @data; + foreach my $line (@data) { + if ($line =~ /^download/) {push @servers, $line} + } +## foreach my $line (slurp($downloadservers)) { +## $line =~ s/$cleanreg//g; +## if ($line =~ /^download/) {push @servers, $line} +## } + $chosen = $servers[rand @servers]; + } + if ($chosen eq "") {$chosen = "download.configserver.com"} + return $chosen; +} +## end getdownloadserver +############################################################################### + +1; diff --git a/cmm/cmm.conf b/cmm/cmm.conf new file mode 100644 index 0000000..391655d --- /dev/null +++ b/cmm/cmm.conf @@ -0,0 +1,27 @@ +# name +name=cmm + +# Service that will serve this app +service=whostmgr + +# Physical path: /usr/local/cpanel/3rdparty/Foo.php +# Literal URL path: $server:$port/$cpsession/3rdparty/Foo.php +url=/cgi/configserver/cmm.cgi + +# System user to run process as +user=root + +# Required acls +acls=all + +# Display name as show in the service ui +displayname=ConfigServer Mail Manage + +# Url to show in the service ui (relative to install path for whm this is cgi/) +entryurl=configserver/cmm.cgi + +upgradecall=/usr/local/cpanel/whostmgr/docroot/cgi/configserver/cmm/upgrade.sh + +icon=cmm.png + +target=mainFrame diff --git a/cmm/cmm.conf.old b/cmm/cmm.conf.old new file mode 100644 index 0000000..0ee7962 --- /dev/null +++ b/cmm/cmm.conf.old @@ -0,0 +1,23 @@ +# name +name=cmm + +# Service that will serve this app +service=whostmgr + +# Physical path: /usr/local/cpanel/3rdparty/Foo.php +# Literal URL path: $server:$port/$cpsession/3rdparty/Foo.php +url=/cgi/addon_cmm.cgi + +# System user to run process as +#user=root + +# Required acls +acls=all + +# Display name as show in the service ui +displayname=ConfigServer Mail Manage + +# Url to show in the service ui (relative to install path for whm this is cgi/) +#entryurl=addon_cmm.cgi + +upgradecall=/usr/local/cpanel/whostmgr/docroot/cgi/configserver/cmm/upgrade.sh diff --git a/cmm/cmm.tmpl b/cmm/cmm.tmpl new file mode 100644 index 0000000..5dbdb78 --- /dev/null +++ b/cmm/cmm.tmpl @@ -0,0 +1,29 @@ +[% +USE Whostmgr; +USE JSON; + +WRAPPER 'master_templates/master.tmpl' + header = 'ConfigServer Mail Manage' + skipsupport = 1 + skipheader = 1 + hide_license_warnings = 1 + theme='bootstrap' + breadcrumbdata = { + previous = [ + { + name = "Home", + url = "/scripts/command?PFILE=main", + }, + { + name = "Plugins", + url = "/scripts/command?PFILE=Plugins", + } + ], + name = 'ConfigServer Mail Manage', + url = '/cgi/configserver/cmm.cgi', + }; +%] + +[% cmm_output %] + +[% END %] diff --git a/cmm/cmm/bootstrap/css/bootstrap.min.css b/cmm/cmm/bootstrap/css/bootstrap.min.css new file mode 100644 index 0000000..ed3905e --- /dev/null +++ b/cmm/cmm/bootstrap/css/bootstrap.min.css @@ -0,0 +1,6 @@ +/*! + * Bootstrap v3.3.7 (http://getbootstrap.com) + * Copyright 2011-2016 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,:after,:before{color:#000!important;text-shadow:none!important;background:0 0!important;-webkit-box-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff2) format('woff2'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\002a"}.glyphicon-plus:before{content:"\002b"}.glyphicon-eur:before,.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:focus,a:hover{color:#23527c;text-decoration:underline}a:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.carousel-inner>.item>a>img,.carousel-inner>.item>img,.img-responsive,.thumbnail a>img,.thumbnail>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;max-width:100%;height:auto;padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role=button]{cursor:pointer}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1;color:#777}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}.small,small{font-size:85%}.mark,mark{padding:.2em;background-color:#fcf8e3}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:focus,a.text-primary:hover{color:#286090}.text-success{color:#3c763d}a.text-success:focus,a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:focus,a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:focus,a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:focus,a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:focus,a.bg-primary:hover{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:focus,a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:focus,a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:focus,a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:focus,a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ol,ul{margin-top:0;margin-bottom:10px}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;margin-left:-5px;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-top:0;margin-bottom:20px}dd,dt{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[data-original-title],abbr[title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child{margin-bottom:0}blockquote .small,blockquote footer,blockquote small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote .small:before,blockquote footer:before,blockquote small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eee;border-left:0}.blockquote-reverse .small:before,.blockquote-reverse footer:before,.blockquote-reverse small:before,blockquote.pull-right .small:before,blockquote.pull-right footer:before,blockquote.pull-right small:before{content:''}.blockquote-reverse .small:after,.blockquote-reverse footer:after,.blockquote-reverse small:after,blockquote.pull-right .small:after,blockquote.pull-right footer:after,blockquote.pull-right small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{margin-right:-15px;margin-left:-15px}.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>td,.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>td,.table>thead:first-child>tr:first-child>th{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>tbody>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>thead>tr>th{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #ddd}.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*=col-]{position:static;display:table-column;float:none}table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;float:none}.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>thead>tr>td.active,.table>thead>tr>th.active{background-color:#f5f5f5}.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover{background-color:#e8e8e8}.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{background-color:#dff0d8}.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6}.table>tbody>tr.info>td,.table>tbody>tr.info>th,.table>tbody>tr>td.info,.table>tbody>tr>th.info,.table>tfoot>tr.info>td,.table>tfoot>tr.info>th,.table>tfoot>tr>td.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>thead>tr.info>th,.table>thead>tr>td.info,.table>thead>tr>th.info{background-color:#d9edf7}.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover{background-color:#c4e3f3}.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fcf8e3}.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc}.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#f2dede}.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc}.table-responsive{min-height:.01%;overflow-x:auto}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=checkbox],input[type=radio]{margin:4px 0 0;margin-top:1px\9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[type=checkbox]:focus,input[type=radio]:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control::-ms-expand{background-color:transparent;border:0}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}input[type=search]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type=date].form-control,input[type=time].form-control,input[type=datetime-local].form-control,input[type=month].form-control{line-height:34px}.input-group-sm input[type=date],.input-group-sm input[type=time],.input-group-sm input[type=datetime-local],.input-group-sm input[type=month],input[type=date].input-sm,input[type=time].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm{line-height:30px}.input-group-lg input[type=date],.input-group-lg input[type=time],.input-group-lg input[type=datetime-local],.input-group-lg input[type=month],input[type=date].input-lg,input[type=time].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg{line-height:46px}}.form-group{margin-bottom:15px}.checkbox,.radio{position:relative;display:block;margin-top:10px;margin-bottom:10px}.checkbox label,.radio label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{position:absolute;margin-top:4px\9;margin-left:-20px}.checkbox+.checkbox,.radio+.radio{margin-top:-5px}.checkbox-inline,.radio-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px}fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox].disabled,input[type=checkbox][disabled],input[type=radio].disabled,input[type=radio][disabled]{cursor:not-allowed}.checkbox-inline.disabled,.radio-inline.disabled,fieldset[disabled] .checkbox-inline,fieldset[disabled] .radio-inline{cursor:not-allowed}.checkbox.disabled label,.radio.disabled label,fieldset[disabled] .checkbox label,fieldset[disabled] .radio label{cursor:not-allowed}.form-control-static{min-height:34px;padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}select[multiple].input-sm,textarea.input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm select[multiple].form-control,.form-group-sm textarea.form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}select[multiple].input-lg,textarea.input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:46px;line-height:46px}.form-group-lg select[multiple].form-control,.form-group-lg textarea.form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.form-group-lg .form-control+.form-control-feedback,.input-group-lg+.form-control-feedback,.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.form-group-sm .form-control+.form-control-feedback,.input-group-sm+.form-control-feedback,.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .checkbox,.has-success .checkbox-inline,.has-success .control-label,.has-success .help-block,.has-success .radio,.has-success .radio-inline,.has-success.checkbox label,.has-success.checkbox-inline label,.has-success.radio label,.has-success.radio-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .checkbox,.has-warning .checkbox-inline,.has-warning .control-label,.has-warning .help-block,.has-warning .radio,.has-warning .radio-inline,.has-warning.checkbox label,.has-warning.checkbox-inline label,.has-warning.radio label,.has-warning.radio-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .checkbox,.has-error .checkbox-inline,.has-error .control-label,.has-error .help-block,.has-error .radio,.has-error .radio-inline,.has-error.checkbox label,.has-error.checkbox-inline label,.has-error.radio label,.has-error.radio-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .form-control,.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .checkbox,.form-inline .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .checkbox label,.form-inline .radio label{padding-left:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .checkbox,.form-horizontal .radio{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:11px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:none;border:1px solid transparent;border-radius:4px}.btn.active.focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn:active:focus,.btn:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.focus,.btn:focus,.btn:hover{color:#333;text-decoration:none}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none;opacity:.65}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default.focus,.btn-default:focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.btn-default:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active.focus,.btn-default.active:focus,.btn-default.active:hover,.btn-default:active.focus,.btn-default:active:focus,.btn-default:active:hover,.open>.dropdown-toggle.btn-default.focus,.open>.dropdown-toggle.btn-default:focus,.open>.dropdown-toggle.btn-default:hover{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled.focus,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled].focus,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#286090;border-color:#122b40}.btn-primary:hover{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active.focus,.btn-primary.active:focus,.btn-primary.active:hover,.btn-primary:active.focus,.btn-primary:active:focus,.btn-primary:active:hover,.open>.dropdown-toggle.btn-primary.focus,.open>.dropdown-toggle.btn-primary:focus,.open>.dropdown-toggle.btn-primary:hover{color:#fff;background-color:#204d74;border-color:#122b40}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled.focus,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled].focus,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#449d44;border-color:#255625}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active.focus,.btn-success.active:focus,.btn-success.active:hover,.btn-success:active.focus,.btn-success:active:focus,.btn-success:active:hover,.open>.dropdown-toggle.btn-success.focus,.open>.dropdown-toggle.btn-success:focus,.open>.dropdown-toggle.btn-success:hover{color:#fff;background-color:#398439;border-color:#255625}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled.focus,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled].focus,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active.focus,.btn-info.active:focus,.btn-info.active:hover,.btn-info:active.focus,.btn-info:active:focus,.btn-info:active:hover,.open>.dropdown-toggle.btn-info.focus,.open>.dropdown-toggle.btn-info:focus,.open>.dropdown-toggle.btn-info:hover{color:#fff;background-color:#269abc;border-color:#1b6d85}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled.focus,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled].focus,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning.focus,.btn-warning:focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active.focus,.btn-warning.active:focus,.btn-warning.active:hover,.btn-warning:active.focus,.btn-warning:active:focus,.btn-warning:active:hover,.open>.dropdown-toggle.btn-warning.focus,.open>.dropdown-toggle.btn-warning:focus,.open>.dropdown-toggle.btn-warning:hover{color:#fff;background-color:#d58512;border-color:#985f0d}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled.focus,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled].focus,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c9302c;border-color:#761c19}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active.focus,.btn-danger.active:focus,.btn-danger.active:hover,.btn-danger:active.focus,.btn-danger:active:focus,.btn-danger:active:hover,.open>.dropdown-toggle.btn-danger.focus,.open>.dropdown-toggle.btn-danger:focus,.open>.dropdown-toggle.btn-danger:hover{color:#fff;background-color:#ac2925;border-color:#761c19}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled.focus,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled].focus,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#337ab7;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#777;text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-group-sm>.btn,.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-xs>.btn,.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:height,visibility;-o-transition-property:height,visibility;transition-property:height,visibility}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid\9;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown,.dropup{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;background-color:#337ab7;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#777}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px dashed;border-bottom:4px solid\9}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;float:left}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-left-radius:0;border-top-right-radius:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group .form-control:focus{z-index:3}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn,textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn,textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group .form-control,.input-group-addon,.input-group-btn{display:table-cell}.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn-group:not(:last-child)>.btn,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:first-child>.btn-group:not(:first-child)>.btn,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:focus,.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:focus,.nav>li.disabled>a:hover{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:focus,.nav .open>a:hover{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:focus,.nav-tabs>li.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:focus,.nav-pills>li.active>a:hover{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;-webkit-overflow-scrolling:touch;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1)}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:200px}}.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;height:50px;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1)}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .form-control,.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .checkbox label,.navbar-form .radio label{padding-left:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:focus,.navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:focus,.navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:focus,.navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:focus,.navbar-default .navbar-nav>.open>a:hover{color:#555;background-color:#e7e7e7}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:focus,.navbar-default .btn-link:hover{color:#333}.navbar-default .btn-link[disabled]:focus,.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:focus,fieldset[disabled] .navbar-default .btn-link:hover{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:focus,.navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:focus,.navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:focus,.navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:focus,.navbar-inverse .navbar-toggle:hover{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{color:#fff;background-color:#080808}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:focus,.navbar-inverse .btn-link:hover{color:#fff}.navbar-inverse .btn-link[disabled]:focus,.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:focus,fieldset[disabled] .navbar-inverse .btn-link:hover{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.42857143;color:#337ab7;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:2;color:#23527c;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:3;color:#fff;cursor:default;background-color:#337ab7;border-color:#337ab7}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:focus,.pager li>a:hover{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:focus,a.label:hover{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:focus,.label-default[href]:hover{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:focus,.label-primary[href]:hover{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:focus,.label-success[href]:hover{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:focus,.label-info[href]:hover{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:focus,.label-warning[href]:hover{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:focus,.label-danger[href]:hover{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:middle;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-group-xs>.btn .badge,.btn-xs .badge{top:0;padding:1px 5px}a.badge:focus,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron .h1,.jumbotron h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{padding-right:15px;padding-left:15px;border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-right:60px;padding-left:60px}.jumbotron .h1,.jumbotron h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail a>img,.thumbnail>img{margin-right:auto;margin-left:auto}a.thumbnail.active,a.thumbnail:focus,a.thumbnail:hover{border-color:#337ab7}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-bar-striped,.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress-bar.active,.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{overflow:hidden;zoom:1}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-body,.media-left,.media-right{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}a.list-group-item,button.list-group-item{color:#555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333}a.list-group-item:focus,a.list-group-item:hover,button.list-group-item:focus,button.list-group-item:hover{color:#555;text-decoration:none;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item.disabled,.list-group-item.disabled:focus,.list-group-item.disabled:hover{color:#777;cursor:not-allowed;background-color:#eee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:focus .list-group-item-text,.list-group-item.active:hover .list-group-item-text{color:#c7ddef}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:focus,a.list-group-item-success:hover,button.list-group-item-success:focus,button.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:focus,a.list-group-item-success.active:hover,button.list-group-item-success.active,button.list-group-item-success.active:focus,button.list-group-item-success.active:hover{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:focus,a.list-group-item-info:hover,button.list-group-item-info:focus,button.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:focus,a.list-group-item-info.active:hover,button.list-group-item-info.active,button.list-group-item-info.active:focus,button.list-group-item-info.active:hover{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:focus,a.list-group-item-warning:hover,button.list-group-item-warning:focus,button.list-group-item-warning:hover{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:focus,a.list-group-item-warning.active:hover,button.list-group-item-warning.active,button.list-group-item-warning.active:focus,button.list-group-item-warning.active:hover{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:focus,a.list-group-item-danger:hover,button.list-group-item-danger:focus,button.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover,button.list-group-item-danger.active,button.list-group-item-danger.active:focus,button.list-group-item-danger.active:hover{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>.small,.panel-title>.small>a,.panel-title>a,.panel-title>small,.panel-title>small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-left-radius:0;border-top-right-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.panel-collapse>.table,.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.panel-collapse>.table caption,.panel>.table caption,.panel>.table-responsive>.table caption{padding-right:15px;padding-left:15px}.panel>.table-responsive:first-child>.table:first-child,.panel>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table:first-child>thead:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table-responsive:last-child>.table:last-child,.panel>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child td,.panel>.table>tbody:first-child>tr:first-child th{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.list-group,.panel-group .panel-heading+.panel-collapse>.panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{-webkit-appearance:none;padding:0;cursor:pointer;background:0 0;border:0}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out;-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%)}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5)}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:12px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;filter:alpha(opacity=0);opacity:0;line-break:auto}.tooltip.in{filter:alpha(opacity=90);opacity:.9}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{right:5px;bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);line-break:auto}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{content:"";border-width:10px}.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25)}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>a>img,.carousel-inner>.item>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.active.right,.carousel-inner>.item.next{left:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.carousel-inner>.item.active.left,.carousel-inner>.item.prev{left:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.carousel-inner>.item.active,.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right{left:0;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);background-color:rgba(0,0,0,0);filter:alpha(opacity=50);opacity:.5}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);background-repeat:repeat-x}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);background-repeat:repeat-x}.carousel-control:focus,.carousel-control:hover{color:#fff;text-decoration:none;filter:alpha(opacity=90);outline:0;opacity:.9}.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block;margin-top:-10px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{left:50%;margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{right:50%;margin-right:-10px}.carousel-control .icon-next,.carousel-control .icon-prev{width:20px;height:20px;font-family:serif;line-height:1}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000\9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-10px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-10px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.btn-group-vertical>.btn-group:after,.btn-group-vertical>.btn-group:before,.btn-toolbar:after,.btn-toolbar:before,.clearfix:after,.clearfix:before,.container-fluid:after,.container-fluid:before,.container:after,.container:before,.dl-horizontal dd:after,.dl-horizontal dd:before,.form-horizontal .form-group:after,.form-horizontal .form-group:before,.modal-footer:after,.modal-footer:before,.modal-header:after,.modal-header:before,.nav:after,.nav:before,.navbar-collapse:after,.navbar-collapse:before,.navbar-header:after,.navbar-header:before,.navbar:after,.navbar:before,.pager:after,.pager:before,.panel-body:after,.panel-body:before,.row:after,.row:before{display:table;content:" "}.btn-group-vertical>.btn-group:after,.btn-toolbar:after,.clearfix:after,.container-fluid:after,.container:after,.dl-horizontal dd:after,.form-horizontal .form-group:after,.modal-footer:after,.modal-header:after,.nav:after,.navbar-collapse:after,.navbar-header:after,.navbar:after,.pager:after,.panel-body:after,.row:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-lg,.visible-md,.visible-sm,.visible-xs{display:none!important}.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table!important}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table!important}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table!important}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table!important}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table!important}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}} +/*# sourceMappingURL=bootstrap.min.css.map */ \ No newline at end of file diff --git a/cmm/cmm/bootstrap/fonts/glyphicons-halflings-regular.eot b/cmm/cmm/bootstrap/fonts/glyphicons-halflings-regular.eot new file mode 100644 index 0000000000000000000000000000000000000000..b93a4953fff68df523aa7656497ee339d6026d64 GIT binary patch literal 20127 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cmm/cmm/bootstrap/fonts/glyphicons-halflings-regular.ttf b/cmm/cmm/bootstrap/fonts/glyphicons-halflings-regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..1413fc609ab6f21774de0cb7e01360095584f65b GIT binary patch literal 45404 zcmd?Sd0-pWwLh*qi$?oCk~i6sWlOeWJC3|4juU5JNSu9hSVACzERcmjLV&P^utNzg zIE4Kr1=5g!SxTX#Ern9_%4&01rlrW`Z!56xXTGQR4C z3vR~wXq>NDx$c~e?;ia3YjJ*$!C>69a?2$lLyhpI!CFfJsP=|`8@K0|bbMpWwVUEygg0=0x_)HeHpGSJagJNLA3c!$EuOV>j$wi! zbo{vZ(s8tl>@!?}dmNHXo)ABy7ohD7_1G-P@SdJWT8*oeyBVYVW9*vn}&VI4q++W;Z+uz=QTK}^C75!`aFYCX# zf7fC2;o`%!huaTNJAB&VWrx=szU=VLhwnbT`vc<#<`4WI6n_x@AofA~2d90o?1L3w z9!I|#P*NQ)$#9aASijuw>JRld^-t)Zhmy|i-`Iam|IWkguaMR%lhi4p~cX-9& zjfbx}yz}s`4-6>D^+6FzihR)Y!GsUy=_MWi_v7y#KmYi-{iZ+s@ekkq!@Wxz!~BQwiI&ti z>hC&iBe2m(dpNVvSbZe3DVgl(dxHt-k@{xv;&`^c8GJY%&^LpM;}7)B;5Qg5J^E${ z7z~k8eWOucjX6)7q1a%EVtmnND8cclz8R1=X4W@D8IDeUGXxEWe&p>Z*voO0u_2!! zj3dT(Ki+4E;uykKi*yr?w6!BW2FD55PD6SMj`OfBLwXL5EA-9KjpMo4*5Eqs^>4&> z8PezAcn!9jk-h-Oo!E9EjX8W6@EkTHeI<@AY{f|5fMW<-Ez-z)xCvW3()Z#x0oydB zzm4MzY^NdpIF9qMp-jU;99LjlgY@@s+=z`}_%V*xV7nRV*Kwrx-i`FzI0BZ#yOI8# z!SDeNA5b6u9!Imj89v0(g$;dT_y|Yz!3V`i{{_dez8U@##|X9A};s^7vEd!3AcdyVlhVk$v?$O442KIM1-wX^R{U7`JW&lPr3N(%kXfXT_`7w^? z=#ntx`tTF|N$UT?pELvw7T*2;=Q-x@KmDUIbLyXZ>f5=y7z1DT<7>Bp0k;eItHF?1 zErzhlD2B$Tm|^7DrxnTYm-tgg`Mt4Eivp5{r$o9e)8(fXBO4g|G^6Xy?y$SM*&V52 z6SR*%`%DZC^w(gOWQL?6DRoI*hBNT)xW9sxvmi@!vI^!mI$3kvAMmR_q#SGn3zRb_ zGe$=;Tv3dXN~9XuIHow*NEU4y&u}FcZEZoSlXb9IBOA}!@J3uovp}yerhPMaiI8|SDhvWVr z^BE&yx6e3&RYqIg;mYVZ*3#A-cDJ;#ms4txEmwm@g^s`BB}KmSr7K+ruIoKs=s|gOXP|2 zb1!)87h9?(+1^QRWb(Vo8+@G=o24gyuzF3ytfsKjTHZJ}o{YznGcTDm!s)DRnmOX} z3pPL4wExoN$kyc2>#J`k+<67sy-VsfbQ-1u+HkyFR?9G`9r6g4*8!(!c65Be-5hUg zZHY$M0k(Yd+DT1*8)G(q)1&tDl=g9H7!bZTOvEEFnBOk_K=DXF(d4JOaH zI}*A3jGmy{gR>s}EQzyJa_q_?TYPNXRU1O;fcV_&TQZhd{@*8Tgpraf~nT0BYktu*n{a~ub^UUqQPyr~yBY{k2O zgV)honv{B_CqY|*S~3up%Wn%7i*_>Lu|%5~j)}rQLT1ZN?5%QN`LTJ}vA!EE=1`So z!$$Mv?6T)xk)H8JTrZ~m)oNXxS}pwPd#);<*>zWsYoL6iK!gRSBB{JCgB28C#E{T? z5VOCMW^;h~eMke(w6vLlKvm!!TyIf;k*RtK)|Q>_@nY#J%=h%aVb)?Ni_By)XNxY)E3`|}_u}fn+Kp^3p4RbhFUBRtGsDyx9Eolg77iWN z2iH-}CiM!pfYDIn7;i#Ui1KG01{3D<{e}uWTdlX4Vr*nsb^>l0%{O?0L9tP|KGw8w z+T5F}md>3qDZQ_IVkQ|BzuN08uN?SsVt$~wcHO4pB9~ykFTJO3g<4X({-Tm1w{Ufo zI03<6KK`ZjqVyQ(>{_aMxu7Zm^ck&~)Q84MOsQ-XS~{6j>0lTl@lMtfWjj;PT{nlZ zIn0YL?kK7CYJa)(8?unZ)j8L(O}%$5S#lTcq{rr5_gqqtZ@*0Yw4}OdjL*kBv+>+@ z&*24U=y{Nl58qJyW1vTwqsvs=VRAzojm&V zEn6=WzdL1y+^}%Vg!ap>x%%nFi=V#wn# zUuheBR@*KS)5Mn0`f=3fMwR|#-rPMQJg(fW*5e`7xO&^UUH{L(U8D$JtI!ac!g(Ze89<`UiO@L+)^D zjPk2_Ie0p~4|LiI?-+pHXuRaZKG$%zVT0jn!yTvvM^jlcp`|VSHRt-G@_&~<4&qW@ z?b#zIN)G(}L|60jer*P7#KCu*Af;{mpWWvYK$@Squ|n-Vtfgr@ZOmR5Xpl;0q~VILmjk$$mgp+`<2jP z@+nW5Oap%fF4nFwnVwR7rpFaOdmnfB$-rkO6T3#w^|*rft~acgCP|ZkgA6PHD#Of| zY%E!3tXtsWS`udLsE7cSE8g@p$ceu*tI71V31uA7jwmXUCT7+Cu3uv|W>ZwD{&O4Nfjjvl43N#A$|FWxId! z%=X!HSiQ-#4nS&smww~iXRn<-`&zc)nR~js?|Ei-cei$^$KsqtxNDZvl1oavXK#Pz zT&%Wln^Y5M95w=vJxj0a-ko_iQt(LTX_5x#*QfQLtPil;kkR|kz}`*xHiLWr35ajx zHRL-QQv$|PK-$ges|NHw8k6v?&d;{A$*q15hz9{}-`e6ys1EQ1oNNKDFGQ0xA!x^( zkG*-ueZT(GukSnK&Bs=4+w|(kuWs5V_2#3`!;f}q?>xU5IgoMl^DNf+Xd<=sl2XvkqviJ>d?+G@Z5nxxd5Sqd$*ENUB_mb8Z+7CyyU zA6mDQ&e+S~w49csl*UePzY;^K)Fbs^%?7;+hFc(xz#mWoek4_&QvmT7Fe)*{h-9R4 zqyXuN5{)HdQ6yVi#tRUO#M%;pL>rQxN~6yoZ)*{{!?jU)RD*oOxDoTjVh6iNmhWNC zB5_{R=o{qvxEvi(khbRS`FOXmOO|&Dj$&~>*oo)bZz%lPhEA@ zQ;;w5eu5^%i;)w?T&*=UaK?*|U3~{0tC`rvfEsRPgR~16;~{_S2&=E{fE2=c>{+y} zx1*NTv-*zO^px5TA|B```#NetKg`19O!BK*-#~wDM@KEllk^nfQ2quy25G%)l72<> zzL$^{DDM#jKt?<>m;!?E2p0l12`j+QJjr{Lx*47Nq(v6i3M&*P{jkZB{xR?NOSPN% zU>I+~d_ny=pX??qjF*E78>}Mgts@_yn`)C`wN-He_!OyE+gRI?-a>Om>Vh~3OX5+& z6MX*d1`SkdXwvb7KH&=31RCC|&H!aA1g_=ZY0hP)-Wm6?A7SG0*|$mC7N^SSBh@MG z9?V0tv_sE>X==yV{)^LsygK2=$Mo_0N!JCOU?r}rmWdHD%$h~~G3;bt`lH& zAuOOZ=G1Mih**0>lB5x+r)X^8mz!0K{SScj4|a=s^VhUEp#2M=^#WRqe?T&H9GnWa zYOq{+gBn9Q0e0*Zu>C(BAX=I-Af9wIFhCW6_>TsIH$d>|{fIrs&BX?2G>GvFc=<8` zVJ`#^knMU~65dWGgXcht`Kb>{V2oo%<{NK|iH+R^|Gx%q+env#Js*(EBT3V0=w4F@W+oLFsA)l7Qy8mx_;6Vrk;F2RjKFvmeq} zro&>@b^(?f))OoQ#^#s)tRL>b0gzhRYRG}EU%wr9GjQ#~Rpo|RSkeik^p9x2+=rUr}vfnQoeFAlv=oX%YqbLpvyvcZ3l$B z5bo;hDd(fjT;9o7g9xUg3|#?wU2#BJ0G&W1#wn?mfNR{O7bq747tc~mM%m%t+7YN}^tMa24O4@w<|$lk@pGx!;%pKiq&mZB z?3h<&w>un8r?Xua6(@Txu~Za9tI@|C4#!dmHMzDF_-_~Jolztm=e)@vG11bZQAs!tFvd9{C;oxC7VfWq377Y(LR^X_TyX9bn$)I765l=rJ%9uXcjggX*r?u zk|0!db_*1$&i8>d&G3C}A`{Fun_1J;Vx0gk7P_}8KBZDowr*8$@X?W6v^LYmNWI)lN92yQ;tDpN zOUdS-W4JZUjwF-X#w0r;97;i(l}ZZT$DRd4u#?pf^e2yaFo zbm>I@5}#8FjsmigM8w_f#m4fEP~r~_?OWB%SGWcn$ThnJ@Y`ZI-O&Qs#Y14To( zWAl>9Gw7#}eT(!c%D0m>5D8**a@h;sLW=6_AsT5v1Sd_T-C4pgu_kvc?7+X&n_fct znkHy(_LExh=N%o3I-q#f$F4QJpy>jZBW zRF7?EhqTGk)w&Koi}QQY3sVh?@e-Z3C9)P!(hMhxmXLC zF_+ZSTQU`Gqx@o(~B$dbr zHlEUKoK&`2gl>zKXlEi8w6}`X3kh3as1~sX5@^`X_nYl}hlbpeeVlj#2sv)CIMe%b zBs7f|37f8qq}gA~Is9gj&=te^wN8ma?;vF)7gce;&sZ64!7LqpR!fy)?4cEZposQ8 zf;rZF7Q>YMF1~eQ|Z*!5j0DuA=`~VG$Gg6B?Om1 z6fM@`Ck-K*k(eJ)Kvysb8sccsFf@7~3vfnC=<$q+VNv)FyVh6ZsWw}*vs>%k3$)9| zR9ek-@pA23qswe1io)(Vz!vS1o*XEN*LhVYOq#T`;rDkgt86T@O`23xW~;W_#ZS|x zvwx-XMb7_!hIte-#JNpFxskMMpo2OYhHRr0Yn8d^(jh3-+!CNs0K2B!1dL$9UuAD= zQ%7Ae(Y@}%Cd~!`h|wAdm$2WoZ(iA1(a_-1?znZ%8h72o&Mm*4x8Ta<4++;Yr6|}u zW8$p&izhdqF=m8$)HyS2J6cKyo;Yvb>DTfx4`4R{ zPSODe9E|uflE<`xTO=r>u~u=NuyB&H!(2a8vwh!jP!yfE3N>IiO1jI>7e&3rR#RO3_}G23W?gwDHgSgekzQ^PU&G5z&}V5GO? zfg#*72*$DP1T8i`S7=P;bQ8lYF9_@8^C(|;9v8ZaK2GnWz4$Th2a0$)XTiaxNWfdq z;yNi9veH!j)ba$9pke8`y2^63BP zIyYKj^7;2don3se!P&%I2jzFf|LA&tQ=NDs{r9fIi-F{-yiG-}@2`VR^-LIFN8BC4 z&?*IvLiGHH5>NY(Z^CL_A;yISNdq58}=u~9!Ia7 zm7MkDiK~lsfLpvmPMo!0$keA$`%Tm`>Fx9JpG^EfEb(;}%5}B4Dw!O3BCkf$$W-dF z$BupUPgLpHvr<<+QcNX*w@+Rz&VQz)Uh!j4|DYeKm5IC05T$KqVV3Y|MSXom+Jn8c zgUEaFW1McGi^44xoG*b0JWE4T`vka7qTo#dcS4RauUpE{O!ZQ?r=-MlY#;VBzhHGU zS@kCaZ*H73XX6~HtHd*4qr2h}Pf0Re@!WOyvres_9l2!AhPiV$@O2sX>$21)-3i+_ z*sHO4Ika^!&2utZ@5%VbpH(m2wE3qOPn-I5Tbnt&yn9{k*eMr3^u6zG-~PSr(w$p> zw)x^a*8Ru$PE+{&)%VQUvAKKiWiwvc{`|GqK2K|ZMy^Tv3g|zENL86z7i<c zW`W>zV1u}X%P;Ajn+>A)2iXZbJ5YB_r>K-h5g^N=LkN^h0Y6dPFfSBh(L`G$D%7c` z&0RXDv$}c7#w*7!x^LUes_|V*=bd&aP+KFi((tG*gakSR+FA26%{QJdB5G1F=UuU&koU*^zQA=cEN9}Vd?OEh| zgzbFf1?@LlPkcXH$;YZe`WEJ3si6&R2MRb}LYK&zK9WRD=kY-JMPUurX-t4(Wy{%` zZ@0WM2+IqPa9D(^*+MXw2NWwSX-_WdF0nMWpEhAyotIgqu5Y$wA=zfuXJ0Y2lL3#ji26-P3Z?-&0^KBc*`T$+8+cqp`%g0WB zTH9L)FZ&t073H4?t=(U6{8B+uRW_J_n*vW|p`DugT^3xe8Tomh^d}0k^G7$3wLgP& zn)vTWiMA&=bR8lX9H=uh4G04R6>C&Zjnx_f@MMY!6HK5v$T%vaFm;E8q=`w2Y}ucJ zkz~dKGqv9$E80NTtnx|Rf_)|3wxpnY6nh3U9<)fv2-vhQ6v=WhKO@~@X57N-`7Ppc zF;I7)eL?RN23FmGh0s;Z#+p)}-TgTJE%&>{W+}C`^-sy{gTm<$>rR z-X7F%MB9Sf%6o7A%ZHReD4R;imU6<9h81{%avv}hqugeaf=~^3A=x(Om6Lku-Pn9i zC;LP%Q7Xw*0`Kg1)X~nAsUfdV%HWrpr8dZRpd-#%)c#Fu^mqo|^b{9Mam`^Zw_@j@ zR&ZdBr3?@<@%4Z-%LT&RLgDUFs4a(CTah_5x4X`xDRugi#vI-cw*^{ncwMtA4NKjByYBza)Y$hozZCpuxL{IP&=tw6ZO52WY3|iwGf&IJCn+u(>icK zZB1~bWXCmwAUz|^<&ysd#*!DSp8}DLNbl5lRFat4NkvItxy;9tpp9~|@ z;JctShv^Iq4(z+y7^j&I?GCdKMVg&jCwtCkc4*@O7HY*veGDBtAIn*JgD$QftP}8= zxFAdF=(S>Ra6(4slk#h%b?EOU-96TIX$Jbfl*_7IY-|R%H zF8u|~hYS-YwWt5+^!uGcnKL~jM;)ObZ#q68ZkA?}CzV-%6_vPIdzh_wHT_$mM%vws9lxUj;E@#1UX?WO2R^41(X!nk$+2oJGr!sgcbn1f^yl1 z#pbPB&Bf;1&2+?};Jg5qgD1{4_|%X#s48rOLE!vx3@ktstyBsDQWwDz4GYlcgu$UJ zp|z_32yN72T*oT$SF8<}>e;FN^X&vWNCz>b2W0rwK#<1#kbV)Cf`vN-F$&knLo5T& z8!sO-*^x4=kJ$L&*h%rQ@49l?7_9IG99~xJDDil00<${~D&;kiqRQqeW5*22A`8I2 z(^@`qZoF7_`CO_e;8#qF!&g>UY;wD5MxWU>azoo=E{kW(GU#pbOi%XAn%?W{b>-bTt&2?G=E&BnK9m0zs{qr$*&g8afR_x`B~o zd#dxPpaap;I=>1j8=9Oj)i}s@V}oXhP*{R|@DAQXzQJekJnmuQ;vL90_)H_nD1g6e zS1H#dzg)U&6$fz0g%|jxDdz|FQN{KJ&Yx0vfuzAFewJjv`pdMRpY-wU`-Y6WQnJ(@ zGVb!-8DRJZvHnRFiR3PG3Tu^nCn(CcZHh7hQvyd7i6Q3&ot86XI{jo%WZqCPcTR0< zMRg$ZE=PQx66ovJDvI_JChN~k@L^Pyxv#?X^<)-TS5gk`M~d<~j%!UOWG;ZMi1af< z+86U0=sm!qAVJAIqqU`Qs1uJhQJA&n@9F1PUrYuW!-~IT>l$I!#5dBaiAK}RUufjg{$#GdQBkxF1=KU2E@N=i^;xgG2Y4|{H>s` z$t`k8c-8`fS7Yfb1FM#)vPKVE4Uf(Pk&%HLe z%^4L>@Z^9Z{ZOX<^e)~adVRkKJDanJ6VBC_m@6qUq_WF@Epw>AYqf%r6qDzQ~AEJ!jtUvLp^CcqZ^G-;Kz3T;O4WG45Z zFhrluCxlY`M+OKr2SeI697btH7Kj`O>A!+2DTEQ=48cR>Gg2^5uqp(+y5Sl09MRl* zp|28!v*wvMd_~e2DdKDMMQ|({HMn3D%%ATEecGG8V9>`JeL)T0KG}=}6K8NiSN5W< z79-ZdYWRUb`T}(b{RjN8>?M~opnSRl$$^gT`B27kMym5LNHu-k;A;VF8R(HtDYJHS zU7;L{a@`>jd0svOYKbwzq+pWSC(C~SPgG~nWR3pBA8@OICK$Cy#U`kS$I;?|^-SBC zBFkoO8Z^%8Fc-@X!KebF2Ob3%`8zlVHj6H;^(m7J35(_bS;cZPd}TY~qixY{MhykQ zV&7u7s%E=?i`}Ax-7dB0ih47w*7!@GBt<*7ImM|_mYS|9_K7CH+i}?*#o~a&tF-?C zlynEu1DmiAbGurEX2Flfy$wEVk7AU;`k#=IQE*6DMWafTL|9-vT0qs{A3mmZGzOyN zcM9#Rgo7WgB_ujU+?Q@Ql?V-!E=jbypS+*chI&zA+C_3_@aJal}!Q54?qsL0In({Ly zjH;e+_SK8yi0NQB%TO+Dl77jp#2pMGtwsgaC>K!)NimXG3;m7y`W+&<(ZaV>N*K$j zLL~I+6ouPk6_(iO>61cIsinx`5}DcKSaHjYkkMuDoVl>mKO<4$F<>YJ5J9A2Vl}#BP7+u~L8C6~D zsk`pZ$9Bz3teQS1Wb|8&c2SZ;qo<#F&gS;j`!~!ADr(jJXMtcDJ9cVi>&p3~{bqaP zgo%s8i+8V{UrYTc9)HiUR_c?cfx{Yan2#%PqJ{%?Wux4J;T$#cumM0{Es3@$>}DJg zqe*c8##t;X(4$?A`ve)e@YU3d2Balcivot{1(ahlE5qg@S-h(mPNH&`pBX$_~HdG48~)$x5p z{>ghzqqn_t8~pY<5?-To>cy^6o~mifr;KWvx_oMtXOw$$d6jddXG)V@a#lL4o%N@A zNJlQAz6R8{7jax-kQsH6JU_u*En%k^NHlvBB!$JAK!cYmS)HkLAkm0*9G3!vwMIWv zo#)+EamIJHEUV|$d|<)2iJ`lqBQLx;HgD}c3mRu{iK23C>G{0Mp1K)bt6OU?xC4!_ zZLqpFzeu&+>O1F>%g-%U^~yRg(-wSp@vmD-PT#bCWy!%&H;qT7rfuRCEgw67V!Qob z&tvPU@*4*$YF#2_>M0(75QxqrJr3Tvh~iDeFhxl=MzV@(psx%G8|I{~9;tv#BBE`l z3)_98eZqFNwEF1h)uqhBmT~mSmT8k$7vSHdR97K~kM)P9PuZdS;|Op4A?O<*%!?h` zn`}r_j%xvffs46x2hCWuo0BfIQWCw9aKkH==#B(TJ%p}p-RuIVzsRlaPL_Co{&R0h zQrqn=g1PGjQg3&sc2IlKG0Io#v%@p>tFwF)RG0ahYs@Zng6}M*d}Xua)+h&?$`%rb z;>M=iMh5eIHuJ5c$aC`y@CYjbFsJnSPH&}LQz4}za9YjDuao>Z^EdL@%saRm&LGQWXs*;FzwN#pH&j~SLhDZ+QzhplV_ij(NyMl z;v|}amvxRddO81LJFa~2QFUs z+Lk zZck)}9uK^buJNMo4G(rSdX{57(7&n=Q6$QZ@lIO9#<3pA2ceDpO_340B*pHlh_y{>i&c1?vdpN1j>3UN-;;Yq?P+V5oY`4Z(|P8SwWq<)n`W@AwcQ?E9 zd5j8>FT^m=MHEWfN9jS}UHHsU`&SScib$qd0i=ky0>4dz5ADy70AeIuSzw#gHhQ_c zOp1!v6qU)@8MY+ zMNIID?(CysRc2uZQ$l*QZVY)$X?@4$VT^>djbugLQJdm^P>?51#lXBkdXglYm|4{L zL%Sr?2f`J+xrcN@=0tiJt(<-=+v>tHy{XaGj7^cA6felUn_KPa?V4ebfq7~4i~GKE zpm)e@1=E;PP%?`vK6KVPKXjUXyLS1^NbnQ&?z>epHCd+J$ktT1G&L~T)nQeExe;0Z zlei}<_ni ztFo}j7nBl$)s_3odmdafVieFxc)m!wM+U`2u%yhJ90giFcU1`dR6BBTKc2cQ*d zm-{?M&%(={xYHy?VCx!ogr|4g5;V{2q(L?QzJGsirn~kWHU`l`rHiIrc-Nan!hR7zaLsPr4uR zG{En&gaRK&B@lyWV@yfFpD_^&z>84~_0Rd!v(Nr%PJhFF_ci3D#ixf|(r@$igZiWw za*qbXIJ_Hm4)TaQ=zW^g)FC6uvyO~Hg-#Z5Vsrybz6uOTF>Rq1($JS`imyNB7myWWpxYL(t7`H8*voI3Qz6mvm z$JxtArLJ(1wlCO_te?L{>8YPzQ})xJlvc5wv8p7Z=HviPYB#^#_vGO#*`<0r%MR#u zN_mV4vaBb2RwtoOYCw)X^>r{2a0kK|WyEYoBjGxcObFl&P*??)WEWKU*V~zG5o=s@ z;rc~uuQQf9wf)MYWsWgPR!wKGt6q;^8!cD_vxrG8GMoFGOVV=(J3w6Xk;}i)9(7*U zwR4VkP_5Zx7wqn8%M8uDj4f1aP+vh1Wue&ry@h|wuN(D2W;v6b1^ z`)7XBZ385zg;}&Pt@?dunQ=RduGRJn^9HLU&HaeUE_cA1{+oSIjmj3z+1YiOGiu-H zf8u-oVnG%KfhB8H?cg%@#V5n+L$MO2F4>XoBjBeX>css^h}Omu#)ExTfUE^07KOQS znMfQY2wz?!7!{*C^)aZ^UhMZf=TJNDv8VrrW;JJ9`=|L0`w9DE8MS>+o{f#{7}B4P z{I34>342vLsP}o=ny1eZkEabr@niT5J2AhByUz&i3Ck0H*H`LRHz;>3C_ru!X+EhJ z6(+(lI#4c`2{`q0o9aZhI|jRjBZOV~IA_km7ItNtUa(Wsr*Hmb;b4=;R(gF@GmsRI`pF+0tmq0zy~wnoJD(LSEwHjTOt4xb0XB-+ z&4RO{Snw4G%gS9w#uSUK$Zbb#=jxEl;}6&!b-rSY$0M4pftat-$Q)*y!bpx)R%P>8 zrB&`YEX2%+s#lFCIV;cUFUTIR$Gn2%F(3yLeiG8eG8&)+cpBlzx4)sK?>uIlH+$?2 z9q9wk5zY-xr_fzFSGxYp^KSY0s%1BhsI>ai2VAc8&JiwQ>3RRk?ITx!t~r45qsMnj zkX4bl06ojFCMq<9l*4NHMAtIxDJOX)H=K*$NkkNG<^nl46 zHWH1GXb?Og1f0S+8-((5yaeegCT62&4N*pNQY;%asz9r9Lfr;@Bl${1@a4QAvMLbV6JDp>8SO^q1)#(o%k!QiRSd0eTmzC< zNIFWY5?)+JTl1Roi=nS4%@5iF+%XztpR^BSuM~DX9q`;Mv=+$M+GgE$_>o+~$#?*y zAcD4nd~L~EsAjXV-+li6Lua4;(EFdi|M2qV53`^4|7gR8AJI;0Xb6QGLaYl1zr&eu zH_vFUt+Ouf4SXA~ z&Hh8K@ms^`(hJfdicecj>J^Aqd00^ccqN!-f-!=N7C1?`4J+`_f^nV!B3Q^|fuU)7 z1NDNT04hd4QqE+qBP+>ZE7{v;n3OGN`->|lHjNL5w40pePJ?^Y6bFk@^k%^5CXZ<+4qbOplxpe)l7c6m%o-l1oWmCx%c6@rx85hi(F=v(2 zJ$jN>?yPgU#DnbDXPkHLeQwED5)W5sH#-eS z%#^4dxiVs{+q(Yd^ShMN3GH)!h!@W&N`$L!SbElXCuvnqh{U7lcCvHI#{ZjwnKvu~ zAeo7Pqot+Ohm{8|RJsTr3J4GjCy5UTo_u_~p)MS&Z5UrUc|+;Mc(YS+ju|m3Y_Dvt zonVtpBWlM718YwaN3a3wUNqX;7TqvAFnVUoD5v5WTh~}r)KoLUDw%8Rrqso~bJqd> z_T!&Rmr6ebpV^4|knJZ%qmzL;OvG3~A*loGY7?YS%hS{2R0%NQ@fRoEK52Aiu%gj( z_7~a}eQUh8PnyI^J!>pxB(x7FeINHHC4zLDT`&C*XUpp@s0_B^!k5Uu)^j_uuu^T> z8WW!QK0SgwFHTA%M!L`bl3hHjPp)|wL5Var_*A1-H8LV?uY5&ou{hRjj>#X@rxV>5%-9hbP+v?$4}3EfoRH;l_wSiz{&1<+`Y5%o%q~4rdpRF0jOsCoLnWY5x?V)0ga>CDo`NpqS) z@x`mh1QGkx;f)p-n^*g5M^zRTHz%b2IkLBY{F+HsjrFC9_H(=9Z5W&Eymh~A_FUJ} znhTc9KG((OnjFO=+q>JQZJbeOoUM77M{)$)qQMcxK9f;=L;IOv_J>*~w^YOW744QZ zoG;!b9VD3ww}OX<8sZ0F##8hvfDP{hpa3HjaLsKbLJ8 z0WpY2E!w?&cWi7&N%bOMZD~o7QT*$xCRJ@{t31~qx~+0yYrLXubXh2{_L699Nl_pn z6)9eu+uUTUdjHXYs#pX^L)AIb!FjjNsTp7C399w&B{Q4q%yKfmy}T2uQdU|1EpNcY zDk~(h#AdxybjfzB+mg6rdU9mDZ^V>|U13Dl$Gj+pAL}lR2a1u!SJXU_YqP9N{ose4 zk+$v}BIHX60WSGVWv;S%zvHOWdDP(-ceo(<8`y@Goy%4wDu>57QZNJc)f>Ls+}9h7 z^N=#3q3|l?aG8K#HwiW2^PJu{v|x5;awYfahC?>_af3$LmMc4%N~JwVlRZa4c+eW2 zE!zosAjOv&UeCeu;Bn5OQUC=jtZjF;NDk9$fGbxf3d29SUBekX1!a$Vmq_VK*MHQ4)eB!dQrHH)LVYNF%-t8!d`@!cb z2CsKs3|!}T^7fSZm?0dJ^JE`ZGxA&a!jC<>6_y67On0M)hd$m*RAzo_qM?aeqkm`* zXpDYcc_>TFZYaC3JV>{>mp(5H^efu!Waa7hGTAts29jjuVd1vI*fEeB?A&uG<8dLZ z(j6;-%vJ7R0U9}XkH)1g>&uptXPHBEA*7PSO2TZ+dbhVxspNW~ZQT3fApz}2 z_@0-lZODcd>dLrYp!mHn4k>>7kibI!Em+Vh*;z}l?0qro=aJt68joCr5Jo(Vk<@i) z5BCKb4p6Gdr9=JSf(2Mgr=_6}%4?SwhV+JZj3Ox^_^OrQk$B^v?eNz}d^xRaz&~ zKVnlLnK#8^y=If2f1zmb~^5lPLe?%l}>?~wN4IN((2~U{e9fKhLMtYFj)I$(y zgnKv?R+ZpxA$f)Q2l=aqE6EPTK=i0sY&MDFJp!vQayyvzh4wee<}kybNthRlX>SHh z7S}9he^EBOqzBCww^duHu!u+dnf9veG{HjW!}aT7aJqzze9K6-Z~8pZAgdm1n~aDs z8_s7?WXMPJ3EPJHi}NL&d;lZP8hDhAXf5Hd!x|^kEHu`6QukXrVdLnq5zbI~oPo?7 z2Cbu8U?$K!Z4_yNM1a(bL!GRe!@{Qom+DxjrJ!B99qu5b*Ma%^&-=6UEbC+S2zX&= zQ!%bgJTvmv^2}hhvNQg!l=kbapAgM^hruE3k@jTxsG(B6d=4thBC*4tzVpCYXFc$a zeqgVB^zua)y-YjpiibCCdU%txXYeNFnXcbNj*D?~)5AGjL+!!ij_4{5EWKGav0^={~M^q}baAFOPzxfUM>`KPf|G z&hsaR*7(M6KzTj8Z?;45zX@L#xU{4n$9Q_<-ac(y4g~S|Hyp^-<*d8+P4NHe?~vfm z@y309=`lGdvN8*jw-CL<;o#DKc-%lb0i9a3%{v&2X($|Qxv(_*()&=xD=5oBg=$B0 zU?41h9)JKvP0yR{KsHoC>&`(Uz>?_`tlLjw1&5tPH3FoB%}j;yffm$$s$C=RHi`I3*m@%CPqWnP@B~%DEe;7ZT{9!IMTo1hT3Q347HJ&!)BM2 z3~aClf>aFh0_9||4G}(Npu`9xYY1*SD|M~9!CCFn{-J$u2&Dg*=5$_nozpoD2nxqq zB!--eA8UWZlcEDp4r#vhZ6|vq^9sFvRnA9HpHch5Mq4*T)oGbruj!U8Lx_G%Lby}o zTQ-_4A7b)5A42vA0U}hUJq6&wQ0J%$`w#ph!EGmW96)@{AUx>q6E>-r^Emk!iCR+X zdIaNH`$}7%57D1FyTccs3}Aq0<0Ei{`=S7*>pyg=Kv3nrqblqZcpsCWSQl^uMSsdj zYzh73?6th$c~CI0>%5@!Ej`o)Xm38u0fp9=HE@Sa6l2oX9^^4|Aq%GA z3(AbFR9gA_2T2i%Ck5V2Q2WW-(a&(j#@l6wE4Z`xg#S za#-UWUpU2U!TmIo`CN0JwG^>{+V#9;zvx;ztc$}@NlcyJr?q(Y`UdW6qhq!aWyB5xV1#Jb{I-ghFNO0 zFU~+QgPs{FY1AbiU&S$QSix>*rqYVma<-~s%ALhFyVhAYepId1 zs!gOB&weC18yhE-v6ltKZMV|>JwTX+X)Y_EI(Ff^3$WTD|Ea-1HlP;6L~&40Q&5{0 z$e$2KhUgH8ucMJxJV#M%cs!d~#hR^nRwk|uuCSf6irJCkSyI<%CR==tftx6d%;?ef zYIcjZrP@APzbtOeUe>m-TW}c-ugh+U*RbL1eIY{?>@8aW9bb1NGRy@MTse@>= za%;5=U}X%K2tKTYe9gjMcBvX%qrC&uZ`d(t)g)X8snf?vBe3H%dG=bl^rv8Z@YN$gd9yveHY0@Wt0$s zh^7jCp(q+6XDoekb;=%y=Wr8%6;z0ANH5dDR_VudDG|&_lYykJaiR+(y{zpR=qL3|2e${8 z2V;?jgHj7}Kl(d8C9xWRjhpf_)KOXl+@c4wrHy zL3#9U(`=N59og2KqVh>nK~g9>fX*PI0`>i;;b6KF|8zg+k2hViCt}4dfMdvb1NJ-Rfa7vL2;lPK{Lq*u`JT>S zoM_bZ_?UY6oV6Ja14X^;LqJPl+w?vf*C!nGK;uU^0GRN|UeFF@;H(Hgp8x^|;ygh? zIZx3DuO(lD01ksanR@Mn#lti=p28RTNYY6yK={RMFiVd~k8!@a&^jicZ&rxD3CCI! zVb=fI?;c#f{K4Pp2lnb8iF2mig)|6JEmU86Y%l}m>(VnI*Bj`a6qk8QL&~PFDxI8b z2mcsQBe9$q`Q$LfG2wdvK`M1}7?SwLAV&)nO;kAk`SAz%x9CDVHVbUd$O(*aI@D|s zLxJW7W(QeGpQY<$dSD6U$ja(;Hb3{Zx@)*fIQaW{8<$KJ&fS0caI2Py^clOq9@Irt z7th7F?7W`j{&UmM==Lo~T&^R7A?G=K_e-zfTX|)i`pLitlNE(~tq*}sS1x2}Jlul6 z5+r#4SpQu8h{ntIv#qCVH`uG~+I8l+7ZG&d`Dm!+(rZQDV*1LS^WfH%-!5aTAxry~ z4xl&rot5ct{xQ$w$MtVTUi6tBFSJWq2Rj@?HAX1H$eL*fk{Hq;E`x|hghRkipYNyt zKCO=*KSziiVk|+)qQCGrTYH9X!Z0$k{Nde~0Wl`P{}ca%nv<6fnYw^~9dYxTnTZB&&962jX0DM&wy&8fdxX8xeHSe=UU&Mq zRTaUKnQO|A>E#|PUo+F=Q@dMdt`P*6e92za(TH{5C*2I2S~p?~O@hYiT>1(n^Lqqn zqewq3ctAA%0E)r53*P-a8Ak32mGtUG`L^WVcm`QovX`ecB4E9X60wrA(6NZ7z~*_DV_e z8$I*eZ8m=WtChE{#QzeyHpZ%7GwFHlwo2*tAuloI-j2exx3#x7EL^&D;Re|Kj-XT- zt908^soV2`7s+Hha!d^#J+B)0-`{qIF_x=B811SZlbUe%kvPce^xu7?LY|C z@f1gRPha1jq|=f}Se)}v-7MWH9)YAs*FJ&v3ZT9TSi?e#jarin0tjPNmxZNU_JFJG z+tZi!q)JP|4pQ)?l8$hRaPeoKf!3>MM-bp06RodLa*wD=g3)@pYJ^*YrwSIO!SaZo zDTb!G9d!hb%Y0QdYxqNSCT5o0I!GDD$Z@N!8J3eI@@0AiJmD7brkvF!pJGg_AiJ1I zO^^cKe`w$DsO|1#^_|`6XTfw6E3SJ(agG*G9qj?JiqFSL|6tSD6vUwK?Cwr~gg)Do zp@$D~7~66-=p4`!!UzJDKAymb!!R(}%O?Uel|rMH>OpRGINALtg%gpg`=}M^Q#V5( zMgJY&gF)+;`e38QHI*c%B}m94o&tOfae;og&!J2;6ENW}QeL73jatbI1*9X~y=$Dm%6FwDcnCyMRL}zo`0=y7=}*Uw zo3!qZncAL{HCgY!+}eKr{P8o27ye+;qJP;kOB%RpSesGoHLT6tcYp*6v~Z9NCyb6m zP#qds0jyqXX46qMNhXDn3pyIxw2f_z;L_X9EIB}AhyC`FYI}G3$WnW>#NMy{0aw}nB%1=Z4&*(FaCn5QG(zvdG^pQRU25;{wwG4h z@kuLO0F->{@g2!;NNd!PfqM-;@F0;&wK}0fT9UrH}(8A5I zt33(+&U;CLN|8+71@g z(s!f-kZZZILUG$QXm9iYiE*>2w;gpM>lgM{R9vT3q>qI{ELO2hJHVi`)*jzOk$r)9 zq}$VrE0$GUCm6A3H5J-=Z9i*biw8ng zi<1nM0lo^KqRY@Asucc#DMmWsnCS;5uPR)GL3pL=-IqSd>4&D&NKSGHH?pG;=Xo`w zw~VV9ddkwbp~m>9G0*b?j7-0fOwR?*U#BE#n7A=_fDS>`fwatxQ+`FzhBGQUAyIRZ??eJt46vHBlR>9m!vfb6I)8!v6TmtZ%G6&E|1e zOtx5xy%yOSu+<9Ul5w5N=&~4Oph?I=ZKLX5DXO(*&Po>5KjbY7s@tp$8(fO|`Xy}Y z;NmMypLoG7r#Xz4aHz7n)MYZ7Z1v;DFHLNV{)to;(;TJ=bbMgud96xRMME#0d$z-S z-r1ROBbW^&YdQWA>U|Y>{whex#~K!ZgEEk=LYG8Wqo28NFv)!t!~}quaAt}I^y-m| z8~E{9H2VnyVxb_wCZ7v%y(B@VrM6lzk~|ywCi3HeiSV`TF>j+Ijd|p*kyn;=mqtf8&DK^|*f+y$38+9!sis9N=S)nINm9=CJ<;Y z!t&C>MIeyou4XLM*ywT_JuOXR>VkpFwuT9j5>667A=CU*{TBrMTgb4HuW&!%Yt`;#md7-`R`ouOi$rEd!ErI zo#>qggAcx?C7`rQ2;)~PYCw%CkS(@EJHZ|!!lhi@Dp$*n^mgrrImsS~(ioGak>3)w zvop0lq@IISuA0Ou*#1JkG{U>xSQV1e}c)!d$L1plFX5XDXX5N7Ns{kT{y5|6MfhBD+esT)e7&CgSW8FxsXTAY=}?0A!j_V9 zJ;IJ~d%av<@=fNPJ9)T3qE78kaz64E>dJaYab5uaU`n~Zdp2h{8DV%SKE5G^$LfuOTRRjB;TnT(Jk$r{Pfe4CO!SM_7d)I zquW~FVCpSycJ~c*B*V8?Qqo=GwU8CkmmLFugfHQ7;A{yCy1OL-+X=twLYg9|H=~8H znnN@|tCs^ZLlCBl5wHvYF}2vo>a6%mUWpTds_mt*@wMN4-r`%NTA%+$(`m6{MNpi@ zMx)8f>U4hd!row@gM&PVo&Hx+lV@$j9yWTjTue zG9n0DP<*HUmJ7ZZWwI2x+{t3QEfr6?T}2iXl=6e0b~)J>X3`!fXd9+2wc1%cj&F@Z zgYR|r5Xd5jy9;YW&=4{-0rJ*L5CgDPj9^3%bp-`HkyBs`j1iTUGD4?WilZ6RO8mIE z+~Joc?GID6K96dyuv(dWREK9Os~%?$$FxswxQsoOi8M?RnL%B~Lyk&(-09D0M?^Jy zWjP)n(b)TF<-|CG%!Vz?8Fu&6iU<>oG#kGcrcrrBlfZMVl0wOJvsq%RL9To%iCW@)#& zZAJWhgzYAq)#NTNb~3GBcD%ZZOc43!YWSyA7TD6xkk)n^FaRAz73b}%9d&YisBic(?mv=Iq^r%Ug zzHq-rRrhfOOF+yR=AN!a9*Rd#sM9ONt5h~w)yMP7Dl9lfpi$H0%GPW^lS4~~?vI8Z z%^ToK#NOe0ExmUsb`lLO$W*}yXNOxPe@zD*90uTDULnH6C?InP3J=jYEO2d)&e|mP z1DSd0QOZeuLWo*NqZzopA+LXy9)fJC00NSX=_4Mi1Z)YyZVC>C!g}cY(Amaj%QN+bev|Xxd2OPD zk!dfkY6k!(sDBvsFC2r^?}hb81(WG5Lt9|riT`2?P;B%jaf5UX<~OJ;uAL$=Ien+V zC!V8u0v?CUa)4*Q+Q_u zkx{q;NjLcvyMuU*{+uDsCQ4U{JLowYby-tn@hatL zy}X>9y08#}oytdn^qfFesF)Tt(2!XGw#r%?7&zzFFh2U;#U9XBO8W--#gOpfbJ`Ey z|M8FCKlWQrOJwE;@Sm02l9OBr7N}go4V8ur)}M@m2uWjggb)DC4s`I4d7_8O&E(j; z?3$9~R$QDxNM^rNh9Y;6P7w+bo2q}NEd6f&_raor-v`UCaTM3TT8HK2-$|n{N@U>_ zL-`P7EXoEU5JRMa)?tNUEe8XFis+w8g9k(QQ)%?&Oac}S`2V$b?%`DwXBgja&&fR@ zH_XidF$p1wA)J|Wk1;?lCl?fgc)=TB3>Y8;BoMqHwJqhL)Tgydv9(?(TBX)fq%=~C zmLj!iX-kn7QA(9snzk0LRf<%SzO&~IhLor6A3f*U^UcoAygRe!H#@UCv$JUP&vPxs zeDj$1%#<2T1!e|!7xI+~_VXLl5|jHqvOhU7ZDUGee;HnkcPP=_k_FFxPjXg*9KyI+ zIh0@+s)1JDSuKMeaDZ3|<_*J8{TUFDLl|mXmY8B>Wj_?4mC#=XjsCKPEO=p0c&t&Z zd1%kHxR#o9S*C?du*}tEHfAC7WetnvS}`<%j=o7YVna)6pw(xzkUi7f#$|^y4WQ{7 zu@@lu=j6xr*11VEIY+`B{tgd(c3zO8%nGk0U^%ec6h)G_`ki|XQXr!?NsQkxzV6Bn1ea9L+@ z(Zr7CU_oXaW>VOdfzENm+FlFQ7Se0ROrNdw(QLvb6{f}HRQ{$Je>(c&rws#{dFI^r zZ4^(`J*G0~Pu_+p5AAh>RRpkcbaS2a?Fe&JqxDTp`dIW9;DL%0wxX5;`KxyA4F{(~_`93>NF@bj4LF!NC&D6Zm+Di$Q-tb2*Q z&csGmXyqA%Z9s(AxNO3@Ij=WGt=UG6J7F;r*uqdQa z?7j!nV{8eQE-cwY7L(3AEXF3&V*9{DpSYdyCjRhv#&2johwf{r+k`QB81%!aRVN<& z@b*N^xiw_lU>H~@4MWzgHxSOGVfnD|iC7=hf0%CPm_@@4^t-nj#GHMug&S|FJtr?i z^JVrobltd(-?Ll>)6>jwgX=dUy+^n_ifzM>3)an3iOzpG9Tu;+96TP<0Jm_PIqof3 zMn=~M!#Ky{CTN_2f7Y-i#|gW~32RCWKA4-J9sS&>kYpTOx#xVNLCo)A$LUme^fVNH z@^S7VU^UJ0YR8?Oy$^IYuG*bm|g;@aX~i60%`7XLy*AYpYvZ^F^U(!|RW z*C!rJ@+7TGdL=nNd1gv^%B+;Fcr$y)i0!GRsZXRHPs>QVGVR{9r_#&Qd(wL|5;H;> zD>HUw=4CF++&{7$<8G@j*nGjhEO%BQYfjeItp4mPvY*JYb1HKd!{HJ9*)(3%BR%{Pp?AM&*yHAJsW({ivOzj*qS!-7|XEn6@zo z3L*tBT%<4RxoAh>q{0n_JBmgW6&8hx?kL(_^k%VL>?xjAyrKBmSl`$=V|SK}ELl}@ zd|d0eo#RfG`bw9SK3%r4Y+rdvc}w}~ixV%tqawbdqvE-WcgE+BUpxMT%F@btm76MG zn=oQRWWuTm+a{dy)Oc2V4yX(@M{QAkx>(QB59*`dLT`Pz3Lsj9iB=HSHAiCq()ns|Cr)1*c605Cx}3V&x}Lg?b+6Q?)z7Kl zQh&1Hx`y6JY-Cwvd*ozeps}a1xAA0CR+Da;+O(i)P1C;SjOI}Dtmf6tPqo-Bl`U78 zv$kYgPntPp@G)n1an9tEoL*Vumu9`>_@I(;+5+fBa-*?fEx=mTEjZ7wq}#@Gd5_cW z!mP{N=yqEntDo)|>oy6{9cu+-3*GTnmb^`O0^FzRPO^&aG`f@F_R*aQ_e{F+_9%NW z4KG_B`@X3EVV9L>?_RNDMddA>w=e0KfAiw5?#i1NFT%Zz#nuv(&!yIU>lVxmzYKQ` zzJ*0w9<&L4aJ6A;0j|_~i>+y(q-=;2Xxhx2v%CYY^{} z^J@LO()eLo|7!{ghQ+(u$wxO*xY#)cL(|miH2_ck2yN{mu4O9=hBW*pM_()-_YdH#Ru{JtwJ^R2}3?!>>m1pohh zrn(!xCjE0Q&EH1QK?zA%sxVh&H99cObJUY$veZhQ)MLu-h%`!*G)s$2k;~+A z)Kk->Ri?`oGDEJEtI*wijm(s5f$W78FH{+qBxiU{~kq((J3uK{m z$|C8K#j-?hm8H@x%VfFqpnvu@xn1s%J7uNZC9C99a<_b1J|mx%)$%!6gPU|~<@2&m zz99GDp`|a%m*iggvfL;4%X;~WY>)@!tMWB@P`)k?$;0x9JSrRI8?s3rlgH(o@`OAo zn{f*gZ#t2u6K??hx|aElOM`Xd0t+SAIUEHvFw%?Wsm$s zUXq{6UU?a>Nc@@Xlb_2k9M1Ctr<#+O?yd}rv z_wu&=_t$!Yngd@N_AUj}T; z#*Ce|%XZr_sQcsWcsl{pCnnj+c8ZNIMmx<;w=-g$Q>BU;9k;w|zQ;4!W32Xg2Cd?{ zvmO3kuKQ^Hv;o>6ZHP8ZJ2`4~Bx?N;cf<0fi=!*G^^WzbTF3e$b&d^qqB{>nqLG81 zs94bBh%|Vj+hLu=!8(b9brJ>ZBns9^6s(gdSVyP9qnu2_I{Sg8j-rloG6{d`De5We zDe5WeY3ga}Y3ga}Y3ga}Y3ga}Y3ga}d8y~6o|k%F>UpW>rJk31Ug~+N=cS&HdOqs; zsOO`ek9t1p`Kafko{xGy>iMbXr=FjBxZMYc8a#gL`Kjlpo}YSt>iMY`pk9DF0qO*( z6QE9jIsxhgs1u-0kUBx8D@eT{^@7w3QZGooAoYUO3sNscy%6<6)C*BBM7L`dk$Xk%6}eZQXgo#!75P`>Uy*-B{uTLGUy*-B{uTLGUy*-B{uTLG))v8{5gt_uj9!t5)^yb-JtjRGrhi zYInOUNJxNyf_yKX01)K=WP|Si>HqEj|B{eUl?MR<)%<1&{(~)D+NPwKxWqT-@~snp zg9KCz1VTZDiS?UH`PRk1VPM{29cgT9=D?!Wc_@}qzggFv;gb@2cJQAYWWtpEZ7?y@jSVqjx${B5UV@SO|wH<<0; z{><1KdVI%Ki}>~<`46C0AggwUwx-|QcU;iiZ{NZu`ur>hd*|Hb(|6veERqxu=b@5Bab=rqptGxd{QJg!4*-i_$sES~)AB46}Fjg|ea#e@?J}z%CUJ zOsLWRQR1#ng^sD)A4FDuY!iUhzlgfJh(J@BRqd&P#v2B`+saBx>m+M&q7vk-75$NH%T5pi%m z5FX?`2-5l53=a&GkC9^NZCLpN5(DMKMwwab$FDIs?q>4!!xBS}75gX_5;(luk;3Vl zLCLd5a_8`Iyz}K}+#RMwu6DVk3O_-}n>aE!4NaD*sQn`GxY?cHe!Bl9n?u&g6?aKm z-P8z&;Q3gr;h`YIxX%z^o&GZZg1=>_+hP2$$-DnL_?7?3^!WAsY4I7|@K;aL<>OTK zByfjl2PA$T83*LM9(;espx-qB%wv7H2i6CFsfAg<9V>Pj*OpwX)l?^mQfr$*OPPS$ z=`mzTYs{*(UW^ij1U8UfXjNoY7GK*+YHht(2oKE&tfZuvAyoN(;_OF>-J6AMmS5fB z^sY6wea&&${+!}@R1f$5oC-2J>J-A${@r(dRzc`wnK>a7~8{Y-scc|ETOI8 zjtNY%Y2!PI;8-@a=O}+{ap1Ewk0@T`C`q!|=KceX9gK8wtOtIC96}-^7)v23Mu;MH zhKyLGOQMujfRG$p(s`(2*nP4EH7*J57^=|%t(#PwCcW7U%e=8Jb>p6~>RAlY4a*ts=pl}_J{->@kKzxH|8XQ5{t=E zV&o`$D#ZHdv&iZWFa)(~oBh-Osl{~CS0hfM7?PyWUWsr5oYlsyC1cwULoQ4|Y5RHA2*rN+EnFPnu z`Y_&Yz*#550YJwDy@brZU>0pWV^RxRjL221@2ABq)AtA%Cz?+FG(}Yh?^v)1Lnh%D zeM{{3&-4#F9rZhS@DT0E(WRkrG!jC#5?OFjZv*xQjUP~XsaxL2rqRKvPW$zHqHr8Urp2Z)L z+)EvQeoeJ8c6A#Iy9>3lxiH3=@86uiTbnnJJJoypZ7gco_*HvKOH97B? zWiwp>+r}*Zf9b3ImxwvjL~h~j<<3shN8$k-$V1p|96I!=N6VBqmb==Bec|*;HUg?) z4!5#R*(#Fe)w%+RH#y{8&%%!|fQ5JcFzUE;-yVYR^&Ek55AXb{^w|@j|&G z|6C-+*On%j;W|f8mj?;679?!qY86c{(s1-PI2Wahoclf%1*8%JAvRh1(0)5Vu37Iz z`JY?RW@qKr+FMmBC{TC7k@}fv-k8t6iO}4K-i3WkF!Lc=D`nuD)v#Na zA|R*no51fkUN3^rmI;tty#IK284*2Zu!kG13!$OlxJAt@zLU`kvsazO25TpJLbK&;M8kw*0)*14kpf*)3;GiDh;C(F}$- z1;!=OBkW#ctacN=je*Pr)lnGzX=OwgNZjTpVbFxqb;8kTc@X&L2XR0A7oc!Mf2?u9 zcctQLCCr+tYipa_k=;1ETIpHt!Jeo;iy^xqBES^Ct6-+wHi%2g&)?7N^Yy zUrMIu){Jk)luDa@7We5U!$$3XFNbyRT!YPIbMKj5$IEpTX1IOtVP~(UPO2-+9ZFi6 z-$3<|{Xb#@tABt0M0s1TVCWKwveDy^S!!@4$s|DAqhsEv--Z}Dl)t%0G>U#ycJ7cy z^8%;|pg32=7~MJmqlC-x07Sd!2YX^|2D`?y;-$a!rZ3R5ia{v1QI_^>gi(HSS_e%2 zUbdg^zjMBBiLr8eSI^BqXM6HKKg#@-w`a**w(}RMe%XWl3MipvBODo*hi?+ykYq)z ziqy4goZw0@VIUY65+L7DaM5q=KWFd$;W3S!Zi>sOzpEF#(*3V-27N;^pDRoMh~(ZD zJLZXIam0lM7U#)119Hm947W)p3$%V`0Tv+*n=&ybF&}h~FA}7hEpA&1Y!BiYIb~~D z$TSo9#3ee02e^%*@4|*+=Nq6&JG5>zX4k5f?)z*#pI-G(+j|jye%13CUdcSP;rNlY z#Q!X%zHf|V)GWIcEz-=fW6AahfxI~y7w7i|PK6H@@twdgH>D_R@>&OtKl}%MuAQ7I zcpFmV^~w~8$4@zzh~P~+?B~%L@EM3x(^KXJSgc6I=;)B6 zpRco2LKIlURPE*XUmZ^|1vb?w*ZfF}EXvY13I4af+()bAI5V?BRbFp`Sb{8GRJHd* z4S2s%4A)6Uc=PK%4@PbJ<{1R6+2THMk0c+kif**#ZGE)w6WsqH z`r^DL&r8|OEAumm^qyrryd(HQ9olv$ltnVGB{aY?_76Uk%6p;e)2DTvF(;t=Q+|8b zqfT(u5@BP);6;jmRAEV057E*2d^wx@*aL1GqWU|$6h5%O@cQtVtC^isd%gD7PZ_Io z_BDP5w(2*)Mu&JxS@X%%ByH_@+l>y07jIc~!@;Raw)q_;9oy@*U#mCnc7%t85qa4? z%_Vr5tkN^}(^>`EFhag;!MpRh!&bKnveQZAJ4)gEJo1@wHtT$Gs6IpznN$Lk-$NcM z3ReVC&qcXvfGX$I0nfkS$a|Pm%x+lq{WweNc;K>a1M@EAVWs2IBcQPiEJNt}+Ea8~WiapASoMvo(&PdUO}AfC~>ZGzqWjd)4no( ziLi#e3lOU~sI*XPH&n&J0cWfoh*}eWEEZW%vX?YK!$?w}htY|GALx3;YZoo=JCF4@ zdiaA-uq!*L5;Yg)z-_`MciiIwDAAR3-snC4V+KA>&V%Ak;p{1u>{Lw$NFj)Yn0Ms2*kxUZ)OTddbiJM}PK!DM}Ot zczn?EZXhx3wyu6i{QMz_Ht%b?K&-@5r;8b076YDir`KXF0&2i9NQ~#JYaq*}Ylb}^ z<{{6xy&;dQ;|@k_(31PDr!}}W$zF7Jv@f%um0M$#=8ygpu%j(VU-d5JtQwT714#f0z+Cm$F9JjGr_G!~NS@L9P;C1? z;Ij2YVYuv}tzU+HugU=f9b1Wbx3418+xj$RKD;$gf$0j_A&c;-OhoF*z@DhEW@d9o zbQBjqEQnn2aG?N9{bmD^A#Um6SDKsm0g{g_<4^dJjg_l_HXdDMk!p`oFv8+@_v_9> zq;#WkQ!GNGfLT7f8m60H@$tu?p;o_It#TApmE`xnZr|_|cb3XXE)N^buLE`9R=Qbg zXJu}6r07me2HU<)S7m?@GzrQDTE3UH?FXM7V+-lT#l}P(U>Fvnyw8T7RTeP`R579m zj=Y>qDw1h-;|mX-)cSXCc$?hr;43LQt)7z$1QG^pyclQ1Bd!jbzsVEgIg~u9b38;> zfsRa%U`l%did6HzPRd;TK{_EW;n^Ivp-%pu0%9G-z@Au{Ry+EqEcqW=z-#6;-!{WA z;l+xC6Zke>dl+(R1q7B^Hu~HmrG~Kt575mzve>x*cL-shl+zqp6yuGX)DDGm`cid! znlnZY=+a5*xQ=$qM}5$N+o!^(TqTFHDdyCcL8NM4VY@2gnNXF|D?5a558Lb*Yfm4) z_;0%2EF7k{)i(tTvS`l5he^KvW%l&-suPwpIlWB_Za1Hfa$@J!emrcyPpTKKM@NqL z?X_SqHt#DucWm<3Lp}W|&YyQE27zbGP55=HtZmB(k*WZA79f##?TweCt{%5yuc+Kx zgfSrIZI*Y57FOD9l@H0nzqOu|Bhrm&^m_RK6^Z<^N($=DDxyyPLA z+J)E(gs9AfaO`5qk$IGGY+_*tEk0n_wrM}n4G#So>8Dw6#K7tx@g;U`8hN_R;^Uw9JLRUgOQ?PTMr4YD5H7=ryv)bPtl=<&4&% z*w6k|D-%Tg*F~sh0Ns(h&mOQ_Qf{`#_XU44(VDY8b})RFpLykg10uxUztD>gswTH} z&&xgt>zc(+=GdM2gIQ%3V4AGxPFW0*l0YsbA|nFZpN~ih4u-P!{39d@_MN)DC%d1w z7>SaUs-g@Hp7xqZ3Tn)e z7x^sC`xJ{V<3YrmbB{h9i5rdancCEyL=9ZOJXoVHo@$$-%ZaNm-75Z-Ry9Z%!^+STWyv~To>{^T&MW0-;$3yc9L2mhq z;ZbQ5LGNM+aN628)Cs16>p55^T^*8$Dw&ss_~4G5Go63gW^CY+0+Z07f2WB4Dh0^q z-|6QgV8__5>~&z1gq0FxDWr`OzmR}3aJmCA^d_eufde7;d|OCrKdnaM>4(M%4V`PxpCJc~UhEuddx9)@)9qe_|i z)0EA%&P@_&9&o#9eqZCUCbh?`j!zgih5sJ%c4(7_#|Xt#r7MVL&Q+^PQEg3MBW;4T zG^4-*8L%s|A}R%*eGdx&i}B1He(mLygTmIAc^G(9Si zK7e{Ngoq>r-r-zhyygK)*9cj8_%g z)`>ANlipCdzw(raeqP-+ldhyUv_VOht+!w*>Sh+Z7(7(l=9~_Vk ztsM|g1xW`?)?|@m2jyAgC_IB`Mtz(O`mwgP15`lPb2V+VihV#29>y=H6ujE#rdnK` zH`EaHzABs~teIrh`ScxMz}FC**_Ii?^EbL(n90b(F0r0PMQ70UkL}tv;*4~bKCiYm zqngRuGy`^c_*M6{*_~%7FmOMquOEZXAg1^kM`)0ZrFqgC>C%RJvQSo_OAA(WF3{euE}GaeA?tu5kF@#62mM$a051I zNhE>u>!gFE8g#Jj95BqHQS%|>DOj71MZ?EYfM+MiJcX?>*}vKfGaBfQFZ3f^Q-R1# znhyK1*RvO@nHb|^i4Ep_0s{lZwCNa;Ix<{E5cUReguJf+72QRZIc%`9-Vy)D zWKhb?FbluyDTgT^naN%l2|rm}oO6D0=3kfXO2L{tqj(kDqjbl(pYz9DykeZlk4iW5 zER`)vqJxx(NOa;so@buE!389-YLbEi@6rZG0#GBsC+Z0fzT6+d7deYVU;dy!rPXiE zmu73@Jr&~K{-9MVQD}&`)e>yLNWr>Yh8CXae9XqfvVQ&eC_;#zpoaMxZ0GpZz7xjx z`t_Q-F?u=vrRPaj3r<9&t6K=+egimiJ8D4gh-rUYvaVy zG($v+3zk5sMuOhjxkH7bQ}(5{PD3Mg?!@8PkK&w>n7tO8FmAmoF30_#^B~c(Q_`4L zYWOoDVSnK|1=p{+@`Fk^Qb81Xf89_S`RSTzv(a4ID%71nll%{Wad$!CKfeTKkyC?n zCkMKHU#*nz_(tO$M)UP&ZfJ#*q(0Gr!E(l5(ce<3xut+_i8XrK8?Xr7_oeHz(bZ?~8q5q~$Rah{5@@7SMN zx9PnJ-5?^xeW2m?yC_7A#WK*B@oIy*Y@iC1n7lYKj&m7vV;KP4TVll=II)$39dOJ^czLRU>L> z68P*PFMN+WXxdAu=Hyt3g$l(GTeTVOZYw3KY|W0Fk-$S_`@9`K=60)bEy?Z%tT+Iq z7f>%M9P)FGg3EY$ood+v$pdsXvG? zd2q3abeu-}LfAQWY@=*+#`CX8RChoA`=1!hS1x5dOF)rGjX4KFg!iPHZE2E=rv|A} zro(8h38LLFljl^>?nJkc+wdY&MOOlVa@6>vBki#gKhNVv+%Add{g6#-@Z$k*ps}0Y zQ=8$)+Nm||)mVz^aa4b-Vpg=1daRaOU)8@BY4jS>=5n#6abG@(F2`=k-eQ9@u# zxfNFHv=z2w@{p1dzSOgHokX1AUGT0DY4jQI@YMw)EWQ~q5wmR$KQ}Y;(HPMSQCwzu zdli|G?bj(>++CP)yQ4s6YfpDc3KqPmquQSxg%*EnTWumWugbDW5ef%8j-rT#3rJu? z)5n;4b2c*;2LIW%LmvUu6t1~di~}0&Svy}QX#ER|hDFZwl!~zUP&}B1oKAxIzt~so zb!GaJYOb#&qRUjEI1xe_`@7qv_-LggQ$JE8+{ryT4%ldwC5ete+{G3C#g@^oxfY3#F zcLlj(l2G8>tC<5XWV|6_DZQZ7ow?MD8EZ9mM2oV~WoV-uoExmbwpzc6eMV}%J_{3l zW(4t2a-o}XRlU|NSiYn!*nR(Sc>*@TuU*(S77gfCi7+WR%2b;4#RiyxWR3(u5BIdf zo@#g4wQjtG3T$PqdX$2z8Zi|QP~I^*9iC+(!;?qkyk&Q7v>DLJGjS44q|%yBz}}>i z&Ve%^6>xY<=Pi9WlwpWB%K10Iz`*#gS^YqMeV9$4qFchMFO}(%y}xs2Hn_E}s4=*3 z+lAeCKtS}9E{l(P=PBI;rsYVG-gw}-_x;KwUefIB@V%RLA&}WU2XCL_?hZHoR<7ED zY}4#P_MmX(_G_lqfp=+iX|!*)RdLCr-1w`4rB_@bI&Uz# z!>9C3&LdoB$r+O#n);WTPi;V52OhNeKfW6_NLnw zpFTuLC^@aPy~ZGUPZr;)=-p|b$-R8htO)JXy{ecE5a|b{{&0O%H2rN&9(VHxmvNly zbY?sVk}@^{aw)%#J}|UW=ucLWs%%j)^n7S%8D1Woi$UT}VuU6@Sd6zc2+t_2IMBxd zb4R#ykMr8s5gKy=v+opw6;4R&&46$V+OOpDZwp3iR0Osqpjx))joB*iX+diVl?E~Q zc|$qmb#T#7Kcal042LUNAoPTPUxF-iGFw>ZFnUqU@y$&s8%h-HGD`EoNBbe#S>Y-4 zlkeAP>62k~-N zHQqXXyN67hGD6CxQIq_zoepU&j0 zYO&}<4cS^2sp!;5))(aAD!KmUED#QGr48DVlwbyft31WlS2yU<1>#VMp?>D1BCFfB z_JJ-kxTB{OLI}5XcPHXUo}x~->VP%of!G_N-(3Snvq`*gX3u0GR&}*fFwHo3-vIw0 zeiWskq3ZT9hTg^je{sC^@+z3FAd}KNhbpE5RO+lsLgv$;1igG7pRwI|;BO7o($2>mS(E z$CO@qYf5i=Zh6-xB=U8@mR7Yjk%OUp;_MMBfe_v1A(Hqk6!D})x%JNl838^ZA13Xu zz}LyD@X2;5o1P61Rc$%jcUnJ>`;6r{h5yrEbnbM$$ntA@P2IS1PyW^RyG0$S2tUlh z8?E(McS?7}X3nAAJs2u_n{^05)*D7 zW{Y>o99!I9&KQdzgtG(k@BT|J*;{Pt*b|?A_})e98pXCbMWbhBZ$t&YbNQOwN^=F) z_yIb_az2Pyya2530n@Y@s>s>n?L79;U-O9oPY$==~f1gXro5Y z*3~JaenSl_I}1*&dpYD?i8s<7w%~sEojqq~iFnaYyLgM#so%_ZZ^WTV0`R*H@{m2+ zja4MX^|#>xS9YQo{@F1I)!%RhM{4ZUapHTKgLZLcn$ehRq(emb8 z9<&Nx*RLcS#)SdTxcURrJhxPM2IBP%I zf1bWu&uRf{60-?Gclb5(IFI*!%tU*7d`i!l@>TaHzYQqH4_Y*6!Wy0d-B#Lz7Rg3l zqKsvXUk9@6iKV6#!bDy5n&j9MYpcKm!vG7z*2&4G*Yl}iccl*@WqKZWQSJCgQSj+d ze&}E1mAs^hP}>`{BJ6lv*>0-ft<;P@`u&VFI~P3qRtufE11+|#Y6|RJccqo27Wzr}Tp|DH z`G4^v)_8}R24X3}=6X&@Uqu;hKEQV^-)VKnBzI*|Iskecw~l?+R|WKO*~(1LrpdJ? z0!JKnCe<|m*WR>m+Qm+NKNH<_yefIml z+x32qzkNRrhR^IhT#yCiYU{3oq196nC3ePkB)f%7X1G^Ibog$ZnYu4(HyHUiFB`6x zo$ty-8pknmO|B9|(5TzoHG|%>s#7)CM(i=M7Nl=@GyDi-*ng6ahK(&-_4h(lyUN-oOa$` zo+P;C4d@m^p9J4c~rbi$rq9nhGxayFjhg+Rqa{l#`Y z!(P6K7fK3T;y!VZhGiC#)|pl$QX?a)a9$(4l(usVSH>2&5pIu5ALn*CqBt)9$yAl; z-{fOmgu><7YJ5k>*0Q~>lq72!XFX6P5Z{vW&zLsraKq5H%Z26}$OKDMv=sim;K?vsoVs(JNbgTU8-M%+ zN(+7Xl}`BDl=KDkUHM9fLlV)gN&PqbyX)$86!Wv!y+r*~kAyjFUKPDWL3A)m$@ir9 zjJ;uQV9#3$*`Dqo1Cy5*;^8DQcid^Td=CivAP+D;gl4b7*xa9IQ-R|lY5tIpiM~9- z%Hm9*vDV@_1FfiR|Kqh_5Ml0sm?abD>@peo(cnhiSWs$uy&$RYcd+m`6%X9FN%?w}s~Q=3!pJzbN~iJ}bbM*PPi@!E0eN zhKcuT=kAsz8TQo76CMO+FW#hr6da({mqpGK2K4T|xv9SNIXZ}a=4_K5pbz1HE6T}9 zbApW~m0C`q)S^F}B9Kw5!eT)Bj_h9vlCX8%VRvMOg8PJ*>PU>%yt-hyGOhjg!2pZR4{ z=VR_*?Hw|aai##~+^H>3p$W@6Zi`o4^iO2Iy=FPdEAI58Ebc~*%1#sh8KzUKOVHs( z<3$LMSCFP|!>fmF^oESZR|c|2JI3|gucuLq4R(||_!8L@gHU8hUQZKn2S#z@EVf3? zTroZd&}JK(mJLe>#x8xL)jfx$6`okcHP?8i%dW?F%nZh=VJ)32CmY;^y5C1^?V0;M z<3!e8GZcPej-h&-Osc>6PU2f4x=XhA*<_K*D6U6R)4xbEx~{3*ldB#N+7QEXD^v=I z+i^L+V7_2ld}O2b-(#bmv*PyZI4|U#Q5|22a(-VLOTZc3!9ns1RI-? zA<~h|tPH0y*bO1#EMrsWN>4yJM7vqFZr?uw$H8*PhiHRQg1U9YoscX-G|gck+SSRX!(e7@~eeUEw+POsT;=W9J&=EV`cUc{PIg_#TQVGnZsQbCs7#Q-)v#BicxLw#Fb?#)8TYbu zN)5R=MI1i7FHhF|X}xEl=sW~`-kf;fOR^h1yjthSw?%#F{HqrY2$q>7!nbw~nZ8q9 zh{vY! z%i=H!!P&wh z7_E%pB7l5)*VU>_O-S~d5Z!+;f{pQ4e86*&);?G<9*Q$JEJ!ZxY;Oj5&@^eg0Zs!iLCAR`2K?MSFzjX;kHD6)^`&=EZOIdW>L#O`J zf~$M4}JiV}v6B-e{NUBGFgj-*H%NG zfY0X(@|S8?V)drF;2OQcpDl2LV=~=%gGx?_$fbSsi@%J~taHcMTLLpjNF8FkjnjyM zW;4sSf6RHaa~LijL#EJ0W2m!BmQP(f=%Km_N@hsBFw%q#7{Er?y1V~UEPEih87B`~ zv$jE%>Ug9&=o+sZVZL7^+sp)PSrS;ZIJac4S-M>#V;T--4FXZ*>CI7w%583<{>tb6 zOZ8gZ#B0jplyTbzto2VOs)s9U%trre`m=RlKf{I_Nwdxn(xNG%zaVNurEYiMV3*g| z``3;{j7`UyfFrjlEbIJN{0db|r>|LA@=vX9CHFZYiexnkn$b%8Rvw0TZOQIXa;oTI zv@j;ZP+#~|!J(aBz9S{wL7W%Dr1H)G-XUNt9-lP?ijJ-XEj1e*CI~-Xz@4(Xg;UoG z{uzBf-U+(SHe}6oG%;A*93Zb=oE>uTb^%qsL>|bQf?7_6=KIiPU`I|r;YcZ!YG7y~ zQu@UldAwz$^|uoz3mz1;An-WVBtefSh-pv<`n&TU3oM!hrEI?l@v8A4#^$4t&~T32 zl*J=1q~h+60sNc43>0aVvhzyfjshgPYZoQ(OOh>LbUIoblb@1z~zp?))n?^)q6WGuDh}gMUaA9|X z3qq-XlcNldy5==T4rq*~g@XVY!9sYZjo#R7 zr{n)r5^S{9+$+8l7IVB*3_k5%-TBY@C%`P@&tZf>82sm#nfw7L%92>nN$663yW!yt zhS>EfLcE_Z)gv-Y^h1;xj(<4nD4GY{C-nWUgQc9cMmH{qpa!uEznrGF^?bbJHApScQ$j>$JZHAX80DdXu z--AMgrA0$Otdd#N9#!cg2Z~N8&lj1d+wDh+^ZObWJ$J)_h(&2#msu>q0B$DEERy{1 zCJN{7M@%#E@8pda`@u!v@{gcT3bA*>g*xYLXlbb&o@1vX*x+l}Voys6o~^_7>#GB| z*r!R%kA9k%J`?m>1tMHB9x$ZRe0$r~ui}X}jOC)9LH=Po*2SLdtf3^4?VKnu2ox&mV~0oDgi` z;9d}P$g~9%ThTK8s}5ow2V4?(-lU*ed8ro|}mU}pk% z;bqB0bx3AOk<0Joeh}Vl@_7Po&C`Cg>>gff>e7fu41U3Ic{JQu1W%+!Gvz3GDO2ixKd;KF6UEw8F_cDAh08gB>@ zaRH2Q96sBJ>`4aXvrF0xPtIWoA1pPsRQtU~xDtnEfTJnl{A9u5pR^K8=UdNq%T8F$)FbN> zgK+_(BF#D>R>kK!M#OT~=@@}3yAYqm33?{Bv?2iBr|-aRK0@uapzuXI)wE0=R@m^7 zQ`wLBn(M*wg!mgmQT1d!@3<2z>~rmDW)KG0*B4>_R6LjiI0^9QT8gtDDT|Lclxppm z+OeL6H3QpearJAB%1ellZ6d*)wBQ(hPbE=%?y6i^uf%`RXm*JW*WQ%>&J+=V(=qf{ zri~yItvTZbII+7S0>4Q0U9@>HnMP$X>8TqAfD(vAh};2P{QK)ik`a6$W$nG<{bR2Ufd!^iE z#1K58$gW!xpeYHeehuhQCXZ9p%N8m zB+l~T_u-Ycr!U>!?xu!!*6rNxq37{`DhMMfY6NpD3Jw zkYQDstvt30Hc_SaZuuMP2YrdW@HsPMbf^Y9lI<9$bnMil2X7`Ba-DGLbzgqP>mxwe zf1&JkDH54D3nLar2KjJ3z`*R+rUABq4;>>4Kjc2iQEj7pVLcZYZ~pteAG4rm1{>PQy=!QiV5G|tVk)53 zP?Azw+N)Yq3zZ`dW7Q9Bq@Y*jSK0<1f`HM;_>GH57pf_S%Ounz_yhTY8lplQSM`xx zU{r-Deqs+*I~sLI$Oq`>i`J1kJ(+yNOYy$_>R3Jfi680<|^u#J@aY%Q>O zqfI~sCbk#3--^zMkV&Yj0D(R^rK}+_npgPr_4^kYuG=pO%$C_7v{s@-{M-P@RL3^<`kO@b=YdKMuccfO1ZW# zeRYE%D~CMAgPlo?T!O6?b|pOZv{iMWb;sN=jF%=?$Iz_5zH?K;aFGU^8l7u%zHgiy z%)~y|k;Es-7YX69AMj^epGX#&^c@pp+lc}kKc`5CjPN4Z$$e58$Yn*J?81%`0~A)D zPg-db*pj-t4-G9>ImW4IMi*v#9z^9VD9h@9t;3jMAUVxt=oor+16yHf{lT|G4 zya6{4#BxFw!!~UTRwXXawKU4iz$$GMY6=Z8VM{2@0{=5A0+A#p6$aT3ubRyWMWPq9 zCEH5(Il0v4e4=Yxg(tDglfYAy!UpC>&^4=x7#6_S&Ktds)a8^`^tp6RnRd{KImB^o z2n=t#>iKx<*evmvoE{+fH#@WXGWs$)Uxrtf?r>AaxV0?kf0o@oDboJ6z0cgP@A$;k>SK1UqC?Q_ zk_I?j74;}uNXhOf_5ZxQSgB4otDEb9JJrX1kq`-o%T>g%M5~xXf!2_4P~K64tKgXq z&KHZ0@!cPvUJG4kw-0;tPo$zJrU-Nop>Uo65Pm|yaNvKjhi7V1g98;^N1~V3% zTR>yWa+X2FJ_wpPwz3i^6AGwOa_VMS-&`*KoKgF2&oR10Jn6{!pvVG@n=Jk@vjNuY zL~P7aDGhg~O9G^!bHi$8?G9v9Gp0cmekYkK;(q=47;~gI>h-kx-ceM{ml$#8KI$4ltyjaqP zki^cyDERloAb)dcDBU4na9C(pfD{P@eBGA}0|Rb)p{ISqi60=^FUEdF!ok{Gs;vb) zfj9(#1QA64w*ud^YsN5&PeiI>c`VioE8h)e}W%S9NMA55Gs zrWL6l+@3CKd@8(UQLTwe12SGWMqRn+j)QZRj*g)Xua)%ayzpqs{pD(WWESJYL3{M$ z%qkpM`jFoqLYVv6{IbCkL?fEiJj$VG=$taup&RL9e{s(Sgse2xVJlw0h74EXJKt2eX|dxz{->0)3W`JN7Bv!rLvRZc z0tAOZ2yVe4g9iq826qXAg`f!*+}(o1;1FDb>kKexumFS40KvK0yH1_@Z=LgWZ+}(Y zwYsa;OLz6tTA%gS=>8$=Z7pLh>|K2QElL)E=Q*(n*H`8R`8={-@4mTD-SWBOYRxV? zmF(-rJB8^Wlp?319rTrh^?QEP?|Msxrv?WbJ-+id+V#F2Y4(JPJ6U9bv+U1cIIH^W z)lg$_=g^Ma>2~Pyd_YOAv29Cb-U6DJO?NxnW7~QP*SmYi*vdUVuW#LWQ_u0`hymZi zaQS3Nb^4`ro$>0G%zbXmr5|D|iq0R<;S@?kr0j5Ruq87-Z1>crx%EzVZ9#U;{?}ti zW2W%*9MQg3Nbh%Ti6LhDd|-aFSgXoPG`mHlUU1iCHr>ru>DX?W_#13(`u*!Plu2OP z6jk=2>BC0l)aw;HCmxoYD1i4b%m$1`DYC_^L~ zIEAnFcHvad=-aO3(_MI=9#`z6-9*_!&$?<%meb5;jGd5Qp=MGf z6BD{%`L#TAOq%z%@*ib95Ey7NbUF=BlszVk3Iu3imD&*91N-ij%hW?W@~2TtdHTfP z#n0@Xd7X8Dyu36n{k#PwQ~T~X7mAO^cNV+z<HO@3X-# z_@rAn$k~(l@kciCC;&Qd*fWRI>=;fL{UPlciNDWyj$bX<#r^(r;EE8wwUVQm&7~QY zCXRj!**r^xybAEPq>h3W$uvI1j=yNIyzkE_D7fpGw)OV{U*Uwm{xB;mEg2(|y|ICd zMdQVqzMb-=XM6|E-a9kNh)^9lY`-DjhhHD1w5lufRcy+QLgJ47!fFne86#F; zX{ufroVBEZJOY?rDo!;Te6aOZ^1SO!dYRxQ*2njyA~dCWawn)>!*k7~>8Ikt&e*0>>V5ZbO|*1+2LFOqVe zXHb!aMk03^h%&9L8GMy7UDI2Kev>V@(R}*Iu6x+!Hn4~D@wj`P%#Hdbf(lK{+DD7f zJ&(v*mhn_e(R$^5L#bM^^Q@-!*b!l|+Xrb(q*MRFJYnrE7*xko!SJOy9LngR2|q5k zY`Ioiu+YBfzF{Labszk-E#*BYQk>$()=xWEGZRKwY)*UxP}0dGuPLZOkNJDI9Hy zFjfwiK6RjhH#rHW#B0(MW}i%V`943<6@Z*Nd^JEP5uZonXm=u%AM>{H^U@&Jy*i0s za_Da^xI6pMtXzHc{e~_ZcnKP*;=YL2Z^RmzDl{dJTk7*}E_h*NvgnhnxVKB59Duh~ zqouS_WoOR*{UvUw_K#OWz;gMracr%8>QQ&V*jv!8)ho;U8}9~8EU{N<=Z_gR%IpMT zbkePUG_afm=#|iIfFmdqkpLMGxY5D$`?I}&T7>TexU@v zkBx09kG)O;09ckj#(_Uov6vv{{HOcr-%H#DUQ@*GzF8Zh{iSM13%fuB%>wjdU@3Nf zlnYE!GTyNrqes|;nLFXfWU*Wg-9wmr=NBd$nCk+H?iwNvcd0Wab^3CT9a`>3V~oWI z9=_H+N-Q=MQ(io4u4mpdQ;k&5FXnKV5M7R`@WJ9h(GrAirO#XXOU{qQpk^B^Vd=Dt{wiqT zg-#j9J~@o%H2;W9mg)o6@*Vo;BSs2*4HAHpDk02mndAsov08R_48zJZ@J)s7+hyCo zy*0L#y)?AqZt-wX%+_Vx`8*A95OLHvs1$k~{h-_N_vov_gHJE=`X>L?5K+ zD?u59=mjtImMvd1GsDytuYp{IyUkW&?h zF>$#`n$~bZ)KN0B$XGeMYh&`;g8 zo_2-koaO6+8O!+L>SpIQbG(i;QW9UJi{Ecewlo?s&D!^>i$|#jaW}#HJuxt|W48=? zb^Y&O$a1s5ddr8DIt!sD!t=y1g(d4GR(s;s-HfV$GXl&m;+sAAxB^rk(3_NjE$p#L z*t4em?tA0d+XwRxN^OQwzbDZMuSE0J1)Ky{mq)^t4bnSl*)s>zNM@mMdtd78&ebHN z`!(|lE5q-p+TsRaNnMXwALaN5QIZ2IUi^Z22tsN5>nvIO+YU}Q*xh6}ee6@rR~<&1 z(PB4z>9ZBUMXZwSMmd9-aKKsmJeJq^G|#JclOh*xf0?^e0(`40nsg1z)(48;4}B_( zGwPI)yo|{oX{dVDL-5-aMGr;~vU1cPtJP5JM(sswz&Q`e<@0?y{YhsO9YK8EYJA;L z>7oG_Mts+(wCBC*Md82#XdKw&J*IizR?9k^rf1r{Ot-&>V^ke{9nI9zavlcNkIJtN z7T>?o|4rENk-?|lewZ(EfdR;%BUrzKJ^UkCpsM)EA9QHBVV8trT&*O(9?FO{MLTFL z=5P0H+T6C^jAuX0k4U;~GM!x`!X2N~3_n?qXY$HI>x@(DHEy&Q3ucT1R6fj28wX!I zC=&d$@bJ_v^%?W2Ngl}e8ww`b%BrN-PzGH;$@B2Ky1?%GMkm#~Okj(-Admyy;qya| zOi73kr_pwt?5Nj3p=&H>81!w#>Agj z(QXx{j0r=pTl>micAI_5vUw<3`Sht?Z}-j2Wx~F8DKCUQrsXl2?W8hur42(F_ zsSJ)_36&x6A|YkY6c<2a94SXbv~d>4CC4nkDPvf9Z5Fys^6^5r0j5=E>Cgy_Dk@tS z%?c}9!qB?t6t8(XMH%le8UeNWp@Nsma~Ql+^3Bo%_npMryeQJz4V=BAqE~T?dejng z3ge{fjCHoNAfYBvsfq;G%VL|j7t z`X0sy1EEgpyD;)tS1x+fnv-?C@glP0{RCW}Ma?3qpoq_&IJAYOy3G#s`rsh5=3>`K zkj``=;|*x5HSjZC zXNvPLh372q;=+6ja|SC!R-`JcL}}wwskajjTUGTpL(1zkN-p?BA2lmf+J3WsB7!k`0Brx8^cLTF9h)r+LZ$vsZo}`OpOs)?c6$hclR!R#MAeh|_DY|9r zy+_3c%IO9h9X?ksp?an&>Lw;QeQ`T-Ku6HaK~H?E9-Z5$cZu{YU;1+-6B$|JD;%!^ zt(4l>F8}a-UkC4YtOxFHckhl4VKr6P$P_O*U!)IDory%}Wz`YeFx6TO{y2Y${SBm?H9cTWV=WWJ z`_*CGso!ZN>l@~_jkeXtV}fczfA{TUkyeD>)i3|NFGcCsBmK3HXp&ol_@GVs7PIpfULy!hi zs+%KYgS%(n7_z_}6)hblk~W#LZ@&2)fwm6xkFP%&Ju|MFWbNiTwy{{g-pV1RK`L&=RE2D z4|g;~vd8xd|teYS%w!IlT4W$&FTrk-hcTADX!P?*f1YWEIRwq$Ys%^(Z9w&HT$>} zsMD#6Df=uJrX!JHP7<>Or;e_Cf=}`!`qR=i8fBj)$6Lxx{HRzd8Tnzd0p>kSps{OG zKJkml>bUj8$u|F=``l(-aMxWBC@CGZ#FXClQZ<4|&%jN}Tkg#q8z)=>Ly{$i0`rjU zvt|QddO&i=91e?h3>s~i;+6{ z8X4i6a1wDLrSuE#W(zhan+U*Zq+8p3a))JFVF4ffaV51K^YgTso~3;Y*NmM; zx8T?y-N0uyWY(8=me-HUC9xtABvX5~%yg+Cp&XF$Bq=OcK6T*D7eZ2EmIoCFWm{$S z1PNw8HDpe5hHeCusN8kdeb&f2#=3M^A~7YwJ7FRrhq*)PG9x?JIAaC{MV}5}g#7R$-Ly%)4=IUkRCGOR|XTMjn&okRmFjaO^YF5^* z@)#MCBOBezD)*xQNxydlUyN?dW{fS(s-T`gv*0BEnk}`BdmrbmPO8q8y(X$AA}*RH%I7Av!~84pudHb&%Q5-j zt?=6x(iR?<^_7X0v6Ys#VAL}dKk^hcjI=|EY;kPcZ_w<*H`_*|N7SacaM1ERD@6ab zg`!iTm7$URV+lpW_{V$ruR&A>jrX68k4x2wo$45}&wf7o<|o(@B!u-L@bKyQBAGwy z4#}UrRAu>^>Vb6k2-th^>WjvP;Nl|i3WrjWv3ISkj{m{eAcQIW^_ndxSX@|8T(ASJ z?_$fcP2u*6uOBk-{d>^ z0vWlfGQMvysI%R=iE|A+!!Nw?C917EU*_$`;;)px?s83CRd3i_jBN)k#nR5t$dJ(+ z_sP;wG@Ad)^(3LRj7q}0b2O(b`|i0~5SYb%Sjk^*5ISZ-Ab+}DGu$-X1n^TF1Ndw_ zF|e*1)cI2%`TR&AW~XpqpFb!=3cHbS>np9hYD_Mr5}y5Y`SY^r7isA2Q4(z zazRQEqWDKT2zIEbjSYdCPi1ZOGz80Nsl}gxO^DWMY0AV<2K&OL{&^6#@L1?lXu#6xSMh%3^5c*}oM6DQGY#(a^@z<&D zF(43I9e&5`h|A$5!+UFuOH0>F3$shBV4`0#M4RSB8=6F0ZgIbq<2LQ$Hh^(kAJu=! zt8ZGXTacD{(3W{V1$j_{Jc)Ka7t6u}ho`4kF+4@t_0!mCBn z)}o%eA}L)_L?=jw6BIfll7tb3n}?*yLt&XADa=rW>qz=_6s9ziOd5sXjil>FVFx3r zf>Feewk0v#W9>Gp4GacTRr>Sd2T6dWi-{YX`v!D)kCWzG5xQB=?es5ON(%nkwUhNl zV>@xkWWWv*N+{e$(SrExvN6BXzU(Hxlx27{VYHf+LpIbTO+Yu(ltMk<;)3A(LU@ytVYFkYvTa79idMtUFhfxx?P!)2F`prNWW#Fub#l>N2s@nh&n_ zA4{#}|AIs9|A4P0ZF%fy=hDN!t#ifH<)4u2kirK~JUpjQ-J+~cXOZI&dIts;P}UeXslP6zKvpEKSN-$y>kJ^nw2tC9bv zo(|lT@?vZ!{_l|d^8Yh)eEBh*5ABh+Lzjw+?V)o z#P-W7361>E(Y4;@`sv;VKn G`u_lkUM?>H literal 0 HcmV?d00001 diff --git a/cmm/cmm/bootstrap/fonts/glyphicons-halflings-regular.woff2 b/cmm/cmm/bootstrap/fonts/glyphicons-halflings-regular.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..64539b54c3751a6d9adb44c8e3a45ba5a73b77f0 GIT binary patch literal 18028 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 literal 0 HcmV?d00001 diff --git a/cmm/cmm/bootstrap/js/bootstrap.min.js b/cmm/cmm/bootstrap/js/bootstrap.min.js new file mode 100644 index 0000000..9bcd2fc --- /dev/null +++ b/cmm/cmm/bootstrap/js/bootstrap.min.js @@ -0,0 +1,7 @@ +/*! + * Bootstrap v3.3.7 (http://getbootstrap.com) + * Copyright 2011-2016 Twitter, Inc. + * Licensed under the MIT license + */ +if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1||b[0]>3)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){if(a(b.target).is(this))return b.handleObj.handler.apply(this,arguments)}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.7",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a("#"===f?[]:f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.7",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c).prop(c,!0)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c).prop(c,!1))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")?(c.prop("checked")&&(a=!1),b.find(".active").removeClass("active"),this.$element.addClass("active")):"checkbox"==c.prop("type")&&(c.prop("checked")!==this.$element.hasClass("active")&&(a=!1),this.$element.toggleClass("active")),c.prop("checked",this.$element.hasClass("active")),a&&c.trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active")),this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target).closest(".btn");b.call(d,"toggle"),a(c.target).is('input[type="radio"], input[type="checkbox"]')||(c.preventDefault(),d.is("input,button")?d.trigger("focus"):d.find("input:visible,button:visible").first().trigger("focus"))}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.7",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c=this.getItemIndex(b),d="prev"==a&&0===c||"next"==a&&c==this.$items.length-1;if(d&&!this.options.wrap)return b;var e="prev"==a?-1:1,f=(c+e)%this.$items.length;return this.$items.eq(f)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(".item.active"));if(!(a>this.$items.length-1||a<0))return this.sliding?this.$element.one("slid.bs.carousel",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?"next":"prev",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){if(!this.sliding)return this.slide("next")},c.prototype.prev=function(){if(!this.sliding)return this.slide("prev")},c.prototype.slide=function(b,d){var e=this.$element.find(".item.active"),f=d||this.getItemForDirection(b,e),g=this.interval,h="next"==b?"left":"right",i=this;if(f.hasClass("active"))return this.sliding=!1;var j=f[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:h});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(f)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:h});return a.support.transition&&this.$element.hasClass("slide")?(f.addClass(b),f[0].offsetWidth,e.addClass(h),f.addClass(h),e.one("bsTransitionEnd",function(){f.removeClass([b,h].join(" ")).addClass("active"),e.removeClass(["active",h].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trigger(m)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}};a(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){var c,d=b.attr("data-target")||(c=b.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data("bs.collapse"),f=a.extend({},d.DEFAULTS,c.data(),"object"==typeof b&&b);!e&&f.toggle&&/show|hide/.test(b)&&(f.toggle=!1),e||c.data("bs.collapse",e=new d(this,f)),"string"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a('[data-toggle="collapse"][href="#'+b.id+'"],[data-toggle="collapse"][data-target="#'+b.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION="3.3.7",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0},d.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},d.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b,e=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(e&&e.length&&(b=e.data("bs.collapse"),b&&b.transitioning))){var f=a.Event("show.bs.collapse");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,"hide"),b||e.data("bs.collapse",null));var g=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[g](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var h=function(){this.$element.removeClass("collapsing").addClass("collapse in")[g](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return h.call(this);var i=a.camelCase(["scroll",g].join("-"));this.$element.one("bsTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var e=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass("in");a.attr("aria-expanded",c),b.toggleClass("collapsed",!c).attr("aria-expanded",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(d){var e=a(this);e.attr("data-target")||d.preventDefault();var f=b(e),g=f.data("bs.collapse"),h=g?"toggle":e.data();c.call(f,h)})}(jQuery),+function(a){"use strict";function b(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function c(c){c&&3===c.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=b(d),f={relatedTarget:this};e.hasClass("open")&&(c&&"click"==c.type&&/input|textarea/i.test(c.target.tagName)&&a.contains(e[0],c.target)||(e.trigger(c=a.Event("hide.bs.dropdown",f)),c.isDefaultPrevented()||(d.attr("aria-expanded","false"),e.removeClass("open").trigger(a.Event("hidden.bs.dropdown",f)))))}))}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.3.7",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=b(e),g=f.hasClass("open");if(c(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(document.createElement("div")).addClass("dropdown-backdrop").insertAfter(a(this)).on("click",c);var h={relatedTarget:this};if(f.trigger(d=a.Event("show.bs.dropdown",h)),d.isDefaultPrevented())return;e.trigger("focus").attr("aria-expanded","true"),f.toggleClass("open").trigger(a.Event("shown.bs.dropdown",h))}return!1}},g.prototype.keydown=function(c){if(/(38|40|27|32)/.test(c.which)&&!/input|textarea/i.test(c.target.tagName)){var d=a(this);if(c.preventDefault(),c.stopPropagation(),!d.is(".disabled, :disabled")){var e=b(d),g=e.hasClass("open");if(!g&&27!=c.which||g&&27==c.which)return 27==c.which&&e.find(f).trigger("focus"),d.trigger("click");var h=" li:not(.disabled):visible a",i=e.find(".dropdown-menu"+h);if(i.length){var j=i.index(c.target);38==c.which&&j>0&&j--,40==c.which&&jdocument.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&a?this.scrollbarWidth:"",paddingRight:this.bodyIsOverflowing&&!a?this.scrollbarWidth:""})},c.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:"",paddingRight:""})},c.prototype.checkScrollbar=function(){var a=window.innerWidth;if(!a){var b=document.documentElement.getBoundingClientRect();a=b.right-Math.abs(b.left)}this.bodyIsOverflowing=document.body.clientWidth
',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){if(this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(a.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusin"==b.type?"focus":"hover"]=!0),c.tip().hasClass("in")||"in"==c.hoverState?void(c.hoverState="in"):(clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show())},c.prototype.isInStateTrue=function(){for(var a in this.inState)if(this.inState[a])return!0;return!1},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);if(c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusout"==b.type?"focus":"hover"]=!1),!c.isInStateTrue())return clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide()},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var d=a.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!d)return;var e=this,f=this.tip(),g=this.getUID(this.type);this.setContent(),f.attr("id",g),this.$element.attr("aria-describedby",g),this.options.animation&&f.addClass("fade");var h="function"==typeof this.options.placement?this.options.placement.call(this,f[0],this.$element[0]):this.options.placement,i=/\s?auto?\s?/i,j=i.test(h);j&&(h=h.replace(i,"")||"top"),f.detach().css({top:0,left:0,display:"block"}).addClass(h).data("bs."+this.type,this),this.options.container?f.appendTo(this.options.container):f.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.getPosition(this.$viewport);h="bottom"==h&&k.bottom+m>o.bottom?"top":"top"==h&&k.top-mo.width?"left":"left"==h&&k.left-lg.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;jg.right&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){if(!this.$tip&&(this.$tip=a(this.options.template),1!=this.$tip.length))throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!");return this.$tip},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),b?(c.inState.click=!c.inState.click,c.isInStateTrue()?c.enter(c):c.leave(c)):c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){var a=this;clearTimeout(this.timeout),this.hide(function(){a.$element.off("."+a.type).removeData("bs."+a.type),a.$tip&&a.$tip.detach(),a.$tip=null,a.$arrow=null,a.$viewport=null,a.$element=null})};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;!e&&/destroy|hide/.test(b)||(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.3.7",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:''}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){this.$body=a(document.body),this.$scrollElement=a(a(c).is(document.body)?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",a.proxy(this.process,this)),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.3.7",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b=this,c="offset",d=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),a.isWindow(this.$scrollElement[0])||(c="position",d=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var b=a(this),e=b.data("target")||b.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[c]().top+d,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b=e[a]&&(void 0===e[a+1]||b .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),b.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),h?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu").length&&b.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),e&&e()}var g=d.find("> .active"),h=e&&a.support.transition&&(g.length&&g.hasClass("fade")||!!d.find("> .fade").length);g.length&&h?g.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),"show")};a(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.3.7",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&"top"==this.affixed)return e=a-d&&"bottom"},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=Math.max(a(document).height(),a(document.body).height());"object"!=typeof d&&(f=e=d),"function"==typeof e&&(e=d.top(this.$element)),"function"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css("top","");var i="affix"+(h?"-"+h:""),j=a.Event(i+".bs.affix");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin="bottom"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace("affix","affixed")+".bs.affix")}"bottom"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery); \ No newline at end of file diff --git a/cmm/cmm/cmm.png b/cmm/cmm/cmm.png new file mode 100644 index 0000000000000000000000000000000000000000..7cbb408fa94efa4ef3b55b1100ec8d8d529762ae GIT binary patch literal 1950 zcmV;P2VwY$P)(-_3*g3oO3rJ$Qc<+tB~TP+QRqW5e~KIy&X_MGqM zJnlXBQVz$C7XXaQ;KPTUE1jK@Et@yLU!I(-mihZ1-|FaiF$2j92V)0V(bd}~5SWC`M-)f_Qb@uh#mG+NYcBUv>&lhcw=Z4trzUWtt81nv zK3;DtuyyO&3S5HhBB7Dph!QD9RETEMqzk7~QZ^3Uy5-8Mz>!UxKFoG>{CTY5U>(@p zx?=@aBjqGGQh{iZN@TyU@5!rGRf|{?$PtUrCC->$KS-V{=|mq&l3oGSrcfNN>jeTkz`3Gp9eWYufZZ8 z&jwjpsaQU4C0;<|nKPJQx_@ejOXzZe0m2ilU;r?%%uT%$fk1P<_|03v+#ZuF(#k z>FRp>*K_B>sGLSy6BC>CxQpW$aEyayiW}$yy&=cR5q6Nuku6q%vZqdk{2(zXf<#at z4uB$&FO&odq11mWD81bwAHR$92yotj8aa%0P`eJaB_$o)i@T3-dj=W<{NTV87trDU z9>l<)W2ljY!J&E2!=Y!NgF|!XKyySmG*6d6bFc{NeT7i#&I8Lbk0dA8(G+O3tgMpn z4th6_Q3c30=`E9Z8XP79F{2CAxK0`&(7t4eiKamPqwpl$RBxL-U>2we2^|)&(E|rO zT!xO*G36dxy3|Nhpw29Sr%2f7#043S<6@s@V7Jf%%Kf}SA0h^WSOj=ZAEGKa6lx=* zp?XF*m?RR|9~=bx@b88|5omn_AV(4eDR^7~Q||F)%XHKPjx1h$z$}30`k{))B8{2U zX?7f|V9GtQVnsPM0UV#TW`QiL03Rcp5jmF&YEMt74GDqPxpSc-ApwrY#X;k&S)dCH zgaUVW*y`W_8?3&c$CP_=)hZ=Tff};_UTI+)x#&!u3r?=tc^;a5WQ7dXVcTuX$tIRYs}l?TxMn(O#y?sqFv0jz#1|n za+&d6$e>_8liBzVA%`iqJ1Z-dnn1^Euj$PKDn^35YnZi+!HyO-FzYBX?3Bz2fGi{O znZNhQyIDguA~_~T5IKyZV$KyzGN z)1BVl0M-RsUVO1yM>#yXN>^|=_m8~shL&}KeIX$~sX4>zcYBr$6NRiwN%>@HvVYE; zQ>+UZLPNXFk4j31TMFttT%Wqd$@3%gqsm8figx& zkNZYsw6F)fy`U{>HXI5KhI$`QD8u8(LauNWjIpstSr^dGo_(6E7;TZqK(-5*AVthO z*)MQ-d`zwdg)V$3c6A-`nIS&Dm34vg=;&|Bdft)}Hy&t3La3Y`0(+t&K^qg80{LgyPB6Epn%FQ?*1_A=g6X)_-on>;*z zKdDmDyB{Fj>+g4ImCN6g&YJc8dTcEOo|3_=sHm=HsWj!zAAgMa@dp)w5x-Qqcu{mh zrFv`Mx^=RhIPrEwMEtNxAh@2&yOHWTf kZ8W}m>)JKp)BIZHU(E_$&%v#~vj6}907*qoM6N<$f;R7#hyVZp literal 0 HcmV?d00001 diff --git a/cmm/cmm/cmm.svg b/cmm/cmm/cmm.svg new file mode 100644 index 0000000..8cf574a --- /dev/null +++ b/cmm/cmm/cmm.svg @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cmm/cmm/configserver.css b/cmm/cmm/configserver.css new file mode 100644 index 0000000..ec8984a --- /dev/null +++ b/cmm/cmm/configserver.css @@ -0,0 +1,128 @@ +.icon-configserver { + color: #990000; +} +.btn-default:active, +.btn-default:visited, +.btn-default:focus, +.btn-default { + background:#FFFFFF; + border-radius:3px; + border:1px solid #A6C150; + color:#990000 !important; +} +.btn-default:hover { + border:1px solid #A6C150; + background: #F5F5F5; +} +input[type=text], select { + -webkit-transition: all 0.30s ease-in-out; + -moz-transition: all 0.30s ease-in-out; + -ms-transition: all 0.30s ease-in-out; + -o-transition: all 0.30s ease-in-out; + transition: all 0.30s ease-in-out; + border-radius:3px; + outline: none; + padding: 3px 0px 3px 3px; + margin: 5px 1px 3px 0px; + border: 1px solid #990000; +} +input[type=text]:focus, select:focus { + box-shadow: 0 0 5px #CC0000; + padding: 3px 0px 3px 3px; + margin: 5px 1px 3px 0px; + border: 1px solid #990000; +} +.td-btn { + width: 200px; +} +.td-text { +} +th { + background: #F4F4EA; +} +.table tbody>tr>td { + vertical-align: middle; +} +.panel-default > .panel-heading-cxs { + font-weight: bold; + background: #F4F4EA; +} +.panel-default > .panel-footer-cxs { + font-weight: bold; + background: #F4F4EA; +} +#loader { + position: absolute; + left: 50%; + top: 50%; + z-index: 1; + margin: -75px 0 0 -75px; + border: 16px solid #F4F4EA; + border-radius: 50%; + border-top: 16px solid #990000; + border-bottom: 16px solid #990000; + width: 120px; + height: 120px; + -webkit-animation: spin 2s linear infinite; + animation: spin 2s linear infinite; +} +@-webkit-keyframes spin { + 0% { -webkit-transform: rotate(0deg); } + 100% { -webkit-transform: rotate(360deg); } +} +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} +.bs-callout { + padding: 20px; + margin: 20px 0; + border: 1px solid #eee; + border-left-width: 5px; + border-radius: 3px; +} +.bs-callout h4 { + margin-top: 0; + margin-bottom: 5px; +} +.bs-callout p:last-child { + margin-bottom: 0; +} +.bs-callout code { + border-radius: 3px; +} +.bs-callout+.bs-callout { + margin-top: -5px; +} +.bs-callout-success { + border-left-color: #5cb85c; + background-color: #edf7ed; +} +.bs-callout-success h4 { + color: #5cb85c; +}.bs-callout-info { + border-left-color: #5bc0de; + background-color: #eaf7fb; +} +.bs-callout-info h4 { + color: #5bc0de; +} +.bs-callout-warning { + border-left-color: #f0ad4e; + background-color: #fdf4e8; +} +.bs-callout-warning h4 { + color: #f0ad4e; +} +.bs-callout-danger { + border-left-color: #d9534f; + background-color: #faebea; +} +.bs-callout-danger h4 { + color: #d9534f; +} +.label-pill { + padding-right: .6em; + padding-left: .6em; + border-radius: 10rem; +} \ No newline at end of file diff --git a/cmm/cmm/jquery.min.js b/cmm/cmm/jquery.min.js new file mode 100644 index 0000000..e836475 --- /dev/null +++ b/cmm/cmm/jquery.min.js @@ -0,0 +1,5 @@ +/*! jQuery v1.12.4 | (c) jQuery Foundation | jquery.org/license */ +!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=a.document,e=c.slice,f=c.concat,g=c.push,h=c.indexOf,i={},j=i.toString,k=i.hasOwnProperty,l={},m="1.12.4",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return e.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:e.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a){return n.each(this,a)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(e.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor()},push:g,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(n.isPlainObject(c)||(b=n.isArray(c)))?(b?(b=!1,f=a&&n.isArray(a)?a:[]):f=a&&n.isPlainObject(a)?a:{},g[d]=n.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray||function(a){return"array"===n.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){var b=a&&a.toString();return!n.isArray(a)&&b-parseFloat(b)+1>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==n.type(a)||a.nodeType||n.isWindow(a))return!1;try{if(a.constructor&&!k.call(a,"constructor")&&!k.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(!l.ownFirst)for(b in a)return k.call(a,b);for(b in a);return void 0===b||k.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?i[j.call(a)]||"object":typeof a},globalEval:function(b){b&&n.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b){var c,d=0;if(s(a)){for(c=a.length;c>d;d++)if(b.call(a[d],d,a[d])===!1)break}else for(d in a)if(b.call(a[d],d,a[d])===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):g.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(h)return h.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,e,g=0,h=[];if(s(a))for(d=a.length;d>g;g++)e=b(a[g],g,c),null!=e&&h.push(e);else for(g in a)e=b(a[g],g,c),null!=e&&h.push(e);return f.apply([],h)},guid:1,proxy:function(a,b){var c,d,f;return"string"==typeof b&&(f=a[b],b=a,a=f),n.isFunction(a)?(c=e.call(arguments,2),d=function(){return a.apply(b||this,c.concat(e.call(arguments)))},d.guid=a.guid=a.guid||n.guid++,d):void 0},now:function(){return+new Date},support:l}),"function"==typeof Symbol&&(n.fn[Symbol.iterator]=c[Symbol.iterator]),n.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(a,b){i["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=!!a&&"length"in a&&a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ga(),z=ga(),A=ga(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+M+"))|)"+L+"*\\]",O=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+N+")*)|.*)\\)|)",P=new RegExp(L+"+","g"),Q=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),R=new RegExp("^"+L+"*,"+L+"*"),S=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),T=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),U=new RegExp(O),V=new RegExp("^"+M+"$"),W={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M+"|[*])"),ATTR:new RegExp("^"+N),PSEUDO:new RegExp("^"+O),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},X=/^(?:input|select|textarea|button)$/i,Y=/^h\d$/i,Z=/^[^{]+\{\s*\[native \w/,$=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,_=/[+~]/,aa=/'|\\/g,ba=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),ca=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},da=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(ea){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fa(a,b,d,e){var f,h,j,k,l,o,r,s,w=b&&b.ownerDocument,x=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==x&&9!==x&&11!==x)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==x&&(o=$.exec(a)))if(f=o[1]){if(9===x){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(w&&(j=w.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(o[2])return H.apply(d,b.getElementsByTagName(a)),d;if((f=o[3])&&c.getElementsByClassName&&b.getElementsByClassName)return H.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==x)w=b,s=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(aa,"\\$&"):b.setAttribute("id",k=u),r=g(a),h=r.length,l=V.test(k)?"#"+k:"[id='"+k+"']";while(h--)r[h]=l+" "+qa(r[h]);s=r.join(","),w=_.test(a)&&oa(b.parentNode)||b}if(s)try{return H.apply(d,w.querySelectorAll(s)),d}catch(y){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(Q,"$1"),b,d,e)}function ga(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ha(a){return a[u]=!0,a}function ia(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ja(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function ka(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function la(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function na(a){return ha(function(b){return b=+b,ha(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function oa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=fa.support={},f=fa.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fa.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ia(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ia(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Z.test(n.getElementsByClassName),c.getById=ia(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return"undefined"!=typeof b.getElementsByClassName&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=Z.test(n.querySelectorAll))&&(ia(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ia(function(a){var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Z.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ia(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",O)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Z.test(o.compareDocumentPosition),t=b||Z.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return ka(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?ka(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},fa.matches=function(a,b){return fa(a,null,null,b)},fa.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(T,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fa(b,n,null,[a]).length>0},fa.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fa.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fa.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fa.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fa.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fa.selectors={cacheLength:50,createPseudo:ha,match:W,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ba,ca),a[3]=(a[3]||a[4]||a[5]||"").replace(ba,ca),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fa.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fa.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return W.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&U.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ba,ca).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fa.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(P," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fa.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ha(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ha(function(a){var b=[],c=[],d=h(a.replace(Q,"$1"));return d[u]?ha(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ha(function(a){return function(b){return fa(a,b).length>0}}),contains:ha(function(a){return a=a.replace(ba,ca),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ha(function(a){return V.test(a||"")||fa.error("unsupported lang: "+a),a=a.replace(ba,ca).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Y.test(a.nodeName)},input:function(a){return X.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:na(function(){return[0]}),last:na(function(a,b){return[b-1]}),eq:na(function(a,b,c){return[0>c?c+b:c]}),even:na(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:na(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:na(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:na(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function ra(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j,k=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(j=b[u]||(b[u]={}),i=j[b.uniqueID]||(j[b.uniqueID]={}),(h=i[d])&&h[0]===w&&h[1]===f)return k[2]=h[2];if(i[d]=k,k[2]=a(b,c,g))return!0}}}function sa(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ta(a,b,c){for(var d=0,e=b.length;e>d;d++)fa(a,b[d],c);return c}function ua(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(c&&!c(f,d,e)||(g.push(f),j&&b.push(h)));return g}function va(a,b,c,d,e,f){return d&&!d[u]&&(d=va(d)),e&&!e[u]&&(e=va(e,f)),ha(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ta(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ua(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ua(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ua(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function wa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ra(function(a){return a===b},h,!0),l=ra(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[ra(sa(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return va(i>1&&sa(m),i>1&&qa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(Q,"$1"),c,e>i&&wa(a.slice(i,e)),f>e&&wa(a=a.slice(e)),f>e&&qa(a))}m.push(c)}return sa(m)}function xa(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=F.call(i));u=ua(u)}H.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&fa.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ha(f):f}return h=fa.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xa(e,d)),f.selector=a}return f},i=fa.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ba,ca),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=W.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ba,ca),_.test(j[0].type)&&oa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qa(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,!b||_.test(a)&&oa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ia(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ia(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ja("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ia(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ja("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ia(function(a){return null==a.getAttribute("disabled")})||ja(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fa}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.uniqueSort=n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},v=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},w=n.expr.match.needsContext,x=/^<([\w-]+)\s*\/?>(?:<\/\1>|)$/,y=/^.[^:#\[\.,]*$/;function z(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(y.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return n.inArray(a,b)>-1!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;e>b;b++)if(n.contains(d[b],this))return!0}));for(b=0;e>b;b++)n.find(a,d[b],c);return c=this.pushStack(e>1?n.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(z(this,a||[],!1))},not:function(a){return this.pushStack(z(this,a||[],!0))},is:function(a){return!!z(this,"string"==typeof a&&w.test(a)?n(a):a||[],!1).length}});var A,B=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=n.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||A,"string"==typeof a){if(e="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:B.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),x.test(e[1])&&n.isPlainObject(b))for(e in b)n.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}if(f=d.getElementById(e[2]),f&&f.parentNode){if(f.id!==e[2])return A.find(a);this.length=1,this[0]=f}return this.context=d,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof c.ready?c.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};C.prototype=n.fn,A=n(d);var D=/^(?:parents|prev(?:Until|All))/,E={children:!0,contents:!0,next:!0,prev:!0};n.fn.extend({has:function(a){var b,c=n(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(n.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=w.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?n.inArray(this[0],n(a)):n.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.uniqueSort(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function F(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return u(a,"parentNode")},parentsUntil:function(a,b,c){return u(a,"parentNode",c)},next:function(a){return F(a,"nextSibling")},prev:function(a){return F(a,"previousSibling")},nextAll:function(a){return u(a,"nextSibling")},prevAll:function(a){return u(a,"previousSibling")},nextUntil:function(a,b,c){return u(a,"nextSibling",c)},prevUntil:function(a,b,c){return u(a,"previousSibling",c)},siblings:function(a){return v((a.parentNode||{}).firstChild,a)},children:function(a){return v(a.firstChild)},contents:function(a){return n.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(E[a]||(e=n.uniqueSort(e)),D.test(a)&&(e=e.reverse())),this.pushStack(e)}});var G=/\S+/g;function H(a){var b={};return n.each(a.match(G)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?H(a):n.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h-1)f.splice(c,1),h>=c&&h--}),this},has:function(a){return a?n.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=!0,c||j.disable(),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().progress(c.notify).done(c.resolve).fail(c.reject):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=e.call(arguments),d=c.length,f=1!==d||a&&n.isFunction(a.promise)?d:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?e.call(arguments):d,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(d>1)for(i=new Array(d),j=new Array(d),k=new Array(d);d>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().progress(h(b,j,i)).done(h(b,k,c)).fail(g.reject):--f;return f||g.resolveWith(k,c),g.promise()}});var I;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(I.resolveWith(d,[n]),n.fn.triggerHandler&&(n(d).triggerHandler("ready"),n(d).off("ready"))))}});function J(){d.addEventListener?(d.removeEventListener("DOMContentLoaded",K),a.removeEventListener("load",K)):(d.detachEvent("onreadystatechange",K),a.detachEvent("onload",K))}function K(){(d.addEventListener||"load"===a.event.type||"complete"===d.readyState)&&(J(),n.ready())}n.ready.promise=function(b){if(!I)if(I=n.Deferred(),"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll)a.setTimeout(n.ready);else if(d.addEventListener)d.addEventListener("DOMContentLoaded",K),a.addEventListener("load",K);else{d.attachEvent("onreadystatechange",K),a.attachEvent("onload",K);var c=!1;try{c=null==a.frameElement&&d.documentElement}catch(e){}c&&c.doScroll&&!function f(){if(!n.isReady){try{c.doScroll("left")}catch(b){return a.setTimeout(f,50)}J(),n.ready()}}()}return I.promise(b)},n.ready.promise();var L;for(L in n(l))break;l.ownFirst="0"===L,l.inlineBlockNeedsLayout=!1,n(function(){var a,b,c,e;c=d.getElementsByTagName("body")[0],c&&c.style&&(b=d.createElement("div"),e=d.createElement("div"),e.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(e).appendChild(b),"undefined"!=typeof b.style.zoom&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",l.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(e))}),function(){var a=d.createElement("div");l.deleteExpando=!0;try{delete a.test}catch(b){l.deleteExpando=!1}a=null}();var M=function(a){var b=n.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b},N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(O,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}n.data(a,b,c)}else c=void 0; +}return c}function Q(a){var b;for(b in a)if(("data"!==b||!n.isEmptyObject(a[b]))&&"toJSON"!==b)return!1;return!0}function R(a,b,d,e){if(M(a)){var f,g,h=n.expando,i=a.nodeType,j=i?n.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||n.guid++:h),j[k]||(j[k]=i?{}:{toJSON:n.noop}),"object"!=typeof b&&"function"!=typeof b||(e?j[k]=n.extend(j[k],b):j[k].data=n.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[n.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[n.camelCase(b)])):f=g,f}}function S(a,b,c){if(M(a)){var d,e,f=a.nodeType,g=f?n.cache:a,h=f?a[n.expando]:n.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){n.isArray(b)?b=b.concat(n.map(b,n.camelCase)):b in d?b=[b]:(b=n.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!Q(d):!n.isEmptyObject(d))return}(c||(delete g[h].data,Q(g[h])))&&(f?n.cleanData([a],!0):l.deleteExpando||g!=g.window?delete g[h]:g[h]=void 0)}}}n.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?n.cache[a[n.expando]]:a[n.expando],!!a&&!Q(a)},data:function(a,b,c){return R(a,b,c)},removeData:function(a,b){return S(a,b)},_data:function(a,b,c){return R(a,b,c,!0)},_removeData:function(a,b){return S(a,b,!0)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=n.data(f),1===f.nodeType&&!n._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d])));n._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){n.data(this,a)}):arguments.length>1?this.each(function(){n.data(this,a,b)}):f?P(f,a,n.data(f,a)):void 0},removeData:function(a){return this.each(function(){n.removeData(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=n._data(a,b),c&&(!d||n.isArray(c)?d=n._data(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return n._data(a,c)||n._data(a,c,{empty:n.Callbacks("once memory").add(function(){n._removeData(a,b+"queue"),n._removeData(a,c)})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthh;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},Z=/^(?:checkbox|radio)$/i,$=/<([\w:-]+)/,_=/^$|\/(?:java|ecma)script/i,aa=/^\s+/,ba="abbr|article|aside|audio|bdi|canvas|data|datalist|details|dialog|figcaption|figure|footer|header|hgroup|main|mark|meter|nav|output|picture|progress|section|summary|template|time|video";function ca(a){var b=ba.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}!function(){var a=d.createElement("div"),b=d.createDocumentFragment(),c=d.createElement("input");a.innerHTML="
a",l.leadingWhitespace=3===a.firstChild.nodeType,l.tbody=!a.getElementsByTagName("tbody").length,l.htmlSerialize=!!a.getElementsByTagName("link").length,l.html5Clone="<:nav>"!==d.createElement("nav").cloneNode(!0).outerHTML,c.type="checkbox",c.checked=!0,b.appendChild(c),l.appendChecked=c.checked,a.innerHTML="",l.noCloneChecked=!!a.cloneNode(!0).lastChild.defaultValue,b.appendChild(a),c=d.createElement("input"),c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),a.appendChild(c),l.checkClone=a.cloneNode(!0).cloneNode(!0).lastChild.checked,l.noCloneEvent=!!a.addEventListener,a[n.expando]=1,l.attributes=!a.getAttribute(n.expando)}();var da={option:[1,""],legend:[1,"
","
"],area:[1,"",""],param:[1,"",""],thead:[1,"","
"],tr:[2,"","
"],col:[2,"","
"],td:[3,"","
"],_default:l.htmlSerialize?[0,"",""]:[1,"X
","
"]};da.optgroup=da.option,da.tbody=da.tfoot=da.colgroup=da.caption=da.thead,da.th=da.td;function ea(a,b){var c,d,e=0,f="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||n.nodeName(d,b)?f.push(d):n.merge(f,ea(d,b));return void 0===b||b&&n.nodeName(a,b)?n.merge([a],f):f}function fa(a,b){for(var c,d=0;null!=(c=a[d]);d++)n._data(c,"globalEval",!b||n._data(b[d],"globalEval"))}var ga=/<|&#?\w+;/,ha=/r;r++)if(g=a[r],g||0===g)if("object"===n.type(g))n.merge(q,g.nodeType?[g]:g);else if(ga.test(g)){i=i||p.appendChild(b.createElement("div")),j=($.exec(g)||["",""])[1].toLowerCase(),m=da[j]||da._default,i.innerHTML=m[1]+n.htmlPrefilter(g)+m[2],f=m[0];while(f--)i=i.lastChild;if(!l.leadingWhitespace&&aa.test(g)&&q.push(b.createTextNode(aa.exec(g)[0])),!l.tbody){g="table"!==j||ha.test(g)?""!==m[1]||ha.test(g)?0:i:i.firstChild,f=g&&g.childNodes.length;while(f--)n.nodeName(k=g.childNodes[f],"tbody")&&!k.childNodes.length&&g.removeChild(k)}n.merge(q,i.childNodes),i.textContent="";while(i.firstChild)i.removeChild(i.firstChild);i=p.lastChild}else q.push(b.createTextNode(g));i&&p.removeChild(i),l.appendChecked||n.grep(ea(q,"input"),ia),r=0;while(g=q[r++])if(d&&n.inArray(g,d)>-1)e&&e.push(g);else if(h=n.contains(g.ownerDocument,g),i=ea(p.appendChild(g),"script"),h&&fa(i),c){f=0;while(g=i[f++])_.test(g.type||"")&&c.push(g)}return i=null,p}!function(){var b,c,e=d.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(l[b]=c in a)||(e.setAttribute(c,"t"),l[b]=e.attributes[c].expando===!1);e=null}();var ka=/^(?:input|select|textarea)$/i,la=/^key/,ma=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,na=/^(?:focusinfocus|focusoutblur)$/,oa=/^([^.]*)(?:\.(.+)|)/;function pa(){return!0}function qa(){return!1}function ra(){try{return d.activeElement}catch(a){}}function sa(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)sa(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=qa;else if(!e)return a;return 1===f&&(g=e,e=function(a){return n().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=n.guid++)),a.each(function(){n.event.add(this,b,e,d,c)})}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=n.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return"undefined"==typeof n||a&&n.event.triggered===a.type?void 0:n.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(G)||[""],h=b.length;while(h--)f=oa.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=n.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=n.event.special[o]||{},l=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},i),(m=g[o])||(m=g[o]=[],m.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,l):m.push(l),n.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n.hasData(a)&&n._data(a);if(r&&(k=r.events)){b=(b||"").match(G)||[""],j=b.length;while(j--)if(h=oa.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=m.length;while(f--)g=m[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(m.splice(f,1),g.selector&&m.delegateCount--,l.remove&&l.remove.call(a,g));i&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(k)&&(delete r.handle,n._removeData(a,"events"))}},trigger:function(b,c,e,f){var g,h,i,j,l,m,o,p=[e||d],q=k.call(b,"type")?b.type:b,r=k.call(b,"namespace")?b.namespace.split("."):[];if(i=m=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!na.test(q+n.event.triggered)&&(q.indexOf(".")>-1&&(r=q.split("."),q=r.shift(),r.sort()),h=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=f?2:3,b.namespace=r.join("."),b.rnamespace=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=e),c=null==c?[b]:n.makeArray(c,[b]),l=n.event.special[q]||{},f||!l.trigger||l.trigger.apply(e,c)!==!1)){if(!f&&!l.noBubble&&!n.isWindow(e)){for(j=l.delegateType||q,na.test(j+q)||(i=i.parentNode);i;i=i.parentNode)p.push(i),m=i;m===(e.ownerDocument||d)&&p.push(m.defaultView||m.parentWindow||a)}o=0;while((i=p[o++])&&!b.isPropagationStopped())b.type=o>1?j:l.bindType||q,g=(n._data(i,"events")||{})[b.type]&&n._data(i,"handle"),g&&g.apply(i,c),g=h&&i[h],g&&g.apply&&M(i)&&(b.result=g.apply(i,c),b.result===!1&&b.preventDefault());if(b.type=q,!f&&!b.isDefaultPrevented()&&(!l._default||l._default.apply(p.pop(),c)===!1)&&M(e)&&h&&e[q]&&!n.isWindow(e)){m=e[h],m&&(e[h]=null),n.event.triggered=q;try{e[q]()}catch(s){}n.event.triggered=void 0,m&&(e[h]=m)}return b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,d,f,g,h=[],i=e.call(arguments),j=(n._data(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())a.rnamespace&&!a.rnamespace.test(g.namespace)||(a.handleObj=g,a.data=g.data,d=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==d&&(a.result=d)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&("click"!==a.type||isNaN(a.button)||a.button<1))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>-1:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h]","i"),va=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,wa=/\s*$/g,Aa=ca(d),Ba=Aa.appendChild(d.createElement("div"));function Ca(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function Da(a){return a.type=(null!==n.find.attr(a,"type"))+"/"+a.type,a}function Ea(a){var b=ya.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Fa(a,b){if(1===b.nodeType&&n.hasData(a)){var c,d,e,f=n._data(a),g=n._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)n.event.add(b,c,h[c][d])}g.data&&(g.data=n.extend({},g.data))}}function Ga(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!l.noCloneEvent&&b[n.expando]){e=n._data(b);for(d in e.events)n.removeEvent(b,d,e.handle);b.removeAttribute(n.expando)}"script"===c&&b.text!==a.text?(Da(b).text=a.text,Ea(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),l.html5Clone&&a.innerHTML&&!n.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&Z.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:"input"!==c&&"textarea"!==c||(b.defaultValue=a.defaultValue)}}function Ha(a,b,c,d){b=f.apply([],b);var e,g,h,i,j,k,m=0,o=a.length,p=o-1,q=b[0],r=n.isFunction(q);if(r||o>1&&"string"==typeof q&&!l.checkClone&&xa.test(q))return a.each(function(e){var f=a.eq(e);r&&(b[0]=q.call(this,e,f.html())),Ha(f,b,c,d)});if(o&&(k=ja(b,a[0].ownerDocument,!1,a,d),e=k.firstChild,1===k.childNodes.length&&(k=e),e||d)){for(i=n.map(ea(k,"script"),Da),h=i.length;o>m;m++)g=k,m!==p&&(g=n.clone(g,!0,!0),h&&n.merge(i,ea(g,"script"))),c.call(a[m],g,m);if(h)for(j=i[i.length-1].ownerDocument,n.map(i,Ea),m=0;h>m;m++)g=i[m],_.test(g.type||"")&&!n._data(g,"globalEval")&&n.contains(j,g)&&(g.src?n._evalUrl&&n._evalUrl(g.src):n.globalEval((g.text||g.textContent||g.innerHTML||"").replace(za,"")));k=e=null}return a}function Ia(a,b,c){for(var d,e=b?n.filter(b,a):a,f=0;null!=(d=e[f]);f++)c||1!==d.nodeType||n.cleanData(ea(d)),d.parentNode&&(c&&n.contains(d.ownerDocument,d)&&fa(ea(d,"script")),d.parentNode.removeChild(d));return a}n.extend({htmlPrefilter:function(a){return a.replace(va,"<$1>")},clone:function(a,b,c){var d,e,f,g,h,i=n.contains(a.ownerDocument,a);if(l.html5Clone||n.isXMLDoc(a)||!ua.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(Ba.innerHTML=a.outerHTML,Ba.removeChild(f=Ba.firstChild)),!(l.noCloneEvent&&l.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(d=ea(f),h=ea(a),g=0;null!=(e=h[g]);++g)d[g]&&Ga(e,d[g]);if(b)if(c)for(h=h||ea(a),d=d||ea(f),g=0;null!=(e=h[g]);g++)Fa(e,d[g]);else Fa(a,f);return d=ea(f,"script"),d.length>0&&fa(d,!i&&ea(a,"script")),d=h=e=null,f},cleanData:function(a,b){for(var d,e,f,g,h=0,i=n.expando,j=n.cache,k=l.attributes,m=n.event.special;null!=(d=a[h]);h++)if((b||M(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)m[e]?n.event.remove(d,e):n.removeEvent(d,e,g.handle);j[f]&&(delete j[f],k||"undefined"==typeof d.removeAttribute?d[i]=void 0:d.removeAttribute(i),c.push(f))}}}),n.fn.extend({domManip:Ha,detach:function(a){return Ia(this,a,!0)},remove:function(a){return Ia(this,a)},text:function(a){return Y(this,function(a){return void 0===a?n.text(this):this.empty().append((this[0]&&this[0].ownerDocument||d).createTextNode(a))},null,a,arguments.length)},append:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.appendChild(a)}})},prepend:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&n.cleanData(ea(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&n.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return Y(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(ta,""):void 0;if("string"==typeof a&&!wa.test(a)&&(l.htmlSerialize||!ua.test(a))&&(l.leadingWhitespace||!aa.test(a))&&!da[($.exec(a)||["",""])[1].toLowerCase()]){a=n.htmlPrefilter(a);try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(ea(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=[];return Ha(this,arguments,function(b){var c=this.parentNode;n.inArray(this,a)<0&&(n.cleanData(ea(this)),c&&c.replaceChild(b,this))},a)}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=0,e=[],f=n(a),h=f.length-1;h>=d;d++)c=d===h?this:this.clone(!0),n(f[d])[b](c),g.apply(e,c.get());return this.pushStack(e)}});var Ja,Ka={HTML:"block",BODY:"block"};function La(a,b){var c=n(b.createElement(a)).appendTo(b.body),d=n.css(c[0],"display");return c.detach(),d}function Ma(a){var b=d,c=Ka[a];return c||(c=La(a,b),"none"!==c&&c||(Ja=(Ja||n("\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + } + elsif ($FORM{action} eq "view") { + print "
\n"; + print "
Headers spool file
\n"; + print "
";
+		my ($childin, $childout);
+		my $cmdpid = open3($childin, $childout, $childout, "/usr/sbin/exim", @config, "-Mvh", $FORM{id});
+		my @data = <$childout>;
+		waitpid ($cmdpid, 0);
+		chomp @data;
+		foreach my $line (@data) {
+			$line =~ s/>/>/g;
+			$line =~ s/
\n"; + print "
\n"; + + print "
\n"; + print "
Data spool file
\n"; + print "
";
+		$cmdpid = open3($childin, $childout, $childout, "/usr/sbin/exim", @config, "-Mvb", $FORM{id});
+		@data = <$childout>;
+		waitpid ($cmdpid, 0);
+		chomp @data;
+		foreach my $line (@data) {
+			$line =~ s/>/>/g;
+			$line =~ s/
\n"; + print "
\n"; + } + elsif ($FORM{action} eq "viewdelivery") { + print "
\n"; + print "\n"; + print "\n"; + print "
Delivery Log (Where available - Can take some time depending on the size of the $eximmainlog)
";
+		my ($childin, $childout);
+		my $cmdpid = open3($childin, $childout, $childout, "/usr/sbin/exigrep", $FORM{id}, "$eximmainlog");
+		my @data = <$childout>;
+		waitpid ($cmdpid, 0);
+		chomp @data;
+		foreach my $line (@data) {
+			$line =~ s/>/>/g;
+			$line =~ s/
\n"; + } + elsif ($FORM{action} eq "deliver") { + print "\n"; + print "\n"; + print "\n"; + print "
Deliver Email
";
+		my ($childin, $childout);
+		my $cmdpid = open3($childin, $childout, $childout, "/usr/sbin/exim", @config, "-v", "-M", $FORM{id});
+		my @data = <$childout>;
+		waitpid ($cmdpid, 0);
+		chomp @data;
+		foreach my $line (@data) {
+			$line =~ s/>/>/g;
+			$line =~ s/
\n"; + } + elsif ($FORM{action} eq "delete") { + print "\n"; + print "\n"; + print "\n"; + print "
Delete Email
";
+		my ($childin, $childout);
+		my $cmdpid = open3($childin, $childout, $childout, "/usr/sbin/exim", @config, "-v", "-Mrm", $FORM{id});
+		my @data = <$childout>;
+		waitpid ($cmdpid, 0);
+		chomp @data;
+		foreach my $line (@data) {
+			$line =~ s/>/>/g;
+			$line =~ s/
\n"; + } + elsif ($FORM{action} eq "mass") { + my $total = 0; + my $class = "tdshade2_noborder"; + if ($FORM{do} ne "Bcc to:") { + print "

Delete Selected

\n"; + } else { + print "

Bcc Selected to $FORM{bcc}

\n"; + } + print "\n"; + print "\n"; + foreach my $key (keys %FORM) { + my $id = 0; + if ($key =~ /^del_(.*)/) {$id = $1} + unless ($id) {next} + print "\n"; + print "\n"; + $total++; + if ($class eq "tdshade2_noborder") {$class = "tdshade1_noborder"} else {$class = "tdshade2_noborder"} + } + print "
Email IDResponse
$id"; + my $data; + if ($FORM{do} eq "Bcc to:") { + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, "/usr/sbin/exim", @config, "-Mar", $id, $FORM{bcc}); + my @data = <$childout>; + waitpid ($cmdpid, 0); + chomp @data; + print $data[-1]; + + $cmdpid = open3($childin, $childout, $childout, "/usr/sbin/exim", @config, "-Mc", $id); + @data = <$childout>; + waitpid ($cmdpid, 0); + chomp @data; + print $data[-1]; + } else { + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, "/usr/sbin/exim", @config, "-Mrm", $id); + my @data = <$childout>; + waitpid ($cmdpid, 0); + chomp @data; + print $data[-1]; + } + print "
\n"; + print "

Total emails: $total

\n"; + print "

\n"; + } + elsif ($FORM{action} eq "Queue Run") { + my @cmd; + my $flags; + if ($config =~ /mailscanner/) {undef @config} + if ($FORM{text} ne "" and $FORM{text} =~ /[^a-zA-Z0-9\-\_\.\@\+]/) { + print "Invalid data [$FORM{text}]"; + } else { + if ($FORM{force}) {$flags = "f"} + if ($FORM{frozen}) {$flags = "ff"} + if ($FORM{search}) { + if ($FORM{field} eq "to") { + push @cmd, "-R$flags", $FORM{text}; + } else { + push @cmd, "-S$flags", $FORM{text}; + } + } else { + push @cmd, "-q$flags"; + } + print "
\n"; + print "
Queue Run
\n"; + print "
";
+			my ($childin, $childout);
+			my $cmdpid = open3($childin, $childout, $childout, "/usr/sbin/exim", @config, "-v", @cmd);
+			my @data = <$childout>;
+			waitpid ($cmdpid, 0);
+			chomp @data;
+			foreach my $line (@data) {
+				$line =~ s/>/>/g;
+				$line =~ s/
\n"; + print "
\n"; + } + print "

\n"; + } + elsif ($FORM{action} eq "Exigrep") { + my $cmd; + my $flags; + if ($FORM{text} eq "") { + print "Empty regex"; + } else { + print "
\n"; + print "
Exigrep for $FORM{text}
\n"; + print "
";
+			my ($childin, $childout);
+			my $cmdpid = open3($childin, $childout, $childout, "/usr/sbin/exigrep", $FORM{text}, "$eximmainlog");
+			my @data = <$childout>;
+			waitpid ($cmdpid, 0);
+			chomp @data;
+			foreach my $line (@data) {
+				$line =~ s/>/>/g;
+				$line =~ s/
\n"; + print "
\n"; + } + print "

\n"; + } + elsif ($FORM{action} eq "upgrade") { + $| = 1; ## no critic + + print "Retrieving new cmq package...\n"; + print "
";
+		&printcmd("rm -Rfv /usr/src/cmq* ; cd /usr/src ; wget -q https://$downloadserver/cmq.tgz 2>&1");
+		print "
"; + if (! -z "/usr/src/cmq.tgz") { + print "Unpacking new cmq package...\n"; + print "
";
+			&printcmd("cd /usr/src ; tar -xzf cmq.tgz ; cd cmq ; sh install.sh 2>&1");
+			print "
"; + print "Tidying up...\n"; + print "
";
+			&printcmd("rm -Rfv /usr/src/cmq*");
+			print "
"; + print "...All done.\n"; + } + + open (my $IN, "<", "/etc/cmq/cmqversion.txt") or die $!; + $myv = <$IN>; + close ($IN); + chomp $myv; + + print "

\n"; + } + else { + if (-e "/etc/cmq/cmqstore") {unlink "/etc/cmq/cmqstore"} + + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, "/usr/sbin/exim", @config, "-bpc"); + my @output = <$childout>; + waitpid ($cmdpid, 0); + chomp @output; + unless ($output[0]) {$output[0] = 0} + + my @eximoutput; + if ($config) { + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, "/usr/sbin/exim", "-bpc"); + @eximoutput = <$childout>; + waitpid ($cmdpid, 0); + chomp @eximoutput; + unless ($eximoutput[0]) {$eximoutput[0] = 0} + } + if ($config =~ /mailscanner/) { + my @tmp = @eximoutput; + @eximoutput = @output; + @output = @tmp; + } + + print "
\n"; + + print "\n"; + print ""; + + if ($config =~ /mailscanner/) { + print "\n"; + if ($config) { + print "\n"; + } + } + elsif ($config =~ /exim/) { + print "\n"; + if ($config) { + print "\n"; + } + } + else { + print "\n"; + } + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "
Mail Queue Queries
Delivery Queue ($output[0] emails)Default queue - email waiting for delivery
MailScanner Queue ($eximoutput[0] emails)Email awaiting processing by MailScanner
Delivery Queue ($output[0] emails)Default queue - email waiting for delivery
MailScanner Queue ($eximoutput[0] emails)Email awaiting processing by MailScanner
Delivery Queue ($output[0] emails)Default queue - email waiting for delivery
All EmailsSelect all email that has been queued
Incoming Emails (may contain outgoing Forwarders)Select incoming email that has been queued
Outgoing EmailsSelect outgoing email that has been queued
Frozen EmailsSelect all frozen email that has been queued
Bounce EmailsSelect all bounce email that has been queued
All Other EmailsSelect all other email that has been queued
Display Email Subject when viewing emailsThis will add load and extend the time it takes to perform the task
Launch links in new windowThis will open links in a new window/tab instead of a modal in View Emails
Emails older than Select email that has been queued by age
Select email that has been queued with specified text
\n"; + print " \n"; + print "
\n"; + &confirmmodal("action", "Delete Emails", "Are you sure you want to delete these emails?"); + print "
\n"; + + print "
\n"; + print "\n"; + print ""; + print "\n"; + print "\n"; + print "\n"; + print "
Exigrep
Perform a pattern match search of $eximmainlog
Regular ExpressionUses exigrep to search $eximmainlog
\n"; + + print "
\n"; + print "\n"; + print ""; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "
Mail Queue Runs
Performs an exim queue run. These runs can take a long time to complete, so you need to be patient and careful not to spawn multiple queue runs by initiating these options until previous runs have completed.
Force runIgnores retry times for all relevant emails
Frozen Emails (implies Force run)Forces all emails including frozen emails to be retried
contains Selects email based on sender or recipient address text
\n"; + + my ($status, $text) = &urlget("https://$downloadserver/cmq/cmqversion.txt"); + my $actv = $text; + my $up = 0; + + print "\n"; + print ""; + if ($actv ne "") { + if ($actv =~ /^[\d\.]*$/) { + if ($actv > $myv) { + print "\n"; + } else { + print "\n"; + } + $up = 1; + } + } + unless ($up) { + print "\n"; + } + print "
Upgrade
A new version of cmq (v$actv) is available. View ChangeLog
You appear to be running the latest version of cmq
Failed to determine the latest version of cmq: [$status] [$text]
\n"; + } + print "
cmq: v$myv
"; + print "

©2006-2019, ConfigServer Services (Jonathan Michaelson)

\n"; + + return; +} +# end displayUI +############################################################################### +# start getqueue +sub getqueue { + my $storable = shift; + + if ($storable eq "storable" and -e "/etc/cmq/cmqstore") { + %queue = %{Storable::retrieve("/etc/cmq/cmqstore")}; + return; + } + + my $pos = 0; + my $id = 0; + my $count = 0; + my $queuecnt = 0; + my $per = 0; + my $oldper = 0; + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, "/usr/sbin/exim", @config, "-bpra"); +# my $cmdpid = open3($childin, $childout, $childout, "cat /root/tmp/q.txt"); + while (my $line = <$childout>) { + chomp $line; + + if ($line eq "") { + $queue{$id}{to} =~ s/,$//; + if ($queue{$id}{to} =~ /\,/) {$expcnt++} + $count++; + $pos = 0; + $id = 0; + next; + } + + if ($pos == 0) { +## if ($line =~ /^\s*(\w+)\s+(\S*)\s+(\w{6}-\w{6}-\w{2})\s+(<.*?>)/) { + if ($line =~ /^\s*(\w+)\s+(\S*)\s+(\S+)\s+(<.*?>)/) { + my $time = $1; + my $size = $2; + $id = $3; + my $from = $4; + if ($from eq "<>") {$from = "[bounce]"; $queue{$id}{bounce} = "*"} + $from =~ s/\<|\>//g; + my $epoch = time; + if ($time =~ /(\d+)(\w)/) { + if ($2 eq "m") {$epoch -= $1 * 60} + elsif ($2 eq "h") {$epoch -= $1 * 60 * 60} + elsif ($2 eq "d") {$epoch -= $1 * 60 * 60 * 24} + } + $queue{$id}{epoch} = $epoch; + $queue{$id}{from} = $from; + $queue{$id}{time} = $time; + $queue{$id}{size} = $size; + $queuecnt++; + if ($line =~ /\*\*\* frozen \*\*\*$/) {$queue{$id}{frozen} = "*"} + } + } else { + $queue{$id}{to} .= "$line,"; + } + $pos++; + } + waitpid ($cmdpid, 0); + + if ($storable eq "storable") { + Storable::nstore(\%queue, "/etc/cmq/cmqstore"); + chmod(0600,"/etc/cmq/cmqstore"); + } + + return; +} +# end getqueue +############################################################################### +# start confirmmodal +# print "\n"; +# &confirmmodal("submit_name", "submit_value", "display text"); +sub confirmmodal { + my $name = shift; + my $value = shift; + my $text = shift; + + print "\n"; + print "\n"; + return; +} +# end confirmmodal +############################################################################### +# start urlget (v1.3) +sub urlget { + my $url = shift; + my $file = shift; + my $status = 0; + my $timeout = 1200; + local $SIG{PIPE} = 'IGNORE'; + + use LWP::UserAgent; + my $ua = LWP::UserAgent->new; + $ua->timeout(30); + my $req = HTTP::Request->new(GET => $url); + my $res; + my $text; + + ($status, $text) = eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die "Download timeout after $timeout seconds"}; + alarm($timeout); + if ($file) { + $|=1; ## no critic + my $expected_length; + my $bytes_received = 0; + my $per = 0; + my $oldper = 0; + open (my $OUT, ">", "$file\.tmp") or return (1, "Unable to open $file\.tmp: $!"); + binmode ($OUT); + print "...0\%\n"; + $res = $ua->request($req, + sub { + my($chunk, $res) = @_; + $bytes_received += length($chunk); + unless (defined $expected_length) {$expected_length = $res->content_length || 0} + if ($expected_length) { + my $per = int(100 * $bytes_received / $expected_length); + if ((int($per / 5) == $per / 5) and ($per != $oldper)) { + print "...$per\%\n"; + $oldper = $per; + } + } else { + print "."; + } + print $OUT $chunk; + }); + close ($OUT); + print "\n"; + } else { + $res = $ua->request($req); + } + alarm(0); + if ($res->is_success) { + if ($file) { + rename ("$file\.tmp","$file") or return (1, "Unable to rename $file\.tmp to $file: $!"); + return (0, $file); + } else { + return (0, $res->content); + } + } else { + return (1, "Unable to download: ".$res->message); + } + }; + alarm(0); + if ($@) { + return (1, $@); + } + if ($text) { + return ($status,$text); + } else { + return (1, "Download timeout after $timeout seconds"); + } +} +# end urlget +############################################################################### +## start printcmd +sub printcmd { + my @command = @_; + my ($childin, $childout); + my $pid = open3($childin, $childout, $childout, @command); + while (<$childout>) {print $_} + waitpid ($pid, 0); + return; +} +## end printcmd +############################################################################### +## start getdownloadserver +sub getdownloadserver { + my @servers; + my $downloadservers = "/etc/cmq/downloadservers"; + my $chosen; + if (-e $downloadservers) { + open (my $DOWNLOAD, "<", $downloadservers); + flock ($DOWNLOAD, LOCK_SH); + my @data = <$DOWNLOAD>; + close ($DOWNLOAD); + chomp @data; + foreach my $line (@data) { + if ($line =~ /^download/) {push @servers, $line} + } + $chosen = $servers[rand @servers]; + } + if ($chosen eq "") {$chosen = "download.configserver.com"} + return $chosen; +} +## end getdownloadserver +############################################################################### + +1; diff --git a/cmq/cmq.c b/cmq/cmq.c new file mode 100644 index 0000000..1db48f7 --- /dev/null +++ b/cmq/cmq.c @@ -0,0 +1,57 @@ +/* +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +*/ +#include +#include +#include +#include +#include +main () +{ + FILE *adminFile; + uid_t ruid; + char name[100]; + struct passwd *pw; + int admin = 0; + + ruid = getuid(); + pw = getpwuid(ruid); + + adminFile=fopen ("/usr/local/directadmin/data/admin/admin.list","r"); + if (adminFile!=NULL) + { + while(fgets(name,100,adminFile) != NULL) + { + int end = strlen(name) - 1; + if (end >= 0 && name[end] == '\n') name[end] = '\0'; + //printf("Name [%s]\n", name); + if (strcmp(pw->pw_name, name) == 0) admin = 1; + } + fclose(adminFile); + } + if (admin == 1) + { + setuid(0); + setgid(0); + + execv("/usr/local/directadmin/plugins/cmq/exec/da_cmq.cgi", NULL); + } else { + printf("Permission denied [User:%s UID:%d]\n", pw->pw_name, ruid); + } + return 0; +} diff --git a/cmq/cmq/admin_icon.svg b/cmq/cmq/admin_icon.svg new file mode 100644 index 0000000..99941be --- /dev/null +++ b/cmq/cmq/admin_icon.svg @@ -0,0 +1,90 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/cmq/cmq/bootstrap/css/bootstrap.min.css b/cmq/cmq/bootstrap/css/bootstrap.min.css new file mode 100644 index 0000000..ed3905e --- /dev/null +++ b/cmq/cmq/bootstrap/css/bootstrap.min.css @@ -0,0 +1,6 @@ +/*! + * Bootstrap v3.3.7 (http://getbootstrap.com) + * Copyright 2011-2016 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,:after,:before{color:#000!important;text-shadow:none!important;background:0 0!important;-webkit-box-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff2) format('woff2'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\002a"}.glyphicon-plus:before{content:"\002b"}.glyphicon-eur:before,.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:focus,a:hover{color:#23527c;text-decoration:underline}a:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.carousel-inner>.item>a>img,.carousel-inner>.item>img,.img-responsive,.thumbnail a>img,.thumbnail>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;max-width:100%;height:auto;padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role=button]{cursor:pointer}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1;color:#777}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}.small,small{font-size:85%}.mark,mark{padding:.2em;background-color:#fcf8e3}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:focus,a.text-primary:hover{color:#286090}.text-success{color:#3c763d}a.text-success:focus,a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:focus,a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:focus,a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:focus,a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:focus,a.bg-primary:hover{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:focus,a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:focus,a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:focus,a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:focus,a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ol,ul{margin-top:0;margin-bottom:10px}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;margin-left:-5px;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-top:0;margin-bottom:20px}dd,dt{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[data-original-title],abbr[title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child{margin-bottom:0}blockquote .small,blockquote footer,blockquote small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote .small:before,blockquote footer:before,blockquote small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eee;border-left:0}.blockquote-reverse .small:before,.blockquote-reverse footer:before,.blockquote-reverse small:before,blockquote.pull-right .small:before,blockquote.pull-right footer:before,blockquote.pull-right small:before{content:''}.blockquote-reverse .small:after,.blockquote-reverse footer:after,.blockquote-reverse small:after,blockquote.pull-right .small:after,blockquote.pull-right footer:after,blockquote.pull-right small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{margin-right:-15px;margin-left:-15px}.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>td,.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>td,.table>thead:first-child>tr:first-child>th{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>tbody>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>thead>tr>th{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #ddd}.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*=col-]{position:static;display:table-column;float:none}table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;float:none}.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>thead>tr>td.active,.table>thead>tr>th.active{background-color:#f5f5f5}.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover{background-color:#e8e8e8}.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{background-color:#dff0d8}.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6}.table>tbody>tr.info>td,.table>tbody>tr.info>th,.table>tbody>tr>td.info,.table>tbody>tr>th.info,.table>tfoot>tr.info>td,.table>tfoot>tr.info>th,.table>tfoot>tr>td.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>thead>tr.info>th,.table>thead>tr>td.info,.table>thead>tr>th.info{background-color:#d9edf7}.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover{background-color:#c4e3f3}.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fcf8e3}.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc}.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#f2dede}.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc}.table-responsive{min-height:.01%;overflow-x:auto}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=checkbox],input[type=radio]{margin:4px 0 0;margin-top:1px\9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[type=checkbox]:focus,input[type=radio]:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control::-ms-expand{background-color:transparent;border:0}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}input[type=search]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type=date].form-control,input[type=time].form-control,input[type=datetime-local].form-control,input[type=month].form-control{line-height:34px}.input-group-sm input[type=date],.input-group-sm input[type=time],.input-group-sm input[type=datetime-local],.input-group-sm input[type=month],input[type=date].input-sm,input[type=time].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm{line-height:30px}.input-group-lg input[type=date],.input-group-lg input[type=time],.input-group-lg input[type=datetime-local],.input-group-lg input[type=month],input[type=date].input-lg,input[type=time].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg{line-height:46px}}.form-group{margin-bottom:15px}.checkbox,.radio{position:relative;display:block;margin-top:10px;margin-bottom:10px}.checkbox label,.radio label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{position:absolute;margin-top:4px\9;margin-left:-20px}.checkbox+.checkbox,.radio+.radio{margin-top:-5px}.checkbox-inline,.radio-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px}fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox].disabled,input[type=checkbox][disabled],input[type=radio].disabled,input[type=radio][disabled]{cursor:not-allowed}.checkbox-inline.disabled,.radio-inline.disabled,fieldset[disabled] .checkbox-inline,fieldset[disabled] .radio-inline{cursor:not-allowed}.checkbox.disabled label,.radio.disabled label,fieldset[disabled] .checkbox label,fieldset[disabled] .radio label{cursor:not-allowed}.form-control-static{min-height:34px;padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}select[multiple].input-sm,textarea.input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm select[multiple].form-control,.form-group-sm textarea.form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}select[multiple].input-lg,textarea.input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:46px;line-height:46px}.form-group-lg select[multiple].form-control,.form-group-lg textarea.form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.form-group-lg .form-control+.form-control-feedback,.input-group-lg+.form-control-feedback,.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.form-group-sm .form-control+.form-control-feedback,.input-group-sm+.form-control-feedback,.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .checkbox,.has-success .checkbox-inline,.has-success .control-label,.has-success .help-block,.has-success .radio,.has-success .radio-inline,.has-success.checkbox label,.has-success.checkbox-inline label,.has-success.radio label,.has-success.radio-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .checkbox,.has-warning .checkbox-inline,.has-warning .control-label,.has-warning .help-block,.has-warning .radio,.has-warning .radio-inline,.has-warning.checkbox label,.has-warning.checkbox-inline label,.has-warning.radio label,.has-warning.radio-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .checkbox,.has-error .checkbox-inline,.has-error .control-label,.has-error .help-block,.has-error .radio,.has-error .radio-inline,.has-error.checkbox label,.has-error.checkbox-inline label,.has-error.radio label,.has-error.radio-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .form-control,.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .checkbox,.form-inline .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .checkbox label,.form-inline .radio label{padding-left:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .checkbox,.form-horizontal .radio{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:11px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:none;border:1px solid transparent;border-radius:4px}.btn.active.focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn:active:focus,.btn:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.focus,.btn:focus,.btn:hover{color:#333;text-decoration:none}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none;opacity:.65}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default.focus,.btn-default:focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.btn-default:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active.focus,.btn-default.active:focus,.btn-default.active:hover,.btn-default:active.focus,.btn-default:active:focus,.btn-default:active:hover,.open>.dropdown-toggle.btn-default.focus,.open>.dropdown-toggle.btn-default:focus,.open>.dropdown-toggle.btn-default:hover{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled.focus,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled].focus,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#286090;border-color:#122b40}.btn-primary:hover{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active.focus,.btn-primary.active:focus,.btn-primary.active:hover,.btn-primary:active.focus,.btn-primary:active:focus,.btn-primary:active:hover,.open>.dropdown-toggle.btn-primary.focus,.open>.dropdown-toggle.btn-primary:focus,.open>.dropdown-toggle.btn-primary:hover{color:#fff;background-color:#204d74;border-color:#122b40}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled.focus,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled].focus,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#449d44;border-color:#255625}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active.focus,.btn-success.active:focus,.btn-success.active:hover,.btn-success:active.focus,.btn-success:active:focus,.btn-success:active:hover,.open>.dropdown-toggle.btn-success.focus,.open>.dropdown-toggle.btn-success:focus,.open>.dropdown-toggle.btn-success:hover{color:#fff;background-color:#398439;border-color:#255625}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled.focus,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled].focus,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active.focus,.btn-info.active:focus,.btn-info.active:hover,.btn-info:active.focus,.btn-info:active:focus,.btn-info:active:hover,.open>.dropdown-toggle.btn-info.focus,.open>.dropdown-toggle.btn-info:focus,.open>.dropdown-toggle.btn-info:hover{color:#fff;background-color:#269abc;border-color:#1b6d85}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled.focus,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled].focus,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning.focus,.btn-warning:focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active.focus,.btn-warning.active:focus,.btn-warning.active:hover,.btn-warning:active.focus,.btn-warning:active:focus,.btn-warning:active:hover,.open>.dropdown-toggle.btn-warning.focus,.open>.dropdown-toggle.btn-warning:focus,.open>.dropdown-toggle.btn-warning:hover{color:#fff;background-color:#d58512;border-color:#985f0d}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled.focus,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled].focus,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c9302c;border-color:#761c19}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active.focus,.btn-danger.active:focus,.btn-danger.active:hover,.btn-danger:active.focus,.btn-danger:active:focus,.btn-danger:active:hover,.open>.dropdown-toggle.btn-danger.focus,.open>.dropdown-toggle.btn-danger:focus,.open>.dropdown-toggle.btn-danger:hover{color:#fff;background-color:#ac2925;border-color:#761c19}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled.focus,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled].focus,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#337ab7;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#777;text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-group-sm>.btn,.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-xs>.btn,.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:height,visibility;-o-transition-property:height,visibility;transition-property:height,visibility}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid\9;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown,.dropup{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;background-color:#337ab7;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#777}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px dashed;border-bottom:4px solid\9}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;float:left}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-left-radius:0;border-top-right-radius:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group .form-control:focus{z-index:3}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn,textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn,textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group .form-control,.input-group-addon,.input-group-btn{display:table-cell}.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn-group:not(:last-child)>.btn,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:first-child>.btn-group:not(:first-child)>.btn,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:focus,.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:focus,.nav>li.disabled>a:hover{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:focus,.nav .open>a:hover{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:focus,.nav-tabs>li.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:focus,.nav-pills>li.active>a:hover{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;-webkit-overflow-scrolling:touch;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1)}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:200px}}.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;height:50px;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1)}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .form-control,.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .checkbox label,.navbar-form .radio label{padding-left:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:focus,.navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:focus,.navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:focus,.navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:focus,.navbar-default .navbar-nav>.open>a:hover{color:#555;background-color:#e7e7e7}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:focus,.navbar-default .btn-link:hover{color:#333}.navbar-default .btn-link[disabled]:focus,.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:focus,fieldset[disabled] .navbar-default .btn-link:hover{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:focus,.navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:focus,.navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:focus,.navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:focus,.navbar-inverse .navbar-toggle:hover{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{color:#fff;background-color:#080808}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:focus,.navbar-inverse .btn-link:hover{color:#fff}.navbar-inverse .btn-link[disabled]:focus,.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:focus,fieldset[disabled] .navbar-inverse .btn-link:hover{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.42857143;color:#337ab7;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:2;color:#23527c;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:3;color:#fff;cursor:default;background-color:#337ab7;border-color:#337ab7}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:focus,.pager li>a:hover{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:focus,a.label:hover{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:focus,.label-default[href]:hover{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:focus,.label-primary[href]:hover{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:focus,.label-success[href]:hover{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:focus,.label-info[href]:hover{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:focus,.label-warning[href]:hover{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:focus,.label-danger[href]:hover{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:middle;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-group-xs>.btn .badge,.btn-xs .badge{top:0;padding:1px 5px}a.badge:focus,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron .h1,.jumbotron h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{padding-right:15px;padding-left:15px;border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-right:60px;padding-left:60px}.jumbotron .h1,.jumbotron h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail a>img,.thumbnail>img{margin-right:auto;margin-left:auto}a.thumbnail.active,a.thumbnail:focus,a.thumbnail:hover{border-color:#337ab7}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-bar-striped,.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress-bar.active,.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{overflow:hidden;zoom:1}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-body,.media-left,.media-right{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}a.list-group-item,button.list-group-item{color:#555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333}a.list-group-item:focus,a.list-group-item:hover,button.list-group-item:focus,button.list-group-item:hover{color:#555;text-decoration:none;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item.disabled,.list-group-item.disabled:focus,.list-group-item.disabled:hover{color:#777;cursor:not-allowed;background-color:#eee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:focus .list-group-item-text,.list-group-item.active:hover .list-group-item-text{color:#c7ddef}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:focus,a.list-group-item-success:hover,button.list-group-item-success:focus,button.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:focus,a.list-group-item-success.active:hover,button.list-group-item-success.active,button.list-group-item-success.active:focus,button.list-group-item-success.active:hover{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:focus,a.list-group-item-info:hover,button.list-group-item-info:focus,button.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:focus,a.list-group-item-info.active:hover,button.list-group-item-info.active,button.list-group-item-info.active:focus,button.list-group-item-info.active:hover{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:focus,a.list-group-item-warning:hover,button.list-group-item-warning:focus,button.list-group-item-warning:hover{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:focus,a.list-group-item-warning.active:hover,button.list-group-item-warning.active,button.list-group-item-warning.active:focus,button.list-group-item-warning.active:hover{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:focus,a.list-group-item-danger:hover,button.list-group-item-danger:focus,button.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover,button.list-group-item-danger.active,button.list-group-item-danger.active:focus,button.list-group-item-danger.active:hover{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>.small,.panel-title>.small>a,.panel-title>a,.panel-title>small,.panel-title>small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-left-radius:0;border-top-right-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.panel-collapse>.table,.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.panel-collapse>.table caption,.panel>.table caption,.panel>.table-responsive>.table caption{padding-right:15px;padding-left:15px}.panel>.table-responsive:first-child>.table:first-child,.panel>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table:first-child>thead:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table-responsive:last-child>.table:last-child,.panel>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child td,.panel>.table>tbody:first-child>tr:first-child th{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.list-group,.panel-group .panel-heading+.panel-collapse>.panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{-webkit-appearance:none;padding:0;cursor:pointer;background:0 0;border:0}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out;-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%)}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5)}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:12px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;filter:alpha(opacity=0);opacity:0;line-break:auto}.tooltip.in{filter:alpha(opacity=90);opacity:.9}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{right:5px;bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);line-break:auto}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{content:"";border-width:10px}.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25)}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>a>img,.carousel-inner>.item>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.active.right,.carousel-inner>.item.next{left:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.carousel-inner>.item.active.left,.carousel-inner>.item.prev{left:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.carousel-inner>.item.active,.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right{left:0;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);background-color:rgba(0,0,0,0);filter:alpha(opacity=50);opacity:.5}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);background-repeat:repeat-x}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);background-repeat:repeat-x}.carousel-control:focus,.carousel-control:hover{color:#fff;text-decoration:none;filter:alpha(opacity=90);outline:0;opacity:.9}.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block;margin-top:-10px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{left:50%;margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{right:50%;margin-right:-10px}.carousel-control .icon-next,.carousel-control .icon-prev{width:20px;height:20px;font-family:serif;line-height:1}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000\9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-10px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-10px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.btn-group-vertical>.btn-group:after,.btn-group-vertical>.btn-group:before,.btn-toolbar:after,.btn-toolbar:before,.clearfix:after,.clearfix:before,.container-fluid:after,.container-fluid:before,.container:after,.container:before,.dl-horizontal dd:after,.dl-horizontal dd:before,.form-horizontal .form-group:after,.form-horizontal .form-group:before,.modal-footer:after,.modal-footer:before,.modal-header:after,.modal-header:before,.nav:after,.nav:before,.navbar-collapse:after,.navbar-collapse:before,.navbar-header:after,.navbar-header:before,.navbar:after,.navbar:before,.pager:after,.pager:before,.panel-body:after,.panel-body:before,.row:after,.row:before{display:table;content:" "}.btn-group-vertical>.btn-group:after,.btn-toolbar:after,.clearfix:after,.container-fluid:after,.container:after,.dl-horizontal dd:after,.form-horizontal .form-group:after,.modal-footer:after,.modal-header:after,.nav:after,.navbar-collapse:after,.navbar-header:after,.navbar:after,.pager:after,.panel-body:after,.row:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-lg,.visible-md,.visible-sm,.visible-xs{display:none!important}.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table!important}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table!important}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table!important}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table!important}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table!important}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}} +/*# sourceMappingURL=bootstrap.min.css.map */ \ No newline at end of file diff --git a/cmq/cmq/bootstrap/fonts/glyphicons-halflings-regular.eot b/cmq/cmq/bootstrap/fonts/glyphicons-halflings-regular.eot new file mode 100644 index 0000000000000000000000000000000000000000..b93a4953fff68df523aa7656497ee339d6026d64 GIT binary patch literal 20127 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cmq/cmq/bootstrap/fonts/glyphicons-halflings-regular.ttf b/cmq/cmq/bootstrap/fonts/glyphicons-halflings-regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..1413fc609ab6f21774de0cb7e01360095584f65b GIT binary patch literal 45404 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 G`u_lkUM?>H literal 0 HcmV?d00001 diff --git a/cmq/cmq/bootstrap/fonts/glyphicons-halflings-regular.woff2 b/cmq/cmq/bootstrap/fonts/glyphicons-halflings-regular.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..64539b54c3751a6d9adb44c8e3a45ba5a73b77f0 GIT binary patch literal 18028 zcmV(~K+nH-Pew8T0RR9107h&84*&oF0I^&E07eM_0Rl|`00000000000000000000 z0000#Mn+Uk92y`7U;vDA2m}!b3WBL5f#qcZHUcCAhI9*rFaQJ~1&1OBl~F%;WnyLq z8)b|&?3j;$^FW}&KmNW53flIFARDZ7_Wz%hpoWaWlgHTHEHf()GI0&dMi#DFPaEt6 zCO)z0v0~C~q&0zBj^;=tv8q{$8JxX)>_`b}WQGgXi46R*CHJ}6r+;}OrvwA{_SY+o zK)H-vy{l!P`+NG*`*x6^PGgHH4!dsolgU4RKj@I8Xz~F6o?quCX&=VQ$Q{w01;M0? zKe|5r<_7CD z=eO3*x!r$aX2iFh3;}xNfx0v;SwBfGG+@Z;->HhvqfF4r__4$mU>Dl_1w;-9`~5rF~@!3;r~xP-hZvOfOx)A z#>8O3N{L{naf215f>m=bzbp7_(ssu&cx)Qo-{)!)Yz3A@Z0uZaM2yJ8#OGlzm?JO5gbrj~@)NB4@?>KE(K-$w}{};@dKY#K3+Vi64S<@!Z{(I{7l=!p9 z&kjG^P~0f46i13(w!hEDJga;*Eb z`!n|++@H8VaKG<9>VDh(y89J#=;Z$ei=GnD5TesW#|Wf)^D+9NKN4J3H5PF_t=V+Z zdeo8*h9+8&Zfc?>>1|E4B7MAx)^uy$L>szyXre7W|81fjy+RZ1>Gd}@@${~PCOXo) z$#HZd3)V3@lNGG%(3PyIbvyJTOJAWcN@Uh!FqUkx^&BuAvc)G}0~SKI`8ZZXw$*xP zum-ZdtPciTAUn$XWb6vrS=JX~f5?M%9S(=QsdYP?K%Odn0S0-Ad<-tBtS3W06I^FK z8}d2eR_n!(uK~APZ-#tl@SycxkRJ@5wmypdWV{MFtYBUY#g-Vv?5AEBj1 z`$T^tRKca*sn7gt%s@XUD-t>bij-4q-ilku9^;QJ3Mpc`HJ_EX4TGGQ-Og)`c~qm51<|gp7D@ zp#>Grssv^#A)&M8>ulnDM_5t#Al`#jaFpZ<#YJ@>!a$w@kEZ1<@PGs#L~kxOSz7jj zEhb?;W)eS}0IQQuk4~JT30>4rFJ3!b+77}>$_>v#2FFEnN^%(ls*o80pv0Q>#t#%H z@`Yy-FXQ9ULKh{Up&oA_A4B!(x^9&>i`+T|eD!&QOLVd(_avv-bFX~4^>o{%mzzrg_i~SBnr%DeE|i+^}|8?kaV(Z32{`vA^l!sp15>Z72z52FgXf z^8ZITvJ9eXBT1~iQjW|Q`Fac^ak$^N-vI^*geh5|*CdMz;n16gV_zk|Z7q8tFfCvU zJK^Pptnn0Rc~egGIAK}uv99VZm2WLPezQQ5K<`f zg{8Ll|GioPYfNheMj-7-S87=w4N0WxHP`1V6Y)0M&SkYzVrwp>yfsEF7wj&T0!}dB z)R~gGfP9pOR;GY_e0~K^^oJ-3AT+m~?Al!{>>5gNe17?OWz)$)sMH*xuQiB>FT2{i zQ>6U_8}Ay~r4li;jzG+$&?S12{)+<*k9 z<^SX#xY|jvlvTxt(m~C7{y{3g>7TX#o2q$xQO|fc<%8rE@A3=UW(o?gVg?gDV!0q6O!{MlX$6-Bu_m&0ms66 znWS&zr{O_4O&{2uCLQvA?xC5vGZ}KV1v6)#oTewgIMSnBur0PtM0&{R5t#UEy3I9) z`LVP?3f;o}sz*7g5qdTxJl^gk3>;8%SOPH@B)rmFOJ)m6?PlYa$y=RX%;}KId{m9R#2=LNwosF@OTivgMqxpRGe}5=LtAn?VVl6VWCFLD z7l#^^H8jY~42hR)OoVF#YDW(md!g(&pJ;yMj|UBAQa}UH?ED@%ci=*(q~Opn>kE2Q z_4Kgf|0kEA6ary41A;)^Ku(*nirvP!Y>{FZYBLXLP6QL~vRL+uMlZ?jWukMV*(dsn zL~~KA@jU)(UeoOz^4Gkw{fJsYQ%|UA7i79qO5=DOPBcWlv%pK!A+)*F`3WJ}t9FU3 zXhC4xMV7Z%5RjDs0=&vC4WdvD?Zi5tg4@xg8-GLUI>N$N&3aS4bHrp%3_1u9wqL)i z)XQLsI&{Hd&bQE!3m&D0vd!4D`l1$rt_{3NS?~lj#|$GN5RmvP(j3hzJOk=+0B*2v z)Bw133RMUM%wu_+$vbzOy?yk#kvR?xGsg-ipX4wKyXqd zROKp5))>tNy$HByaEHK%$mqd>-{Yoj`oSBK;w>+eZ&TVcj^DyXjo{DDbZ>vS2cCWB z(6&~GZ}kUdN(*2-nI!hvbnVy@z2E#F394OZD&Jb04}`Tgaj?MoY?1`{ejE2iud51% zQ~J0sijw(hqr_Ckbj@pm$FAVASKY(D4BS0GYPkSMqSDONRaFH+O2+jL{hIltJSJT~e)TNDr(}=Xt7|UhcU9eoXl&QZRR<9WomW%&m)FT~j zTgGd3-j}Uk%CRD;$@X)NNV9+RJbifYu>yr{FkO;p>_&njI> zyBHh_72bW;8}oGeY0gpHOxiV597j7mY<#?WMmkf5x~Kfk*re(&tG_mX<3&2cON*2u%V29tsXUv{#-ijs2>EuNH-x3) zPBpi+V6gI=wn}u164_j8xi-y(B?Au2o;UO=r6&)i5S3Mx*)*{_;u}~i4dh$`VgUS- zMG6t*?DXDYX0D2Oj31MI!HF>|aG8rjrOPnxHu4wZl;!=NGjjDoBpXf?ntrwt^dqxm zs(lE@*QB3NH)!`rH)5kks-D89g@UX&@DU9jvrsY)aI=9b4nPy3bfdX_U;#?zsan{G>DKob2LnhCJv8o}duQK)qP{7iaaf2=K`a-VNcfC582d4a z>sBJA*%S|NEazDxXcGPW_uZ&d7xG`~JB!U>U(}acUSn=FqOA~(pn^!aMXRnqiL0;? zebEZYouRv}-0r;Dq&z9>s#Rt1HL`0p4bB)A&sMyn|rE_9nh z?NO*RrjET8D4s(-`nS{MrdYtv*kyCnJKbsftG2D#ia@;42!8xd?a3P(&Y?vCf9na< zQ&Ni*1Qel&Xq{Z?=%f0SRqQt5m|Myg+8T=GDc)@^};=tM>9IDr7hdvE9-M@@<0pqv45xZTeNecbL- zWFQt4t`9>j8~X%lz}%We>Kzh_=`XO}!;4!OWH?=p*DOs#Nt({k^IvtBEL~Qafn)I^ zm*k{y7_bIs9YE}0B6%r`EIUH8US+MGY!KQA1fi-jCx9*}oz2k1nBsXp;4K<_&SN}}w<)!EylI_)v7}3&c)V;Cfuj*eJ2yc8LK=vugqTL><#65r6%#2e| zdYzZ)9Uq7)A$ol&ynM!|RDHc_7?FlWqjW>8TIHc`jExt)f5W|;D%GC#$u!%B*S%Z0 zsj&;bIU2jrt_7%$=!h4Q29n*A^^AI8R|stsW%O@?i+pN0YOU`z;TVuPy!N#~F8Z29 zzZh1`FU(q31wa>kmw{$q=MY>XBprL<1)Py~5TW4mgY%rg$S=4C^0qr+*A^T)Q)Q-U zGgRb9%MdE-&i#X3xW=I`%xDzAG95!RG9)s?v_5+qx`7NdkQ)If5}BoEp~h}XoeK>kweAMxJ8tehagx~;Nr_WP?jXa zJ&j7%Ef3w*XWf?V*nR)|IOMrX;$*$e23m?QN` zk>sC^GE=h6?*Cr~596s_QE@>Nnr?{EU+_^G=LZr#V&0fEXQ3IWtrM{=t^qJ62Sp=e zrrc>bzX^6yFV!^v7;>J9>j;`qHDQ4uc92eVe6nO@c>H=ouLQot``E~KLNqMqJ7(G+?GWO9Ol+q$w z!^kMv!n{vF?RqLnxVk{a_Ar;^sw0@=+~6!4&;SCh^utT=I zo&$CwvhNOjQpenw2`5*a6Gos6cs~*TD`8H9P4=#jOU_`%L!W;$57NjN%4 z39(61ZC#s7^tv`_4j}wMRT9rgDo*XtZwN-L;Qc$6v8kKkhmRrxSDkUAzGPgJ?}~_t zkwoGS4=6lsD`=RL|8L3O9L()N)lmEn-M15fRC{dhZ}7eYV%O-R^gsAp{q4 z!C1}_T8gy^v@SZ5R&Li5JMJy+K8iZw3LOGA0pN1~y@w7RRl#F()ii6Y5mr~Mdy@Kz z@FT4cm^I&#Fu_9IX(HAFP{XLbRALqm&)>m_we>a`hfv?eE|t z?YdDp2yAhj-~vuw^wzVDuj%w?exOcOT(ls(F*ceCe(C5HlN{lcQ;}|mRPqFDqLEzw zR7ldY+M6xe$$qLwekmk{Z&5cME$gpC?-8)f0m$rqaS|mj9ATNJvvyCgs(f2{r;2E!oy$k5{jik#(;S>do<#m0wVcU<}>)VtYmF9O0%(C>GDzPgh6X z9OkQLMR~y7=|MtaU!LDPPY7O)L{X#SC+M|v^X2CZ?$GS>U_|aC(VA(mIvCNk+biD| zSpj>gd(v>_Cbq>~-x^Y3o|?eHmuC?E&z>;Ij`%{$Pm$hI}bl0Kd`9KD~AchY+goL1?igDxf$qxL9< z4sW@sD)nwWr`T>e2B8MQN|p*DVTT8)3(%AZ&D|@Zh6`cJFT4G^y6`(UdPLY-&bJYJ z*L06f2~BX9qX}u)nrpmHPG#La#tiZ23<>`R@u8k;ueM6 znuSTY7>XEc+I-(VvL?Y>)adHo(cZ;1I7QP^q%hu#M{BEd8&mG_!EWR7ZV_&EGO;d(hGGJzX|tqyYEg2-m0zLT}a{COi$9!?9yK zGN7&yP$a|0gL`dPUt=4d^}?zrLN?HfKP0_gdRvb}1D73Hx!tXq>7{DWPV;^X{-)cm zFa^H5oBDL3uLkaFDWgFF@HL6Bt+_^g~*o*t`Hgy3M?nHhWvTp^|AQDc9_H< zg>IaSMzd7c(Sey;1SespO=8YUUArZaCc~}}tZZX80w%)fNpMExki-qB+;8xVX@dr; z#L52S6*aM-_$P9xFuIui;dN#qZ_MYy^C^hrY;YAMg;K`!ZpKKFc z9feHsool)`tFSS}Su|cL0%F;h!lpR+ym|P>kE-O`3QnHbJ%gJ$dQ_HPTT~>6WNX41 zoDEUpX-g&Hh&GP3koF4##?q*MX1K`@=W6(Gxm1=2Tb{hn8{sJyhQBoq}S>bZT zisRz-xDBYoYxt6--g2M1yh{#QWFCISux}4==r|7+fYdS$%DZ zXVQu{yPO<)Hn=TK`E@;l!09aY{!TMbT)H-l!(l{0j=SEj@JwW0a_h-2F0MZNpyucb zPPb+4&j?a!6ZnPTB>$t`(XSf-}`&+#rI#`GB> zl=$3HORwccTnA2%>$Nmz)u7j%_ywoGri1UXVNRxSf(<@vDLKKxFo;5pTI$R~a|-sQ zd5Rfwj+$k1t0{J`qOL^q>vZUHc7a^`cKKVa{66z?wMuQAfdZBaVVv@-wamPmes$d! z>gv^xx<0jXOz;7HIQS z4RBIFD?7{o^IQ=sNQ-k!ao*+V*|-^I2=UF?{d>bE9avsWbAs{sRE-y`7r zxVAKA9amvo4T}ZAHSF-{y1GqUHlDp4DO9I3mz5h8n|}P-9nKD|$r9AS3gbF1AX=2B zyaK3TbKYqv%~JHKQH8v+%zQ8UVEGDZY|mb>Oe3JD_Z{+Pq%HB+J1s*y6JOlk`6~H) zKt)YMZ*RkbU!GPHzJltmW-=6zqO=5;S)jz{ zFSx?ryqSMxgx|Nhv3z#kFBTuTBHsViaOHs5e&vXZ@l@mVI37<+^KvTE51!pB4Tggq zz!NlRY2ZLno0&6bA|KHPYOMY;;LZG&_lzuLy{@i$&B(}_*~Zk2 z>bkQ7u&Ww%CFh{aqkT{HCbPbRX&EvPRp=}WKmyHc>S_-qbwAr0<20vEoJ(!?-ucjE zKQ+nSlRL^VnOX0h+WcjGb6WI(8;7bsMaHXDb6ynPoOXMlf9nLKre;w*#E_whR#5!! z!^%_+X3eJVKc$fMZP;+xP$~e(CIP1R&{2m+iTQhDoC8Yl@kLM=Wily_cu>7C1wjVU z-^~I0P06ZSNVaN~A`#cSBH2L&tk6R%dU1(u1XdAx;g+5S^Hn9-L$v@p7CCF&PqV{Z?R$}4EJi36+u2JP7l(@fYfP!=e#76LGy^f>~vs0%s*x@X8`|5 zGd6JOHsQ=feES4Vo8%1P_7F5qjiIm#oRT0kO1(?Z_Dk6oX&j=Xd8Klk(;gk3S(ZFnc^8Gc=d;8O-R9tlGyp=2I@1teAZpGWUi;}`n zbJOS_Z2L16nVtDnPpMn{+wR9&yU9~C<-ncppPee`>@1k7hTl5Fn_3_KzQ)u{iJPp3 z)df?Xo%9ta%(dp@DhKuQj4D8=_!*ra#Ib&OXKrsYvAG%H7Kq|43WbayvsbeeimSa= z8~{7ya9ZUAIgLLPeuNmSB&#-`Je0Lja)M$}I41KHb7dQq$wgwX+EElNxBgyyLbA2* z=c1VJR%EPJEw(7!UE?4w@94{pI3E%(acEYd8*Wmr^R7|IM2RZ-RVXSkXy-8$!(iB* zQA`qh2Ze!EY6}Zs7vRz&nr|L60NlIgnO3L*Yz2k2Ivfen?drnVzzu3)1V&-t5S~S? zw#=Sdh>K@2vA25su*@>npw&7A%|Uh9T1jR$mV*H@)pU0&2#Se`7iJlOr$mp79`DKM z5vr*XLrg7w6lc4&S{So1KGKBqcuJ!E|HVFB?vTOjQHi)g+FwJqX@Y3q(qa#6T@3{q zhc@2T-W}XD9x4u+LCdce$*}x!Sc#+rH-sCz6j}0EE`Tk*irUq)y^za`}^1gFnF)C!yf_l_}I<6qfbT$Gc&Eyr?!QwJR~RE4!gKVmqjbI+I^*^ z&hz^7r-dgm@Mbfc#{JTH&^6sJCZt-NTpChB^fzQ}?etydyf~+)!d%V$0faN(f`rJb zm_YaJZ@>Fg>Ay2&bzTx3w^u-lsulc{mX4-nH*A(32O&b^EWmSuk{#HJk}_ULC}SB(L7`YAs>opp9o5UcnB^kVB*rmW6{s0&~_>J!_#+cEWib@v-Ms`?!&=3fDot`oH9v&$f<52>{n2l* z1FRzJ#yQbTHO}}wt0!y8Eh-0*|Um3vjX-nWH>`JN5tWB_gnW%; zUJ0V?_a#+!=>ahhrbGvmvObe8=v1uI8#gNHJ#>RwxL>E^pT05Br8+$@a9aDC1~$@* zicSQCbQcr=DCHM*?G7Hsovk|{$3oIwvymi#YoXeVfWj{Gd#XmnDgzQPRUKNAAI44y z{1WG&rhIR4ipmvBmq$BZ*5tmPIZmhhWgq|TcuR{6lA)+vhj(cH`0;+B^72{&a7ff* zkrIo|pd-Yxm+VVptC@QNCDk0=Re%Sz%ta7y{5Dn9(EapBS0r zLbDKeZepar5%cAcb<^;m>1{QhMzRmRem=+0I3ERot-)gb`i|sII^A#^Gz+x>TW5A& z3PQcpM$lDy`zb%1yf!e8&_>D02RN950KzW>GN6n@2so&Wu09x@PB=&IkIf|zZ1W}P zAKf*&Mo5@@G=w&290aG1@3=IMCB^|G4L7*xn;r3v&HBrD4D)Zg+)f~Ls$7*P-^i#B z4X7ac=0&58j^@2EBZCs}YPe3rqgLAA1L3Y}o?}$%u~)7Rk=LLFbAdSy@-Uw6lv?0K z&P@@M`o2Rll3GoYjotf@WNNjHbe|R?IKVn*?Rzf9v9QoFMq)ODF~>L}26@z`KA82t z43e!^z&WGqAk$Ww8j6bc3$I|;5^BHwt`?e)zf|&+l#!8uJV_Cwy-n1yS0^Q{W*a8B zTzTYL>tt&I&9vzGQUrO?YIm6C1r>eyh|qw~-&;7s7u1achP$K3VnXd8sV8J7ZTxTh z5+^*J5%_#X)XL2@>h(Gmv$@)fZ@ikR$v(2Rax89xscFEi!3_;ORI0dBxw)S{r50qf zg&_a*>2Xe{s@)7OX9O!C?^6fD8tc3bQTq9}fxhbx2@QeaO9Ej+2m!u~+u%Q6?Tgz{ zjYS}bleKcVhW~1$?t*AO^p!=Xkkgwx6OTik*R3~yg^L`wUU9Dq#$Z*iW%?s6pO_f8 zJ8w#u#Eaw7=8n{zJ}C>w{enA6XYHfUf7h)!Qaev)?V=yW{b@-z`hAz;I7^|DoFChP z1aYQnkGauh*ps6x*_S77@z1wwGmF8ky9fMbM$dr*`vsot4uvqWn)0vTRwJqH#&D%g zL3(0dP>%Oj&vm5Re%>*4x|h1J2X*mK5BH1?Nx_#7( zepgF`+n)rHXj!RiipusEq!X81;QQBXlTvLDj=Qub(ha&D=BDx3@-V*d!D9PeXUY?l zwZ0<4=iY!sUj4G>zTS+eYX7knN-8Oynl=NdwHS*nSz_5}*5LQ@=?Yr?uj$`C1m2OR zK`f5SD2|;=BhU#AmaTKe9QaSHQ_DUj1*cUPa*JICFt1<&S3P3zsrs^yUE;tx=x^cmW!Jq!+hohv_B> zPDMT0D&08dC4x@cTD$o1$x%So1Ir(G3_AVQMvQ13un~sP(cEWi$2%5q93E7t{3VJf%K? zuwSyDke~7KuB2?*#DV8YzJw z&}SCDexnUPD!%4|y~7}VzvJ4ch)WT4%sw@ItwoNt(C*RP)h?&~^g##vnhR0!HvIYx z0td2yz9=>t3JNySl*TszmfH6`Ir;ft@RdWs3}!J88UE|gj_GMQ6$ZYphUL2~4OY7} zB*33_bjkRf_@l;Y!7MIdb~bVe;-m78Pz|pdy=O*3kjak63UnLt!{^!!Ljg0rJD3a~ z1Q;y5Z^MF<=Hr}rdoz>yRczx+p3RxxgJE2GX&Si)14B@2t21j4hnnP#U?T3g#+{W+Zb z5s^@>->~-}4|_*!5pIzMCEp|3+i1XKcfUxW`8|ezAh>y{WiRcjSG*asw6;Ef(k#>V ztguN?EGkV_mGFdq!n#W)<7E}1#EZN8O$O|}qdoE|7K?F4zo1jL-v}E8v?9qz(d$&2 zMwyK&xlC9rXo_2xw7Qe0caC?o?Pc*-QAOE!+UvRuKjG+;dk|jQhDDBe?`XT7Y5lte zqSu0t5`;>Wv%|nhj|ZiE^IqA_lZu7OWh!2Y(627zb=r7Ends}wVk7Q5o09a@ojhH7 zU0m&h*8+j4e|OqWyJ&B`V`y=>MVO;K9=hk^6EsmVAGkLT{oUtR{JqSRY{Qi{kKw1k z6s;0SMPJOLp!som|A`*q3t0wIj-=bG8a#MC)MHcMSQU98Juv$?$CvYX)(n`P^!`5| zv3q@@|G@6wMqh;d;m4qvdibx2Yjml}vG9mDv&!0ne02M#D`Bo}xIB0VWh8>>WtNZQ z$&ISlJX;*ORQIO;k62qA{^6P%3!Z=Y1EbmY02{w^yB$`;%!{kur&XTGDiO2cjA)lr zsY^XZWy^DSAaz;kZ_VG?uWnJR7qdN18$~)>(kOoybY0~QYu9||K#|$Mby{3GduV~N zk9H7$7=RSo+?CUYF502`b76ytBy}sFak&|HIwRvB=0D|S`c#QCJPq zP)uOWI)#(n&{6|C4A^G~%B~BY21aOMoz9RuuM`Ip%oBz+NoAlb7?#`E^}7xXo!4S? zFg8I~G%!@nXi8&aJSGFcZAxQf;0m}942=i#p-&teLvE{AKm7Sl2f}Io?!IqbC|J;h z`=5LFOnU5?^w~SV@YwNZx$k_(kLNxZDE z3cf08^-rIT_>A$}B%IJBPcN^)4;90BQtiEi!gT#+EqyAUZ|}*b_}R>SGloq&6?opL zuT_+lwQMgg6!Cso$BwUA;k-1NcrzyE>(_X$B0HocjY~=Pk~Q08+N}(|%HjO_i+*=o z%G6C6A30Ch<0UlG;Zdj@ed!rfUY_i9mYwK8(aYuzcUzlTJ1yPz|Bb-9b33A9zRhGl>Ny-Q#JAq-+qtI@B@&w z$;PJbyiW=!py@g2hAi0)U1v=;avka`gd@8LC4=BEbNqL&K^UAQ5%r95#x%^qRB%KLaqMnG|6xKAm}sx!Qwo}J=2C;NROi$mfADui4)y(3wVA3k~{j^_5%H)C6K zlYAm1eY**HZOj($)xfKIQFtIVw$4&yvz9>(Crs>Gh{ zya6-FG7Dgi92#K)64=9Csj5?Zqe~_9TwSI!2quAwa1w-*uC5!}xY`?tltb0Hq740< zsq2QelPveZ4chr$=~U3!+c&>xyfvA1`)owOqj=i4wjY=A1577Gwg&Ko7;?il9r|_* z8P&IDV_g2D{in5OLFxsO!kx3AhO$5aKeoM|!q|VokqMlYM@HtsRuMtBY%I35#5$+G zpp|JOeoj^U=95HLemB04Yqv{a8X<^K9G2`&ShM_6&Bi1n?o?@MXsDj9Z*A3>#XK%J zRc*&SlFl>l)9DyRQ{*%Z+^e1XpH?0@vhpXrnPPU*d%vOhKkimm-u3c%Q^v3RKp9kx@A2dS?QfS=iigGr7m><)YkV=%LA5h@Uj@9=~ABPMJ z1UE;F&;Ttg5Kc^Qy!1SuvbNEqdgu3*l`=>s5_}dUv$B%BJbMiWrrMm7OXOdi=GOmh zZBvXXK7VqO&zojI2Om9};zCB5i|<210I{iwiGznGCx=FT89=Ef)5!lB1cZ6lbzgDn07*he}G&w7m!;|E(L-?+cz@0<9ZI~LqYQE7>HnPA436}oeN2Y(VfG6 zxNZuMK3Crm^Z_AFeHc~CVRrSl0W^?+Gbteu1g8NGYa3(8f*P{(ZT>%!jtSl6WbYVv zmE(37t0C8vJ6O-5+o*lL9XRcFbd~GSBGbGh3~R!67g&l)7n!kJlWd)~TUyXus#!&G6sR%(l(h1$xyrR5j_jM1zj#giA&@(Xl26@n<9>folx!92bQ z24h570+<)4!$!IQ(5yOU|4_E6aN@4v0+{Kx~Z z;q7fp%0cHziuI%!kB~w}g9@V+1wDz0wFlzX2UOvOy|&;e;t!lAR8tV2KQHgtfk8Uf zw;rs!(4JPODERk4ckd5I2Vq|0rd@@Mwd8MID%0^fITjYIQom^q;qhP8@|eJx{?5xX zc1@Fj*kDknlk{c-rnCloQ3hGh7OU+@efO3>fkRMcM>J?AeVP& zlfzX%cdp=N+4S#E*%^=BQ+N`A7C}|k%$|QUn0yI6S3$MS-NjO!4hm55uyju)Q6e!} z*OVO@A#-mfC9Pha6ng((Xl^V7{d+&u+yx)_B1{~t7d5e8L^i4J>;x<7@5;+l7-Gge zf#9diXJ$&v^rbN5V(ee%q0xBMEgS6%qZm7hNUP%G;^J44I!BmI@M*+FWz0!+s;+iQ zU4CuI+27bvNK8v>?7PZnVxB=heJ&_ymE0nN^W#-rqB%+JXkYGDuRw>JM_LdtLkiq* z6%%3&^BX$jnM@2bjiGc-DymKly)wVkA-pq;jSWL#7_*moZZ4I|-N}o8SK?sIv)p|c zu~9-B%tMc=!)YMFp*SiC0>kfnH8+X5>;+FFVN{~a9YVdIg1uGkZ~kegFy{^PU(4{( z`CbY`XmVA3esai686Yw8djCEyF7`bfB^F1)nwv+AqYLZ&Zy=eFhYT2uMd@{sP_qS4 zbJ&>PxajjZt?&c<1^!T|pLHfX=E^FJ>-l_XCZzvRV%x}@u(FtF(mS+Umw$e+IA74e>gCdTqi;6&=euAIpxd=Y3I5xWR zBhGoT+T`V1@91OlQ}2YO*~P4ukd*TBBdt?Plt)_ou6Y@Db`ss+Q~A-48s>?eaJYA2 zRGOa8^~Em}EFTmKIVVbMb|ob)hJJ7ITg>yHAn2i|{2ZJU!cwt9YNDT0=*WO7Bq#Xj zg@FjEaKoolrF8%c;49|`IT&25?O$dq8kp3#la9&6aH z6G|{>^C(>yP7#Dr$aeFyS0Ai_$ILhL43#*mgEl(c*4?Ae;tRL&S7Vc}Szl>B`mBuI zB9Y%xp%CZwlH!3V(`6W4-ZuETssvI&B~_O;CbULfl)X1V%(H7VSPf`_Ka9ak@8A=z z1l|B1QKT}NLI`WVTRd;2En5u{0CRqy9PTi$ja^inu){LJ&E&6W%JJPw#&PaTxpt?k zpC~gjN*22Q8tpGHR|tg~ye#9a8N<%odhZJnk7Oh=(PKfhYfzLAxdE36r<6a?A;rO&ELp_Y?8Pdw(PT^Fxn!eG_|LEbSYoBrsBA|6Fgr zt5LntyusI{Q2fdy=>ditS;}^B;I2MD4=(>7fWt0Jp~y=?VvfvzHvQhj6dyIef46J$ zl4Xu7U9v_NJV?uBBC0!kcTS0UcrV7+@~is?Fi+jrr@l3XwD|uG zr26jUWiv>Ju48Y^#qn7r9mwIH-Pv6Y|V|V-GZ&+&gQ?S?-`&ts{@5GXPqbmyZjUACC&oVXfNwUX0}ba(v978 zp8z!v9~8Zx8qB@7>oFPDm^iR@+yw`79YF)w^OHB_N;&&x7c3l^3!)IY#)}x)@D(iNaOm9 zC=^*!{`7={3*S=%iU=KsPXh=DDZcc``Ss>057i{pdW8M@4q+Ba@Tt%OytH!4>rbIbQw^-pR zGGYNPzw@n=PV@)b7yVbFr;glF*Qq3>F9oBN5PUXt!?2mdGcpv^o1?Thp`jP10G2Yi z(c93td3F3SW!Le5DUwdub!aDKoVLU6g!O?Ret21l$qOC;kdd@L#M&baVu&JZGt&<6 z!VCkvgRaav6QDW2x}tUy4~Y5(B+#Ej-8vM?DM-1?J_*&PntI3E96M!`WL#<&Z5n2u zo`P!~vBT$YOT~gU9#PB)%JZ zcd_u=m^LYzC!pH#W`yA1!(fA;D~b zG#73@l)NNd;n#XrKXZEfab;@kQRnOFU2Th-1m<4mJzlj9b3pv-GF$elX7ib9!uILM_$ke zHIGB*&=5=;ynQA{y7H93%i^d)T}y@(p>8vVhJ4L)M{0Q*@D^+SPp`EW+G6E%+`Z;u zS3goV@Dic7vc5`?!pCN44Ts@*{)zwy)9?B||AM{zKlN4T}qQRL2 zgv+{K8bv7w)#xge16;kI1fU87!W4pX)N&|cq8&i^1r`W|Hg4366r(?-ecEJ9u&Eaw zrhyikXQB>C9d>cpPGiu=VU3Z-u4|0V_iap!_J3o+K_R5EXk@sfu~zHwwYkpncVh!R zqNe7Cmf_|Wmeq4#(mIO&(wCK@b4(x0?W1Qtk(`$?+$uCJCGZm_%k?l32vuShgDFMa ztc`{$8DhB9)&?~(m&EUc=LzI1=qo#zjy#2{hLT_*aj<618qQ7mD#k2ZFGou&69;=2 z1j7=Su8k}{L*h&mfs7jg^PN&9C1Z@U!p6gXk&-7xM~{X`nqH#aGO`;Xy_zbz^rYacIq0AH%4!Oh93TzJ820%ur)8OyeS@K?sF1V(iFO z37Nnqj1z#1{|v7=_CX`lQA|$<1gtuNMHGNJYp1D_k;WQk-b+T6VmUK(x=bWviOZ~T z|4e%SpuaWLWD?qN2%`S*`P;BQBw(B__wTD6epvGdJ+>DBq2oVlf&F*lz+#avb4)3P1c^Mf#olQheVvZ|Z5 z>xXfgmv!5Z^SYn+_x}K5B%G^sRwiez&z9|f!E!#oJlT2kCOV0000$L_|bHBqAarB4TD{W@grX1CUr72@caw0faEd7-K|4L_|cawbojjHdpd6 zI6~Iv5J?-Q4*&oF000000FV;^004t70Z6Qk1Xl{X9oJ{sRC2(cs?- literal 0 HcmV?d00001 diff --git a/cmq/cmq/bootstrap/js/bootstrap.min.js b/cmq/cmq/bootstrap/js/bootstrap.min.js new file mode 100644 index 0000000..9bcd2fc --- /dev/null +++ b/cmq/cmq/bootstrap/js/bootstrap.min.js @@ -0,0 +1,7 @@ +/*! + * Bootstrap v3.3.7 (http://getbootstrap.com) + * Copyright 2011-2016 Twitter, Inc. + * Licensed under the MIT license + */ +if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1||b[0]>3)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){if(a(b.target).is(this))return b.handleObj.handler.apply(this,arguments)}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.7",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a("#"===f?[]:f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.7",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c).prop(c,!0)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c).prop(c,!1))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")?(c.prop("checked")&&(a=!1),b.find(".active").removeClass("active"),this.$element.addClass("active")):"checkbox"==c.prop("type")&&(c.prop("checked")!==this.$element.hasClass("active")&&(a=!1),this.$element.toggleClass("active")),c.prop("checked",this.$element.hasClass("active")),a&&c.trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active")),this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target).closest(".btn");b.call(d,"toggle"),a(c.target).is('input[type="radio"], input[type="checkbox"]')||(c.preventDefault(),d.is("input,button")?d.trigger("focus"):d.find("input:visible,button:visible").first().trigger("focus"))}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.7",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c=this.getItemIndex(b),d="prev"==a&&0===c||"next"==a&&c==this.$items.length-1;if(d&&!this.options.wrap)return b;var e="prev"==a?-1:1,f=(c+e)%this.$items.length;return this.$items.eq(f)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(".item.active"));if(!(a>this.$items.length-1||a<0))return this.sliding?this.$element.one("slid.bs.carousel",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?"next":"prev",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){if(!this.sliding)return this.slide("next")},c.prototype.prev=function(){if(!this.sliding)return this.slide("prev")},c.prototype.slide=function(b,d){var e=this.$element.find(".item.active"),f=d||this.getItemForDirection(b,e),g=this.interval,h="next"==b?"left":"right",i=this;if(f.hasClass("active"))return this.sliding=!1;var j=f[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:h});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(f)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:h});return a.support.transition&&this.$element.hasClass("slide")?(f.addClass(b),f[0].offsetWidth,e.addClass(h),f.addClass(h),e.one("bsTransitionEnd",function(){f.removeClass([b,h].join(" ")).addClass("active"),e.removeClass(["active",h].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trigger(m)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}};a(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){var c,d=b.attr("data-target")||(c=b.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data("bs.collapse"),f=a.extend({},d.DEFAULTS,c.data(),"object"==typeof b&&b);!e&&f.toggle&&/show|hide/.test(b)&&(f.toggle=!1),e||c.data("bs.collapse",e=new d(this,f)),"string"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a('[data-toggle="collapse"][href="#'+b.id+'"],[data-toggle="collapse"][data-target="#'+b.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION="3.3.7",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0},d.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},d.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b,e=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(e&&e.length&&(b=e.data("bs.collapse"),b&&b.transitioning))){var f=a.Event("show.bs.collapse");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,"hide"),b||e.data("bs.collapse",null));var g=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[g](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var h=function(){this.$element.removeClass("collapsing").addClass("collapse in")[g](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return h.call(this);var i=a.camelCase(["scroll",g].join("-"));this.$element.one("bsTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var e=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass("in");a.attr("aria-expanded",c),b.toggleClass("collapsed",!c).attr("aria-expanded",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(d){var e=a(this);e.attr("data-target")||d.preventDefault();var f=b(e),g=f.data("bs.collapse"),h=g?"toggle":e.data();c.call(f,h)})}(jQuery),+function(a){"use strict";function b(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function c(c){c&&3===c.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=b(d),f={relatedTarget:this};e.hasClass("open")&&(c&&"click"==c.type&&/input|textarea/i.test(c.target.tagName)&&a.contains(e[0],c.target)||(e.trigger(c=a.Event("hide.bs.dropdown",f)),c.isDefaultPrevented()||(d.attr("aria-expanded","false"),e.removeClass("open").trigger(a.Event("hidden.bs.dropdown",f)))))}))}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.3.7",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=b(e),g=f.hasClass("open");if(c(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(document.createElement("div")).addClass("dropdown-backdrop").insertAfter(a(this)).on("click",c);var h={relatedTarget:this};if(f.trigger(d=a.Event("show.bs.dropdown",h)),d.isDefaultPrevented())return;e.trigger("focus").attr("aria-expanded","true"),f.toggleClass("open").trigger(a.Event("shown.bs.dropdown",h))}return!1}},g.prototype.keydown=function(c){if(/(38|40|27|32)/.test(c.which)&&!/input|textarea/i.test(c.target.tagName)){var d=a(this);if(c.preventDefault(),c.stopPropagation(),!d.is(".disabled, :disabled")){var e=b(d),g=e.hasClass("open");if(!g&&27!=c.which||g&&27==c.which)return 27==c.which&&e.find(f).trigger("focus"),d.trigger("click");var h=" li:not(.disabled):visible a",i=e.find(".dropdown-menu"+h);if(i.length){var j=i.index(c.target);38==c.which&&j>0&&j--,40==c.which&&jdocument.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&a?this.scrollbarWidth:"",paddingRight:this.bodyIsOverflowing&&!a?this.scrollbarWidth:""})},c.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:"",paddingRight:""})},c.prototype.checkScrollbar=function(){var a=window.innerWidth;if(!a){var b=document.documentElement.getBoundingClientRect();a=b.right-Math.abs(b.left)}this.bodyIsOverflowing=document.body.clientWidth
',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){if(this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(a.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusin"==b.type?"focus":"hover"]=!0),c.tip().hasClass("in")||"in"==c.hoverState?void(c.hoverState="in"):(clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show())},c.prototype.isInStateTrue=function(){for(var a in this.inState)if(this.inState[a])return!0;return!1},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);if(c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusout"==b.type?"focus":"hover"]=!1),!c.isInStateTrue())return clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide()},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var d=a.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!d)return;var e=this,f=this.tip(),g=this.getUID(this.type);this.setContent(),f.attr("id",g),this.$element.attr("aria-describedby",g),this.options.animation&&f.addClass("fade");var h="function"==typeof this.options.placement?this.options.placement.call(this,f[0],this.$element[0]):this.options.placement,i=/\s?auto?\s?/i,j=i.test(h);j&&(h=h.replace(i,"")||"top"),f.detach().css({top:0,left:0,display:"block"}).addClass(h).data("bs."+this.type,this),this.options.container?f.appendTo(this.options.container):f.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.getPosition(this.$viewport);h="bottom"==h&&k.bottom+m>o.bottom?"top":"top"==h&&k.top-mo.width?"left":"left"==h&&k.left-lg.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;jg.right&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){if(!this.$tip&&(this.$tip=a(this.options.template),1!=this.$tip.length))throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!");return this.$tip},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),b?(c.inState.click=!c.inState.click,c.isInStateTrue()?c.enter(c):c.leave(c)):c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){var a=this;clearTimeout(this.timeout),this.hide(function(){a.$element.off("."+a.type).removeData("bs."+a.type),a.$tip&&a.$tip.detach(),a.$tip=null,a.$arrow=null,a.$viewport=null,a.$element=null})};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;!e&&/destroy|hide/.test(b)||(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.3.7",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:''}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){this.$body=a(document.body),this.$scrollElement=a(a(c).is(document.body)?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",a.proxy(this.process,this)),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.3.7",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b=this,c="offset",d=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),a.isWindow(this.$scrollElement[0])||(c="position",d=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var b=a(this),e=b.data("target")||b.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[c]().top+d,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b=e[a]&&(void 0===e[a+1]||b .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),b.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),h?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu").length&&b.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),e&&e()}var g=d.find("> .active"),h=e&&a.support.transition&&(g.length&&g.hasClass("fade")||!!d.find("> .fade").length);g.length&&h?g.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),"show")};a(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.3.7",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&"top"==this.affixed)return e=a-d&&"bottom"},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=Math.max(a(document).height(),a(document.body).height());"object"!=typeof d&&(f=e=d),"function"==typeof e&&(e=d.top(this.$element)),"function"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css("top","");var i="affix"+(h?"-"+h:""),j=a.Event(i+".bs.affix");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin="bottom"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace("affix","affixed")+".bs.affix")}"bottom"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery); \ No newline at end of file diff --git a/cmq/cmq/cmq.js b/cmq/cmq/cmq.js new file mode 100644 index 0000000..13dc883 --- /dev/null +++ b/cmq/cmq/cmq.js @@ -0,0 +1,129 @@ +var isNav4, isNav6, isIE4; +setBrowser(); + +function setBrowser() +{ + if (navigator.appVersion.charAt(0) == "4") + { + if (navigator.appName.indexOf("Explorer") >= 0) + { + isIE4 = true; + } + else + { + isNav4 = true; + } + } + else if (navigator.appVersion.charAt(0) > "4") + { + isNav6 = true; + } +} + +function getStyleBySelector( selector ) +{ + if (!isNav6) + { + return null; + } + var sheetList = document.styleSheets; + var ruleList; + var i, j; + + /* look through stylesheets in reverse order that + they appear in the document */ + for (i=sheetList.length-1; i >= 0; i--) + { + ruleList = sheetList[i].cssRules; + for (j=0; jN7~6nj1~U*C|Nk$x-lIae zTUF0yvj7`2GYOxcJ*)oX?%l_~Ub{B@;{5r~{b$dvIc+u%$^bjYIb6d%xEIe@QFp-D zo}G<$I~@03CMUmTBoA33Kg;3El$5uy0b5}szWL?Lx1+ajKj}YxdMg0Z(gIts3ELqf z?%CP-=7Zh-u>Z`NO{<6>afI1M9jMDv^2_7n-~Dv);s?FT2hW|O*X89j(b7VHKYvd1 zBO|o@@gpxd#yMQWJwLL0^=zRo)M*L%8JDYqiEu;u#!j80k?Lyt=hZ7Z*xx6!z`b~8 zVE>_V2fDNn65ncY=6ieg5avRN7lv z2^o0>hlht;>@rOl3LC?hY_$39#tqtAUWWCMJD@=31i0xAvEz1oz4*{rZ7qK*;Rfm) zm2@X?l#)jj6ob^zrAuC8larG)#)RfinV6U$kH-_R6VQYxY;crD?9n@So`^%GGTKyD zR#IeSBo!7G`c-0MW2vB^AgC4u2XTl6S0D07ro`L^V>7V1xk=H{(VS3wd%Nk1dwO~( zGc%Ktl9FhCemZ07-Tv}aS<^Kb9Km<4m0redxkBNmCagnDez?)Yb0CsnGsidTY>~_2NO@%|?;3P(9 zJ}JWN$S13eitV>bldrE|_jyp!fEr5Q-q_fn zDCRJTI2;bsZ!=JVBNZ10n#VTGQ`INkOr&a{FRL9`T3Vv4tSsv7?d8tlO+qIScngc3 z2L}hbB!UsRTZqo!ZhLXz!e8o>n0RP8u(-HL85tSma=G|_nZO$x8@*0gtq*Wha|L%B zOOn>rC+FY1@p%Xuh>3~eO`V>eP6Go2-fLO{udlD?|E<;sxCsf~y6wNE5AVqp=Dmn& zHiX5;$5UcrB9*g#s1&pgDpLb30VmV}u&u4lbT`q{#|oRC3L}xnlmmDZ)6>)BcDsFw zs1E>r8ydkcoI@+YiRR|!paY=P0i!OY2R(s9A4=;e`eKC@p{RYm#v`Mjn2 z`uceHTUc1obU-tekS24(!+y1b40`$i5UBR{_Pqa{PA6Tta>YwpbU-tiGfJleg`PgN zfO}F?Q)zZ~meSJFxZ?^m(`lm#O)${XhhD+G2?+^QQBmO)y2ga&o~bEiFwoM6QJI>W z@<|E}r<6vMdMg|W6s9Kiddn)IT1tddMvn1i6~@8TvWnKi78aL|Yhi2b{(afP)OU{T0{}*=^Xf3a!JB4(4o#jgJA3O+d zd0m0#1_u*W$Tm1GU$$n0!^esL>lTx`JB4hMk3AdGO+K}-{oZC}vnNaeQE;r@W*rRY zHmd>*U*loe=pGNnMzB@W&oQ$MLa;49EGo&A)GF V=QjL|yD$I%002ovPDHLkV1iGh=}G_q literal 0 HcmV?d00001 diff --git a/cmq/cmq/cmq.svg b/cmq/cmq/cmq.svg new file mode 100644 index 0000000..af7b98c --- /dev/null +++ b/cmq/cmq/cmq.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cmq/cmq/configserver.css b/cmq/cmq/configserver.css new file mode 100644 index 0000000..353ae0a --- /dev/null +++ b/cmq/cmq/configserver.css @@ -0,0 +1,76 @@ +.icon-configserver { + color: #990000; +} +.btn-default:active, +.btn-default:visited, +.btn-default:focus, +.btn-default { + background:#FFFFFF; + border-radius:3px; + border:1px solid #A6C150; + color:#990000 !important; +} +.btn-default:hover { + border:1px solid #A6C150; + background: #F5F5F5; +} +input[type=text], select { + -webkit-transition: all 0.30s ease-in-out; + -moz-transition: all 0.30s ease-in-out; + -ms-transition: all 0.30s ease-in-out; + -o-transition: all 0.30s ease-in-out; + transition: all 0.30s ease-in-out; + border-radius:3px; + outline: none; + padding: 3px 0px 3px 3px; + margin: 5px 1px 3px 0px; + border: 1px solid #990000; +} +input[type=text]:focus, select:focus { + box-shadow: 0 0 5px #CC0000; + padding: 3px 0px 3px 3px; + margin: 5px 1px 3px 0px; + border: 1px solid #990000; +} +.td-btn { + width: 200px; +} +.td-text { +} +th { + background: #F4F4EA; +} +.table tbody>tr>td { + vertical-align: middle; +} +.panel-default > .panel-heading-cxs { + font-weight: bold; + background: #F4F4EA; +} +.panel-default > .panel-footer-cxs { + font-weight: bold; + background: #F4F4EA; +} +#loader { + position: absolute; + left: 50%; + top: 50%; + z-index: 1; + margin: -75px 0 0 -75px; + border: 16px solid #F4F4EA; + border-radius: 50%; + border-top: 16px solid #990000; + border-bottom: 16px solid #990000; + width: 120px; + height: 120px; + -webkit-animation: spin 2s linear infinite; + animation: spin 2s linear infinite; +} +@-webkit-keyframes spin { + 0% { -webkit-transform: rotate(0deg); } + 100% { -webkit-transform: rotate(360deg); } +} +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} diff --git a/cmq/cmq/jquery.min.js b/cmq/cmq/jquery.min.js new file mode 100644 index 0000000..e836475 --- /dev/null +++ b/cmq/cmq/jquery.min.js @@ -0,0 +1,5 @@ +/*! jQuery v1.12.4 | (c) jQuery Foundation | jquery.org/license */ +!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=a.document,e=c.slice,f=c.concat,g=c.push,h=c.indexOf,i={},j=i.toString,k=i.hasOwnProperty,l={},m="1.12.4",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return e.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:e.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a){return n.each(this,a)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(e.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor()},push:g,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(n.isPlainObject(c)||(b=n.isArray(c)))?(b?(b=!1,f=a&&n.isArray(a)?a:[]):f=a&&n.isPlainObject(a)?a:{},g[d]=n.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray||function(a){return"array"===n.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){var b=a&&a.toString();return!n.isArray(a)&&b-parseFloat(b)+1>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==n.type(a)||a.nodeType||n.isWindow(a))return!1;try{if(a.constructor&&!k.call(a,"constructor")&&!k.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(!l.ownFirst)for(b in a)return k.call(a,b);for(b in a);return void 0===b||k.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?i[j.call(a)]||"object":typeof a},globalEval:function(b){b&&n.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b){var c,d=0;if(s(a)){for(c=a.length;c>d;d++)if(b.call(a[d],d,a[d])===!1)break}else for(d in a)if(b.call(a[d],d,a[d])===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):g.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(h)return h.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,e,g=0,h=[];if(s(a))for(d=a.length;d>g;g++)e=b(a[g],g,c),null!=e&&h.push(e);else for(g in a)e=b(a[g],g,c),null!=e&&h.push(e);return f.apply([],h)},guid:1,proxy:function(a,b){var c,d,f;return"string"==typeof b&&(f=a[b],b=a,a=f),n.isFunction(a)?(c=e.call(arguments,2),d=function(){return a.apply(b||this,c.concat(e.call(arguments)))},d.guid=a.guid=a.guid||n.guid++,d):void 0},now:function(){return+new Date},support:l}),"function"==typeof Symbol&&(n.fn[Symbol.iterator]=c[Symbol.iterator]),n.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(a,b){i["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=!!a&&"length"in a&&a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ga(),z=ga(),A=ga(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+M+"))|)"+L+"*\\]",O=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+N+")*)|.*)\\)|)",P=new RegExp(L+"+","g"),Q=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),R=new RegExp("^"+L+"*,"+L+"*"),S=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),T=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),U=new RegExp(O),V=new RegExp("^"+M+"$"),W={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M+"|[*])"),ATTR:new RegExp("^"+N),PSEUDO:new RegExp("^"+O),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},X=/^(?:input|select|textarea|button)$/i,Y=/^h\d$/i,Z=/^[^{]+\{\s*\[native \w/,$=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,_=/[+~]/,aa=/'|\\/g,ba=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),ca=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},da=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(ea){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fa(a,b,d,e){var f,h,j,k,l,o,r,s,w=b&&b.ownerDocument,x=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==x&&9!==x&&11!==x)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==x&&(o=$.exec(a)))if(f=o[1]){if(9===x){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(w&&(j=w.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(o[2])return H.apply(d,b.getElementsByTagName(a)),d;if((f=o[3])&&c.getElementsByClassName&&b.getElementsByClassName)return H.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==x)w=b,s=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(aa,"\\$&"):b.setAttribute("id",k=u),r=g(a),h=r.length,l=V.test(k)?"#"+k:"[id='"+k+"']";while(h--)r[h]=l+" "+qa(r[h]);s=r.join(","),w=_.test(a)&&oa(b.parentNode)||b}if(s)try{return H.apply(d,w.querySelectorAll(s)),d}catch(y){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(Q,"$1"),b,d,e)}function ga(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ha(a){return a[u]=!0,a}function ia(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ja(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function ka(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function la(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function na(a){return ha(function(b){return b=+b,ha(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function oa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=fa.support={},f=fa.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fa.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ia(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ia(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Z.test(n.getElementsByClassName),c.getById=ia(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return"undefined"!=typeof b.getElementsByClassName&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=Z.test(n.querySelectorAll))&&(ia(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ia(function(a){var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Z.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ia(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",O)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Z.test(o.compareDocumentPosition),t=b||Z.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return ka(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?ka(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},fa.matches=function(a,b){return fa(a,null,null,b)},fa.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(T,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fa(b,n,null,[a]).length>0},fa.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fa.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fa.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fa.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fa.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fa.selectors={cacheLength:50,createPseudo:ha,match:W,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ba,ca),a[3]=(a[3]||a[4]||a[5]||"").replace(ba,ca),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fa.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fa.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return W.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&U.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ba,ca).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fa.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(P," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fa.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ha(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ha(function(a){var b=[],c=[],d=h(a.replace(Q,"$1"));return d[u]?ha(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ha(function(a){return function(b){return fa(a,b).length>0}}),contains:ha(function(a){return a=a.replace(ba,ca),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ha(function(a){return V.test(a||"")||fa.error("unsupported lang: "+a),a=a.replace(ba,ca).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Y.test(a.nodeName)},input:function(a){return X.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:na(function(){return[0]}),last:na(function(a,b){return[b-1]}),eq:na(function(a,b,c){return[0>c?c+b:c]}),even:na(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:na(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:na(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:na(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function ra(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j,k=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(j=b[u]||(b[u]={}),i=j[b.uniqueID]||(j[b.uniqueID]={}),(h=i[d])&&h[0]===w&&h[1]===f)return k[2]=h[2];if(i[d]=k,k[2]=a(b,c,g))return!0}}}function sa(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ta(a,b,c){for(var d=0,e=b.length;e>d;d++)fa(a,b[d],c);return c}function ua(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(c&&!c(f,d,e)||(g.push(f),j&&b.push(h)));return g}function va(a,b,c,d,e,f){return d&&!d[u]&&(d=va(d)),e&&!e[u]&&(e=va(e,f)),ha(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ta(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ua(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ua(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ua(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function wa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ra(function(a){return a===b},h,!0),l=ra(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[ra(sa(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return va(i>1&&sa(m),i>1&&qa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(Q,"$1"),c,e>i&&wa(a.slice(i,e)),f>e&&wa(a=a.slice(e)),f>e&&qa(a))}m.push(c)}return sa(m)}function xa(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=F.call(i));u=ua(u)}H.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&fa.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ha(f):f}return h=fa.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xa(e,d)),f.selector=a}return f},i=fa.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ba,ca),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=W.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ba,ca),_.test(j[0].type)&&oa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qa(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,!b||_.test(a)&&oa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ia(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ia(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ja("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ia(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ja("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ia(function(a){return null==a.getAttribute("disabled")})||ja(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fa}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.uniqueSort=n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},v=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},w=n.expr.match.needsContext,x=/^<([\w-]+)\s*\/?>(?:<\/\1>|)$/,y=/^.[^:#\[\.,]*$/;function z(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(y.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return n.inArray(a,b)>-1!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;e>b;b++)if(n.contains(d[b],this))return!0}));for(b=0;e>b;b++)n.find(a,d[b],c);return c=this.pushStack(e>1?n.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(z(this,a||[],!1))},not:function(a){return this.pushStack(z(this,a||[],!0))},is:function(a){return!!z(this,"string"==typeof a&&w.test(a)?n(a):a||[],!1).length}});var A,B=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=n.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||A,"string"==typeof a){if(e="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:B.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),x.test(e[1])&&n.isPlainObject(b))for(e in b)n.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}if(f=d.getElementById(e[2]),f&&f.parentNode){if(f.id!==e[2])return A.find(a);this.length=1,this[0]=f}return this.context=d,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof c.ready?c.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};C.prototype=n.fn,A=n(d);var D=/^(?:parents|prev(?:Until|All))/,E={children:!0,contents:!0,next:!0,prev:!0};n.fn.extend({has:function(a){var b,c=n(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(n.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=w.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?n.inArray(this[0],n(a)):n.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.uniqueSort(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function F(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return u(a,"parentNode")},parentsUntil:function(a,b,c){return u(a,"parentNode",c)},next:function(a){return F(a,"nextSibling")},prev:function(a){return F(a,"previousSibling")},nextAll:function(a){return u(a,"nextSibling")},prevAll:function(a){return u(a,"previousSibling")},nextUntil:function(a,b,c){return u(a,"nextSibling",c)},prevUntil:function(a,b,c){return u(a,"previousSibling",c)},siblings:function(a){return v((a.parentNode||{}).firstChild,a)},children:function(a){return v(a.firstChild)},contents:function(a){return n.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(E[a]||(e=n.uniqueSort(e)),D.test(a)&&(e=e.reverse())),this.pushStack(e)}});var G=/\S+/g;function H(a){var b={};return n.each(a.match(G)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?H(a):n.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h-1)f.splice(c,1),h>=c&&h--}),this},has:function(a){return a?n.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=!0,c||j.disable(),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().progress(c.notify).done(c.resolve).fail(c.reject):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=e.call(arguments),d=c.length,f=1!==d||a&&n.isFunction(a.promise)?d:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?e.call(arguments):d,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(d>1)for(i=new Array(d),j=new Array(d),k=new Array(d);d>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().progress(h(b,j,i)).done(h(b,k,c)).fail(g.reject):--f;return f||g.resolveWith(k,c),g.promise()}});var I;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(I.resolveWith(d,[n]),n.fn.triggerHandler&&(n(d).triggerHandler("ready"),n(d).off("ready"))))}});function J(){d.addEventListener?(d.removeEventListener("DOMContentLoaded",K),a.removeEventListener("load",K)):(d.detachEvent("onreadystatechange",K),a.detachEvent("onload",K))}function K(){(d.addEventListener||"load"===a.event.type||"complete"===d.readyState)&&(J(),n.ready())}n.ready.promise=function(b){if(!I)if(I=n.Deferred(),"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll)a.setTimeout(n.ready);else if(d.addEventListener)d.addEventListener("DOMContentLoaded",K),a.addEventListener("load",K);else{d.attachEvent("onreadystatechange",K),a.attachEvent("onload",K);var c=!1;try{c=null==a.frameElement&&d.documentElement}catch(e){}c&&c.doScroll&&!function f(){if(!n.isReady){try{c.doScroll("left")}catch(b){return a.setTimeout(f,50)}J(),n.ready()}}()}return I.promise(b)},n.ready.promise();var L;for(L in n(l))break;l.ownFirst="0"===L,l.inlineBlockNeedsLayout=!1,n(function(){var a,b,c,e;c=d.getElementsByTagName("body")[0],c&&c.style&&(b=d.createElement("div"),e=d.createElement("div"),e.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(e).appendChild(b),"undefined"!=typeof b.style.zoom&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",l.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(e))}),function(){var a=d.createElement("div");l.deleteExpando=!0;try{delete a.test}catch(b){l.deleteExpando=!1}a=null}();var M=function(a){var b=n.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b},N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(O,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}n.data(a,b,c)}else c=void 0; +}return c}function Q(a){var b;for(b in a)if(("data"!==b||!n.isEmptyObject(a[b]))&&"toJSON"!==b)return!1;return!0}function R(a,b,d,e){if(M(a)){var f,g,h=n.expando,i=a.nodeType,j=i?n.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||n.guid++:h),j[k]||(j[k]=i?{}:{toJSON:n.noop}),"object"!=typeof b&&"function"!=typeof b||(e?j[k]=n.extend(j[k],b):j[k].data=n.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[n.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[n.camelCase(b)])):f=g,f}}function S(a,b,c){if(M(a)){var d,e,f=a.nodeType,g=f?n.cache:a,h=f?a[n.expando]:n.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){n.isArray(b)?b=b.concat(n.map(b,n.camelCase)):b in d?b=[b]:(b=n.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!Q(d):!n.isEmptyObject(d))return}(c||(delete g[h].data,Q(g[h])))&&(f?n.cleanData([a],!0):l.deleteExpando||g!=g.window?delete g[h]:g[h]=void 0)}}}n.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?n.cache[a[n.expando]]:a[n.expando],!!a&&!Q(a)},data:function(a,b,c){return R(a,b,c)},removeData:function(a,b){return S(a,b)},_data:function(a,b,c){return R(a,b,c,!0)},_removeData:function(a,b){return S(a,b,!0)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=n.data(f),1===f.nodeType&&!n._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d])));n._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){n.data(this,a)}):arguments.length>1?this.each(function(){n.data(this,a,b)}):f?P(f,a,n.data(f,a)):void 0},removeData:function(a){return this.each(function(){n.removeData(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=n._data(a,b),c&&(!d||n.isArray(c)?d=n._data(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return n._data(a,c)||n._data(a,c,{empty:n.Callbacks("once memory").add(function(){n._removeData(a,b+"queue"),n._removeData(a,c)})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthh;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},Z=/^(?:checkbox|radio)$/i,$=/<([\w:-]+)/,_=/^$|\/(?:java|ecma)script/i,aa=/^\s+/,ba="abbr|article|aside|audio|bdi|canvas|data|datalist|details|dialog|figcaption|figure|footer|header|hgroup|main|mark|meter|nav|output|picture|progress|section|summary|template|time|video";function ca(a){var b=ba.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}!function(){var a=d.createElement("div"),b=d.createDocumentFragment(),c=d.createElement("input");a.innerHTML="
a",l.leadingWhitespace=3===a.firstChild.nodeType,l.tbody=!a.getElementsByTagName("tbody").length,l.htmlSerialize=!!a.getElementsByTagName("link").length,l.html5Clone="<:nav>"!==d.createElement("nav").cloneNode(!0).outerHTML,c.type="checkbox",c.checked=!0,b.appendChild(c),l.appendChecked=c.checked,a.innerHTML="",l.noCloneChecked=!!a.cloneNode(!0).lastChild.defaultValue,b.appendChild(a),c=d.createElement("input"),c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),a.appendChild(c),l.checkClone=a.cloneNode(!0).cloneNode(!0).lastChild.checked,l.noCloneEvent=!!a.addEventListener,a[n.expando]=1,l.attributes=!a.getAttribute(n.expando)}();var da={option:[1,""],legend:[1,"
","
"],area:[1,"",""],param:[1,"",""],thead:[1,"","
"],tr:[2,"","
"],col:[2,"","
"],td:[3,"","
"],_default:l.htmlSerialize?[0,"",""]:[1,"X
","
"]};da.optgroup=da.option,da.tbody=da.tfoot=da.colgroup=da.caption=da.thead,da.th=da.td;function ea(a,b){var c,d,e=0,f="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||n.nodeName(d,b)?f.push(d):n.merge(f,ea(d,b));return void 0===b||b&&n.nodeName(a,b)?n.merge([a],f):f}function fa(a,b){for(var c,d=0;null!=(c=a[d]);d++)n._data(c,"globalEval",!b||n._data(b[d],"globalEval"))}var ga=/<|&#?\w+;/,ha=/r;r++)if(g=a[r],g||0===g)if("object"===n.type(g))n.merge(q,g.nodeType?[g]:g);else if(ga.test(g)){i=i||p.appendChild(b.createElement("div")),j=($.exec(g)||["",""])[1].toLowerCase(),m=da[j]||da._default,i.innerHTML=m[1]+n.htmlPrefilter(g)+m[2],f=m[0];while(f--)i=i.lastChild;if(!l.leadingWhitespace&&aa.test(g)&&q.push(b.createTextNode(aa.exec(g)[0])),!l.tbody){g="table"!==j||ha.test(g)?""!==m[1]||ha.test(g)?0:i:i.firstChild,f=g&&g.childNodes.length;while(f--)n.nodeName(k=g.childNodes[f],"tbody")&&!k.childNodes.length&&g.removeChild(k)}n.merge(q,i.childNodes),i.textContent="";while(i.firstChild)i.removeChild(i.firstChild);i=p.lastChild}else q.push(b.createTextNode(g));i&&p.removeChild(i),l.appendChecked||n.grep(ea(q,"input"),ia),r=0;while(g=q[r++])if(d&&n.inArray(g,d)>-1)e&&e.push(g);else if(h=n.contains(g.ownerDocument,g),i=ea(p.appendChild(g),"script"),h&&fa(i),c){f=0;while(g=i[f++])_.test(g.type||"")&&c.push(g)}return i=null,p}!function(){var b,c,e=d.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(l[b]=c in a)||(e.setAttribute(c,"t"),l[b]=e.attributes[c].expando===!1);e=null}();var ka=/^(?:input|select|textarea)$/i,la=/^key/,ma=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,na=/^(?:focusinfocus|focusoutblur)$/,oa=/^([^.]*)(?:\.(.+)|)/;function pa(){return!0}function qa(){return!1}function ra(){try{return d.activeElement}catch(a){}}function sa(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)sa(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=qa;else if(!e)return a;return 1===f&&(g=e,e=function(a){return n().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=n.guid++)),a.each(function(){n.event.add(this,b,e,d,c)})}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=n.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return"undefined"==typeof n||a&&n.event.triggered===a.type?void 0:n.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(G)||[""],h=b.length;while(h--)f=oa.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=n.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=n.event.special[o]||{},l=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},i),(m=g[o])||(m=g[o]=[],m.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,l):m.push(l),n.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n.hasData(a)&&n._data(a);if(r&&(k=r.events)){b=(b||"").match(G)||[""],j=b.length;while(j--)if(h=oa.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=m.length;while(f--)g=m[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(m.splice(f,1),g.selector&&m.delegateCount--,l.remove&&l.remove.call(a,g));i&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(k)&&(delete r.handle,n._removeData(a,"events"))}},trigger:function(b,c,e,f){var g,h,i,j,l,m,o,p=[e||d],q=k.call(b,"type")?b.type:b,r=k.call(b,"namespace")?b.namespace.split("."):[];if(i=m=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!na.test(q+n.event.triggered)&&(q.indexOf(".")>-1&&(r=q.split("."),q=r.shift(),r.sort()),h=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=f?2:3,b.namespace=r.join("."),b.rnamespace=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=e),c=null==c?[b]:n.makeArray(c,[b]),l=n.event.special[q]||{},f||!l.trigger||l.trigger.apply(e,c)!==!1)){if(!f&&!l.noBubble&&!n.isWindow(e)){for(j=l.delegateType||q,na.test(j+q)||(i=i.parentNode);i;i=i.parentNode)p.push(i),m=i;m===(e.ownerDocument||d)&&p.push(m.defaultView||m.parentWindow||a)}o=0;while((i=p[o++])&&!b.isPropagationStopped())b.type=o>1?j:l.bindType||q,g=(n._data(i,"events")||{})[b.type]&&n._data(i,"handle"),g&&g.apply(i,c),g=h&&i[h],g&&g.apply&&M(i)&&(b.result=g.apply(i,c),b.result===!1&&b.preventDefault());if(b.type=q,!f&&!b.isDefaultPrevented()&&(!l._default||l._default.apply(p.pop(),c)===!1)&&M(e)&&h&&e[q]&&!n.isWindow(e)){m=e[h],m&&(e[h]=null),n.event.triggered=q;try{e[q]()}catch(s){}n.event.triggered=void 0,m&&(e[h]=m)}return b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,d,f,g,h=[],i=e.call(arguments),j=(n._data(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())a.rnamespace&&!a.rnamespace.test(g.namespace)||(a.handleObj=g,a.data=g.data,d=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==d&&(a.result=d)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&("click"!==a.type||isNaN(a.button)||a.button<1))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>-1:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h]","i"),va=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,wa=/\s*$/g,Aa=ca(d),Ba=Aa.appendChild(d.createElement("div"));function Ca(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function Da(a){return a.type=(null!==n.find.attr(a,"type"))+"/"+a.type,a}function Ea(a){var b=ya.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Fa(a,b){if(1===b.nodeType&&n.hasData(a)){var c,d,e,f=n._data(a),g=n._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)n.event.add(b,c,h[c][d])}g.data&&(g.data=n.extend({},g.data))}}function Ga(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!l.noCloneEvent&&b[n.expando]){e=n._data(b);for(d in e.events)n.removeEvent(b,d,e.handle);b.removeAttribute(n.expando)}"script"===c&&b.text!==a.text?(Da(b).text=a.text,Ea(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),l.html5Clone&&a.innerHTML&&!n.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&Z.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:"input"!==c&&"textarea"!==c||(b.defaultValue=a.defaultValue)}}function Ha(a,b,c,d){b=f.apply([],b);var e,g,h,i,j,k,m=0,o=a.length,p=o-1,q=b[0],r=n.isFunction(q);if(r||o>1&&"string"==typeof q&&!l.checkClone&&xa.test(q))return a.each(function(e){var f=a.eq(e);r&&(b[0]=q.call(this,e,f.html())),Ha(f,b,c,d)});if(o&&(k=ja(b,a[0].ownerDocument,!1,a,d),e=k.firstChild,1===k.childNodes.length&&(k=e),e||d)){for(i=n.map(ea(k,"script"),Da),h=i.length;o>m;m++)g=k,m!==p&&(g=n.clone(g,!0,!0),h&&n.merge(i,ea(g,"script"))),c.call(a[m],g,m);if(h)for(j=i[i.length-1].ownerDocument,n.map(i,Ea),m=0;h>m;m++)g=i[m],_.test(g.type||"")&&!n._data(g,"globalEval")&&n.contains(j,g)&&(g.src?n._evalUrl&&n._evalUrl(g.src):n.globalEval((g.text||g.textContent||g.innerHTML||"").replace(za,"")));k=e=null}return a}function Ia(a,b,c){for(var d,e=b?n.filter(b,a):a,f=0;null!=(d=e[f]);f++)c||1!==d.nodeType||n.cleanData(ea(d)),d.parentNode&&(c&&n.contains(d.ownerDocument,d)&&fa(ea(d,"script")),d.parentNode.removeChild(d));return a}n.extend({htmlPrefilter:function(a){return a.replace(va,"<$1>")},clone:function(a,b,c){var d,e,f,g,h,i=n.contains(a.ownerDocument,a);if(l.html5Clone||n.isXMLDoc(a)||!ua.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(Ba.innerHTML=a.outerHTML,Ba.removeChild(f=Ba.firstChild)),!(l.noCloneEvent&&l.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(d=ea(f),h=ea(a),g=0;null!=(e=h[g]);++g)d[g]&&Ga(e,d[g]);if(b)if(c)for(h=h||ea(a),d=d||ea(f),g=0;null!=(e=h[g]);g++)Fa(e,d[g]);else Fa(a,f);return d=ea(f,"script"),d.length>0&&fa(d,!i&&ea(a,"script")),d=h=e=null,f},cleanData:function(a,b){for(var d,e,f,g,h=0,i=n.expando,j=n.cache,k=l.attributes,m=n.event.special;null!=(d=a[h]);h++)if((b||M(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)m[e]?n.event.remove(d,e):n.removeEvent(d,e,g.handle);j[f]&&(delete j[f],k||"undefined"==typeof d.removeAttribute?d[i]=void 0:d.removeAttribute(i),c.push(f))}}}),n.fn.extend({domManip:Ha,detach:function(a){return Ia(this,a,!0)},remove:function(a){return Ia(this,a)},text:function(a){return Y(this,function(a){return void 0===a?n.text(this):this.empty().append((this[0]&&this[0].ownerDocument||d).createTextNode(a))},null,a,arguments.length)},append:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.appendChild(a)}})},prepend:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&n.cleanData(ea(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&n.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return Y(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(ta,""):void 0;if("string"==typeof a&&!wa.test(a)&&(l.htmlSerialize||!ua.test(a))&&(l.leadingWhitespace||!aa.test(a))&&!da[($.exec(a)||["",""])[1].toLowerCase()]){a=n.htmlPrefilter(a);try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(ea(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=[];return Ha(this,arguments,function(b){var c=this.parentNode;n.inArray(this,a)<0&&(n.cleanData(ea(this)),c&&c.replaceChild(b,this))},a)}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=0,e=[],f=n(a),h=f.length-1;h>=d;d++)c=d===h?this:this.clone(!0),n(f[d])[b](c),g.apply(e,c.get());return this.pushStack(e)}});var Ja,Ka={HTML:"block",BODY:"block"};function La(a,b){var c=n(b.createElement(a)).appendTo(b.body),d=n.css(c[0],"display");return c.detach(),d}function Ma(a){var b=d,c=Ka[a];return c||(c=La(a,b),"none"!==c&&c||(Ja=(Ja||n("\n"; +print "\n"; diff --git a/cmq/da/admin/index.raw b/cmq/da/admin/index.raw new file mode 100644 index 0000000..b0e71b0 --- /dev/null +++ b/cmq/da/admin/index.raw @@ -0,0 +1,7 @@ +#!/usr/bin/perl + +$| = 1; + +print "HTTP/1.1 200 OK\n"; +print "Content-type: text/html\r\n\r\n"; +system ("/usr/local/directadmin/plugins/cmq/exec/cmq"); diff --git a/cmq/da/exec/da_cmq.cgi b/cmq/da/exec/da_cmq.cgi new file mode 100644 index 0000000..d197764 --- /dev/null +++ b/cmq/da/exec/da_cmq.cgi @@ -0,0 +1,147 @@ +#!/usr/bin/perl +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +# start main +use strict; +use File::Find; +use Fcntl qw(:DEFAULT :flock); +use Sys::Hostname qw(hostname); +use IPC::Open3; +use File::Copy; +use Digest::MD5; + +use lib '/etc/cmq/Modules'; +use ConfigServer::cmqUI; + +our ($script, $script_da, $images, %FORM, $myv, %daconfig, %ajaxsubs, %fullsubs); + +my %session; +if ($ENV{SESSION_ID} =~ /^\w+$/) { + open (my $SESSION, "<", "/usr/local/directadmin/data/sessions/da_sess_".$ENV{SESSION_ID}) or die "Security Error: No valid session key for [$ENV{SESSION_ID}]"; + flock ($SESSION, LOCK_SH); + my @data = <$SESSION>; + close ($SESSION); + chomp @data; + foreach my $line (@data) { + my ($name, $value) = split(/\=/,$line); + $session{$name} = $value; + } +} +if (($session{key} eq "") or ($session{ip} eq "") or ($session{key} ne $ENV{SESSION_KEY})) { + &loginfail("Security Error: No valid session key"); + exit; +} + +my ($ppid, $pexe) = &getexe(getppid()); +if ($pexe ne "/usr/local/directadmin/directadmin") { + print "Security Error: Invalid parent"; + exit; +} + +$script = "/CMD_PLUGINS_ADMIN/cmq/index.raw"; +$script_da = "/CMD_PLUGINS_ADMIN/cmq/index.raw"; +$images = "/CMD_PLUGINS_ADMIN/cmq/images"; +my $buffer = $ENV{'QUERY_STRING'}; +if ($buffer eq "") {$buffer = $ENV{POST}} +my @pairs = split(/&/, $buffer); +foreach my $pair (@pairs) { + my ($name, $value) = split(/=/, $pair); + $value =~ tr/+/ /; + $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; + $FORM{$name} = $value; +} + +my $bootstrapcss = ""; +my $jqueryjs = ""; +my $bootstrapjs = ""; +my $fontawesome = ""; + +my $versionfile = "/etc/cmq/cmqversion.txt"; +open (my $IN, "<", $versionfile) or die $!; +flock ($IN, LOCK_SH); +$myv = <$IN>; +close ($IN); +chomp $myv; + +unless ($FORM{action} eq "tailcmd" or $FORM{action} eq "tracking_detail" or $FORM{format} ne "" or $FORM{action} eq "help") { + print < + + + ConfigServer Mail Queues + + + $bootstrapcss + $fontawesome + + $jqueryjs + $bootstrapjs + + +
+
+
+
+

ConfigServer Mail Queues - cmq v$myv

+
+EOF + } else { + print < + + + $bootstrapcss + + $jqueryjs + $bootstrapjs + + +
+ +EOF +} + +ConfigServer::cmqUI::displayUI(\%FORM,$script,$script_da,$images,$myv); + + print < + \$("#loader").hide(); + window.parent.parent.scrollTo(0,0); + parent.resizeIframe(parent.document.getElementById("myiframe")); + + + +EOF + +sub getexe { + my $thispid = shift; + open (my $STAT, "<", "/proc/".$thispid."/stat"); + my $stat = <$STAT>; + close ($STAT); + chomp $stat; + $stat =~ /\w\s+(\d+)\s+[^\)]*$/; + my $ppid = $1; + my $exe = readlink("/proc/".$ppid."/exe"); + return ($ppid, $exe); +} +1; diff --git a/cmq/da/hooks/admin_img.html b/cmq/da/hooks/admin_img.html new file mode 100644 index 0000000..d430562 --- /dev/null +++ b/cmq/da/hooks/admin_img.html @@ -0,0 +1,4 @@ + +
+ ConfigServer Mail Queues +
diff --git a/cmq/da/hooks/admin_txt.html b/cmq/da/hooks/admin_txt.html new file mode 100644 index 0000000..d3b365d --- /dev/null +++ b/cmq/da/hooks/admin_txt.html @@ -0,0 +1 @@ +ConfigServer Mail Queues \ No newline at end of file diff --git a/cmq/da/plugin.conf b/cmq/da/plugin.conf new file mode 100644 index 0000000..dfebb67 --- /dev/null +++ b/cmq/da/plugin.conf @@ -0,0 +1,8 @@ +active=yes +author=WTTW +id=cmq +installed=yes +name=ConfigServer Mail Queues +update_url= +version=1.0 +version_url= diff --git a/cmq/da/scripts/install.sh b/cmq/da/scripts/install.sh new file mode 100644 index 0000000..ede7059 --- /dev/null +++ b/cmq/da/scripts/install.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +echo "This plugin is installed by installing csf from the root shell" + +exit 0; diff --git a/cmq/da/scripts/uninstall.sh b/cmq/da/scripts/uninstall.sh new file mode 100644 index 0000000..35cd4f5 --- /dev/null +++ b/cmq/da/scripts/uninstall.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +echo "This plugin is uninstalled by uninstalling csf from the root shell" + +exit 0; diff --git a/cmq/da/scripts/update.sh b/cmq/da/scripts/update.sh new file mode 100644 index 0000000..2fbca44 --- /dev/null +++ b/cmq/da/scripts/update.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +echo "This plugin is updated by updating csf from the root shell" + +exit 0; diff --git a/cmq/downloadservers b/cmq/downloadservers new file mode 100644 index 0000000..e7b430f --- /dev/null +++ b/cmq/downloadservers @@ -0,0 +1,2 @@ +#download.configserver.com +#download2.configserver.com diff --git a/cmq/install.cpanel.sh b/cmq/install.cpanel.sh new file mode 100644 index 0000000..7164d10 --- /dev/null +++ b/cmq/install.cpanel.sh @@ -0,0 +1,64 @@ +#!/bin/sh +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +PATH=$PATH:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin + +#First replace: +if [ -e "/usr/local/cpanel/3rdparty/bin/perl" ]; then + find ./ -type f -exec sed -i 's%^#\!/usr/bin/perl%#\!/usr/local/cpanel/3rdparty/bin/perl%' {} \; +fi + +mkdir /etc/cmq +chmod 700 /etc/cmq + +mkdir /usr/local/cpanel/whostmgr/docroot/cgi/configserver +chmod 700 /usr/local/cpanel/whostmgr/docroot/cgi/configserver +mkdir /usr/local/cpanel/whostmgr/docroot/cgi/configserver/cmq +chmod 700 /usr/local/cpanel/whostmgr/docroot/cgi/configserver/cmq + +cp -avf cpanel/cmq.cgi /usr/local/cpanel/whostmgr/docroot/cgi/configserver/cmq.cgi +chmod -v 700 /usr/local/cpanel/whostmgr/docroot/cgi/configserver/cmq.cgi + +cp -avf Modules /etc/cmq/ +cp -avf cmqversion.txt /etc/cmq/ +cp -avf downloadservers /etc/cmq/ +cp -avf INSTALL.txt /etc/cmq/ +cp -avf uninstall.sh /etc/cmq/ +chmod 700 /etc/cmq/uninstall.sh + +cp -avf cmq/ /usr/local/cpanel/whostmgr/docroot/cgi/configserver/ +cp -avf cpanel/cmq.conf /etc/cmq/cmq.conf +cp -avf upgrade.sh /etc/cmq/upgrade.sh +chmod 700 /etc/cmq/upgrade.sh +cp -af cmq/cmq.png /usr/local/cpanel/whostmgr/docroot/addon_plugins/ +cp -af cpanel/cmq.tmpl /usr/local/cpanel/whostmgr/docroot/templates/ + +/usr/local/cpanel/bin/register_appconfig /etc/cmq/cmq.conf + +/bin/rm -f /usr/local/cpanel/whostmgr/docroot/cgi/addon_cmq.cgi +/bin/rm -f /usr/local/cpanel/whostmgr/docroot/cgi/cmqversion.txt +/bin/rm -Rf /usr/local/cpanel/whostmgr/docroot/cgi/cmq + +#Second replace +if [ -e "/usr/local/cpanel/3rdparty/bin/perl" ]; then + find ./ -type f -exec sed -i 's%^#\!/usr/local/cpanel/3rdparty/bin/perl%#\!/usr/bin/perl%' {} \; +fi + +echo "ConfigServer Mail Queues has been installed." +exit diff --git a/cmq/install.directadmin.sh b/cmq/install.directadmin.sh new file mode 100644 index 0000000..1e743e5 --- /dev/null +++ b/cmq/install.directadmin.sh @@ -0,0 +1,58 @@ +#!/bin/sh +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### + +mkdir /etc/cmq +chmod 700 /etc/cmq + +mkdir /usr/local/cpanel/whostmgr/docroot/cgi/configserver +chmod 700 /usr/local/cpanel/whostmgr/docroot/cgi/configserver +mkdir /usr/local/cpanel/whostmgr/docroot/cgi/configserver/cmq +chmod 700 /usr/local/cpanel/whostmgr/docroot/cgi/configserver/cmq + +cp -avf cpanel/cmq.cgi /usr/local/cpanel/whostmgr/docroot/cgi/configserver/cmq.cgi +chmod -v 700 /usr/local/cpanel/whostmgr/docroot/cgi/configserver/cmq.cgi + +cp -avf Modules /etc/cmq/ +cp -avf cmqversion.txt /etc/cmq/ +cp -avf downloadservers /etc/cmq/ +cp -avf INSTALL.txt /etc/cmq/ +cp -avf uninstall.sh /etc/cmq/ +chmod 700 /etc/cmq/uninstall.sh + +mkdir -p /usr/local/directadmin/plugins/cmq/ +chmod 711 /usr/local/directadmin/plugins/cmq/ +chown diradmin:diradmin /usr/local/directadmin/plugins/cmq/ +cp -avf da/* /usr/local/directadmin/plugins/cmq/ +cp -avf cmq/* /usr/local/directadmin/plugins/cmq/images/ + +export PATH=$PATH; +gcc -o /usr/local/directadmin/plugins/cmq/exec/cmq cmq.c +find /usr/local/directadmin/plugins/cmq/ -type d -exec chmod -v 755 {} \; +find /usr/local/directadmin/plugins/cmq/ -type f -exec chmod -v 644 {} \; +chown -Rv diradmin:diradmin /usr/local/directadmin/plugins/cmq +chmod -v 755 /usr/local/directadmin/plugins/cmq/admin/index.html +chmod -v 755 /usr/local/directadmin/plugins/cmq/admin/index.raw +chmod -v 755 /usr/local/directadmin/plugins/cmq/exec/da_cmq.cgi +chmod -v 755 /usr/local/directadmin/plugins/cmq/scripts/* +chown -v root:root /usr/local/directadmin/plugins/cmq/exec/cmq +chmod -v 4755 /usr/local/directadmin/plugins/cmq/exec/cmq + +echo "ConfigServer Mail Queues has been installed." +exit diff --git a/cmq/install.sh b/cmq/install.sh new file mode 100644 index 0000000..9c4a199 --- /dev/null +++ b/cmq/install.sh @@ -0,0 +1,30 @@ +#!/bin/sh +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +PATH=$PATH:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin + +if [ -e "/usr/local/cpanel/version" ]; then + echo "Running cmq cPanel installer" + echo + sh install.cpanel.sh +elif [ -e "/usr/local/directadmin/directadmin" ]; then + echo "Running cmq DirectAdmin installer" + echo + sh install.directadmin.sh +fi diff --git a/cmq/license.txt b/cmq/license.txt new file mode 100644 index 0000000..f288702 --- /dev/null +++ b/cmq/license.txt @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/cmq/uninstall.sh b/cmq/uninstall.sh new file mode 100644 index 0000000..4b9fdea --- /dev/null +++ b/cmq/uninstall.sh @@ -0,0 +1,56 @@ +#!/bin/sh +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +PATH=$PATH:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin + +if [ -e "/usr/local/cpanel/version" ]; then + + echo "Running cmq cPanel uninstaller" + echo + + if [ -e "/usr/local/cpanel/bin/unregister_appconfig" ]; then + cd / + /usr/local/cpanel/bin/unregister_appconfig cmq + else + if [ ! -e "/var/cpanel/apps/cmq.conf" ]; then + /bin/rm -fv /var/cpanel/apps/cmq.conf + fi + fi + + /bin/rm -fv /usr/local/cpanel/whostmgr/docroot/cgi/addon_cmq.cgi + /bin/rm -fv /usr/local/cpanel/whostmgr/docroot/cgi/cmqversion.txt + /bin/rm -Rfv /usr/local/cpanel/whostmgr/docroot/cgi/cmq + + /bin/rm -fv /usr/local/cpanel/whostmgr/docroot/cgi/configserver/cmq.cgi + /bin/rm -fv /usr/local/cpanel/whostmgr/docroot/cgi/configserver/cmqversion.txt + /bin/rm -Rfv /usr/local/cpanel/whostmgr/docroot/cgi/configserver/cmq + +elif [ -e "/usr/local/directadmin/directadmin" ]; then + + echo "Running cmq DirectAdmin uninstaller" + echo + + /bin/rm -Rfv /usr/local/directadmin/plugins/cmq + +fi + +/bin/rm -Rfv /etc/cmq + +echo "ConfigServer Mail Queues has been uninstalled." +exit diff --git a/cmq/upgrade.sh b/cmq/upgrade.sh new file mode 100644 index 0000000..2a9bd4e --- /dev/null +++ b/cmq/upgrade.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +if [ -e "/usr/local/cpanel/bin/register_appconfig" ]; then + if [ -e "/usr/local/cpanel/whostmgr/docroot/cgi/addon_cmq.cgi" ]; then + /usr/local/cpanel/bin/register_appconfig /usr/local/cpanel/whostmgr/docroot/cgi/configserver/cmq/cmq.conf + + /bin/rm -f /usr/local/cpanel/whostmgr/docroot/cgi/addon_cmq.cgi + /bin/rm -f /usr/local/cpanel/whostmgr/docroot/cgi/cmqversion.txt + /bin/rm -Rf /usr/local/cpanel/whostmgr/docroot/cgi/cmq + fi +fi diff --git a/cse.tgz b/cse.tgz new file mode 100644 index 0000000000000000000000000000000000000000..a5e03c6217dc19be94cfb5e3776e67cf46ace881 GIT binary patch literal 214154 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쫴obz68lnoyAuD9%L)R^+)-m5fuYf< zKD_JTqQRN_i1%s}A}^1<`j(9joYt2Sw-h=NQ@eIbx|&oR&3(J` zbdHs}*Jm?zLV-zfc2m**y`>r-1o$^qTj_i;2wK0%)UsV@U2^^hzaiGWVN-f3-YfSX zsgH`hM%P@sexL!j`g^ENmr7X)&1ef9BOIZVs+Axg*89kql77jTZ5%hnj(Eyo5^e7t?$Zx$urecdQlYWnp_mb7AC9JI#UkMqcj zsK%gzi_tq-x4b^L`Rim=qxh+ zode`dm(Xe&?2VJO*V=D$pL@^RicGk_)kHZwG^(CrZ`cU%gO&323dh|MBU9WBlf5mO)Dpqz}xh})BGbz+FL_Uv; z{bkg_n+Wnpo*VA!2R}SITtZdy*wo)u|8l@dyX1{RD^IcRr_rNp&K(J#n8}k3^($5K zUbRn7PHH%xnCg}nET2V~ll$nE(`+Ac@ z-RBQ;9Gel?RgP@t-54LOCAFF=X>vs_*K?x#vzYJsbTP7HG+e^TnFDt*Na-u$BWlV8M^bu3Ul&uXCJ~e zEA~ZP+<5oWtlw@M>)<2B0eg=Q2p3jb&2{fU?5mCT`*=C8h4bDtwXx8R`ea++UAw}U z*N@b+VRP&U`ri*&`W#jw`cFLk?}i?JuJp5ZkcH`QF5tWL*8;Q=MBn{W(PMC$^ z<`Zr0lkUOkFjt4nJ;aZY^r6%Kq7|H;8}&waLc*bmFfD^>H*#6F@0xCI_Pk=0{BF2H zR%`psjF;g$1Il7iZ9s6@Bl!4c=!vi2-)f!nesyMe>xAoa1cr@IjFyoJV_8r;{RfI&%97k*8>T z6QjH}yvxQhFGLS(Uj9_02mgA)_^PNwi%QE5M-DxasPsJ^?r+w(Kx8&XzTh}@BxFtA zz{I}EQ`hdO)N@YMYT-MDH(+hag%q^ikm>z3itpOK?Q^Yf&Qode61s-kXoyD1Tz$;C zYU=77GWu$g(dkyp?RUR?4;s}qd5|?0Lxov+Yp#aBPt)lvm^<4V$)ovg*Ii>v<&Y?} zSDetq5yM;U^~T4JACTN`H}LYlmQ|X}4cwtEPnB2qKJn~5{%wZh84(kZuAo1njr9^l zR%%wGUs#T|G)`N`Cl20@Hr)Db*I~z*{-UPN4hw%{P1FfrWwIfo$hfreUMpZ6=R7yw+&2oRp3}I0Y+^ zzLpWp`)w;eLZQ#vt5Q|=aTu!~`%Zhof#Xju!i@#a4u&A{N3&H|xy!3KpCwgBnuML* zd=I0Uoy51#Xj(w~?Wo*g4TpoqlO~>b?{x7FCuB%ZZ$2`Va|mTy)%t$kopbfzIalid zeZdpdgAd(5Sg(J>wN{7Fm!ayJxBhIIV5M?7D?*OTSejVaL(#apGQ>vZiR!#)V0OYg z?h{t(#|zBa=-V7QYAn%DQZ|JcyAT56cFkJ%V?@^;+HtYF(IFhe<$6f4@#&`lFO`)P z=&jkT!enKY3l)QTJ~fu550kIlxw%15nmh`HSc!~%oa0^@`OVzc`fyl$Ree^W4t`Ls zW~??@8xMO|m?UCmZ1!McGM<0M2G?Vp9a5r z=W%_}6b!%Hqkr4>u&u^$@U^5`z`yWt(rECLG=F%0c(fz7qc*-ZPX`t&lDmrEec1EN zg^$X9FNoTmqEy%RB4wd+%n=mv?8UtDj}iQ(>Lf|4QxTJbuUKo=4@`Wha)|wuI(uf@ zMyn8y%QoNnY)(IJ9;iswjN8GloO69sA8Bpe=kgN=uNs~_@p1C@PS_`W&~==k&;cLa zko+-KX)FHW(*`ZV+<7OSovBxG7MbRx!?p425ai~_lnZjn`61ueOyuEXST~Ycx!Wf- z5{IE4LzNpuo>PUwIgh?w;W1=jwPEW_@W<-S;ZGC$c zu?WS@^_TQ+eL|!U6-#Ff_6)$p+F4eVP2JioW1aUPoS&aK^)TCn{~bQ1KbtKCQZ>FR z%I0=Y#!7j|Q-UVBd||o*-<9x|`z$_{r9Pcz8(ti=W0nr+cpX{vaDMe_g`!>$u&_);5Z^e2)63 z)rGp(I397o*^az;?SbL=Qy%=8t0V8J2-?L!5zwT{{+0#mX)9KL*xrI#{IlTqCXp?xv2d<3WT{~rOe134`=40(cJfmVTCU`ttfls-7dbyu2rkOfi)bfEqmb^`mi^`Jwh*fm8XVNzn&l{3Jeh?Oc;=s=6XLvi;#loU5A0 zX_n6~xjWDD7|@<>lGEnTyirNiLgkjPv68uQdtaoVqdQSNd%CGu-axHAL06{HEy6j) zkS%?q)5YGh%#kzR?Us`ZwGNYP-&ddorEb~Hew@J;@+J+u!=lzp7VH}8HQT!*R5{URTDcIf`Az#|F)m&b<>e=UFa z{z`<}^@>l~@9!#LCfi>aubLXToBt%oSI}kS{;eOgd@iY%R3L9Tsk%W|5W3Qv3N>af zhkt2KDIR*xW10O7x9_B8gk74Ovz^QVl26n6Q~cI1Ddw^-4yq;B9G(lP8F@3^^4?=x z6x%@e0I^*|=D0V-Ekv9>@cRn5wY3f8rPGVRn+bz2r|bF8-thTy^h{r1&ZW!ds}APZ zXj^ZNhX~Z^T^N6Bvqngh|I@YADvc$gE^_Kl(SGrsj}p`yPHl)#t5>#|3C8WcHUgXe zZi(LJa!D=e2Hr?NxuLK8!&Z`8;Jdpj@N%8m+}FcAmUZN@2i!Ik!CBS9D^H}*HZ%E` z)*Xf%QY}1q=i}EC)J(z)zq`ue&f5zM=O288Lz<`7OC9^tV{Lx^m9Yz#Wy-r6RnI56 zompQvimn#!8?VG$7W(hy*YSaBUcZhwXmDu9+ZF>l&!;ot3F`xsPmlvkpdsh;%Z(=A z1q}y=>~Wb5nQ<O0?o=ba8r5%!w2$ zT~7P6P?l->tI8h*kCjWve)wQ(6uVcl)607$&wRL+rcD2Z&H87bcnz@|Z%b(rh<#CY zKbq&PuxEUA>3*Sf6(z};C;L*zFrm(Ikvy^oB3p*;-l5sy^8#C z`!-$^RP~|^=vkl4M0-Lc9&&nDs;FBBp9i&ygZ`y&Ycro z%^gW^FIBTul!yh(zRA5`5WQ_$uKLPe%6iml`(YTb-ilVAx8AE|gLR*a4XPGdo-+6Q z)Hl;k(#72EP1U-G$aEUd>YgJ<(|1hm7C%s|W87R~Pj?gQJrxp}yXzhM=|T@{?VE@5 z;vKB!#&6uSTjkMO_+IzS;c35T{#{mzEO+Es3qQA8A25xdi6ow4+cN&q*h-X)f+mMq zH6l3lIUn}7vd&uEE#6^P>wO#|(Afa#(&s2`H&luUi1%Z65Qun@md!C~FZ;}}h6O9E zhg|h~@Pp&U1itsq0^!iMEqb46l>}M7&)&z@>FYo(S3kPFyMwap&1IRR`jZE*jRx)1 zY0>pSc(Tl!q1F6{)n2q1Ma{BXoE+kN@o9~!<)OR^o>NC9Rkt*5>E5^LJWq``*Xitx z<^!x3CSCZ){BzNd*MHfNT%d92T4C|S!L;`CM^ms5qS(>zk3_V}j{a{D&6U;H)FES0USLL~o&N;5vuDf^ zu#Doke(a5tJ0!keY3|q>f3h_035RV~*3>%rmYUatid@qZNs4-BzpT%axLFw!=1HZY zDle{oA$;(qGSB`b$!f=Hp@fn~hYc)RL;gEnv1=aE6^w}$Es-fv%h5hoV;#7cV67oH zDMTlWAHQo%INxn81grb*7G+RXGyWz&W88sM>Y!Y!(BnEN2_GN6pR6IVRwcm8Ay1rY zQ$AU4ea9$XamHRj5$W{?DRg7!vn=baYa_Y#@3Hsh<=rVV@Cb5(wh7JB)9^ae;p_@u zj{P;*4J#jxy={7Sjo%y3Zh{|JlWkm9+mgNGV4^3ovMyq-q6PId_X(E0RX@0E$7T<; zw0*3oCqbb~+zIjVA|C7a6d9!?ZW_NkEKqz-z;LT_w2)^*%?{COgwCVb$*?W?-{x=W zxV%4n{hf7uy?(d5VJ&5^SN|izYF}4=4zUAjeNXx}_NZ=BTy;YK{(0fM6>|aG<4?1z z$BH)yIZbSb?^eE&(EX(TIR5T|8xAkML`u^r=AOqp9t2oc+uV$^R0tH1zwUZ@K(;F* zHf4X=)S-iV=#JLiZB2W;i-dQSe%=xXm(ZFUr26%KJ^!Q)W;;9kj2#hnzWRm)>-3jr ztqld+Ot{eKvPVU=`%AQCm2nG zir38@OG_>!tNW&H;*v5Lgk7WW9eR!IY3-LeF(f{5{`rogLAfrWqi=NC&c7rXj=Ye} zQgCW7wDr^3y9FZWAJo@#u-IzwKrEYqIIBsi(3cBY-RzYEU0+m_OkZG5tqgM8cr#As zeBXq(GJY`kkf)g2^;P!{8=hX9wtt`g3i?w!oKK#eEi7u)?!bXpt50Zdu3Oz`@F0V$ zy)^EVJZsZvh$)MHZJU7J;npDbHP>3ate;qV$H|HA=6Gd?Yhw!w(n7hOUu%^YWv9%w za_f!keMj%Ux%!ce6dLSpWOux=CMDhnpCyT@MgCLRYRxT4$|$ zQ-djvb3A^|tZcJar`W3*xf#_*hc^2@Hdc>*Nxw64)6bcB=gKH+er(hslH1Ds(a*B> zAtS8F)rCe}sZ~0u@L{{sN8;*=Be%_kCpgs}B_>$1#|DWA zu_(L}2_9RusX41mOY*kCBiHI9GP`~9x|4P{!6ze&O>Qc(tyQt#xZ|iqvnBW3+Bdm{ zQM7=Bd+W^8O|{&f4qeICv@Dt>OU#djnJ4lc%{%LIAk^#omya=d6B9dD_?vYQj;u{= z9g45t#Mf}}xwB8L#>=~{Ek2)L!U@|~!>zAu_g_&Tw#o_bRwKHi9g^`-`dyA_=Ac3K znoug?^i_e$SBHZif5;v2!(^LOt!|9bx!tZI!LhsSI^o;b4hG&1(GG^wzoa+3_XHO?lL>xgDqYM8!HX_Z~$J1ILX z(TllcVwMr98ms2DfxResyk0d~wwYC$U%h_#CL`d&jJMLX?d85E#{P9K7fUcu2(edz}&JT&aH^+ExU1@w;QxiO^ zoXXh{y&4sZI$L|j*z)kzXz2q(H8m(RH$3{obi?{HfeqIK=tZY14#p~{*rMg`unUb( z#d=&AJ5aEy=yk=zBC*O(3%0 zAKNit)Mg=&`t^z->gW!OqlbED50kuWl7e!CAsW}Po@0^l=E{n8qzOT7AM&;agfqOO zP$y&hD&NsE$7`Ae?<5~PoDfS$_{4jDXXje)tKZ6nPo!M6n>cpt$dTRJn*|CQEjlV4 zq}#O3N;!iRReBl)nlUKpOSVGn=k9h&i)V_o#j!S>w``kghJL^=+wh-)agO)waf zJSR_*_nV{5u9er$68I8j+;OiJ^L84$uKHqkBJJ{tb9Z&BY64-@edj3G%C7VCYugpq z+g`kwqjN@>RJ~tverhDZvZ%P15AMmXBsp%&)g<=rGQaiLnYuk!-mPBAzvqSd3cLX~ z>y@PE1G?^GiO;PM8A~2WtqH7;oA*Bbey^9#)N$j&!;epD38olkb(X2`+Ml?g&Mn|P zPxDUu^W?A6$~hULby~D788;ILAH7cQ$kKuG-u|{%Ym4Vt!Gm3$Wtuix+dRkeC2oDA zY*zmoo&Hk8Jn!f!iRXLR0}8!UEhaJ`)H^HPPQo{DPR~nl z-_YFB9YS&}zw;?&vd!5V*4j6$v~@N66~bQOu`731oOu=7eDgrS+$5$R} zOL2G@sv2NFgqHJuezVfdiEvqR?&3k-bytJd1s$?GHGNS1!JdhuC0%&oK!Z>#Osq|zRamp@E%#-3 z9!y?V7j|2A4}L=oxsBu9+T?3l$@VYO5H+nT5!O#WDLkzImiqZLKC`sg9}8D2@ot(Y zndrGVl&cor-4*%RhBEqnJ@3I*jgj+ri#e&m-^xwKGc4TWig1OE(>pX?oMtl{e4pTZ zfF6$Vk)3Xd5>fa-(Okg`=~5fI6y1>+<7giHJcs>=m(w|)gnOSvP79{H49s@=rrP+e zPHwm$_lW<}#@B@(pG_dHj9(|rx_aIdJXUiB()6Zpw~^bos@GTglFoY1SFYQl2+cmB z#&)(wG*Q`!(B<`X;Pb=?&yH{BNBVK>eMbuQVafLtlC#XE+gI|ZRc-UQvt@-i_Py4X z&2d+5OR2FsQRHSxT?0>L{mM1eq>DdgTJNcO)Y0PTeq^2aC;gKl(Yi{*rY}z1`?``y zT&1{X-fwp5sOQc{I{Q~m2UI>&+Av#y>vG22Y&}+2`?OQHO0&T6+Fd2LZ?yAn#sh;I z^gYm5DIRZl(^2@T*Q~;2);SzutYW)Pi_}pLjL5CDG}eK*S>lKAIa(eGT`iifmd0`` zgGAjbt{H9>i;#aw-mkI4<|7wfPOWc6mAX5N#N3SnV)&NqBS+Wv>%YHiPadIYtmC{=9`~vN#_!OeDswF-IOy(|Q(p?2 zDc51}ogr$0D_<5&BwO*H7i;u1F*tlT`8H3G_{5Dj-Ta2E=tiv!J_&YF*kvGePJKOi zDlBRxkBa%Eh5tFEt^1WD+u zJ?=rxwIf37uFjd-IUuQlN(F7(wl~=xm*q`7$=+05o9R)sZHM!7_ivh~W(AH|mGxJA zmRuca>MKA!!Xeu)-TmC_8Y%RuS?&xjZkJ?z_&Ku5Sh3^f_0<<@b#^_1J^oZ$vDpfy zXyI`DLu^dbC3Cq!^1A$+i4C(BoTH5exCy9mVt~ojT-(}yZgGwakh`W2-`Slo$vmWZ zaqD)NSAui;g-fYLp~;~a#>gKXt&O|Fy5C*m(|s|V8o9=;JI**cY}~6Mi}J03BfoQR z%G%g1$Et5!GfUw*6E*49)tZ{H|1Me4Ex!Fcd@#5>%s6xS-F<@ed##g4r#iB|>Dn)6_}nGs*k$NL1GyIc9;pnCPa?!8e#vqehya=&`*FfOvp-Vt(I z%HZ8Y#hu#D8!p;?E}T!60db%k-yr-qjBv*rCjX| z?NT-VqgGpYwqp0E_O{!wY4JVt+>l!0s5>`f$<;*p{{9Nh zRbhL3>}*ct=dBT=8B<+aS3f-a=y`EG>UPQ-9nm4p7++QTYlrZevdo(W*Ia%Kn^$!}@w=)6N9&}WzTSKNF=9?e>p35$^}MD` z&3(y;s*O7HJXaLGr?=%C`jYhVxy-3{nQbcPudQBpBg|&3abHu=HxK1##cbO6-NG+j zEm7z=3$1lweP_?xA3I*-s{$AL7_9QdTGKKIkoviT0i`@t5+8@5- z;$R;ViSCLnFZUUZUG9m#gIaGfR?*sGry-)Uc1-oP=WF@y!tAV<8uGKzkVM0mY>Kfi znvK#8Vi=ndpX<;eIW`<4>-YL|BJOV(MgH<YMQ~*58wH^s%b36j1&bRU zPgJ|sp}b`@-kv*-z(K$CK$NFs8+2cbaA>^^zcT8z3dW;HyV$_GMOD}*DdX+ovMke! zD+MK>vi+A=4Qi7%H4oe@zL`CCnH7Bp#k(_kgBX6r+GjUh&lTH77MROUxwsahx#jjG z_^*vkEiV`EuJ0BVkj8p5~!Nu3AL<$J-mq8d;Aw;V^BvZ{0As`OZNYa6qh zp6$ARWaX*jrY5hiI|%64`NC>zZeokB2er}G`Kz0{GO7-_3n~{sv)n9 zSIL3MTo9({1qLyt=WcjBdiNoL}> zp#e+fx%l{f2jt`rm_)DFJ16(}&is1z*znF^!prvSckdeN%9m_<`|9HxQCrs6s+vma zH&TZx4ZoCEk8QqD{^4|&M3PeHn~ZlJ94a;?oc3?|Th_ieh5JHnP5~s_O_YZtE2Ja=eu6ELEPS^HrBO@#gAR-@5DTA-64fG(02rO(9&& zeD-y4?x@Dz^m?_TOgtu&O;4~`Y2%c1iDlMXzNa4ESKf$**Svp~NTFSmiZ%GW^83fB zy3|S=`EwYZZb7!4-4o7IVof*gL=W!tlQ3jGk;S`t|HG^s(e+fG6dlL@HB+oo7SW>i z_wgaqwXCX#ccY-{Xz2055Rnq8&SP5JALKnh z8{N23V=N@-_`7z<495?_Afu!p%wCF&RQm|7Lyi z_ItbiIk^F5FOEIt?g_o;O$=TVi$Try_1OWHv_a@QrZT`tseE^ z*AFk~%9Opo@1xhn2KjUqvQ;joXyy}g-eo?Uv@|HC}^BDBij8QGgtc|28eOua)=yWB1hk zBNq~iJ2b43&&5(qCmR|j-_1O}n=tcs2C-h_Rp$z?`XR@wC7fs>{? z)*uXddi>W368I;@v4fdg`Ot^*f-Dt_E%_QzS077VMkgKOH^hrpr-xJF$M5ytP2A=9 za%W3*Pqb*IwSjnxVM_50isbb?4Mpx1H^w6|>hTvxIkrjT?egz$G-%A(+h{*V`%WoB zyy2g8zyIOkj2n-kSD<}#OyHfZ>m`vB5%W55_$S;3Sz*)bCr+9s74W{Bqe*5SKENlM zWIPgl#HyOZivBF4uYPz^qwE9Q9LIO7vpK}%o z%b%`kKQMfMhcve;eai~m>Px4wbSI8;!z+d8-De0*;of}b-_?oRO1K;M?1Lm1Cno4+ z$L!5{bCFx8OhfI`N9nfk%I=|8&f~+x3ET15GhMez(+(e-n2;{B-Ez!y$834{`jC*d zz5TW`4^zZm$7lK1hvMx{WIvd`r6LHE5aQ94-{KP@D+`Z{p-niqOy)=q=M~LuI3?I* zQ)%FxpJO|GXSbq^{FmYVd$`Z}-zc&@6U@Rpp!9}IQ`Dt&%-uuj)x_M4#`KzC7g+5* zp_Io#uU~!e&whBQeUs0#a=|SKuSo@0QA>eX>pLNn)s7OSdv3R=Px2ktDA}im?RnZ; z@ZcqH-A6}a>Uk%3iq6;4q+ZC8ew(~CZ>EpF+@tWAEb7{)_T^$RyN$lAeY%?51ryg} zjp}+W)jsI${9b!>ldhYO4+xgC_pxlUK8?yW;P$!VtW7(k?94B~LXXMW@E&pgkgMIP ziW{iwtwZO%?tSdt(j4&K{9;H^Nsa;Scd;=Q6-VyFl3mcQf95&pT z4ztl%e`3g>9n;++d=oE%!{+ZXx6Y`|Vtey=gG+9OUb91ko0fTC%gS^M(a5>af*+eB zcS(PrG)xJN7L0U*jfoe@AZ&>9F0?Bp){PG@U++9)HFr;Dgf&jw>0XHcK)H_YYWTdw z?i+CPygTOlgyfc8YTx>93Q1tD?yB>dI7&`da;-8E);7COh7@Z>hFZplhp9AozT%Se zcwHQ;vVDiBbIxh?h7+|!+5TI*F^#0-PVPD3koJ=P>;jYvTD_AejaSUa<>tGrswk5c z+awc?uD+nAk#P3ohy6!Row_kT*C-NuXr5~RK_tQklCo<3zHbL|(*V`4-i}6{z_wSs z&`GW!e{wWqKW9HtGRuY7*4tTh1+)LcmwEovU*8Xr(PjtAiL~1~zQV4ET2$ph;o`~GRA4%Uf&7LN8Mj!TFJx=#l9hxO{=xVb52A%;E@9z0}jd}y&F*yx;8BPJy z{dr9+HC_E9GU7E(n2f!majRFEycF2FA49!8TJ>xKnRZNP1z*7AB~(EHyhJUPjhsHh z^PYe7a`$xlDW!}wJ(be@51BPSV}!_o&k8BG)VbOzIPo)gBYj&BmG=3+Su+j9yJ;3x05KXk}c-ni5n9UP5ct2h(qq3P)wc? zmT34^XIr%WQ|azabKY zozutktlxTka(heO>$>YvAGx>I?^4crmDX0r_4cNi9h-2cXQV!~_2BAt35sUne7_ovZ3{ZP$)IDU7P*-Zy_v?+|t=m`6M ztu6cPl+Bs*)ZufYIH#wzbWwj9*7_#vagjTOP_BKqKR=PVA|4T1`Jt;kQTl4b;4XWi z4Be<(AI43&JK8v6y{>QC6)_h%L%Sps`myuDsjLf^*f&6<9K7PYbsLiSg?2cks9%xI znKPZGsT6d^9he$1egL^>{Xt8GMBfk8R^GdlTXoQ@r+V&A0L1-C>2PfqpKV%)8}G-P*Y@DTZ&_*K8HP z94%*ZY2w(m`!CNLxSGcar0)k^di+4R64x-P;;?uB9zF6%P)K# zm-gbdaM}~P`y*_^{G;^a`Sh(4_s0r6b&i}$NA@VHD$9Nll)FET5a6~a2=9X$_mm!r zQ(RA|?|90IL8jjvkA1UpNNHF}D|_k}EVe zU^g3$TCRZJa%^dMp>F~WCWgufc(rbqxN){>s~$e~N=%Ykixm;Ibr5n!pL;)wFnY&+ zW#%=xB*EQ@^L*zuKj}+9w%)ppi@g-P$5?2$rccqiqeq&>Jo?N{juSM|L6^455aaKc z`p<8Tn9se6=^(A`_UF$3{$b{Mg^tY5Q}EB@B^zV5PjcaEMOg9%bz^fyEe{K|R%}pN zlW=qGxvk|^#T{a0mNdkP7U7cC_x_i9Hl2U4T5>NzL*GXAM&M=1Emis6SEIk=wDUi% z+Soa{50Q|ndOxwM_+;(70|6(}gP*5NUds7AtIus>#V2o;;ITbf#AvgForU_=`ynn5 zRyQeFK7y&-E2egrOEgp5p8Dywy^HA^|9n6|=*G&U`RmgLIjoPavw!?Ap?{udA;_F6 z338D0EPs$Tw(EMJ&Q0VUM#u|Fa;qhxN6B`d_c99)7mH^F<41lkXW6?7LJ~9yCL+}7T zPovomZx>&=>hU(#SVXfZ5v(;Tt$DiRq?+RdLc`$cn>Cxo&#Yd2(aT{$;AbD4)vWXo zyCXNVj3>YUpy2Ix&0LoF;8?{o$7~e0xJB>YByCT(x@I3PdYg;gd7Mb(&_(`IR5qfpAf3* z7&HqKjYO)eqtQrp6bk~Wibkpa@B5$rZ+zh3JHC{ckG^Ci&q^ZAmllYXl-AS)2S|%2 zng>n@qAHWf9{6D2AS|93L`5fy#k+5+#_9Mf-;>m0^+oVUl#3FNGv2t*>T?!~irc5V=63q!h)^pB5N| zrw08-t`}{gTmJ&sGJ+(fO)%gWghQeF2M0L^h5M6nLFBL?SC}N7>`Nvx`k)+2CiqZ- zl!F5CRG{k=8Wk&v_w|)Tz|jc0BpFX9D^sY-v|xasmCAm!h<~#o{oiXx`?s3?J8k~N zcA&O`@A3o5N0)WQ=CCG&u#PYF|T*mJo z0`)6r7bInYzsxJw&U7#M^sD0MXd#nT8t&Pe1ifZ5B2 zL|Gji6mT>dXUm5~?Z=ob;{HWI7XU95GEgnQYjGqO8xUwgK{UU=v{@KoB#J2*UJIO9 zyk4B)cq+vY&+IYXpF)*H(Ivsz0oV-+pf{-$1_S<`M$tTai!go2;U0l_KQf)!8el6z zRx(oZC#B*+3j`<+qy^!F$O;G&*%PWI8O^g2iTH=6Xtkxr0LH&y`ZqBAYsf1BElXDh zOZm%ajkqa!QsY0`vRb{#ai;JxH18Me!y53}*mWK&Zd*Cd99|5NRaxLeqbwPU&}s zEhkg?cZ!th!9*gNPX8GLgExyd8bc&#V2D3W+@(4)$wQq?`Wwt8Ui}IxdU_#9z?kJ=8r2zoKUV{2liKoS)l<;sdFGJpBv&9tb>1^)L86NFJ(WjlaSCjf6!| zKQ|}gsh$kI_csbini#aI$6qMGlL=(}UqJpwz#=4|wJ)9kXls88V6(wC3-d}jkg1^H zYGgmHWyMV8yIA^*93l~cV0rW({l6vupH7DRQ$7D9KIT99|Dey0L?e*k`(H6=(EmpP zdgg!q|Nk4Gcq>a&ejYI%;FN!}nUM`}1lf+@<^+BnSIis$4qQQ-EsVJac!hbz)}~L6 zg2{!I{$@@obI+l6(HWjwdFbrfn| z9T%%7xkt2p#ae2-%Uj#oYv!{%wQ9S&BhC#^5wf}?94{yG@Z`G`n;B6R9WKh=vxrqJ zs6l6q%s(92TC~f+{S@W#bXH?+*Gl=GlDYx(=#Wrx|K8|^*kwyyP~ zTsrb*c=F7_2ahjA`zUw!H^PnkR;l=CTY!$o8N-2 zqfyTd+4k!^tb=~szjDX4sqk1%gUol4l;KewG)xL9O$|8Se>d{IfRvmWpTItuz}>_0 zU%4+tANaE8`uw)LU;HlRj~iH&xE%{~-~05#N({m%Yi=}NSdb9#(aQK;(_{Wv@q>;Q z+ERkiL9W}x%*?;-<-gouG+UPS@?+PdJ7@0+Y|7mKB563Y-QvizH3Fo#4E?nlYYynE z1sqq^yPwY&WDT>FF7FlC)VepKUkH6yJIM4rSF{C*yEz`oaZ#tjqdXI{+iLiFm)>(z071-6 z%`q2noT)qQkQb+U|J3HEO+}gBFNNqwHLp8zr^`_<#=b}=pJHtxlR@Xmc&(3d!fyi@!C3j=E`@^lanRv9~HaYtc2QmNM-Ih zjC$o&uv(K>y;ZE9x>GM9$4*`8*3ArWgUuz^GjNhmSzdk<6Zf*=yKn-z`w?ED`5N2j zt%8#ngpj9TqR;Lt4TPsGCS~SGL~|bG(AgJgVfol3k6c>vdOed%_@{c;pjbQpq$(>4 zDJuKrn`%xE(SaC?_1CCE5xo5&vS^m=|2dvaTH+Zpa*Bj=3r6;IfE<)IH=G=;aoW~|X8c>6E z^n=e#u8x_bgj2$3iOAhG2d;|vv0!+x1}pbaj0c}>w0`~ev}twv&9RCAiauFi+4hES zT|#6#XJAxH>6x?N;Ad8^H{k9yL338@CPf%>Y5AT16fL@;Dsg{eyZ*2nim3NKjN~X^%-8yW_<;)66;7M=xg_@I|pr6XKk^3RY8C3gH>Z-6QXYL{_UN zxLi4a#d(QT?l9(^Lox<-4b>HP&u_2$|H+K)e3&w{f zABk1&StB<7MtW`Vl+>47_Ya}iCdekj{#EZUUZ1&|>TZkA#n^MFa~{_D=vua(?b+dO zjqeYjoE;z5RG^$BVKI`R{woCm=vvB}B9XJ&_GR_cvZ{lJ=_Tu2Pi(@bSR-tRs49(&mA{$n+h1Ks7_Zcc^>arYYscKc^ z%uh~HM*5q!ie5Y0q4XyAY~o&CSdoa0w=|U9M%uG%c=ApZzswrS=FKaeEFB4MPf@ep zC9gtbcSr1w)QQ8gy&c>cbiO<7p%n7z3OCa{juW~3VuE%rHVY@d4sH;iqQXP z0^)8NUU_vG=loLQU~hLu^BYvfn%Ah^#{B&4Ht#1z^u<-v!Y4QO@r6Pz_{cgrr5)8i zUl2t;_oj7kQx9ra{Q1kz>Jm166`T>LAbEV|9*^9bAZ(OrV;9TiIB{?8jE+~VgI8P# znR9}|IY;2UGxofzi%Us6`@T^w1YNza9Jekr+wJ8lq+aYnJRvC~x4&rk>%k1U>^0ls zb25tNdN0JJ)Q9fP+4#DavwqC&VS1k@i&(BKiY*4oM$O){-shU^)7`r251ib#59L7( z&DO0^inqV%Y{Y^2vdYy_(C1+A%?JWpW#%&jyS2`lTfS4#{ngnyP6c&R-Ngg7jsfl* z5&fsH=QK2Brq}d@@wZG@9=UIKQu+Gvmla{B;O_$Kw4k?BGY#Y(PxRjjS@&w_Qnb>9 z_IGWXLww!N@N;#N4X~?-qS9QAx{mSA>-}F=U45~sC(-i*tXt37OVF=i_0)bHzqj01 zzt3&conJ9CJeBTa!cz-+9Gi_Tjmiyn?)`t}^8D{-*=M=`PY?Nj;r}BsCxFa5Dr1LLz(6!6P$KW(r2EWNMJ4=fa6Sl@bI138s?+ZT;~?@;0hH zoeYtrkZ_Qn??59o(Ev^)4uVF&HPjGD-~xq%pfunZbqsJ34%Dck;i?E#geGtWRH-81 z>gsBmY78>yK{S6!nuiCS90c?Q>@Urq8N%Zr(s)fg9(@@92RN?Aqga$?(hD5^=NL64qK_UMw zHmNh&ghawsHBl&4CZCY%aHOWDDvHS{BwP)HR##*438e;CM`@z|4L*5zc>Eho@*o0V zkA*@SKrJOG90!4;&>EWm6RcCiXsDtzn5orI|L1u3JL3@l6Fk#IY9dff zo@uB93Rn|{hGSGQ7!5U;1{|r1P(!N!_gIF+EJ+(eRRgiWGC-t|>KaHilVzF!1~oK> z$uVH|qE*r8e`XjkEr9R8!81Gp{QggHNewVhY73I3hDI?Y3yIN0siR@QI3rN%DD;1m zOPULUr3tVfp^91Hk}4orNR0*M1t?b(F#T1TY(j#V)ip8y%qMkqbxn2jzriOWfk-6c z|3A$q6q3m&4Pcf7DrtdDNH`jSL8vbZ6Cku0^nx&<03D~UsrhfHcoZI^N&Gjsgh2!L z z`H=r|7YYeoY@rO+5%KMq>WYnXG|8{=#FxlBuIG7#I?83BU-(3(!rPK&RA~s6_*& zO>&vjgTbh2{2)~tfk6CWFj0$h_%}p=C!&hPAT|Hi)n(BWZks4eBrKYO(pGO2valp#{#}NTO8Uiru|9PoH1I7}qs`;OnIy4%HKh)L# z^HPTfeL4i@KQDD?H9-BM(U|`jBEW*9H8qf6IEq3b5vrgC2LcDQIvxdttm+y734oMn zsH!jM?_Wwm8;(&2PX5wd`Ilmb75`W87jIBrM4QDwZ1iIIyToE3TtxsOI$#OafSv#$Cs7%WMxjth7(yAY2?T9$B$)PCI0sB88s!T| zsH4E`C?EnLG&F$lN*VCV(I~Ve;5h@19!ePlSJOaiNP=oz4W)`v2BJJo4Ruvt zI1+(I0xVHQqBT$eIv{96YAVBlm=J?e2HYaF1`;@+fDjEd;NWIm;1UUVLJ|MU6GCXJ z|HTvf!Dmer;4uE~vjANKyhIET7ip@4J_|q=5{(BK1NI6a2Mq&ARs*`i98^ZRIh)Bp=L=fFjH4Sf5;Xf(CTQ_g;Xa(1FfnCDlZKUG?;us zs>6Zs9k9$$CSjgGL1XM)^}zd4e1TbHi1(!s0x1inbV>x!DU3Rx?hs&}$(I}iZhEDI za}G>vBbH4!0vi1OHt2wdg8?Wehk?64iC$ow%-pW~Q#a^Dyf0Y+2`0YP009P~5i}U} zh0+2^%d!2c*EQADG#LI38mY=qw1E0m1%E;13`YS0Ca74^>R=%np$hz}1Jgl`4j2Tq z2B6I`z!l)YYGN4L8HvVVh+vih2^a(5fYtp{@o)0UiMgqZtD9NL`Hx>Mu=oz^DKbF>sTr1_tymfKv?( zH4r~qT@#=Q2q?kZGyrh{+N%Sq00^)!L}fLyGQbuXSf!2um7pquk#$A_eFOqs1ZcE? z;qe7*HyQ&N7Z`&Gv>JmSfW>3}f{f5aqCjjIu(xOgAQp@ZI=~3Dni>Ea!C)U?BQfgA zi);Z7XiWwek;tVhbwC5ENdl%z6N3Wp#sIPn7%&XLQ*}V%kiLLQ0xYElAlhm`&oRFU z@UKGii@{b0Nksqyivd6b{uj^@6yRQIz)%cMFf1tGZve&&AVm$}gc=;B29N@DgmDDA zudb=Fc%g=I@sv1%Q2~?mM6@ZTi%xz6TM8URzeFXn>x*GG`3!p*`jX@DX z+-l(LR8lbwQUZh|NDQ5EVCV-8AZTTjDT8=X%;pUKVKh`h{;6S@br=NL zUK7P2Qx$}(24;2_uKpcteB2qp)H!~G~!xcC3)!(S}_ zu>Okz>^l<8f<&oHX{`-I9qoOD!>1_>;y<`Yzwc)CgQIZNo=whJ> z=n^p=YXHg@galm1^`#KWR61EwQH4j!BbZ7ATPWaR1ZX6LM(`#RgCIB@_;3%+L(-2% z0-OvvxxZAv$zkAwTXfx@FL8J{iAD_e1H3g|0svVG0mc461dXJ4C`kQi0uAyCq=iaS z$)S?Qfq}F@1;_&Zf#iT-N+6joiI)teP)R_WPzs>0@sf*oLZDiKx`8IeXM z;)7tGz^Q*Q-3#UgoG_k{+2#SG;3A`8-Z%<8h-M48M^sOk4{+gyr*8|TS_RVl$$>%P zFki5dAL!(Rg9U+6aX%BW&>4^uRJaEf4nBFpsELNra4K%jE_9b*6Jrw-moR;Vt5Vc2 z*D@-eFn^#K_!ycBEC8pXtl;cI!YfC(LRCB|u)sefBLEcJ`vdeD;^|}sXtWlH8ApZt z2hxIQj7Pj8nWBUBg8>Wx%tA0Rh!%*Y!kABc0jCfM%$H2{4D!MvU_mtfz(9QXkKtZI zM23S~=oLWT1O4$N2mK@xi(L=)^_9ZmbrCvvU9hDyUI{$Fnebh)%raN(&%nUZunoc! zeSQK74k-cXi61%8lgwxeU)BKyC=CBYe1PtfL$)zw9LJCj0@xOGA#sa0f)_ACG>nWV zdi{}fI9S8L13(7G8Snq6W(;sk1S?lwKiUAaW%aF%E@b?$M zWH{d6-#2`Lo`wNGX|IF>WX!C1;JBEf9>VcU`0j!KCVo8zyfG)xU z6Bsza=>8100auKZXc#bDVL<>69Al;}oG-%%b_bXz0N+V4VEO~Ieu;_B2-m16U?zLv zkifiODqifiH%GFg|MJad!Y6J>k$KfadJWr;;dMPVIwJ17XS|A`m!7^u(0{JIQP$)bXX4vzzD7t_RncUS_$9!MenVUmJvmkgD{B6Fpdj~_54mHqL7bh3#r4IiXH zfGQz@i3)->_VW)4XO86Wpc!&c0Obo0U4V*Q1kbp8nH>D#ZiZtJ6}31Gq?Yj@Dhdy$ z(nw@G;F38hm>dDBeqag;3OxE|%(2oV^!-LtTGx8oO8z%t~Jx0q<)Zg7^J_6mS;^;5-Hd z#t*mvCMF)3g=C^FF_7XPv`mVDhCmH)@3Ia+6~JB)@qT1q(8u^wSMW;{)gJ}{+!x4? znHvBLWK2R5*%E+&{i6@Vlnk&Q6zs)wK*G1uLKhtykg-3P{AS9R{6N47M1ZnL2ZbvV z94jI)vzY2#i>O1=A~AI=VWF3x{v^S`1BgZn2_*!Q@jlUHU%<&;Qn>hkzGG1ofKdQB z{jUZc7;*)0;D0cR2C6sE?eHQ0;({%6Z~@tJcGdb-aR41%Qq54^MUROHgU}foV!8N$ z&KDkv^pPMd;B@-l$ z3x z9GT%rF-n*82>DmnbJ<7$o{T4e!VAE)B;QQtFLj@!C308@7%SXgp|U?_lrxZizC`~qbJrdJ7DjQA9O1po!zXc8PG z9bnwD18A7QqmmMgwCKrz$}9ADPgV)^GK}y+z;Mxn{lTyq>kD{wf6&>s;eG^~FT*GE zpgJ?J;FKV8ARaJQfOqs;5y%8aECMlLI-rt(D?lIzN-_<;Tmu zlBoum-p>MJ2*YI#Qh-PT-qX(mL~({VGYyC&M2VmTafP`4reuNHy@-zf!vm3$0@MzK zDRK}{d_cv$H2s&1zSbXnD&jBJUsno={oykKwF@>BLS=ONCut$*fU$-$k|D9tASpq( z-@K3?EJXiU{=Cx@nkb_!c1Ol`32dc)*%Aa{WSHLbSs{zQwd8tRqKaNHOE1SUSy&V znH0rL0RSg>dN`FBg%1v*F<$<{I0MX5coY~o2hx1$Q6#blIWUSup@VN%Aw_vnNF*{f zib4l;Rg^E_Vn_J}`vy_`eaTTk@2F9LIV91jzTr^|Ngx0h5vU+RU|VqzXBU?+6vD+N z$i*el#f9qP;^7K`S>PZFx>y(B1CIh4getp6IlBQ35eQ}A7msj-DnVeDIEagjGel{t z5=2n}qGX{2fdV%zTstee$wW!Txa#7d3njW(d4(T9-N2)~D^w9GALRo1wZa7g*0?~T z7T`jo7NEGe0Mu>60S0>sp^J-xg2I0tG&Jhh8U-lORae(2h>|4$SrHlq2im!Ss9{z( zP%N4AS^=N~=sm;}n8Mb}%OP$I8kHD;-4=klLKm?B5SjHd3pd;R;buh`^8i%a{;68Q zSw|@bBoVlPE;Y6LsVQ!;DL{a$JkVc7-R0b4;I?0W$2KU;;a6k;b7g>bj=0FpM%bU~ zq!(BZ)EaKpx3&Gb7U<}YdOLm7pKF;_QO=64V70!ToelOEyp~Xym94S8(Y9YJ03r>| zHgElf7_0(Auo-EXC@|3yMGf)-|0{zRP-O+iD@>wj9?GENS`e27{(y_UQ8W?>7%yif zK*FI4E-oZRC^hPb#4c1UTm#igfH*8MlOY-q3eXcUIq^$R!I@wVut8>_36)GH(G8iY zuV4EHf@2OW_6JqufGAI(Ps|?u=-|(N04{(TNrLJ!NMA;nf-cV44WM0Sfy8LocAN@G z72|zV3(6)6BnA(thbTgDP!Np@l~JLBjJp?8pqXVGK67je{I$}5oA`CE@%4!%4T5ZuY0-ZX*g&>0I zG98jG(^|tl0%?ARUid&mAgoa!DKYMVV*gmFqk}|5VK697H5d|sLd%h&z!gz2pGU$k z_jmljJTDk4n=N=e#<s3 z7h385Y=2A_(BfeWXbFHr^+zuqzsyNr@XP_z^uyJLYAre0M8GyhM=v=W9(V@B0ZYz= zfK zC&P%fL0=s-%^o0K*yp4{^1wdCpf$8AB*k?I8 z8eV|__Xm_LH3*#RP(V~cZqcEj&iIYZp>W3fknO^9kUlV<=?n%l6+$>PGTMVe1*Um; zqz@oA!Qc=ElKp5QKr>p*kc$+W@ZXRtEp%44e6ptVUC=f?FGupc1$cwZPexUTi zFV9&y2fG4ZIuP0~)l=}x*PV!fkqRO&$e#j)L?|fP9ePcwi{Z@Klm7*_r4}b_Mk7 z4`@C=K?Bq#9#F?bK-Ym;mnCh+Nu#0+0p}(L|7#gT$^N9M z7IQ2_fL1DC?rkXqUqJOTl0M6#5@qC4rbQQt1=Rl%#lFi2YI$;Up$mVRu8ZL&!{1;; zlOW$2i=aSHm+{x{{|LUqG6X=J%JgFxSJ1!Uqb|n>Na1pni(-mXBEXhc0Z}ZI9&qs* z52jld2Obzpm?zHTXEE>u!~ht1oQJcgE2sxSDZoi7kiY|Y4p?aLyF?Q0r?~(G^M6=% z$Ny2?1M(A1#CZU6z|4Dqi{c*OHHE(2V(ahmI3q)e|J8Wnp-YkW0*0lGzT-cjCs#c!E_vDneZ%6%@Y^xCJu1QVN&>C z%-K>kpujY^* z-+Tt2MBP7)(X!kB>hoe5-X~E1oBM=c${qh@bqY}CWE=v}ntufjno(emFxEvP7pf1zt3hWphH1xfrDt{C7IrHFyKAwXsh6Lv=`nNzErFXrW@rY z{pjGkKtqXmf1sCSoIKE)=FiMw>>xDuG4VOX1AhW9U?H`CjKYW*5pfg%Y6Kg?7# zgOugcL4f|!oC?}F7{usrYy#_Xq(6-v<4$JAY$?V3H>Q!Pj0E|gn6_92gJ2i)=zoEt z2*ZW}Rf~7R;EGs~Ur=z;_<;cjnZDS5aRSkCw8g5ZC>oskerk)K+kzE-w1_{H(*D$v z{!1Y^BYzn&A{^)mkp|2{P*@r5arC9#8jO$$_T$=_E(OjGM&AM#`X+^gz_x+15P%C< zV*IjfUBE(+8wGk3flJZzPi+F1w;?QYga#+l{J@}V(G9d(cy~G!76hhhmNlaW;VD!) zRQFFQEX|*yBwhTk?jRP7rU*X=cuR2&j*$_RQjj7s6HTOLdtjs#h)bw-f1Cob6c+zC z(t#jNP42I?z^%V0;uwqfObbH5{gf5}YnCm%OChwDVpx~~j-dM+9Q^VnC2)xghR|ZB zL#6&old=@yZ&gd?N|yw<9=Jcn2mnHb-}7!z-M_Pd0L3CeXfm62EivlZcQtpM_nSRdUj3O>LM%HRQ@34v9W zBY}4#|1>~t372Fkw!+C)_FGxyCKjZ*F z$=K7#sKG8Y3js;?T0BQ$!4-KZmI?%&_(hHP=fzk?3K`6-Fn_>ZOh0Z}(x1N##-HSH zG0lr-q`>DO$8yItT`*7B$iz zx%&@XTHN;zfB{3)UqJlpn;D`HnBwJ0tzWh!fLm<WQ%nIuUL^A9A`>5RW^0a3y;SsF~G08WD~ zn0)y?1+px>U`%R2p8&E0#C60VqhN6NG~ip&VLrG8{bAw#jWrQ$$x2!$3*U+Dc$_s0CKQFJs6C^BIr z3$T%lRrWt6ADoe{IPm9}!~qQNjCKVa0N@u;1WWiR z01vt#$>6CP&KgGr*liQFDYdc(AZM1j5h-CnA>7AziQ~?q`-`iE?uG%;sQ58<1g71tRzm z81rK3p(zC*CgFpX5Qq7|GKm|^HW0Rzr6hzppLowwP;|%{4#f8%b#XiDqdWg zz%AH!1=6yov6y?D$+}={2l5R|&{ZHSfl3|1EYJo0Od@u%UY9JzxO7{%1jG;A14v$y zGa?iVQT$Q4yg~=?4Iwhi>zLy7Ll&8+ViuZ!+aQ(5OHyP7szWG4Z~O{0YB{Y@QRF2# zU4*QJWWZK}C_}Jd<{pr)-__0H6G#i27;p^j!tm36h&|xKL%?k|%gdEj!L?$@!X_dH zC5!9@4IXKMMY_L>jg-{#XknSagOpI1bo{g@66XQn_0)wdvv`m{Sb>0_!;V03|MK4! z%3ySy6a{d8y?{tt3JIF-0EUJ3Sac`+p^<(|0fQgT&)MG<3`f0m{r*1x0#7% zpeq>Ahzj6=@ywPF&ez#*!TZ{51XlfY&1mC|^8s9G#+DN*&KuN%I9#ZloHt-j0B%sh zGn6aL4?GK4wjalt>bk@ZB_+@k2L1tT0dN3!;Sf+TCF4)?S72-+`I!@Pa!N`-0N}@n zA|pZcIOkAcaD!a6m`^e+c`kH7GXsqO&vXsUt1uph`1kwqUmWp;jxxIO-|NC6bAkX% z%H-G2k8T7h=s#HAA6b2dH_Y(X=nN*2!1N>2Ap#11 z3161^5rEEKSV#rDeI@{=r@!<-0MI{OMg&4$jL(qZws>be3=ad8D!~=D9M>t^p|Htz#TO} zFy{$wqhWX|USM|!;K2j>b7#PP!lfn+M|c z#Zx{1f^%WF5}x5H{7rxv_cO#7_B)Ng7>VCDUTBeMl8ikf;93#`(yx23!u))(U!)>0rlm(RA8n(MfFO=W`{PsfU>1)CxW?et{J+&x;mp4bypWX!lS>Sg zCXD_3Q9sTVK#x;O3e*dXG&COW6-Wl6*%&@F{^UNE#h5XdfE z{&Qm>gj`rT`lE0EZ|>?Lfb;`?@4`b2K-A>F_;ATW)#B<|G;Hzg&$KPyptbyJ2>^o~ zupa;yIza}Xq5TQuzm-Q|JleV_OxkLHdcu}T!yl-XTCy&126o0{#o*tlB?tbgZ%zx7 zb&03oL&zWl|I~Q<9~v`vHT@qB)3Uu$i{iGdh!729>`edtIpSYI{S7C80fg`aKKPUs zBl-XnFTdyqh9eCH1D(ZteoYlFzFUF1O#dx12~hJ4_4rHmvW%!RK^Y0QAqV{0;ztDK z3_cf0R3c!BjFur}>hI8&J>8>4U_8=;LqYMsuJPl6`)MT7zq%dy54ZdN)|H(9IzU>BU`RiK@%*>JC@GP&34eyd*y6G%;6RLoTPE%SOOIPeg6|NdfzSRkCO?4| z2A+EWx*I(D1A#2~`Zw^L;)nMH3!|YwyfT6-&KKOX`2!q1nBYeNQ(Le=GT=e|-rkSd zesR;BKe%T#+8@8{?JA2qWavLA{>dFU0GVlkrt zC=H)Qqejq0V11VIv|4~?1EYW*lQ)QbG5xmaq#@R6UpL>C_uK-RFFPzr` z5HgscSqPM)qP(Cm%0fmLfC}y}1K$k+K(Jkc0PZXVBJ+j)wlEK7^GIgOo5+0DodI;2 z`zFa)>;HjtDKuw}1mpSBMK(e~f*k>;av9Cuz$LRM;F$uM(T{(m!V|Wz9s_uvf58qe zmk}2p_Fm$!*FrtkOZP|S4T_BbhKd4R;(hcFp$Nb)8UUt(1cY<>a}N-R7EyQhCBfujp26z-e00=(?ct2e;+5o~$0l~`2c`XH~USO(s`N}4khV%kcqyQSQHO>dd zDEpn>Wt({EKkbeQ*dTH^ZMF~MlqMO#=UAe3&k$L%1HjaL5zXKep~A9SvqXfI|67tRnImMWqK!O&6L zQH#pZssx0gR$_S;;~C1=GN#cAPiACUEfz}9KWVG4=Q4qoh87Xt#NYVAz*=$8e3}F1 z4&S!m1hmql3A86oTB%7eBEA~U2h&!!P2gDVwZmpg9DS{QeA?_c-?EK6QSbCIEEDH$dU_OTg$mhJG)8jFH1ONF}eH#)TVsu@g&*cj`phnM) z1x&WRskC<{oA8!?QA0a1Q$u2OcSggx`9O6#b8-9cw7$bybA(646~agV_zWZL;}3=> zr+CT}h8cBxs#ShzpxduCr?i!AHG)1ZR8nhdr;|Q{f;h(Lmsu1V@MUOWl34n>R&X7& zP5~GmpxcL>#k|6ONwD09kpNa|3G2+1=KuW~5_u8k1du2pI-{#qDQg z*~!LMO$S|2w=wMrE3}f0ZE3PiN3rSqH%@dX?IJ|mzMHJBUfL!TLNs*0@5b`fh{w%S zzI3B;!l0q#F z(R_7?n&V&qZ#h{=!W}{uVKkSmtJ)2sdBK$6EqYsBoo;Ldv;=cqoN?B4y)_G{AjUi8 zA(`$v(%swYJXm09YgV5>-Q83Y;~62NInC|*dcprz@u&4zj64!LISZhiMeRo8ktA3U zilzI4hO#jGNTV~+VF02Tg9&QK7$nHt=*qjO1@jwgb&tEI*6itWgH})M&1j6Jl)JLH z-~cdt4&A;&6BJEgpM4}Pq{tiSD0v((=^+=aLyd&X>_ z6*{Kgi8Uz5dM)#fi=jHvFj{5NrQjNtwy>Hs;MUl5gIh@K!(x{HgJ4TFq8C~%1+|qr z`d%Um^d4*z{d({Sc%XXDdV`u`){R4j_~W?FXA_(ygOJWxPtOR64H{e40i$}Zv75_w zD4}SlhVje*pxgt+lVkyTA|puSM`=Wqvt{ z6Uu}4B^EXm`O`JaS_g5`AIz^g-n}1`ONs~$iGf-(Z;2N8MkSn;U(xNdEk0bj{JGbIZj=WWF6Bs!*fstzyNccOvftll&Pkn37Au%V@ z*4$cysYk~|DM^UU$<#=f#;*CF{y~-PQz{~%Z?%yfN7efI=@U8;^pL;OBV*q=H(%NG zajA8E9AtL^54lg7!`?lt0zTv3Vo z@xPj1pB$gmgVS&BG^`}(-+H|eztxRn)-h_SaUF5wGWI^;CA8^=jxUJdg0P6~-tfKK zDH!vXw3Fp5z zHajtftMA$5vds35Ro5JO4q{n?)u zc^pXFO0AS+)vY8;0LVglM@-bp2cF*DYHO?l%d0M5yqezR!unS`^NYh%gv}7~B$X9k z$?E2M`?m^k&1B`u7B67xyTc$T#Q6-CJbi`8{5)L(*W)#}x_eN~d_k!;w z^blc$>I1?KC$CS}cWcN0+CBZ|T7@I}hNBNXY?;9CrLa!Kl?2IkA%Mk6urb>!8KfXh zx})XJ?GD1}-khjwBB^&Xk2D`kEVvEEx7)hgJ{B)ub^f zx=vl<#kV0g>(&(5)S87r-5v9eSpyx^hUjXK;Bp?0yO_YZjnm!i1a2UA`oY18L4I(} zpreh+_(+$8+KG6RgLkrH+*>g+bw|Qs#vEC+mO;TBoSew+w)#RW7yXi1u?1rs@RJ>9 zV^|K?it-NHF=FF@`|Y{pF59=&69j>Zo!~ipW|5rG>a8t4v0#}Dm+8i-Z$&}oXthHA zePf6>vr^SeHQlHb&vsU8=0j_iS&Me-h}?J8R)6_aRL4Z zH$=8H0dA|ILR&XG4;_UX4p6Yyf{iI3zDIKOWTj`&U^v_7wVbJJ=II3O~^N_4sdK{kk`ot)nm zhgUMj3R{o^_uG9joKZHic}MgmH!(*UrfC@+bVlQr!|Oe(SaAtm7Ray-19e|&%+W51 zc5LYpbut1};gg{06pig5R&J_YZ>rL(tLlrhE^W2{#QIcgoXG$lyZXjJ6q_K7qTG%y zx$fQhW%67Q!XbWFDs!+}YV!Mhehjx!dSBI{rE@73nz`Q^b|E%(qq{zqp+>1E1icQ| zM)X#euD4oy6{hxmiP4I-6)F0}c9f@@i|&=Plse;Ovs}P`*wKO3Oligh%M8}@)nJY& zIH9ButU$(WxOO9WV_Dg}jkIc;0AlGBN}9i|_>vwzJZHBbo-|teh^5L~eWU73ew6OZ z1>7a=0wWbh%@GW6CKZF5OY6IG1QgcDyOh1q(gBP$=}kFmOsO}08+;H4>++#t9Fu_COTRYU(EaT8eoLmtrqsOMbgl_`n@@dq= za>uc5dIKq1a@Q<$HYrh;@Vlo0>}Y-O4vN>_cUyfez*RVGeSPpi-z&A=@j&axy0{U# zASKz7k$oWN>E!wNaX6fbp^UD^rZBY|T99~@POsPig&qW)JtbzTZ5P^Mj^TgSdY`!i ztfjBgp?5NE(;WNyZnRdh9zs~WR~ymEWf#hja$Ot&0S;(@iKyXpFXp~&vbCw^o-Mtg z<8;HxD}wHfo5Bn8nR{HJxCA z<(NXL{rase>nGw`Ci3Fr9^t>!YN6XcLgJOCAlp$Xp=^8L-bTqR1|CvhnKqWSWi|rq zU6XYHYsq`4)&ak zdRwYG1EdhdHVJ@<+uVoau ztK4l3Zi3G7*1y72s;5x`J=x~pKnb-V<^?%zmB3W#QpN44S$<-(sE&_8n6h(L-A`uq%w93wjymE#m*i1u~Me-&!+g89;UWduNxfKl3VI(gylwn&n zj8g0CP4%m~f^g^4LU9g}v$EOV*l?<`M2nk-;g$KpQGHiXe04Qbes`0K9b{G|3XaE| zaHYrDvHJa31y_J{3m}$zTJ^a#1lPyQwAV9FYB`4b?{r$DVhm8WvjQEJiv#-T`BUYo z^&|}=gbDixyyHvDN(j(@)S!TbzT6EE%A?_HsyhhB{aCe=D`i@+Hd6nf@m7lizP^_3 zSk?@Wg}L_RfSMigBH18WR{041f+6`kh= zlq+Q#5!I(kk=Jc$1vj(6#^tLpcPHWx^8k7&U@@h)y;qejuxIH#_hAatRN~&;*P*W6 zv~A9M_JaF#ax>e0b5k{1!vljqI;>C2;S`?V6INP1f$)9|lQK~b+nju`ydzL}5)6st zA134Yd)$)Gpuc?*UeO@Hi;WAUjJSvHbTfi{Hxz9r#qnicklpg;SBQsG?NEg>dlA;| zmA{a>_3muOp>6z$vOH;q9YQ&adA!p}r|{U?++pJn`YW~|^o1Bt`WH*x-1sYfChrhj z!;NT21XDJ^VNf2SQwH(xG#z0U`7sftfy_QlS;CzW-HgeYdNw1Q5G>Q#YHm&5sZrt^ znrm+P%hx_^-DNE;p+o|U*Qf|$qS|%F)7s*o#cufXnC)*0kK3hp1k zs^Zp$ED^DAS}47BqliQWaZgKv+Cs?mD4d7Kjz63Ph{#2tLV8@sX~6_D-;&&?u!iU& zxfLtb)OA!Ee8Ys`4W21A<9pFDesgkjeR8b7pF+X-yw#{4?``}Sazfjy=7nQ;VDeBF zBD|a2B@s<;!(X>?%$^7S1}t!M9(}Br%ng~Sn}SHEt58PEpHCNzu4&?%P2$Q3^{Jm* zO&=>Szc~KPdUxHIpX=S`GaYZHtyF`5KYIR*Wfu+(8`m*%HCHi0?<#|ooyv{j#LTk% z(|Qy-2|HnO$4kHw#yRYBCM&A&N9Ua0_o(&<}+S#a#6zOX+}za>9vft@xd7RKVKl%#alPg`Yx*=e(%f9Eui z3sa;%g}OB)I_?KO$Jyt|IZ<{;BjuN1c9FO~XBP+HVvfy*pEk``cAA0{4Qt3nDBQ+_ zCjOBLid0Vt#%gWYrz%r=kvBtyZiY=mW^j(E9L=xExt-lf1)_(i0(jkVk^t6R4fXpZ*5J+J2$#?dd=`uN z3x@RlO% zhPR7&5f>mXV>lZkt2}$%_1+=67FU7zR4*sTnSrI>N+j7pbx!(rrcB0K1i9rSt0v*3 zUUsrkTpU;JJ*VWtAQb<^QRWva&W$6gLQ);$OpFn5u^-d)d}ds9VDRbYMv??q*@T$Y}fWKv}ZYN%(u;eeX#tF9!W$>W!@t&_oTYu#$W z$b}g++6B~#h^K`E|!BT zm~uz*P{L{wPdOXV7|&l%!wGY>Gk0#V;}T7Q@s-~RA&4=as@9VB*9aKe|5xP;8vHvoi(62-6E&csIozK$|eR%>&-D&W8S$1l=4q+Sw zEi1>2qFs|j4ZOmLsA|$bm^z>0N_NqrKznE6t2osKq zLB`Pu*nA>s;oP1&FuV26K2j`7ekFG5S6dvpO`k6K` zK?F@=ENR#cbP5Sj54wlGp%OvtP_x98qiI-m!tSJfzFx)O^{v`B-Q(@k<~sg`u@C|3 z0!HL#2qrTRr}Nf1eIqb#!SpBQ+~>dKG-NvMxeD4*7S{o8J5K7$mSY1_dk+Hz7L*LY zICg8laI=G;OFUSBI6Ks|i6oif#@VzXqt}W!J_Kh$KV!?$s&#GA2@h*c#Q2~eOW2n) zsevnvDF?W7vhvM@rs#0+K7{OON6koefG2}MzjDG+#O<(o*4E>wHIsIS!xTgH*Sq1& z!*u*~WT9)0HN@$O@3b216x4)Q5T_Xa*PZK=1{FRFFT(4%I|^&F?lhUqsW9>m|LbJ7 z-ay)6KkRg-*R*{JUDekiai8?>g4(_AM9FnG9AAX9YZiLopJ6haUqexoAmMrv4%7a1 zFXCRD4 z6DHTQm{3tLr)4okQqV=E*3&zMwItzCGt%Cn;tplZq0uLBXaPLp+{_eMYMy zJIvx*orFXiV&z`Ld6dI~T34-={9V25VzgIjaU?;vSW9OV%6LI~-h&~L0gc@U?5eu^ zprQV1$InK%wi|L{DX#Cax%!%hmo@lL4ry|%nR-1)hyk92-I&GV8D~i&JsQ^MAPrhe zljO~XaxfWV>x21dcoa_wG!R8LOz9x&gsKyR@4lmz*WavQbC%-Bry-i&u>ZY1GtkiafZCAp;-2b8?l`L6==tyo6oo0=CgQ}LQ`J=u}`be2s{ zFPm8rRul4i=u>(E*bJ zayeM`Z7)GY5_zfCEN>~F_^e%$3r)A6)I1VZ14KYi;sv`_ z+(g{&s30kkB)#R>Hc-GhrsEMZH1%{0LSqr$3uqA{rVzDlx{(xIUw6R9JJ#nND5{hx zd3YLdxDcyS4@(?*^vJr%2tp%^*eO$(+-~6ahiNAq?q7sMKac^-D~{^rzOB`m`0Epy z@!)#(>-Ndz`c5Ml;3q>uBeB~m39bK2hxb&`BC5uVUZYeKOw}<5Ia?MqOou28MnP)n z%So$?Sc#I`aZ1xocc(j3afIsAl&7Z%GK1CRIH*Mmv|p>~6@44n%)D*l|C@blrqLHA zFN(iUT0~1vvP^3^e@EnR^^ULteb}E3pWifwzQ0SX~Xxq)gI5JrOX~d>2p|HGTw8sRb*F zdZ@kcw|vGg%=cVh4@_figCpq;2A+Aj*-V;=>#NZdqfdLDvNCqe$2kM%Ew|`#kDyeM zE32z3=fzggw97o7!zxJccjEeD&@U%$H3BHAs4A|fNRnwR^J*t)P3)=*$Fgiy`(OxH zS0~xl3PcMlPT?_5IO1(!sD>o0F{~@WRqO5XR0UOv*v?NGruT{GfsK2N{1iM62cV%L zHXL_9$8q-&^pN_@0(l>*PUbgg3!jKUr&>2f2`I=OKmcBOH!uE9aAT)QHNGP&N zf#PNX*D_;_k}#@b%fvxh5oC$;PDFzKE*g0ZTj=EQ%l`Cp=nJHy2kmKiA*I{sJv^qU%FKlN&Ty>?w|zLi-7q4!*fN;k?PUlhS0%ktYO5C!3EmsMkkW*2C~ikg)O zbZXrGfZIp7eConF11do&3j}lq80bNuXVGmn)e9&?3PvO-P2`CwtA08|foPQXKW@DZ z%>i1mQA~{qPD^zC{Z<^rrADn)vE2+|5?gBJeiOuODnVEdf7mF2e`^a0&RtZL(u;*8 zo(Z3|7D#AuelQp&~(Z5QT)}i#w){d18xUwD?Ys;*JMuXwek zt+y>$>k|o6g$=*7rsN!T9jB@mq#T$}kCB7>gu~YZd9 zvE|kEbs8+KJG7=T?>TgF8l<#F+{Rn67l;D2qs?xBJ!{Gi26}Isap1{0Z`39nHWM=m;T@V~^24_IuiwT_0_=^o*GYQTS zzGh{MS}1a-?Gk(0l)xNWlrko;Fqq3(#QN)05-yHsXaiex0{1z4m^13#do!VHVVfSx_If&bc(Za1JGzd3=r1Qr8Td_#6Lcz?D=MMAVs^emB_D+mFK^i_3zV(9MTxPl9g#G#S* z0LiE{C1l{9#!3(*<(!}v{x{$FVqLdlpYvJJ@X~{iqFW~iKpPtbh5{6;tNNSK<_pQW zGO~6sM9RnEG$Ps$#r1bxVGq3DiVOU_rngk8qvkq* zgMk$gowxKlXJZ*@QFl?$>iYttKIiXK*gYFZ+$Bc%9H>*!I;Q<1{`PI_Tqdi7+tm@95b9QhpLAJFL-*JV5321Qy8A$o!i zZO%&>TC3OIZr%-?HE2yO4yWf+`@$*IE=7r@%pkQ}wkK zL&~Z&O>B9XG2sbdSsN5F%Ui)LJvwniz50k{tG=4ZlwCOh650}BN>?BY{eIEm47O~i zC=UNHD`%O-Su2aFuCLz)dc)7w-{Mq*M|a|$>?Aw6Clk2_5=aM<9b^q7#w8b^2%w_M zjf@mJi7&6ON2)0q7$T|O*uc2d`9vb)!r2q0fr#VZnXqRV^7$no>g}7=)u+{jlYZ)*&r~r_ z#d*HNK}HaUL8f1=sn~Tq__qP?7v`wmzmU?HAuPd$M&5#**WXot6VVM(ufhOeWDsT1 zm}7#T;@;Eo$6R2cfG?tN42mS^TlOD78&&P#GGj~gd_e{CrooY6p7k=^uwOV6u31kv z1Ma=#T{RQyKrFC!ZpD6S8{f#6!;HXfcJqvPNx#5*_ z?A#+Y_Ur4+PZ^f7Ig-=&eqg#&l-0~F6`X-8HxS+<0-&QHJX{9h??YGz;Fzd^^@Qf{ z+IEnZPIq_Qbs9Vvjp8UluH>?oLkAUd1^cs%9w2H}I-v`&)yIOt5M4~ri5aa{^9yY$ zk5dVLBGuu2sYY8|hXDXw|E^+_YCm;pk+^8@4MDgb&~X;&3ihc(o+ma|whZQm170EPO`OlH5-<#AlJO z54N;Mf2Ad%@G_`ZVp!=&qM1$-lUR&hYv7KU?Nwa>k*EnacLtmbX`NU=1TKMCAQQPT zFw%acEeF*@e_)X8a8B(p-9bDe6$UHecoQnLqP&vSfXB(H*1i%&#toXd-aC;a5tYO> z0E}j0Hzc|-dpmg0DKE~QnHn8s!aRUCRUZ)=vQe^-ddwj?ti&XnaA7V^4RB>pajxF6 z%^lI&I|HQf%sp%kS|fFv_9V1kods)RjylY}I*+g91%wK5YXHl<$xH{VqOaQFLA|Lp z?JKzVJ48|+I3~{W1sygVjN$GPA~p@|z>R#$(kl8Zi2i9;iPLa{2coH$w=S%i8s=pt zaCm(b&%=MjSFDLu--Ce)>(d^XfLlcQH$yhRoXnbjIGj^CufxR4%xlv1&+6|l9%0b*1TUYhhBiPB~WeJ#@4HB zBR*r-U6=zZhS+_uS=*3OQpYLfK7eU1xBiQ1{g+JZFVjh;asHia+m>;DLz0V|*o9lB z<*K=dgkJ24EFA}d-U&ib5npxUEIz0@U2ER zT45ics8AU;-xqjTyenENmmr~C1?o*d<#5S&WQMQp3F^`Vh)$CAH6B21!P9f%a) za|1Fa4SKbDufMWh9Jq3F%;%3M6BkX)TMW} z5;FDRUKY%f(PEg1@RJEtZRE7hRRos_7FC2nGCNZBBi4KE+|w$JAJNVaxHNJE)}}0=1pAyVnX{; z|1y!%>jGeui61P5+f@!sGq*8sGdrpy-ZHDH$QXW5T;-OrelU+56jFRCYi8jEGMNR)rrB7Zt~73*nA4av^c}Q@@;mx$m8z z%uNlH#d*_!gEH<*p5MYmp+FWWi$SW2JF>HE`6nTV1<3O_?IP3D%q~3Q?*%z7=+}&- zI5Rbt6;;3-ULIbqCmkFx!-64(B-3qjhqTzy5~a$P^Vf{^mhDi3meG`zyX~C{Iaizs zV;PC&%G4J2YTESqJE4oIFGScd4liQ;nC^x^DbQ7M^-C(KAF7Ie#aB^2)Mie0aoT#H zxy3qx7J1QEVR;Gxsk%1yevXJ>#>O!9#u%KbE|&7U!Sn;kE-EO5*gwtO6UAl359JEu zK-Ga~;|-@$uZvv-`!8f>s9v<*v)1fmZeqF$M}7@a6c|$#)Xc*C*563OpwTBV_0|vk zAirE4LsmgvYrE^1TR&qnM~_wBW)9Fmkb_4uDs7tAb$oWafv1v!s}=kKyQm@^8)-Fy2B#5#v-Vxh+6^S$~B_@|#-L&6e%N?zL{+_*^=q zZE;9Kva*>D)h-`f_VDfKZRyxOagI?Z&?CqnBlD)bmz5lFLgMCJaPsq|RHDB7?jx1Q3{Q>eEgSSde9ayk`P z$1BQrsW6m=+Y@HbWy;E&p54_eY)vOHh&!uRsNL-3FVfCw2|f_2UPzCus6kzydV66D zy#p0$(O4stpb~*oG(eP^&D#3b5+wMmy4~2?L0k>nc+8RR%2*d?D2`H^?YM6Wj^-{A zX1o{G#?NeM1%7@Lq~oGV$Fkx9=AHI>y!-3bFv?v^HY8 z7CCC&$j~Y4e%)VpUN!A2PD`)Sb3{ft5s28m#6VDGHAHR990xQ_#hmZDN?wuT8Z*0`A@!<626yJBL#2uRUUI@Q|s1|%5w)Vo0 zan-i=v=76qpgEHrKrG^G8MlpM-ieND|L)JHoK4_XUp(4;Tv8d&vMff+4_j4)?B5Li zQ8t%6GY%@wKucv&;iN>Nwuh;$`wf3xNj98@_8srcD`oDb^j{|7Mq6_x$6KdOEda{< zy4BoPAFGvBiZ?eet825C4FhED*Mfe_(g-~c<*V%2SY24t@%priH0WDvQ#Lnd3-Lis z^mlNU9>4@Vm-IeM4s`>RfoIK)Xlr5qn+rVl{w7et#A=Sw^bdL8r=7yIYm#Z(5@|WF zk(I1V-s-Ar-UG*Kvm9bh9bta4w(ZMWb8#d&ZOygQDQuVHt*4y;B-mevy(UEe31wyV z5&EmE3{0Hfa34=Iq_9f3Ib{NO5l&pBN@sX?P>5YaWW(i1nLs z%3}n=WXiy^{z({6&ONDP{7a3aQqYlnr%+$0i{$6If6KN}*2#2r^_@0zGYKE_=Ih#86>)ywR)IjUrm!4& z>(~&`QD;ElJR?7boDP`jB_2@9W~*m7_;9VyxwEWn1?>MHx6WO}i^EpxF+@!v204_o zLX0FT_evaA&mA9_Mm4uH+X11W*? zU*ERKVM0G=!#$$1}TnL6@HonDOSKb80f!4gyEoz zmKI+OoQ;o%0qO%Ch0{0&!e_M8&SVU2hC$EzJw~k5Oo$UtekHKeJ93v`!E1Z0$a1+}Yms zC7WA;V{qa|$~kY{8eauK=Hgk2jwYFVIosRHLLFoOfxqqssHG9KdwEy#X7&3pgM+OX z|My{LIeM+{Gl`h!POIiGwY(?3Y@(ZWcPslKH~N~o&|{AGH^5(}6%2^rp6?TgtgrWL z5q(=-{ee^7^Fx>ta#A{OWzZU2UrPh*uq17kwACkYdu&@_gJ>pitnZSH$U!HONg%^8 z6$LBF>MFZPyO7lysPhr@Bof!SB(|b+Je0NHCc}V^347L3;Uk0dmg}TXs3XVC+jE4# zCN++Kf>5@^S3LzZb7<2D>E<~O;~5Sc(=D2~vZ*o6lM(T8?Hr2*5qL98l3?(CLz19n zD^A6);G8f>i9RsO6EAIyPw{`v!drG?)K*d@+`ZM5!U|daTe4Cxd-`{@4=@*9#GxC)n!GPWA)qp$TV^E+k9Ew1@V1xL1USHwFiL>p`2>hI%3E0Q;z3OBrsX!l5CcL4}*V%t@i*9nlZvd`oZ_l zAN`_#IN=JPxKbV(a6V87!F*k>Gri=<8XU10fde^Fq>Ykjq`%6#2|<1>Z}ij=$syO& zKSEkVQ-!7AYA`AiqevL==I>#P{v)!P$a_g|>hZr4>aw-Ax#mfTN_>;Zp7`3>^|PbT znTxWQ^xv5u&!k1YzRo<<^hnLrr_*;iB?M8$Ipk#398XOT|L>t$fLg%QM5@y+$ESG) zF|fqyYy{84T$D={*|NPdc~_J0mg_pY<%_To*3d+lB+^z%2zwHcpbs1LP=Ydo5Vc=h z9oVcR4zoa2s3JzYwVl#v$e4!Q1ph>+x!fx5lm^EzeBF}JbZ5(=XAmAglm2V(&+mhVJc^{G%c09knz42HuGGe>xYGTC;V!DZ_%U#ld)47q5wf0?|yEuO6j1iPt% z#BQJrV!;;T^VY{8Cv!X(oUMh5eK7f`I*V+$B>#h&!49M{(i};*BlYoytTp9 zhXIik!vv~|ACoAG$IsbDy)22OqGMK9VO~oNry0hfYT!e42&yN^yLkANmxd$9eyB=U zRe7P8?*rvKxLaj3zoM6Zz81{SKU8UuNws#aP9(e6mz>;DW_OcXP&jZUQHurm@_~t+ zrv|Fn+$_0>%Oe$si+QSp6>m9Eith}de^%gqfAh~iyjofVB(mzZ`kcrPcj3cyG$E*s zj#O%@VXOGK%5Hc5)}L{oREOe>hA{GjmcKpW^QfPW%resj?%#7>%0T!LmE&J#twwfB zTRxAqo2~2=Fikkmf^#|$AEDq2&U2gdF`M-Vg_z#-&FI|aIM2q9-t^6)sV7^AC{6px zNhBB-BX4?P3(srr265Yf)oj=-3%zR8Eg>TyY-OZ_X4%=|kT|MY)r0}Hx<=T1ztRJ1Aq}7p%Ek&?O{3`hLah=*DQt#8aVe{23MwBMF7on z+lJZdTeiY%nmc=LLp*(cJn{2Z*zEh|}QiyKQdug|gFQ{T8))eT`(LiYX<=5J5CnSB*DDKVw!~6m)Zt zAt#!)@Ix!Zdj5`rQ^a#8Jl->HFehnT1`0{Rn{bqjCGA`fKf-tN!#;PO>Uym{W~kcG z&my-@95}UlHR~qYZ}*%1b)S%2^Pk3hStDq7PhH)CTkN;*i?ac8IriC$YQSk`X?+JA zZoyr>m6!SD8_F#Z)~AcHxF%4C@Hs=QI(~@*Bwt(E3Gg$zishZ(qunNwgd@v$+WuBN z@|#%Rf$S-+n{`BI*A*hSWh6K$EG>~yxIBILs(+O+`gl)}Swbp=)tbbVQbKBGAW^ic zzqLBGC2_xQn0@()&T%-L48oJ@@xN-P-<-hKao2d~R@uD$`Vn zy+6VL2|wZ%!j`;_)rHJSt=@#KV_)b|>h?MPM|3OwJDMRZ@3NE>3JlFAbUNCnn2p0a zId@`K(}&Z&d36&c$Sb<@m8@tzRDQ}^;3MCJSqI*(1TG5c#c}s^y%Xe{w@h}oQwXuj zMkvQne{Ay6QB4na`>X_l-lTuZ;q>KvH3%jR(~jI{ zg=>YldP!KDd9k|sy2{~XZs|368df7~Qd+BV3_R2ep!{_EU5TB5QMp#)cDE^Fi^!2# zK%tAp>a$9E$&z%OUJ4WNOP-djK&P#i$!|(quAOPAY07W1P5kB(?{17t?F!t#YFlk&b)u#m3@=I5gamRcAb! zeMWN3m^B`@fw<++>xd4rX_CIJYhVK*QwCay?o#9X&P`f4n<+PTE!D|hVA|-;kbyi` zUllfjN0m0!-}0MqHM$8*3Y6yiaGZ?Tr|W?30{+4wJ2*HiT__{_vzH8q&($#Sa~Qw- zVVYj*??;>zNkX}rTZDcg`R|YBS85v&0-e9my*ZxYD}hRS$>08cfQT9V4T*W+ZB3(o z!QTAuMc(B%t@Ntx>u#y*&4e1nXnH1Es*~)LL!HJgmFlJoO|e3OlF?C-U`+08_jS-ppw@Ork}FF9xx5`&=) z-ICK$I8=+zNn7uPT<8vGA{KgrR+S^hjIE02|2$A@nFXN6ab>7xkp#EIIu71}Q_)&B~EBAKqPmxxnY>hH!$ zXI3%>-cW>1;+w^g3LSahR!BJtKH#rbCPgIv|{Z@R(|71b^n6@9%U~LieEB*==npfj78HU&Zu? zJ#f$HuzwPxLQ#2UtbRB}e8DDNdeX#nhXZx4M0S;`dN8e@Y>=T$ceI&31a?}Fl`hrn zqAR&0b`tS93qtFlbay)f%W zI)EYMfo;oY=jB@kFXG?uJ&-X$zLgWQn6NkBkO@|7o6XIelB0WjD>pbuLjAb2SN`Q9 z(j)lNqCEPl#CwV)Eh?f7b_&;lpTvC50>5jB%4%sulWdj581Fi9eVT|5bx(N{#MJUn z$I&U8hgSOfn*QC`=D(YcYVam_W~?MK$bmr{axDc56i6d2uY`~op94CtHjFaxT*~9(1HG*clmlP zowUdDSJ%@&r7CBowE~WQhLzL`sQ8jz*vK1oT)9p;BJ^Kg#__n-?*wkSY=jPaiFzf$ zq7fulX27w{0~7qL)z!{%GpHkD@h`=9o1;Yh^Tckd)zMKNkT_7;%3aDAPQs{~8%M23 zzH+X?UXI%9T5697ti`lwEF-g=2>hGj+MsK=0};82|5XN(ZXFxu)4ab4ri*a~5R|I@ zL!G$`P>&YE`>5D*DJ@A$ui3G)mZ#ceE?@DRFxU*X%HQd*blj>oxuf;1>Q&vat6!tr z)c(r0H=D;3WxwP;vc47)FjBWK#z88DEG;Vkd+VZ__gs}wR{?q*Aa&mbZhNiwCW2Fr z?ooSVvMw;Mg)zGp;F3I-A0LOZWjaBGDl81Qde_btZE6Or8mcS+{2astBJPNM7~Dp? z)8ybQxd9Rue#fh7+AlmoD#)cn&kfRH4peQ4J!>z4(pfMIdf7DSH8T}{w;u8ts4!z!Ha5aI*XO4C zwo{+u)B&T?6aVg{RqT8M{rLUcfApsIYUT01p+1G zy~a0w3YukNn2@&_`OE7nr%bX5=l$M0Y^7f#j)J$4E+H`MZk}~6rQ{Z^)__h5zeJoS z`-2@T1}YDDFPTDdXMeaUy=@(0oN@IB_R0EsFsg^c%kXOEf=JmjTWMn>(5d3pP}Kro zU%O*qDuWpQykT`!Gv_c$BTh;c|kLzn#E?WIV^DI#O4XT}M)qu-Ei`Y&KilrzgP=AJ)xlh6?I%iZ%wLus* z+kShZSjgtYs!uWu6?@_7sZl3(o-LyZD`szpB)4q8oZ7Zk7Au-=-~8gf**?9g zIgY&SmIU|eh*rNNQn*-rZnG~3qaPvsqK`Iy;fBa~o=>tDi=b2M03Qlob_JJRX7&V{pd$?|Q`i#)2xl^q zmo0FvbcA%EaSXqw^Mjy3PN*4)6jOL>7Gxr$TwnRBLELESMyGa|y_$>`Vbi2n8W&=0 zw_*i>7;r0gGM*K$5x$q+atZ;F>u4U6CAW{_UOb&5LT1UiR)b2Ipt<3UG4>@+W=$to z+tC+ir!^o%3)+DA3P;U&CR+#^Vg1a|`x}VY+3Ggz6J&7jwYD}QRyHTCGr4E2r-$Og z^>bprVP8?TK8FK3Tl1uM1-pA%jN>!fdThwnE**}f-EGp%HjQWL@FF%vPC5A04PkhW zk3C8VAS4!esDetnkq&6k#8o)YRyKq8%9n7TNjwC67Gkei;3sd8;6X>~Qno)yJZpB$ z!{@@XG`oRWv!+>9y->}rS+hWvqKRhT3iZ0olZNqhfT(pCbb+#$zcadLb=AH#q4ia_IJw(x=}4| z@m7HISlrlv&`_<3=RnGt$BJ{SvF#jhGLM2V$9d_B)Uq^P=0q9#?korcUEPp*ndkx$ zM~IZ5V=g6jCY+1vnP1enXp5r)zPnO2S+NnB@Yn2gbsmg6$PJO{NY8M6eKd3Dp#1URKu?}f=w zm%w*}f7CPi1Xf9J;CX=m}jZiCqK>+D)-D|i&p6QjZsY*{MTY2PJ6xfX4C3hjil z`xO_g@Wq(!tnGY1wxy75$vn5BK@q`3aweeA;V&v}MpgZ635!Kc=rDp6m|B#;es!J&J`tVh&L~C)kK?vU2iXNK8?>Jn9;s73E_1y2fmXv5p8f zH3bQ>45R`dNxCDokwWJt2vux1^=_HYxRocA!x~38;-#%hN%-04NKiT%GQ%v4!I-5Q z+nnAi{AV&wW&>7=br@;F+r|J+zb@}veZ)WMsZHYG(^kseSE5K+TU99N*Ya0g=2R5j zRwZ8WjtP*;7`#KorXEcpQEbS@1qkK_)S?5rLFcIgz&XPr!Vs_(9G@{+ae_` zq;}SQd+qqV_Kg2$PHZU#GP$MuoMHw4^56*;t9{A;t`p!%;Dchp^NuzWvX$hX?-^vc zv9VL@p$aguiim0?o2#q*N}nl^!TbOaCfkZsS@7uS>GXkd0MF@_4mr@4CItNO)r24M_|>DAqH)7xHBDMp!oCM% zYn&!+-0<_~i@EcHTap*5A^T1>ck^Ly;v#C-v+QU@&C?TTgl(@P1iR;X)XT2^8f?2t zDr<$gJ6)4Ti3#^ml0b!!72%s4+>QpT?#2cI)=tNW@sv!ObI@6Fu|t>Ug0{*)G^K)m zwB8{^a>%AFfhJW$93cH79JaRZ2DWsDn?(@Kgb{W;KTyT1W>K=u)O5Q{pF6FDVz_1M zC$M>wNC~QjP)S&21FsZ)*9j3Zup=P z?mpm&d92%8(@~S*Doz)6cZnNT$nhg%ahYRdy2FV4)E)gs7jE(A&e-m@yH$sU#o~?jVzQk0g zc|9MuR#sF1K{o%gQ387=N+7+638Jv1D=UTVlz8sCL=c+{b+{|J$w%fv&%C@1Ci5G? zqw`t$34uEm65r%bZfa7lrh_D6L6>c+MA$}q{Ou=Qo?GSG+QDtwX*Eu!jeanrFUKeE zwl`1aC)1PhN$+&M(cj6?@l>%)hmR}EgwSP+-F$Qo6Ot>(f|b!YilU8o3PFNc5*oqc z&JZ8nKpT7j{kyURVjMGBH;X2+M*(>DV(=Eo9fQ8edD)qhqz8 z5_9GsmxmTTWi7X|jqNyA!X2aC58^;?xX#cgyB^n6P(~xg$_yqh8A*KWF#5$|a8y(n zZ`eW9AiYF_GC517Mp)WTZ`$F|HacN2ty@s{1~9zGI5FmxuXO}u$?;_pYekYrBTtTFgJIRV6oT6 zfSR0Kvqylo)zoBmkhG{sn`r-b+=Q!6vXh83uPf2rs$J97^>xxxo(~!H(q8Er^rF^Q z(6e*=^?T+&t5m^>DW%_CU#~bpn%pArNtnZ=djij*_hKhc2T~3f@w*z}c2v&FjtSw^ zUuw6?*ugGpujS^B?$lhxwfKwm#a|4n>prVORO}rK(5f+p&`WCST0EO45)=E%giw)TH* z69~8EOdDD<*?O+Lai-9&O5=P6I^s8 zz~Ph+qeN2=E|vL)8uqnbxY`}W8t=3UR6uZrhkVIp?-n$At1;!6`(19aXpN1_80;ls z<838}PtPE#!nm>uF01heN`{|GPux@J&o=(3GgF#aEwc$a1CO%Ou|&8Io>aRBw-=q}yi;?M6?fYjm9$m<6K74Z4b9kIRk3?V&;d1W z9MohxYVyf(z=|fa4yvXrjr2_;DkeHNA^sGqfhdRYJK8)XYU}ut97sz~w<$^bN{$y& z$-C5#$$it}Xd~G$b&4{xmiBxAc3cai0*%#SqrIvsix5d2_S!0i!z?z0ny~}mVTe{F#??9L7(qer1cO4=Kgq2@(iuf(VF0yIde~MWQ_NQKylN4u&{J9obMs#m3ZxQLo1U3DEt9(7QbE>Wj;TG|J;QqQdFpcDn*w{3Ch zY2txYvmw-5giq!O@7GbNgL70;$K2_B2_PxGPX=9bAggZ8S=lV;@O!4_O0qau0PAuz zX_;XMoPnk>#W|}}yekPvJN6E~=+u*lc9e6o;BPlgr_rojb+wbDf`|fZU~d3d z%%Lr}%4pv58U$O!I4XMT-->9GoGwB#UF%E)*RrM8qTysZYEP99uTcPxvZNER;|EA5 zF-g9ibb66(#tpt|5O9bzDdn08(BCWs2z4yzz=_jAPZc%Zfoo@u$STa>(}*l@Da~YO zz>-R)nXKCZEHWH|=;H~VkbPD^lDI)($rGjp1IX$Nd#XRi4sffc(0Ve)a(;gFk)7p06jp$ zzrLhAEWwE1v+PmJ9UFZo8&oHgS6rV3flBtPy~(nXQS=b+mdPniU{7N>>xd(3%b7($ zuaY$CE~>5|vJ*U1Zf{yVR~F7WM6wubsRJ7u9VABts0j#twmW_ZO??oxwphyJnw7)( z6)vz=#Pz+1xN7g=Qz-2bgK^wvuE9F&Q$_ZjmGH&UdP{!o476h}a<~xY;tVRh(p|mM z!GIt!6RleXO#94h?ey}2KyW^%MLi!~!T(O5jX|^*vS8L|Y*UAO|dfS~*RQCGZ_hSd2wc55RTZHca&YUAs9jqQXuQ6 z^Gmht1Z=1$u^f8y#@w-Q-mrW@ZKu3eJBr+@!cemoV|fD-bU@{Ao!xR!2_!o$z*Y#@ z%7S~Oz`Yd6`2>^#x&daESZYh{%^hvB?c8cUlBar{JJnMORXv?a)f=W^gN zxABFVkEhd=&I|6zcXL8J3*T`;FEf$Ia_p9ME)e9KayD4!uA<#{6`1R6l$}~3i^>2K zyd`6%oiW78cG5^R6Pn2DkAVD!X;)0U_l==N@EBUcb|d(K{#Jw9b@k-<`aS)*xjwC3 z`n!cf>)^wlKNaJG+10q)@_EaB`i+B3uOaWS*&n*v4968x!g5l#vYJ6xyitE7!2Y`a&7DSY01!WJub$T4w2uF^diqTx_&YP; z^>5m>=COA&KSh8@hV^f1C)4(wMt>CiL-Xhz!Y|k1WP<-TX7h9!_T%gN`UW4=8N5t- zgkP@-m0VvY5%T^vsnaK_`VadruYcU%dj$8_r+9YKIB7J3XZ-s3kbY53Zi)c=OI=CIRx)M1V; zIO?>XDQCCCoRCniM?;yvbSd+!olp_-uxOGEpP6=@N$_!7cov;{=z0 zo)Pa8gEQmrO3 zLl6;wi`kmjpVfjs{();zEl7--)-4P_G6bDuAA;4@J_CcD_fL60Ht3no!gojUd`@GV z)qBHmuKa}%;M#Sav<3~du(bKrnEnzTltdZt3H4#s@zRw>x=u~F_1xsOugjg35erF} z)fq>4Gm}$v3{8plDZx~ex-5+owJTQ91xLw9MF(KBhr@U_p-II*5|d3ArmwOqZoHJF zy<&X9VK*hCEpkY5Vmth6q7%MP%x?5+J00TK&u^$C#zM8awH^;kJT6URUC~@6Dj_k= zjqY`J^XYTgBfL0e2R_vz1R+tYPx}T()JSi1uU+k}$i!Dy?LZJ*3@PNaMAR(r&v_uX zKHvcNb9ZUg>Ed-jv~9Z-?tp7&$Nju;AUh#KCWx^vo1)nw4iyVuD&B#|Nj!{ZlA5l2 zT=JZNsK$x>BHZ~H;$!wBfXt=kK7jG5nL>^I2?M8lbStpZ!^Vh(xje%%(i*ayku&eL z&WH_UW(F+BHTFIC>EbK@eliT zaQHZs3C_)qqScxMUVSc!?)$VN$NqdUO)qEuX|2=hL-x-T!{sl()x|qBp_gZKI8bEn z(SZLn`|V-Vf0lZ(g}BPR9uWorN}9?%#VXurc2l=ATXefI_!caEvvcEw%?z1jXl@3? zn#`Z35o;mXdvPAJ7o&@8n(r6WVe_yPu)f!)d(sb**%KmFhs}Q|0p}4?VH4itEUAb| zIhm&DoD(<#rGWmBkePg*Uvg8h&Q65lZM@sKyu93i#oq>X$3m(&+5uxQMF^-@FCTCG z#ScQ75_~Y(`Rkt@Ni!&95mAT9*q0Pz@&sS~;2nNvdKwJ_&rnjq*^Hw@I|cAWl{gD8 zLY1NNMvt9(N1Kh44*falG^9)ViN6hLkAC4Vy@j~OJvdU?*AIyr^3^Q#BPcEOu=F#~ zpfUn=gs}oVM87HIp%8~2&lw9XKhX+!RYSC^=a_lZ60>xv+6zVYTkq97L?yj35V2UI z?&!4X&f;q;ds9JF(4^SiFVw@FUu(e)&C)sA zd4>(5Rm78gWR0P{P!|*U6m^kXcvx3czP=s?sr^Y!yJ2ib^|QB&czT5hSR-Z_kkm7n zWc;dwxAgO2I2v zY@gnATIYoLvu|!3P6paVHoNQGU`%_%VRl$$X?J)~?S9k9@DJgvGn*GC;%ZVeL(o*q z0`_99IV=w5Y@QGXtO4sNAKw6c`80{*r;5ZVQ+S|}p&>$Ap{{E;r+jTWl)(1xqGlo? zgtaLo4afL5fWk@W3-3~UxQ54-YLiwZ>>~UXh4xr1UwBmGi|G1+nkA40`>ZX`Fzr3CWlJ3 z{l9GbP5<7#yF`Z~wg;8Y730=2<+yiD5XqjMJJCvV4V$6MsTFB4b`JFdVUb}(1pt93 zO7IH!G8huscv%bNq$^0d+(~q*WArL_a*#+QSwee!_ph%r&Chv?wQS30j0hJQyQ%Ug zn{xmv$Z)18^VZ4}MFU7th;?}vGNt&Gsrjk*>#geJj)^qtuhN>e{o1;kuF_x2FWy4r zbZ#kEJ%QK*TipgKJs?oMv-PIsukXWit=U^I?Z!7H*z&)pi6C~+cc~&KfG_KLL{;?< zdKD^Sl47w>SFH=CCt@NUF9d7O=?jA-Ez8Or zBDQ(!Du7=!;%-w5imRlBVlI6X7nG(-XwCFjwwpqBkSovuv{sW$h?P-rOkfgRp4OTZ zH^#~cFnbluPi>>1psG_4ylOKu(0<+)cvqZilYi~Y7yW`c9y6b2Ao+ zK{wENj)O`hvlrm7P51_A?A7q!#24Z472U{XUJufz+m(nAOm})M0>0uMX~C9}ClHQN z!W1y0wOovg%V{`4>See0PqlhbZDlPUw4sA?v@=FxD%LG$wR25fYxVdoGBugR%saYR z*7PWoYF;-Ubn+S1B{VPxOe!Xa*QV?CiM3)6GtX_(Ad}Wx0t9Dx5iG#LcpR6ya(sj- zL2fO%sp4whVmn~W1KN(I*JSji=6soP?<@y}ZV?nZS+~bp zQ@UD=vz=v?zOvDXoKkRnG4|SGI)KF3uo$p*Hzt3$_#WDnkkqe4V#$Qo{-skbn9G{H zEH*=E9w#omoE zQ&4ULIz*9*ZCC=6Hq?J6<8QT=&8769wTVS>^C|J8m2g>l&nBq$?2U&5O(1M+&&r8<4#vJkz)R!t&x)v)R=Vr#&gzR zvR!hwdz&5ed3@E6$F)Xcfh6kYlnjLc`05sNwChN7^PY%+H`GY-9Pq; zu+Pikj1_L&?tq+M_fP#Gme>^sB=IP!xi48jK(one}j0_HcwWRe-C~JC$KCb0c8+u;vOOC$p;GwBEg|tKF`g zhm4mwa)EZb`k>IxE8H#4nb#}-rC-%J9kDYvH|UM)QNNRsw2HH!<2>K3wZ(D1TjDtX z9&>1lYfK=%C862TkO)`UP%!n`EGgP8FUmx$BKa~f{BEGhdye{^F-U1I*TB5@l^5dU)lpaB@9PBUV|RK25Wx}TqlB|Yvt1nWawQHBi|TN zDSKVc{?W~A(`o#)+#yW<=t%908!P~(nrS0OS;t`PGhT3?U5z*>FId|d5_pti#jypG5k@QcnY0|@NpXS2(68i7!y zMntQ{V(=a#Yv&=ey3PaoxzjPi_SMyXJujj!dseko&}U}e(Xs#Yh7ttD(FTYnA2Qj} z=Pm!|r%!&I&nN1Iiet>fj;!5;i2V9R5mPUSILjl|>x;0YlM&5{eTT#`1NrKl@JKIx z5}aYR;l4^(0i1o`k!r9mT!}sjmIkMWc?)P=#$1qDezBKi8$pf@dT%A$5XP?sSZw8R zCYCdO#g-R?Nc8Kj{*e=#gPv$*pNqICG40@)k`|p4V77e!rbo!GqmMVNI-Ct_Z*6bi zH7VP+H}BP&y_R&;-rn47-rKx)bGEt~S9zfV&iGc;D)A+vV6&ZH!ge;eQLS0JaJ;y! zZWAaXuYMt#hj6@mif=OXHn0o3Tsc{6!g?08T!$-DF)6KhoB7_4FJHd!Yi?s1wWZO9 z3kR*#-d1NFcp0_!lIL-ERQmkghJBOKeyiRZCmo_d(dsn{*5om(yfb=gRyeC>%9%=G z^Y?My!m7~YGxDGlBh*mNTh)s7Hwf&o<0=A2zGGNMiRMq z9PVfe{iz`HlrOMWr}RK%45UGy(;>E}>iW8YxRQToSF zw&z{w31Rcy%q>_ar=8Rbr&WilxNw0?kyyhzb!5fv=CoC$ef!oT8jebr;mjMSa}SWj z+J!zX0WLRpNm?Ri<|G6$YzyK{%l(#dWVi{Ul6d|$Q>tWzus+At81Wp?9P`vX`Rvkn zb4v+GhM6wx`1<1RYjy?+6Nr#xA!fhTvpIkaB6D*Wvh5Ma;L8iz*`=(+iayL((UeY3O7o`4 zs&%YlGNX9fkE@V3xZ*k`_!&wxQ#QKaG2hCjT^1I2Xwn-Gm&7x5Eu17{5VV1gQ=2_^ zyBk|^EDZD z05D8WBOsQ0%5Jfi%T9u@VHV`6b(F3~1l#_DD7o16jdN5Wjkc_Io6&cu*#+&r>SyvUKwpzV0FPoZ|=NXQA!09A>&Y!e9BdF~Gm;eOm+r;WGH5ep4y@!ENZni?Gi@ z4cibKAO(u*cT|&f^wp8XB5|aNX?}Zax5cuwR6i@A%5+J5Mx@oc0UsS!yQ8D4i4W#` z1Ww%yhAK6$iKmHJv#B;mnZN8M}Y##YP;%$A2Vn@E>HH$sCmgd7_xO+ zbi(K=;t?}!taA{-e*BBfkRvYZ{D!p+5OUlA{bIP_ISMf8nm^}jA_byT6+cn;rUo^z zhEA8n%_~OvZ01)rGEqvEmyJ0Va)u)Jytcs$Em?(TRf%n7cV8$y8(m1wQ@)dJTqJC! z+$o&s+N4wGHRWa0Cz(r1>SS6o$(_u>!Mn0(CFQU{wxHS^IXv92( z1-}LZZGK>&RGusNE##>dv3TPb&283p3PI0p!1H42XDjn;@!hnO#~^XL*JkV8UK>&I zoAx~C4>t0b!Bve(*eVq_2d&y|GdXDIN>CaH-FDn`p1%bDSK}s-#*3rP=Mfwu*?h!& zPz-#%6o~+nXpBe!PI^9}Lp6M%b}Gp7^dwG8LrcuLU@Asl0k~^cPy-q(}(G}N37kv zRYu#_?*QR5O?;=7b|w9cYRkM)KgaZXe1nh}_8F>;@wm2A`O|;m)1AeQhd=H;`(gjd z^B?N-ck|EC$0mKgy?2lQ(kK7-{&(MQ{%Py}=Kbw&x4+%|Zu?K0TibWPyZa|^^D~U4 z@L3?ih3EZgnx?nT{X_5nmwq0ykoig4Z&oT7ck7#*-i9a7A`b$MG5jx6?}rypF78r^ z?fT}oRAPTTTTEl`)qzA7nR!Iic*;mB7N=^M9>!DD4H+ADhT-_!1K~20cJ5OET&4fKQN5ttS#PNHGXu@Gss6qI0!YD&&M=GBBEG7}*E!FfrYWfvFa3&E? zM^f{LM=uUNmdPh@7n3S?smf!}*IqK4En*K^XKzH`>GJjHW}MIF({SSThgXw9LRT>L zq`Q_$gkCSc^hPNy1X9`3uQ-}vB_K-iXoi!;T)NuE5))EM`m}}-7Lg|2BgB2>A#F;3 zO5>LPyD!3VJfxx1STQ?(iij}GB$@#v91e{}^i`o*wI|%XZVt}3QFpo+bxNzu787W5 zbm@z4zx7`K_!KWiA)(fIi)Nv%xn+)2w;Liz4HkJ6o+09l#HfL%xM@wQZ|dq-s@nza zQDMGl>Ehda>om?Ekk>DyNe~U-C8NnSy%19tYHzE)^%rdUfeb{A(~~#f(VN3Kif2iG zER*bnGy0N_z3=tD<~MUOpq=7<_^Po%V z;RI7@Hf2g$us{ceU}8=%=8e-!uM-2hu&L2Byd2XkHPjM#ju20dH|L1Ko<=Uc-Iu9a zh^J?O_@lVHm?m@D?Bre3n@rhs+xz+G$cq+yxDfrYo1}{wfyI=LSvtLHz&y?y3;3X+ zyVAItE>kz27|@FXLlpxIAN0INJnuHTvqd81mBo)2ze{HG8C~fy?)BI<2nZ%X#Lx)B zXm`!J6I|nv4nhd_$1LAZC+ZlW3Hoouo2Cc4<(%=wI2jWfr@WKlZmXqN5ls$#x(9HfEH=|t7p$&?l-*yA_BTyB7=cS z>~Nu{W*x^^ww(dF*mC776kbe+*dBcC&U$>>Cc_0$*s@yc5HU_{bo)tzhx3Nuuui|I zX5}k>+~p<(M>f>ky7!XkDrqMj6NVYEoL8Y2g#W^NtOLX=U*%Vz?mZt8dGBfedF0K2 zcP0-?rT^AP7lTiS)X1yDC#ur{D{2VkPl+*J43WKsu=@osl+?n-!Gc>H16Zps`U6Zq zsC-56A{~Xj9&QAISdUs)RlLrXYJ!%Qh{tKfJzZ74a@1`=a0d>q(98T&GMz67nb0oG zi0QHDd8__c2dx44=*j%f#pJ`bma!g~t*xwXHzSh6d3spvp-Ys$ls zE{#z_1H8nUnJz5!n%Wl$4S|oVb6*n76CMF{(fR^N=>3cl7PqIor*&J?`0aw$(W1@o zoXM)u=?OCeo;#;PW=XhUF^ui)CwJy-LYN1LC4R@}Nl^vKxOBCrF$xKtK<{-^sw;_A zHcb0G!f(w2%8v37Crl0STJZ8kAV$I-?w*iP#~?O04*`iZYX+>qK~=}1G7iSFb8t5N zN@d&zH|mKfqDD7$$y_WC^ZrK~o#Fd|P2&4B?qOX8#=xdP-B&U`@Z-0bR5#j8hcL@I_dFnMpPNf zBecM**=Y3X3@u=3GHP6gS94qomvN^deB+FZGMU1u*uxQMaz6erB)lYkcE`I)7a&F% zN6l1xZ&2@qz8YY0gngk05S-D}g-~TalSn1}_~F?rPctqr79BdN-V?=-5^*%ali48V zV~paD(f^U^pW1s2WW(ro$BPrb*EB75S9hV>3qS@{iF&3%6Z&LR?;4HtiZ5~uPSvcJ z&fHE=-^$(q^fwdai6X^1F{lG#B?FN2-s^*xKR$o;l3Lq)_KWv=@9=Q%*~?#c43i4} zgIh|#YE#2Bt7$l_~7NU{i7qy`}v`_M_10_%Y%on zp6nfZFJ2wKcz(2BCmtvM(84nJnezHY@jOh1Gnw))w3{;;*f1i>^a5zU8z&cx*@@M- z`j{;nrixwTy|yd31FDY*kHDMJ_#S8oyu7@u_s5HRI_)=<7-F_t|NW21*C4YAtm#(s zs)s`3y_&_Z!|9kK2YD~1>42{1ISwvyfb&C^UcQ2o)xLZRO745n0X!#M5E6e#bya)c zPm{PukH@tNC`3R@cfP~l4_-WMHu37N{C?aW&xhXI%WCt{{^Pw@PhNV>-Z1T+*VJpe zqngdfL_4{^amwZQ!ygXlXE>dpiC##z`s`);yb}?YX0lHEw?TrHzvR3|fSK6UHObY(U>4;sodqG5RyANgS4U2Ovz; zSK$3^MBLnfTKk)Nq`xv%Lbc}oB*LEs|3RG4n46_m{s!j;I!h=<)E51l61Fy-&gS|n zccj`@?f#A9&5dL<@jK$J1NB!A)4PMBV~m_mlQi`=uzh-Dni7)h2k^mD_gWbcXg1m4 z18=G*lLdrkGa)MJP1qg6X|_UVxw?`sLCh>DfNHJgy{~*VnG*NsnE)YdljWHJYMdAV z9zZ*$B#=*(vfUyhAH~ChgHzvxWG-H^b!mrqN;oD|ZYq^5Og5Xdc>ZR}-`~vBH^~@j z#OGH$&x!&FS`J@PdDNH!9`z6p93aBe!pUk}s^w@zX&38IDsaGm`j(l$n^VIT4S>|@ zT7%9fgCYIcq<2{7JJ^!C3~z{k@k22w#207#OR;oj!T~@E>pXf95wdl)s@S zOb2OcA8?Ufyy*^zv9m9^8BiIU_43k?oq~WF_qZjhc^}ZkNdOlRkL&p+qrJi|9PTc&8G`Q z5svLEc@A6nusiUa>8Rn!>E+U%f9H)HMd|sgResqWMb(lm1U;<>^@cV_cFzxfcd+8| zWLJnyIz0}q-&*U;HegEzddz;^fS7b`_rc)au9p5dLNkc(An3->=nor%!89sPMr}u%M zy@P9@WTPbZ?yL~Dqq`bM>fjljCpD3SXEX~rS$GW`nZ3iP!YUns?86k2|Jdv{7~{u3d&a$8Mc+k!|@PzW$xBc@-RWMyfsG;4-a0vB;F+O)^^td z?M)yP=GrdE$gHl2JbkV<2=U zUe*{SLsP(KAN1UyW_63dQxvN+PS^(N&V&1 z7q=G_JoyF`^Bauwq;5L^YRpe!>xOAFUYg81D!eKW@av{Ra9yPKuzIT^|6Ec+sbPI- zj=$$h5;r!dDYU%p4>s2MaDS5z7fC-{r2F9_qmLNN<%i2mKU`!SU-mw#RP+%OGmY`L zTS`TyRJ3g9@tDid-z6oYc*rH_?~)S4_{fgo%kna*E|V@Bu^R5Ou{sybs`|d9B(jWh zF??B4<{`%@{_tuag%{H0jJ_-#+2l&~C|{SsTY3?za`JWQYK7D8K&=op2d!m@oxP!@E(Nf0^@+OB2vrVVd;pj zEMXef-msC;+HMB9<4;07_Jc;a>s3pn#x)v=P@Ffp>q!wKm9I|jRQ<2jB~?R^BE(cy zkLhxrZQ!cSy@^a@Gj{29jm(Lxr2=cmU^O=8X$m{1mao3}r)!Al%ip;z*ajNHi0`70 zSaYE^9RkPDJTD)~@4V2f*;J~lH=0Z)Eurx=Dt9 zzyNwgRF5A@azPMZU`;m`6;58QH)kdv-G{|ETjwRJ9Z z<2GXs7eB0MxhRcIPf)G3ezC$N(;Y}L%(FV=X2cx24`h}TLX)=5|IeFI-E|~N>hDyP zyT9JfXd+BWJ!N`;mbTr;wKOaw!HBf)qw>dODb}X^#dwg8_

>#9!qPmuYreh9MxHwg^F=FONLjpLC`>o?oUY( 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 literal 0 HcmV?d00001 diff --git a/cse/CHANGELOG.txt b/cse/CHANGELOG.txt new file mode 100644 index 0000000..45e59f8 --- /dev/null +++ b/cse/CHANGELOG.txt @@ -0,0 +1,102 @@ +ChangeLog: + +v3.00 - Changed license to GPLv3 + +v2.06 - Ensure UI errors are displayed in browser to avoid blank pages + +v2.05 - Added routine to select from multiple download servers for script + updates + +v2.04 - Updated license terms for GDPR compliance + +v2.03 - Fixed issue with missing bootstrap glyphicons + + Added a few more line feeds in HTML output + +v2.02 - Configured UI to fully integrate with cPanel templates without using + iframes + + Configured UI to display full cPanel breadcrumbs + + Configured UI to support cPanel v66 WHM UI changes + +v2.01 - Modified HTML to cater for major change in cPanel v66 + +v2.00 - Modify UI to use cPanel templates for v64+ + + General code improvements + +v1.18 - UI HTML changes + +v1.17 - Redesigned UI based on Bootstrap + + Added upgrade check and button to cse main menu + +v1.16 - Removed use of Cpanel::cPanelFunctions as it is now being withdrawn + + Updated common ConfigServer UI + +v1.15 - UI updates + +v1.14 - Security fix: prevent XSS due to malicious directory/file names + +v1.13 - UI button style modifications + +v1.12 - If /etc/csuibuttondisable exists then the UI buttons will revert for + those that cannot cope with the themed ones + +v1.11 - Updated uninstall information + + UI Changes + +v1.10 - Added support for cPanel v11.38.1+ AppConfig addon registration + + NOTE: In accordance with the new conventions for v11.38.1+ AppConfig + the url to the csf WHM plugin will change from /cgi/addon_cse.cgi to + /cgi/configserver/cse.cgi. This will only happen with cse v1.10+ and + cPanel v11.38.1+. Older version of cse will continue to use the old + URL. This has no particular relevance to users accessing through WHM, + but will affect direct URL access by users or third party + applications + + Improvements to the Virtual Console output + +v1.9 - Updated to use the new cPanel 11.36+ integrated perl binary if exists + +v1.8 - Modified cse to remove cPanel process limits when run + + Modified view file routine to allow for large files and limit memory + requirements + +v1.7 - Updated cse to use the latest cPanel v11 perl modules + + Fixed spurious export errors in the Virtual Console reported in the + cPanel error log + +v1.6 - Modification to upload file procedure after another change by cPanel + + Improved file viewing when clicking on the file name in the browser + window + +v1.5 - Modification to upload file procedure for cPanel v11 + + Improved the display output on the command console + +v1.4 - Modification to work correctly current EDGE + +v1.3 - Renamed to ConfigServer Explorer + + Added a PATH declaration for better compatibility in the Console + + Added error and output redirection for better output display in Console + + Increased CHMOD octal from 3 to 4 characters to include the sticky bit + + First free release + +v1.2 - Added a workaround for a bug in cPanel's form processing library that + prefixes non-IE browser files uploads with "file-" + +v1.1 - Added file download by clicking on file name + +v1.0 - Initial release diff --git a/cse/INSTALL.txt b/cse/INSTALL.txt new file mode 100644 index 0000000..5ebba60 --- /dev/null +++ b/cse/INSTALL.txt @@ -0,0 +1,22 @@ +To install or upgrade cse simply do the following from the root shell via SSH: + +cd /usr/src +rm -fv /usr/src/cse.tgz +wget https://download.configserver.com/cse.tgz +tar -xzf cse.tgz +cd cse +sh install.sh +rm -Rfv /usr/src/cse* + +Then login to WHM and scroll to the bottom of the left hand menu and you should see "ConfigServer Explorer" + + +If you want to uninstall, simply: + +cd /usr/src +rm -fv /usr/src/cse.tgz +wget http://download.configserver.com/cse.tgz +tar -xzf cse.tgz +cd cse +sh uninstall.sh +rm -Rfv /usr/src/cse* diff --git a/cse/cse.cgi b/cse/cse.cgi new file mode 100644 index 0000000..7d7a6f9 --- /dev/null +++ b/cse/cse.cgi @@ -0,0 +1,1515 @@ +#!/usr/bin/perl +#WHMADDON:addonupdates:ConfigServer Explorer +#ACLS:configserver +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +## no critic (RequireUseWarnings, ProhibitExplicitReturnUndef, ProhibitMixedBooleanOperators, RequireBriefOpen) +use strict; +use IPC::Open3; +use Fcntl qw(:DEFAULT :flock); +use File::Find; +use File::Copy; +use CGI::Carp qw(fatalsToBrowser); + +use lib '/usr/local/cpanel'; +require Cpanel::Form; +require Whostmgr::ACLS; +require Cpanel::Template; +require Cpanel::Rlimit; +require Cpanel::Version::Tiny; +############################################################################### +# start main + +our ($myv, $images, $versionfile, $script, %form, $webpath, $demo, $message, + $thisdir, @months, @thisdirs, @thisfiles, $tgid, $tuid, $storepath, + @passrecs, $act, $origpath, $destpath, $dir, @dirs, @files, @splitme, + $extra, $extramessage, $fileno, $wwwpath, @userfiles, $downloadserver); + +%form = Cpanel::Form::parseform(); + +Whostmgr::ACLS::init_acls(); +if (!Whostmgr::ACLS::hasroot()) { + print "Content-type: text/html\r\n\r\n"; + print "You do not have access to access the ConfigServer Explorer.\n"; + exit(); +} + +Cpanel::Rlimit::set_rlimit_to_infinity(); + + +$script = "cse.cgi"; +$images = "cse"; +$versionfile = "/usr/local/cpanel/whostmgr/docroot/cgi/configserver/cse/cseversion.txt"; + +$webpath = '/'; +$demo = 0; + +if ($form{do} eq "view") { + &view; + exit; +} + +my $thisapp = "cse"; +my $reregister; +my $modalstyle; +if ($Cpanel::Version::Tiny::major_version >= 65) { + if (-e "/usr/local/cpanel/whostmgr/docroot/cgi/configserver/${thisapp}/${thisapp}.conf") { + sysopen (my $CONF, "/usr/local/cpanel/whostmgr/docroot/cgi/configserver/${thisapp}/${thisapp}.conf", O_RDWR | O_CREAT); + flock ($CONF, LOCK_EX); + my @confdata = <$CONF>; + chomp @confdata; + for (0..scalar(@confdata)) { + if ($confdata[$_] =~ /^target=mainFrame/) { + $confdata[$_] = "target=_self"; + $reregister = 1; + } + } + if ($reregister) { + seek ($CONF, 0, 0); + truncate ($CONF, 0); + foreach (@confdata) { + print $CONF "$_\n"; + } + &printcmd("/usr/local/cpanel/bin/register_appconfig","/usr/local/cpanel/whostmgr/docroot/cgi/configserver/${thisapp}/${thisapp}.conf"); + $reregister = "

Updated application. The next time you login to WHM this will open within the native WHM main window instead of launching a separate window

\n"; + } + close ($CONF); + } +} + +print "Content-type: text/html\r\n\r\n"; +#if ($Cpanel::Version::Tiny::major_version < 65) {$modalstyle = "style='top:120px'"} + +open (IN, "<", $versionfile) or die $!; +$myv = ; +close (IN); +chomp $myv; + +$downloadserver = &getdownloadserver; + +my $bootstrapcss = ""; +my $jqueryjs = ""; +my $bootstrapjs = ""; + +my $templatehtml; +unless ($form{do} eq "console") { + open SCRIPTOUT, '>', \$templatehtml; + select SCRIPTOUT; + + print < + $jqueryjs + $bootstrapjs +EOF +} else { + print < + + + $bootstrapcss + + $jqueryjs + $bootstrapjs + + +
+EOF +} + +print <

+
+

ConfigServer Explorer - cse v$myv

+EOF +if ($reregister ne "") {print $reregister} + +$message = ""; +my $uploadingfile = 0; +foreach my $key (keys %form) { + if (($form{$key} =~ /\/tmp\/cpanel3upload\./) or ($form{$key} =~ /\/tmp\/cpanel\.TMP/) or ($form{$key} =~ /\/tmp\/Cpanel_Form_file\.upload\./)) {$uploadingfile = 1}; +} + +if ($uploadingfile) {&uploadfile} +elsif ($form{do} eq "") {&browse} +elsif ($form{do} eq "upgrade") {&upgrade} +elsif ($form{quit} == 2) {&browse} +elsif ($form{do} eq "b") {&browse} +elsif ($form{do} eq "p") {&browse} +elsif ($form{do} eq "o") {&browse} +elsif ($form{do} eq "c") {&browse} +elsif ($form{do} eq "m") {&browse} +elsif ($form{do} eq "pw") {&browse} +elsif ($form{do} eq "r") {&browse} +elsif ($form{do} eq "newf") {&browse} +elsif ($form{do} eq "newd") {&browse} +elsif ($form{do} eq "cnewf") {&cnewf} +elsif ($form{do} eq "cnewd") {&cnewd} +elsif ($form{do} eq "ren") {&ren} +elsif ($form{do} eq "del") {&del} +elsif ($form{do} eq "setp") {&setp} +elsif ($form{do} eq "seto") {&seto} +elsif ($form{do} eq "cd") {&cd} +elsif ($form{do} eq "console") {&console} +elsif ($form{do} eq "edit") {&edit} +elsif ($form{do} eq "Cancel") {&browse} +elsif ($form{do} eq "Save") {&save} +elsif ($form{do} eq "copyit") {©it} +elsif ($form{do} eq "moveit") {&moveit} +elsif ($form{do} eq "search") {&search} +else {print "Invalid action"}; + +unless ($form{do} eq "console") { + print "
cse: v$myv
"; + print "

©2006-2019, ConfigServer Services (Jonathan Michaelson)

\n"; +} +print < + \$("#loader").hide(); + \$("#docs-link").hide(); + \$(document).ready(function(){ + \$('[data-tooltip="tooltip"]').tooltip(); + }); + +EOF +unless ($form{do} eq "console") { + close SCRIPTOUT; + select STDOUT; + Cpanel::Template::process_template( + 'whostmgr', + { + "template_file" => "${thisapp}.tmpl", + "${thisapp}_output" => $templatehtml, + "print" => 1, + } + ); +} else { + print "
\n"; + print "\n"; + print "\n"; +} + +exit; +# end main +############################################################################### +# start browse +sub browse { + +my %htmlext; +#foreach my $img (split(/\,/,$wwwext)) {$htmlext{$img} = 1} +my $extra; +if ($form{c}) { + if (-e "$webpath$form{c}") { + $extra = "&c=$form{c}"; + } else { + $form{c} = ""; + } +} +if ($form{m}) { + if (-e "$webpath$form{m}") { + $extra = "&m=$form{m}" + } else { + $form{m} = ""; + } +} + +print "\n"; + +$thisdir = $webpath; +if ($thisdir !~ /\/$/) {$thisdir .= "/"} +$thisdir .= $form{p}; +$thisdir =~ s/\/+/\//g; +@months = ("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"); + +my $errordir = 0; +opendir (DIR, "$thisdir") or $errordir = 1; +while (my $file = readdir(DIR)) { + if (-d "$thisdir/$file") { + if ($file !~ /^\.$|^\.\.$/) {push (@thisdirs, $file)} + } else { + push (@thisfiles, $file); + } + +} +closedir (DIR); + +@thisdirs = sort @thisdirs; +@thisfiles = sort @thisfiles; + +print "
\n"; +print "WARNING! While this utility can be very useful it is also very dangerous indeed. You can easily render your server inoperable and unrecoverable by performing ill advised actions. No warranty or guarantee is provided with the product that protects against system damage.\n\n"; +print "
\n"; + +if ($message) {print "

$message

\n";} +print "
\n"; +print "\n"; +if ($errordir) { + print ""; +} else { + if (@thisdirs > 0) { + print "\n"; + print ""; + print ""; + print ""; + print ""; + print ""; + print ""; + print ""; + print "\n"; + } + foreach my $dir (@thisdirs) { + if ($dir =~/'|"|\||\`/) { + print "\n"; + next; + } + my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,$blksize,$blocks) = stat("$thisdir/$dir"); + if ($size < 1024) { + } + elsif ($size < (1024 * 1024)) { + $size = sprintf("%.1f",($size/1024)); + $size .= "k"; + } + else { + $size = sprintf("%.1f",($size/(1024 * 1024))); + $size .= "M"; + } + $mode = sprintf "%04o", $mode & 07777; + $tgid = getgrgid($gid); + if ($tgid eq "") {$tgid = $gid} + $tuid = getpwuid($uid); + if ($tuid eq "") {$tuid = $uid} + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($mtime); + $year += 1900; + my $time = sprintf "%02d:%02d:%02d", $hour, $min, $sec; + $mday = sprintf "%02d", $mday; + $mtime = "$mday-$months[$mon]-$year $time"; + my $pp = ""; + my $passfile = "$form{p}/$dir"; + $passfile =~ s/\//\_/g; + $passfile =~ s/\\/\_/g; + $passfile =~ s/\:/\_/g; + if (-e "$storepath/$passfile.htpasswd") { + open (PASSFILE, "<", "$storepath/$passfile.htpasswd") or die $!; + @passrecs = ; + close (PASSFILE); + chomp @passrecs; + if (@passrecs > 0) {$pp = "**"} + } + + print ""; + if ($form{do} eq "r" and ($form{f} eq $dir)) { + print "
\n"; + print "
\n"; + print "\n"; + } + elsif (-r "$webpath$form{p}/$dir") { + print "\n"; + } + else { + print "\n"; + } + print "\n"; + print "\n"; + if ($form{do} eq "o" and ($form{f} eq $dir)) { + print "
\n"; + print "
\n"; + print "\n"; + } + else { + print "\n"; + } + if ($form{do} eq "p" and ($form{f} eq $dir)) { + print "
\n"; + print "
\n"; + print "\n"; + } + else { + print "\n"; + } + print "\n"; + print "\n"; + print "\n"; + } + if ($form{do} eq "newd") { + print ""; + print "
\n"; + print "
\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + } + if (($form{do} eq "c") and (-d "$webpath$form{c}")) { + my $newf = (split(/\//,$form{c}))[-1]; + print ""; + print "
\n"; + print "
\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + } + if (($form{do} eq "m") and (-d "$webpath$form{m}")) { + my $newf = (split(/\//,$form{m}))[-1]; + print ""; + print "
\n"; + print "
\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + } + + if (@thisfiles > 0) { + print "\n"; + print ""; + print ""; + print ""; + print ""; + print ""; + print ""; + print ""; + print "\n"; + } + my $class = "tdshade2"; + foreach my $file (@thisfiles) { + if ($file =~/'|"|\||\`/) { + print "\n"; + next; + } + my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,$blksize,$blocks) = stat("$thisdir/$file"); + if ($size < 1024) { + } + elsif ($size < (1024 * 1024)) { + $size = sprintf("%.1f",($size/1024)); + $size .= "k"; + } + else { + $size = sprintf("%.1f",($size/(1024 * 1024))); + $size .= "M"; + } + $mode = sprintf "%03o", $mode & 00777; + $tgid = getgrgid($gid); + if ($tgid eq "") {$tgid = $gid} + $tuid = getpwuid($uid); + if ($tuid eq "") {$tuid = $uid} + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($mtime); + $year += 1900; + my $time = sprintf "%02d:%02d:%02d", $hour, $min, $sec; + $mday = sprintf "%02d", $mday; + $mtime = "$mday-$months[$mon]-$year $time"; + print ""; + if ($form{do} eq "r" and ($form{f} eq $file)) { + print "
\n"; + print "
\n"; + print "\n"; + } + else { + $act = "$script?do=view&p=$form{p}&f=$file$extra\#new"; + print "\n"; + } + print "\n"; + print "\n"; + if ($form{do} eq "o" and ($form{f} eq $file)) { + print "
\n"; + print "
\n"; + print "\n"; + } + else { + print "\n"; + } + if ($form{do} eq "p" and ($form{f} eq $file)) { + print "
\n"; + print "
\n"; + print "\n"; + } + else { + print "\n"; + } + my $ext = (split(/\./,$file))[-1]; + if (-T "$webpath$form{p}/$file") { + my $act = ""; + print "\n"; + } else { + print "\n"; + } + print "\n"; + print "\n"; + } + if ($form{do} eq "newf") { + print ""; + print "
\n"; + print "
\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + } + if (($form{do} eq "c") and (-f "$webpath$form{c}")) { + my $newf = (split(/\//,$form{c}))[-1]; + print ""; + print "
\n"; + print "
\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + } + if (($form{do} eq "m") and (-f "$webpath$form{m}")) { + my $newf = (split(/\//,$form{m}))[-1]; + print ""; + print "
\n"; + print "
\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + } +} +print "
"; +print "[Home]"; +my $path = ""; +my $cnt = 2; +my @path = split(/\//,$form{p}); +foreach my $dir (@path) { + if ($dir ne "" and ($dir ne "/")) { + if ($cnt == @path) { + print "/$dir"; + } else { + print "/$dir"; + } + $path .= "/$dir"; + $cnt++; + } +} +if ($form{c}) {print "    Copy buffer:$form{c} \n"} +if ($form{m}) {print "    Move buffer:$form{m} \n"} +print "
Permission Denied
Directory NameSizeDateUser(uid)/Group(gid)PermsActions
".quotemeta($dir)."Invalid directory name - ignored
"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "$pp$dir$pp$dir$size$mtime"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "$tuid($uid)/$tgid($gid)"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "$mode \n"; + print " \n"; + print " \n"; + print "
"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "     
"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "     
"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "     
 
File NameSizeDateUser(uid)/Group(gid)PermsActions
".quotemeta($file)."Invalid file name - ignored
"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "$file$size$mtime"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "$tuid($uid)/$tgid($gid)"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "$mode$act \n"; + print " \n"; + print " \n"; + print "
"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "     
"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "     
"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "     
\n"; + +print "
All the following actions apply to the current directory
\n"; +print "
\n"; +print "\n"; +print "\n"; +print "\n"; +print "\n"; +print "\n"; +print "\n"; +print "\n"; +print "\n"; +print "\n"; +print "\n\n"; +print "\n"; +print "\n"; +print "\n"; +print "\n"; +print "\n"; +print "\n"; +print "\n"; +print "\n"; +print "\n"; +print "\n"; +print "\n"; +print "\n"; +print "\n"; +print "\n"; +print "\n"; +print "
Search for filenames or directories
"; +print " \n"; +print "
Create New...
Create New DirectoryCreate Empty File
Upload Files...

\n"; +print "
\n"; +print "
\n"; +print "
Mode:
Change Directory...
"; +print "\n"; +print "


\n"; +print "\n"; + +print "
\n"; +print "\n"; +print "\n"; +print "\n"; +print "\n"; +print "\n"; +print "\n"; +print "\n"; +print "
Virtual Console $thisdir
"; +print "\n"; +print "

Command: \n"; +print "

\n"; +print "
Note: You cannot change directory within the console. Use the Change Directory feature above.
\n"; +print "
\n"; +print "
\n"; + +my $retry = 0; +my $retrytime = 300; +print "\n"; +print ""; +if (-e "/usr/local/cpanel/whostmgr/docroot/cgi/csenocheck") { + open (IN, "<", "/usr/local/cpanel/whostmgr/docroot/cgi/csenocheck"); + flock (IN, LOCK_SH); + my $time = ; + close (IN); + chomp $time; + $retry = time - $time; + if ($retry > $retrytime) {unlink ("/usr/local/cpanel/whostmgr/docroot/cgi/csenocheck")} +} +unless (-e "/usr/local/cpanel/whostmgr/docroot/cgi/csenocheck") { + my ($status, $text) = &urlget("https://$downloadserver/cse/cseversion.txt"); + my $actv = $text; + my $up = 0; + + if ($actv ne "") { + if ($actv =~ /^[\d\.]*$/) { + if ($actv > $myv) { + print "\n"; + } else { + print "\n"; + } + $up = 1; + } + } + unless ($up) { + sysopen (OUT, "/usr/local/cpanel/whostmgr/docroot/cgi/csenocheck", O_WRONLY | O_CREAT); + flock (OUT, LOCK_EX); + print OUT time; + close (OUT); + print "\n"; + } +} else { + print "\n"; +} +print "
Upgrade
A new version of cse (v$actv) is available. Upgrading will retain your settings
View ChangeLog
You are running the latest version of cse.
An Upgrade button will appear here if a new version becomes available
Unable to connect to http://www.configserver.com, retry in $retrytime seconds.
An Upgrade button will appear here if new version is detected
Unable to connect to http://www.configserver.com, retry in ".($retrytime - $retry)." seconds.
An Upgrade button will appear here if new version is detected
\n"; +return; +} +# end browse +############################################################################### +# start setp +sub setp { + +if ($demo) { + $message = "This action is disabled in the demonstration"; +} else { + my $status = 0; + chmod (oct("0$form{newp}"),"$webpath$form{p}/$form{f}") or $status = $!; + if ($status) {$message = "Operation Failed - $status"} else {$message = ""} +} +&browse; +return; +} +# end setp +############################################################################### +# start seto +sub seto { + +if ($demo) { + $message = "This action is disabled in the demonstration"; +} else { + my $status = ""; + my ($uid,$gid) = split (/\:/,$form{newo}); + if ($uid !~ /^\d/) {$uid = (getpwnam($uid))[2]} + if ($gid !~ /^\d/) {$gid = (getgrnam($gid))[2]} + if ($uid eq "") {$message .= "No such user
\n"} + if ($gid eq "") {$message .= "No such group
\n"} + + if ($message eq "") { + chown ($uid,$gid,"$webpath$form{p}/$form{f}") or $status = $!; + if ($status) {$message = "Operation Failed - $status"} else {$message = ""} + } +} +&browse; +return; +} +# end seto +############################################################################### +# start ren +sub ren { + +if ($demo) { + $message = "This action is disabled in the demonstration"; +} else { + my $status = 0; + rename ("$webpath$form{p}/$form{f}","$webpath$form{p}/$form{newf}") or $status = $!; + if ($status) {$message = "Operation Failed - $status"} else {$message = ""} +} +&browse; +return; +} +# end ren +############################################################################### +# start moveit +sub moveit { + +if ($demo) { + $form{m} = ""; + $message = "This action is disabled in the demonstration"; +} else { + if ("$webpath$form{m}" eq "$webpath$form{p}/$form{newf}") { + $message = "Move Failed - Cannot overwrite original"; + } + elsif ((-d "$webpath$form{m}") and ("$webpath$form{p}/$form{newf}" =~ /^$webpath$form{m}\//)) { + $message = "Move Failed - Cannot move inside original"; + } + else { + my $status = 0; + rename ("$webpath$form{m}","$webpath$form{p}/$form{newf}") or $status = $!; + if ($status) {$message = "Operation Failed - $status"} else {$message = ""} + } + if ($message eq "") {$form{m} = ""} +} +&browse; +return; +} +# end moveit +############################################################################### +# start copyit +sub copyit { + +if ($demo) { + $form{c} = ""; + $message = "This action is disabled in the demonstration"; +} else { + if ("$webpath$form{c}" eq "$webpath$form{p}/$form{newf}") { + $message = "Copy Failed - Cannot overwrite original"; + } + elsif ((-d "$webpath$form{c}") and ("$webpath$form{p}/$form{newf}" =~ /^$webpath$form{c}\//)) { + $message = "Copy Failed - Cannot copy inside original"; + } + else { + if (-d "$webpath$form{c}") { + use File::Copy; + $origpath = "$webpath$form{c}"; + $destpath = "$webpath$form{p}/$form{newf}"; + find(\&mycopy, $origpath); + } else { + use File::Copy; + copy ("$webpath$form{c}","$webpath$form{p}/$form{newf}") or $message = "Copy Failed - $!"; + if ($message eq "") { + my $mode = sprintf "%04o", (stat("$webpath$form{c}"))[2] & 00777; + chmod (oct($mode),"$webpath$form{p}/$form{newf}") or $message = "Permission Change Failed - $!"; + } + } + } + if ($message eq "") {$form{c} = ""} +} +&browse; +return; +} +# end copyit +############################################################################### +# start mycopy +sub mycopy { + +if ($demo) { + $message = "This action is disabled in the demonstration"; +} else { + my $file = $File::Find::name; + (my $dest = $file) =~ s/^\Q$origpath/$destpath/; + my $status = ""; + if (-d $file) { + my $err = (split(/\//,$dest))[-1]; + mkpath ($dest) or $status = "Copy Failed Making New Dir [$err] - $!
\n"; + } elsif (-f $file) { + my $err = (split(/\//,$file))[-1]; + copy ($file,$dest) or $status = "Copy Failed [$err] - $!
\n"; + } + if ($status eq "") { + my $err = (split(/\//,$file))[-1]; + my $mode = sprintf "%04o", (stat("$file"))[2] & 00777; + chmod (oct($mode),"$dest") or $message .= "Copy Failed Setting Perms [$err] - $!
\n"; + } else { + $message .= $status; + } +} +return; +} +# end mycopy +############################################################################### +# start cnewd +sub cnewd { + +if ($demo) { + $message = "This action is disabled in the demonstration"; +} else { + my $status = 0; + if ($form{newf} ne "") { + mkdir ("$webpath$form{p}/$form{newf}",0777) or $status = $!; + } + if ($status) {$message = "Operation Failed - $status"} else {$message = ""} +} +&browse; +return; +} +# end cnewd +############################################################################### +# start cnewf +sub cnewf { + +if ($demo) { + $message = "This action is disabled in the demonstration"; +} else { + my $status = 0; + if ($form{newf} ne "") { + if (-f ">$webpath$form{p}/$form{newf}") { + $status = "File exists"; + } else { + open (OUT, ">", "$webpath$form{p}/$form{newf}") or $status = $!; + close (OUT); + } + } + if ($status) {$message = "Operation Failed - $status"} else {$message = ""} +} +&browse; +return; +} +# end cnewf +############################################################################### +# start del +sub del { + +if ($demo) { + $message = "This action is disabled in the demonstration"; +} else { + my $status = 0; + if (-d "$webpath$form{p}/$form{f}") { + use File::Path; + rmtree("$webpath$form{p}/$form{f}", 0, 0) or $status = $!; + } else { + unlink ("$webpath$form{p}/$form{f}") or $status = $!; + } + if ($status) {$message = "Operation Failed - $status"} else {$message = ""} +} +&browse; +return; +} +# end del +############################################################################### +# start view +sub view { + if (-e "$webpath$form{p}/$form{f}" ) { + if (-T "$webpath$form{p}/$form{f}") { + print "content-type: text/plain\r\n"; + } else { + print "content-type: application/octet-stream\r\n"; + } + print "content-disposition: attachment; filename=$form{f}\r\n\r\n"; + + open(IN,"<","$webpath$form{p}/$form{f}") or die $!; + while () {print} + close(IN); + }else{ + print "content-type: text/html\r\n\r\n"; + print "File [$webpath$form{p}/$form{f}] not found!"; + } + return; +} +# end view +############################################################################### +# start console +sub console { + my $thisdir = "$webpath$form{p}"; + $thisdir =~ s/\/+/\//g; + + print "

\n";
+	print "root [$thisdir]# $form{cmd}\n";
+	chdir $thisdir;
+
+	local $| = 1;
+	my ($childin, $childout);
+	my $cmdpid = open3($childin, $childout, $childout, $form{cmd});
+	while (my $line = <$childout>) {
+		$line =~ s/\/\>\;/g;
+		print $line;
+	}
+	waitpid ($cmdpid, 0);
+	print "root [$thisdir]# _

\n"; + print ""; + return; +} +# end console +############################################################################### +# start cd +sub cd { + +if (-d $form{directory}) { + $form{p} = $form{directory}; +} else { + $message = "No such directory [$form{directory}]"; +} + +&browse; +return; +} +# end cd +############################################################################### +# start edit +sub edit { + + open (IN, "<", "$webpath$form{p}/$form{f}") or die $!; + my @data = ; + close (IN); + + my $filedata; + foreach my $line (@data) { + $line =~ s/\/>/g; + $filedata .= $line; + } + + my $lf = 0; + if ($filedata =~ /\r/) {$lf = 1} + + print "\n"; + print "
\n"; + print "\n"; + print "\n"; + print "\n"; + print "
"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "
"; + print " \n"; + print "\n"; + print "
\n"; + print "
\n"; + return; +} +# end edit +############################################################################### +# start save +sub save { + +if ($demo) { + $message = "This action is disabled in the demonstration"; +} else { + unless ($form{lf}) {$form{newf} =~ s/\r//g} + my $status = 0; + open (OUT, ">", "$webpath$form{p}/$form{f}") or $status = $!; + print OUT $form{newf}; + close (OUT); + + if ($status) {$message = "Operation Failed - $status"} else {$message = ""} +} +&browse; +return; +} +# end save +############################################################################### +# start search +sub search { + +my $words = $form{words}; +$words =~ s/\s+/ /g; +if (($words eq "") or ($words eq " ")) {&browse; exit;} +my @words = split(/ /,$words); + +if ($form{c}) {$extra = "&c=$form{c}"} +if ($form{m}) {$extra = "&m=$form{m}"} + +undef @dirs; +undef @files; +find(\&countfiles, "$webpath$form{p}"); +@dirs = sort {lc($a) cmp lc($b)} @dirs; +@files = sort {lc($a) cmp lc($b)} @files; +my @dirmatches; +my @filematches; +foreach my $dir (@dirs) { + if (($dir eq $webpath) or ("$dir/" eq $webpath) or ($dir eq "$webpath/")) {next} + my $this = (split(/\//,$dir))[-1]; + my $score = 0; + my $hit = 0; + if ($form{type} eq "match") { + if ($this eq $form{words}) { + $hit++; + $score += 5; + } + elsif ($this =~ /\b$form{words}\b/i) { + $hit++; + $score += 4; + } + elsif ($this =~ /\b$form{words}/i) { + $hit++; + $score += 3; + } + elsif ($this =~ /$form{words}\b/i) { + $hit++; + $score += 2; + } + elsif ($this =~ /$form{words}/i) { + $hit++; + $score += 1; + } + } else { + foreach my $word (@words) { + if ($this eq $word) { + $hit++; + $score += 5; + } + elsif ($this =~ /\b$word\b/i) { + $hit++; + $score += 4; + } + elsif ($this =~ /\b$word/i) { + $hit++; + $score += 3; + } + elsif ($this =~ /$word\b/i) { + $hit++; + $score += 2; + } + elsif ($this =~ /$word/i) { + $hit++; + $score += 1; + } + } + if ($form{type} eq "and") { + if ($hit < @words) {$score = 0} + } + } + if ($score > 0) { + my $score = sprintf "%04d", $score; + push (@dirmatches,"$score,$dir"); + } +} +@dirmatches = sort {$a <=> $b} @dirmatches; +@dirmatches = reverse @dirmatches; +foreach my $file (@files) { + my $this = (split(/\//,$file))[-1]; + my $score = 0; + my $hit = 0; + if ($form{type} eq "match") { + if ($this eq $form{words}) { + $hit++; + $score += 5; + } + elsif ($this =~ /\b$form{words}\b/i) { + $hit++; + $score += 4; + } + elsif ($this =~ /\b$form{words}/i) { + $hit++; + $score += 3; + } + elsif ($this =~ /$form{words}\b/i) { + $hit++; + $score += 2; + } + elsif ($this =~ /$form{words}/i) { + $hit++; + $score += 1; + } + } else { + foreach my $word (@words) { + if ($this eq $word) { + $hit++; + $score += 5; + } + elsif ($this =~ /\b$word\b/i) { + $hit++; + $score += 4; + } + elsif ($this =~ /\b$word/i) { + $hit++; + $score += 3; + } + elsif ($this =~ /$word\b/i) { + $hit++; + $score += 2; + } + elsif ($this =~ /$word/i) { + $hit++; + $score += 1; + } + } + if ($form{type} eq "and") { + if ($hit < @words) {$score = 0} + } + } + if ($score > 0) { + my $score = sprintf "%04d", $score; + push (@filematches,"$score,$file"); + } +} +@filematches = sort {$a <=> $b} @filematches; +@filematches = reverse @filematches; + +print "\n"; +print "\n"; +print "\n"; +print "\n"; + +my @skipath = split(/\//,$webpath); +my $class = "tdshade2"; +if (@dirmatches > 0) { + foreach my $match (@dirmatches) { + my ($score,$dir) = split(/\,/,$match); + my $view = ""; + @splitme = split(/\//,$dir); + for (my $x = @skipath + 1;$x < (@splitme - 1);$x++) { + $view .= "/$splitme[$x]"; + } + $view .= "/$splitme[-1]"; + if ($class eq "tdshade2") {$class = "tdshade1"} else {$class = "tdshade2"} + print "\n"; + } +} else { + print "\n"; +} +print "\n"; +$class = "tdshade2"; +if (@filematches > 0) { + foreach my $match (@filematches) { + my ($score,$file) = split(/\,/,$match); + my $view = ""; + @splitme = split(/\//,$file); + if ((@skipath + 2) > @splitme) { + $view = "[Home]/$splitme[-1]"; + } else { + for (my $x = @skipath + 1;$x < (@splitme - 2);$x++) { + $view .= "/$splitme[$x]"; + } + $view = "[Home]$view/$splitme[-2]/$splitme[-1]"; + } + if ($class eq "tdshade2") {$class = "tdshade1"} else {$class = "tdshade2"} + print "\n"; + } +} else { + print "\n"; +} + +print "
"; +print "[Home]"; +my $path = ""; +my $cnt = 1; +my @path = split(/\//,$form{p}); +foreach my $dir (@path) { + if ($dir ne "" and ($dir ne "/")) { + if ($cnt == @path) { + print "/$dir"; + } else { + print "/$dir"; + } + $path .= "/$dir"; + $cnt++; + } +} +print "
"; +print "Search results for [$form{words}] (".uc($form{type})." words)
Score: $score Directory: [Home]$view
No directory matches found
 
Score: $score File: $view
No file matches found
\n"; +return; +} +# end search +############################################################################### +# start process_form +sub process_form { + +my $buffer = $ENV{'QUERY_STRING'}; +if ($buffer eq "") { + binmode (STDIN); + read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); + if (($buffer =~ /Content-Disposition: form-data/) and ($buffer =~ /^--/)) { + &upload($buffer); + exit; + } +} + +my @pairs = split(/&/, $buffer); +foreach my $pair (@pairs) { + my ($name, $value) = split(/=/, $pair); + $value =~ tr/+/ /; + $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; + $value =~ s/\|//g; + $value =~ s/\`//g; + $value =~ s/\0//g; + $value =~ s/\.\.//g; + $value =~ s/~!/ ~!/g; + $form{$name} = $value; +} + +return; +} +# end process_form +############################################################################### +# start uploadfile +sub uploadfile { + +$form{p} =~ s/\r//g; +$form{p} =~ s/\n//g; +$form{p} = &validate_upload_vars($form{p}); +$form{type} =~ s/\r//g; +$form{type} =~ s/\n//g; +$form{type} = &validate_upload_vars($form{type}); +$form{c} =~ s/\r//g; +$form{c} =~ s/\n//g; +$form{c} = &validate_upload_vars($form{c}); +$form{m} =~ s/\r//g; +$form{m} =~ s/\n//g; +$form{m} = &validate_upload_vars($form{m}); +$form{caller} =~ s/\r//g; +$form{caller} =~ s/\n//g; + +my @filenames; +my @filebodies; +foreach my $key (keys %form) { + if (($form{$key} =~ /\/tmp\/cpanel3upload\./) or ($form{$key} =~ /\/tmp\/cpanel\.TMP/) or ($form{$key} =~ /\/tmp\/Cpanel_Form_file\.upload\./)) { + push (@filenames, $key); + push (@filebodies, $form{$key}); + } +} + +if ($demo) { + $message = "This action is disabled in the demonstration"; +} else { + for (my $x = 0;$x < @filenames ;$x++) { + $filenames[$x] = &validate_upload_vars($filenames[$x]); + $filenames[$x] =~ s/\r//g; + $filenames[$x] =~ s/\n//g; + $filenames[$x] =~ s/^file-//g; + $filenames[$x] = (split (/\\/,$filenames[$x]))[-1]; + $filenames[$x] = (split (/\//,$filenames[$x]))[-1]; + if ($form{type} eq "ascii") {$filebodies[$x] =~ s/\r//g} + if (-e "$webpath$form{p}/$filenames[$x]") { + $extramessage .= "
$filenames[$x] - Already exists, delete the original first"; + $fileno--; + next; + } + my $openok = 1; + &printcmd("mv -f $filebodies[$x] $webpath$form{p}/$filenames[$x]"); + $extramessage .= "
$filenames[$x] - Uploaded"; + } + + $message = "$fileno File(s) Uploaded".$extramessage; +} + +&browse; +return; +} +# end upload +############################################################################### +# start validate_upload_vars +sub validate_upload_vars { + +my $value = shift; +return $value; + +} +# end validate_upload_vars +############################################################################### +# start countfiles +sub countfiles { + +if (-d $File::Find::name) {push (@dirs, $File::Find::name)} else {push (@files, $File::Find::name)} + +return; +} +# end countfiles +############################################################################### +# start wantedfiles +sub wantedfiles { + +unless (-f $File::Find::name) {return} +if ($File::Find::name =~ /\_vti\_/) {return} +if ($File::Find::dir =~ /^$wwwpath/) {$dir = $';} else {return} +if ($dir =~ /^\//) {$dir = $';} +if ($dir ne "") {$dir = $dir."/";} +push (@userfiles,$dir.$_); + +return; +} +# end wantedfiles +############################################################################### +# start upgrade +sub upgrade { + +$| = 1; + +print "
";
+
+if (-e "/usr/src/cse.tgz") {unlink ("/usr/src/cse.tgz") or die $!}
+print "Retrieving new cse package...\n";
+
+my ($status, $text) = &urlget("https://$downloadserver/cse.tgz","/usr/src/cse.tgz");
+if ($status) {print "Oops: $text\n"}
+
+if (! -z "/usr/src/cse.tgz") {
+	print "Unpacking new cse package...\n";
+	print "
";
+	&printcmd("cd /usr/src ; tar -xzf cse.tgz ; cd cse ; sh install.sh 2>&1");
+	print "
"; + print "Tidying up...\n"; + print "
";
+	&printcmd("rm -Rfv /usr/src/cse*");
+	print "
"; + print "...All done.\n"; +} +print "
"; + +open (IN, "<", $versionfile) or die $!; +$myv = ; +close (IN); +chomp $myv; + +print "

\n"; + +return; +} +# end upgrade +############################################################################### + +############################################################################### +# start urlget (v1.3) +# +# Examples: +#my ($status, $text) = &urlget("http://prdownloads.sourceforge.net/clamav/clamav-0.92.tar.gz","/tmp/clam.tgz"); +#if ($status) {print "Oops: $text\n"} +# +#my ($status, $text) = &urlget("http://www.configserver.com/free/msfeversion.txt"); +#if ($status) {print "Oops: $text\n"} else {print "Version: $text\n"} +# +sub urlget { + my $url = shift; + my $file = shift; + my $status = 0; + my $timeout = 1200; + local $SIG{PIPE} = 'IGNORE'; + + use LWP::UserAgent; + my $ua = LWP::UserAgent->new; + $ua->timeout(30); + my $req = HTTP::Request->new(GET => $url); + my $res; + my $text; + + ($status, $text) = eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die "Download timeout after $timeout seconds"}; + alarm($timeout); + if ($file) { + $|=1; + my $expected_length; + my $bytes_received = 0; + my $per = 0; + my $oldper = 0; + open (OUT, ">", "$file\.tmp") or return (1, "Unable to open $file\.tmp: $!"); + binmode (OUT); + print "...0\%\n"; + $res = $ua->request($req, + sub { + my($chunk, $res) = @_; + $bytes_received += length($chunk); + unless (defined $expected_length) {$expected_length = $res->content_length || 0} + if ($expected_length) { + my $per = int(100 * $bytes_received / $expected_length); + if ((int($per / 5) == $per / 5) and ($per != $oldper)) { + print "...$per\%\n"; + $oldper = $per; + } + } else { + print "."; + } + print OUT $chunk; + }); + close (OUT); + print "\n"; + } else { + $res = $ua->request($req); + } + alarm(0); + if ($res->is_success) { + if ($file) { + rename ("$file\.tmp","$file") or return (1, "Unable to rename $file\.tmp to $file: $!"); + return (0, $file); + } else { + return (0, $res->content); + } + } else { + return (1, "Unable to download: ".$res->message); + } + }; + alarm(0); + if ($@) { + return (1, $@); + } + if ($text) { + return ($status,$text); + } else { + return (1, "Download timeout after $timeout seconds"); + } +} +# end urlget +############################################################################### +## start printcmd +sub printcmd { + my @command = @_; + my ($childin, $childout); + my $pid = open3($childin, $childout, $childout, @command); + while (<$childout>) {print $_} + waitpid ($pid, 0); + return; +} +## end printcmd +############################################################################### +## start getdownloadserver +sub getdownloadserver { + my @servers; + my $downloadservers = "/usr/local/cpanel/whostmgr/docroot/cgi/configserver/cse/downloadservers"; + my $chosen; + if (-e $downloadservers) { + open (my $DOWNLOAD, "<", $downloadservers); + flock ($DOWNLOAD, LOCK_SH); + my @data = <$DOWNLOAD>; + close ($DOWNLOAD); + chomp @data; + foreach my $line (@data) { + if ($line =~ /^download/) {push @servers, $line} + } +## foreach my $line (slurp($downloadservers)) { +## $line =~ s/$cleanreg//g; +## if ($line =~ /^download/) {push @servers, $line} +## } + $chosen = $servers[rand @servers]; + } + if ($chosen eq "") {$chosen = "download.configserver.com"} + return $chosen; +} +## end getdownloadserver +############################################################################### + +1; diff --git a/cse/cse.conf b/cse/cse.conf new file mode 100644 index 0000000..dd5b2a5 --- /dev/null +++ b/cse/cse.conf @@ -0,0 +1,27 @@ +# name +name=cse + +# Service that will serve this app +service=whostmgr + +# Physical path: /usr/local/cpanel/3rdparty/Foo.php +# Literal URL path: $server:$port/$cpsession/3rdparty/Foo.php +url=/cgi/configserver/cse.cgi + +# System user to run process as +user=root + +# Required acls +acls=all + +# Display name as show in the service ui +displayname=ConfigServer Explorer + +# Url to show in the service ui (relative to install path for whm this is cgi/) +entryurl=configserver/cse.cgi + +upgradecall=/usr/local/cpanel/whostmgr/docroot/cgi/configserver/cse/upgrade.sh + +icon=cse.png + +target=_self diff --git a/cse/cse.conf.old b/cse/cse.conf.old new file mode 100644 index 0000000..99fa1ff --- /dev/null +++ b/cse/cse.conf.old @@ -0,0 +1,23 @@ +# name +name=cse + +# Service that will serve this app +service=whostmgr + +# Physical path: /usr/local/cpanel/3rdparty/Foo.php +# Literal URL path: $server:$port/$cpsession/3rdparty/Foo.php +url=/cgi/addon_cse.cgi + +# System user to run process as +#user=root + +# Required acls +acls=all + +# Display name as show in the service ui +displayname=ConfigServer Explorer + +# Url to show in the service ui (relative to install path for whm this is cgi/) +#entryurl=addon_cse.cgi + +upgradecall=/usr/local/cpanel/whostmgr/docroot/cgi/configserver/cse/upgrade.sh diff --git a/cse/cse.tmpl b/cse/cse.tmpl new file mode 100644 index 0000000..7214326 --- /dev/null +++ b/cse/cse.tmpl @@ -0,0 +1,29 @@ +[% +USE Whostmgr; +USE JSON; + +WRAPPER 'master_templates/master.tmpl' + header = 'ConfigServer Explorer' + skipsupport = 1 + skipheader = 1 + hide_license_warnings = 1 + theme='bootstrap' + breadcrumbdata = { + previous = [ + { + name = "Home", + url = "/scripts/command?PFILE=main", + }, + { + name = "Plugins", + url = "/scripts/command?PFILE=Plugins", + } + ], + name = 'ConfigServer Explorer', + url = '/cgi/configserver/cse.cgi', + }; +%] + +[% cse_output %] + +[% END %] diff --git a/cse/cse/bootstrap/css/bootstrap.min.css b/cse/cse/bootstrap/css/bootstrap.min.css new file mode 100644 index 0000000..ed3905e --- /dev/null +++ b/cse/cse/bootstrap/css/bootstrap.min.css @@ -0,0 +1,6 @@ +/*! + * Bootstrap v3.3.7 (http://getbootstrap.com) + * Copyright 2011-2016 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,:after,:before{color:#000!important;text-shadow:none!important;background:0 0!important;-webkit-box-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff2) format('woff2'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\002a"}.glyphicon-plus:before{content:"\002b"}.glyphicon-eur:before,.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:focus,a:hover{color:#23527c;text-decoration:underline}a:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.carousel-inner>.item>a>img,.carousel-inner>.item>img,.img-responsive,.thumbnail a>img,.thumbnail>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;max-width:100%;height:auto;padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role=button]{cursor:pointer}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1;color:#777}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}.small,small{font-size:85%}.mark,mark{padding:.2em;background-color:#fcf8e3}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:focus,a.text-primary:hover{color:#286090}.text-success{color:#3c763d}a.text-success:focus,a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:focus,a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:focus,a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:focus,a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:focus,a.bg-primary:hover{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:focus,a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:focus,a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:focus,a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:focus,a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ol,ul{margin-top:0;margin-bottom:10px}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;margin-left:-5px;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-top:0;margin-bottom:20px}dd,dt{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[data-original-title],abbr[title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child{margin-bottom:0}blockquote .small,blockquote footer,blockquote small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote .small:before,blockquote footer:before,blockquote small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eee;border-left:0}.blockquote-reverse .small:before,.blockquote-reverse footer:before,.blockquote-reverse small:before,blockquote.pull-right .small:before,blockquote.pull-right footer:before,blockquote.pull-right small:before{content:''}.blockquote-reverse .small:after,.blockquote-reverse footer:after,.blockquote-reverse small:after,blockquote.pull-right .small:after,blockquote.pull-right footer:after,blockquote.pull-right small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{margin-right:-15px;margin-left:-15px}.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>td,.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>td,.table>thead:first-child>tr:first-child>th{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>tbody>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>thead>tr>th{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #ddd}.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*=col-]{position:static;display:table-column;float:none}table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;float:none}.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>thead>tr>td.active,.table>thead>tr>th.active{background-color:#f5f5f5}.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover{background-color:#e8e8e8}.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{background-color:#dff0d8}.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6}.table>tbody>tr.info>td,.table>tbody>tr.info>th,.table>tbody>tr>td.info,.table>tbody>tr>th.info,.table>tfoot>tr.info>td,.table>tfoot>tr.info>th,.table>tfoot>tr>td.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>thead>tr.info>th,.table>thead>tr>td.info,.table>thead>tr>th.info{background-color:#d9edf7}.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover{background-color:#c4e3f3}.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fcf8e3}.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc}.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#f2dede}.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc}.table-responsive{min-height:.01%;overflow-x:auto}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=checkbox],input[type=radio]{margin:4px 0 0;margin-top:1px\9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[type=checkbox]:focus,input[type=radio]:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control::-ms-expand{background-color:transparent;border:0}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}input[type=search]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type=date].form-control,input[type=time].form-control,input[type=datetime-local].form-control,input[type=month].form-control{line-height:34px}.input-group-sm input[type=date],.input-group-sm input[type=time],.input-group-sm input[type=datetime-local],.input-group-sm input[type=month],input[type=date].input-sm,input[type=time].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm{line-height:30px}.input-group-lg input[type=date],.input-group-lg input[type=time],.input-group-lg input[type=datetime-local],.input-group-lg input[type=month],input[type=date].input-lg,input[type=time].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg{line-height:46px}}.form-group{margin-bottom:15px}.checkbox,.radio{position:relative;display:block;margin-top:10px;margin-bottom:10px}.checkbox label,.radio label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{position:absolute;margin-top:4px\9;margin-left:-20px}.checkbox+.checkbox,.radio+.radio{margin-top:-5px}.checkbox-inline,.radio-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px}fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox].disabled,input[type=checkbox][disabled],input[type=radio].disabled,input[type=radio][disabled]{cursor:not-allowed}.checkbox-inline.disabled,.radio-inline.disabled,fieldset[disabled] .checkbox-inline,fieldset[disabled] .radio-inline{cursor:not-allowed}.checkbox.disabled label,.radio.disabled label,fieldset[disabled] .checkbox label,fieldset[disabled] .radio label{cursor:not-allowed}.form-control-static{min-height:34px;padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}select[multiple].input-sm,textarea.input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm select[multiple].form-control,.form-group-sm textarea.form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}select[multiple].input-lg,textarea.input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:46px;line-height:46px}.form-group-lg select[multiple].form-control,.form-group-lg textarea.form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.form-group-lg .form-control+.form-control-feedback,.input-group-lg+.form-control-feedback,.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.form-group-sm .form-control+.form-control-feedback,.input-group-sm+.form-control-feedback,.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .checkbox,.has-success .checkbox-inline,.has-success .control-label,.has-success .help-block,.has-success .radio,.has-success .radio-inline,.has-success.checkbox label,.has-success.checkbox-inline label,.has-success.radio label,.has-success.radio-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .checkbox,.has-warning .checkbox-inline,.has-warning .control-label,.has-warning .help-block,.has-warning .radio,.has-warning .radio-inline,.has-warning.checkbox label,.has-warning.checkbox-inline label,.has-warning.radio label,.has-warning.radio-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .checkbox,.has-error .checkbox-inline,.has-error .control-label,.has-error .help-block,.has-error .radio,.has-error .radio-inline,.has-error.checkbox label,.has-error.checkbox-inline label,.has-error.radio label,.has-error.radio-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .form-control,.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .checkbox,.form-inline .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .checkbox label,.form-inline .radio label{padding-left:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .checkbox,.form-horizontal .radio{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:11px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:none;border:1px solid transparent;border-radius:4px}.btn.active.focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn:active:focus,.btn:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.focus,.btn:focus,.btn:hover{color:#333;text-decoration:none}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none;opacity:.65}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default.focus,.btn-default:focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.btn-default:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active.focus,.btn-default.active:focus,.btn-default.active:hover,.btn-default:active.focus,.btn-default:active:focus,.btn-default:active:hover,.open>.dropdown-toggle.btn-default.focus,.open>.dropdown-toggle.btn-default:focus,.open>.dropdown-toggle.btn-default:hover{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled.focus,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled].focus,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#286090;border-color:#122b40}.btn-primary:hover{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active.focus,.btn-primary.active:focus,.btn-primary.active:hover,.btn-primary:active.focus,.btn-primary:active:focus,.btn-primary:active:hover,.open>.dropdown-toggle.btn-primary.focus,.open>.dropdown-toggle.btn-primary:focus,.open>.dropdown-toggle.btn-primary:hover{color:#fff;background-color:#204d74;border-color:#122b40}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled.focus,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled].focus,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#449d44;border-color:#255625}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active.focus,.btn-success.active:focus,.btn-success.active:hover,.btn-success:active.focus,.btn-success:active:focus,.btn-success:active:hover,.open>.dropdown-toggle.btn-success.focus,.open>.dropdown-toggle.btn-success:focus,.open>.dropdown-toggle.btn-success:hover{color:#fff;background-color:#398439;border-color:#255625}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled.focus,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled].focus,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active.focus,.btn-info.active:focus,.btn-info.active:hover,.btn-info:active.focus,.btn-info:active:focus,.btn-info:active:hover,.open>.dropdown-toggle.btn-info.focus,.open>.dropdown-toggle.btn-info:focus,.open>.dropdown-toggle.btn-info:hover{color:#fff;background-color:#269abc;border-color:#1b6d85}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled.focus,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled].focus,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning.focus,.btn-warning:focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active.focus,.btn-warning.active:focus,.btn-warning.active:hover,.btn-warning:active.focus,.btn-warning:active:focus,.btn-warning:active:hover,.open>.dropdown-toggle.btn-warning.focus,.open>.dropdown-toggle.btn-warning:focus,.open>.dropdown-toggle.btn-warning:hover{color:#fff;background-color:#d58512;border-color:#985f0d}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled.focus,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled].focus,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c9302c;border-color:#761c19}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active.focus,.btn-danger.active:focus,.btn-danger.active:hover,.btn-danger:active.focus,.btn-danger:active:focus,.btn-danger:active:hover,.open>.dropdown-toggle.btn-danger.focus,.open>.dropdown-toggle.btn-danger:focus,.open>.dropdown-toggle.btn-danger:hover{color:#fff;background-color:#ac2925;border-color:#761c19}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled.focus,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled].focus,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#337ab7;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#777;text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-group-sm>.btn,.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-xs>.btn,.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:height,visibility;-o-transition-property:height,visibility;transition-property:height,visibility}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid\9;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown,.dropup{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;background-color:#337ab7;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#777}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px dashed;border-bottom:4px solid\9}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;float:left}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-left-radius:0;border-top-right-radius:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group .form-control:focus{z-index:3}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn,textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn,textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group .form-control,.input-group-addon,.input-group-btn{display:table-cell}.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn-group:not(:last-child)>.btn,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:first-child>.btn-group:not(:first-child)>.btn,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:focus,.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:focus,.nav>li.disabled>a:hover{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:focus,.nav .open>a:hover{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:focus,.nav-tabs>li.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:focus,.nav-pills>li.active>a:hover{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;-webkit-overflow-scrolling:touch;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1)}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:200px}}.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;height:50px;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1)}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .form-control,.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .checkbox label,.navbar-form .radio label{padding-left:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:focus,.navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:focus,.navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:focus,.navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:focus,.navbar-default .navbar-nav>.open>a:hover{color:#555;background-color:#e7e7e7}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:focus,.navbar-default .btn-link:hover{color:#333}.navbar-default .btn-link[disabled]:focus,.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:focus,fieldset[disabled] .navbar-default .btn-link:hover{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:focus,.navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:focus,.navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:focus,.navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:focus,.navbar-inverse .navbar-toggle:hover{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{color:#fff;background-color:#080808}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:focus,.navbar-inverse .btn-link:hover{color:#fff}.navbar-inverse .btn-link[disabled]:focus,.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:focus,fieldset[disabled] .navbar-inverse .btn-link:hover{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.42857143;color:#337ab7;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:2;color:#23527c;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:3;color:#fff;cursor:default;background-color:#337ab7;border-color:#337ab7}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:focus,.pager li>a:hover{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:focus,a.label:hover{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:focus,.label-default[href]:hover{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:focus,.label-primary[href]:hover{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:focus,.label-success[href]:hover{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:focus,.label-info[href]:hover{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:focus,.label-warning[href]:hover{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:focus,.label-danger[href]:hover{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:middle;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-group-xs>.btn .badge,.btn-xs .badge{top:0;padding:1px 5px}a.badge:focus,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron .h1,.jumbotron h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{padding-right:15px;padding-left:15px;border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-right:60px;padding-left:60px}.jumbotron .h1,.jumbotron h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail a>img,.thumbnail>img{margin-right:auto;margin-left:auto}a.thumbnail.active,a.thumbnail:focus,a.thumbnail:hover{border-color:#337ab7}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-bar-striped,.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress-bar.active,.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{overflow:hidden;zoom:1}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-body,.media-left,.media-right{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}a.list-group-item,button.list-group-item{color:#555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333}a.list-group-item:focus,a.list-group-item:hover,button.list-group-item:focus,button.list-group-item:hover{color:#555;text-decoration:none;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item.disabled,.list-group-item.disabled:focus,.list-group-item.disabled:hover{color:#777;cursor:not-allowed;background-color:#eee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:focus .list-group-item-text,.list-group-item.active:hover .list-group-item-text{color:#c7ddef}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:focus,a.list-group-item-success:hover,button.list-group-item-success:focus,button.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:focus,a.list-group-item-success.active:hover,button.list-group-item-success.active,button.list-group-item-success.active:focus,button.list-group-item-success.active:hover{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:focus,a.list-group-item-info:hover,button.list-group-item-info:focus,button.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:focus,a.list-group-item-info.active:hover,button.list-group-item-info.active,button.list-group-item-info.active:focus,button.list-group-item-info.active:hover{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:focus,a.list-group-item-warning:hover,button.list-group-item-warning:focus,button.list-group-item-warning:hover{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:focus,a.list-group-item-warning.active:hover,button.list-group-item-warning.active,button.list-group-item-warning.active:focus,button.list-group-item-warning.active:hover{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:focus,a.list-group-item-danger:hover,button.list-group-item-danger:focus,button.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover,button.list-group-item-danger.active,button.list-group-item-danger.active:focus,button.list-group-item-danger.active:hover{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>.small,.panel-title>.small>a,.panel-title>a,.panel-title>small,.panel-title>small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-left-radius:0;border-top-right-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.panel-collapse>.table,.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.panel-collapse>.table caption,.panel>.table caption,.panel>.table-responsive>.table caption{padding-right:15px;padding-left:15px}.panel>.table-responsive:first-child>.table:first-child,.panel>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table:first-child>thead:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table-responsive:last-child>.table:last-child,.panel>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child td,.panel>.table>tbody:first-child>tr:first-child th{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.list-group,.panel-group .panel-heading+.panel-collapse>.panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{-webkit-appearance:none;padding:0;cursor:pointer;background:0 0;border:0}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out;-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%)}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5)}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:12px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;filter:alpha(opacity=0);opacity:0;line-break:auto}.tooltip.in{filter:alpha(opacity=90);opacity:.9}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{right:5px;bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);line-break:auto}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{content:"";border-width:10px}.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25)}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>a>img,.carousel-inner>.item>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.active.right,.carousel-inner>.item.next{left:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.carousel-inner>.item.active.left,.carousel-inner>.item.prev{left:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.carousel-inner>.item.active,.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right{left:0;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);background-color:rgba(0,0,0,0);filter:alpha(opacity=50);opacity:.5}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);background-repeat:repeat-x}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);background-repeat:repeat-x}.carousel-control:focus,.carousel-control:hover{color:#fff;text-decoration:none;filter:alpha(opacity=90);outline:0;opacity:.9}.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block;margin-top:-10px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{left:50%;margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{right:50%;margin-right:-10px}.carousel-control .icon-next,.carousel-control .icon-prev{width:20px;height:20px;font-family:serif;line-height:1}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000\9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-10px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-10px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.btn-group-vertical>.btn-group:after,.btn-group-vertical>.btn-group:before,.btn-toolbar:after,.btn-toolbar:before,.clearfix:after,.clearfix:before,.container-fluid:after,.container-fluid:before,.container:after,.container:before,.dl-horizontal dd:after,.dl-horizontal dd:before,.form-horizontal .form-group:after,.form-horizontal .form-group:before,.modal-footer:after,.modal-footer:before,.modal-header:after,.modal-header:before,.nav:after,.nav:before,.navbar-collapse:after,.navbar-collapse:before,.navbar-header:after,.navbar-header:before,.navbar:after,.navbar:before,.pager:after,.pager:before,.panel-body:after,.panel-body:before,.row:after,.row:before{display:table;content:" "}.btn-group-vertical>.btn-group:after,.btn-toolbar:after,.clearfix:after,.container-fluid:after,.container:after,.dl-horizontal dd:after,.form-horizontal .form-group:after,.modal-footer:after,.modal-header:after,.nav:after,.navbar-collapse:after,.navbar-header:after,.navbar:after,.pager:after,.panel-body:after,.row:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-lg,.visible-md,.visible-sm,.visible-xs{display:none!important}.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table!important}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table!important}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table!important}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table!important}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table!important}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}} +/*# sourceMappingURL=bootstrap.min.css.map */ \ No newline at end of file diff --git a/cse/cse/bootstrap/fonts/glyphicons-halflings-regular.eot b/cse/cse/bootstrap/fonts/glyphicons-halflings-regular.eot new file mode 100644 index 0000000000000000000000000000000000000000..b93a4953fff68df523aa7656497ee339d6026d64 GIT binary patch literal 20127 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cse/cse/bootstrap/fonts/glyphicons-halflings-regular.ttf b/cse/cse/bootstrap/fonts/glyphicons-halflings-regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..1413fc609ab6f21774de0cb7e01360095584f65b GIT binary patch literal 45404 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 G`u_lkUM?>H literal 0 HcmV?d00001 diff --git a/cse/cse/bootstrap/fonts/glyphicons-halflings-regular.woff2 b/cse/cse/bootstrap/fonts/glyphicons-halflings-regular.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..64539b54c3751a6d9adb44c8e3a45ba5a73b77f0 GIT binary patch literal 18028 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 literal 0 HcmV?d00001 diff --git a/cse/cse/bootstrap/js/bootstrap.min.js b/cse/cse/bootstrap/js/bootstrap.min.js new file mode 100644 index 0000000..9bcd2fc --- /dev/null +++ b/cse/cse/bootstrap/js/bootstrap.min.js @@ -0,0 +1,7 @@ +/*! + * Bootstrap v3.3.7 (http://getbootstrap.com) + * Copyright 2011-2016 Twitter, Inc. + * Licensed under the MIT license + */ +if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1||b[0]>3)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){if(a(b.target).is(this))return b.handleObj.handler.apply(this,arguments)}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.7",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a("#"===f?[]:f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.7",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c).prop(c,!0)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c).prop(c,!1))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")?(c.prop("checked")&&(a=!1),b.find(".active").removeClass("active"),this.$element.addClass("active")):"checkbox"==c.prop("type")&&(c.prop("checked")!==this.$element.hasClass("active")&&(a=!1),this.$element.toggleClass("active")),c.prop("checked",this.$element.hasClass("active")),a&&c.trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active")),this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target).closest(".btn");b.call(d,"toggle"),a(c.target).is('input[type="radio"], input[type="checkbox"]')||(c.preventDefault(),d.is("input,button")?d.trigger("focus"):d.find("input:visible,button:visible").first().trigger("focus"))}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.7",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c=this.getItemIndex(b),d="prev"==a&&0===c||"next"==a&&c==this.$items.length-1;if(d&&!this.options.wrap)return b;var e="prev"==a?-1:1,f=(c+e)%this.$items.length;return this.$items.eq(f)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(".item.active"));if(!(a>this.$items.length-1||a<0))return this.sliding?this.$element.one("slid.bs.carousel",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?"next":"prev",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){if(!this.sliding)return this.slide("next")},c.prototype.prev=function(){if(!this.sliding)return this.slide("prev")},c.prototype.slide=function(b,d){var e=this.$element.find(".item.active"),f=d||this.getItemForDirection(b,e),g=this.interval,h="next"==b?"left":"right",i=this;if(f.hasClass("active"))return this.sliding=!1;var j=f[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:h});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(f)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:h});return a.support.transition&&this.$element.hasClass("slide")?(f.addClass(b),f[0].offsetWidth,e.addClass(h),f.addClass(h),e.one("bsTransitionEnd",function(){f.removeClass([b,h].join(" ")).addClass("active"),e.removeClass(["active",h].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trigger(m)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}};a(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){var c,d=b.attr("data-target")||(c=b.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data("bs.collapse"),f=a.extend({},d.DEFAULTS,c.data(),"object"==typeof b&&b);!e&&f.toggle&&/show|hide/.test(b)&&(f.toggle=!1),e||c.data("bs.collapse",e=new d(this,f)),"string"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a('[data-toggle="collapse"][href="#'+b.id+'"],[data-toggle="collapse"][data-target="#'+b.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION="3.3.7",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0},d.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},d.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b,e=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(e&&e.length&&(b=e.data("bs.collapse"),b&&b.transitioning))){var f=a.Event("show.bs.collapse");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,"hide"),b||e.data("bs.collapse",null));var g=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[g](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var h=function(){this.$element.removeClass("collapsing").addClass("collapse in")[g](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return h.call(this);var i=a.camelCase(["scroll",g].join("-"));this.$element.one("bsTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var e=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass("in");a.attr("aria-expanded",c),b.toggleClass("collapsed",!c).attr("aria-expanded",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(d){var e=a(this);e.attr("data-target")||d.preventDefault();var f=b(e),g=f.data("bs.collapse"),h=g?"toggle":e.data();c.call(f,h)})}(jQuery),+function(a){"use strict";function b(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function c(c){c&&3===c.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=b(d),f={relatedTarget:this};e.hasClass("open")&&(c&&"click"==c.type&&/input|textarea/i.test(c.target.tagName)&&a.contains(e[0],c.target)||(e.trigger(c=a.Event("hide.bs.dropdown",f)),c.isDefaultPrevented()||(d.attr("aria-expanded","false"),e.removeClass("open").trigger(a.Event("hidden.bs.dropdown",f)))))}))}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.3.7",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=b(e),g=f.hasClass("open");if(c(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(document.createElement("div")).addClass("dropdown-backdrop").insertAfter(a(this)).on("click",c);var h={relatedTarget:this};if(f.trigger(d=a.Event("show.bs.dropdown",h)),d.isDefaultPrevented())return;e.trigger("focus").attr("aria-expanded","true"),f.toggleClass("open").trigger(a.Event("shown.bs.dropdown",h))}return!1}},g.prototype.keydown=function(c){if(/(38|40|27|32)/.test(c.which)&&!/input|textarea/i.test(c.target.tagName)){var d=a(this);if(c.preventDefault(),c.stopPropagation(),!d.is(".disabled, :disabled")){var e=b(d),g=e.hasClass("open");if(!g&&27!=c.which||g&&27==c.which)return 27==c.which&&e.find(f).trigger("focus"),d.trigger("click");var h=" li:not(.disabled):visible a",i=e.find(".dropdown-menu"+h);if(i.length){var j=i.index(c.target);38==c.which&&j>0&&j--,40==c.which&&jdocument.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&a?this.scrollbarWidth:"",paddingRight:this.bodyIsOverflowing&&!a?this.scrollbarWidth:""})},c.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:"",paddingRight:""})},c.prototype.checkScrollbar=function(){var a=window.innerWidth;if(!a){var b=document.documentElement.getBoundingClientRect();a=b.right-Math.abs(b.left)}this.bodyIsOverflowing=document.body.clientWidth
',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){if(this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(a.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusin"==b.type?"focus":"hover"]=!0),c.tip().hasClass("in")||"in"==c.hoverState?void(c.hoverState="in"):(clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show())},c.prototype.isInStateTrue=function(){for(var a in this.inState)if(this.inState[a])return!0;return!1},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);if(c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusout"==b.type?"focus":"hover"]=!1),!c.isInStateTrue())return clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide()},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var d=a.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!d)return;var e=this,f=this.tip(),g=this.getUID(this.type);this.setContent(),f.attr("id",g),this.$element.attr("aria-describedby",g),this.options.animation&&f.addClass("fade");var h="function"==typeof this.options.placement?this.options.placement.call(this,f[0],this.$element[0]):this.options.placement,i=/\s?auto?\s?/i,j=i.test(h);j&&(h=h.replace(i,"")||"top"),f.detach().css({top:0,left:0,display:"block"}).addClass(h).data("bs."+this.type,this),this.options.container?f.appendTo(this.options.container):f.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.getPosition(this.$viewport);h="bottom"==h&&k.bottom+m>o.bottom?"top":"top"==h&&k.top-mo.width?"left":"left"==h&&k.left-lg.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;jg.right&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){if(!this.$tip&&(this.$tip=a(this.options.template),1!=this.$tip.length))throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!");return this.$tip},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),b?(c.inState.click=!c.inState.click,c.isInStateTrue()?c.enter(c):c.leave(c)):c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){var a=this;clearTimeout(this.timeout),this.hide(function(){a.$element.off("."+a.type).removeData("bs."+a.type),a.$tip&&a.$tip.detach(),a.$tip=null,a.$arrow=null,a.$viewport=null,a.$element=null})};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;!e&&/destroy|hide/.test(b)||(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.3.7",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:''}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){this.$body=a(document.body),this.$scrollElement=a(a(c).is(document.body)?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",a.proxy(this.process,this)),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.3.7",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b=this,c="offset",d=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),a.isWindow(this.$scrollElement[0])||(c="position",d=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var b=a(this),e=b.data("target")||b.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[c]().top+d,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b=e[a]&&(void 0===e[a+1]||b .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),b.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),h?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu").length&&b.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),e&&e()}var g=d.find("> .active"),h=e&&a.support.transition&&(g.length&&g.hasClass("fade")||!!d.find("> .fade").length);g.length&&h?g.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),"show")};a(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.3.7",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&"top"==this.affixed)return e=a-d&&"bottom"},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=Math.max(a(document).height(),a(document.body).height());"object"!=typeof d&&(f=e=d),"function"==typeof e&&(e=d.top(this.$element)),"function"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css("top","");var i="affix"+(h?"-"+h:""),j=a.Event(i+".bs.affix");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin="bottom"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace("affix","affixed")+".bs.affix")}"bottom"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery); \ No newline at end of file diff --git a/cse/cse/configserver.css b/cse/cse/configserver.css new file mode 100644 index 0000000..ec8984a --- /dev/null +++ b/cse/cse/configserver.css @@ -0,0 +1,128 @@ +.icon-configserver { + color: #990000; +} +.btn-default:active, +.btn-default:visited, +.btn-default:focus, +.btn-default { + background:#FFFFFF; + border-radius:3px; + border:1px solid #A6C150; + color:#990000 !important; +} +.btn-default:hover { + border:1px solid #A6C150; + background: #F5F5F5; +} +input[type=text], select { + -webkit-transition: all 0.30s ease-in-out; + -moz-transition: all 0.30s ease-in-out; + -ms-transition: all 0.30s ease-in-out; + -o-transition: all 0.30s ease-in-out; + transition: all 0.30s ease-in-out; + border-radius:3px; + outline: none; + padding: 3px 0px 3px 3px; + margin: 5px 1px 3px 0px; + border: 1px solid #990000; +} +input[type=text]:focus, select:focus { + box-shadow: 0 0 5px #CC0000; + padding: 3px 0px 3px 3px; + margin: 5px 1px 3px 0px; + border: 1px solid #990000; +} +.td-btn { + width: 200px; +} +.td-text { +} +th { + background: #F4F4EA; +} +.table tbody>tr>td { + vertical-align: middle; +} +.panel-default > .panel-heading-cxs { + font-weight: bold; + background: #F4F4EA; +} +.panel-default > .panel-footer-cxs { + font-weight: bold; + background: #F4F4EA; +} +#loader { + position: absolute; + left: 50%; + top: 50%; + z-index: 1; + margin: -75px 0 0 -75px; + border: 16px solid #F4F4EA; + border-radius: 50%; + border-top: 16px solid #990000; + border-bottom: 16px solid #990000; + width: 120px; + height: 120px; + -webkit-animation: spin 2s linear infinite; + animation: spin 2s linear infinite; +} +@-webkit-keyframes spin { + 0% { -webkit-transform: rotate(0deg); } + 100% { -webkit-transform: rotate(360deg); } +} +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} +.bs-callout { + padding: 20px; + margin: 20px 0; + border: 1px solid #eee; + border-left-width: 5px; + border-radius: 3px; +} +.bs-callout h4 { + margin-top: 0; + margin-bottom: 5px; +} +.bs-callout p:last-child { + margin-bottom: 0; +} +.bs-callout code { + border-radius: 3px; +} +.bs-callout+.bs-callout { + margin-top: -5px; +} +.bs-callout-success { + border-left-color: #5cb85c; + background-color: #edf7ed; +} +.bs-callout-success h4 { + color: #5cb85c; +}.bs-callout-info { + border-left-color: #5bc0de; + background-color: #eaf7fb; +} +.bs-callout-info h4 { + color: #5bc0de; +} +.bs-callout-warning { + border-left-color: #f0ad4e; + background-color: #fdf4e8; +} +.bs-callout-warning h4 { + color: #f0ad4e; +} +.bs-callout-danger { + border-left-color: #d9534f; + background-color: #faebea; +} +.bs-callout-danger h4 { + color: #d9534f; +} +.label-pill { + padding-right: .6em; + padding-left: .6em; + border-radius: 10rem; +} \ No newline at end of file diff --git a/cse/cse/cse.png b/cse/cse/cse.png new file mode 100644 index 0000000000000000000000000000000000000000..8aa1f0339989f6a7c986631812944b378823c38a GIT binary patch literal 2170 zcmV-=2!;2FP)UnoU}k=EAUS96@7sIrwb$92 z_WJYs^WS`yY1*gnFVX(`z@mj;CFlcvy;Skpn)W3%{=D6(g&!@|!jC;#czO;V$AIS~ zKgKY{OcHHrx{>GT^QDN-)3kkSE!y9`E-n0PW~8$z10kxQN#>zj3r{c)h;d?!7|jrj z5W~d%bip$++d~6|KGC-+@r4Om^+y)%pSvXf7mw)dJ~J#KF(YnqmEXyG?hzp-NDL8! zByxc0C;AAqeTVpg!T(Rm_-(qP??O$hUX*xWg4XZ}H84b-{OpMq6Jl}kP(|y)(+z|h zh*wQKArpOcT~8WFOZ|ckyt_pEt)1fW+0w|U$`Kx!h2f0onb1v<*bot9hL}MTI1qGbWto$Bd*;M9?gP!-xM>+Jak8|2YpRs2*!yq1-U-3X0DkvfKce9YZucU zhb{%&-@#lb0hmb$38aZEgHdf|uB2+=%f$CY3(-t8Ika#ify5CoW1y1_NMR6iK1B-*LI8^nA%ZE!PKi7|f&8w3|7DIJRnn?l#IY$GwXgwM`;4&QQAIce>M4+DWG)dGfkV*ioLK|)vVi~_Xl4UFW(^<% z^u-vMQOqeEv1{QE>7I24tmS&Y%5J=XZ^kjuV#WY607eSww3!XeR?HnBahvF#9o7h6 zD{Q3S_Sn0EHdm1 z{W4~GQyW$4BU#Xma5)j;BCelzUs*Qv@JrHl89p5E=;LCFFo2N4OVgqa)N>rF2KsoR z1zG$Ei^n^ztV|zpc_9r9vH@9n$`snk1_B(S4Q!x+4O}&A0HQHEE!+?q@8=^Db@Uaxxc`D;EHg<%-5JP0Qaq&5wN4GGZ5tZXE-CeGL@%yA>{?;u50emhuC^H zP|pUip`A@OVF0HI7#YOl+2rUoAZOv8Qk_B+>Y@EgrrE=pMrIq739*a!3LmS~DF(0} zaPMg|25=ODhA$}wWEL7^6G7!D5h)UB5T_TYJXJPuSq&o{2BQzLa-G2l!U!{8ZN>l| zZsr$}Gi>0FD`H}RjYu%^m8dvrL)y#iA$AkHY~ttyv(T<&p3A)Z>S4+T&L@jmz|5aC zV?Z7>VKh#&f!nT#iMyO#Y4I~h0Nl6J=PFG@H)-wBQtL1lufO>#?K8892>f>N^uiBQ;Au-kh zUPqw?nxG9D6I9_z7K`R}yA#X21&*>}-_r6TUru?kzvw+%;vb0J+L*@YGO!TlGJr)5 z4bW2V^A|xIG?sbu9o`IgBD8BISy`5nJg=jCWvS=Qg2LP~e~GWW*td!v`V;vZX)y|G z{L|^h@?sq%&IB5u1)9qIr9NncR%nKHWd`zT2K-_M$nD$N*#|2;p36j_A~Umtu00i* zo?hY(F+hZfVPcG!px>wH`iPh&o)AxopO~lo-L!s>xOak|9p<(Mxb0rim)>Up8lWXI z1AZ|BZk~Y|YrrMefIm0SSzcJ=p(#U16%Z?lRm59F1vU5%T~`xph;_tzVgs?6*g{ki zTbWA!ZZqGro}XExw;|f9;I>zBUj=&Kq`{xN!kL$~+;|Pl^|6u5RGTfqmEy2?oG$Bf zw>v4vlbJ#$)AHZQb`|C1x_vA1JpMdyR*AP@d8xM`yDYyjr>vkjx76>~!Qc1}zu_L- wi)ZjG+CW=q6K$gp^o2fc>IlF7{7*ms0{Q6lmup4}wg3PC07*qoM6N<$f|lIvmH+?% literal 0 HcmV?d00001 diff --git a/cse/cse/cse.svg b/cse/cse/cse.svg new file mode 100644 index 0000000..07b7465 --- /dev/null +++ b/cse/cse/cse.svg @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cse/cse/jquery.min.js b/cse/cse/jquery.min.js new file mode 100644 index 0000000..e836475 --- /dev/null +++ b/cse/cse/jquery.min.js @@ -0,0 +1,5 @@ +/*! jQuery v1.12.4 | (c) jQuery Foundation | jquery.org/license */ +!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=a.document,e=c.slice,f=c.concat,g=c.push,h=c.indexOf,i={},j=i.toString,k=i.hasOwnProperty,l={},m="1.12.4",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return e.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:e.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a){return n.each(this,a)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(e.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor()},push:g,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(n.isPlainObject(c)||(b=n.isArray(c)))?(b?(b=!1,f=a&&n.isArray(a)?a:[]):f=a&&n.isPlainObject(a)?a:{},g[d]=n.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray||function(a){return"array"===n.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){var b=a&&a.toString();return!n.isArray(a)&&b-parseFloat(b)+1>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==n.type(a)||a.nodeType||n.isWindow(a))return!1;try{if(a.constructor&&!k.call(a,"constructor")&&!k.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(!l.ownFirst)for(b in a)return k.call(a,b);for(b in a);return void 0===b||k.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?i[j.call(a)]||"object":typeof a},globalEval:function(b){b&&n.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b){var c,d=0;if(s(a)){for(c=a.length;c>d;d++)if(b.call(a[d],d,a[d])===!1)break}else for(d in a)if(b.call(a[d],d,a[d])===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):g.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(h)return h.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,e,g=0,h=[];if(s(a))for(d=a.length;d>g;g++)e=b(a[g],g,c),null!=e&&h.push(e);else for(g in a)e=b(a[g],g,c),null!=e&&h.push(e);return f.apply([],h)},guid:1,proxy:function(a,b){var c,d,f;return"string"==typeof b&&(f=a[b],b=a,a=f),n.isFunction(a)?(c=e.call(arguments,2),d=function(){return a.apply(b||this,c.concat(e.call(arguments)))},d.guid=a.guid=a.guid||n.guid++,d):void 0},now:function(){return+new Date},support:l}),"function"==typeof Symbol&&(n.fn[Symbol.iterator]=c[Symbol.iterator]),n.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(a,b){i["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=!!a&&"length"in a&&a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ga(),z=ga(),A=ga(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+M+"))|)"+L+"*\\]",O=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+N+")*)|.*)\\)|)",P=new RegExp(L+"+","g"),Q=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),R=new RegExp("^"+L+"*,"+L+"*"),S=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),T=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),U=new RegExp(O),V=new RegExp("^"+M+"$"),W={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M+"|[*])"),ATTR:new RegExp("^"+N),PSEUDO:new RegExp("^"+O),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},X=/^(?:input|select|textarea|button)$/i,Y=/^h\d$/i,Z=/^[^{]+\{\s*\[native \w/,$=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,_=/[+~]/,aa=/'|\\/g,ba=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),ca=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},da=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(ea){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fa(a,b,d,e){var f,h,j,k,l,o,r,s,w=b&&b.ownerDocument,x=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==x&&9!==x&&11!==x)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==x&&(o=$.exec(a)))if(f=o[1]){if(9===x){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(w&&(j=w.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(o[2])return H.apply(d,b.getElementsByTagName(a)),d;if((f=o[3])&&c.getElementsByClassName&&b.getElementsByClassName)return H.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==x)w=b,s=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(aa,"\\$&"):b.setAttribute("id",k=u),r=g(a),h=r.length,l=V.test(k)?"#"+k:"[id='"+k+"']";while(h--)r[h]=l+" "+qa(r[h]);s=r.join(","),w=_.test(a)&&oa(b.parentNode)||b}if(s)try{return H.apply(d,w.querySelectorAll(s)),d}catch(y){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(Q,"$1"),b,d,e)}function ga(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ha(a){return a[u]=!0,a}function ia(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ja(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function ka(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function la(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function na(a){return ha(function(b){return b=+b,ha(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function oa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=fa.support={},f=fa.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fa.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ia(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ia(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Z.test(n.getElementsByClassName),c.getById=ia(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return"undefined"!=typeof b.getElementsByClassName&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=Z.test(n.querySelectorAll))&&(ia(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ia(function(a){var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Z.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ia(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",O)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Z.test(o.compareDocumentPosition),t=b||Z.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return ka(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?ka(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},fa.matches=function(a,b){return fa(a,null,null,b)},fa.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(T,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fa(b,n,null,[a]).length>0},fa.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fa.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fa.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fa.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fa.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fa.selectors={cacheLength:50,createPseudo:ha,match:W,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ba,ca),a[3]=(a[3]||a[4]||a[5]||"").replace(ba,ca),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fa.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fa.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return W.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&U.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ba,ca).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fa.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(P," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fa.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ha(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ha(function(a){var b=[],c=[],d=h(a.replace(Q,"$1"));return d[u]?ha(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ha(function(a){return function(b){return fa(a,b).length>0}}),contains:ha(function(a){return a=a.replace(ba,ca),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ha(function(a){return V.test(a||"")||fa.error("unsupported lang: "+a),a=a.replace(ba,ca).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Y.test(a.nodeName)},input:function(a){return X.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:na(function(){return[0]}),last:na(function(a,b){return[b-1]}),eq:na(function(a,b,c){return[0>c?c+b:c]}),even:na(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:na(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:na(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:na(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function ra(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j,k=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(j=b[u]||(b[u]={}),i=j[b.uniqueID]||(j[b.uniqueID]={}),(h=i[d])&&h[0]===w&&h[1]===f)return k[2]=h[2];if(i[d]=k,k[2]=a(b,c,g))return!0}}}function sa(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ta(a,b,c){for(var d=0,e=b.length;e>d;d++)fa(a,b[d],c);return c}function ua(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(c&&!c(f,d,e)||(g.push(f),j&&b.push(h)));return g}function va(a,b,c,d,e,f){return d&&!d[u]&&(d=va(d)),e&&!e[u]&&(e=va(e,f)),ha(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ta(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ua(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ua(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ua(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function wa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ra(function(a){return a===b},h,!0),l=ra(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[ra(sa(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return va(i>1&&sa(m),i>1&&qa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(Q,"$1"),c,e>i&&wa(a.slice(i,e)),f>e&&wa(a=a.slice(e)),f>e&&qa(a))}m.push(c)}return sa(m)}function xa(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=F.call(i));u=ua(u)}H.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&fa.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ha(f):f}return h=fa.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xa(e,d)),f.selector=a}return f},i=fa.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ba,ca),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=W.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ba,ca),_.test(j[0].type)&&oa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qa(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,!b||_.test(a)&&oa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ia(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ia(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ja("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ia(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ja("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ia(function(a){return null==a.getAttribute("disabled")})||ja(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fa}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.uniqueSort=n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},v=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},w=n.expr.match.needsContext,x=/^<([\w-]+)\s*\/?>(?:<\/\1>|)$/,y=/^.[^:#\[\.,]*$/;function z(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(y.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return n.inArray(a,b)>-1!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;e>b;b++)if(n.contains(d[b],this))return!0}));for(b=0;e>b;b++)n.find(a,d[b],c);return c=this.pushStack(e>1?n.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(z(this,a||[],!1))},not:function(a){return this.pushStack(z(this,a||[],!0))},is:function(a){return!!z(this,"string"==typeof a&&w.test(a)?n(a):a||[],!1).length}});var A,B=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=n.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||A,"string"==typeof a){if(e="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:B.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),x.test(e[1])&&n.isPlainObject(b))for(e in b)n.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}if(f=d.getElementById(e[2]),f&&f.parentNode){if(f.id!==e[2])return A.find(a);this.length=1,this[0]=f}return this.context=d,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof c.ready?c.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};C.prototype=n.fn,A=n(d);var D=/^(?:parents|prev(?:Until|All))/,E={children:!0,contents:!0,next:!0,prev:!0};n.fn.extend({has:function(a){var b,c=n(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(n.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=w.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?n.inArray(this[0],n(a)):n.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.uniqueSort(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function F(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return u(a,"parentNode")},parentsUntil:function(a,b,c){return u(a,"parentNode",c)},next:function(a){return F(a,"nextSibling")},prev:function(a){return F(a,"previousSibling")},nextAll:function(a){return u(a,"nextSibling")},prevAll:function(a){return u(a,"previousSibling")},nextUntil:function(a,b,c){return u(a,"nextSibling",c)},prevUntil:function(a,b,c){return u(a,"previousSibling",c)},siblings:function(a){return v((a.parentNode||{}).firstChild,a)},children:function(a){return v(a.firstChild)},contents:function(a){return n.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(E[a]||(e=n.uniqueSort(e)),D.test(a)&&(e=e.reverse())),this.pushStack(e)}});var G=/\S+/g;function H(a){var b={};return n.each(a.match(G)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?H(a):n.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h-1)f.splice(c,1),h>=c&&h--}),this},has:function(a){return a?n.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=!0,c||j.disable(),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().progress(c.notify).done(c.resolve).fail(c.reject):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=e.call(arguments),d=c.length,f=1!==d||a&&n.isFunction(a.promise)?d:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?e.call(arguments):d,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(d>1)for(i=new Array(d),j=new Array(d),k=new Array(d);d>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().progress(h(b,j,i)).done(h(b,k,c)).fail(g.reject):--f;return f||g.resolveWith(k,c),g.promise()}});var I;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(I.resolveWith(d,[n]),n.fn.triggerHandler&&(n(d).triggerHandler("ready"),n(d).off("ready"))))}});function J(){d.addEventListener?(d.removeEventListener("DOMContentLoaded",K),a.removeEventListener("load",K)):(d.detachEvent("onreadystatechange",K),a.detachEvent("onload",K))}function K(){(d.addEventListener||"load"===a.event.type||"complete"===d.readyState)&&(J(),n.ready())}n.ready.promise=function(b){if(!I)if(I=n.Deferred(),"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll)a.setTimeout(n.ready);else if(d.addEventListener)d.addEventListener("DOMContentLoaded",K),a.addEventListener("load",K);else{d.attachEvent("onreadystatechange",K),a.attachEvent("onload",K);var c=!1;try{c=null==a.frameElement&&d.documentElement}catch(e){}c&&c.doScroll&&!function f(){if(!n.isReady){try{c.doScroll("left")}catch(b){return a.setTimeout(f,50)}J(),n.ready()}}()}return I.promise(b)},n.ready.promise();var L;for(L in n(l))break;l.ownFirst="0"===L,l.inlineBlockNeedsLayout=!1,n(function(){var a,b,c,e;c=d.getElementsByTagName("body")[0],c&&c.style&&(b=d.createElement("div"),e=d.createElement("div"),e.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(e).appendChild(b),"undefined"!=typeof b.style.zoom&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",l.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(e))}),function(){var a=d.createElement("div");l.deleteExpando=!0;try{delete a.test}catch(b){l.deleteExpando=!1}a=null}();var M=function(a){var b=n.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b},N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(O,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}n.data(a,b,c)}else c=void 0; +}return c}function Q(a){var b;for(b in a)if(("data"!==b||!n.isEmptyObject(a[b]))&&"toJSON"!==b)return!1;return!0}function R(a,b,d,e){if(M(a)){var f,g,h=n.expando,i=a.nodeType,j=i?n.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||n.guid++:h),j[k]||(j[k]=i?{}:{toJSON:n.noop}),"object"!=typeof b&&"function"!=typeof b||(e?j[k]=n.extend(j[k],b):j[k].data=n.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[n.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[n.camelCase(b)])):f=g,f}}function S(a,b,c){if(M(a)){var d,e,f=a.nodeType,g=f?n.cache:a,h=f?a[n.expando]:n.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){n.isArray(b)?b=b.concat(n.map(b,n.camelCase)):b in d?b=[b]:(b=n.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!Q(d):!n.isEmptyObject(d))return}(c||(delete g[h].data,Q(g[h])))&&(f?n.cleanData([a],!0):l.deleteExpando||g!=g.window?delete g[h]:g[h]=void 0)}}}n.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?n.cache[a[n.expando]]:a[n.expando],!!a&&!Q(a)},data:function(a,b,c){return R(a,b,c)},removeData:function(a,b){return S(a,b)},_data:function(a,b,c){return R(a,b,c,!0)},_removeData:function(a,b){return S(a,b,!0)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=n.data(f),1===f.nodeType&&!n._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d])));n._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){n.data(this,a)}):arguments.length>1?this.each(function(){n.data(this,a,b)}):f?P(f,a,n.data(f,a)):void 0},removeData:function(a){return this.each(function(){n.removeData(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=n._data(a,b),c&&(!d||n.isArray(c)?d=n._data(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return n._data(a,c)||n._data(a,c,{empty:n.Callbacks("once memory").add(function(){n._removeData(a,b+"queue"),n._removeData(a,c)})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthh;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},Z=/^(?:checkbox|radio)$/i,$=/<([\w:-]+)/,_=/^$|\/(?:java|ecma)script/i,aa=/^\s+/,ba="abbr|article|aside|audio|bdi|canvas|data|datalist|details|dialog|figcaption|figure|footer|header|hgroup|main|mark|meter|nav|output|picture|progress|section|summary|template|time|video";function ca(a){var b=ba.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}!function(){var a=d.createElement("div"),b=d.createDocumentFragment(),c=d.createElement("input");a.innerHTML="
a",l.leadingWhitespace=3===a.firstChild.nodeType,l.tbody=!a.getElementsByTagName("tbody").length,l.htmlSerialize=!!a.getElementsByTagName("link").length,l.html5Clone="<:nav>"!==d.createElement("nav").cloneNode(!0).outerHTML,c.type="checkbox",c.checked=!0,b.appendChild(c),l.appendChecked=c.checked,a.innerHTML="",l.noCloneChecked=!!a.cloneNode(!0).lastChild.defaultValue,b.appendChild(a),c=d.createElement("input"),c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),a.appendChild(c),l.checkClone=a.cloneNode(!0).cloneNode(!0).lastChild.checked,l.noCloneEvent=!!a.addEventListener,a[n.expando]=1,l.attributes=!a.getAttribute(n.expando)}();var da={option:[1,""],legend:[1,"
","
"],area:[1,"",""],param:[1,"",""],thead:[1,"","
"],tr:[2,"","
"],col:[2,"","
"],td:[3,"","
"],_default:l.htmlSerialize?[0,"",""]:[1,"X
","
"]};da.optgroup=da.option,da.tbody=da.tfoot=da.colgroup=da.caption=da.thead,da.th=da.td;function ea(a,b){var c,d,e=0,f="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||n.nodeName(d,b)?f.push(d):n.merge(f,ea(d,b));return void 0===b||b&&n.nodeName(a,b)?n.merge([a],f):f}function fa(a,b){for(var c,d=0;null!=(c=a[d]);d++)n._data(c,"globalEval",!b||n._data(b[d],"globalEval"))}var ga=/<|&#?\w+;/,ha=/r;r++)if(g=a[r],g||0===g)if("object"===n.type(g))n.merge(q,g.nodeType?[g]:g);else if(ga.test(g)){i=i||p.appendChild(b.createElement("div")),j=($.exec(g)||["",""])[1].toLowerCase(),m=da[j]||da._default,i.innerHTML=m[1]+n.htmlPrefilter(g)+m[2],f=m[0];while(f--)i=i.lastChild;if(!l.leadingWhitespace&&aa.test(g)&&q.push(b.createTextNode(aa.exec(g)[0])),!l.tbody){g="table"!==j||ha.test(g)?""!==m[1]||ha.test(g)?0:i:i.firstChild,f=g&&g.childNodes.length;while(f--)n.nodeName(k=g.childNodes[f],"tbody")&&!k.childNodes.length&&g.removeChild(k)}n.merge(q,i.childNodes),i.textContent="";while(i.firstChild)i.removeChild(i.firstChild);i=p.lastChild}else q.push(b.createTextNode(g));i&&p.removeChild(i),l.appendChecked||n.grep(ea(q,"input"),ia),r=0;while(g=q[r++])if(d&&n.inArray(g,d)>-1)e&&e.push(g);else if(h=n.contains(g.ownerDocument,g),i=ea(p.appendChild(g),"script"),h&&fa(i),c){f=0;while(g=i[f++])_.test(g.type||"")&&c.push(g)}return i=null,p}!function(){var b,c,e=d.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(l[b]=c in a)||(e.setAttribute(c,"t"),l[b]=e.attributes[c].expando===!1);e=null}();var ka=/^(?:input|select|textarea)$/i,la=/^key/,ma=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,na=/^(?:focusinfocus|focusoutblur)$/,oa=/^([^.]*)(?:\.(.+)|)/;function pa(){return!0}function qa(){return!1}function ra(){try{return d.activeElement}catch(a){}}function sa(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)sa(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=qa;else if(!e)return a;return 1===f&&(g=e,e=function(a){return n().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=n.guid++)),a.each(function(){n.event.add(this,b,e,d,c)})}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=n.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return"undefined"==typeof n||a&&n.event.triggered===a.type?void 0:n.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(G)||[""],h=b.length;while(h--)f=oa.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=n.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=n.event.special[o]||{},l=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},i),(m=g[o])||(m=g[o]=[],m.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,l):m.push(l),n.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n.hasData(a)&&n._data(a);if(r&&(k=r.events)){b=(b||"").match(G)||[""],j=b.length;while(j--)if(h=oa.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=m.length;while(f--)g=m[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(m.splice(f,1),g.selector&&m.delegateCount--,l.remove&&l.remove.call(a,g));i&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(k)&&(delete r.handle,n._removeData(a,"events"))}},trigger:function(b,c,e,f){var g,h,i,j,l,m,o,p=[e||d],q=k.call(b,"type")?b.type:b,r=k.call(b,"namespace")?b.namespace.split("."):[];if(i=m=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!na.test(q+n.event.triggered)&&(q.indexOf(".")>-1&&(r=q.split("."),q=r.shift(),r.sort()),h=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=f?2:3,b.namespace=r.join("."),b.rnamespace=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=e),c=null==c?[b]:n.makeArray(c,[b]),l=n.event.special[q]||{},f||!l.trigger||l.trigger.apply(e,c)!==!1)){if(!f&&!l.noBubble&&!n.isWindow(e)){for(j=l.delegateType||q,na.test(j+q)||(i=i.parentNode);i;i=i.parentNode)p.push(i),m=i;m===(e.ownerDocument||d)&&p.push(m.defaultView||m.parentWindow||a)}o=0;while((i=p[o++])&&!b.isPropagationStopped())b.type=o>1?j:l.bindType||q,g=(n._data(i,"events")||{})[b.type]&&n._data(i,"handle"),g&&g.apply(i,c),g=h&&i[h],g&&g.apply&&M(i)&&(b.result=g.apply(i,c),b.result===!1&&b.preventDefault());if(b.type=q,!f&&!b.isDefaultPrevented()&&(!l._default||l._default.apply(p.pop(),c)===!1)&&M(e)&&h&&e[q]&&!n.isWindow(e)){m=e[h],m&&(e[h]=null),n.event.triggered=q;try{e[q]()}catch(s){}n.event.triggered=void 0,m&&(e[h]=m)}return b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,d,f,g,h=[],i=e.call(arguments),j=(n._data(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())a.rnamespace&&!a.rnamespace.test(g.namespace)||(a.handleObj=g,a.data=g.data,d=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==d&&(a.result=d)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&("click"!==a.type||isNaN(a.button)||a.button<1))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>-1:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h]","i"),va=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,wa=/\s*$/g,Aa=ca(d),Ba=Aa.appendChild(d.createElement("div"));function Ca(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function Da(a){return a.type=(null!==n.find.attr(a,"type"))+"/"+a.type,a}function Ea(a){var b=ya.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Fa(a,b){if(1===b.nodeType&&n.hasData(a)){var c,d,e,f=n._data(a),g=n._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)n.event.add(b,c,h[c][d])}g.data&&(g.data=n.extend({},g.data))}}function Ga(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!l.noCloneEvent&&b[n.expando]){e=n._data(b);for(d in e.events)n.removeEvent(b,d,e.handle);b.removeAttribute(n.expando)}"script"===c&&b.text!==a.text?(Da(b).text=a.text,Ea(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),l.html5Clone&&a.innerHTML&&!n.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&Z.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:"input"!==c&&"textarea"!==c||(b.defaultValue=a.defaultValue)}}function Ha(a,b,c,d){b=f.apply([],b);var e,g,h,i,j,k,m=0,o=a.length,p=o-1,q=b[0],r=n.isFunction(q);if(r||o>1&&"string"==typeof q&&!l.checkClone&&xa.test(q))return a.each(function(e){var f=a.eq(e);r&&(b[0]=q.call(this,e,f.html())),Ha(f,b,c,d)});if(o&&(k=ja(b,a[0].ownerDocument,!1,a,d),e=k.firstChild,1===k.childNodes.length&&(k=e),e||d)){for(i=n.map(ea(k,"script"),Da),h=i.length;o>m;m++)g=k,m!==p&&(g=n.clone(g,!0,!0),h&&n.merge(i,ea(g,"script"))),c.call(a[m],g,m);if(h)for(j=i[i.length-1].ownerDocument,n.map(i,Ea),m=0;h>m;m++)g=i[m],_.test(g.type||"")&&!n._data(g,"globalEval")&&n.contains(j,g)&&(g.src?n._evalUrl&&n._evalUrl(g.src):n.globalEval((g.text||g.textContent||g.innerHTML||"").replace(za,"")));k=e=null}return a}function Ia(a,b,c){for(var d,e=b?n.filter(b,a):a,f=0;null!=(d=e[f]);f++)c||1!==d.nodeType||n.cleanData(ea(d)),d.parentNode&&(c&&n.contains(d.ownerDocument,d)&&fa(ea(d,"script")),d.parentNode.removeChild(d));return a}n.extend({htmlPrefilter:function(a){return a.replace(va,"<$1>")},clone:function(a,b,c){var d,e,f,g,h,i=n.contains(a.ownerDocument,a);if(l.html5Clone||n.isXMLDoc(a)||!ua.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(Ba.innerHTML=a.outerHTML,Ba.removeChild(f=Ba.firstChild)),!(l.noCloneEvent&&l.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(d=ea(f),h=ea(a),g=0;null!=(e=h[g]);++g)d[g]&&Ga(e,d[g]);if(b)if(c)for(h=h||ea(a),d=d||ea(f),g=0;null!=(e=h[g]);g++)Fa(e,d[g]);else Fa(a,f);return d=ea(f,"script"),d.length>0&&fa(d,!i&&ea(a,"script")),d=h=e=null,f},cleanData:function(a,b){for(var d,e,f,g,h=0,i=n.expando,j=n.cache,k=l.attributes,m=n.event.special;null!=(d=a[h]);h++)if((b||M(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)m[e]?n.event.remove(d,e):n.removeEvent(d,e,g.handle);j[f]&&(delete j[f],k||"undefined"==typeof d.removeAttribute?d[i]=void 0:d.removeAttribute(i),c.push(f))}}}),n.fn.extend({domManip:Ha,detach:function(a){return Ia(this,a,!0)},remove:function(a){return Ia(this,a)},text:function(a){return Y(this,function(a){return void 0===a?n.text(this):this.empty().append((this[0]&&this[0].ownerDocument||d).createTextNode(a))},null,a,arguments.length)},append:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.appendChild(a)}})},prepend:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&n.cleanData(ea(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&n.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return Y(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(ta,""):void 0;if("string"==typeof a&&!wa.test(a)&&(l.htmlSerialize||!ua.test(a))&&(l.leadingWhitespace||!aa.test(a))&&!da[($.exec(a)||["",""])[1].toLowerCase()]){a=n.htmlPrefilter(a);try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(ea(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=[];return Ha(this,arguments,function(b){var c=this.parentNode;n.inArray(this,a)<0&&(n.cleanData(ea(this)),c&&c.replaceChild(b,this))},a)}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=0,e=[],f=n(a),h=f.length-1;h>=d;d++)c=d===h?this:this.clone(!0),n(f[d])[b](c),g.apply(e,c.get());return this.pushStack(e)}});var Ja,Ka={HTML:"block",BODY:"block"};function La(a,b){var c=n(b.createElement(a)).appendTo(b.body),d=n.css(c[0],"display");return c.detach(),d}function Ma(a){var b=d,c=Ka[a];return c||(c=La(a,b),"none"!==c&&c||(Ja=(Ja||n("\n"; + print "

Command: \n"; + print "

\n"; + print "
Note: You cannot change directory within the console. Use the Change Directory feature above.
\n"; + print "\n"; + print "
\n"; + print "\n"; + return; +} +# end browse +############################################################################### +# start setp +sub setp { + my $status = 0; + chmod (oct("0$FORM{newp}"),"$webpath$FORM{p}/$FORM{f}") or $status = $!; + if ($status) {$message = "Operation Failed - $status"} else {$message = ""} + &browse; + return; +} +# end setp +############################################################################### +# start seto +sub seto { + my $status = ""; + my ($uid,$gid) = split (/\:/,$FORM{newo}); + if ($uid !~ /^\d/) {$uid = (getpwnam($uid))[2]} + if ($gid !~ /^\d/) {$gid = (getgrnam($gid))[2]} + if ($uid eq "") {$message .= "No such user
\n"} + if ($gid eq "") {$message .= "No such group
\n"} + + if ($message eq "") { + chown ($uid,$gid,"$webpath$FORM{p}/$FORM{f}") or $status = $!; + if ($status) {$message = "Operation Failed - $status"} else {$message = ""} + } + &browse; + return; +} +# end seto +############################################################################### +# start ren +sub ren { + my $status = 0; + rename ("$webpath$FORM{p}/$FORM{f}","$webpath$FORM{p}/$FORM{newf}") or $status = $!; + if ($status) {$message = "Operation Failed - $status"} else {$message = ""} + &browse; + return; +} +# end ren +############################################################################### +# start moveit +sub moveit { + if ("$webpath$FORM{m}" eq "$webpath$FORM{p}/$FORM{newf}") { + $message = "Move Failed - Cannot overwrite original"; + } + elsif ((-d "$webpath$FORM{m}") and ("$webpath$FORM{p}/$FORM{newf}" =~ /^$webpath$FORM{m}\//)) { + $message = "Move Failed - Cannot move inside original"; + } + else { + my $status = 0; + rename ("$webpath$FORM{m}","$webpath$FORM{p}/$FORM{newf}") or $status = $!; + if ($status) {$message = "Operation Failed - $status"} else {$message = ""} + } + if ($message eq "") {$FORM{m} = ""} + &browse; + return; +} +# end moveit +############################################################################### +# start copyit +sub copyit { + if ("$webpath$FORM{c}" eq "$webpath$FORM{p}/$FORM{newf}") { + $message = "Copy Failed - Cannot overwrite original"; + } + elsif ((-d "$webpath$FORM{c}") and ("$webpath$FORM{p}/$FORM{newf}" =~ /^$webpath$FORM{c}\//)) { + $message = "Copy Failed - Cannot copy inside original"; + } + else { + if (-d "$webpath$FORM{c}") { + $origpath = "$webpath$FORM{c}"; + $destpath = "$webpath$FORM{p}/$FORM{newf}"; + find(\&mycopy, $origpath); + } else { + copy ("$webpath$FORM{c}","$webpath$FORM{p}/$FORM{newf}") or $message = "Copy Failed - $!"; + if ($message eq "") { + my $mode = sprintf "%04o", (stat("$webpath$FORM{c}"))[2] & oct("00777"); + chmod (oct($mode),"$webpath$FORM{p}/$FORM{newf}") or $message = "Permission Change Failed - $!"; + } + } + } + if ($message eq "") {$FORM{c} = ""} + &browse; + return; +} +# end copyit +############################################################################### +# start mycopy +sub mycopy { + my $file = $File::Find::name; + (my $dest = $file) =~ s/^\Q$origpath/$destpath/; + my $status = ""; + if (-d $file) { + my $err = (split(/\//,$dest))[-1]; + mkpath ($dest) or $status = "Copy Failed Making New Dir [$err] - $!
\n"; + } elsif (-f $file) { + my $err = (split(/\//,$file))[-1]; + copy ($file,$dest) or $status = "Copy Failed [$err] - $!
\n"; + } + if ($status eq "") { + my $err = (split(/\//,$file))[-1]; + my $mode = sprintf "%04o", (stat("$file"))[2] & oct("00777"); + chmod (oct($mode),"$dest") or $message .= "Copy Failed Setting Perms [$err] - $!
\n"; + } else { + $message .= $status; + } + return; +} +# end mycopy +############################################################################### +# start cnewd +sub cnewd { + my $status = 0; + if ($FORM{newf} ne "") { + mkdir ("$webpath$FORM{p}/$FORM{newf}",0777) or $status = $!; + } + if ($status) {$message = "Operation Failed - $status"} else {$message = ""} + &browse; + return; +} +# end cnewd +############################################################################### +# start cnewf +sub cnewf { + my $status = 0; + if ($FORM{newf} ne "") { + if (-f "$webpath$FORM{p}/$FORM{newf}") { + $status = "File exists"; + } else { + open (my $OUT, ">","$webpath$FORM{p}/$FORM{newf}") or $status = $!; + flock ($OUT, LOCK_EX); + close ($OUT); + } + } + if ($status) {$message = "Operation Failed - $status"} else {$message = ""} + &browse; + return; +} +# end cnewf +############################################################################### +# start del +sub del { + my $status = 0; + if (-d "$webpath$FORM{p}/$FORM{f}") { + rmtree("$webpath$FORM{p}/$FORM{f}", 0, 0) or $status = $!; + } else { + unlink ("$webpath$FORM{p}/$FORM{f}") or $status = $!; + } + if ($status) {$message = "Operation Failed - $status"} else {$message = ""} + &browse; + return; +} +# end del +############################################################################### +# start view +sub view { + if (-e "$webpath$FORM{p}/$FORM{f}" ) { + if (-T "$webpath$FORM{p}/$FORM{f}") { + print "content-type: text/plain\r\n"; + } else { + print "content-type: application/octet-stream\r\n"; + } + print "content-disposition: attachment; filename=$FORM{f}\r\n\r\n"; + + open(my $IN,"<","$webpath$FORM{p}/$FORM{f}") or die $!; + flock ($IN, LOCK_SH); + while (<$IN>) {print} + close($IN); + }else{ + print "content-type: text/html\r\n\r\n"; + print "File [$webpath$FORM{p}/$FORM{f}] not found!"; + } + return; +} +# end view +############################################################################### +# start console +sub console { + my $thisdir = "$webpath$FORM{p}"; + $thisdir =~ s/\/+/\//g; + + print "

\n";
+	print "root [$thisdir]# $FORM{cmd}\n";
+	chdir $thisdir;
+
+	$| = 1;
+	my ($childin, $childout);
+	my $cmdpid = open3($childin, $childout, $childout, $FORM{cmd});
+	while (my $line = <$childout>) {
+		$line =~ s/\/\>\;/g;
+		print $line;
+	}
+	waitpid ($cmdpid, 0);
+	print "root [$thisdir]# _

\n"; + print ""; + return; +} +# end console +############################################################################### +# start cd +sub cd { + if (-d $FORM{directory}) { + $FORM{p} = $FORM{directory}; + } else { + $message = "No such directory [$FORM{directory}]"; + } + + &browse; + return; +} +# end cd +############################################################################### +# start edit +sub edit { + open (my $IN, "<","$webpath$FORM{p}/$FORM{f}") or die $!; + flock ($IN, LOCK_SH); + my @data = <$IN>; + close ($IN); + + my $filedata; + foreach my $line (@data) { + $line =~ s/\/>/g; + $filedata .= $line; + } + + my $lf = 0; + if ($filedata =~ /\r/) {$lf = 1} + + print "\n"; + print "
\n"; + print "\n"; + print "\n"; + print ""; + print "
"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "
"; + print " \n"; + print "\n"; + print "
\n"; + print "
\n"; + return; +} +# end edit +############################################################################### +# start save +sub save { + unless ($FORM{lf}) {$FORM{newf} =~ s/\r//g} + my $status = 0; + open (my $OUT, ">","$webpath$FORM{p}/$FORM{f}") or $status = $!; + flock ($OUT, LOCK_EX); + print $OUT $FORM{newf}; + close ($OUT); + + if ($status) {$message = "Operation Failed - $status"} else {$message = ""} + &browse; + return; +} +# end save +############################################################################### +# start uploadfile +sub uploadfile { + my $crlf = "\r\n"; + my @data = split (/$crlf/,$fileinc); + + my $boundary = $data[0]; + + $boundary =~ s/\"//g; + $boundary =~ s/$crlf//g; + + my $start = 0; + my $part_cnt=-1; + undef @parts; + my $fileno = 0; + + foreach my $line (@data) { + if ($line =~ /^$boundary--/) { + last; + } + if ($line =~ /^$boundary/) { + $part_cnt++; + $start = 1; + next; + } + if ($start) { + $parts[$part_cnt] .= $line.$crlf; + } + } + + foreach my $part (@parts) { + my @partdata = split(/$crlf/,$part); + undef %header; + my $body = ""; + my $dobody = 0; + my $lastfieldname = ""; + + foreach my $line (@partdata) { + if (($line eq "") and !($dobody)) { + $dobody = 1; + next; + } + + if ($dobody) { + $body .= $line.$crlf; + } else { + if ($line =~ /^\s/) { + $header{$lastfieldname} .= $line; + } else { + ($fieldname, $value) = split (/\:\s/,$line,2); + $fieldname = lc $fieldname; + $fieldname =~ s/-/_/g; + $header{$fieldname} = $value; + $lastfieldname = $fieldname; + } + } + } + + my @elements = split(/\;/,$header{content_disposition}); + foreach my $element (@elements) { + $element =~ s/\s//g; + $element =~ s/\"//g; + ($name,$value) = split(/\=/,$element); + $FORM{$value} = $body; + $ele{$name} = $value; + $ele{$ele{name}} = $value; + if ($value =~ /^file(.*)$/) {$files = $1} + } + + my $filename = $ele{"file$files"}; + if ($filename ne "") { + $fileno++; + $filename =~ s/\"//g; + $filename =~ s/\r//g; + $filename =~ s/\n//g; + @bits = split(/\\/,$filename); + $filetemp=$bits[-1]; + @bits = split(/\//,$filetemp); + $filetemp=$bits[-1]; + @bits = split(/\:/,$filetemp); + $filetemp=$bits[-1]; + @bits = split(/\"/,$filetemp); + $filename=$bits[0]; + push (@filenames, $filename); + push (@filebodies, $body); + } + } + + $FORM{p} =~ s/\r//g; + $FORM{p} =~ s/\n//g; + $FORM{type} =~ s/\r//g; + $FORM{type} =~ s/\n//g; + $FORM{c} =~ s/\r//g; + $FORM{c} =~ s/\n//g; + $FORM{m} =~ s/\r//g; + $FORM{m} =~ s/\n//g; + $FORM{caller} =~ s/\r//g; + $FORM{caller} =~ s/\n//g; + + for (my $x = 0;$x < @filenames ;$x++) { + $filenames[$x] =~ s/\r//g; + $filenames[$x] =~ s/\n//g; + $filenames[$x] =~ s/^file-//g; + $filenames[$x] = (split (/\\/,$filenames[$x]))[-1]; + $filenames[$x] = (split (/\//,$filenames[$x]))[-1]; + if ($FORM{type} eq "ascii") {$filebodies[$x] =~ s/\r//g} + if (-e "$webpath$FORM{p}/$filenames[$x]") { + $extramessage .= "
$filenames[$x] - Already exists, delete the original first"; + $fileno--; + next; + } + sysopen (my $OUT,"$webpath$FORM{p}/$filenames[$x]", O_WRONLY | O_CREAT); + flock ($OUT, LOCK_EX); + print $OUT $filebodies[$x]; + close ($OUT); + $extramessage .= "
$filenames[$x] - Uploaded"; + } + + $message = "$fileno File(s) Uploaded".$extramessage; + + &browse; + return; +} +# end uploadfile +############################################################################### +# start countfiles +sub countfiles { + if (-d $File::Find::name) {push (@dirs, $File::Find::name)} else {push (@files, $File::Find::name)} + return; +} +# end countfiles +############################################################################### +# loadconfig +sub loadconfig { + sysopen (my $IN, "/etc/csf/csf.conf", O_RDWR | O_CREAT) or die "Unable to open file: $!"; + flock ($IN, LOCK_SH); + my @config = <$IN>; + close ($IN); + chomp @config; + + foreach my $line (@config) { + if ($line =~ /^\#/) {next} + if ($line !~ /=/) {next} + my ($name,$value) = split (/=/,$line,2); + $name =~ s/\s//g; + if ($value =~ /\"(.*)\"/) { + $value = $1; + } else { + &error(__LINE__,"Invalid configuration line"); + } + $config{$name} = $value; + } + return; +} +# end loadconfig +############################################################################### + +1; diff --git a/csf/Crypt/Blowfish_PP.pm b/csf/Crypt/Blowfish_PP.pm new file mode 100644 index 0000000..455e3fc --- /dev/null +++ b/csf/Crypt/Blowfish_PP.pm @@ -0,0 +1,519 @@ +# This is Crypt/Blowfish_PP.pm which is an implementation of Bruce Schneier's +# blowfish cryptographic algorithm. I will write some proper docs when I get +# time.... +# code is (c) copyright Matthew Byng-Maddick 2000-2023, and +# some bits are copyright Bruce Schneier. For more information see his website +# at http://www.counterpane.com/ + +=head1 NAME + +B - Blowfish encryption algorithm implemented purely in Perl + +=head1 SYNOPSIS + +C; + +$blowfish=new Crypt::Blowfish_PP($key); + +$ciphertextBlock=$blowfish->encrypt($plaintextBlock); + +$plaintextBlock=$blowfish->decrypt($ciphertextBlock); + +=head1 DESCRIPTION + +The B module provides for users to use the Blowfish encryption +algorithm in perl. The implementation is entirely Object Oriented, as there is +quite a lot of context inherent in making blowfish as fast as it is. The key is +anywhere between 64 and 448 bits (8 and 56 bytes), and should be passed as a +packed string. The transformation itself is a 16-round Feistel Network, and +operates on a 64 bit block. + +Object methods for the Crypt::Blowfish_PP module: + +=cut +package Crypt::Blowfish_PP; + +use strict; +use vars qw($VERSION); + +$VERSION="1.12"; + +=head2 B(I) + +The B() method initialises a blowfish object with the key that is passed. +This is the slow part of doing a blowfish encryption or decryption, as it +initialises the 18 p-boxes and the 1024 s-boxes that are used for the algorithm. +It will return undef if the key is not of a valid length. + +=cut + +sub new + { + my $pack=shift; + my $key=shift; + return undef if(!defined($key)); + my %h=( + p_boxes => + [ + 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, + 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, + 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, + 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, + 0x9216d5d9, 0x8979fb1b + ], + s_boxes => + [ + [ + 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, + 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, + 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, + 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, + 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, + 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, + 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, + 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, + 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, + 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, + 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, + 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, + 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, + 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, + 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, + 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, + 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, + 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, + 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, + 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, + 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, + 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, + 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, + 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, + 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, + 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, + 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, + 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, + 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, + 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, + 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, + 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, + 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, + 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, + 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, + 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, + 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, + 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, + 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, + 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, + 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, + 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, + 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, + 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, + 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, + 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, + 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, + 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, + 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, + 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, + 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, + 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, + 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, + 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, + 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, + 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, + 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, + 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, + 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, + 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, + 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, + 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, + 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, + 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a + ], + [ + 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, + 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, + 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, + 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, + 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, + 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, + 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, + 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, + 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, + 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, + 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, + 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, + 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, + 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7, + 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, + 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, + 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, + 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, + 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, + 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87, + 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, + 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, + 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, + 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, + 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, + 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, + 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, + 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, + 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, + 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, + 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, + 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, + 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, + 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, + 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, + 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, + 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, + 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, + 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, + 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, + 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, + 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, + 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, + 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281, + 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, + 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, + 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, + 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, + 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, + 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, + 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, + 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, + 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, + 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, + 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, + 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061, + 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, + 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, + 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, + 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, + 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, + 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, + 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, + 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7 + ], + [ + 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, + 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, + 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, + 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, + 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, + 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, + 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, + 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, + 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, + 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, + 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, + 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, + 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, + 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, + 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, + 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, + 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, + 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, + 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, + 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, + 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, + 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, + 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, + 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, + 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, + 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, + 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, + 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, + 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, + 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, + 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, + 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, + 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, + 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, + 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, + 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, + 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, + 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, + 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, + 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, + 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, + 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, + 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, + 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, + 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, + 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, + 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, + 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, + 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, + 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, + 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, + 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, + 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, + 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, + 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, + 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62, + 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, + 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, + 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, + 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, + 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, + 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, + 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, + 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0 + ], + [ + 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, + 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, + 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, + 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, + 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, + 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, + 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, + 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, + 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, + 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, + 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, + 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, + 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, + 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, + 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, + 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, + 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, + 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, + 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, + 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd, + 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, + 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, + 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, + 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, + 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, + 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, + 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, + 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, + 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, + 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, + 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, + 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, + 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, + 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, + 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, + 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, + 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, + 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, + 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, + 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, + 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, + 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, + 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, + 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, + 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, + 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, + 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, + 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, + 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, + 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, + 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, + 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, + 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, + 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, + 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, + 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, + 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, + 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, + 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, + 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, + 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, + 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9, + 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, + 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6 + ] + ] + ); + my $keylen=length($key); + return undef if(($keylen < 8) || ($keylen > 56)); + my @keybytes=split//,$key; + my $b; + for $b (@keybytes) + { + $b=unpack("C",$b); + } + my $j=0; + my $i=0; + my($l,$r)=(0,0); + + # BEGIN PROCESS OF SETTING UP S & P-BOXES FOR THE KEY + for ($i=0;$i<18;$i++) + { + my $temp= ($keybytes[$j]<<24) + + ($keybytes[($j+1)%($keylen)]<<16) + + ($keybytes[($j+2)%($keylen)]<<8) + + ($keybytes[($j+3)%($keylen)]) ; + $h{"p_boxes"}->[$i]^=$temp; + $j=($j+4)%($keylen); + } + for ($i=0;$i<18;$i+=2) + { + ($l,$r)=crypt_block(\%h,$l,$r,0); + $h{"p_boxes"}->[$i]=$l; + $h{"p_boxes"}->[$i+1]=$r; + } + for $i (0..3) + { + for($j=0;$j<256;$j+=2) + { + ($l,$r)=crypt_block(\%h,$l,$r,0); + $h{"s_boxes"}->[$i]->[$j]=$l; + $h{"s_boxes"}->[$i]->[$j+1]=$r; + } + } + # S-BOXES AND P-BOXES NOW SET UP, NEED NO LONGER CARE + # ABOUT ACTUAL KEY + return bless \%h, $pack; + } + +sub F + { + my $S0=$_[0]->{"s_boxes"}->[0]->[($_[1]&0xFF000000)>>24]; + my $S1=$_[0]->{"s_boxes"}->[1]->[($_[1]&0x00FF0000)>>16]; + my $S2=$_[0]->{"s_boxes"}->[2]->[($_[1]&0x0000FF00)>>8]; + my $S3=$_[0]->{"s_boxes"}->[3]->[($_[1]&0x000000FF)]; + # this is horrid, but otherwise Perl overflows. :( + if($S0>$S1) + { + $S0=$S0-4294967296 if($S0>2147483647); + } + else + { + $S1=$S1-4294967296 if($S1>2147483647); + } + my $F=($S0+$S1); + $F+=4294967296 if($F<0); + $F^=$S2; + if($F>$S3) + { + $F=$F-4294967296 if($F>2147483647); + } + else + { + $S3=$S3-4294967296 if($S3>2147483647); + } + $F+=$S3; + $F&=0xFFFFFFFF; + return $F; + } + +sub ROUND + { + return($_[1],($_[2]^($_[0]->{"p_boxes"}->[$_[3]]))^F($_[0],$_[1])); + } + +sub crypt_block + { + my $self=shift; + my $l=shift; + my $r=shift; + my $d=shift; + if(!$d) + { + $l^=$self->{"p_boxes"}->[0]; + my $i; + for $i (1..16) + { + ($r,$l)=ROUND($self,$l,$r,$i); + } + $r^=$self->{"p_boxes"}->[17]; + } + else + { + $l^=$self->{"p_boxes"}->[17]; + my $i; + for $i (1..16) + { + ($r,$l)=ROUND($self,$l,$r,17-$i); + } + $r^=$self->{"p_boxes"}->[0]; + } + return($r,$l); + } + +=head2 B(I) + +The B() method uses the initialised blowfish object to encrypt 8 bytes +of data of the string passed to it. It returns the encrypted block. + +=cut + +sub encrypt + { + my($self)=shift; + my($block)=shift; + my(@block)=split//,$block; + map{$_=unpack("C",$_)}@block; + # I'm not sure what endianness these are.... so hey. + my($l)=$block[3]|($block[2]<<8)|($block[1]<<16)|($block[0]<<24); + my($r)=$block[7]|($block[6]<<8)|($block[5]<<16)|($block[4]<<24); + + ($l,$r)=crypt_block($self,$l,$r,0); + + @block=( + $l>>24,($l>>16)&0xFF,($l>>8)&0xFF,$l&0xFF, + $r>>24,($r>>16)&0xFF,($r>>8)&0xFF,$r&0xFF + ); + map{$_=pack("C",$_)}@block; + return join"",@block; + } + +=head2 B(I) + +The B() method uses the initialised blowfish object to decrypt 8 bytes +of data of the string passed to it. It returns the decrypted block. + +=cut + +sub decrypt + { + my($self)=shift; + my($block)=shift; + my(@block)=split//,$block; + map{$_=unpack("C",$_)}@block; + my($l)=$block[3]|($block[2]<<8)|($block[1]<<16)|($block[0]<<24); + my($r)=$block[7]|($block[6]<<8)|($block[5]<<16)|($block[4]<<24); + + ($l,$r)=crypt_block($self,$l,$r,1); + + @block=( + $l>>24,($l>>16)&0xFF,($l>>8)&0xFF,$l&0xFF, + $r>>24,($r>>16)&0xFF,($r>>8)&0xFF,$r&0xFF + ); + map{$_=pack("C",$_)}@block; + return join"",@block; + } + +sub blocksize + { + return 8; + } + +sub keysize + { + return 56; + } + +=head1 COMMENTS + +This is probably crap software, but hey, its for general use. I'm happy to patch +it with other people's code... :) + +If you want speed, then see the Crypt::Blowfish module. + +=head1 AUTHOR + +Matthew Byng-Maddick > + +=head1 SEE ALSO + +http://www.counterpane.com/,L + +=cut + +1; diff --git a/csf/Crypt/CBC.pm b/csf/Crypt/CBC.pm new file mode 100644 index 0000000..39ff251 --- /dev/null +++ b/csf/Crypt/CBC.pm @@ -0,0 +1,1064 @@ +package Crypt::CBC; + +use Digest::MD5 'md5'; +use Carp; +use strict; +use bytes; +use vars qw($VERSION); +$VERSION = '2.33'; + +use constant RANDOM_DEVICE => '/dev/urandom'; + +sub new { + my $class = shift; + + my $options = {}; + + # hashref arguments + if (ref $_[0] eq 'HASH') { + $options = shift; + } + + # CGI style arguments + elsif ($_[0] =~ /^-[a-zA-Z_]{1,20}$/) { + my %tmp = @_; + while ( my($key,$value) = each %tmp) { + $key =~ s/^-//; + $options->{lc $key} = $value; + } + } + + else { + $options->{key} = shift; + $options->{cipher} = shift; + } + + my $cipher_object_provided = $options->{cipher} && ref $options->{cipher}; + + # "key" is a misnomer here, because it is actually usually a passphrase that is used + # to derive the true key + my $pass = $options->{key}; + + if ($cipher_object_provided) { + carp "Both a key and a pre-initialized Crypt::* object were passed. The key will be ignored" + if defined $pass; + $pass ||= ''; + } + elsif (!defined $pass) { + croak "Please provide an encryption/decryption passphrase or key using -key" + } + + # header mode + my %valid_modes = map {$_=>1} qw(none salt randomiv); + my $header_mode = $options->{header}; + $header_mode ||= 'none' if exists $options->{prepend_iv} && !$options->{prepend_iv}; + $header_mode ||= 'none' if exists $options->{add_header} && !$options->{add_header}; + $header_mode ||= 'salt'; # default + croak "Invalid -header mode '$header_mode'" unless $valid_modes{$header_mode}; + + croak "The -salt argument is incompatible with a -header mode of $header_mode" + if exists $options->{salt} && $header_mode ne 'salt'; + + my $cipher = $options->{cipher}; + $cipher = 'Crypt::DES' unless $cipher; + my $cipherclass = ref $cipher || $cipher; + + unless (ref $cipher) { # munge the class name if no object passed + $cipher = $cipher=~/^Crypt::/ ? $cipher : "Crypt::$cipher"; + $cipher->can('encrypt') or eval "require $cipher; 1" or croak "Couldn't load $cipher: $@"; + # some crypt modules use the class Crypt::, and others don't + $cipher =~ s/^Crypt::// unless $cipher->can('keysize'); + } + + # allow user to override these values + my $ks = $options->{keysize}; + my $bs = $options->{blocksize}; + + # otherwise we get the values from the cipher + $ks ||= eval {$cipher->keysize}; + $bs ||= eval {$cipher->blocksize}; + + # Some of the cipher modules are busted and don't report the + # keysize (well, Crypt::Blowfish in any case). If we detect + # this, and find the blowfish module in use, then assume 56. + # Otherwise assume the least common denominator of 8. + $ks ||= $cipherclass =~ /blowfish/i ? 56 : 8; + $bs ||= $ks; + + my $pcbc = $options->{'pcbc'}; + + # Default behavior is to treat -key as a passphrase. + # But if the literal_key option is true, then use key as is + croak "The options -literal_key and -regenerate_key are incompatible with each other" + if exists $options->{literal_key} && exists $options->{regenerate_key}; + my $key; + $key = $pass if $options->{literal_key}; + $key = $pass if exists $options->{regenerate_key} && !$options->{regenerate_key}; + + # Get the salt. + my $salt = $options->{salt}; + my $random_salt = 1 unless defined $salt && $salt ne '1'; + croak "Argument to -salt must be exactly 8 bytes long" if defined $salt && length $salt != 8 && $salt ne '1'; + + # note: iv will be autogenerated by start() if not specified in options + my $iv = $options->{iv}; + my $random_iv = 1 unless defined $iv; + croak "Initialization vector must be exactly $bs bytes long when using the $cipherclass cipher" if defined $iv and length($iv) != $bs; + + my $literal_key = $options->{literal_key} || (exists $options->{regenerate_key} && !$options->{regenerate_key}); + my $legacy_hack = $options->{insecure_legacy_decrypt}; + my $padding = $options->{padding} || 'standard'; + + if ($padding && ref($padding) eq 'CODE') { + # check to see that this code does its padding correctly + for my $i (1..$bs-1) { + my $rbs = length($padding->(" "x$i,$bs,'e')); + croak "padding method callback does not behave properly: expected $bs bytes back, got $rbs bytes back." + unless ($rbs == $bs); + } + } else { + $padding = $padding eq 'none' ? \&_no_padding + :$padding eq 'null' ? \&_null_padding + :$padding eq 'space' ? \&_space_padding + :$padding eq 'oneandzeroes' ? \&_oneandzeroes_padding + :$padding eq 'rijndael_compat'? \&_rijndael_compat + :$padding eq 'standard' ? \&_standard_padding + :croak "'$padding' padding not supported. See perldoc Crypt::CBC for instructions on creating your own."; + } + + # CONSISTENCY CHECKS + # HEADER consistency + if ($header_mode eq 'salt') { + croak "Cannot use salt-based key generation if literal key is specified" + if $options->{literal_key}; + croak "Cannot use salt-based IV generation if literal IV is specified" + if exists $options->{iv}; + } + elsif ($header_mode eq 'randomiv') { + croak "Cannot encrypt using a non-8 byte blocksize cipher when using randomiv header mode" + unless $bs == 8 || $legacy_hack; + } + elsif ($header_mode eq 'none') { + croak "You must provide an initialization vector using -iv when using -header=>'none'" + unless exists $options->{iv}; + } + + # KEYSIZE consistency + if (defined $key && length($key) != $ks) { + croak "If specified by -literal_key, then the key length must be equal to the chosen cipher's key length of $ks bytes"; + } + + # IV consistency + if (defined $iv && length($iv) != $bs) { + croak "If specified by -iv, then the initialization vector length must be equal to the chosen cipher's blocksize of $bs bytes"; + } + + + return bless {'cipher' => $cipher, + 'passphrase' => $pass, + 'key' => $key, + 'iv' => $iv, + 'salt' => $salt, + 'padding' => $padding, + 'blocksize' => $bs, + 'keysize' => $ks, + 'header_mode' => $header_mode, + 'legacy_hack' => $legacy_hack, + 'literal_key' => $literal_key, + 'pcbc' => $pcbc, + 'make_random_salt' => $random_salt, + 'make_random_iv' => $random_iv, + },$class; +} + +sub encrypt (\$$) { + my ($self,$data) = @_; + $self->start('encrypting'); + my $result = $self->crypt($data); + $result .= $self->finish; + $result; +} + +sub decrypt (\$$){ + my ($self,$data) = @_; + $self->start('decrypting'); + my $result = $self->crypt($data); + $result .= $self->finish; + $result; +} + +sub encrypt_hex (\$$) { + my ($self,$data) = @_; + return join('',unpack 'H*',$self->encrypt($data)); +} + +sub decrypt_hex (\$$) { + my ($self,$data) = @_; + return $self->decrypt(pack'H*',$data); +} + +# call to start a series of encryption/decryption operations +sub start (\$$) { + my $self = shift; + my $operation = shift; + croak "Specify ncryption or ecryption" unless $operation=~/^[ed]/i; + + $self->{'buffer'} = ''; + $self->{'decrypt'} = $operation=~/^d/i; +} + +# call to encrypt/decrypt a bit of data +sub crypt (\$$){ + my $self = shift; + my $data = shift; + + my $result; + + croak "crypt() called without a preceding start()" + unless exists $self->{'buffer'}; + + my $d = $self->{'decrypt'}; + + unless ($self->{civ}) { # block cipher has not yet been initialized + $result = $self->_generate_iv_and_cipher_from_datastream(\$data) if $d; + $result = $self->_generate_iv_and_cipher_from_options() unless $d; + } + + my $iv = $self->{'civ'}; + $self->{'buffer'} .= $data; + + my $bs = $self->{'blocksize'}; + + croak "When using no padding, plaintext size must be a multiple of $bs" + if $self->{'padding'} eq \&_no_padding + and length($data) % $bs; + + croak "When using rijndael_compat padding, plaintext size must be a multiple of $bs" + if $self->{'padding'} eq \&_rijndael_compat + and length($data) % $bs; + + return $result unless (length($self->{'buffer'}) >= $bs); + + my @blocks = unpack("a$bs "x(int(length($self->{'buffer'})/$bs)) . "a*", $self->{'buffer'}); + $self->{'buffer'} = ''; + + if ($d) { # when decrypting, always leave a free block at the end + $self->{'buffer'} = length($blocks[-1]) < $bs ? join '',splice(@blocks,-2) : pop(@blocks); + } else { + $self->{'buffer'} = pop @blocks if length($blocks[-1]) < $bs; # what's left over + } + + foreach my $block (@blocks) { + if ($d) { # decrypting + $result .= $iv = $iv ^ $self->{'crypt'}->decrypt($block); + $iv = $block unless $self->{pcbc}; + } else { # encrypting + $result .= $iv = $self->{'crypt'}->encrypt($iv ^ $block); + } + $iv = $iv ^ $block if $self->{pcbc}; + } + $self->{'civ'} = $iv; # remember the iv + return $result; +} + +# this is called at the end to flush whatever's left +sub finish (\$) { + my $self = shift; + my $bs = $self->{'blocksize'}; + my $block = defined $self->{'buffer'} ? $self->{'buffer'} : ''; + + $self->{civ} ||= ''; + + my $result; + if ($self->{'decrypt'}) { #decrypting + $block = length $block ? pack("a$bs",$block) : ''; # pad and truncate to block size + + if (length($block)) { + $result = $self->{'civ'} ^ $self->{'crypt'}->decrypt($block); + $result = $self->{'padding'}->($result, $bs, 'd'); + } else { + $result = ''; + } + + } else { # encrypting + $block = $self->{'padding'}->($block,$bs,'e') || ''; + $result = length $block ? $self->{'crypt'}->encrypt($self->{'civ'} ^ $block) : ''; + } + delete $self->{'civ'}; + delete $self->{'buffer'}; + return $result; +} + +# this subroutine will generate the actual {en,de}cryption key, the iv +# and the block cipher object. This is called when reading from a datastream +# and so it uses previous values of salt or iv if they are encoded in datastream +# header +sub _generate_iv_and_cipher_from_datastream { + my $self = shift; + my $input_stream = shift; + my $bs = $self->blocksize; + + # use our header mode to figure out what to do with the data stream + my $header_mode = $self->header_mode; + + if ($header_mode eq 'none') { + croak "You must specify a $bs byte initialization vector by passing the -iv option to new() when using -header_mode=>'none'" + unless exists $self->{iv}; + $self->{civ} = $self->{iv}; # current IV equals saved IV + $self->{key} ||= $self->_key_from_key($self->{passphrase}); + } + + elsif ($header_mode eq 'salt') { + my ($salt) = $$input_stream =~ /^Salted__(.{8})/s; + croak "Ciphertext does not begin with a valid header for 'salt' header mode" unless defined $salt; + $self->{salt} = $salt; # new salt + substr($$input_stream,0,16) = ''; + my ($key,$iv) = $self->_salted_key_and_iv($self->{passphrase},$salt); + $self->{iv} = $self->{civ} = $iv; + $self->{key} = $key; + } + + elsif ($header_mode eq 'randomiv') { + my ($iv) = $$input_stream =~ /^RandomIV(.{8})/s; + croak "Ciphertext does not begin with a valid header for 'randomiv' header mode" unless defined $iv; + croak "randomiv header mode cannot be used securely when decrypting with a >8 byte block cipher.\nUse the -insecure_legacy_decrypt flag if you are sure you want to do this" unless $self->blocksize == 8 || $self->legacy_hack; + $self->{iv} = $self->{civ} = $iv; + $self->{key} = $self->_key_from_key($self->{passphrase}); + undef $self->{salt}; # paranoia + substr($$input_stream,0,16) = ''; # truncate + } + + else { + croak "Invalid header mode '$header_mode'"; + } + + # we should have the key and iv now, or we are dead in the water + croak "Cipher stream did not contain IV or salt, and you did not specify these values in new()" + unless $self->{key} && $self->{civ}; + + # now we can generate the crypt object itself + $self->{crypt} = ref $self->{cipher} ? $self->{cipher} + : $self->{cipher}->new($self->{key}) + or croak "Could not create $self->{cipher} object: $@"; + return ''; +} + +sub _generate_iv_and_cipher_from_options { + my $self = shift; + my $blocksize = $self->blocksize; + + my $result = ''; + + my $header_mode = $self->header_mode; + if ($header_mode eq 'none') { + croak "You must specify a $blocksize byte initialization vector by passing the -iv option to new() when using -header_mode=>'none'" + unless exists $self->{iv}; + $self->{civ} = $self->{iv}; + $self->{key} ||= $self->_key_from_key($self->{passphrase}); + } + + elsif ($header_mode eq 'salt') { + $self->{salt} = $self->_get_random_bytes(8) if $self->{make_random_salt}; + defined (my $salt = $self->{salt}) or croak "No header_mode of 'salt' specified, but no salt value provided"; # shouldn't happen + length($salt) == 8 or croak "Salt must be exactly 8 bytes long"; + my ($key,$iv) = $self->_salted_key_and_iv($self->{passphrase},$salt); + $self->{key} = $key; + $self->{civ} = $self->{iv} = $iv; + $result = "Salted__${salt}"; + } + + elsif ($header_mode eq 'randomiv') { + croak "randomiv header mode cannot be used when encrypting with a >8 byte block cipher. There is no option to allow this" + unless $blocksize == 8; + $self->{key} ||= $self->_key_from_key($self->{passphrase}); + $self->{iv} = $self->_get_random_bytes(8) if $self->{make_random_iv}; + length($self->{iv}) == 8 or croak "IV must be exactly 8 bytes long when used with header mode of 'randomiv'"; + $self->{civ} = $self->{iv}; + $result = "RandomIV$self->{iv}"; + } + + croak "key and/or iv are missing" unless defined $self->{key} && defined $self->{civ}; + + $self->_taintcheck($self->{key}); + $self->{crypt} = ref $self->{cipher} ? $self->{cipher} + : $self->{cipher}->new($self->{key}) + or croak "Could not create $self->{cipher} object: $@"; + return $result; +} + +sub _taintcheck { + my $self = shift; + my $key = shift; + return unless ${^TAINT}; + + my $has_scalar_util = eval "require Scalar::Util; 1"; + my $tainted; + + + if ($has_scalar_util) { + $tainted = Scalar::Util::tainted($key); + } else { + local($@, $SIG{__DIE__}, $SIG{__WARN__}); + local $^W = 0; + eval { kill 0 * $key }; + $tainted = $@ =~ /^Insecure/; + } + + croak "Taint checks are turned on and your key is tainted. Please untaint the key and try again" + if $tainted; +} + +sub _key_from_key { + my $self = shift; + my $pass = shift; + my $ks = $self->{keysize}; + + return $pass if $self->{literal_key}; + + my $material = md5($pass); + while (length($material) < $ks) { + $material .= md5($material); + } + return substr($material,0,$ks); +} + +sub _salted_key_and_iv { + my $self = shift; + my ($pass,$salt) = @_; + + croak "Salt must be 8 bytes long" unless length $salt == 8; + + my $key_len = $self->{keysize}; + my $iv_len = $self->{blocksize}; + + my $desired_len = $key_len+$iv_len; + + my $data = ''; + my $d = ''; + + while (length $data < $desired_len) { + $d = md5($d . $pass . $salt); + $data .= $d; + } + return (substr($data,0,$key_len),substr($data,$key_len,$iv_len)); +} + +sub random_bytes { + my $self = shift; + my $bytes = shift or croak "usage: random_bytes(\$byte_length)"; + $self->_get_random_bytes($bytes); +} + +sub _get_random_bytes { + my $self = shift; + my $length = shift; + my $result; + + if (-r RANDOM_DEVICE && open(F,RANDOM_DEVICE)) { + read(F,$result,$length); + close F; + } else { + $result = pack("C*",map {rand(256)} 1..$length); + } + # Clear taint and check length + $result =~ /^(.+)$/s; + length($1) == $length or croak "Invalid length while gathering $length random bytes"; + return $1; +} + +sub _standard_padding ($$$) { + my ($b,$bs,$decrypt) = @_; + $b = length $b ? $b : ''; + if ($decrypt eq 'd') { + my $pad_length = unpack("C",substr($b,-1)); + + # sanity check for implementations that don't pad correctly + return $b unless $pad_length >= 0 && $pad_length <= $bs; + my @pad_chars = unpack("C*",substr($b,-$pad_length)); + return $b if grep {$pad_length != $_} @pad_chars; + + return substr($b,0,$bs-$pad_length); + } + my $pad = $bs - length($b) % $bs; + return $b . pack("C*",($pad)x$pad); +} + +sub _space_padding ($$$) { + my ($b,$bs,$decrypt) = @_; + return unless length $b; + $b = length $b ? $b : ''; + if ($decrypt eq 'd') { + $b=~ s/ *\z//s; + return $b; + } + return $b . pack("C*", (32) x ($bs - length($b) % $bs)); +} + +sub _no_padding ($$$) { + my ($b,$bs,$decrypt) = @_; + return $b; +} + +sub _null_padding ($$$) { + my ($b,$bs,$decrypt) = @_; + return unless length $b; + $b = length $b ? $b : ''; + if ($decrypt eq 'd') { + $b=~ s/\0*\z//s; + return $b; + } + return $b . pack("C*", (0) x ($bs - length($b) % $bs)); +} + +sub _oneandzeroes_padding ($$$) { + my ($b,$bs,$decrypt) = @_; + $b = length $b ? $b : ''; + if ($decrypt eq 'd') { + $b=~ s/\x80\0*\z//s; + return $b; + } + return $b . pack("C*", 128, (0) x ($bs - length($b) % $bs - 1) ); +} + +sub _rijndael_compat ($$$) { + my ($b,$bs,$decrypt) = @_; + return unless length $b; + if ($decrypt eq 'd') { + $b=~ s/\x80\0*\z//s; + return $b; + } + return $b . pack("C*", 128, (0) x ($bs - length($b) % $bs - 1) ); +} + +sub get_initialization_vector (\$) { + my $self = shift; + $self->iv(); +} + +sub set_initialization_vector (\$$) { + my $self = shift; + my $iv = shift; + my $bs = $self->blocksize; + croak "Initialization vector must be $bs bytes in length" unless length($iv) == $bs; + $self->iv($iv); +} + +sub salt { + my $self = shift; + my $d = $self->{salt}; + $self->{salt} = shift if @_; + $d; +} + +sub iv { + my $self = shift; + my $d = $self->{iv}; + $self->{iv} = shift if @_; + $d; +} + +sub key { + my $self = shift; + my $d = $self->{key}; + $self->{key} = shift if @_; + $d; +} + +sub passphrase { + my $self = shift; + my $d = $self->{passphrase}; + if (@_) { + undef $self->{key}; + undef $self->{iv}; + $self->{passphrase} = shift; + } + $d; +} + +sub cipher { shift->{cipher} } +sub padding { shift->{padding} } +sub keysize { shift->{keysize} } +sub blocksize { shift->{blocksize} } +sub pcbc { shift->{pcbc} } +sub header_mode {shift->{header_mode} } +sub legacy_hack { shift->{legacy_hack} } + +1; +__END__ + +=head1 NAME + +Crypt::CBC - Encrypt Data with Cipher Block Chaining Mode + +=head1 SYNOPSIS + + use Crypt::CBC; + $cipher = Crypt::CBC->new( -key => 'my secret key', + -cipher => 'Blowfish' + ); + + $ciphertext = $cipher->encrypt("This data is hush hush"); + $plaintext = $cipher->decrypt($ciphertext); + + $cipher->start('encrypting'); + open(F,"./BIG_FILE"); + while (read(F,$buffer,1024)) { + print $cipher->crypt($buffer); + } + print $cipher->finish; + + # do-it-yourself mode -- specify key, initialization vector yourself + $key = Crypt::CBC->random_bytes(8); # assuming a 8-byte block cipher + $iv = Crypt::CBC->random_bytes(8); + $cipher = Crypt::CBC->new(-literal_key => 1, + -key => $key, + -iv => $iv, + -header => 'none'); + + $ciphertext = $cipher->encrypt("This data is hush hush"); + $plaintext = $cipher->decrypt($ciphertext); + + # RANDOMIV-compatible mode + $cipher = Crypt::CBC->new(-key => 'Super Secret!' + -header => 'randomiv'); + + +=head1 DESCRIPTION + +This module is a Perl-only implementation of the cryptographic cipher +block chaining mode (CBC). In combination with a block cipher such as +DES or IDEA, you can encrypt and decrypt messages of arbitrarily long +length. The encrypted messages are compatible with the encryption +format used by the B package. + +To use this module, you will first create a Crypt::CBC cipher object +with new(). At the time of cipher creation, you specify an encryption +key to use and, optionally, a block encryption algorithm. You will +then call the start() method to initialize the encryption or +decryption process, crypt() to encrypt or decrypt one or more blocks +of data, and lastly finish(), to pad and encrypt the final block. For +your convenience, you can call the encrypt() and decrypt() methods to +operate on a whole data value at once. + +=head2 new() + + $cipher = Crypt::CBC->new( -key => 'my secret key', + -cipher => 'Blowfish', + ); + + # or (for compatibility with versions prior to 2.13) + $cipher = Crypt::CBC->new( { + key => 'my secret key', + cipher => 'Blowfish' + } + ); + + + # or (for compatibility with versions prior to 2.0) + $cipher = new Crypt::CBC('my secret key' => 'Blowfish'); + +The new() method creates a new Crypt::CBC object. It accepts a list of +-argument => value pairs selected from the following list: + + Argument Description + -------- ----------- + + -key The encryption/decryption key (required) + + -cipher The cipher algorithm (defaults to Crypt::DES), or + a preexisting cipher object. + + -salt Enables OpenSSL-compatibility. If equal to a value + of "1" then causes a random salt to be generated + and used to derive the encryption key and IV. Other + true values are taken to be the literal salt. + + -iv The initialization vector (IV) + + -header What type of header to prepend to ciphertext. One of + 'salt' -- use OpenSSL-compatible salted header + 'randomiv' -- Randomiv-compatible "RandomIV" header + 'none' -- prepend no header at all + + -padding The padding method, one of "standard" (default), + "space", "oneandzeroes", "rijndael_compat", + "null", or "none" (default "standard"). + + -literal_key If true, the key provided by "key" is used directly + for encryption/decryption. Otherwise the actual + key used will be a hash of the provided key. + (default false) + + -pcbc Whether to use the PCBC chaining algorithm rather than + the standard CBC algorithm (default false). + + -keysize Force the cipher keysize to the indicated number of bytes. + + -blocksize Force the cipher blocksize to the indicated number of bytes. + + -insecure_legacy_decrypt + Allow decryption of data encrypted using the "RandomIV" header + produced by pre-2.17 versions of Crypt::CBC. + + -add_header [deprecated; use -header instread] + Whether to add the salt and IV to the header of the output + cipher text. + + -regenerate_key [deprecated; use literal_key instead] + Whether to use a hash of the provided key to generate + the actual encryption key (default true) + + -prepend_iv [deprecated; use add_header instead] + Whether to prepend the IV to the beginning of the + encrypted stream (default true) + +Crypt::CBC requires three pieces of information to do its job. First +it needs the name of the block cipher algorithm that will encrypt or +decrypt the data in blocks of fixed length known as the cipher's +"blocksize." Second, it needs an encryption/decryption key to pass to +the block cipher. Third, it needs an initialization vector (IV) that +will be used to propagate information from one encrypted block to the +next. Both the key and the IV must be exactly the same length as the +chosen cipher's blocksize. + +Crypt::CBC can derive the key and the IV from a passphrase that you +provide, or can let you specify the true key and IV manually. In +addition, you have the option of embedding enough information to +regenerate the IV in a short header that is emitted at the start of +the encrypted stream, or outputting a headerless encryption stream. In +the first case, Crypt::CBC will be able to decrypt the stream given +just the original key or passphrase. In the second case, you will have +to provide the original IV as well as the key/passphrase. + +The B<-cipher> option specifies which block cipher algorithm to use to +encode each section of the message. This argument is optional and +will default to the quick-but-not-very-secure DES algorithm unless +specified otherwise. You may use any compatible block encryption +algorithm that you have installed. Currently, this includes +Crypt::DES, Crypt::DES_EDE3, Crypt::IDEA, Crypt::Blowfish, +Crypt::CAST5 and Crypt::Rijndael. You may refer to them using their +full names ("Crypt::IDEA") or in abbreviated form ("IDEA"). + +Instead of passing the name of a cipher class, you may pass an +already-created block cipher object. This allows you to take advantage +of cipher algorithms that have parameterized new() methods, such as +Crypt::Eksblowfish: + + my $eksblowfish = Crypt::Eksblowfish->new(8,$salt,$key); + my $cbc = Crypt::CBC->new(-cipher=>$eksblowfish); + +The B<-key> argument provides either a passphrase to use to generate +the encryption key, or the literal value of the block cipher key. If +used in passphrase mode (which is the default), B<-key> can be any +number of characters; the actual key will be derived by passing the +passphrase through a series of MD5 hash operations. To take full +advantage of a given block cipher, the length of the passphrase should +be at least equal to the cipher's blocksize. To skip this hashing +operation and specify the key directly, pass a true value to the +B<-literal_key> option. In this case, you should choose a key of +length exactly equal to the cipher's key length. You should also +specify the IV yourself and a -header mode of 'none'. + +If you pass an existing Crypt::* object to new(), then the -key +argument is ignored and the module will generate a warning. + +The B<-header> argument specifies what type of header, if any, to +prepend to the beginning of the encrypted data stream. The header +allows Crypt::CBC to regenerate the original IV and correctly decrypt +the data without your having to provide the same IV used to encrypt +the data. Valid values for the B<-header> are: + + "salt" -- Combine the passphrase with an 8-byte random value to + generate both the block cipher key and the IV from the + provided passphrase. The salt will be appended to the + beginning of the data stream allowing decryption to + regenerate both the key and IV given the correct passphrase. + This method is compatible with current versions of OpenSSL. + + "randomiv" -- Generate the block cipher key from the passphrase, and + choose a random 8-byte value to use as the IV. The IV will + be prepended to the data stream. This method is compatible + with ciphertext produced by versions of the library prior to + 2.17, but is incompatible with block ciphers that have non + 8-byte block sizes, such as Rijndael. Crypt::CBC will exit + with a fatal error if you try to use this header mode with a + non 8-byte cipher. + + "none" -- Do not generate a header. To decrypt a stream encrypted + in this way, you will have to provide the original IV + manually. + +B + +When using a "salt" header, you may specify your own value of the +salt, by passing the desired 8-byte salt to the B<-salt> +argument. Otherwise, the module will generate a random salt for +you. Crypt::CBC will generate a fatal error if you specify a salt +value that isn't exactly 8 bytes long. For backward compatibility +reasons, passing a value of "1" will generate a random salt, the same +as if no B<-salt> argument was provided. + +The B<-padding> argument controls how the last few bytes of the +encrypted stream are dealt with when they not an exact multiple of the +cipher block length. The default is "standard", the method specified +in PKCS#5. + +The B<-pcbc> argument, if true, activates a modified chaining mode +known as PCBC. It provides better error propagation characteristics +than the default CBC encryption and is required for authenticating to +Kerberos4 systems (see RFC 2222). + +The B<-keysize> and B<-blocksize> arguments can be used to force the +cipher's keysize and/or blocksize. This is only currently useful for +the Crypt::Blowfish module, which accepts a variable length +keysize. If -keysize is not specified, then Crypt::CBC will use the +maximum length Blowfish key size of 56 bytes (448 bits). The Openssl +library defaults to 16 byte Blowfish key sizes, so for compatibility +with Openssl you may wish to set -keysize=>16. There are currently no +Crypt::* modules that have variable block sizes, but an option to +change the block size is provided just in case. + +For compatibility with earlier versions of this module, you can +provide new() with a hashref containing key/value pairs. The key names +are the same as the arguments described earlier, but without the +initial hyphen. You may also call new() with one or two positional +arguments, in which case the first argument is taken to be the key and +the second to be the optional block cipher algorithm. + +B Versions of this module prior to 2.17 were +incorrectly using 8-byte IVs when generating the "randomiv" style of +header, even when the chosen cipher's blocksize was greater than 8 +bytes. This primarily affects the Rijndael algorithm. Such encrypted +data streams were B. From versions 2.17 onward, Crypt::CBC +will refuse to encrypt or decrypt using the "randomiv" header and non-8 +byte block ciphers. To decrypt legacy data encrypted with earlier +versions of the module, you can override the check using the +B<-insecure_legacy_decrypt> option. It is not possible to override +encryption. Please use the default "salt" header style, or no headers +at all. + +=head2 start() + + $cipher->start('encrypting'); + $cipher->start('decrypting'); + +The start() method prepares the cipher for a series of encryption or +decryption steps, resetting the internal state of the cipher if +necessary. You must provide a string indicating whether you wish to +encrypt or decrypt. "E" or any word that begins with an "e" indicates +encryption. "D" or any word that begins with a "d" indicates +decryption. + +=head2 crypt() + + $ciphertext = $cipher->crypt($plaintext); + +After calling start(), you should call crypt() as many times as +necessary to encrypt the desired data. + +=head2 finish() + + $ciphertext = $cipher->finish(); + +The CBC algorithm must buffer data blocks internally until they are +even multiples of the encryption algorithm's blocksize (typically 8 +bytes). After the last call to crypt() you should call finish(). +This flushes the internal buffer and returns any leftover ciphertext. + +In a typical application you will read the plaintext from a file or +input stream and write the result to standard output in a loop that +might look like this: + + $cipher = new Crypt::CBC('hey jude!'); + $cipher->start('encrypting'); + print $cipher->crypt($_) while <>; + print $cipher->finish(); + +=head2 encrypt() + + $ciphertext = $cipher->encrypt($plaintext) + +This convenience function runs the entire sequence of start(), crypt() +and finish() for you, processing the provided plaintext and returning +the corresponding ciphertext. + +=head2 decrypt() + + $plaintext = $cipher->decrypt($ciphertext) + +This convenience function runs the entire sequence of start(), crypt() +and finish() for you, processing the provided ciphertext and returning +the corresponding plaintext. + +=head2 encrypt_hex(), decrypt_hex() + + $ciphertext = $cipher->encrypt_hex($plaintext) + $plaintext = $cipher->decrypt_hex($ciphertext) + +These are convenience functions that operate on ciphertext in a +hexadecimal representation. B is exactly +equivalent to B. These functions +can be useful if, for example, you wish to place the encrypted in an +email message. + +=head2 get_initialization_vector() + + $iv = $cipher->get_initialization_vector() + +This function will return the IV used in encryption and or decryption. +The IV is not guaranteed to be set when encrypting until start() is +called, and when decrypting until crypt() is called the first +time. Unless the IV was manually specified in the new() call, the IV +will change with every complete encryption operation. + +=head2 set_initialization_vector() + + $cipher->set_initialization_vector('76543210') + +This function sets the IV used in encryption and/or decryption. This +function may be useful if the IV is not contained within the +ciphertext string being decrypted, or if a particular IV is desired +for encryption. Note that the IV must match the chosen cipher's +blocksize bytes in length. + +=head2 iv() + + $iv = $cipher->iv(); + $cipher->iv($new_iv); + +As above, but using a single method call. + +=head2 key() + + $key = $cipher->key(); + $cipher->key($new_key); + +Get or set the block cipher key used for encryption/decryption. When +encrypting, the key is not guaranteed to exist until start() is +called, and when decrypting, the key is not guaranteed to exist until +after the first call to crypt(). The key must match the length +required by the underlying block cipher. + +When salted headers are used, the block cipher key will change after +each complete sequence of encryption operations. + +=head2 salt() + + $salt = $cipher->salt(); + $cipher->salt($new_salt); + +Get or set the salt used for deriving the encryption key and IV when +in OpenSSL compatibility mode. + +=head2 passphrase() + + $passphrase = $cipher->passphrase(); + $cipher->passphrase($new_passphrase); + +This gets or sets the value of the B passed to new() when +B is false. + +=head2 $data = random_bytes($numbytes) + +Return $numbytes worth of random data. On systems that support the +"/dev/urandom" device file, this data will be read from the +device. Otherwise, it will be generated by repeated calls to the Perl +rand() function. + +=head2 cipher(), padding(), keysize(), blocksize(), pcbc() + +These read-only methods return the identity of the chosen block cipher +algorithm, padding method, key and block size of the chosen block +cipher, and whether PCBC chaining is in effect. + +=head2 Padding methods + +Use the 'padding' option to change the padding method. + +When the last block of plaintext is shorter than the block size, +it must be padded. Padding methods include: "standard" (i.e., PKCS#5), +"oneandzeroes", "space", "rijndael_compat", "null", and "none". + + standard: (default) Binary safe + pads with the number of bytes that should be truncated. So, if + blocksize is 8, then "0A0B0C" will be padded with "05", resulting + in "0A0B0C0505050505". If the final block is a full block of 8 + bytes, then a whole block of "0808080808080808" is appended. + + oneandzeroes: Binary safe + pads with "80" followed by as many "00" necessary to fill the + block. If the last block is a full block and blocksize is 8, a + block of "8000000000000000" will be appended. + + rijndael_compat: Binary safe, with caveats + similar to oneandzeroes, except that no padding is performed if + the last block is a full block. This is provided for + compatibility with Crypt::Rijndael only and can only be used + with messages that are a multiple of the Rijndael blocksize + of 16 bytes. + + null: text only + pads with as many "00" necessary to fill the block. If the last + block is a full block and blocksize is 8, a block of + "0000000000000000" will be appended. + + space: text only + same as "null", but with "20". + + none: + no padding added. Useful for special-purpose applications where + you wish to add custom padding to the message. + +Both the standard and oneandzeroes paddings are binary safe. The +space and null paddings are recommended only for text data. Which +type of padding you use depends on whether you wish to communicate +with an external (non Crypt::CBC library). If this is the case, use +whatever padding method is compatible. + +You can also pass in a custom padding function. To do this, create a +function that takes the arguments: + + $padded_block = function($block,$blocksize,$direction); + +where $block is the current block of data, $blocksize is the size to +pad it to, $direction is "e" for encrypting and "d" for decrypting, +and $padded_block is the result after padding or depadding. + +When encrypting, the function should always return a string of + length, and when decrypting, can expect the string coming +in to always be that length. See _standard_padding(), _space_padding(), +_null_padding(), or _oneandzeroes_padding() in the source for examples. + +Standard and oneandzeroes padding are recommended, as both space and +null padding can potentially truncate more characters than they should. + +=head1 EXAMPLES + +Two examples, des.pl and idea.pl can be found in the eg/ subdirectory +of the Crypt-CBC distribution. These implement command-line DES and +IDEA encryption algorithms. + +=head1 LIMITATIONS + +The encryption and decryption process is about a tenth the speed of +the equivalent SSLeay programs (compiled C). This could be improved +by implementing this module in C. It may also be worthwhile to +optimize the DES and IDEA block algorithms further. + +=head1 BUGS + +Please report them. + +=head1 AUTHOR + +Lincoln Stein, lstein@cshl.org + +This module is distributed under the ARTISTIC LICENSE using the same +terms as Perl itself. + +=head1 SEE ALSO + +perl(1), Crypt::DES(3), Crypt::IDEA(3), rfc2898 (PKCS#5) + +=cut diff --git a/csf/HTTP/Tiny.pm b/csf/HTTP/Tiny.pm new file mode 100644 index 0000000..541befe --- /dev/null +++ b/csf/HTTP/Tiny.pm @@ -0,0 +1,2425 @@ +# vim: ts=4 sts=4 sw=4 et: +package HTTP::Tiny; +use strict; +use warnings; +# ABSTRACT: A small, simple, correct HTTP/1.1 client + +our $VERSION = '0.070'; + +sub _croak { require Carp; Carp::croak(@_) } + +#pod =method new +#pod +#pod $http = HTTP::Tiny->new( %attributes ); +#pod +#pod This constructor returns a new HTTP::Tiny object. Valid attributes include: +#pod +#pod =for :list +#pod * C — A user-agent string (defaults to 'HTTP-Tiny/$VERSION'). If +#pod C — ends in a space character, the default user-agent string is +#pod appended. +#pod * C — An instance of L — or equivalent class +#pod that supports the C and C methods +#pod * C — A hashref of default headers to apply to requests +#pod * C — The local IP address to bind to +#pod * C — Whether to reuse the last connection (if for the same +#pod scheme, host and port) (defaults to 1) +#pod * C — Maximum number of redirects allowed (defaults to 5) +#pod * C — Maximum response size in bytes (only when not using a data +#pod callback). If defined, responses larger than this will return an +#pod exception. +#pod * C — URL of a proxy server to use for HTTP connections +#pod (default is C<$ENV{http_proxy}> — if set) +#pod * C — URL of a proxy server to use for HTTPS connections +#pod (default is C<$ENV{https_proxy}> — if set) +#pod * C — URL of a generic proxy server for both HTTP and HTTPS +#pod connections (default is C<$ENV{all_proxy}> — if set) +#pod * C — List of domain suffixes that should not be proxied. Must +#pod be a comma-separated string or an array reference. (default is +#pod C<$ENV{no_proxy}> —) +#pod * C — Request timeout in seconds (default is 60) If a socket open, +#pod read or write takes longer than the timeout, an exception is thrown. +#pod * C — A boolean that indicates whether to validate the SSL +#pod certificate of an C — connection (default is false) +#pod * C — A hashref of C — options to pass through to +#pod L +#pod +#pod Passing an explicit C for C, C or C will +#pod prevent getting the corresponding proxies from the environment. +#pod +#pod Exceptions from C, C or other errors will result in a +#pod pseudo-HTTP status code of 599 and a reason of "Internal Exception". The +#pod content field in the response will contain the text of the exception. +#pod +#pod The C parameter enables a persistent connection, but only to a +#pod single destination scheme, host and port. Also, if any connection-relevant +#pod attributes are modified, or if the process ID or thread ID change, the +#pod persistent connection will be dropped. If you want persistent connections +#pod across multiple destinations, use multiple HTTP::Tiny objects. +#pod +#pod See L for more on the C and C attributes. +#pod +#pod =cut + +my @attributes; +BEGIN { + @attributes = qw( + cookie_jar default_headers http_proxy https_proxy keep_alive + local_address max_redirect max_size proxy no_proxy + SSL_options verify_SSL + ); + my %persist_ok = map {; $_ => 1 } qw( + cookie_jar default_headers max_redirect max_size + ); + no strict 'refs'; + no warnings 'uninitialized'; + for my $accessor ( @attributes ) { + *{$accessor} = sub { + @_ > 1 + ? do { + delete $_[0]->{handle} if !$persist_ok{$accessor} && $_[1] ne $_[0]->{$accessor}; + $_[0]->{$accessor} = $_[1] + } + : $_[0]->{$accessor}; + }; + } +} + +sub agent { + my($self, $agent) = @_; + if( @_ > 1 ){ + $self->{agent} = + (defined $agent && $agent =~ / $/) ? $agent . $self->_agent : $agent; + } + return $self->{agent}; +} + +sub timeout { + my ($self, $timeout) = @_; + if ( @_ > 1 ) { + $self->{timeout} = $timeout; + if ($self->{handle}) { + $self->{handle}->timeout($timeout); + } + } + return $self->{timeout}; +} + +sub new { + my($class, %args) = @_; + + my $self = { + max_redirect => 5, + timeout => defined $args{timeout} ? $args{timeout} : 60, + keep_alive => 1, + verify_SSL => $args{verify_SSL} || $args{verify_ssl} || 0, # no verification by default + no_proxy => $ENV{no_proxy}, + }; + + bless $self, $class; + + $class->_validate_cookie_jar( $args{cookie_jar} ) if $args{cookie_jar}; + + for my $key ( @attributes ) { + $self->{$key} = $args{$key} if exists $args{$key} + } + + $self->agent( exists $args{agent} ? $args{agent} : $class->_agent ); + + $self->_set_proxies; + + return $self; +} + +sub _set_proxies { + my ($self) = @_; + + # get proxies from %ENV only if not provided; explicit undef will disable + # getting proxies from the environment + + # generic proxy + if (! exists $self->{proxy} ) { + $self->{proxy} = $ENV{all_proxy} || $ENV{ALL_PROXY}; + } + + if ( defined $self->{proxy} ) { + $self->_split_proxy( 'generic proxy' => $self->{proxy} ); # validate + } + else { + delete $self->{proxy}; + } + + # http proxy + if (! exists $self->{http_proxy} ) { + # under CGI, bypass HTTP_PROXY as request sets it from Proxy header + local $ENV{HTTP_PROXY} if $ENV{REQUEST_METHOD}; + $self->{http_proxy} = $ENV{http_proxy} || $ENV{HTTP_PROXY} || $self->{proxy}; + } + + if ( defined $self->{http_proxy} ) { + $self->_split_proxy( http_proxy => $self->{http_proxy} ); # validate + $self->{_has_proxy}{http} = 1; + } + else { + delete $self->{http_proxy}; + } + + # https proxy + if (! exists $self->{https_proxy} ) { + $self->{https_proxy} = $ENV{https_proxy} || $ENV{HTTPS_PROXY} || $self->{proxy}; + } + + if ( $self->{https_proxy} ) { + $self->_split_proxy( https_proxy => $self->{https_proxy} ); # validate + $self->{_has_proxy}{https} = 1; + } + else { + delete $self->{https_proxy}; + } + + # Split no_proxy to array reference if not provided as such + unless ( ref $self->{no_proxy} eq 'ARRAY' ) { + $self->{no_proxy} = + (defined $self->{no_proxy}) ? [ split /\s*,\s*/, $self->{no_proxy} ] : []; + } + + return; +} + +#pod =method get|head|put|post|delete +#pod +#pod $response = $http->get($url); +#pod $response = $http->get($url, \%options); +#pod $response = $http->head($url); +#pod +#pod These methods are shorthand for calling C for the given method. The +#pod URL must have unsafe characters escaped and international domain names encoded. +#pod See C for valid options and a description of the response. +#pod +#pod The C field of the response will be true if the status code is 2XX. +#pod +#pod =cut + +for my $sub_name ( qw/get head put post delete/ ) { + my $req_method = uc $sub_name; + no strict 'refs'; + eval <<"HERE"; ## no critic + sub $sub_name { + my (\$self, \$url, \$args) = \@_; + \@_ == 2 || (\@_ == 3 && ref \$args eq 'HASH') + or _croak(q/Usage: \$http->$sub_name(URL, [HASHREF])/ . "\n"); + return \$self->request('$req_method', \$url, \$args || {}); + } +HERE +} + +#pod =method post_form +#pod +#pod $response = $http->post_form($url, $form_data); +#pod $response = $http->post_form($url, $form_data, \%options); +#pod +#pod This method executes a C request and sends the key/value pairs from a +#pod form data hash or array reference to the given URL with a C of +#pod C. If data is provided as an array +#pod reference, the order is preserved; if provided as a hash reference, the terms +#pod are sorted on key and value for consistency. See documentation for the +#pod C method for details on the encoding. +#pod +#pod The URL must have unsafe characters escaped and international domain names +#pod encoded. See C for valid options and a description of the response. +#pod Any C header or content in the options hashref will be ignored. +#pod +#pod The C field of the response will be true if the status code is 2XX. +#pod +#pod =cut + +sub post_form { + my ($self, $url, $data, $args) = @_; + (@_ == 3 || @_ == 4 && ref $args eq 'HASH') + or _croak(q/Usage: $http->post_form(URL, DATAREF, [HASHREF])/ . "\n"); + + my $headers = {}; + while ( my ($key, $value) = each %{$args->{headers} || {}} ) { + $headers->{lc $key} = $value; + } + delete $args->{headers}; + + return $self->request('POST', $url, { + %$args, + content => $self->www_form_urlencode($data), + headers => { + %$headers, + 'content-type' => 'application/x-www-form-urlencoded' + }, + } + ); +} + +#pod =method mirror +#pod +#pod $response = $http->mirror($url, $file, \%options) +#pod if ( $response->{success} ) { +#pod print "$file is up to date\n"; +#pod } +#pod +#pod Executes a C request for the URL and saves the response body to the file +#pod name provided. The URL must have unsafe characters escaped and international +#pod domain names encoded. If the file already exists, the request will include an +#pod C header with the modification timestamp of the file. You +#pod may specify a different C header yourself in the C<< +#pod $options->{headers} >> hash. +#pod +#pod The C field of the response will be true if the status code is 2XX +#pod or if the status code is 304 (unmodified). +#pod +#pod If the file was modified and the server response includes a properly +#pod formatted C header, the file modification time will +#pod be updated accordingly. +#pod +#pod =cut + +sub mirror { + my ($self, $url, $file, $args) = @_; + @_ == 3 || (@_ == 4 && ref $args eq 'HASH') + or _croak(q/Usage: $http->mirror(URL, FILE, [HASHREF])/ . "\n"); + + if ( exists $args->{headers} ) { + my $headers = {}; + while ( my ($key, $value) = each %{$args->{headers} || {}} ) { + $headers->{lc $key} = $value; + } + $args->{headers} = $headers; + } + + if ( -e $file and my $mtime = (stat($file))[9] ) { + $args->{headers}{'if-modified-since'} ||= $self->_http_date($mtime); + } + my $tempfile = $file . int(rand(2**31)); + + require Fcntl; + sysopen my $fh, $tempfile, Fcntl::O_CREAT()|Fcntl::O_EXCL()|Fcntl::O_WRONLY() + or _croak(qq/Error: Could not create temporary file $tempfile for downloading: $!\n/); + binmode $fh; + $args->{data_callback} = sub { print {$fh} $_[0] }; + my $response = $self->request('GET', $url, $args); + close $fh + or _croak(qq/Error: Caught error closing temporary file $tempfile: $!\n/); + + if ( $response->{success} ) { + rename $tempfile, $file + or _croak(qq/Error replacing $file with $tempfile: $!\n/); + my $lm = $response->{headers}{'last-modified'}; + if ( $lm and my $mtime = $self->_parse_http_date($lm) ) { + utime $mtime, $mtime, $file; + } + } + $response->{success} ||= $response->{status} eq '304'; + unlink $tempfile; + return $response; +} + +#pod =method request +#pod +#pod $response = $http->request($method, $url); +#pod $response = $http->request($method, $url, \%options); +#pod +#pod Executes an HTTP request of the given method type ('GET', 'HEAD', 'POST', +#pod 'PUT', etc.) on the given URL. The URL must have unsafe characters escaped and +#pod international domain names encoded. +#pod +#pod If the URL includes a "user:password" stanza, they will be used for Basic-style +#pod authorization headers. (Authorization headers will not be included in a +#pod redirected request.) For example: +#pod +#pod $http->request('GET', 'http://Aladdin:open sesame@example.com/'); +#pod +#pod If the "user:password" stanza contains reserved characters, they must +#pod be percent-escaped: +#pod +#pod $http->request('GET', 'http://john%40example.com:password@example.com/'); +#pod +#pod A hashref of options may be appended to modify the request. +#pod +#pod Valid options are: +#pod +#pod =for :list +#pod * C — +#pod A hashref containing headers to include with the request. If the value for +#pod a header is an array reference, the header will be output multiple times with +#pod each value in the array. These headers over-write any default headers. +#pod * C — +#pod A scalar to include as the body of the request OR a code reference +#pod that will be called iteratively to produce the body of the request +#pod * C — +#pod A code reference that will be called if it exists to provide a hashref +#pod of trailing headers (only used with chunked transfer-encoding) +#pod * C — +#pod A code reference that will be called for each chunks of the response +#pod body received. +#pod * C — +#pod Override host resolution and force all connections to go only to a +#pod specific peer address, regardless of the URL of the request. This will +#pod include any redirections! This options should be used with extreme +#pod caution (e.g. debugging or very special circumstances). +#pod +#pod The C header is generated from the URL in accordance with RFC 2616. It +#pod is a fatal error to specify C in the C option. Other headers +#pod may be ignored or overwritten if necessary for transport compliance. +#pod +#pod If the C option is a code reference, it will be called iteratively +#pod to provide the content body of the request. It should return the empty +#pod string or undef when the iterator is exhausted. +#pod +#pod If the C option is the empty string, no C or +#pod C headers will be generated. +#pod +#pod If the C option is provided, it will be called iteratively until +#pod the entire response body is received. The first argument will be a string +#pod containing a chunk of the response body, the second argument will be the +#pod in-progress response hash reference, as described below. (This allows +#pod customizing the action of the callback based on the C or C +#pod received prior to the content body.) +#pod +#pod The C method returns a hashref containing the response. The hashref +#pod will have the following keys: +#pod +#pod =for :list +#pod * C — +#pod Boolean indicating whether the operation returned a 2XX status code +#pod * C — +#pod URL that provided the response. This is the URL of the request unless +#pod there were redirections, in which case it is the last URL queried +#pod in a redirection chain +#pod * C — +#pod The HTTP status code of the response +#pod * C — +#pod The response phrase returned by the server +#pod * C — +#pod The body of the response. If the response does not have any content +#pod or if a data callback is provided to consume the response body, +#pod this will be the empty string +#pod * C — +#pod A hashref of header fields. All header field names will be normalized +#pod to be lower case. If a header is repeated, the value will be an arrayref; +#pod it will otherwise be a scalar string containing the value +#pod * C +#pod If this field exists, it is an arrayref of response hash references from +#pod redirects in the same order that redirections occurred. If it does +#pod not exist, then no redirections occurred. +#pod +#pod On an exception during the execution of the request, the C field will +#pod contain 599, and the C field will contain the text of the exception. +#pod +#pod =cut + +my %idempotent = map { $_ => 1 } qw/GET HEAD PUT DELETE OPTIONS TRACE/; + +sub request { + my ($self, $method, $url, $args) = @_; + @_ == 3 || (@_ == 4 && ref $args eq 'HASH') + or _croak(q/Usage: $http->request(METHOD, URL, [HASHREF])/ . "\n"); + $args ||= {}; # we keep some state in this during _request + + # RFC 2616 Section 8.1.4 mandates a single retry on broken socket + my $response; + for ( 0 .. 1 ) { + $response = eval { $self->_request($method, $url, $args) }; + last unless $@ && $idempotent{$method} + && $@ =~ m{^(?:Socket closed|Unexpected end)}; + } + + if (my $e = $@) { + # maybe we got a response hash thrown from somewhere deep + if ( ref $e eq 'HASH' && exists $e->{status} ) { + $e->{redirects} = delete $args->{_redirects} if @{ $args->{_redirects} || []}; + return $e; + } + + # otherwise, stringify it + $e = "$e"; + $response = { + url => $url, + success => q{}, + status => 599, + reason => 'Internal Exception', + content => $e, + headers => { + 'content-type' => 'text/plain', + 'content-length' => length $e, + }, + ( @{$args->{_redirects} || []} ? (redirects => delete $args->{_redirects}) : () ), + }; + } + return $response; +} + +#pod =method www_form_urlencode +#pod +#pod $params = $http->www_form_urlencode( $data ); +#pod $response = $http->get("http://example.com/query?$params"); +#pod +#pod This method converts the key/value pairs from a data hash or array reference +#pod into a C string. The keys and values from the data +#pod reference will be UTF-8 encoded and escaped per RFC 3986. If a value is an +#pod array reference, the key will be repeated with each of the values of the array +#pod reference. If data is provided as a hash reference, the key/value pairs in the +#pod resulting string will be sorted by key and value for consistent ordering. +#pod +#pod =cut + +sub www_form_urlencode { + my ($self, $data) = @_; + (@_ == 2 && ref $data) + or _croak(q/Usage: $http->www_form_urlencode(DATAREF)/ . "\n"); + (ref $data eq 'HASH' || ref $data eq 'ARRAY') + or _croak("form data must be a hash or array reference\n"); + + my @params = ref $data eq 'HASH' ? %$data : @$data; + @params % 2 == 0 + or _croak("form data reference must have an even number of terms\n"); + + my @terms; + while( @params ) { + my ($key, $value) = splice(@params, 0, 2); + if ( ref $value eq 'ARRAY' ) { + unshift @params, map { $key => $_ } @$value; + } + else { + push @terms, join("=", map { $self->_uri_escape($_) } $key, $value); + } + } + + return join("&", (ref $data eq 'ARRAY') ? (@terms) : (sort @terms) ); +} + +#pod =method can_ssl +#pod +#pod $ok = HTTP::Tiny->can_ssl; +#pod ($ok, $why) = HTTP::Tiny->can_ssl; +#pod ($ok, $why) = $http->can_ssl; +#pod +#pod Indicates if SSL support is available. When called as a class object, it +#pod checks for the correct version of L and L. +#pod When called as an object methods, if C is true or if C +#pod is set in C, it checks that a CA file is available. +#pod +#pod In scalar context, returns a boolean indicating if SSL is available. +#pod In list context, returns the boolean and a (possibly multi-line) string of +#pod errors indicating why SSL isn't available. +#pod +#pod =cut + +sub can_ssl { + my ($self) = @_; + + my($ok, $reason) = (1, ''); + + # Need IO::Socket::SSL 1.42 for SSL_create_ctx_callback + local @INC = @INC; + pop @INC if $INC[-1] eq '.'; + unless (eval {require IO::Socket::SSL; IO::Socket::SSL->VERSION(1.42)}) { + $ok = 0; + $reason .= qq/IO::Socket::SSL 1.42 must be installed for https support\n/; + } + + # Need Net::SSLeay 1.49 for MODE_AUTO_RETRY + unless (eval {require Net::SSLeay; Net::SSLeay->VERSION(1.49)}) { + $ok = 0; + $reason .= qq/Net::SSLeay 1.49 must be installed for https support\n/; + } + + # If an object, check that SSL config lets us get a CA if necessary + if ( ref($self) && ( $self->{verify_SSL} || $self->{SSL_options}{SSL_verify_mode} ) ) { + my $handle = HTTP::Tiny::Handle->new( + SSL_options => $self->{SSL_options}, + verify_SSL => $self->{verify_SSL}, + ); + unless ( eval { $handle->_find_CA_file; 1 } ) { + $ok = 0; + $reason .= "$@"; + } + } + + wantarray ? ($ok, $reason) : $ok; +} + +#pod =method connected +#pod +#pod $host = $http->connected; +#pod ($host, $port) = $http->connected; +#pod +#pod Indicates if a connection to a peer is being kept alive, per the C +#pod option. +#pod +#pod In scalar context, returns the peer host and port, joined with a colon, or +#pod C (if no peer is connected). +#pod In list context, returns the peer host and port or an empty list (if no peer +#pod is connected). +#pod +#pod B: This method cannot reliably be used to discover whether the remote +#pod host has closed its end of the socket. +#pod +#pod =cut + +sub connected { + my ($self) = @_; + + # If a socket exists... + if ($self->{handle} && $self->{handle}{fh}) { + my $socket = $self->{handle}{fh}; + + # ...and is connected, return the peer host and port. + if ($socket->connected) { + return wantarray + ? ($socket->peerhost, $socket->peerport) + : join(':', $socket->peerhost, $socket->peerport); + } + } + return; +} + +#--------------------------------------------------------------------------# +# private methods +#--------------------------------------------------------------------------# + +my %DefaultPort = ( + http => 80, + https => 443, +); + +sub _agent { + my $class = ref($_[0]) || $_[0]; + (my $default_agent = $class) =~ s{::}{-}g; + return $default_agent . "/" . $class->VERSION; +} + +sub _request { + my ($self, $method, $url, $args) = @_; + + my ($scheme, $host, $port, $path_query, $auth) = $self->_split_url($url); + + my $request = { + method => $method, + scheme => $scheme, + host => $host, + port => $port, + host_port => ($port == $DefaultPort{$scheme} ? $host : "$host:$port"), + uri => $path_query, + headers => {}, + }; + + my $peer = $args->{peer} || $host; + + # We remove the cached handle so it is not reused in the case of redirect. + # If all is well, it will be recached at the end of _request. We only + # reuse for the same scheme, host and port + my $handle = delete $self->{handle}; + if ( $handle ) { + unless ( $handle->can_reuse( $scheme, $host, $port, $peer ) ) { + $handle->close; + undef $handle; + } + } + $handle ||= $self->_open_handle( $request, $scheme, $host, $port, $peer ); + + $self->_prepare_headers_and_cb($request, $args, $url, $auth); + $handle->write_request($request); + + my $response; + do { $response = $handle->read_response_header } + until (substr($response->{status},0,1) ne '1'); + + $self->_update_cookie_jar( $url, $response ) if $self->{cookie_jar}; + my @redir_args = $self->_maybe_redirect($request, $response, $args); + + my $known_message_length; + if ($method eq 'HEAD' || $response->{status} =~ /^[23]04/) { + # response has no message body + $known_message_length = 1; + } + else { + # Ignore any data callbacks during redirection. + my $cb_args = @redir_args ? +{} : $args; + my $data_cb = $self->_prepare_data_cb($response, $cb_args); + $known_message_length = $handle->read_body($data_cb, $response); + } + + if ( $self->{keep_alive} + && $known_message_length + && $response->{protocol} eq 'HTTP/1.1' + && ($response->{headers}{connection} || '') ne 'close' + ) { + $self->{handle} = $handle; + } + else { + $handle->close; + } + + $response->{success} = substr( $response->{status}, 0, 1 ) eq '2'; + $response->{url} = $url; + + # Push the current response onto the stack of redirects if redirecting. + if (@redir_args) { + push @{$args->{_redirects}}, $response; + return $self->_request(@redir_args, $args); + } + + # Copy the stack of redirects into the response before returning. + $response->{redirects} = delete $args->{_redirects} + if @{$args->{_redirects}}; + return $response; +} + +sub _open_handle { + my ($self, $request, $scheme, $host, $port, $peer) = @_; + + my $handle = HTTP::Tiny::Handle->new( + timeout => $self->{timeout}, + SSL_options => $self->{SSL_options}, + verify_SSL => $self->{verify_SSL}, + local_address => $self->{local_address}, + keep_alive => $self->{keep_alive} + ); + + if ($self->{_has_proxy}{$scheme} && ! grep { $host =~ /\Q$_\E$/ } @{$self->{no_proxy}}) { + return $self->_proxy_connect( $request, $handle ); + } + else { + return $handle->connect($scheme, $host, $port, $peer); + } +} + +sub _proxy_connect { + my ($self, $request, $handle) = @_; + + my @proxy_vars; + if ( $request->{scheme} eq 'https' ) { + _croak(qq{No https_proxy defined}) unless $self->{https_proxy}; + @proxy_vars = $self->_split_proxy( https_proxy => $self->{https_proxy} ); + if ( $proxy_vars[0] eq 'https' ) { + _croak(qq{Can't proxy https over https: $request->{uri} via $self->{https_proxy}}); + } + } + else { + _croak(qq{No http_proxy defined}) unless $self->{http_proxy}; + @proxy_vars = $self->_split_proxy( http_proxy => $self->{http_proxy} ); + } + + my ($p_scheme, $p_host, $p_port, $p_auth) = @proxy_vars; + + if ( length $p_auth && ! defined $request->{headers}{'proxy-authorization'} ) { + $self->_add_basic_auth_header( $request, 'proxy-authorization' => $p_auth ); + } + + $handle->connect($p_scheme, $p_host, $p_port, $p_host); + + if ($request->{scheme} eq 'https') { + $self->_create_proxy_tunnel( $request, $handle ); + } + else { + # non-tunneled proxy requires absolute URI + $request->{uri} = "$request->{scheme}://$request->{host_port}$request->{uri}"; + } + + return $handle; +} + +sub _split_proxy { + my ($self, $type, $proxy) = @_; + + my ($scheme, $host, $port, $path_query, $auth) = eval { $self->_split_url($proxy) }; + + unless( + defined($scheme) && length($scheme) && length($host) && length($port) + && $path_query eq '/' + ) { + _croak(qq{$type URL must be in format http[s]://[auth@]:/\n}); + } + + return ($scheme, $host, $port, $auth); +} + +sub _create_proxy_tunnel { + my ($self, $request, $handle) = @_; + + $handle->_assert_ssl; + + my $agent = exists($request->{headers}{'user-agent'}) + ? $request->{headers}{'user-agent'} : $self->{agent}; + + my $connect_request = { + method => 'CONNECT', + uri => "$request->{host}:$request->{port}", + headers => { + host => "$request->{host}:$request->{port}", + 'user-agent' => $agent, + } + }; + + if ( $request->{headers}{'proxy-authorization'} ) { + $connect_request->{headers}{'proxy-authorization'} = + delete $request->{headers}{'proxy-authorization'}; + } + + $handle->write_request($connect_request); + my $response; + do { $response = $handle->read_response_header } + until (substr($response->{status},0,1) ne '1'); + + # if CONNECT failed, throw the response so it will be + # returned from the original request() method; + unless (substr($response->{status},0,1) eq '2') { + die $response; + } + + # tunnel established, so start SSL handshake + $handle->start_ssl( $request->{host} ); + + return; +} + +sub _prepare_headers_and_cb { + my ($self, $request, $args, $url, $auth) = @_; + + for ($self->{default_headers}, $args->{headers}) { + next unless defined; + while (my ($k, $v) = each %$_) { + $request->{headers}{lc $k} = $v; + $request->{header_case}{lc $k} = $k; + } + } + + if (exists $request->{headers}{'host'}) { + die(qq/The 'Host' header must not be provided as header option\n/); + } + + $request->{headers}{'host'} = $request->{host_port}; + $request->{headers}{'user-agent'} ||= $self->{agent}; + $request->{headers}{'connection'} = "close" + unless $self->{keep_alive}; + + if ( defined $args->{content} ) { + if (ref $args->{content} eq 'CODE') { + $request->{headers}{'content-type'} ||= "application/octet-stream"; + $request->{headers}{'transfer-encoding'} = 'chunked' + unless $request->{headers}{'content-length'} + || $request->{headers}{'transfer-encoding'}; + $request->{cb} = $args->{content}; + } + elsif ( length $args->{content} ) { + my $content = $args->{content}; + if ( $] ge '5.008' ) { + utf8::downgrade($content, 1) + or die(qq/Wide character in request message body\n/); + } + $request->{headers}{'content-type'} ||= "application/octet-stream"; + $request->{headers}{'content-length'} = length $content + unless $request->{headers}{'content-length'} + || $request->{headers}{'transfer-encoding'}; + $request->{cb} = sub { substr $content, 0, length $content, '' }; + } + $request->{trailer_cb} = $args->{trailer_callback} + if ref $args->{trailer_callback} eq 'CODE'; + } + + ### If we have a cookie jar, then maybe add relevant cookies + if ( $self->{cookie_jar} ) { + my $cookies = $self->cookie_jar->cookie_header( $url ); + $request->{headers}{cookie} = $cookies if length $cookies; + } + + # if we have Basic auth parameters, add them + if ( length $auth && ! defined $request->{headers}{authorization} ) { + $self->_add_basic_auth_header( $request, 'authorization' => $auth ); + } + + return; +} + +sub _add_basic_auth_header { + my ($self, $request, $header, $auth) = @_; + require MIME::Base64; + $request->{headers}{$header} = + "Basic " . MIME::Base64::encode_base64($auth, ""); + return; +} + +sub _prepare_data_cb { + my ($self, $response, $args) = @_; + my $data_cb = $args->{data_callback}; + $response->{content} = ''; + + if (!$data_cb || $response->{status} !~ /^2/) { + if (defined $self->{max_size}) { + $data_cb = sub { + $_[1]->{content} .= $_[0]; + die(qq/Size of response body exceeds the maximum allowed of $self->{max_size}\n/) + if length $_[1]->{content} > $self->{max_size}; + }; + } + else { + $data_cb = sub { $_[1]->{content} .= $_[0] }; + } + } + return $data_cb; +} + +sub _update_cookie_jar { + my ($self, $url, $response) = @_; + + my $cookies = $response->{headers}->{'set-cookie'}; + return unless defined $cookies; + + my @cookies = ref $cookies ? @$cookies : $cookies; + + $self->cookie_jar->add( $url, $_ ) for @cookies; + + return; +} + +sub _validate_cookie_jar { + my ($class, $jar) = @_; + + # duck typing + for my $method ( qw/add cookie_header/ ) { + _croak(qq/Cookie jar must provide the '$method' method\n/) + unless ref($jar) && ref($jar)->can($method); + } + + return; +} + +sub _maybe_redirect { + my ($self, $request, $response, $args) = @_; + my $headers = $response->{headers}; + my ($status, $method) = ($response->{status}, $request->{method}); + $args->{_redirects} ||= []; + + if (($status eq '303' or ($status =~ /^30[1278]/ && $method =~ /^GET|HEAD$/)) + and $headers->{location} + and @{$args->{_redirects}} < $self->{max_redirect} + ) { + my $location = ($headers->{location} =~ /^\//) + ? "$request->{scheme}://$request->{host_port}$headers->{location}" + : $headers->{location} ; + return (($status eq '303' ? 'GET' : $method), $location); + } + return; +} + +sub _split_url { + my $url = pop; + + # URI regex adapted from the URI module + my ($scheme, $host, $path_query) = $url =~ m<\A([^:/?#]+)://([^/?#]*)([^#]*)> + or die(qq/Cannot parse URL: '$url'\n/); + + $scheme = lc $scheme; + $path_query = "/$path_query" unless $path_query =~ m<\A/>; + + my $auth = ''; + if ( (my $i = index $host, '@') != -1 ) { + # user:pass@host + $auth = substr $host, 0, $i, ''; # take up to the @ for auth + substr $host, 0, 1, ''; # knock the @ off the host + + # userinfo might be percent escaped, so recover real auth info + $auth =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg; + } + my $port = $host =~ s/:(\d*)\z// && length $1 ? $1 + : $scheme eq 'http' ? 80 + : $scheme eq 'https' ? 443 + : undef; + + return ($scheme, (length $host ? lc $host : "localhost") , $port, $path_query, $auth); +} + +# Date conversions adapted from HTTP::Date +my $DoW = "Sun|Mon|Tue|Wed|Thu|Fri|Sat"; +my $MoY = "Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec"; +sub _http_date { + my ($sec, $min, $hour, $mday, $mon, $year, $wday) = gmtime($_[1]); + return sprintf("%s, %02d %s %04d %02d:%02d:%02d GMT", + substr($DoW,$wday*4,3), + $mday, substr($MoY,$mon*4,3), $year+1900, + $hour, $min, $sec + ); +} + +sub _parse_http_date { + my ($self, $str) = @_; + require Time::Local; + my @tl_parts; + if ($str =~ /^[SMTWF][a-z]+, +(\d{1,2}) ($MoY) +(\d\d\d\d) +(\d\d):(\d\d):(\d\d) +GMT$/) { + @tl_parts = ($6, $5, $4, $1, (index($MoY,$2)/4), $3); + } + elsif ($str =~ /^[SMTWF][a-z]+, +(\d\d)-($MoY)-(\d{2,4}) +(\d\d):(\d\d):(\d\d) +GMT$/ ) { + @tl_parts = ($6, $5, $4, $1, (index($MoY,$2)/4), $3); + } + elsif ($str =~ /^[SMTWF][a-z]+ +($MoY) +(\d{1,2}) +(\d\d):(\d\d):(\d\d) +(?:[^0-9]+ +)?(\d\d\d\d)$/ ) { + @tl_parts = ($5, $4, $3, $2, (index($MoY,$1)/4), $6); + } + return eval { + my $t = @tl_parts ? Time::Local::timegm(@tl_parts) : -1; + $t < 0 ? undef : $t; + }; +} + +# URI escaping adapted from URI::Escape +# c.f. http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4.1 +# perl 5.6 ready UTF-8 encoding adapted from JSON::PP +my %escapes = map { chr($_) => sprintf("%%%02X", $_) } 0..255; +$escapes{' '}="+"; +my $unsafe_char = qr/[^A-Za-z0-9\-\._~]/; + +sub _uri_escape { + my ($self, $str) = @_; + if ( $] ge '5.008' ) { + utf8::encode($str); + } + else { + $str = pack("U*", unpack("C*", $str)) # UTF-8 encode a byte string + if ( length $str == do { use bytes; length $str } ); + $str = pack("C*", unpack("C*", $str)); # clear UTF-8 flag + } + $str =~ s/($unsafe_char)/$escapes{$1}/ge; + return $str; +} + +package + HTTP::Tiny::Handle; # hide from PAUSE/indexers +use strict; +use warnings; + +use Errno qw[EINTR EPIPE]; +use IO::Socket qw[SOCK_STREAM]; +use Socket qw[SOL_SOCKET SO_KEEPALIVE]; + +# PERL_HTTP_TINY_IPV4_ONLY is a private environment variable to force old +# behavior if someone is unable to boostrap CPAN from a new perl install; it is +# not intended for general, per-client use and may be removed in the future +my $SOCKET_CLASS = + $ENV{PERL_HTTP_TINY_IPV4_ONLY} ? 'IO::Socket::INET' : + eval { require IO::Socket::IP; IO::Socket::IP->VERSION(0.25) } ? 'IO::Socket::IP' : + 'IO::Socket::INET'; + +sub BUFSIZE () { 32768 } ## no critic + +my $Printable = sub { + local $_ = shift; + s/\r/\\r/g; + s/\n/\\n/g; + s/\t/\\t/g; + s/([^\x20-\x7E])/sprintf('\\x%.2X', ord($1))/ge; + $_; +}; + +my $Token = qr/[\x21\x23-\x27\x2A\x2B\x2D\x2E\x30-\x39\x41-\x5A\x5E-\x7A\x7C\x7E]/; +my $Field_Content = qr/[[:print:]]+ (?: [\x20\x09]+ [[:print:]]+ )*/x; + +sub new { + my ($class, %args) = @_; + return bless { + rbuf => '', + timeout => 60, + max_line_size => 16384, + max_header_lines => 64, + verify_SSL => 0, + SSL_options => {}, + %args + }, $class; +} + +sub timeout { + my ($self, $timeout) = @_; + if ( @_ > 1 ) { + $self->{timeout} = $timeout; + if ( $self->{fh} && $self->{fh}->can('timeout') ) { + $self->{fh}->timeout($timeout); + } + } + return $self->{timeout}; +} + +sub connect { + @_ == 5 || die(q/Usage: $handle->connect(scheme, host, port, peer)/ . "\n"); + my ($self, $scheme, $host, $port, $peer) = @_; + + if ( $scheme eq 'https' ) { + $self->_assert_ssl; + } + elsif ( $scheme ne 'http' ) { + die(qq/Unsupported URL scheme '$scheme'\n/); + } + $self->{fh} = $SOCKET_CLASS->new( + PeerHost => $peer, + PeerPort => $port, + $self->{local_address} ? + ( LocalAddr => $self->{local_address} ) : (), + Proto => 'tcp', + Type => SOCK_STREAM, + Timeout => $self->{timeout}, + ) or die(qq/Could not connect to '$host:$port': $@\n/); + + binmode($self->{fh}) + or die(qq/Could not binmode() socket: '$!'\n/); + + if ( $self->{keep_alive} ) { + unless ( defined( $self->{fh}->setsockopt( SOL_SOCKET, SO_KEEPALIVE, 1 ) ) ) { + CORE::close($self->{fh}); + die(qq/Could not set SO_KEEPALIVE on socket: '$!'\n/); + } + } + + $self->start_ssl($host) if $scheme eq 'https'; + + $self->{scheme} = $scheme; + $self->{host} = $host; + $self->{peer} = $peer; + $self->{port} = $port; + $self->{pid} = $$; + $self->{tid} = _get_tid(); + + return $self; +} + +sub start_ssl { + my ($self, $host) = @_; + + # As this might be used via CONNECT after an SSL session + # to a proxy, we shut down any existing SSL before attempting + # the handshake + if ( ref($self->{fh}) eq 'IO::Socket::SSL' ) { + unless ( $self->{fh}->stop_SSL ) { + my $ssl_err = IO::Socket::SSL->errstr; + die(qq/Error halting prior SSL connection: $ssl_err/); + } + } + + my $ssl_args = $self->_ssl_args($host); + IO::Socket::SSL->start_SSL( + $self->{fh}, + %$ssl_args, + SSL_create_ctx_callback => sub { + my $ctx = shift; + Net::SSLeay::CTX_set_mode($ctx, Net::SSLeay::MODE_AUTO_RETRY()); + }, + ); + + unless ( ref($self->{fh}) eq 'IO::Socket::SSL' ) { + my $ssl_err = IO::Socket::SSL->errstr; + die(qq/SSL connection failed for $host: $ssl_err\n/); + } +} + +sub close { + @_ == 1 || die(q/Usage: $handle->close()/ . "\n"); + my ($self) = @_; + CORE::close($self->{fh}) + or die(qq/Could not close socket: '$!'\n/); +} + +sub write { + @_ == 2 || die(q/Usage: $handle->write(buf)/ . "\n"); + my ($self, $buf) = @_; + + if ( $] ge '5.008' ) { + utf8::downgrade($buf, 1) + or die(qq/Wide character in write()\n/); + } + + my $len = length $buf; + my $off = 0; + + local $SIG{PIPE} = 'IGNORE'; + + while () { + $self->can_write + or die(qq/Timed out while waiting for socket to become ready for writing\n/); + my $r = syswrite($self->{fh}, $buf, $len, $off); + if (defined $r) { + $len -= $r; + $off += $r; + last unless $len > 0; + } + elsif ($! == EPIPE) { + die(qq/Socket closed by remote server: $!\n/); + } + elsif ($! != EINTR) { + if ($self->{fh}->can('errstr')){ + my $err = $self->{fh}->errstr(); + die (qq/Could not write to SSL socket: '$err'\n /); + } + else { + die(qq/Could not write to socket: '$!'\n/); + } + + } + } + return $off; +} + +sub read { + @_ == 2 || @_ == 3 || die(q/Usage: $handle->read(len [, allow_partial])/ . "\n"); + my ($self, $len, $allow_partial) = @_; + + my $buf = ''; + my $got = length $self->{rbuf}; + + if ($got) { + my $take = ($got < $len) ? $got : $len; + $buf = substr($self->{rbuf}, 0, $take, ''); + $len -= $take; + } + + while ($len > 0) { + $self->can_read + or die(q/Timed out while waiting for socket to become ready for reading/ . "\n"); + my $r = sysread($self->{fh}, $buf, $len, length $buf); + if (defined $r) { + last unless $r; + $len -= $r; + } + elsif ($! != EINTR) { + if ($self->{fh}->can('errstr')){ + my $err = $self->{fh}->errstr(); + die (qq/Could not read from SSL socket: '$err'\n /); + } + else { + die(qq/Could not read from socket: '$!'\n/); + } + } + } + if ($len && !$allow_partial) { + die(qq/Unexpected end of stream\n/); + } + return $buf; +} + +sub readline { + @_ == 1 || die(q/Usage: $handle->readline()/ . "\n"); + my ($self) = @_; + + while () { + if ($self->{rbuf} =~ s/\A ([^\x0D\x0A]* \x0D?\x0A)//x) { + return $1; + } + if (length $self->{rbuf} >= $self->{max_line_size}) { + die(qq/Line size exceeds the maximum allowed size of $self->{max_line_size}\n/); + } + $self->can_read + or die(qq/Timed out while waiting for socket to become ready for reading\n/); + my $r = sysread($self->{fh}, $self->{rbuf}, BUFSIZE, length $self->{rbuf}); + if (defined $r) { + last unless $r; + } + elsif ($! != EINTR) { + if ($self->{fh}->can('errstr')){ + my $err = $self->{fh}->errstr(); + die (qq/Could not read from SSL socket: '$err'\n /); + } + else { + die(qq/Could not read from socket: '$!'\n/); + } + } + } + die(qq/Unexpected end of stream while looking for line\n/); +} + +sub read_header_lines { + @_ == 1 || @_ == 2 || die(q/Usage: $handle->read_header_lines([headers])/ . "\n"); + my ($self, $headers) = @_; + $headers ||= {}; + my $lines = 0; + my $val; + + while () { + my $line = $self->readline; + + if (++$lines >= $self->{max_header_lines}) { + die(qq/Header lines exceeds maximum number allowed of $self->{max_header_lines}\n/); + } + elsif ($line =~ /\A ([^\x00-\x1F\x7F:]+) : [\x09\x20]* ([^\x0D\x0A]*)/x) { + my ($field_name) = lc $1; + if (exists $headers->{$field_name}) { + for ($headers->{$field_name}) { + $_ = [$_] unless ref $_ eq "ARRAY"; + push @$_, $2; + $val = \$_->[-1]; + } + } + else { + $val = \($headers->{$field_name} = $2); + } + } + elsif ($line =~ /\A [\x09\x20]+ ([^\x0D\x0A]*)/x) { + $val + or die(qq/Unexpected header continuation line\n/); + next unless length $1; + $$val .= ' ' if length $$val; + $$val .= $1; + } + elsif ($line =~ /\A \x0D?\x0A \z/x) { + last; + } + else { + die(q/Malformed header line: / . $Printable->($line) . "\n"); + } + } + return $headers; +} + +sub write_request { + @_ == 2 || die(q/Usage: $handle->write_request(request)/ . "\n"); + my($self, $request) = @_; + $self->write_request_header(@{$request}{qw/method uri headers header_case/}); + $self->write_body($request) if $request->{cb}; + return; +} + +# Standard request header names/case from HTTP/1.1 RFCs +my @rfc_request_headers = qw( + Accept Accept-Charset Accept-Encoding Accept-Language Authorization + Cache-Control Connection Content-Length Expect From Host + If-Match If-Modified-Since If-None-Match If-Range If-Unmodified-Since + Max-Forwards Pragma Proxy-Authorization Range Referer TE Trailer + Transfer-Encoding Upgrade User-Agent Via +); + +my @other_request_headers = qw( + Content-Encoding Content-MD5 Content-Type Cookie DNT Date Origin + X-XSS-Protection +); + +my %HeaderCase = map { lc($_) => $_ } @rfc_request_headers, @other_request_headers; + +# to avoid multiple small writes and hence nagle, you can pass the method line or anything else to +# combine writes. +sub write_header_lines { + (@_ >= 2 && @_ <= 4 && ref $_[1] eq 'HASH') || die(q/Usage: $handle->write_header_lines(headers, [header_case, prefix])/ . "\n"); + my($self, $headers, $header_case, $prefix_data) = @_; + $header_case ||= {}; + + my $buf = (defined $prefix_data ? $prefix_data : ''); + + # Per RFC, control fields should be listed first + my %seen; + for my $k ( qw/host cache-control expect max-forwards pragma range te/ ) { + next unless exists $headers->{$k}; + $seen{$k}++; + my $field_name = $HeaderCase{$k}; + my $v = $headers->{$k}; + for (ref $v eq 'ARRAY' ? @$v : $v) { + $_ = '' unless defined $_; + $buf .= "$field_name: $_\x0D\x0A"; + } + } + + # Other headers sent in arbitrary order + while (my ($k, $v) = each %$headers) { + my $field_name = lc $k; + next if $seen{$field_name}; + if (exists $HeaderCase{$field_name}) { + $field_name = $HeaderCase{$field_name}; + } + else { + if (exists $header_case->{$field_name}) { + $field_name = $header_case->{$field_name}; + } + else { + $field_name =~ s/\b(\w)/\u$1/g; + } + $field_name =~ /\A $Token+ \z/xo + or die(q/Invalid HTTP header field name: / . $Printable->($field_name) . "\n"); + $HeaderCase{lc $field_name} = $field_name; + } + for (ref $v eq 'ARRAY' ? @$v : $v) { + # unwrap a field value if pre-wrapped by user + s/\x0D?\x0A\s+/ /g; + die(qq/Invalid HTTP header field value ($field_name): / . $Printable->($_). "\n") + unless $_ eq '' || /\A $Field_Content \z/xo; + $_ = '' unless defined $_; + $buf .= "$field_name: $_\x0D\x0A"; + } + } + $buf .= "\x0D\x0A"; + return $self->write($buf); +} + +# return value indicates whether message length was defined; this is generally +# true unless there was no content-length header and we just read until EOF. +# Other message length errors are thrown as exceptions +sub read_body { + @_ == 3 || die(q/Usage: $handle->read_body(callback, response)/ . "\n"); + my ($self, $cb, $response) = @_; + my $te = $response->{headers}{'transfer-encoding'} || ''; + my $chunked = grep { /chunked/i } ( ref $te eq 'ARRAY' ? @$te : $te ) ; + return $chunked + ? $self->read_chunked_body($cb, $response) + : $self->read_content_body($cb, $response); +} + +sub write_body { + @_ == 2 || die(q/Usage: $handle->write_body(request)/ . "\n"); + my ($self, $request) = @_; + if ($request->{headers}{'content-length'}) { + return $self->write_content_body($request); + } + else { + return $self->write_chunked_body($request); + } +} + +sub read_content_body { + @_ == 3 || @_ == 4 || die(q/Usage: $handle->read_content_body(callback, response, [read_length])/ . "\n"); + my ($self, $cb, $response, $content_length) = @_; + $content_length ||= $response->{headers}{'content-length'}; + + if ( defined $content_length ) { + my $len = $content_length; + while ($len > 0) { + my $read = ($len > BUFSIZE) ? BUFSIZE : $len; + $cb->($self->read($read, 0), $response); + $len -= $read; + } + return length($self->{rbuf}) == 0; + } + + my $chunk; + $cb->($chunk, $response) while length( $chunk = $self->read(BUFSIZE, 1) ); + + return; +} + +sub write_content_body { + @_ == 2 || die(q/Usage: $handle->write_content_body(request)/ . "\n"); + my ($self, $request) = @_; + + my ($len, $content_length) = (0, $request->{headers}{'content-length'}); + while () { + my $data = $request->{cb}->(); + + defined $data && length $data + or last; + + if ( $] ge '5.008' ) { + utf8::downgrade($data, 1) + or die(qq/Wide character in write_content()\n/); + } + + $len += $self->write($data); + } + + $len == $content_length + or die(qq/Content-Length mismatch (got: $len expected: $content_length)\n/); + + return $len; +} + +sub read_chunked_body { + @_ == 3 || die(q/Usage: $handle->read_chunked_body(callback, $response)/ . "\n"); + my ($self, $cb, $response) = @_; + + while () { + my $head = $self->readline; + + $head =~ /\A ([A-Fa-f0-9]+)/x + or die(q/Malformed chunk head: / . $Printable->($head) . "\n"); + + my $len = hex($1) + or last; + + $self->read_content_body($cb, $response, $len); + + $self->read(2) eq "\x0D\x0A" + or die(qq/Malformed chunk: missing CRLF after chunk data\n/); + } + $self->read_header_lines($response->{headers}); + return 1; +} + +sub write_chunked_body { + @_ == 2 || die(q/Usage: $handle->write_chunked_body(request)/ . "\n"); + my ($self, $request) = @_; + + my $len = 0; + while () { + my $data = $request->{cb}->(); + + defined $data && length $data + or last; + + if ( $] ge '5.008' ) { + utf8::downgrade($data, 1) + or die(qq/Wide character in write_chunked_body()\n/); + } + + $len += length $data; + + my $chunk = sprintf '%X', length $data; + $chunk .= "\x0D\x0A"; + $chunk .= $data; + $chunk .= "\x0D\x0A"; + + $self->write($chunk); + } + $self->write("0\x0D\x0A"); + if ( ref $request->{trailer_cb} eq 'CODE' ) { + $self->write_header_lines($request->{trailer_cb}->()) + } + else { + $self->write("\x0D\x0A"); + } + return $len; +} + +sub read_response_header { + @_ == 1 || die(q/Usage: $handle->read_response_header()/ . "\n"); + my ($self) = @_; + + my $line = $self->readline; + + $line =~ /\A (HTTP\/(0*\d+\.0*\d+)) [\x09\x20]+ ([0-9]{3}) [\x09\x20]+ ([^\x0D\x0A]*) \x0D?\x0A/x + or die(q/Malformed Status-Line: / . $Printable->($line). "\n"); + + my ($protocol, $version, $status, $reason) = ($1, $2, $3, $4); + + die (qq/Unsupported HTTP protocol: $protocol\n/) + unless $version =~ /0*1\.0*[01]/; + + return { + status => $status, + reason => $reason, + headers => $self->read_header_lines, + protocol => $protocol, + }; +} + +sub write_request_header { + @_ == 5 || die(q/Usage: $handle->write_request_header(method, request_uri, headers, header_case)/ . "\n"); + my ($self, $method, $request_uri, $headers, $header_case) = @_; + + return $self->write_header_lines($headers, $header_case, "$method $request_uri HTTP/1.1\x0D\x0A"); +} + +sub _do_timeout { + my ($self, $type, $timeout) = @_; + $timeout = $self->{timeout} + unless defined $timeout && $timeout >= 0; + + my $fd = fileno $self->{fh}; + defined $fd && $fd >= 0 + or die(qq/select(2): 'Bad file descriptor'\n/); + + my $initial = time; + my $pending = $timeout; + my $nfound; + + vec(my $fdset = '', $fd, 1) = 1; + + while () { + $nfound = ($type eq 'read') + ? select($fdset, undef, undef, $pending) + : select(undef, $fdset, undef, $pending) ; + if ($nfound == -1) { + $! == EINTR + or die(qq/select(2): '$!'\n/); + redo if !$timeout || ($pending = $timeout - (time - $initial)) > 0; + $nfound = 0; + } + last; + } + $! = 0; + return $nfound; +} + +sub can_read { + @_ == 1 || @_ == 2 || die(q/Usage: $handle->can_read([timeout])/ . "\n"); + my $self = shift; + if ( ref($self->{fh}) eq 'IO::Socket::SSL' ) { + return 1 if $self->{fh}->pending; + } + return $self->_do_timeout('read', @_) +} + +sub can_write { + @_ == 1 || @_ == 2 || die(q/Usage: $handle->can_write([timeout])/ . "\n"); + my $self = shift; + return $self->_do_timeout('write', @_) +} + +sub _assert_ssl { + my($ok, $reason) = HTTP::Tiny->can_ssl(); + die $reason unless $ok; +} + +sub can_reuse { + my ($self,$scheme,$host,$port,$peer) = @_; + return 0 if + $self->{pid} != $$ + || $self->{tid} != _get_tid() + || length($self->{rbuf}) + || $scheme ne $self->{scheme} + || $host ne $self->{host} + || $port ne $self->{port} + || $peer ne $self->{peer} + || eval { $self->can_read(0) } + || $@ ; + return 1; +} + +# Try to find a CA bundle to validate the SSL cert, +# prefer Mozilla::CA or fallback to a system file +sub _find_CA_file { + my $self = shift(); + + my $ca_file = + defined( $self->{SSL_options}->{SSL_ca_file} ) + ? $self->{SSL_options}->{SSL_ca_file} + : $ENV{SSL_CERT_FILE}; + + if ( defined $ca_file ) { + unless ( -r $ca_file ) { + die qq/SSL_ca_file '$ca_file' not found or not readable\n/; + } + return $ca_file; + } + + local @INC = @INC; + pop @INC if $INC[-1] eq '.'; + return Mozilla::CA::SSL_ca_file() + if eval { require Mozilla::CA; 1 }; + + # cert list copied from golang src/crypto/x509/root_unix.go + foreach my $ca_bundle ( + "/etc/ssl/certs/ca-certificates.crt", # Debian/Ubuntu/Gentoo etc. + "/etc/pki/tls/certs/ca-bundle.crt", # Fedora/RHEL + "/etc/ssl/ca-bundle.pem", # OpenSUSE + "/etc/openssl/certs/ca-certificates.crt", # NetBSD + "/etc/ssl/cert.pem", # OpenBSD + "/usr/local/share/certs/ca-root-nss.crt", # FreeBSD/DragonFly + "/etc/pki/tls/cacert.pem", # OpenELEC + "/etc/certs/ca-certificates.crt", # Solaris 11.2+ + ) { + return $ca_bundle if -e $ca_bundle; + } + + die qq/Couldn't find a CA bundle with which to verify the SSL certificate.\n/ + . qq/Try installing Mozilla::CA from CPAN\n/; +} + +# for thread safety, we need to know thread id if threads are loaded +sub _get_tid { + no warnings 'reserved'; # for 'threads' + return threads->can("tid") ? threads->tid : 0; +} + +sub _ssl_args { + my ($self, $host) = @_; + + my %ssl_args; + + # This test reimplements IO::Socket::SSL::can_client_sni(), which wasn't + # added until IO::Socket::SSL 1.84 + if ( Net::SSLeay::OPENSSL_VERSION_NUMBER() >= 0x01000000 ) { + $ssl_args{SSL_hostname} = $host, # Sane SNI support + } + + if ($self->{verify_SSL}) { + $ssl_args{SSL_verifycn_scheme} = 'http'; # enable CN validation + $ssl_args{SSL_verifycn_name} = $host; # set validation hostname + $ssl_args{SSL_verify_mode} = 0x01; # enable cert validation + $ssl_args{SSL_ca_file} = $self->_find_CA_file; + } + else { + $ssl_args{SSL_verifycn_scheme} = 'none'; # disable CN validation + $ssl_args{SSL_verify_mode} = 0x00; # disable cert validation + } + + # user options override settings from verify_SSL + for my $k ( keys %{$self->{SSL_options}} ) { + $ssl_args{$k} = $self->{SSL_options}{$k} if $k =~ m/^SSL_/; + } + + return \%ssl_args; +} + +1; + +__END__ + +=pod + +=encoding UTF-8 + +=head1 NAME + +HTTP::Tiny - A small, simple, correct HTTP/1.1 client + +=head1 VERSION + +version 0.070 + +=head1 SYNOPSIS + + use HTTP::Tiny; + + my $response = HTTP::Tiny->new->get('http://example.com/'); + + die "Failed!\n" unless $response->{success}; + + print "$response->{status} $response->{reason}\n"; + + while (my ($k, $v) = each %{$response->{headers}}) { + for (ref $v eq 'ARRAY' ? @$v : $v) { + print "$k: $_\n"; + } + } + + print $response->{content} if length $response->{content}; + +=head1 DESCRIPTION + +This is a very simple HTTP/1.1 client, designed for doing simple +requests without the overhead of a large framework like L. + +It is more correct and more complete than L. It supports +proxies and redirection. It also correctly resumes after EINTR. + +If L 0.25 or later is installed, HTTP::Tiny will use it instead +of L for transparent support for both IPv4 and IPv6. + +Cookie support requires L or an equivalent class. + +=head1 METHODS + +=head2 new + + $http = HTTP::Tiny->new( %attributes ); + +This constructor returns a new HTTP::Tiny object. Valid attributes include: + +=over 4 + +=item * + +C — A user-agent string (defaults to 'HTTP-Tiny/$VERSION'). If C — ends in a space character, the default user-agent string is appended. + +=item * + +C — An instance of L — or equivalent class that supports the C and C methods + +=item * + +C — A hashref of default headers to apply to requests + +=item * + +C — The local IP address to bind to + +=item * + +C — Whether to reuse the last connection (if for the same scheme, host and port) (defaults to 1) + +=item * + +C — Maximum number of redirects allowed (defaults to 5) + +=item * + +C — Maximum response size in bytes (only when not using a data callback). If defined, responses larger than this will return an exception. + +=item * + +C — URL of a proxy server to use for HTTP connections (default is C<$ENV{http_proxy}> — if set) + +=item * + +C — URL of a proxy server to use for HTTPS connections (default is C<$ENV{https_proxy}> — if set) + +=item * + +C — URL of a generic proxy server for both HTTP and HTTPS connections (default is C<$ENV{all_proxy}> — if set) + +=item * + +C — List of domain suffixes that should not be proxied. Must be a comma-separated string or an array reference. (default is C<$ENV{no_proxy}> —) + +=item * + +C — Request timeout in seconds (default is 60) If a socket open, read or write takes longer than the timeout, an exception is thrown. + +=item * + +C — A boolean that indicates whether to validate the SSL certificate of an C — connection (default is false) + +=item * + +C — A hashref of C — options to pass through to L + +=back + +Passing an explicit C for C, C or C will +prevent getting the corresponding proxies from the environment. + +Exceptions from C, C or other errors will result in a +pseudo-HTTP status code of 599 and a reason of "Internal Exception". The +content field in the response will contain the text of the exception. + +The C parameter enables a persistent connection, but only to a +single destination scheme, host and port. Also, if any connection-relevant +attributes are modified, or if the process ID or thread ID change, the +persistent connection will be dropped. If you want persistent connections +across multiple destinations, use multiple HTTP::Tiny objects. + +See L for more on the C and C attributes. + +=head2 get|head|put|post|delete + + $response = $http->get($url); + $response = $http->get($url, \%options); + $response = $http->head($url); + +These methods are shorthand for calling C for the given method. The +URL must have unsafe characters escaped and international domain names encoded. +See C for valid options and a description of the response. + +The C field of the response will be true if the status code is 2XX. + +=head2 post_form + + $response = $http->post_form($url, $form_data); + $response = $http->post_form($url, $form_data, \%options); + +This method executes a C request and sends the key/value pairs from a +form data hash or array reference to the given URL with a C of +C. If data is provided as an array +reference, the order is preserved; if provided as a hash reference, the terms +are sorted on key and value for consistency. See documentation for the +C method for details on the encoding. + +The URL must have unsafe characters escaped and international domain names +encoded. See C for valid options and a description of the response. +Any C header or content in the options hashref will be ignored. + +The C field of the response will be true if the status code is 2XX. + +=head2 mirror + + $response = $http->mirror($url, $file, \%options) + if ( $response->{success} ) { + print "$file is up to date\n"; + } + +Executes a C request for the URL and saves the response body to the file +name provided. The URL must have unsafe characters escaped and international +domain names encoded. If the file already exists, the request will include an +C header with the modification timestamp of the file. You +may specify a different C header yourself in the C<< +$options->{headers} >> hash. + +The C field of the response will be true if the status code is 2XX +or if the status code is 304 (unmodified). + +If the file was modified and the server response includes a properly +formatted C header, the file modification time will +be updated accordingly. + +=head2 request + + $response = $http->request($method, $url); + $response = $http->request($method, $url, \%options); + +Executes an HTTP request of the given method type ('GET', 'HEAD', 'POST', +'PUT', etc.) on the given URL. The URL must have unsafe characters escaped and +international domain names encoded. + +If the URL includes a "user:password" stanza, they will be used for Basic-style +authorization headers. (Authorization headers will not be included in a +redirected request.) For example: + + $http->request('GET', 'http://Aladdin:open sesame@example.com/'); + +If the "user:password" stanza contains reserved characters, they must +be percent-escaped: + + $http->request('GET', 'http://john%40example.com:password@example.com/'); + +A hashref of options may be appended to modify the request. + +Valid options are: + +=over 4 + +=item * + +C — A hashref containing headers to include with the request. If the value for a header is an array reference, the header will be output multiple times with each value in the array. These headers over-write any default headers. + +=item * + +C — A scalar to include as the body of the request OR a code reference that will be called iteratively to produce the body of the request + +=item * + +C — A code reference that will be called if it exists to provide a hashref of trailing headers (only used with chunked transfer-encoding) + +=item * + +C — A code reference that will be called for each chunks of the response body received. + +=item * + +C — Override host resolution and force all connections to go only to a specific peer address, regardless of the URL of the request. This will include any redirections! This options should be used with extreme caution (e.g. debugging or very special circumstances). + +=back + +The C header is generated from the URL in accordance with RFC 2616. It +is a fatal error to specify C in the C option. Other headers +may be ignored or overwritten if necessary for transport compliance. + +If the C option is a code reference, it will be called iteratively +to provide the content body of the request. It should return the empty +string or undef when the iterator is exhausted. + +If the C option is the empty string, no C or +C headers will be generated. + +If the C option is provided, it will be called iteratively until +the entire response body is received. The first argument will be a string +containing a chunk of the response body, the second argument will be the +in-progress response hash reference, as described below. (This allows +customizing the action of the callback based on the C or C +received prior to the content body.) + +The C method returns a hashref containing the response. The hashref +will have the following keys: + +=over 4 + +=item * + +C — Boolean indicating whether the operation returned a 2XX status code + +=item * + +C — URL that provided the response. This is the URL of the request unless there were redirections, in which case it is the last URL queried in a redirection chain + +=item * + +C — The HTTP status code of the response + +=item * + +C — The response phrase returned by the server + +=item * + +C — The body of the response. If the response does not have any content or if a data callback is provided to consume the response body, this will be the empty string + +=item * + +C — A hashref of header fields. All header field names will be normalized to be lower case. If a header is repeated, the value will be an arrayref; it will otherwise be a scalar string containing the value + +=item * + +C If this field exists, it is an arrayref of response hash references from redirects in the same order that redirections occurred. If it does not exist, then no redirections occurred. + +=back + +On an exception during the execution of the request, the C field will +contain 599, and the C field will contain the text of the exception. + +=head2 www_form_urlencode + + $params = $http->www_form_urlencode( $data ); + $response = $http->get("http://example.com/query?$params"); + +This method converts the key/value pairs from a data hash or array reference +into a C string. The keys and values from the data +reference will be UTF-8 encoded and escaped per RFC 3986. If a value is an +array reference, the key will be repeated with each of the values of the array +reference. If data is provided as a hash reference, the key/value pairs in the +resulting string will be sorted by key and value for consistent ordering. + +=head2 can_ssl + + $ok = HTTP::Tiny->can_ssl; + ($ok, $why) = HTTP::Tiny->can_ssl; + ($ok, $why) = $http->can_ssl; + +Indicates if SSL support is available. When called as a class object, it +checks for the correct version of L and L. +When called as an object methods, if C is true or if C +is set in C, it checks that a CA file is available. + +In scalar context, returns a boolean indicating if SSL is available. +In list context, returns the boolean and a (possibly multi-line) string of +errors indicating why SSL isn't available. + +=head2 connected + + $host = $http->connected; + ($host, $port) = $http->connected; + +Indicates if a connection to a peer is being kept alive, per the C +option. + +In scalar context, returns the peer host and port, joined with a colon, or +C (if no peer is connected). +In list context, returns the peer host and port or an empty list (if no peer +is connected). + +B: This method cannot reliably be used to discover whether the remote +host has closed its end of the socket. + +=for Pod::Coverage SSL_options +agent +cookie_jar +default_headers +http_proxy +https_proxy +keep_alive +local_address +max_redirect +max_size +no_proxy +proxy +timeout +verify_SSL + +=head1 SSL SUPPORT + +Direct C connections are supported only if L 1.56 or +greater and L 1.49 or greater are installed. An exception will be +thrown if new enough versions of these modules are not installed or if the SSL +encryption fails. You can also use C utility function +that returns boolean to see if the required modules are installed. + +An C connection may be made via an C proxy that supports the CONNECT +command (i.e. RFC 2817). You may not proxy C via a proxy that itself +requires C to communicate. + +SSL provides two distinct capabilities: + +=over 4 + +=item * + +Encrypted communication channel + +=item * + +Verification of server identity + +=back + +B. + +Server identity verification is controversial and potentially tricky because it +depends on a (usually paid) third-party Certificate Authority (CA) trust model +to validate a certificate as legitimate. This discriminates against servers +with self-signed certificates or certificates signed by free, community-driven +CA's such as L. + +By default, HTTP::Tiny does not make any assumptions about your trust model, +threat level or risk tolerance. It just aims to give you an encrypted channel +when you need one. + +Setting the C attribute to a true value will make HTTP::Tiny verify +that an SSL connection has a valid SSL certificate corresponding to the host +name of the connection and that the SSL certificate has been verified by a CA. +Assuming you trust the CA, this will protect against a L. If you are +concerned about security, you should enable this option. + +Certificate verification requires a file containing trusted CA certificates. + +If the environment variable C is present, HTTP::Tiny +will try to find a CA certificate file in that location. + +If the L module is installed, HTTP::Tiny will use the CA file +included with it as a source of trusted CA's. (This means you trust Mozilla, +the author of Mozilla::CA, the CPAN mirror where you got Mozilla::CA, the +toolchain used to install it, and your operating system security, right?) + +If that module is not available, then HTTP::Tiny will search several +system-specific default locations for a CA certificate file: + +=over 4 + +=item * + +/etc/ssl/certs/ca-certificates.crt + +=item * + +/etc/pki/tls/certs/ca-bundle.crt + +=item * + +/etc/ssl/ca-bundle.pem + +=back + +An exception will be raised if C is true and no CA certificate file +is available. + +If you desire complete control over SSL connections, the C attribute +lets you provide a hash reference that will be passed through to +C, overriding any options set by HTTP::Tiny. For +example, to provide your own trusted CA file: + + SSL_options => { + SSL_ca_file => $file_path, + } + +The C attribute could also be used for such things as providing a +client certificate for authentication to a server or controlling the choice of +cipher used for the SSL connection. See L documentation for +details. + +=head1 PROXY SUPPORT + +HTTP::Tiny can proxy both C and C requests. Only Basic proxy +authorization is supported and it must be provided as part of the proxy URL: +C. + +HTTP::Tiny supports the following proxy environment variables: + +=over 4 + +=item * + +http_proxy or HTTP_PROXY + +=item * + +https_proxy or HTTPS_PROXY + +=item * + +all_proxy or ALL_PROXY + +=back + +If the C environment variable is set, then this might be a CGI +process and C would be set from the C header, which is a +security risk. If C is set, C (the upper case +variant only) is ignored. + +Tunnelling C over an C proxy using the CONNECT method is +supported. If your proxy uses C itself, you can not tunnel C +over it. + +Be warned that proxying an C connection opens you to the risk of a +man-in-the-middle attack by the proxy server. + +The C environment variable is supported in the format of a +comma-separated list of domain extensions proxy should not be used for. + +Proxy arguments passed to C will override their corresponding +environment variables. + +=head1 LIMITATIONS + +HTTP::Tiny is I with the +L: + +=over 4 + +=item * + +"Message Syntax and Routing" [RFC7230] + +=item * + +"Semantics and Content" [RFC7231] + +=item * + +"Conditional Requests" [RFC7232] + +=item * + +"Range Requests" [RFC7233] + +=item * + +"Caching" [RFC7234] + +=item * + +"Authentication" [RFC7235] + +=back + +It attempts to meet all "MUST" requirements of the specification, but does not +implement all "SHOULD" requirements. (Note: it was developed against the +earlier RFC 2616 specification and may not yet meet the revised RFC 7230-7235 +spec.) + +Some particular limitations of note include: + +=over + +=item * + +HTTP::Tiny focuses on correct transport. Users are responsible for ensuring +that user-defined headers and content are compliant with the HTTP/1.1 +specification. + +=item * + +Users must ensure that URLs are properly escaped for unsafe characters and that +international domain names are properly encoded to ASCII. See L, +L and L. + +=item * + +Redirection is very strict against the specification. Redirection is only +automatic for response codes 301, 302, 307 and 308 if the request method is +'GET' or 'HEAD'. Response code 303 is always converted into a 'GET' +redirection, as mandated by the specification. There is no automatic support +for status 305 ("Use proxy") redirections. + +=item * + +There is no provision for delaying a request body using an C header. +Unexpected C<1XX> responses are silently ignored as per the specification. + +=item * + +Only 'chunked' C is supported. + +=item * + +There is no support for a Request-URI of '*' for the 'OPTIONS' request. + +=item * + +Headers mentioned in the RFCs and some other, well-known headers are +generated with their canonical case. Other headers are sent in the +case provided by the user. Except for control headers (which are sent first), +headers are sent in arbitrary order. + +=back + +Despite the limitations listed above, HTTP::Tiny is considered +feature-complete. New feature requests should be directed to +L. + +=head1 SEE ALSO + +=over 4 + +=item * + +L - Higher level UA features for HTTP::Tiny + +=item * + +L - HTTP::Tiny wrapper with L/L compatibility + +=item * + +L - Wrap L instance in HTTP::Tiny compatible interface + +=item * + +L - Required for IPv6 support + +=item * + +L - Required for SSL support + +=item * + +L - If HTTP::Tiny isn't enough for you, this is the "standard" way to do things + +=item * + +L - Required if you want to validate SSL certificates + +=item * + +L - Required for SSL support + +=back + +=for :stopwords cpan testmatrix url annocpan anno bugtracker rt cpants kwalitee diff irc mailto metadata placeholders metacpan + +=head1 SUPPORT + +=head2 Bugs / Feature Requests + +Please report any bugs or feature requests through the issue tracker +at L. +You will be notified automatically of any progress on your issue. + +=head2 Source Code + +This is open source software. The code repository is available for +public review and contribution under the terms of the license. + +L + + git clone https://github.com/chansen/p5-http-tiny.git + +=head1 AUTHORS + +=over 4 + +=item * + +Christian Hansen + +=item * + +David Golden + +=back + +=head1 CONTRIBUTORS + +=for stopwords Alan Gardner Alessandro Ghedini A. Sinan Unur Brad Gilbert brian m. carlson Chris Nehren Weyl Claes Jakobsson Clinton Gormley Craig Berry David Golden Dean Pearce Edward Zborowski James Raspass Jeremy Mates Jess Robinson Karen Etheridge Lukas Eklund Martin J. Evans Martin-Louis Bright Mike Doherty Nicolas Rochelemagne Olaf Alders Olivier Mengué Petr Písař SkyMarshal Sören Kornetzki Steve Grazzini Syohei YOSHIDA Tatsuhiko Miyagawa Tom Hukins Tony Cook + +=over 4 + +=item * + +Alan Gardner + +=item * + +Alessandro Ghedini + +=item * + +A. Sinan Unur + +=item * + +Brad Gilbert + +=item * + +brian m. carlson + +=item * + +Chris Nehren + +=item * + +Chris Weyl + +=item * + +Claes Jakobsson + +=item * + +Clinton Gormley + +=item * + +Craig A. Berry + +=item * + +David Golden + +=item * + +Dean Pearce + +=item * + +Edward Zborowski + +=item * + +James Raspass + +=item * + +Jeremy Mates + +=item * + +Jess Robinson + +=item * + +Karen Etheridge + +=item * + +Lukas Eklund + +=item * + +Martin J. Evans + +=item * + +Martin-Louis Bright + +=item * + +Mike Doherty + +=item * + +Nicolas Rochelemagne + +=item * + +Olaf Alders + +=item * + +Olivier Mengué + +=item * + +Petr Písař + +=item * + +SkyMarshal + +=item * + +Sören Kornetzki + +=item * + +Steve Grazzini + +=item * + +Syohei YOSHIDA + +=item * + +Tatsuhiko Miyagawa + +=item * + +Tom Hukins + +=item * + +Tony Cook + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 2016 by Christian Hansen. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=cut diff --git a/csf/JSON/Tiny.pm b/csf/JSON/Tiny.pm new file mode 100644 index 0000000..a713d56 --- /dev/null +++ b/csf/JSON/Tiny.pm @@ -0,0 +1,306 @@ +package JSON::Tiny; + +# Minimalistic JSON. Adapted from Mojo::JSON. (c)2012-2023 David Oswald +# License: Artistic 2.0 license. +# http://www.perlfoundation.org/artistic_license_2_0 + +use strict; +use warnings; +use Carp 'croak'; +use Exporter 'import'; +use Scalar::Util 'blessed'; +use Encode (); + +our $VERSION = '0.56'; +our @EXPORT_OK = qw(decode_json encode_json false from_json j to_json true); + +# Literal names +# Users may override Booleans with literal 0 or 1 if desired. +our($FALSE, $TRUE) = map { bless \(my $dummy = $_), 'JSON::Tiny::_Bool' } 0, 1; + +# Escaped special character map with u2028 and u2029 +my %ESCAPE = ( + '"' => '"', + '\\' => '\\', + '/' => '/', + 'b' => "\x08", + 'f' => "\x0c", + 'n' => "\x0a", + 'r' => "\x0d", + 't' => "\x09", + 'u2028' => "\x{2028}", + 'u2029' => "\x{2029}" +); +my %REVERSE = map { $ESCAPE{$_} => "\\$_" } keys %ESCAPE; + +for(0x00 .. 0x1f) { + my $packed = pack 'C', $_; + $REVERSE{$packed} = sprintf '\u%.4X', $_ unless defined $REVERSE{$packed}; +} + +sub decode_json { + my $err = _decode(\my $value, shift); + return defined $err ? croak $err : $value; +} + +sub encode_json { Encode::encode 'UTF-8', _encode_value(shift) } + +sub false () {$FALSE} ## no critic (prototypes) + +sub from_json { + my $err = _decode(\my $value, shift, 1); + return defined $err ? croak $err : $value; +} + +sub j { + return encode_json $_[0] if ref $_[0] eq 'ARRAY' || ref $_[0] eq 'HASH'; + return decode_json $_[0]; +} + +sub to_json { _encode_value(shift) } + +sub true () {$TRUE} ## no critic (prototypes) + +sub _decode { + my $valueref = shift; + + eval { + + # Missing input + die "Missing or empty input\n" unless length( local $_ = shift ); + + # UTF-8 + $_ = eval { Encode::decode('UTF-8', $_, 1) } unless shift; + die "Input is not UTF-8 encoded\n" unless defined $_; + + # Value + $$valueref = _decode_value(); + + # Leftover data + return m/\G[\x20\x09\x0a\x0d]*\z/gc || _throw('Unexpected data'); + } ? return undef : chomp $@; + + return $@; +} + +sub _decode_array { + my @array; + until (m/\G[\x20\x09\x0a\x0d]*\]/gc) { + + # Value + push @array, _decode_value(); + + # Separator + redo if m/\G[\x20\x09\x0a\x0d]*,/gc; + + # End + last if m/\G[\x20\x09\x0a\x0d]*\]/gc; + + # Invalid character + _throw('Expected comma or right square bracket while parsing array'); + } + + return \@array; +} + +sub _decode_object { + my %hash; + until (m/\G[\x20\x09\x0a\x0d]*\}/gc) { + + # Quote + m/\G[\x20\x09\x0a\x0d]*"/gc + or _throw('Expected string while parsing object'); + + # Key + my $key = _decode_string(); + + # Colon + m/\G[\x20\x09\x0a\x0d]*:/gc + or _throw('Expected colon while parsing object'); + + # Value + $hash{$key} = _decode_value(); + + # Separator + redo if m/\G[\x20\x09\x0a\x0d]*,/gc; + + # End + last if m/\G[\x20\x09\x0a\x0d]*\}/gc; + + # Invalid character + _throw('Expected comma or right curly bracket while parsing object'); + } + + return \%hash; +} + +sub _decode_string { + my $pos = pos; + + # Extract string with escaped characters + m!\G((?:(?:[^\x00-\x1f\\"]|\\(?:["\\/bfnrt]|u[0-9a-fA-F]{4})){0,32766})*)!gc; # segfault on 5.8.x in t/20-mojo-json.t + my $str = $1; + + # Invalid character + unless (m/\G"/gc) { + _throw('Unexpected character or invalid escape while parsing string') + if m/\G[\x00-\x1f\\]/; + _throw('Unterminated string'); + } + + # Unescape popular characters + if (index($str, '\\u') < 0) { + $str =~ s!\\(["\\/bfnrt])!$ESCAPE{$1}!gs; + return $str; + } + + # Unescape everything else + my $buffer = ''; + while ($str =~ m/\G([^\\]*)\\(?:([^u])|u(.{4}))/gc) { + $buffer .= $1; + + # Popular character + if ($2) { $buffer .= $ESCAPE{$2} } + + # Escaped + else { + my $ord = hex $3; + + # Surrogate pair + if (($ord & 0xf800) == 0xd800) { + + # High surrogate + ($ord & 0xfc00) == 0xd800 + or pos($_) = $pos + pos($str), _throw('Missing high-surrogate'); + + # Low surrogate + $str =~ m/\G\\u([Dd][C-Fc-f]..)/gc + or pos($_) = $pos + pos($str), _throw('Missing low-surrogate'); + + $ord = 0x10000 + ($ord - 0xd800) * 0x400 + (hex($1) - 0xdc00); + } + + # Character + $buffer .= pack 'U', $ord; + } + } + + # The rest + return $buffer . substr $str, pos $str, length $str; +} + +sub _decode_value { + + # Leading whitespace + m/\G[\x20\x09\x0a\x0d]*/gc; + + # String + return _decode_string() if m/\G"/gc; + + # Object + return _decode_object() if m/\G\{/gc; + + # Array + return _decode_array() if m/\G\[/gc; + + # Number + my ($i) = /\G([-]?(?:0|[1-9][0-9]*)(?:\.[0-9]*)?(?:[eE][+-]?[0-9]+)?)/gc; + return 0 + $i if defined $i; + + # True + return $TRUE if m/\Gtrue/gc; + + # False + return $FALSE if m/\Gfalse/gc; + + # Null + return undef if m/\Gnull/gc; ## no critic (return) + + # Invalid character + _throw('Expected string, array, object, number, boolean or null'); +} + +sub _encode_array { + '[' . join(',', map { _encode_value($_) } @{$_[0]}) . ']'; +} + +sub _encode_object { + my $object = shift; + my @pairs = map { _encode_string($_) . ':' . _encode_value($object->{$_}) } + sort keys %$object; + return '{' . join(',', @pairs) . '}'; +} + +sub _encode_string { + my $str = shift; + $str =~ s!([\x00-\x1f\x{2028}\x{2029}\\"/])!$REVERSE{$1}!gs; + return "\"$str\""; +} + +sub _encode_value { + my $value = shift; + + # Reference + if (my $ref = ref $value) { + + # Object + return _encode_object($value) if $ref eq 'HASH'; + + # Array + return _encode_array($value) if $ref eq 'ARRAY'; + + # True or false + return $$value ? 'true' : 'false' if $ref eq 'SCALAR'; + return $value ? 'true' : 'false' if $ref eq 'JSON::Tiny::_Bool'; + + # Blessed reference with TO_JSON method + if (blessed $value && (my $sub = $value->can('TO_JSON'))) { + return _encode_value($value->$sub); + } + } + + # Null + return 'null' unless defined $value; + + + # Number (bitwise operators change behavior based on the internal value type) + + # "0" & $x will modify the flags on the "0" on perl < 5.14, so use a copy + my $zero = "0"; + # "0" & $num -> 0. "0" & "" -> "". "0" & $string -> a character. + # this maintains the internal type but speeds up the xor below. + my $check = $zero & $value; + return $value + if length $check + # 0 ^ itself -> 0 (false) + # $character ^ itself -> "\0" (true) + && !($check ^ $check) + # filter out "upgraded" strings whose numeric form doesn't strictly match + && 0 + $value eq $value + # filter out inf and nan + && $value * 0 == 0; + + # String + return _encode_string($value); +} + +sub _throw { + + # Leading whitespace + m/\G[\x20\x09\x0a\x0d]*/gc; + + # Context + my $context = 'Malformed JSON: ' . shift; + if (m/\G\z/gc) { $context .= ' before end of data' } + else { + my @lines = split "\n", substr($_, 0, pos); + $context .= ' at line ' . @lines . ', offset ' . length(pop @lines || ''); + } + + die "$context\n"; +} + +# Emulate boolean type +package JSON::Tiny::_Bool; +use overload '""' => sub { ${$_[0]} }, fallback => 1; +1; diff --git a/csf/Module/Installed/Tiny.pm b/csf/Module/Installed/Tiny.pm new file mode 100644 index 0000000..3aab233 --- /dev/null +++ b/csf/Module/Installed/Tiny.pm @@ -0,0 +1,223 @@ +package Module::Installed::Tiny; + +our $DATE = '2016-08-04'; # DATE +our $VERSION = '0.003'; # VERSION + +use strict; +use warnings; + +use Exporter qw(import); +our @EXPORT_OK = qw(module_installed module_source); + +our $SEPARATOR; +BEGIN { + if ($^O =~ /^(dos|os2)/i) { + $SEPARATOR = '\\'; + } elsif ($^O =~ /^MacOS/i) { + $SEPARATOR = ':'; + } else { + $SEPARATOR = '/'; + } +} + +sub _module_source { + my $name_pm = shift; + + for my $entry (@INC) { + next unless defined $entry; + my $ref = ref($entry); + my ($is_hook, @hook_res); + if ($ref eq 'ARRAY') { + $is_hook++; + @hook_res = $entry->[0]->($entry, $name_pm); + } elsif (UNIVERSAL::can($entry, 'INC')) { + $is_hook++; + @hook_res = $entry->INC($name_pm); + } elsif ($ref eq 'CODE') { + $is_hook++; + @hook_res = $entry->($entry, $name_pm); + } else { + my $path = "$entry$SEPARATOR$name_pm"; + if (-f $path) { + open my($fh), "<", $path + or die "Can't locate $name_pm: $path: $!"; + local $/; + return scalar <$fh>; + } + } + + if ($is_hook) { + next unless @hook_res; + my $prepend_ref = shift @hook_res if ref($hook_res[0]) eq 'SCALAR'; + my $fh = shift @hook_res if ref($hook_res[0]) eq 'GLOB'; + my $code = shift @hook_res if ref($hook_res[0]) eq 'CODE'; + my $code_state = shift @hook_res if @hook_res; + if ($fh) { + my $src = ""; + local $_; + while (!eof($fh)) { + $_ = <$fh>; + if ($code) { + $code->($code, $code_state); + } + $src .= $_; + } + $src = $$prepend_ref . $src if $prepend_ref; + return $src; + } elsif ($code) { + my $src = ""; + local $_; + while ($code->($code, $code_state)) { + $src .= $_; + } + $src = $$prepend_ref . $src if $prepend_ref; + return $src; + } + } + } + + die "Can't locate $name_pm in \@INC (\@INC contains: ".join(" ", @INC).")"; +} + +sub module_source { + my $name = shift; + + # convert Foo::Bar -> Foo/Bar.pm + my $name_pm; + if ($name =~ /\A\w+(?:::\w+)*\z/) { + ($name_pm = "$name.pm") =~ s!::!$SEPARATOR!g; + } else { + $name_pm = $name; + } + + _module_source $name_pm; +} + +sub module_installed { + my $name = shift; + + # convert Foo::Bar -> Foo/Bar.pm + my $name_pm; + if ($name =~ /\A\w+(?:::\w+)*\z/) { + ($name_pm = "$name.pm") =~ s!::!$SEPARATOR!g; + } else { + $name_pm = $name; + } + + return 1 if exists $INC{$name_pm}; + + if (eval { _module_source $name_pm; 1 }) { + 1; + } else { + 0; + } +} + +1; +# ABSTRACT: Check if a module is installed, with as little code as possible + +__END__ + +=pod + +=encoding UTF-8 + +=head1 NAME + +Module::Installed::Tiny - Check if a module is installed, with as little code as possible + +=head1 VERSION + +This document describes version 0.003 of Module::Installed::Tiny (from Perl distribution Module-Installed-Tiny), released on 2016-08-04. + +=head1 SYNOPSIS + + use Module::Installed::Tiny qw(module_installed module_source); + + # check if a module is available + if (module_installed "Foo::Bar") { + # Foo::Bar is available + } elsif (module_installed "Foo/Baz.pm") { + # Foo::Baz is available + } + + # get a module's source code, dies on failure + my $src = module_source("Foo/Baz.pm"); + +=head1 DESCRIPTION + +To check if a module is installed (available), generally the simplest way is to +try to C it: + + if (eval { require Foo::Bar; 1 }) { + # Foo::Bar is available + } + +However, this actually loads the module. There are some cases where this is not +desirable: 1) we have to check a lot of modules (actually loading the modules +will take a lot of CPU time and memory; 2) some of the modules conflict with one +another and cannot all be loaded; 3) the module is OS specific and might not +load under another OS; 4) we simply do not want to execute the module, for +security or other reasons. + +C provides a routine C which works +like Perl's C but does not actually load the module. + +This module does not require any other module except L. + +=head1 FUNCTIONS + +=head2 module_installed($name) => bool + +Check that module named C<$name> is available to load. This means that: either +the module file exists on the filesystem and searchable in C<@INC> and the +contents of the file can be retrieved, or when there is a require hook in +C<@INC>, the module's source can be retrieved from the hook. + +Note that this does not guarantee that the module can eventually be loaded +successfully, as there might be syntax or runtime errors in the module's source. +To check for that, one would need to actually load the module using C. + +=head2 module_source($name) => str + +Return module's source code, without actually loading it. Die on failure. + +=head1 HOMEPAGE + +Please visit the project's homepage at L. + +=head1 SOURCE + +Source repository is at L. + +=head1 BUGS + +Please report any bugs or feature requests on the bugtracker website L + +When submitting a bug or request, please include a test-file or a +patch to an existing test-file that illustrates the bug or desired +feature. + +=head1 SEE ALSO + +L provides C which also does what +C does, plus can check module version. It also has a couple +other knobs to customize its behavior. It's less tiny than +Module::Installed::Tiny though. + +L and L. These modules can also be used to +check if a module on the filesystem is available. They do not handle require +hooks, nor do they actually check that the module file is readable. + +=head1 AUTHOR + +perlancar + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 2016 by perlancar@cpan.org. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=cut diff --git a/csf/Net/CIDR/Lite.pm b/csf/Net/CIDR/Lite.pm new file mode 100644 index 0000000..fd6df73 --- /dev/null +++ b/csf/Net/CIDR/Lite.pm @@ -0,0 +1,685 @@ +package Net::CIDR::Lite; + +use strict; +use vars qw($VERSION); +use Carp qw(confess); + +$VERSION = '0.21'; + +my %masks; +my @fields = qw(PACK UNPACK NBITS MASKS); + +# Preloaded methods go here. + +sub new { + my $proto = shift; + my $class = ref($proto) || $proto; + my $self = bless {}, $class; + $self->add_any($_) for @_; + $self; +} + +sub add_any { + my $self = shift; + for (@_) { + tr|/|| && do { $self->add($_); next }; + tr|-|| && do { $self->add_range($_); next }; + UNIVERSAL::isa($_, 'Net::CIDR::Lite') && do { + $self->add_cidr($_); next + }; + $self->add_ip($_), next; + } + $self; +} + +sub add { + my $self = shift; + my ($ip, $mask) = split "/", shift; + $self->_init($ip) || confess "Can't determine ip format" unless %$self; + confess "Bad mask $mask" + unless $mask =~ /^\d+$/ and $mask <= $self->{NBITS}-8; + $mask += 8; + my $start = $self->{PACK}->($ip) & $self->{MASKS}[$mask] + or confess "Bad ip address: $ip"; + my $end = $self->_add_bit($start, $mask); + ++$$self{RANGES}{$start} || delete $$self{RANGES}{$start}; + --$$self{RANGES}{$end} || delete $$self{RANGES}{$end}; + $self; +} + +sub clean { + my $self = shift; + return $self unless $self->{RANGES}; + my $ranges = $$self{RANGES}; + my $total; + $$self{RANGES} = { + map { $total ? ($total+=$$ranges{$_})? () : ($_=>-1) + : do { $total+=$$ranges{$_}; ($_=>1) } + } sort keys %$ranges + }; + $self; +} + +sub list { + my $self = shift; + return unless $self->{NBITS}; + my $nbits = $$self{NBITS}; + my ($start, $total); + my @results; + for my $ip (sort keys %{$$self{RANGES}}) { + $start = $ip unless $total; + $total += $$self{RANGES}{$ip}; + unless ($total) { + while ($start lt $ip) { + my ($end, $bits); + my $sbit = $nbits-1; + # Find the position of the last 1 bit + $sbit-- while !vec($start, $sbit^7, 1) and $sbit>0; + for my $pos ($sbit+1..$nbits) { + $end = $self->_add_bit($start, $pos); + $bits = $pos-8, last if $end le $ip; + } + push @results, $self->{UNPACK}->($start) . "/$bits"; + $start = $end; + } + } + } + wantarray ? @results : \@results; +} + +sub list_range { + my $self = shift; + my ($start, $total); + my @results; + for my $ip (sort keys %{$$self{RANGES}}) { + $start = $ip unless $total; + $total += $$self{RANGES}{$ip}; + unless ($total) { + $ip = $self->_minus_one($ip); + push @results, + $self->{UNPACK}->($start) . "-" . $self->{UNPACK}->($ip); + } + } + wantarray ? @results : \@results; +} + +sub list_short_range { + my $self = shift; + + my $start; + my $total; + my @results; + + for my $ip (sort keys %{$$self{RANGES}}) { + # we begin new range when $total is zero + $start = $ip if not $total; + + # add to total (1 for start of the range or -1 for end of the range) + $total += $$self{RANGES}{$ip}; + + # in case of end of range + if (not $total) { + while ($ip gt $start) { + $ip = $self->_minus_one($ip); + + # in case of single ip not a range + if ($ip eq $start) { + push @results, + $self->{UNPACK}->($start); + next; + } + + # get the last ip octet number + my $to_octet = ( unpack('C5', $ip) )[4]; + + # next ip end will be current end masked by c subnet mask 255.255.255.0 - /24 + $ip = $ip & $self->{MASKS}[32]; + + # if the ip range is in the same c subnet + if ($ip eq ($start & $self->{MASKS}[32])) { + push @results, + $self->{UNPACK}->($start) . "-" . $to_octet; + } + # otherwise the range start is .0 (end of range masked by c subnet mask) + else { + push @results, + $self->{UNPACK}->($ip & $self->{MASKS}[32]) . "-" . $to_octet; + } + }; + } + } + wantarray ? @results : \@results; +} + +sub _init { + my $self = shift; + my $ip = shift; + my ($nbits, $pack, $unpack); + if (_pack_ipv4($ip)) { + $nbits = 40; + $pack = \&_pack_ipv4; + $unpack = \&_unpack_ipv4; + } elsif (_pack_ipv6($ip)) { + $nbits = 136; + $pack = \&_pack_ipv6; + $unpack = \&_unpack_ipv6; + } else { + return; + } + $$self{PACK} = $pack; + $$self{UNPACK} = $unpack; + $$self{NBITS} = $nbits; + $$self{MASKS} = $masks{$nbits} ||= [ + map { pack("B*", substr("1" x $_ . "0" x $nbits, 0, $nbits)) + } 0..$nbits + ]; + $$self{RANGES} = {}; + $self; +} + +sub _pack_ipv4 { + my @nums = split /\./, shift(), -1; + return unless @nums == 4; + for (@nums) { + return unless /^\d{1,3}$/ and $_ <= 255; + } + pack("CC*", 0, @nums); +} + +sub _unpack_ipv4 { + join(".", unpack("xC*", shift)); +} + +sub _pack_ipv6 { + my $ip = shift; + $ip =~ s/^::$/::0/; + return if $ip =~ /^:/ and $ip !~ s/^::/:/; + return if $ip =~ /:$/ and $ip !~ s/::$/:/; + my @nums = split /:/, $ip, -1; + return unless @nums <= 8; + my ($empty, $ipv4, $str) = (0,'',''); + for (@nums) { + return if $ipv4; + $str .= "0" x (4-length) . $_, next if /^[a-fA-F\d]{1,4}$/; + do { return if $empty++ }, $str .= "X", next if $_ eq ''; + next if $ipv4 = _pack_ipv4($_); + return; + } + return if $ipv4 and @nums > 6; + $str =~ s/X/"0" x (($ipv4 ? 25 : 33)-length($str))/e if $empty; + pack("H*", "00" . $str).$ipv4; +} + +sub _unpack_ipv6 { + _compress_ipv6(join(":", unpack("xH*", shift) =~ /..../g)), +} + +# Replace longest run of null blocks with a double colon +sub _compress_ipv6 { + my $ip = shift; + if (my @runs = $ip =~ /((?:(?:^|:)(?:0000))+:?)/g ) { + my $max = $runs[0]; + for (@runs[1..$#runs]) { + $max = $_ if length($max) < length; + } + $ip =~ s/$max/::/; + } + $ip =~ s/:0{1,3}/:/g; + $ip; +} + +# Add a single IP address +sub add_ip { + my $self = shift; + my $ip = shift; + $self->_init($ip) || confess "Can't determine ip format" unless %$self; + my $start = $self->{PACK}->($ip) or confess "Bad ip address: $ip"; + my $end = $self->_add_bit($start, $self->{NBITS}); + ++$$self{RANGES}{$start} || delete $$self{RANGES}{$start}; + --$$self{RANGES}{$end} || delete $$self{RANGES}{$end}; + $self; +} + +# Add a hyphenated range of IP addresses +sub add_range { + my $self = shift; + local $_ = shift; + my ($ip_start, $ip_end, $crud) = split /\s*-\s*/; + confess "Only one hyphen allowed in range" if defined $crud; + $self->_init($ip_start) || confess "Can't determine ip format" + unless %$self; + my $start = $self->{PACK}->($ip_start) + or confess "Bad ip address: $ip_start"; + my $end = $self->{PACK}->($ip_end) + or confess "Bad ip address: $ip_end"; + confess "Start IP is greater than end IP" if $start gt $end; + $end = $self->_add_bit($end, $$self{NBITS}); + ++$$self{RANGES}{$start} || delete $$self{RANGES}{$start}; + --$$self{RANGES}{$end} || delete $$self{RANGES}{$end}; + $self; +} + +# Add ranges from another Net::CIDR::Lite object +sub add_cidr { + my $self = shift; + my $cidr = shift; + confess "Not a CIDR object" unless UNIVERSAL::isa($cidr, 'Net::CIDR::Lite'); + unless (%$self) { + @$self{@fields} = @$cidr{@fields}; + } + $$self{RANGES}{$_} += $$cidr{RANGES}{$_} for keys %{$$cidr{RANGES}}; + $self; +} + +# Increment the ip address at the given bit position +# bit position is in range 1 to # of bits in ip +# where 1 is high order bit, # of bits is low order bit +sub _add_bit { + my $self= shift; + my $base= shift(); + my $bits= shift()-1; + while (vec($base, $bits^7, 1)) { + vec($base, $bits^7, 1) = 0; + $bits--; + return $base if $bits < 0; + } + vec($base, $bits^7, 1) = 1; + return $base; +} + +# Subtract one from an ip address +sub _minus_one { + my $self = shift; + my $nbits = $self->{NBITS}; + my $ip = shift; + $ip = ~$ip; + $ip = $self->_add_bit($ip, $nbits); + $ip = $self->_add_bit($ip, $nbits); + $self->_add_bit(~$ip, $nbits); +} + +sub find { + my $self = shift; + $self->prep_find unless $self->{FIND}; + return $self->bin_find(@_) unless @{$self->{FIND}} < $self->{PCT}; + return 0 unless $self->{PACK}; + my $this_ip = $self->{PACK}->(shift); + my $ranges = $self->{RANGES}; + my $last = -1; + for my $ip (@{$self->{FIND}}) { + last if $this_ip lt $ip; + $last = $ranges->{$ip}; + } + $last > 0; +} + +sub bin_find { + my $self = shift; + my $ip = $self->{PACK}->(shift); + $self->prep_find unless $self->{FIND}; + my $find = $self->{FIND}; + my ($start, $end) = (0, $#$find); + return unless $ip ge $find->[$start] and $ip lt $find->[$end]; + while ($end - $start > 0) { + my $mid = int(($start+$end)/2); + if ($start == $mid) { + if ($find->[$end] eq $ip) { + $start = $end; + } else { $end = $start } + } else { + ($find->[$mid] lt $ip ? $start : $end) = $mid; + } + } + $self->{RANGES}{$find->[$start]} > 0; +} + +sub prep_find { + my $self = shift; + $self->clean; + $self->{PCT} = shift || 20; + my $aref = $self->{FIND} = []; + push @$aref, $_ for sort keys %{$self->{RANGES}}; + $self; +} + +sub spanner { + Net::CIDR::Lite::Span->new(@_); +} + +sub _ranges { + sort keys %{shift->{RANGES}}; +} + +sub _packer { shift->{PACK} } +sub _unpacker { shift->{UNPACK} } + +package Net::CIDR::Lite::Span; +use Carp qw(confess); + +sub new { + my $proto = shift; + my $class = ref($proto) || $proto; + my $self = bless {RANGES=>{}}, $class; + $self->add(@_); +} + +sub add { + my $self = shift; + my $ranges = $self->{RANGES}; + if (@_ && !$self->{PACK}) { + my $cidr = $_[0]; + $cidr = Net::CIDR::Lite->new($cidr) unless ref($cidr); + $self->{PACK} = $cidr->_packer; + $self->{UNPACK} = $cidr->_unpacker; + } + while (@_) { + my ($cidr, $label) = (shift, shift); + $cidr = Net::CIDR::Lite->new($cidr) unless ref($cidr); + $cidr->clean; + for my $ip ($cidr->_ranges) { + push @{$ranges->{$ip}}, $label; + } + } + $self; +} + +sub find { + my $self = shift; + my $pack = $self->{PACK}; + my $unpack = $self->{UNPACK}; + my %results; + my $in_range; + $self->prep_find unless $self->{FIND}; + return {} unless @_; + return { map { $_ => {} } @_ } unless @{$self->{FIND}}; + return $self->bin_find(@_) if @_/@{$self->{FIND}} < $self->{PCT}; + my @ips = sort map { $pack->($_) || confess "Bad IP: $_" } @_; + my $last; + for my $ip (@{$self->{FIND}}) { + if ($ips[0] lt $ip) { + $results{$unpack->(shift @ips)} = $self->_in_range($last) + while @ips and $ips[0] lt $ip; + } + last unless @ips; + $last = $ip; + } + if (@ips) { + my $no_range = $self->_in_range({}); + $results{$unpack->(shift @ips)} = $no_range while @ips; + } + \%results; +} + +sub bin_find { + my $self = shift; + return {} unless @_; + $self->prep_find unless $self->{FIND}; + return { map { $_ => {} } @_ } unless @{$self->{FIND}}; + my $pack = $self->{PACK}; + my $unpack = $self->{UNPACK}; + my $find = $self->{FIND}; + my %results; + for my $ip ( map { $pack->($_) || confess "Bad IP: $_" } @_) { + my ($start, $end) = (0, $#$find); + $results{$unpack->($ip)} = $self->_in_range, next + unless $ip ge $find->[$start] and $ip lt $find->[$end]; + while ($start < $end) { + my $mid = int(($start+$end)/2); + if ($start == $mid) { + if ($find->[$end] eq $ip) { + $start = $end; + } else { $end = $start } + } else { + ($find->[$mid] lt $ip ? $start : $end) = $mid; + } + } + $results{$unpack->($ip)} = $self->_in_range($find->[$start]); + } + \%results; +} + +sub _in_range { + my $self = shift; + my $ip = shift || ''; + my $aref = $self->{PREPPED}{$ip} || []; + my $key = join "|", sort @$aref; + $self->{CACHE}{$key} ||= { map { $_ => 1 } @$aref }; +} + +sub prep_find { + my $self = shift; + my $pct = shift || 4; + $self->{PCT} = $pct/100; + $self->{FIND} = [ sort keys %{$self->{RANGES}} ]; + $self->{PREPPED} = {}; + $self->{CACHE} = {}; + my %cache; + my %in_range; + for my $ip (@{$self->{FIND}}) { + my $keys = $self->{RANGES}{$ip}; + $_ = !$_ for @in_range{@$keys}; + my @keys = grep $in_range{$_}, keys %in_range; + my $key_str = join "|", @keys; + $self->{PREPPED}{$ip} = $cache{$key_str} ||= \@keys; + } + $self; +} + +sub clean { + my $self = shift; + unless ($self->{PACK}) { + my $ip = shift; + my $cidr = Net::CIDR::Lite->new($ip); + return $cidr->clean($ip); + } + my $ip = $self->{PACK}->(shift) || return; + $self->{UNPACK}->($ip); +} + +1; +__END__ + +=head1 NAME + +Net::CIDR::Lite - Perl extension for merging IPv4 or IPv6 CIDR addresses + +=head1 SYNOPSIS + + use Net::CIDR::Lite; + + my $cidr = Net::CIDR::Lite->new; + $cidr->add($cidr_address); + @cidr_list = $cidr->list; + @ip_ranges = $cidr->list_range; + +=head1 DESCRIPTION + +Faster alternative to Net::CIDR when merging a large number +of CIDR address ranges. Works for IPv4 and IPv6 addresses. + +=head1 METHODS + +=over 4 + +=item new() + + $cidr = Net::CIDR::Lite->new + $cidr = Net::CIDR::Lite->new(@args) + +Creates an object to represent a list of CIDR address ranges. +No particular format is set yet; once an add method is called +with a IPv4 or IPv6 format, only that format may be added for this +cidr object. Any arguments supplied are passed to add_any() (see below). + +=item add() + + $cidr->add($cidr_address) + +Adds a CIDR address range to the list. + +=item add_range() + + $cidr->add_range($ip_range) + +Adds a hyphenated IP address range to the list. + +=item add_cidr() + + $cidr1->add_cidr($cidr2) + +Adds address ranges from one object to another object. + +=item add_ip() + + $cidr->add_ip($ip_address) + +Adds a single IP address to the list. + +=item add_any() + + $cidr->add_any($cidr_or_range_or_address); + +Determines format of range or single ip address and calls add(), +add_range(), add_cidr(), or add_ip() as appropriate. + +=item $cidr->clean() + + $cidr->clean; + +If you are going to call the list method more than once on the +same data, then for optimal performance, you can call this to +purge null nodes in overlapping ranges from the list. Boundary +nodes in contiguous ranges are automatically purged during add(). +Only useful when ranges overlap or when contiguous ranges are added +out of order. + +=item $cidr->list() + + @cidr_list = $cidr->list; + $list_ref = $cidr->list; + +Returns a list of the merged CIDR addresses. Returns an array if called +in list context, an array reference if not. + +=item $cidr->list_range() + + @cidr_list = $cidr->list_range; + $list_ref = $cidr->list_range; + +Returns a list of the merged addresses, but in hyphenated range +format. Returns an array if called in list context, an array reference +if not. + +=item $cidr->list_short_range() + + @cidr_list = $cidr->list_short_range; + $list_ref = $cidr->list_short_range; + +Returns a list of the C subnet merged addresses, in short hyphenated range +format. Returns an array if called in list context, an array reference +if not. + +Example: + + 1.1.1.1-2 + 1.1.1.5-7 + 1.1.1.254-255 + 1.1.2.0-2 + 1.1.3.5 + 1.1.3.7 + +=item $cidr->find() + + $found = $cidr->find($ip); + +Returns true if the ip address is found in the CIDR range. False if not. +Not extremely efficient, is O(n*log(n)) to sort the ranges in the +cidr object O(n) to search through the ranges in the cidr object. +The sort is cached on the first call and used in subsequent calls, +but if more addresses are added to the cidr object, prep_find() must +be called on the cidr object. + +=item $cidr->bin_find() + +Same as find(), but forces a binary search. See also prep_find. + +=item $cidr->prep_find() + + $cidr->prep_find($num); + +Caches the result of sorting the ip addresses. Implicitly called on the first +find call, but must be explicitly called if more addresses are added to +the cidr object. find() will do a binary search if the number of ranges is +greater than or equal to $num (default 20); + +=item $cidr->spanner() + + $spanner = $cidr1->spanner($label1, $cidr2, $label2, ...); + +Creates a spanner object to find out if multiple ip addresses are within +multiple labeled address ranges. May also be called as (with or without +any arguments): + + Net::CIDR::Lite::Span->new($cidr1, $label1, $cidr2, $label2, ...); + +=item $spanner->add() + + $spanner->add($cidr1, $label1, $cidr2, $label2,...); + +Adds labeled address ranges to the spanner object. The 'address range' may +be a Net::CIDR::Lite object, a single CIDR address range, a single +hyphenated IP address range, or a single IP address. + +=item $spanner->find() + + $href = $spanner->find(@ip_addresses); + +Look up which range(s) ip addresses are in, and return a lookup table +of the results, with the keys being the ip addresses, and the value a +hash reference of which address ranges the ip address is in. + +=item $spanner->bin_find() + +Same as find(), but forces a binary search. See also prep_find. + +=item $spanner->prep_find() + + $spanner->prep_find($num); + +Called implicitly the first time $spanner->find(..) is called, must be called +again if more cidr objects are added to the spanner object. Will do a +binary search if ratio of the number of ip addresses to the number of ranges +is less than $num percent (default 4). + +=item $spanner->clean() + + $clean_address = $spanner->clean($ip_address); + +Validates and returns a cleaned up version of an ip address (which is +what you will find as the key in the result from the $spanner->find(..), +not necessarily what the original argument looked like). E.g. removes +unnecessary leading zeros, removes null blocks from IPv6 +addresses, etc. + +=back + +=head1 CAVEATS + +Garbage in/garbage out. This module does do validation, but maybe +not enough to suit your needs. + +=head1 AUTHOR + +Douglas Wilson, Edougw@cpan.orgE +w/numerous hints and ideas borrowed from Tye McQueen. + +=head1 COPYRIGHT + + This module is free software; you can redistribute it and/or + modify it under the same terms as Perl itself. + +=head1 SEE ALSO + +L. + +=cut diff --git a/csf/Net/IP.pm b/csf/Net/IP.pm new file mode 100644 index 0000000..0ff27ff --- /dev/null +++ b/csf/Net/IP.pm @@ -0,0 +1,2679 @@ +# Copyright (c) 1999 - 2002 RIPE NCC +# +# All Rights Reserved +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose and without fee is hereby granted, +# provided that the above copyright notice appear in all copies and that +# both that copyright notice and this permission notice appear in +# supporting documentation, and that the name of the author not be +# used in advertising or publicity pertaining to distribution of the +# software without specific, written prior permission. +# +# THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL +# AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY +# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN +# AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +#------------------------------------------------------------------------------ +# Module Header +# Filename : IP.pm +# Purpose : Provide functions to manipulate IPv4/v6 addresses +# Author : Manuel Valente +# Date : 19991124 +# Description : +# Language Version : Perl 5 +# OSs Tested : BSDI 3.1 - Linux +# Command Line : ipcount +# Input Files : +# Output Files : +# External Programs : Math::BigInt.pm +# Problems : +# To Do : +# Comments : Based on ipv4pack.pm (Monica) and iplib.pm (Lee) +# Math::BigInt is only loaded if int functions are used +# $Id: IP.pm,v 1.23 2003/02/18 16:13:01 manuel Exp $ +#------------------------------------------------------------------------------ + +package Net::IP; + +use strict; +use Math::BigInt; + +# Global Variables definition +use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $ERROR $ERRNO + %IPv4ranges %IPv6ranges $useBigInt + $IP_NO_OVERLAP $IP_PARTIAL_OVERLAP $IP_A_IN_B_OVERLAP $IP_B_IN_A_OVERLAP $IP_IDENTICAL); + +$VERSION = '1.26'; + +require Exporter; + +@ISA = qw(Exporter); + +# Functions and variables exported in all cases +@EXPORT = qw(&Error &Errno + $IP_NO_OVERLAP $IP_PARTIAL_OVERLAP $IP_A_IN_B_OVERLAP $IP_B_IN_A_OVERLAP $IP_IDENTICAL +); + +# Functions exported on demand (with :PROC) +@EXPORT_OK = qw(&Error &Errno &ip_iptobin &ip_bintoip &ip_bintoint &ip_inttobin + &ip_get_version &ip_is_ipv4 &ip_is_ipv6 &ip_expand_address &ip_get_mask + &ip_last_address_bin &ip_splitprefix &ip_prefix_to_range + &ip_is_valid_mask &ip_bincomp &ip_binadd &ip_get_prefix_length + &ip_range_to_prefix &ip_compress_address &ip_is_overlap + &ip_get_embedded_ipv4 &ip_aggregate &ip_iptype &ip_check_prefix + &ip_reverse &ip_normalize &ip_normal_range &ip_iplengths + $IP_NO_OVERLAP $IP_PARTIAL_OVERLAP $IP_A_IN_B_OVERLAP $IP_B_IN_A_OVERLAP $IP_IDENTICAL +); + +%EXPORT_TAGS = (PROC => [@EXPORT_OK],); + +# Definition of the Ranges for IPv4 IPs +%IPv4ranges = ( + '00000000' => 'PRIVATE', # 0/8 + '00001010' => 'PRIVATE', # 10/8 + '0110010001' => 'SHARED', # 100.64/10 + '01111111' => 'LOOPBACK', # 127.0/8 + '1010100111111110' => 'LINK-LOCAL', # 169.254/16 + '101011000001' => 'PRIVATE', # 172.16/12 + '110000000000000000000000' => 'RESERVED', # 192.0.0/24 + '110000000000000000000010' => 'TEST-NET', # 192.0.2/24 + '110000000101100001100011' => '6TO4-RELAY', # 192.88.99.0/24 + '1100000010101000' => 'PRIVATE', # 192.168/16 + '110001100001001' => 'RESERVED', # 198.18/15 + '110001100011001101100100' => 'TEST-NET', # 198.51.100/24 + '110010110000000001110001' => 'TEST-NET', # 203.0.113/24 + '1110' => 'MULTICAST', # 224/4 + '1111' => 'RESERVED', # 240/4 + '11111111111111111111111111111111' => 'BROADCAST', # 255.255.255.255/32 +); + +# Definition of the Ranges for Ipv6 IPs +%IPv6ranges = ( + '00000000' => 'RESERVED', # ::/8 + ('0' x 128) => 'UNSPECIFIED', # ::/128 + ('0' x 127) . '1' => 'LOOPBACK', # ::1/128 + ('0' x 80) . ('1' x 16) => 'IPV4MAP', # ::FFFF:0:0/96 + '00000001' => 'RESERVED', # 0100::/8 + '0000000100000000' . ('0' x 48) => 'DISCARD', # 0100::/64 + '0000001' => 'RESERVED', # 0200::/7 + '000001' => 'RESERVED', # 0400::/6 + '00001' => 'RESERVED', # 0800::/5 + '0001' => 'RESERVED', # 1000::/4 + '001' => 'GLOBAL-UNICAST', # 2000::/3 + '0010000000000001' . ('0' x 16) => 'TEREDO', # 2001::/32 + '00100000000000010000000000000010' . ('0' x 16) => 'BMWG', # 2001:0002::/48 + '00100000000000010000110110111000' => 'DOCUMENTATION', # 2001:DB8::/32 + '0010000000000001000000000001' => 'ORCHID', # 2001:10::/28 + '0010000000000010' => '6TO4', # 2002::/16 + '010' => 'RESERVED', # 4000::/3 + '011' => 'RESERVED', # 6000::/3 + '100' => 'RESERVED', # 8000::/3 + '101' => 'RESERVED', # A000::/3 + '110' => 'RESERVED', # C000::/3 + '1110' => 'RESERVED', # E000::/4 + '11110' => 'RESERVED', # F000::/5 + '111110' => 'RESERVED', # F800::/6 + '1111110' => 'UNIQUE-LOCAL-UNICAST', # FC00::/7 + '111111100' => 'RESERVED', # FE00::/9 + '1111111010' => 'LINK-LOCAL-UNICAST', # FE80::/10 + '1111111011' => 'RESERVED', # FEC0::/10 + '11111111' => 'MULTICAST', # FF00::/8 +); + +# Overlap constants +$IP_NO_OVERLAP = 0; +$IP_PARTIAL_OVERLAP = 1; +$IP_A_IN_B_OVERLAP = -1; +$IP_B_IN_A_OVERLAP = -2; +$IP_IDENTICAL = -3; + +# ---------------------------------------------------------- +# OVERLOADING + +use overload ( + '+' => 'ip_add_num', + 'bool' => sub { @_ }, +); + +#------------------------------------------------------------------------------ +# Subroutine ip_num_add +# Purpose : Add an integer to an IP +# Params : Number to add +# Returns : New object or undef +# Note : Used by overloading - returns undef when +# the end of the range is reached + +sub ip_add_num { + my $self = shift; + + my ($value) = @_; + + my $ip = $self->intip + $value; + + my $last = $self->last_int; + + # Reached the end of the range ? + if ($ip > $self->last_int) { + return; + } + + my $newb = ip_inttobin($ip, $self->version); + $newb = ip_bintoip($newb, $self->version); + + my $newe = ip_inttobin($last, $self->version); + $newe = ip_bintoip($newe, $self->version); + + my $new = new Net::IP("$newb - $newe"); + + return ($new); +} + +# ----------------------------------------------------------------------------- + +#------------------------------------------------------------------------------ +# Subroutine new +# Purpose : Create an instance of an IP object +# Params : Class, IP prefix, IP version +# Returns : Object reference or undef +# Note : New just allocates a new object - set() does all the work +sub new { + my ($class, $data, $ipversion) = (@_); + + # Allocate new object + my $self = {}; + + bless($self, $class); + + # Pass everything to set() + unless ($self->set($data, $ipversion)) { + return; + } + + return $self; +} + +#------------------------------------------------------------------------------ +# Subroutine set +# Purpose : Set the IP for an IP object +# Params : Data, IP type +# Returns : 1 (success) or undef (failure) +sub set { + my $self = shift; + + my ($data, $ipversion) = @_; + + # Normalize data as received - this should return 2 IPs + my ($begin, $end) = ip_normalize($data, $ipversion) or do { + $self->{error} = $ERROR; + $self->{errno} = $ERRNO; + return; + }; + + # Those variables are set when the object methods are called + # We need to reset everything + for ( + qw(ipversion errno prefixlen binmask reverse_ip last_ip iptype + binip error ip intformat hexformat mask last_bin last_int prefix is_prefix) + ) + { + delete($self->{$_}); + } + + # Determine IP version for this object + return unless ($self->{ipversion} = $ipversion || ip_get_version($begin)); + + # Set begin IP address + $self->{ip} = $begin; + + # Set Binary IP address + return + unless ($self->{binip} = ip_iptobin($self->ip(), $self->version())); + + $self->{is_prefix} = 0; + + # Set end IP address + # If single IP: begin and end IPs are identical + $end ||= $begin; + $self->{last_ip} = $end; + + # Try to determine the IP version + my $ver = ip_get_version($end) || return; + + # Check if begin and end addresses have the same version + if ($ver != $self->version()) { + $ERRNO = 201; + $ERROR = + "Begin and End addresses have different IP versions - $begin - $end"; + $self->{errno} = $ERRNO; + $self->{error} = $ERROR; + return; + } + + # Get last binary address + return + unless ($self->{last_bin} = + ip_iptobin($self->last_ip(), $self->version())); + + # Check that End IP >= Begin IP + unless (ip_bincomp($self->binip(), 'le', $self->last_bin())) { + $ERRNO = 202; + $ERROR = "Begin address is greater than End address $begin - $end"; + $self->{errno} = $ERRNO; + $self->{error} = $ERROR; + return; + } + + # Find all prefixes (eg:/24) in the current range + my @prefixes = $self->find_prefixes() or return; + + # If there is only one prefix: + if (scalar(@prefixes) == 1) { + + # Get length of prefix + return + unless ((undef, $self->{prefixlen}) = ip_splitprefix($prefixes[0])); + + # Set prefix boolean var + # This value is 1 if the IP range only contains a single /nn prefix + $self->{is_prefix} = 1; + } + + # If the range is a single prefix: + if ($self->{is_prefix}) { + + # Set mask property + $self->{binmask} = ip_get_mask($self->prefixlen(), $self->version()); + + # Check that the mask is valid + unless ( + ip_check_prefix( + $self->binip(), $self->prefixlen(), $self->version() + ) + ) + { + $self->{error} = $ERROR; + $self->{errno} = $ERRNO; + return; + } + } + + return ($self); +} + +sub print { + my $self = shift; + + if ($self->{is_prefix}) { + return ($self->short() . '/' . $self->prefixlen()); + } + else { + return (sprintf("%s - %s", $self->ip(), $self->last_ip())); + } +} + +#------------------------------------------------------------------------------ +# Subroutine error +# Purpose : Return the current error message +# Returns : Error string +sub error { + my $self = shift; + return $self->{error}; +} + +#------------------------------------------------------------------------------ +# Subroutine errno +# Purpose : Return the current error number +# Returns : Error number +sub errno { + my $self = shift; + return $self->{errno}; +} + +#------------------------------------------------------------------------------ +# Subroutine binip +# Purpose : Return the IP as a binary string +# Returns : binary string +sub binip { + my $self = shift; + return $self->{binip}; +} + +#------------------------------------------------------------------------------ +# Subroutine prefixlen +# Purpose : Get the IP prefix length +# Returns : prefix length +sub prefixlen { + my $self = shift; + return $self->{prefixlen}; +} + +#------------------------------------------------------------------------------ +# Subroutine version +# Purpose : Return the IP version +# Returns : IP version +sub version { + my $self = shift; + return $self->{ipversion}; +} + +#------------------------------------------------------------------------------ +# Subroutine version +# Purpose : Return the IP in quad format +# Returns : IP string +sub ip { + my $self = shift; + return $self->{ip}; +} + +#------------------------------------------------------------------------------ +# Subroutine is_prefix +# Purpose : Check if range of IPs is a prefix +# Returns : boolean +sub is_prefix { + my $self = shift; + return $self->{is_prefix}; +} + +#------------------------------------------------------------------------------ +# Subroutine binmask +# Purpose : Return the binary mask of an IP prefix +# Returns : Binary mask (as string) +sub binmask { + my $self = shift; + return $self->{binmask}; +} + +#------------------------------------------------------------------------------ +# Subroutine size +# Purpose : Return the number of addresses contained in an IP object +# Returns : Number of addresses +sub size { + my $self = shift; + + my $size = new Math::BigInt($self->last_int); + $size->badd(1); + + $size->bsub($self->intip); +} + +# All the following functions work the same way: the method is just a frontend +# to the real function. When the real function is called, the output is cached +# so that next time the same function is called,the frontend function directly +# returns the result. + +#------------------------------------------------------------------------------ +# Subroutine intip +# Purpose : Return the IP in integer format +# Returns : Integer +sub intip { + my $self = shift; + + return ($self->{intformat}) if defined($self->{intformat}); + + my $int = ip_bintoint($self->binip()); + + if (!$int) { + $self->{error} = $ERROR; + $self->{errno} = $ERRNO; + return; + } + + $self->{intformat} = $int; + + return ($int); +} + +#------------------------------------------------------------------------------ +# Subroutine hexip +# Purpose : Return the IP in hex format +# Returns : hex string +sub hexip { + my $self = shift; + return $self->{'hexformat'} if(defined($self->{'hexformat'})); + $self->{'hexformat'} = $self->intip->as_hex(); + return $self->{'hexformat'}; +} + +#------------------------------------------------------------------------------ +# Subroutine hexmask +# Purpose : Return the mask back in hex +# Returns : hex string +sub hexmask { + my $self = shift; + + return $self->{hexmask} if(defined($self->{hexmask})); + + my $intmask = ip_bintoint($self->binmask); + + $self->{'hexmask'} = $intmask->as_hex(); + + return ($self->{'hexmask'}); +} + +#------------------------------------------------------------------------------ +# Subroutine prefix +# Purpose : Return the Prefix (n.n.n.n/s) +# Returns : IP Prefix +sub prefix { + my $self = shift; + + if (not $self->is_prefix()) { + $self->{error} = "IP range $self->{ip} is not a Prefix."; + $self->{errno} = 209; + return; + } + + return ($self->{prefix}) if defined($self->{prefix}); + + my $prefix = $self->ip() . '/' . $self->prefixlen(); + + if (!$prefix) { + $self->{error} = $ERROR; + $self->{errno} = $ERRNO; + return; + } + + $self->{prefix} = $prefix; + + return ($prefix); +} + +#------------------------------------------------------------------------------ +# Subroutine mask +# Purpose : Return the IP mask in quad format +# Returns : Mask (string) +sub mask { + my $self = shift; + + if (not $self->is_prefix()) { + $self->{error} = "IP range $self->{ip} is not a Prefix."; + $self->{errno} = 209; + return; + } + + return ($self->{mask}) if defined($self->{mask}); + + my $mask = ip_bintoip($self->binmask(), $self->version()); + + if (!$mask) { + $self->{error} = $ERROR; + $self->{errno} = $ERRNO; + return; + } + + $self->{mask} = $mask; + + return ($mask); +} + +#------------------------------------------------------------------------------ +# Subroutine short +# Purpose : Get the short format of an IP address or a Prefix +# Returns : short format IP or undef +sub short { + my $self = shift; + + my $r; + + if ($self->version == 6) { + $r = ip_compress_address($self->ip(), $self->version()); + } + else { + $r = ip_compress_v4_prefix($self->ip(), $self->prefixlen()); + } + + if (!defined($r)) { + $self->{error} = $ERROR; + $self->{errno} = $ERRNO; + return; + } + + return ($r); +} + +#------------------------------------------------------------------------------ +# Subroutine iptype +# Purpose : Return the type of an IP +# Returns : Type or undef (failure) +sub iptype { + my ($self) = shift; + + return ($self->{iptype}) if defined($self->{iptype}); + + my $type = ip_iptype($self->binip(), $self->version()); + + if (!$type) { + $self->{error} = $ERROR; + $self->{errno} = $ERRNO; + return; + } + + $self->{iptype} = $type; + + return ($type); +} + +#------------------------------------------------------------------------------ +# Subroutine reverse_ip +# Purpose : Return the Reverse IP +# Returns : Reverse IP or undef(failure) +sub reverse_ip { + my ($self) = shift; + + if (not $self->is_prefix()) { + $self->{error} = "IP range $self->{ip} is not a Prefix."; + $self->{errno} = 209; + return; + } + + return ($self->{reverse_ip}) if defined($self->{reverse_ip}); + + my $rev = ip_reverse($self->ip(), $self->prefixlen(), $self->version()); + + if (!$rev) { + $self->{error} = $ERROR; + $self->{errno} = $ERRNO; + return; + } + + $self->{reverse_ip} = $rev; + + return ($rev); +} + +#------------------------------------------------------------------------------ +# Subroutine last_bin +# Purpose : Get the last IP of a range in binary format +# Returns : Last binary IP or undef (failure) +sub last_bin { + my ($self) = shift; + + return ($self->{last_bin}) if defined($self->{last_bin}); + + my $last; + + if ($self->is_prefix()) { + $last = + ip_last_address_bin($self->binip(), $self->prefixlen(), + $self->version()); + } + else { + $last = ip_iptobin($self->last_ip(), $self->version()); + } + + if (!$last) { + $self->{error} = $ERROR; + $self->{errno} = $ERRNO; + return; + } + + $self->{last_bin} = $last; + + return ($last); +} + +#------------------------------------------------------------------------------ +# Subroutine last_int +# Purpose : Get the last IP of a range in integer format +# Returns : Last integer IP or undef (failure) +sub last_int { + my ($self) = shift; + + return ($self->{last_int}) if defined($self->{last_int}); + + my $last_bin = $self->last_bin() or return; + + my $last_int = ip_bintoint($last_bin, $self->version()) or return; + + $self->{last_int} = $last_int; + + return ($last_int); +} + +#------------------------------------------------------------------------------ +# Subroutine last_ip +# Purpose : Get the last IP of a prefix in IP format +# Returns : IP or undef (failure) +sub last_ip { + my ($self) = shift; + + return ($self->{last_ip}) if defined($self->{last_ip}); + + my $last = ip_bintoip($self->last_bin(), $self->version()); + + if (!$last) { + $self->{error} = $ERROR; + $self->{errno} = $ERRNO; + return; + } + + $self->{last_ip} = $last; + + return ($last); +} + +#------------------------------------------------------------------------------ +# Subroutine find_prefixes +# Purpose : Get all prefixes in the range defined by two IPs +# Params : IP +# Returns : List of prefixes or undef (failure) +sub find_prefixes { + my ($self) = @_; + + my @list = + ip_range_to_prefix($self->binip(), $self->last_bin(), $self->version()); + + if (!scalar(@list)) { + $self->{error} = $ERROR; + $self->{errno} = $ERRNO; + return; + } + + return (@list); +} + +#------------------------------------------------------------------------------ +# Subroutine bincomp +# Purpose : Compare two IPs +# Params : Operation, IP to compare +# Returns : 1 (True), 0 (False) or undef (problem) +# Comments : Operation can be lt, le, gt, ge +sub bincomp { + my ($self, $op, $other) = @_; + + my $a = ip_bincomp($self->binip(), $op, $other->binip()); + + unless (defined $a) { + $self->{error} = $ERROR; + $self->{errno} = $ERRNO; + return; + } + + return ($a); +} + +#------------------------------------------------------------------------------ +# Subroutine binadd +# Purpose : Add two IPs +# Params : IP to add +# Returns : New IP object or undef (failure) +sub binadd { + my ($self, $other) = @_; + + my $ip = ip_binadd($self->binip(), $other->binip()); + + if (!$ip) { + $self->{error} = $ERROR; + $self->{errno} = $ERRNO; + return; + } + + my $new = new Net::IP(ip_bintoip($ip, $self->version())) or return; + + return ($new); +} + +#------------------------------------------------------------------------------ +# Subroutine aggregate +# Purpose : Aggregate (append) two IPs +# Params : IP to add +# Returns : New IP object or undef (failure) +sub aggregate { + my ($self, $other) = @_; + + my $r = ip_aggregate( + $self->binip(), $self->last_bin(), + $other->binip(), $other->last_bin(), + $self->version() + ); + + if (!$r) { + $self->{error} = $ERROR; + $self->{errno} = $ERRNO; + return; + } + + return (new Net::IP($r)); +} + +#------------------------------------------------------------------------------ +# Subroutine overlaps +# Purpose : Check if two prefixes overlap +# Params : Prefix to compare +# Returns : $NO_OVERLAP (no overlap) +# $IP_PARTIAL_OVERLAP (overlap) +# $IP_A_IN_B_OVERLAP (range1 is included in range2) +# $IP_B_IN_A_OVERLAP (range2 is included in range1) +# $IP_IDENTICAL (range1 == range2) +# or undef (problem) + +sub overlaps { + my ($self, $other) = @_; + + my $r = ip_is_overlap( + $self->binip(), $self->last_bin(), + $other->binip(), $other->last_bin() + ); + + if (!defined($r)) { + $self->{error} = $ERROR; + $self->{errno} = $ERRNO; + return; + } + + return ($r); +} + +#------------------------------------------------------------------------------ +# Subroutine auth +# Purpose : Return Authority information from IP::Authority +# Params : IP object +# Returns : Authority Source + +sub auth { + my ($self) = shift; + + return ($self->{auth}) if defined($self->{auth}); + + my $auth = ip_auth($self->ip, $self->version); + + if (!$auth) { + $self->{error} = $ERROR; + $self->{errno} = $ERRNO; + return; + } + + $self->{auth} = $auth; + + return ($self->{auth}); +} + +#------------------------------ PROCEDURAL INTERFACE -------------------------- +#------------------------------------------------------------------------------ +# Subroutine Error +# Purpose : Return the ERROR string +# Returns : string +sub Error { + return ($ERROR); +} + +#------------------------------------------------------------------------------ +# Subroutine Error +# Purpose : Return the ERRNO value +# Returns : number +sub Errno { + return ($ERRNO); +} + +#------------------------------------------------------------------------------ +# Subroutine ip_iplengths +# Purpose : Get the length in bits of an IP from its version +# Params : IP version +# Returns : Number of bits + +sub ip_iplengths { + my ($version) = @_; + + if ($version == 4) { + return (32); + } + elsif ($version == 6) { + return (128); + } + else { + return; + } +} + +#------------------------------------------------------------------------------ +# Subroutine ip_iptobin +# Purpose : Transform an IP address into a bit string +# Params : IP address, IP version +# Returns : bit string on success, undef otherwise +sub ip_iptobin { + my ($ip, $ipversion) = @_; + + # v4 -> return 32-bit array + if ($ipversion == 4) { + return unpack('B32', pack('C4C4C4C4', split(/\./, $ip))); + } + + # Strip ':' + $ip =~ s/://g; + + # Check size + unless (length($ip) == 32) { + $ERROR = "Bad IP address $ip"; + $ERRNO = 102; + return; + } + + # v6 -> return 128-bit array + return unpack('B128', pack('H32', $ip)); +} + +#------------------------------------------------------------------------------ +# Subroutine ip_bintoip +# Purpose : Transform a bit string into an IP address +# Params : bit string, IP version +# Returns : IP address on success, undef otherwise +sub ip_bintoip { + my ($binip, $ip_version) = @_; + + # Define normal size for address + my $len = ip_iplengths($ip_version); + + if ($len < length($binip)) { + $ERROR = "Invalid IP length for binary IP $binip\n"; + $ERRNO = 189; + return; + } + + # Prepend 0s if address is less than normal size + $binip = '0' x ($len - length($binip)) . $binip; + + # IPv4 + if ($ip_version == 4) { + return join '.', unpack('C4C4C4C4', pack('B32', $binip)); + } + + # IPv6 + return join(':', unpack('H4H4H4H4H4H4H4H4', pack('B128', $binip))); +} + +#------------------------------------------------------------------------------ +# Subroutine ip_bintoint +# Purpose : Transform a bit string into an Integer +# Params : bit string +# Returns : BigInt +sub ip_bintoint { + my $binip = shift; + + # $n is the increment, $dec is the returned value + my ($n, $dec) = (Math::BigInt->new(1), Math::BigInt->new(0)); + + + # Reverse the bit string + foreach (reverse(split '', $binip)) { + + # If the nth bit is 1, add 2**n to $dec + $_ and $dec += $n; + $n *= 2; + } + + # Strip leading + sign + $dec =~ s/^\+//; + return $dec; +} + +#------------------------------------------------------------------------------ +# Subroutine ip_inttobin +# Purpose : Transform a BigInt into a bit string +# Comments : sets warnings (-w) off. +# This is necessary because Math::BigInt is not compliant +# Params : BigInt, IP version +# Returns : bit string +sub ip_inttobin { + + my $dec = Math::BigInt->new(shift); + + # Find IP version + my $ip_version = shift; + + unless ($ip_version) { + $ERROR = "Cannot determine IP version for $dec"; + $ERRNO = 101; + return; + } + + my $binip = $dec->as_bin(); + $binip =~ s/^0b//; + + # Define normal size for address + my $len = ip_iplengths($ip_version); + + # Prepend 0s if result is less than normal size + $binip = '0' x ($len - length($binip)) . $binip; + + + return $binip; + +} + +#------------------------------------------------------------------------------ +# Subroutine ip_get_version +# Purpose : Get an IP version +# Params : IP address +# Returns : 4, 6, 0(don't know) +sub ip_get_version { + my $ip = shift; + + # If the address does not contain any ':', maybe it's IPv4 + $ip !~ /:/ and ip_is_ipv4($ip) and return '4'; + + # Is it IPv6 ? + ip_is_ipv6($ip) and return '6'; + + return; +} + +#------------------------------------------------------------------------------ +# Subroutine ip_is_ipv4 +# Purpose : Check if an IP address is version 4 +# Params : IP address +# Returns : 1 (yes) or 0 (no) +sub ip_is_ipv4 { + my $ip = shift; + + # Check for invalid chars + unless ($ip =~ m/^[\d\.]+$/) { + $ERROR = "Invalid chars in IP $ip"; + $ERRNO = 107; + return 0; + } + + if ($ip =~ m/^\./) { + $ERROR = "Invalid IP $ip - starts with a dot"; + $ERRNO = 103; + return 0; + } + + if ($ip =~ m/\.$/) { + $ERROR = "Invalid IP $ip - ends with a dot"; + $ERRNO = 104; + return 0; + } + + # Single Numbers are considered to be IPv4 + if ($ip =~ m/^(\d+)$/ and $1 < 256) { return 1 } + + # Count quads + my $n = ($ip =~ tr/\./\./); + + # IPv4 must have from 1 to 4 quads + unless ($n >= 0 and $n < 4) { + $ERROR = "Invalid IP address $ip"; + $ERRNO = 105; + return 0; + } + + # Check for empty quads + if ($ip =~ m/\.\./) { + $ERROR = "Empty quad in IP address $ip"; + $ERRNO = 106; + return 0; + } + + foreach (split /\./, $ip) { + + # Check for invalid quads + unless ($_ >= 0 and $_ < 256) { + $ERROR = "Invalid quad in IP address $ip - $_"; + $ERRNO = 107; + return 0; + } + } + return 1; +} + +#------------------------------------------------------------------------------ +# Subroutine ip_is_ipv6 +# Purpose : Check if an IP address is version 6 +# Params : IP address +# Returns : 1 (yes) or 0 (no) +sub ip_is_ipv6 { + my $ip = shift; + + # Count octets + my $n = ($ip =~ tr/:/:/); + return 0 unless ($n > 0 and $n < 8); + + # $k is a counter + my $k; + + foreach (split /:/, $ip) { + $k++; + + # Empty octet ? + next if ($_ eq ''); + + # Normal v6 octet ? + next if (/^[a-f\d]{1,4}$/i); + + # Last octet - is it IPv4 ? + if ( ($k == $n + 1) && ip_is_ipv4($_) ) { + $n++; # ipv4 is two octets + next; + } + + $ERROR = "Invalid IP address $ip"; + $ERRNO = 108; + return 0; + } + + # Does the IP address start with : ? + if ($ip =~ m/^:[^:]/) { + $ERROR = "Invalid address $ip (starts with :)"; + $ERRNO = 109; + return 0; + } + + # Does the IP address finish with : ? + if ($ip =~ m/[^:]:$/) { + $ERROR = "Invalid address $ip (ends with :)"; + $ERRNO = 110; + return 0; + } + + # Does the IP address have more than one '::' pattern ? + if ($ip =~ s/:(?=:)/:/g > 1) { + $ERROR = "Invalid address $ip (More than one :: pattern)"; + $ERRNO = 111; + return 0; + } + + # number of octets + if ($n != 7 && $ip !~ /::/) { + $ERROR = "Invalid number of octets $ip"; + $ERRNO = 112; + return 0; + } + + # valid IPv6 address + return 1; +} + +#------------------------------------------------------------------------------ +# Subroutine ip_expand_address +# Purpose : Expand an address from compact notation +# Params : IP address, IP version +# Returns : expanded IP address or undef on failure +sub ip_expand_address { + my ($ip, $ip_version) = @_; + + unless ($ip_version) { + $ERROR = "Cannot determine IP version for $ip"; + $ERRNO = 101; + return; + } + + # v4 : add .0 for missing quads + if ($ip_version == 4) { + my @quads = split /\./, $ip; + + # check number of quads + if (scalar(@quads) > 4) { + $ERROR = "Not a valid IPv address $ip"; + $ERRNO = 102; + return; + } + my @clean_quads = (0, 0, 0, 0); + + foreach my $q (reverse @quads) { + + #check quad data + if ($q !~ m/^\d{1,3}$/) { + $ERROR = "Not a valid IPv4 address $ip"; + $ERRNO = 102; + return; + } + + # build clean ipv4 + unshift(@clean_quads, $q + 1 - 1); + } + + return (join '.', @clean_quads[ 0 .. 3 ]); + } + + # Keep track of :: + my $num_of_double_colon = ($ip =~ s/::/:!:/g); + if ($num_of_double_colon > 1) { + $ERROR = "Too many :: in ip"; + $ERRNO = 102; + return; + } + + # IP as an array + my @ip = split /:/, $ip; + + # Number of octets + my $num = scalar(@ip); + + foreach (0 .. (scalar(@ip) - 1)) { + + # Embedded IPv4 + if ($ip[$_] =~ /\./) { + + # Expand Ipv4 address + # Convert into binary + # Convert into hex + # Keep the last two octets + + $ip[$_] = substr( ip_bintoip( ip_iptobin( ip_expand_address($ip[$_], 4), 4), 6), -9); + + # Has an error occured here ? + return unless (defined($ip[$_])); + + # $num++ because we now have one more octet: + # IPv4 address becomes two octets + $num++; + next; + } + + # Add missing trailing 0s + $ip[$_] = ('0' x (4 - length($ip[$_]))) . $ip[$_]; + } + + # Now deal with '::' ('000!') + foreach (0 .. (scalar(@ip) - 1)) { + + # Find the pattern + next unless ($ip[$_] eq '000!'); + + # @empty is the IP address 0 + my @empty = map { $_ = '0' x 4 } (0 .. 7); + + # Replace :: with $num '0000' octets + $ip[$_] = join ':', @empty[ 0 .. 8 - $num ]; + last; + } + + return (lc(join ':', @ip)); +} + +#------------------------------------------------------------------------------ +# Subroutine ip_get_mask +# Purpose : Get IP mask from prefix length. +# Params : Prefix length, IP version +# Returns : Binary Mask +sub ip_get_mask { + my ($len, $ip_version) = @_; + + unless ($ip_version) { + $ERROR = "Cannot determine IP version"; + $ERRNO = 101; + return; + } + + my $size = ip_iplengths($ip_version); + + # mask is $len 1s plus the rest as 0s + return (('1' x $len) . ('0' x ($size - $len))); +} + +#------------------------------------------------------------------------------ +# Subroutine ip_last_address_bin +# Purpose : Return the last binary address of a range +# Params : First binary IP, prefix length, IP version +# Returns : Binary IP +sub ip_last_address_bin { + my ($binip, $len, $ip_version) = @_; + + unless ($ip_version) { + $ERROR = "Cannot determine IP version"; + $ERRNO = 101; + return; + } + + my $size = ip_iplengths($ip_version); + + # Find the part of the IP address which will not be modified + $binip = substr($binip, 0, $len); + + # Fill with 1s the variable part + return ($binip . ('1' x ($size - length($binip)))); +} + +#------------------------------------------------------------------------------ +# Subroutine ip_splitprefix +# Purpose : Split a prefix into IP and prefix length +# Comments : If it was passed a simple IP, it just returns it +# Params : Prefix +# Returns : IP, optionnaly length of prefix +sub ip_splitprefix { + my $prefix = shift; + + # Find the '/' + return unless ($prefix =~ m!^([^/]+?)(/\d+)?$!); + + my ($ip, $len) = ($1, $2); + + defined($len) and $len =~ s!/!!; + + return ($ip, $len); +} + +#------------------------------------------------------------------------------ +# Subroutine ip_prefix_to_range +# Purpose : Get a range from a prefix +# Params : IP, Prefix length, IP version +# Returns : First IP, last IP +sub ip_prefix_to_range { + my ($ip, $len, $ip_version) = @_; + + unless ($ip_version) { + $ERROR = "Cannot determine IP version"; + $ERRNO = 101; + return; + } + + # Expand the first IP address + $ip = ip_expand_address($ip, $ip_version); + + # Turn into a binary + # Get last address + # Turn into an IP + my $binip = ip_iptobin($ip, $ip_version) or return; + + return unless (ip_check_prefix($binip, $len, $ip_version)); + + my $lastip = ip_last_address_bin($binip, $len, $ip_version) or return; + return unless ($lastip = ip_bintoip($lastip, $ip_version)); + + return ($ip, $lastip); +} + +#------------------------------------------------------------------------------ +# Subroutine ip_is_valid_mask +# Purpose : Check the validity of an IP mask (11110000) +# Params : Mask +# Returns : 1 or undef (invalid) +sub ip_is_valid_mask { + my ($mask, $ip_version) = @_; + + unless ($ip_version) { + $ERROR = "Cannot determine IP version for $mask"; + $ERRNO = 101; + return; + } + + my $len = ip_iplengths($ip_version); + + if (length($mask) != $len) { + $ERROR = "Invalid mask length for $mask"; + $ERRNO = 150; + return; + } + + # The mask should be of the form 111110000000 + unless ($mask =~ m/^1*0*$/) { + $ERROR = "Invalid mask $mask"; + $ERRNO = 151; + return; + } + + return 1; +} + +#------------------------------------------------------------------------------ +# Subroutine ip_bincomp +# Purpose : Compare binary Ips with <, >, <=, >= +# Comments : Operators are lt(<), le(<=), gt(>), and ge(>=) +# Params : First binary IP, operator, Last binary Ip +# Returns : 1 (yes), 0 (no), or undef (problem) +sub ip_bincomp { + my ($begin, $op, $end) = @_; + + my ($b, $e); + + if ($op =~ /^l[te]$/) # Operator is lt or le + { + ($b, $e) = ($end, $begin); + } + elsif ($op =~ /^g[te]$/) # Operator is gt or ge + { + ($b, $e) = ($begin, $end); + } + else { + $ERROR = "Invalid Operator $op\n"; + $ERRNO = 131; + return; + } + + # le or ge -> return 1 if IPs are identical + return (1) if ($op =~ /e/ and ($begin eq $end)); + + # Check IP sizes + unless (length($b) eq length($e)) { + $ERROR = "IP addresses of different length\n"; + $ERRNO = 130; + return; + } + + my $c; + + # Foreach bit + for (0 .. length($b) - 1) { + + # substract the two bits + $c = substr($b, $_, 1) - substr($e, $_, 1); + + # Check the result + return (1) if ($c == 1); + return (0) if ($c == -1); + } + + # IPs are identical + return 0; +} + +#------------------------------------------------------------------------------ +# Subroutine ip_binadd +# Purpose : Add two binary IPs +# Params : First binary IP, Last binary Ip +# Returns : Binary sum or undef (problem) +sub ip_binadd { + my ($b, $e) = @_; + + # Check IP length + unless (length($b) eq length($e)) { + $ERROR = "IP addresses of different length\n"; + $ERRNO = 130; + return; + } + + # Reverse the two IPs + $b = scalar(reverse $b); + $e = scalar(reverse $e); + + my ($carry, $result, $c) = (0); + + # Foreach bit (reversed) + for (0 .. length($b) - 1) { + + # add the two bits plus the carry + $c = substr($b, $_, 1) + substr($e, $_, 1) + $carry; + $carry = 0; + + # sum = 0 => $c = 0, $carry = 0 + # sum = 1 => $c = 1, $carry = 0 + # sum = 2 => $c = 0, $carry = 1 + # sum = 3 => $c = 1, $carry = 1 + if ($c > 1) { + $c -= 2; + $carry = 1; + } + + $result .= $c; + } + + # Reverse result + return scalar(reverse($result)); +} + +#------------------------------------------------------------------------------ +# Subroutine ip_get_prefix_length +# Purpose : Get the prefix length for a given range of IPs +# Params : First binary IP, Last binary IP +# Returns : Length of prefix or undef (problem) +sub ip_get_prefix_length { + my ($bin1, $bin2) = @_; + + # Check length of IPs + unless (length($bin1) eq length($bin2)) { + $ERROR = "IP addresses of different length\n"; + $ERRNO = 130; + return; + } + + # reverse IPs + $bin1 = scalar(reverse $bin1); + $bin2 = scalar(reverse $bin2); + + # foreach bit + for (0 .. length($bin1) - 1) { + + # If bits are equal it means we have reached the longest prefix + return ("$_") if (substr($bin1, $_, 1) eq substr($bin2, $_, 1)); + + } + + # Return 32 (IPv4) or 128 (IPv6) + return length($bin1); +} + +#------------------------------------------------------------------------------ +# Subroutine ip_range_to_prefix +# Purpose : Return all prefixes between two IPs +# Params : First IP, Last IP, IP version +# Returns : List of Prefixes or undef (problem) +sub ip_range_to_prefix { + my ($binip, $endbinip, $ip_version) = @_; + + unless ($ip_version) { + $ERROR = "Cannot determine IP version"; + $ERRNO = 101; + return; + } + + unless (length($binip) eq length($endbinip)) { + $ERROR = "IP addresses of different length\n"; + $ERRNO = 130; + return; + } + + my ($len, $nbits, $current, $add, @prefix); + + # 1 in binary + my $one = ('0' x (ip_iplengths($ip_version) - 1)) . '1'; + + # While we have not reached the last IP + while (ip_bincomp($binip, 'le', $endbinip) == 1) { + + # Find all 0s at the end + if ($binip =~ m/(0+)$/) { + + # nbits = nb of 0 bits + $nbits = length($1); + } + else { + $nbits = 0; + } + + do { + $current = $binip; + $add = '1' x $nbits; + + # Replace $nbits 0s with 1s + $current =~ s/0{$nbits}$/$add/; + $nbits--; + + # Decrease $nbits if $current >= $endbinip + } while (ip_bincomp($current, 'le', $endbinip) != 1); + + # Find Prefix length + $len = + (ip_iplengths($ip_version)) - ip_get_prefix_length($binip, $current); + + # Push prefix in list + push(@prefix, ip_bintoip($binip, $ip_version) . "/$len"); + + # Add 1 to current IP + $binip = ip_binadd($current, $one); + + # Exit if IP is 32/128 1s + last if ($current =~ m/^1+$/); + } + + return (@prefix); +} + +#------------------------------------------------------------------------------ +# Subroutine ip_compress_v4_prefix +# Purpose : Compress an IPv4 Prefix +# Params : IP, Prefix length +# Returns : Compressed IP - ie: 194.5 +sub ip_compress_v4_prefix { + my ($ip, $len) = @_; + + my @quads = split /\./, $ip; + + my $qlen = int(($len - 1) / 8); + + $qlen = 0 if ($qlen < 0); + + my $newip = join '.', @quads[ 0 .. $qlen ]; + + return ($newip); +} + +#------------------------------------------------------------------------------ +# Subroutine ip_compress_address +# Purpose : Compress an IPv6 address +# Params : IP, IP version +# Returns : Compressed IP or undef (problem) +sub ip_compress_address { + my ($ip, $ip_version) = @_; + + unless ($ip_version) { + $ERROR = "Cannot determine IP version for $ip"; + $ERRNO = 101; + return; + } + + # Just return if IP is IPv4 + return ($ip) if ($ip_version == 4); + + # already compressed addresses must be expanded first + $ip = ip_expand_address( $ip, $ip_version); + + # Remove leading 0s: 0034 -> 34; 0000 -> 0 + $ip =~ s/ + (^|:) # Find beginning or ':' -> $1 + 0+ # 1 or several 0s + (?= # Look-ahead + [a-fA-F\d]+ # One or several Hexs + (?::|$)) # ':' or end + /$1/gx; + + my $reg = ''; + + # Find the longuest :0:0: sequence + while ( + $ip =~ m/ + ((?:^|:) # Find beginning or ':' -> $1 + 0(?::0)+ # 0 followed by 1 or several ':0' + (?::|$)) # ':' or end + /gx + ) + { + $reg = $1 if (length($reg) < length($1)); + } + + # Replace sequence by '::' + $ip =~ s/$reg/::/ if ($reg ne ''); + + return $ip; +} + +#------------------------------------------------------------------------------ +# Subroutine ip_is_overlap +# Purpose : Check if two ranges overlap +# Params : Four binary IPs (begin of range 1,end1,begin2,end2) +# Returns : $NO_OVERLAP (no overlap) +# $IP_PARTIAL_OVERLAP (overlap) +# $IP_A_IN_B_OVERLAP (range1 is included in range2) +# $IP_B_IN_A_OVERLAP (range2 is included in range1) +# $IP_IDENTICAL (range1 == range2) +# or undef (problem) + +sub ip_is_overlap { + my ($b1, $e1, $b2, $e2) = (@_); + + my $swap; + $swap = 0; + + unless ((length($b1) eq length($e1)) + and (length($b2) eq length($e2)) + and (length($b1) eq length($b2))) + { + $ERROR = "IP addresses of different length\n"; + $ERRNO = 130; + return; + } + + # begin1 <= end1 ? + unless (ip_bincomp($b1, 'le', $e1) == 1) { + $ERROR = "Invalid range $b1 - $e1"; + $ERRNO = 140; + return; + } + + # begin2 <= end2 ? + unless (ip_bincomp($b2, 'le', $e2) == 1) { + $ERROR = "Invalid range $b2 - $e2"; + $ERRNO = 140; + return; + } + + # b1 == b2 ? + if ($b1 eq $b2) { + + # e1 == e2 + return ($IP_IDENTICAL) if ($e1 eq $e2); + + # e1 < e2 ? + return ( + ip_bincomp($e1, 'lt', $e2) + ? $IP_A_IN_B_OVERLAP + : $IP_B_IN_A_OVERLAP + ); + } + + # e1 == e2 ? + if ($e1 eq $e2) { + + # b1 < b2 + return ( + ip_bincomp($b1, 'lt', $b2) + ? $IP_B_IN_A_OVERLAP + : $IP_A_IN_B_OVERLAP + ); + } + + # b1 < b2 + if ((ip_bincomp($b1, 'lt', $b2) == 1)) { + + # e1 < b2 + return ($IP_NO_OVERLAP) if (ip_bincomp($e1, 'lt', $b2) == 1); + + # e1 < e2 ? + return ( + ip_bincomp($e1, 'lt', $e2) + ? $IP_PARTIAL_OVERLAP + : $IP_B_IN_A_OVERLAP + ); + } + else # b1 > b2 + { + + # e2 < b1 + return ($IP_NO_OVERLAP) if (ip_bincomp($e2, 'lt', $b1) == 1); + + # e2 < e1 ? + return ( + ip_bincomp($e2, 'lt', $e1) + ? $IP_PARTIAL_OVERLAP + : $IP_A_IN_B_OVERLAP + ); + } +} + +#------------------------------------------------------------------------------ +# Subroutine get_embedded_ipv4 +# Purpose : Get an IPv4 embedded in an IPv6 address +# Params : IPv6 +# Returns : IPv4 or undef (not found) +sub ip_get_embedded_ipv4 { + my $ipv6 = shift; + + my @ip = split /:/, $ipv6; + + # Bugfix by Norbert Koch + return unless (@ip); + + # last octet should be ipv4 + return ($ip[-1]) if (ip_is_ipv4($ip[-1])); + + return; +} + +#------------------------------------------------------------------------------ +# Subroutine aggregate +# Purpose : Aggregate 2 ranges +# Params : 1st range (1st IP, Last IP), last range (1st IP, last IP), +# IP version +# Returns : prefix or undef (invalid) +sub ip_aggregate { + my ($binbip1, $bineip1, $binbip2, $bineip2, $ip_version) = @_; + + unless ($ip_version) { + $ERROR = "Cannot determine IP version for $binbip1"; + $ERRNO = 101; + return; + } + + # Bin 1 + my $one = (('0' x (ip_iplengths($ip_version) - 1)) . '1'); + + # $eip1 + 1 = $bip2 ? + unless (ip_binadd($bineip1, $one) eq $binbip2) { + $ERROR = "Ranges not contiguous - $bineip1 - $binbip2"; + $ERRNO = 160; + return; + } + + # Get ranges + my @prefix = ip_range_to_prefix($binbip1, $bineip2, $ip_version); + + # There should be only one range + return if scalar(@prefix) < 1; + + if (scalar(@prefix) > 1) { + $ERROR = "$binbip1 - $bineip2 is not a single prefix"; + $ERRNO = 161; + return; + } + return ($prefix[0]); + +} + +#------------------------------------------------------------------------------ +# Subroutine ip_iptype +# Purpose : Return the type of an IP (Public, Private, Reserved) +# Params : IP to test, IP version +# Returns : type or undef (invalid) +sub ip_iptype { + my ($ip, $ip_version) = @_; + + # handle known ip versions + return ip_iptypev4($ip) if $ip_version == 4; + return ip_iptypev6($ip) if $ip_version == 6; + + # unsupported ip version + $ERROR = "IP version $ip not supported"; + $ERRNO = 180; + return; +} + +#------------------------------------------------------------------------------ +# Subroutine ip_iptypev4 +# Purpose : Return the type of an IP (Public, Private, Reserved) +# Params : IP to test, IP version +# Returns : type or undef (invalid) +sub ip_iptypev4 { + my ($ip) = @_; + + # check ip + if ($ip !~ m/^[01]{1,32}$/) { + $ERROR = "$ip is not a binary IPv4 address $ip"; + $ERRNO = 180; + return; + } + + # see if IP is listed + foreach (sort { length($b) <=> length($a) } keys %IPv4ranges) { + return ($IPv4ranges{$_}) if ($ip =~ m/^$_/); + } + + # not listed means IP is public + return 'PUBLIC'; +} + +#------------------------------------------------------------------------------ +# Subroutine ip_iptypev6 +# Purpose : Return the type of an IP (Public, Private, Reserved) +# Params : IP to test, IP version +# Returns : type or undef (invalid) +sub ip_iptypev6 { + my ($ip) = @_; + + # check ip + if ($ip !~ m/^[01]{1,128}$/) { + $ERROR = "$ip is not a binary IPv6 address"; + $ERRNO = 180; + return; + } + + foreach (sort { length($b) <=> length($a) } keys %IPv6ranges) { + return ($IPv6ranges{$_}) if ($ip =~ m/^$_/); + } + + # How did we get here? All IPv6 addresses should match + $ERROR = "Cannot determine type for $ip"; + $ERRNO = 180; + return; +} + +#------------------------------------------------------------------------------ +# Subroutine ip_check_prefix +# Purpose : Check the validity of a prefix +# Params : binary IP, length of prefix, IP version +# Returns : 1 or undef (invalid) +sub ip_check_prefix { + my ($binip, $len, $ipversion) = (@_); + + # Check if len is longer than IP + if ($len > length($binip)) { + $ERROR = + "Prefix length $len is longer than IP address (" + . length($binip) . ")"; + $ERRNO = 170; + return; + } + + my $rest = substr($binip, $len); + + # Check if last part of the IP (len part) has only 0s + unless ($rest =~ /^0*$/) { + $ERROR = "Invalid prefix $binip/$len"; + $ERRNO = 171; + return; + } + + # Check if prefix length is correct + unless (length($rest) + $len == ip_iplengths($ipversion)) { + $ERROR = "Invalid prefix length /$len"; + $ERRNO = 172; + return; + } + + return 1; +} + +#------------------------------------------------------------------------------ +# Subroutine ip_reverse +# Purpose : Get a reverse name from a prefix +# Comments : From Lee's iplib.pm +# Params : IP, length of prefix, IP version +# Returns : Reverse name or undef (error) +sub ip_reverse { + my ($ip, $len, $ip_version) = (@_); + + $ip_version ||= ip_get_version($ip); + unless ($ip_version) { + $ERROR = "Cannot determine IP version for $ip"; + $ERRNO = 101; + return; + } + + if ($ip_version == 4) { + my @quads = split /\./, $ip; + my $no_quads = ($len / 8); + + my @reverse_quads = reverse @quads; + + while (@reverse_quads and $reverse_quads[0] == 0) { + shift(@reverse_quads); + } + + return join '.', @reverse_quads, 'in-addr', 'arpa.'; + } + elsif ($ip_version == 6) { + my @rev_groups = reverse split /:/, ip_expand_address($ip, 6); + my @result; + + foreach (@rev_groups) { + my @revhex = reverse split //; + push @result, @revhex; + } + + # This takes the zone above if it's not exactly on a nibble + my $first_nibble_index = $len ? 32 - (int($len / 4)) : 0; + return join '.', @result[ $first_nibble_index .. $#result ], 'ip6', + 'arpa.'; + } +} + +#------------------------------------------------------------------------------ +# Subroutine ip_normalize +# Purpose : Normalize data to a range of IP addresses +# Params : IP or prefix or range +# Returns : ip1, ip2 (if range) or undef (error) +sub ip_normalize { + my ($data) = shift; + + my $ipversion; + + my ($len, $ip, $ip2, $real_len, $first, $last, $curr_bin, $addcst, $clen); + + # Prefix + if ($data =~ m!^(\S+?)(/\S+)$!) { + ($ip, $len) = ($1, $2); + + return unless ($ipversion = ip_get_version($ip)); + return unless ($ip = ip_expand_address($ip, $ipversion)); + return unless ($curr_bin = ip_iptobin($ip, $ipversion)); + + my $one = '0' x (ip_iplengths($ipversion) - 1) . '1'; + + while ($len) { + last unless ($len =~ s!^/(\d+)(\,|$)!!); + + $clen = $1; + $addcst = length($2) > 0; + + return unless (ip_check_prefix($curr_bin, $clen, $ipversion)); + + return + unless ($curr_bin = + ip_last_address_bin($curr_bin, $clen, $ipversion)); + + if ($addcst) { + return unless ($curr_bin = ip_binadd($curr_bin, $one)); + } + } + + return ($ip, ip_bintoip($curr_bin, $ipversion)); + } + + # Range + elsif ($data =~ /^(.+?)\s*\-\s*(.+)$/) { + ($ip, $ip2) = ($1, $2); + + return unless ($ipversion = ip_get_version($ip)); + + return unless ($ip = ip_expand_address($ip, $ipversion)); + return unless ($ip2 = ip_expand_address($ip2, $ipversion)); + + return ($ip, $ip2); + } + + # IP + Number + elsif ($data =~ /^(.+?)\s+\+\s+(.+)$/) { + ($ip, $len) = ($1, $2); + + return unless ($ipversion = ip_get_version($ip)); + return unless ($ip = ip_expand_address($ip, $ipversion)); + + my ($bin_ip); + return unless ($bin_ip = ip_iptobin($ip, $ipversion)); + + return unless ($len = ip_inttobin($len, $ipversion)); + + return unless ($ip2 = ip_binadd($bin_ip, $len)); + return unless ($ip2 = ip_bintoip($ip2, $ipversion)); + + return ($ip, $ip2); + } + + # Single IP + else { + $ip = $data; + + return unless ($ipversion = ip_get_version($ip)); + + return unless ($ip = ip_expand_address($ip, $ipversion)); + + return $ip; + } +} + +#------------------------------------------------------------------------------ +# Subroutine normal_range +# Purpose : Return the normalized format of a range +# Params : IP or prefix or range +# Returns : "ip1 - ip2" or undef (error) +sub ip_normal_range { + my ($data) = shift; + + my ($ip1, $ip2) = ip_normalize($data); + + return unless ($ip1); + + $ip2 ||= $ip1; + + return ("$ip1 - $ip2"); +} + +#------------------------------------------------------------------------------ +# Subroutine ip_auth +# Purpose : Get Authority information from IP::Authority Module +# Comments : Requires IP::Authority +# Params : IP, length of prefix +# Returns : Reverse name or undef (error) +sub ip_auth { + my ($ip, $ip_version) = (@_); + + unless ($ip_version) { + $ERROR = "Cannot determine IP version for $ip"; + $ERRNO = 101; + die; + return; + } + + if ($ip_version != 4) { + + $ERROR = "Cannot get auth information: Not an IPv4 address"; + $ERRNO = 308; + die; + return; + } + + require IP::Authority; + + my $reg = new IP::Authority; + + return ($reg->inet_atoauth($ip)); +} + +1; + +__END__ +=encoding utf8 +=head1 NAME + +Net::IP - Perl extension for manipulating IPv4/IPv6 addresses + +=head1 SYNOPSIS + + use Net::IP; + + my $ip = new Net::IP ('193.0.1/24') or die (Net::IP::Error()); + print ("IP : ".$ip->ip()."\n"); + print ("Sho : ".$ip->short()."\n"); + print ("Bin : ".$ip->binip()."\n"); + print ("Int : ".$ip->intip()."\n"); + print ("Mask: ".$ip->mask()."\n"); + print ("Last: ".$ip->last_ip()."\n"); + print ("Len : ".$ip->prefixlen()."\n"); + print ("Size: ".$ip->size()."\n"); + print ("Type: ".$ip->iptype()."\n"); + print ("Rev: ".$ip->reverse_ip()."\n"); + +=head1 DESCRIPTION + +This module provides functions to deal with B addresses. The module +can be used as a class, allowing the user to instantiate IP objects, which can +be single IP addresses, prefixes, or ranges of addresses. There is also a +procedural way of accessing most of the functions. Most subroutines can take +either B or B addresses transparently. + +=head1 OBJECT-ORIENTED INTERFACE + +=head2 Object Creation + +A Net::IP object can be created from a single IP address: + + $ip = new Net::IP ('193.0.1.46') || die ... + +Or from a Classless Prefix (a /24 prefix is equivalent to a C class): + + $ip = new Net::IP ('195.114.80/24') || die ... + +Or from a range of addresses: + + $ip = new Net::IP ('20.34.101.207 - 201.3.9.99') || die ... + +Or from a address plus a number: + + $ip = new Net::IP ('20.34.10.0 + 255') || die ... + +The new() function accepts IPv4 and IPv6 addresses: + + $ip = new Net::IP ('dead:beef::/32') || die ... + +Optionnaly, the function can be passed the version of the IP. Otherwise, it +tries to guess what the version is (see B<_is_ipv4()> and B<_is_ipv6()>). + + $ip = new Net::IP ('195/8',4); # Class A + +=head1 OBJECT METHODS + +Most of these methods are front-ends for the real functions, which use a +procedural interface. Most functions return undef on failure, and a true +value on success. A detailed description of the procedural interface is +provided below. + +=head2 set + +Set an IP address in an existing IP object. This method has the same +functionality as the new() method, except that it reuses an existing object to +store the new IP. + +C<$ip-Eset('130.23.1/24',4);> + +Like new(), set() takes two arguments - a string used to build an IP address, +prefix, or range, and optionally, the IP version of the considered address. + +It returns an IP object on success, and undef on failure. + +=head2 error + +Return the current object error string. The error string is set whenever one +of the methods produces an error. Also, a global, class-wide B +function is avaliable. + +Cerror());> + +=head2 errno + +Return the current object error number. The error number is set whenever one +of the methods produces an error. Also, a global B<$ERRNO> variable is set +when an error is produced. + +Cerrno());> + +=head2 ip + +Return the IP address (or first IP of the prefix or range) in quad format, as +a string. + +Cip());> + +=head2 binip + +Return the IP address as a binary string of 0s and 1s. + +Cbinip());> + +=head2 prefixlen + +Return the length in bits of the current prefix. + +Cprefixlen());> + +=head2 version + +Return the version of the current IP object (4 or 6). + +Cversion());> + +=head2 size + +Return the number of IP addresses in the current prefix or range. +Use of this function requires Math::BigInt. + +Csize());> + +=head2 binmask + +Return the binary mask of the current prefix, if applicable. + +Cbinmask());> + +=head2 mask + +Return the mask in quad format of the current prefix. + +Cmask());> + +=head2 prefix + +Return the full prefix (ip+prefix length) in quad (standard) format. + +Cprefix());> + +=head2 print + +Print the IP object (IP/Prefix or First - Last) + +Cprint());> + +=head2 intip + +Convert the IP in integer format and return it as a Math::BigInt object. + +Cintip());> + +=head2 hexip + +Return the IP in hex format + +Chexip());> + +=head2 hexmask + +Return the mask in hex format + +Chexmask());> + +=head2 short + +Return the IP in short format: + IPv4 addresses: 194.5/16 + IPv6 addresses: ab32:f000:: + + +Cshort());> + +=head2 iptype + +Return the IP Type - this describes the type of an IP (Public, Private, +Reserved, etc.) See procedural interface ip_iptype for more details. + +Ciptype());> + +=head2 reverse_ip + +Return the reverse IP for a given IP address (in.addr. format). + +Creserve_ip());> + +=head2 last_ip + +Return the last IP of a prefix/range in quad format. + +Clast_ip());> + +=head2 last_bin + +Return the last IP of a prefix/range in binary format. + +Clast_bin());> + +=head2 last_int + +Return the last IP of a prefix/range in integer format. + +Clast_int());> + +=head2 find_prefixes + +This function finds all the prefixes that can be found between the two +addresses of a range. The function returns a list of prefixes. + +C<@list = $ip-Efind_prefixes($other_ip));> + +=head2 bincomp + +Binary comparaison of two IP objects. The function takes an operation +and an IP object as arguments. It returns a boolean value. + +The operation can be one of: +lt: less than (smaller than) +le: smaller or equal to +gt: greater than +ge: greater or equal to + +Cbincomp('lt',$ip2) {...}> + +=head2 binadd + +Binary addition of two IP objects. The value returned is an IP object. + +Cbinadd($ip2);> + +=head2 aggregate + +Aggregate 2 IPs - Append one range/prefix of IPs to another. The last address +of the first range must be the one immediately preceding the first address of +the second range. A new IP object is returned. + +Caggregate($ip2);> + +=head2 overlaps + +Check if two IP ranges/prefixes overlap each other. The value returned by the +function should be one of: + $IP_PARTIAL_OVERLAP (ranges overlap) + $IP_NO_OVERLAP (no overlap) + $IP_A_IN_B_OVERLAP (range2 contains range1) + $IP_B_IN_A_OVERLAP (range1 contains range2) + $IP_IDENTICAL (ranges are identical) + undef (problem) + +Coverlaps($ip2)==$IP_A_IN_B_OVERLAP) {...};> + + +=head2 looping + +The C<+> operator is overloaded in order to allow looping though a whole +range of IP addresses: + + my $ip = new Net::IP ('195.45.6.7 - 195.45.6.19') || die; + # Loop + do { + print $ip->ip(), "\n"; + } while (++$ip); + + + +The ++ operator returns undef when the last address of the range is reached. + + +=head2 auth + +Return IP authority information from the IP::Authority module + +C<$auth = ip->auth ();> + +Note: IPv4 only + + +=head1 PROCEDURAL INTERFACE + +These functions do the real work in the module. Like the OO methods, +most of these return undef on failure. In order to access error codes +and strings, instead of using $ip-Eerror() and $ip-Eerrno(), use the +global functions C and C. + +The functions of the procedural interface are not exported by default. In +order to import these functions, you need to modify the use statement for +the module: + +C + +=head2 Error + +Returns the error string corresponding to the last error generated in the +module. This is also useful for the OO interface, as if the new() function +fails, we cannot call $ip-Eerror() and so we have to use Error(). + +warn Error(); + +=head2 Errno + +Returns a numeric error code corresponding to the error string returned by +Error. + +=head2 ip_iptobin + +Transform an IP address into a bit string. + + Params : IP address, IP version + Returns : binary IP string on success, undef otherwise + +C<$binip = ip_iptobin ($ip,6);> + +=head2 ip_bintoip + +Transform a bit string into an IP address + + Params : binary IP, IP version + Returns : IP address on success, undef otherwise + +C<$ip = ip_bintoip ($binip,6);> + +=head2 ip_bintoint + +Transform a bit string into a BigInt. + + Params : binary IP + Returns : BigInt + +C<$bigint = new Math::BigInt (ip_bintoint($binip));> + +=head2 ip_inttobin + +Transform a BigInt into a bit string. +I: sets warnings (C<-w>) off. This is necessary because Math::BigInt +is not compliant. + + Params : BigInt, IP version + Returns : binary IP + +C<$binip = ip_inttobin ($bigint);> + +=head2 ip_get_version + +Try to guess the IP version of an IP address. + + Params : IP address + Returns : 4, 6, undef(unable to determine) + +C<$version = ip_get_version ($ip)> + +=head2 ip_is_ipv4 + +Check if an IP address is of type 4. + + Params : IP address + Returns : 1 (yes) or 0 (no) + +C + +=head2 ip_is_ipv6 + +Check if an IP address is of type 6. + + Params : IP address + Returns : 1 (yes) or 0 (no) + +C + +=head2 ip_expand_address + +Expand an IP address from compact notation. + + Params : IP address, IP version + Returns : expanded IP address or undef on failure + +C<$ip = ip_expand_address ($ip,4);> + +=head2 ip_get_mask + +Get IP mask from prefix length. + + Params : Prefix length, IP version + Returns : Binary Mask + +C<$mask = ip_get_mask ($len,6);> + +=head2 ip_last_address_bin + +Return the last binary address of a prefix. + + Params : First binary IP, prefix length, IP version + Returns : Binary IP + +C<$lastbin = ip_last_address_bin ($ip,$len,6);> + +=head2 ip_splitprefix + +Split a prefix into IP and prefix length. +If it was passed a simple IP, it just returns it. + + Params : Prefix + Returns : IP, optionnaly length of prefix + +C<($ip,$len) = ip_splitprefix ($prefix)> + +=head2 ip_prefix_to_range + +Get a range of IPs from a prefix. + + Params : Prefix, IP version + Returns : First IP, last IP + +C<($ip1,$ip2) = ip_prefix_to_range ($prefix,6);> + +=head2 ip_bincomp + +Compare binary Ips with <, >, <=, >=. + Operators are lt(<), le(<=), gt(>), and ge(>=) + + Params : First binary IP, operator, Last binary IP + Returns : 1 (yes), 0 (no), or undef (problem) + +C + +=head2 ip_binadd + +Add two binary IPs. + + Params : First binary IP, Last binary IP + Returns : Binary sum or undef (problem) + +C<$binip = ip_binadd ($bin1,$bin2);> + +=head2 ip_get_prefix_length + +Get the prefix length for a given range of 2 IPs. + + Params : First binary IP, Last binary IP + Returns : Length of prefix or undef (problem) + +C<$len = ip_get_prefix_length ($ip1,$ip2);> + +=head2 ip_range_to_prefix + +Return all prefixes between two IPs. + + Params : First IP (binary format), Last IP (binary format), IP version + Returns : List of Prefixes or undef (problem) + +The prefixes returned have the form q.q.q.q/nn. + +C<@prefix = ip_range_to_prefix ($ip1,$ip2,6);> + + +=head2 ip_compress_v4_prefix + +Compress an IPv4 Prefix. + + Params : IP, Prefix length + Returns : Compressed Prefix + +C<$ip = ip_compress_v4_prefix ($ip, $len);> + + +=head2 ip_compress_address + +Compress an IPv6 address. Just returns the IP if it is an IPv4. + + Params : IP, IP version + Returns : Compressed IP or undef (problem) + +C<$ip = ip_compress_adress ($ip, $version);> + +=head2 ip_is_overlap + +Check if two ranges of IPs overlap. + + Params : Four binary IPs (begin of range 1,end1,begin2,end2), IP version + $IP_PARTIAL_OVERLAP (ranges overlap) + $IP_NO_OVERLAP (no overlap) + $IP_A_IN_B_OVERLAP (range2 contains range1) + $IP_B_IN_A_OVERLAP (range1 contains range2) + $IP_IDENTICAL (ranges are identical) + undef (problem) + +C<(ip_is_overlap($rb1,$re1,$rb2,$re2,4) eq $IP_A_IN_B_OVERLAP) and do {};> + +=head2 ip_get_embedded_ipv4 + +Get an IPv4 embedded in an IPv6 address + + Params : IPv6 + Returns : IPv4 string or undef (not found) + +C<$ip4 = ip_get_embedded($ip6);> + +=head2 ip_check_mask + +Check the validity of a binary IP mask + + Params : Mask + Returns : 1 or undef (invalid) + +C + +Checks if mask has only 1s followed by 0s. + +=head2 ip_aggregate + +Aggregate 2 ranges of binary IPs + + Params : 1st range (1st IP, Last IP), last range (1st IP, last IP), IP version + Returns : prefix or undef (invalid) + +C<$prefix = ip_aggregate ($bip1,$eip1,$bip2,$eip2) || die ...> + +=head2 ip_iptypev4 + +Return the type of an IPv4 address. + + Params: binary IP + Returns: type as of the following table or undef (invalid ip) + +See RFC 5735 and RFC 6598 + +S
+S<-------------------------------------------------------------------> +S<0.0.0.0/8 "This" Network RFC 1122 PRIVATE> +S<10.0.0.0/8 Private-Use Networks RFC 1918 PRIVATE> +S<100.64.0.0/10 CGN Shared Address Space RFC 6598 SHARED> +S<127.0.0.0/8 Loopback RFC 1122 LOOPBACK> +S<169.254.0.0/16 Link Local RFC 3927 LINK-LOCAL> +S<172.16.0.0/12 Private-Use Networks RFC 1918 PRIVATE> +S<192.0.0.0/24 IETF Protocol Assignments RFC 5736 RESERVED> +S<192.0.2.0/24 TEST-NET-1 RFC 5737 TEST-NET> +S<192.88.99.0/24 6to4 Relay Anycast RFC 3068 6TO4-RELAY> +S<192.168.0.0/16 Private-Use Networks RFC 1918 PRIVATE> +S<198.18.0.0/15 Network Interconnect> +S< Device Benchmark Testing RFC 2544 RESERVED> +S<198.51.100.0/24 TEST-NET-2 RFC 5737 TEST-NET> +S<203.0.113.0/24 TEST-NET-3 RFC 5737 TEST-NET> +S<224.0.0.0/4 Multicast RFC 3171 MULTICAST> +S<240.0.0.0/4 Reserved for Future Use RFC 1112 RESERVED> +S<255.255.255.255/32 Limited Broadcast RFC 919 BROADCAST> +S< RFC 922> + +=head2 ip_iptypev6 + +Return the type of an IPv6 address. + + Params: binary ip + Returns: type as of the following table or undef (invalid) + +See L and L + + +S +S<-------------------------------------------------------------> +S<0000::/8 Reserved by IETF [RFC4291] RESERVED> +S<0100::/8 Reserved by IETF [RFC4291] RESERVED> +S<0200::/7 Reserved by IETF [RFC4048] RESERVED> +S<0400::/6 Reserved by IETF [RFC4291] RESERVED> +S<0800::/5 Reserved by IETF [RFC4291] RESERVED> +S<1000::/4 Reserved by IETF [RFC4291] RESERVED> +S<2000::/3 Global Unicast [RFC4291] GLOBAL-UNICAST> +S<4000::/3 Reserved by IETF [RFC4291] RESERVED> +S<6000::/3 Reserved by IETF [RFC4291] RESERVED> +S<8000::/3 Reserved by IETF [RFC4291] RESERVED> +S +S +S +S +S +S +S +S +S +S + + +S +S<---------------------------------------------------------------------> +S<::1/128 Loopback Address [RFC4291] UNSPECIFIED> +S<::/128 Unspecified Address [RFC4291] LOOPBACK> +S<::FFFF:0:0/96 IPv4-mapped Address [RFC4291] IPV4MAP> +S<0100::/64 Discard-Only Prefix [RFC6666] DISCARD> +S<2001:0000::/32 TEREDO [RFC4380] TEREDO> +S<2001:0002::/48 BMWG [RFC5180] BMWG> +S<2001:db8::/32 Documentation Prefix [RFC3849] DOCUMENTATION> +S<2001:10::/28 ORCHID [RFC4843] ORCHID> +S<2002::/16 6to4 [RFC3056] 6TO4> +S +S +S + + +=head2 ip_iptype + +Return the type of an IP (Public, Private, Reserved) + + Params : Binary IP to test, IP version (defaults to 6) + Returns : type (see ip_iptypev4 and ip_iptypev6 for details) or undef (invalid) + +C<$type = ip_iptype ($ip);> + +=head2 ip_check_prefix + +Check the validity of a prefix + + Params : binary IP, length of prefix, IP version + Returns : 1 or undef (invalid) + +Checks if the variant part of a prefix only has 0s, and the length is correct. + +C + +=head2 ip_reverse + +Get a reverse name from a prefix + + Params : IP, length of prefix, IP version + Returns : Reverse name or undef (error) + +C<$reverse = ip_reverse ($ip);> + +=head2 ip_normalize + +Normalize data to a range/prefix of IP addresses + + Params : Data String (Single IP, Range, Prefix) + Returns : ip1, ip2 (if range/prefix) or undef (error) + +C<($ip1,$ip2) = ip_normalize ($data);> + +=head2 ip_auth + +Return IP authority information from the IP::Authority module + + Params : IP, version + Returns : Auth info (RI for RIPE, AR for ARIN, etc) + +C<$auth = ip_auth ($ip,4);> + +Note: IPv4 only + + +=head1 BUGS + +The Math::BigInt library is needed for functions that use integers. These are +ip_inttobin, ip_bintoint, and the size method. In a next version, +Math::BigInt will become optionnal. + +=head1 AUTHORS + +Manuel Valente . + +Original IPv4 code by Monica Cortes Sack . + +Original IPv6 code by Lee Wilmot . + +=head1 BASED ON + +ipv4pack.pm, iplib.pm, iplibncc.pm. + +=head1 SEE ALSO + +perl(1), IP::Authority + +=cut diff --git a/csf/accounttracking.txt b/csf/accounttracking.txt new file mode 100644 index 0000000..24c9080 --- /dev/null +++ b/csf/accounttracking.txt @@ -0,0 +1,9 @@ +From: root +To: root +Subject: lfd on [hostname]: Account modification alert + +Time: [time] + +Reported Modifications: + +[report] diff --git a/csf/alert.txt b/csf/alert.txt new file mode 100644 index 0000000..d27e1d7 --- /dev/null +++ b/csf/alert.txt @@ -0,0 +1,13 @@ +From: root +To: root +Subject: lfd on [hostname]: blocked [ip] + +Time: [time] +IP: [ip] +Failures: [ipcount] +Interval: [iptick] seconds +Blocked: [block] + +Log entries: + +[text] diff --git a/csf/apache.http.txt b/csf/apache.http.txt new file mode 100644 index 0000000..a0dcd50 --- /dev/null +++ b/csf/apache.http.txt @@ -0,0 +1,35 @@ +Listen 0.0.0.0:[PORT] +Listen [::]:[PORT] + +# Virtualhost start - do not remove this line + + ServerName [SERVERNAME] + DocumentRoot [DOCUMENTROOT] + KeepAlive Off + + AllowOverride All + + + suPHP_Engine On + suPHP_UserGroup [USER] [USER] + + + + SuexecUserGroup [USER] [USER] + + + + RMode config + RUidGid [USER] [USER] + + + AssignUserID [USER] [USER] + + + lsapi_user_group [USER] [USER] + + + [PHPHANDLER] + + +# Virtualhost end - do not remove this line diff --git a/csf/apache.https.txt b/csf/apache.https.txt new file mode 100644 index 0000000..2cfc8a8 --- /dev/null +++ b/csf/apache.https.txt @@ -0,0 +1,43 @@ +Listen 0.0.0.0:[SSLPORT] +Listen [::]:[SSLPORT] + +# Virtualhost start - do not remove this line + + ServerName [SERVERNAME] + ServerAlias [SERVERALIAS] + DocumentRoot [DOCUMENTROOT] + UseCanonicalName Off + KeepAlive Off + + AllowOverride All + + + suPHP_Engine On + suPHP_UserGroup [USER] [USER] + + + + SuexecUserGroup [USER] [USER] + + + + RMode config + RUidGid [USER] [USER] + + + AssignUserID [USER] [USER] + + + lsapi_user_group [USER] [USER] + + ScriptAlias /local-bin /usr/bin + + [PHPHANDLER] + + SSLEngine on + SSLCertificateFile [SSLCERTIFICATEFILE] + SSLCertificateKeyFile [SSLCERTIFICATEKEYFILE] + SSLCACertificateFile [SSLCACERTIFICATEFILE] + SSLUseStapling off + +# Virtualhost end - do not remove this line diff --git a/csf/apache.main.txt b/csf/apache.main.txt new file mode 100644 index 0000000..e69de29 diff --git a/csf/apf_stub.pl b/csf/apf_stub.pl new file mode 100644 index 0000000..73874f9 --- /dev/null +++ b/csf/apf_stub.pl @@ -0,0 +1,43 @@ +#!/usr/bin/perl +use strict; +use warnings; + +my @cmd = @ARGV; + +if ($cmd[0] eq "-a" or $cmd[0] eq "--allow") { + $cmd[0] = "--add"; + system("csf",@cmd); +} +elsif ($cmd[0] eq "-d" or $cmd[0] eq "--deny") { + $cmd[0] = "--deny"; + system("csf",@cmd); +} +elsif ($cmd[0] eq "-u" or $cmd[0] eq "--remove" or $cmd[0] eq "--unban") { + $cmd[1] =~ s/\^|\$//g; + $cmd[0] = "--addrm"; + system("csf",@cmd); + $cmd[0] = "--denyrm"; + system("csf",@cmd); + $cmd[0] = "--temprm"; + system("csf",@cmd); +} +elsif ($cmd[0] eq "-s" or $cmd[0] eq "--start") { + $cmd[0] = "--start"; + system("csf",@cmd); +} +elsif ($cmd[0] eq "-f" or $cmd[0] eq "--flush" or $cmd[0] eq "--stop") { + $cmd[0] = "--stop"; + system("csf",@cmd); +} +elsif ($cmd[0] eq "-r" or $cmd[0] eq "--restart") { + $cmd[0] = "--restart"; + system("csf",@cmd); +} +elsif ($cmd[0] eq "-l" or $cmd[0] eq "--list") { + $cmd[0] = "--status"; + system("csf",@cmd); +} else { + print "Unknown command, please use csf directly instead of this apf stub\n"; +} + +exit; diff --git a/csf/auto.cwp.pl b/csf/auto.cwp.pl new file mode 100644 index 0000000..86ae11e --- /dev/null +++ b/csf/auto.cwp.pl @@ -0,0 +1,605 @@ +#!/usr/bin/perl +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +## no critic (ProhibitBarewordFileHandles, ProhibitExplicitReturnUndef, ProhibitMixedBooleanOperators, RequireBriefOpen) +use strict; +use Fcntl qw(:DEFAULT :flock); +use IPC::Open3; + +umask(0177); + +our (%config, %configsetting, $vps, $oldversion); + +$oldversion = $ARGV[0]; + +open (VERSION, "<","/etc/csf/version.txt"); +flock (VERSION, LOCK_SH); +my $version = ; +close (VERSION); +chomp $version; +$version =~ s/\W/_/g; +system("/bin/cp","-avf","/etc/csf/csf.conf","/var/lib/csf/backup/".time."_pre_v${version}_upgrade"); + +&loadcsfconfig; + +foreach my $alertfile ("sshalert.txt","sualert.txt","sudoalert.txt","webminalert.txt","cpanelalert.txt") { + if (-e "/usr/local/csf/tpl/".$alertfile) { + sysopen (my $IN, "/usr/local/csf/tpl/".$alertfile, O_RDWR | O_CREAT); + flock ($IN, LOCK_EX); + my @data = <$IN>; + chomp @data; + my $hit = 0; + foreach my $line (@data) { + if ($line =~ /\[text\]/) {$hit = 1} + } + unless ($hit) { + print $IN "\nLog line:\n\n[text]\n"; + } + close ($IN); + } +} + +if (-e "/proc/vz/veinfo") { + $vps = 1; +} else { + open (IN, "<","/proc/self/status"); + flock (IN, LOCK_SH); + while (my $line = ) { + chomp $line; + if ($line =~ /^envID:\s*(\d+)\s*$/) { + if ($1 > 0) { + $vps = 1; + last; + } + } + } + close (IN); +} +if (-e "/usr/local/cwpsrv") { + sysopen (my $CWP, "/usr/local/cwpsrv/htdocs/resources/admin/include/3rdparty.php", O_RDWR | O_CREAT); + flock ($CWP, LOCK_EX); + my @data = <$CWP>; + chomp @data; + if (!(grep {$_ =~ /configserver/} @data)) { + + seek ($CWP, 0, 0); + truncate ($CWP, 0); + foreach my $line (@data) { + print $CWP $line."\n"; + } + print $CWP "\n"; + } + close ($CWP); +} + +if (&checkversion("10.11") and !-e "/var/lib/csf/auto1011") { + if (-e "/var/lib/csf/stats/lfdstats") { + sysopen (STATS,"/var/lib/csf/stats/lfdstats", O_RDWR | O_CREAT); + flock (STATS, LOCK_EX); + my @stats = ; + chomp @stats; + my %ccs; + my @line = split(/\,/,$stats[69]); + for (my $x = 0; $x < @line; $x+=2) {$ccs{$line[$x]} = $line[$x+1]} + $stats[69] = ""; + foreach my $key (keys %ccs) {$stats[69] .= "$key,$ccs{$key},"} + seek (STATS, 0, 0); + truncate (STATS, 0); + foreach my $line (@stats) { + print STATS "$line\n"; + } + close (STATS); + } + + open (OUT, ">", "/var/lib/csf/auto1011"); + flock (OUT, LOCK_EX); + print OUT time; + close (OUT); +} +if (&checkversion("10.23") and !-e "/var/lib/csf/auto1023") { + if (-e "/etc/csf/csf.blocklists") { + sysopen (IN,"/etc/csf/csf.blocklists", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + my $SPAMDROPV6 = 0; + my $STOPFORUMSPAMV6 = 0; + foreach my $line (@data) { + if ($line =~ /^(\#)?SPAMDROPV6/) {$SPAMDROPV6 = 1} + if ($line =~ /^(\#)?STOPFORUMSPAMV6/) {$STOPFORUMSPAMV6 = 1} + print IN "$line\n"; + } + unless ($SPAMDROPV6) { + print IN "\n# Spamhaus IPv6 Don't Route Or Peer List (DROPv6)\n"; + print IN "# Details: http://www.spamhaus.org/drop/\n"; + print IN "#SPAMDROPV6|86400|0|https://www.spamhaus.org/drop/dropv6.txt\n"; + } + unless ($STOPFORUMSPAMV6) { + print IN "\n# Stop Forum Spam IPv6\n"; + print IN "# Details: http://www.stopforumspam.com/downloads/\n"; + print IN "# Many of the lists available contain a vast number of IP addresses so special\n"; + print IN "# care needs to be made when selecting from their lists\n"; + print IN "#STOPFORUMSPAMV6|86400|0|http://www.stopforumspam.com/downloads/listed_ip_1_ipv6.zip\n"; + } + close (IN); + } + + open (OUT, ">", "/var/lib/csf/auto1023"); + flock (OUT, LOCK_EX); + print OUT time; + close (OUT); +} +if (&checkversion("12.02") and !-e "/var/lib/csf/auto1202") { + if (-e "/etc/csf/csf.blocklists") { + sysopen (IN,"/etc/csf/csf.blocklists", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /greensnow/) {$line =~ s/http:/https:/g} + print IN "$line\n"; + } + close (IN); + } + + open (OUT, ">", "/var/lib/csf/auto1202"); + flock (OUT, LOCK_EX); + print OUT time; + close (OUT); +} +if (&checkversion("14.03") and !-e "/var/lib/csf/auto1403") { + if (-e "/etc/csf/csf.blocklists") { + sysopen (IN,"/etc/csf/csf.blocklists", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /dshield/) {$line =~ s/http:/https:/g} + print IN "$line\n"; + } + close (IN); + } + + open (OUT, ">", "/var/lib/csf/auto1403"); + flock (OUT, LOCK_EX); + print OUT time; + close (OUT); +} + +if (-e "/etc/csf/csf.allow") { + sysopen (IN,"/etc/csf/csf.allow", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /^Include \/etc\/csf\/cpanel\.comodo\.allow/) {next} + print IN "$line\n"; + } + close (IN); +} +if (-e "/etc/csf/csf.ignore") { + sysopen (IN,"/etc/csf/csf.ignore", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /^Include \/etc\/csf\/cpanel\.comodo\.ignore/) {next} + print IN "$line\n"; + } + close (IN); +} +if (-e "/usr/local/csf/bin/regex.custom.pm") { + sysopen (IN,"/usr/local/csf/bin/regex.custom.pm", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /^use strict;/) {next} + print IN "$line\n"; + } + close (IN); +} +if (-e "/etc/csf/csf.blocklists") { + sysopen (IN,"/etc/csf/csf.blocklists", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /feeds\.dshield\.org/) {$line =~ s/feeds\.dshield\.org/www\.dshield\.org/g} + if ($line =~ /openbl\.org/i) {next} + if ($line =~ /autoshun/i) {next} + print IN "$line\n"; + } + close (IN); +} +if (-e "/var/lib/csf/csf.tempban") { + sysopen (IN,"/var/lib/csf/csf.tempban", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /^\d+\:/) {$line =~ s/\:/\|/g} + print IN "$line\n"; + } + close (IN); +} +if (-e "/var/lib/csf/csf.tempallow") { + sysopen (IN,"/var/lib/csf/csf.tempallow", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /^\d+\:/) {$line =~ s/\:/\|/g} + print IN "$line\n"; + } + close (IN); +} + +if ($config{TESTING}) { + + open (IN, "<", "/etc/ssh/sshd_config") or die $!; + flock (IN, LOCK_SH) or die $!; + my @sshconfig = ; + close (IN); + chomp @sshconfig; + + my $sshport = "22"; + foreach my $line (@sshconfig) { + if ($line =~ /^Port (\d+)/) {$sshport = $1} + } + + $config{TCP_IN} =~ s/\s//g; + if ($config{TCP_IN} ne "") { + foreach my $port (split(/\,/,$config{TCP_IN})) { + if ($port eq $sshport) {$sshport = "22"} + } + } + + if ($sshport ne "22") { + $config{TCP_IN} .= ",$sshport"; + $config{TCP6_IN} .= ",$sshport"; + open (IN, "<", "/etc/csf/csf.conf") or die $!; + flock (IN, LOCK_SH) or die $!; + my @config = ; + close (IN); + chomp @config; + open (OUT, ">", "/etc/csf/csf.conf") or die $!; + flock (OUT, LOCK_EX) or die $!; + foreach my $line (@config) { + if ($line =~ /^TCP6_IN/) { + print OUT "TCP6_IN = \"$config{TCP6_IN}\"\n"; + print "\n*** SSH port $sshport added to the TCP6_IN port list\n\n"; + } + elsif ($line =~ /^TCP_IN/) { + print OUT "TCP_IN = \"$config{TCP_IN}\"\n"; + print "\n*** SSH port $sshport added to the TCP_IN port list\n\n"; + } + else { + print OUT $line."\n"; + } + } + close OUT; + &loadcsfconfig; + + } + + open (FH, "<", "/proc/sys/kernel/osrelease"); + flock (IN, LOCK_SH); + my @data = ; + close (FH); + chomp @data; + if ($data[0] =~ /^(\d+)\.(\d+)\.(\d+)/) { + my $maj = $1; + my $mid = $2; + my $min = $3; + if ($maj == 3 and $mid > 6) { + open (IN, "<", "/etc/csf/csf.conf") or die $!; + flock (IN, LOCK_SH) or die $!; + my @config = ; + close (IN); + chomp @config; + open (OUT, ">", "/etc/csf/csf.conf") or die $!; + flock (OUT, LOCK_EX) or die $!; + foreach my $line (@config) { + if ($line =~ /^USE_CONNTRACK =/) { + print OUT "USE_CONNTRACK = \"1\"\n"; + print "\n*** USE_CONNTRACK Enabled\n\n"; + } else { + print OUT $line."\n"; + } + } + close OUT; + &loadcsfconfig; + } + } + + my @ipdata; + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die "alarm\n"}; + alarm(3); + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, "$config{IPTABLES} --wait -L OUTPUT -nv"); + @ipdata = <$childout>; + waitpid ($cmdpid, 0); + chomp @ipdata; + if ($ipdata[0] =~ /# Warning: iptables-legacy tables present/) {shift @ipdata} + alarm(0); + }; + alarm(0); + if ($@ ne "alarm\n" and $ipdata[0] =~ /^Chain OUTPUT/) { + $config{IPTABLESWAIT} = "--wait"; + $config{WAITLOCK} = 1; + open (IN, "<", "/etc/csf/csf.conf") or die $!; + flock (IN, LOCK_SH) or die $!; + my @config = ; + close (IN); + chomp @config; + open (OUT, ">", "/etc/csf/csf.conf") or die $!; + flock (OUT, LOCK_EX) or die $!; + foreach my $line (@config) { + if ($line =~ /WAITLOCK =/) { + print OUT "WAITLOCK = \"1\"\n"; + } else { + print OUT $line."\n"; + } + } + close OUT; + &loadcsfconfig; + } + + if (-e $config{IP6TABLES} and !$vps) { + my ($childin, $childout); + my $cmdpid; + if (-e $config{IP}) {$cmdpid = open3($childin, $childout, $childout, $config{IP}, "-oneline", "addr")} + elsif (-e $config{IFCONFIG}) {$cmdpid = open3($childin, $childout, $childout, $config{IFCONFIG})} + my @ifconfig = <$childout>; + waitpid ($cmdpid, 0); + chomp @ifconfig; + if (grep {$_ =~ /\s*inet6/} @ifconfig) { + $config{IPV6} = 1; + open (FH, "<", "/proc/sys/kernel/osrelease"); + flock (IN, LOCK_SH); + my @data = ; + close (FH); + chomp @data; + if ($data[0] =~ /^(\d+)\.(\d+)\.(\d+)/) { + my $maj = $1; + my $mid = $2; + my $min = $3; + if (($maj > 2) or (($maj > 1) and ($mid > 6)) or (($maj > 1) and ($mid > 5) and ($min > 19))) { + $config{IPV6_SPI} = 1; + } else { + $config{IPV6_SPI} = 0; + } + } + open (IN, "<", "/etc/csf/csf.conf") or die $!; + flock (IN, LOCK_SH) or die $!; + my @config = ; + close (IN); + chomp @config; + open (OUT, ">", "/etc/csf/csf.conf") or die $!; + flock (OUT, LOCK_EX) or die $!; + foreach my $line (@config) { + if ($line =~ /^IPV6 =/) { + print OUT "IPV6 = \"$config{IPV6}\"\n"; + print "\n*** IPV6 Enabled\n\n"; + } + elsif ($line =~ /^IPV6_SPI =/) { + print OUT "IPV6_SPI = \"$config{IPV6_SPI}\"\n"; + print "\n*** IPV6_SPI set to $config{IPV6_SPI}\n\n"; + } else { + print OUT $line."\n"; + } + } + close OUT; + &loadcsfconfig; + } + } +} + +open (IN, "<", "csf.cwp.conf") or die $!; +flock (IN, LOCK_SH) or die $!; +my @config = ; +close (IN); +chomp @config; +open (OUT, ">", "/etc/csf/csf.conf") or die $!; +flock (OUT, LOCK_EX) or die $!; +foreach my $line (@config) { + if ($line =~ /^\#/) { + print OUT $line."\n"; + next; + } + if ($line !~ /=/) { + print OUT $line."\n"; + next; + } + my ($name,$value) = split (/=/,$line,2); + $name =~ s/\s//g; + if ($value =~ /\"(.*)\"/) { + $value = $1; + } else { + print "Error: Invalid configuration line [$line]"; + } + if (&checkversion("10.15") and !-e "/var/lib/csf/auto1015") { + if ($name eq "MESSENGER_RATE" and $config{$name} eq "30/m") {$config{$name} = "100/s"} + if ($name eq "MESSENGER_BURST" and $config{$name} eq "5") {$config{$name} = "150"} + open (my $AUTO, ">", "/var/lib/csf/auto1015"); + flock ($AUTO, LOCK_EX); + print $AUTO time; + close ($AUTO); + } + if ($configsetting{$name}) { + print OUT "$name = \"$config{$name}\"\n"; + } else { + if (&checkversion("9.29") and !-e "/var/lib/csf/auto929" and $name eq "PT_USERRSS") { + $line = "PT_USERRSS = \"$config{PT_USERMEM}\""; + open (my $AUTO, ">", "/var/lib/csf/auto929"); + flock ($AUTO, LOCK_EX); + print $AUTO time; + close ($AUTO); + } + if ($name eq "CC_SRC") {$line = "CC_SRC = \"1\""} + print OUT $line."\n"; + print "New setting: $name\n"; + } +} +close OUT; + +if ($config{TESTING}) { + my @netstat = `netstat -lpn`; + chomp @netstat; + my @tcpports; + my @udpports; + my @tcp6ports; + my @udp6ports; + foreach my $line (@netstat) { + if ($line =~ /^(\w+).* (\d+\.\d+\.\d+\.\d+):(\d+)/) { + if ($2 eq '127.0.0.1') {next} + if ($1 eq "tcp") { + push @tcpports, $3; + } + elsif ($1 eq "udp") { + push @udpports, $3; + } + } + if ($line =~ /^(\w+).* (::):(\d+) /) { + if ($1 eq "tcp") { + push @tcp6ports, $3; + } + elsif ($1 eq "udp") { + push @udp6ports, $3; + } + } + } + + @tcpports = sort { $a <=> $b } @tcpports; + @udpports = sort { $a <=> $b } @udpports; + @tcp6ports = sort { $a <=> $b } @tcp6ports; + @udp6ports = sort { $a <=> $b } @udp6ports; + + print "\nTCP ports currently listening for incoming connections:\n"; + my $last = ""; + foreach my $port (@tcpports) { + if ($port ne $last) { + if ($port ne $tcpports[0]) {print ","} + print $port; + $last = $port; + } + } + print "\n\nUDP ports currently listening for incoming connections:\n"; + $last = ""; + foreach my $port (@udpports) { + if ($port ne $last) { + if ($port ne $udpports[0]) {print ","} + print $port; + $last = $port; + } + } + my $opts = "TCP_*, UDP_*"; + if (@tcp6ports or @udp6ports) { + $opts .= ", IPV6, TCP6_*, UDP6_*"; + print "\n\nIPv6 TCP ports currently listening for incoming connections:\n"; + my $last = ""; + foreach my $port (@tcp6ports) { + if ($port ne $last) { + if ($port ne $tcp6ports[0]) {print ","} + print $port; + $last = $port; + } + } + print "\n"; + print "\nIPv6 UDP ports currently listening for incoming connections:\n"; + $last = ""; + foreach my $port (@udp6ports) { + if ($port ne $last) { + if ($port ne $udp6ports[0]) {print ","} + print $port; + $last = $port; + } + } + } + print "\n\nNote: The port details above are for information only, csf hasn't been auto-configured.\n\n"; + print "Don't forget to:\n"; + print "1. Configure the following options in the csf configuration to suite your server: $opts\n"; + print "2. Restart csf and lfd\n"; + print "3. Set TESTING to 0 once you're happy with the firewall, lfd will not run until you do so\n"; +} + +if ($ENV{SSH_CLIENT}) { + my $ip = (split(/ /,$ENV{SSH_CLIENT}))[0]; + if ($ip =~ /(\d+\.\d+\.\d+\.\d+)/) { + print "\nAdding current SSH session IP address to the csf whitelist in csf.allow:\n"; + system("/usr/sbin/csf -a $1 csf SSH installation/upgrade IP address"); + } +} + +exit; +############################################################################### +sub loadcsfconfig { + open (IN, "<", "/etc/csf/csf.conf") or die $!; + flock (IN, LOCK_SH) or die $!; + my @config = ; + close (IN); + chomp @config; + + foreach my $line (@config) { + if ($line =~ /^\#/) {next} + if ($line !~ /=/) {next} + my ($name,$value) = split (/=/,$line,2); + $name =~ s/\s//g; + if ($value =~ /\"(.*)\"/) { + $value = $1; + } else { + print "Error: Invalid configuration line [$line]"; + } + $config{$name} = $value; + $configsetting{$name} = 1; + } + return; +} +############################################################################### +sub checkversion { + my $version = shift; + my ($maj, $min) = split(/\./,$version); + my ($oldmaj, $oldmin) = split(/\./,$oldversion); + + if ($oldmaj == 0 or $oldmaj eq "") {return 0} + + if (($oldmaj < $maj) or ($oldmaj == $maj and $oldmin < $min)) {return 1} else {return 0} +} +############################################################################### diff --git a/csf/auto.cyberpanel.pl b/csf/auto.cyberpanel.pl new file mode 100644 index 0000000..ea4c079 --- /dev/null +++ b/csf/auto.cyberpanel.pl @@ -0,0 +1,589 @@ +#!/usr/bin/perl +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +## no critic (ProhibitBarewordFileHandles, ProhibitExplicitReturnUndef, ProhibitMixedBooleanOperators, RequireBriefOpen) +use strict; +use Fcntl qw(:DEFAULT :flock); +use IPC::Open3; + +umask(0177); + +our (%config, %configsetting, $vps, $oldversion); + +$oldversion = $ARGV[0]; + +open (VERSION, "<","/etc/csf/version.txt"); +flock (VERSION, LOCK_SH); +my $version = ; +close (VERSION); +chomp $version; +$version =~ s/\W/_/g; +system("/bin/cp","-avf","/etc/csf/csf.conf","/var/lib/csf/backup/".time."_pre_v${version}_upgrade"); + +&loadcsfconfig; + +if (-e "/proc/vz/veinfo") { + $vps = 1; +} else { + open (IN, "<","/proc/self/status"); + flock (IN, LOCK_SH); + while (my $line = ) { + chomp $line; + if ($line =~ /^envID:\s*(\d+)\s*$/) { + if ($1 > 0) { + $vps = 1; + last; + } + } + } + close (IN); +} + +foreach my $alertfile ("sshalert.txt","sualert.txt","sudoalert.txt","webminalert.txt","cpanelalert.txt") { + if (-e "/usr/local/csf/tpl/".$alertfile) { + sysopen (my $IN, "/usr/local/csf/tpl/".$alertfile, O_RDWR | O_CREAT); + flock ($IN, LOCK_EX); + my @data = <$IN>; + chomp @data; + my $hit = 0; + foreach my $line (@data) { + if ($line =~ /\[text\]/) {$hit = 1} + } + unless ($hit) { + print $IN "\nLog line:\n\n[text]\n"; + } + close ($IN); + } +} + +if (&checkversion("10.11") and !-e "/var/lib/csf/auto1011") { + if (-e "/var/lib/csf/stats/lfdstats") { + sysopen (STATS,"/var/lib/csf/stats/lfdstats", O_RDWR | O_CREAT); + flock (STATS, LOCK_EX); + my @stats = ; + chomp @stats; + my %ccs; + my @line = split(/\,/,$stats[69]); + for (my $x = 0; $x < @line; $x+=2) {$ccs{$line[$x]} = $line[$x+1]} + $stats[69] = ""; + foreach my $key (keys %ccs) {$stats[69] .= "$key,$ccs{$key},"} + seek (STATS, 0, 0); + truncate (STATS, 0); + foreach my $line (@stats) { + print STATS "$line\n"; + } + close (STATS); + } + + open (OUT, ">", "/var/lib/csf/auto1011"); + flock (OUT, LOCK_EX); + print OUT time; + close (OUT); +} +if (&checkversion("10.23") and !-e "/var/lib/csf/auto1023") { + if (-e "/etc/csf/csf.blocklists") { + sysopen (IN,"/etc/csf/csf.blocklists", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + my $SPAMDROPV6 = 0; + my $STOPFORUMSPAMV6 = 0; + foreach my $line (@data) { + if ($line =~ /^(\#)?SPAMDROPV6/) {$SPAMDROPV6 = 1} + if ($line =~ /^(\#)?STOPFORUMSPAMV6/) {$STOPFORUMSPAMV6 = 1} + print IN "$line\n"; + } + unless ($SPAMDROPV6) { + print IN "\n# Spamhaus IPv6 Don't Route Or Peer List (DROPv6)\n"; + print IN "# Details: http://www.spamhaus.org/drop/\n"; + print IN "#SPAMDROPV6|86400|0|https://www.spamhaus.org/drop/dropv6.txt\n"; + } + unless ($STOPFORUMSPAMV6) { + print IN "\n# Stop Forum Spam IPv6\n"; + print IN "# Details: http://www.stopforumspam.com/downloads/\n"; + print IN "# Many of the lists available contain a vast number of IP addresses so special\n"; + print IN "# care needs to be made when selecting from their lists\n"; + print IN "#STOPFORUMSPAMV6|86400|0|http://www.stopforumspam.com/downloads/listed_ip_1_ipv6.zip\n"; + } + close (IN); + } + + open (OUT, ">", "/var/lib/csf/auto1023"); + flock (OUT, LOCK_EX); + print OUT time; + close (OUT); +} +if (&checkversion("12.02") and !-e "/var/lib/csf/auto1202") { + if (-e "/etc/csf/csf.blocklists") { + sysopen (IN,"/etc/csf/csf.blocklists", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /greensnow/) {$line =~ s/http:/https:/g} + print IN "$line\n"; + } + close (IN); + } + + open (OUT, ">", "/var/lib/csf/auto1202"); + flock (OUT, LOCK_EX); + print OUT time; + close (OUT); +} +if (&checkversion("14.03") and !-e "/var/lib/csf/auto1403") { + if (-e "/etc/csf/csf.blocklists") { + sysopen (IN,"/etc/csf/csf.blocklists", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /dshield/) {$line =~ s/http:/https:/g} + print IN "$line\n"; + } + close (IN); + } + + open (OUT, ">", "/var/lib/csf/auto1403"); + flock (OUT, LOCK_EX); + print OUT time; + close (OUT); +} + +if (-e "/etc/csf/csf.allow") { + sysopen (IN,"/etc/csf/csf.allow", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /^Include \/etc\/csf\/cpanel\.comodo\.allow/) {next} + print IN "$line\n"; + } + close (IN); +} +if (-e "/etc/csf/csf.ignore") { + sysopen (IN,"/etc/csf/csf.ignore", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /^Include \/etc\/csf\/cpanel\.comodo\.ignore/) {next} + print IN "$line\n"; + } + close (IN); +} +if (-e "/usr/local/csf/bin/regex.custom.pm") { + sysopen (IN,"/usr/local/csf/bin/regex.custom.pm", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /^use strict;/) {next} + print IN "$line\n"; + } + close (IN); +} +if (-e "/etc/csf/csf.blocklists") { + sysopen (IN,"/etc/csf/csf.blocklists", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /feeds\.dshield\.org/) {$line =~ s/feeds\.dshield\.org/www\.dshield\.org/g} + if ($line =~ /openbl\.org/i) {next} + if ($line =~ /autoshun/i) {next} + print IN "$line\n"; + } + close (IN); +} +if (-e "/var/lib/csf/csf.tempban") { + sysopen (IN,"/var/lib/csf/csf.tempban", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /^\d+\:/) {$line =~ s/\:/\|/g} + print IN "$line\n"; + } + close (IN); +} +if (-e "/var/lib/csf/csf.tempallow") { + sysopen (IN,"/var/lib/csf/csf.tempallow", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /^\d+\:/) {$line =~ s/\:/\|/g} + print IN "$line\n"; + } + close (IN); +} + +if ($config{TESTING}) { + + open (IN, "<", "/etc/ssh/sshd_config") or die $!; + flock (IN, LOCK_SH) or die $!; + my @sshconfig = ; + close (IN); + chomp @sshconfig; + + my $sshport = "22"; + foreach my $line (@sshconfig) { + if ($line =~ /^Port (\d+)/) {$sshport = $1} + } + + $config{TCP_IN} =~ s/\s//g; + if ($config{TCP_IN} ne "") { + foreach my $port (split(/\,/,$config{TCP_IN})) { + if ($port eq $sshport) {$sshport = "22"} + } + } + + if ($sshport ne "22") { + $config{TCP_IN} .= ",$sshport"; + $config{TCP6_IN} .= ",$sshport"; + open (IN, "<", "/etc/csf/csf.conf") or die $!; + flock (IN, LOCK_SH) or die $!; + my @config = ; + close (IN); + chomp @config; + open (OUT, ">", "/etc/csf/csf.conf") or die $!; + flock (OUT, LOCK_EX) or die $!; + foreach my $line (@config) { + if ($line =~ /^TCP6_IN/) { + print OUT "TCP6_IN = \"$config{TCP6_IN}\"\n"; + print "\n*** SSH port $sshport added to the TCP6_IN port list\n\n"; + } + elsif ($line =~ /^TCP_IN/) { + print OUT "TCP_IN = \"$config{TCP_IN}\"\n"; + print "\n*** SSH port $sshport added to the TCP_IN port list\n\n"; + } + else { + print OUT $line."\n"; + } + } + close OUT; + &loadcsfconfig; + + } + + open (FH, "<", "/proc/sys/kernel/osrelease"); + flock (IN, LOCK_SH); + my @data = ; + close (FH); + chomp @data; + if ($data[0] =~ /^(\d+)\.(\d+)\.(\d+)/) { + my $maj = $1; + my $mid = $2; + my $min = $3; + if ($maj == 3 and $mid > 6) { + open (IN, "<", "/etc/csf/csf.conf") or die $!; + flock (IN, LOCK_SH) or die $!; + my @config = ; + close (IN); + chomp @config; + open (OUT, ">", "/etc/csf/csf.conf") or die $!; + flock (OUT, LOCK_EX) or die $!; + foreach my $line (@config) { + if ($line =~ /^USE_CONNTRACK =/) { + print OUT "USE_CONNTRACK = \"1\"\n"; + print "\n*** USE_CONNTRACK Enabled\n\n"; + } else { + print OUT $line."\n"; + } + } + close OUT; + &loadcsfconfig; + } + } + + my @ipdata; + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die "alarm\n"}; + alarm(3); + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, "$config{IPTABLES} --wait -L OUTPUT -nv"); + @ipdata = <$childout>; + waitpid ($cmdpid, 0); + chomp @ipdata; + if ($ipdata[0] =~ /# Warning: iptables-legacy tables present/) {shift @ipdata} + alarm(0); + }; + alarm(0); + if ($@ ne "alarm\n" and $ipdata[0] =~ /^Chain OUTPUT/) { + $config{IPTABLESWAIT} = "--wait"; + $config{WAITLOCK} = 1; + open (IN, "<", "/etc/csf/csf.conf") or die $!; + flock (IN, LOCK_SH) or die $!; + my @config = ; + close (IN); + chomp @config; + open (OUT, ">", "/etc/csf/csf.conf") or die $!; + flock (OUT, LOCK_EX) or die $!; + foreach my $line (@config) { + if ($line =~ /WAITLOCK =/) { + print OUT "WAITLOCK = \"1\"\n"; + } else { + print OUT $line."\n"; + } + } + close OUT; + &loadcsfconfig; + } + + if (-e $config{IP6TABLES} and !$vps) { + my ($childin, $childout); + my $cmdpid; + if (-e $config{IP}) {$cmdpid = open3($childin, $childout, $childout, $config{IP}, "-oneline", "addr")} + elsif (-e $config{IFCONFIG}) {$cmdpid = open3($childin, $childout, $childout, $config{IFCONFIG})} + my @ifconfig = <$childout>; + waitpid ($cmdpid, 0); + chomp @ifconfig; + if (grep {$_ =~ /\s*inet6/} @ifconfig) { + $config{IPV6} = 1; + open (FH, "<", "/proc/sys/kernel/osrelease"); + flock (IN, LOCK_SH); + my @data = ; + close (FH); + chomp @data; + if ($data[0] =~ /^(\d+)\.(\d+)\.(\d+)/) { + my $maj = $1; + my $mid = $2; + my $min = $3; + if (($maj > 2) or (($maj > 1) and ($mid > 6)) or (($maj > 1) and ($mid > 5) and ($min > 19))) { + $config{IPV6_SPI} = 1; + } else { + $config{IPV6_SPI} = 0; + } + } + open (IN, "<", "/etc/csf/csf.conf") or die $!; + flock (IN, LOCK_SH) or die $!; + my @config = ; + close (IN); + chomp @config; + open (OUT, ">", "/etc/csf/csf.conf") or die $!; + flock (OUT, LOCK_EX) or die $!; + foreach my $line (@config) { + if ($line =~ /^IPV6 =/) { + print OUT "IPV6 = \"$config{IPV6}\"\n"; + print "\n*** IPV6 Enabled\n\n"; + } + elsif ($line =~ /^IPV6_SPI =/) { + print OUT "IPV6_SPI = \"$config{IPV6_SPI}\"\n"; + print "\n*** IPV6_SPI set to $config{IPV6_SPI}\n\n"; + } else { + print OUT $line."\n"; + } + } + close OUT; + &loadcsfconfig; + } + } +} + +open (IN, "<", "csf.cyberpanel.conf") or die $!; +flock (IN, LOCK_SH) or die $!; +my @config = ; +close (IN); +chomp @config; +open (OUT, ">", "/etc/csf/csf.conf") or die $!; +flock (OUT, LOCK_EX) or die $!; +foreach my $line (@config) { + if ($line =~ /^\#/) { + print OUT $line."\n"; + next; + } + if ($line !~ /=/) { + print OUT $line."\n"; + next; + } + my ($name,$value) = split (/=/,$line,2); + $name =~ s/\s//g; + if ($value =~ /\"(.*)\"/) { + $value = $1; + } else { + print "Error: Invalid configuration line [$line]"; + } + if (&checkversion("10.15") and !-e "/var/lib/csf/auto1015") { + if ($name eq "MESSENGER_RATE" and $config{$name} eq "30/m") {$config{$name} = "100/s"} + if ($name eq "MESSENGER_BURST" and $config{$name} eq "5") {$config{$name} = "150"} + open (my $AUTO, ">", "/var/lib/csf/auto1015"); + flock ($AUTO, LOCK_EX); + print $AUTO time; + close ($AUTO); + } + if ($configsetting{$name}) { + print OUT "$name = \"$config{$name}\"\n"; + } else { + if (&checkversion("9.29") and !-e "/var/lib/csf/auto929" and $name eq "PT_USERRSS") { + $line = "PT_USERRSS = \"$config{PT_USERMEM}\""; + open (my $AUTO, ">", "/var/lib/csf/auto929"); + flock ($AUTO, LOCK_EX); + print $AUTO time; + close ($AUTO); + } + if ($name eq "CC_SRC") {$line = "CC_SRC = \"1\""} + print OUT $line."\n"; + print "New setting: $name\n"; + } +} +close OUT; + +if ($config{TESTING}) { + my @netstat = `netstat -lpn`; + chomp @netstat; + my @tcpports; + my @udpports; + my @tcp6ports; + my @udp6ports; + foreach my $line (@netstat) { + if ($line =~ /^(\w+).* (\d+\.\d+\.\d+\.\d+):(\d+)/) { + if ($2 eq '127.0.0.1') {next} + if ($1 eq "tcp") { + push @tcpports, $3; + } + elsif ($1 eq "udp") { + push @udpports, $3; + } + } + if ($line =~ /^(\w+).* (::):(\d+) /) { + if ($1 eq "tcp") { + push @tcp6ports, $3; + } + elsif ($1 eq "udp") { + push @udp6ports, $3; + } + } + } + + @tcpports = sort { $a <=> $b } @tcpports; + @udpports = sort { $a <=> $b } @udpports; + @tcp6ports = sort { $a <=> $b } @tcp6ports; + @udp6ports = sort { $a <=> $b } @udp6ports; + + print "\nTCP ports currently listening for incoming connections:\n"; + my $last = ""; + foreach my $port (@tcpports) { + if ($port ne $last) { + if ($port ne $tcpports[0]) {print ","} + print $port; + $last = $port; + } + } + print "\n\nUDP ports currently listening for incoming connections:\n"; + $last = ""; + foreach my $port (@udpports) { + if ($port ne $last) { + if ($port ne $udpports[0]) {print ","} + print $port; + $last = $port; + } + } + my $opts = "TCP_*, UDP_*"; + if (@tcp6ports or @udp6ports) { + $opts .= ", IPV6, TCP6_*, UDP6_*"; + print "\n\nIPv6 TCP ports currently listening for incoming connections:\n"; + my $last = ""; + foreach my $port (@tcp6ports) { + if ($port ne $last) { + if ($port ne $tcp6ports[0]) {print ","} + print $port; + $last = $port; + } + } + print "\n"; + print "\nIPv6 UDP ports currently listening for incoming connections:\n"; + $last = ""; + foreach my $port (@udp6ports) { + if ($port ne $last) { + if ($port ne $udp6ports[0]) {print ","} + print $port; + $last = $port; + } + } + } + print "\n\nNote: The port details above are for information only, csf hasn't been auto-configured.\n\n"; + print "Don't forget to:\n"; + print "1. Configure the following options in the csf configuration to suite your server: $opts\n"; + print "2. Restart csf and lfd\n"; + print "3. Set TESTING to 0 once you're happy with the firewall, lfd will not run until you do so\n"; +} + +if ($ENV{SSH_CLIENT}) { + my $ip = (split(/ /,$ENV{SSH_CLIENT}))[0]; + if ($ip =~ /(\d+\.\d+\.\d+\.\d+)/) { + print "\nAdding current SSH session IP address to the csf whitelist in csf.allow:\n"; + system("/usr/sbin/csf -a $1 csf SSH installation/upgrade IP address"); + } +} + +exit; +############################################################################### +sub loadcsfconfig { + open (IN, "<", "/etc/csf/csf.conf") or die $!; + flock (IN, LOCK_SH) or die $!; + my @config = ; + close (IN); + chomp @config; + + foreach my $line (@config) { + if ($line =~ /^\#/) {next} + if ($line !~ /=/) {next} + my ($name,$value) = split (/=/,$line,2); + $name =~ s/\s//g; + if ($value =~ /\"(.*)\"/) { + $value = $1; + } else { + print "Error: Invalid configuration line [$line]"; + } + $config{$name} = $value; + $configsetting{$name} = 1; + } + return; +} +############################################################################### +sub checkversion { + my $version = shift; + my ($maj, $min) = split(/\./,$version); + my ($oldmaj, $oldmin) = split(/\./,$oldversion); + + if ($oldmaj == 0 or $oldmaj eq "") {return 0} + + if (($oldmaj < $maj) or ($oldmaj == $maj and $oldmin < $min)) {return 1} else {return 0} +} +############################################################################### diff --git a/csf/auto.directadmin.pl b/csf/auto.directadmin.pl new file mode 100644 index 0000000..f6b111e --- /dev/null +++ b/csf/auto.directadmin.pl @@ -0,0 +1,618 @@ +#!/usr/bin/perl +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +## no critic (ProhibitBarewordFileHandles, ProhibitExplicitReturnUndef, ProhibitMixedBooleanOperators, RequireBriefOpen) +use strict; +use Fcntl qw(:DEFAULT :flock); +use IPC::Open3; + +umask(0177); + +our (%config, %configsetting, $vps, $oldversion); + +$oldversion = $ARGV[0]; + +open (VERSION, "<","/etc/csf/version.txt"); +flock (VERSION, LOCK_SH); +my $version = ; +close (VERSION); +chomp $version; +$version =~ s/\W/_/g; +system("/bin/cp","-avf","/etc/csf/csf.conf","/var/lib/csf/backup/".time."_pre_v${version}_upgrade"); + +&loadcsfconfig; + +if (-e "/proc/vz/veinfo") { + $vps = 1; +} else { + open (IN, "<","/proc/self/status"); + flock (IN, LOCK_SH); + while (my $line = ) { + chomp $line; + if ($line =~ /^envID:\s*(\d+)\s*$/) { + if ($1 > 0) { + $vps = 1; + last; + } + } + } + close (IN); +} + +foreach my $alertfile ("sshalert.txt","sualert.txt","sudoalert.txt","webminalert.txt","cpanelalert.txt") { + if (-e "/usr/local/csf/tpl/".$alertfile) { + sysopen (my $IN, "/usr/local/csf/tpl/".$alertfile, O_RDWR | O_CREAT); + flock ($IN, LOCK_EX); + my @data = <$IN>; + chomp @data; + my $hit = 0; + foreach my $line (@data) { + if ($line =~ /\[text\]/) {$hit = 1} + } + unless ($hit) { + print $IN "\nLog line:\n\n[text]\n"; + } + close ($IN); + } +} + +if (&checkversion("10.11") and !-e "/var/lib/csf/auto1011") { + if (-e "/var/lib/csf/stats/lfdstats") { + sysopen (STATS,"/var/lib/csf/stats/lfdstats", O_RDWR | O_CREAT); + flock (STATS, LOCK_EX); + my @stats = ; + chomp @stats; + my %ccs; + my @line = split(/\,/,$stats[69]); + for (my $x = 0; $x < @line; $x+=2) {$ccs{$line[$x]} = $line[$x+1]} + $stats[69] = ""; + foreach my $key (keys %ccs) {$stats[69] .= "$key,$ccs{$key},"} + seek (STATS, 0, 0); + truncate (STATS, 0); + foreach my $line (@stats) { + print STATS "$line\n"; + } + close (STATS); + } + + open (OUT, ">", "/var/lib/csf/auto1011"); + flock (OUT, LOCK_EX); + print OUT time; + close (OUT); +} +if (&checkversion("10.23") and !-e "/var/lib/csf/auto1023") { + if (-e "/etc/csf/csf.blocklists") { + sysopen (IN,"/etc/csf/csf.blocklists", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + my $SPAMDROPV6 = 0; + my $STOPFORUMSPAMV6 = 0; + foreach my $line (@data) { + if ($line =~ /^(\#)?SPAMDROPV6/) {$SPAMDROPV6 = 1} + if ($line =~ /^(\#)?STOPFORUMSPAMV6/) {$STOPFORUMSPAMV6 = 1} + print IN "$line\n"; + } + unless ($SPAMDROPV6) { + print IN "\n# Spamhaus IPv6 Don't Route Or Peer List (DROPv6)\n"; + print IN "# Details: http://www.spamhaus.org/drop/\n"; + print IN "#SPAMDROPV6|86400|0|https://www.spamhaus.org/drop/dropv6.txt\n"; + } + unless ($STOPFORUMSPAMV6) { + print IN "\n# Stop Forum Spam IPv6\n"; + print IN "# Details: http://www.stopforumspam.com/downloads/\n"; + print IN "# Many of the lists available contain a vast number of IP addresses so special\n"; + print IN "# care needs to be made when selecting from their lists\n"; + print IN "#STOPFORUMSPAMV6|86400|0|http://www.stopforumspam.com/downloads/listed_ip_1_ipv6.zip\n"; + } + close (IN); + } + + open (OUT, ">", "/var/lib/csf/auto1023"); + flock (OUT, LOCK_EX); + print OUT time; + close (OUT); +} +if (&checkversion("12.02") and !-e "/var/lib/csf/auto1202") { + if (-e "/etc/csf/csf.blocklists") { + sysopen (IN,"/etc/csf/csf.blocklists", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /greensnow/) {$line =~ s/http:/https:/g} + print IN "$line\n"; + } + close (IN); + } + + open (OUT, ">", "/var/lib/csf/auto1202"); + flock (OUT, LOCK_EX); + print OUT time; + close (OUT); +} +if (&checkversion("14.03") and !-e "/var/lib/csf/auto1403") { + if (-e "/etc/csf/csf.blocklists") { + sysopen (IN,"/etc/csf/csf.blocklists", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /dshield/) {$line =~ s/http:/https:/g} + print IN "$line\n"; + } + close (IN); + } +} + +if (-e "/etc/csf/csf.allow") { + sysopen (IN,"/etc/csf/csf.allow", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /^Include \/etc\/csf\/cpanel\.comodo\.allow/) {next} + print IN "$line\n"; + } + close (IN); +} +if (-e "/etc/csf/csf.ignore") { + sysopen (IN,"/etc/csf/csf.ignore", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /^Include \/etc\/csf\/cpanel\.comodo\.ignore/) {next} + print IN "$line\n"; + } + close (IN); +} +if (-e "/usr/local/csf/bin/regex.custom.pm") { + sysopen (IN,"/usr/local/csf/bin/regex.custom.pm", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /^use strict;/) {next} + print IN "$line\n"; + } + close (IN); +} +if (-e "/etc/csf/csf.blocklists") { + sysopen (IN,"/etc/csf/csf.blocklists", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /feeds\.dshield\.org/) {$line =~ s/feeds\.dshield\.org/www\.dshield\.org/g} + if ($line =~ /openbl\.org/i) {next} + if ($line =~ /autoshun/i) {next} + print IN "$line\n"; + } + close (IN); +} +if (-e "/var/lib/csf/csf.tempban") { + sysopen (IN,"/var/lib/csf/csf.tempban", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /^\d+\:/) {$line =~ s/\:/\|/g} + print IN "$line\n"; + } + close (IN); +} +if (-e "/var/lib/csf/csf.tempallow") { + sysopen (IN,"/var/lib/csf/csf.tempallow", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /^\d+\:/) {$line =~ s/\:/\|/g} + print IN "$line\n"; + } + close (IN); +} + +open (IN,"<", "/usr/local/directadmin/data/admin/services.status"); +flock (IN, LOCK_SH); +my @chkservd = ; +close (IN); +chomp @chkservd; + +if (not grep {$_ =~ /^lfd/} @chkservd) { + open (OUT, ">>", "/usr/local/directadmin/data/admin/services.status"); + flock (OUT, LOCK_EX); + print OUT "lfd=ON\n"; + close OUT; +} + +if ($config{TESTING}) { + + open (IN, "<", "/etc/ssh/sshd_config") or die $!; + flock (IN, LOCK_SH) or die $!; + my @sshconfig = ; + close (IN); + chomp @sshconfig; + + my $sshport = "22"; + foreach my $line (@sshconfig) { + if ($line =~ /^Port (\d+)/) {$sshport = $1} + } + + $config{TCP_IN} =~ s/\s//g; + if ($config{TCP_IN} ne "") { + foreach my $port (split(/\,/,$config{TCP_IN})) { + if ($port eq $sshport) {$sshport = "22"} + } + } + + if ($sshport ne "22") { + $config{TCP_IN} .= ",$sshport"; + $config{TCP6_IN} .= ",$sshport"; + open (IN, "<", "/etc/csf/csf.conf") or die $!; + flock (IN, LOCK_SH) or die $!; + my @config = ; + close (IN); + chomp @config; + open (OUT, ">", "/etc/csf/csf.conf") or die $!; + flock (OUT, LOCK_EX) or die $!; + foreach my $line (@config) { + if ($line =~ /^TCP6_IN/) { + print OUT "TCP6_IN = \"$config{TCP6_IN}\"\n"; + print "\n*** SSH port $sshport added to the TCP6_IN port list\n\n"; + } + elsif ($line =~ /^TCP_IN/) { + print OUT "TCP_IN = \"$config{TCP_IN}\"\n"; + print "\n*** SSH port $sshport added to the TCP_IN port list\n\n"; + } + else { + print OUT $line."\n"; + } + } + close OUT; + &loadcsfconfig; + } + + open (FH, "<", "/proc/sys/kernel/osrelease"); + flock (FH, LOCK_SH); + my @data = ; + close (FH); + chomp @data; + if ($data[0] =~ /^(\d+)\.(\d+)\.(\d+)/) { + my $maj = $1; + my $mid = $2; + my $min = $3; + if ($maj == 3 and $mid > 6) { + open (IN, "<", "/etc/csf/csf.conf") or die $!; + flock (IN, LOCK_SH) or die $!; + my @config = ; + close (IN); + chomp @config; + open (OUT, ">", "/etc/csf/csf.conf") or die $!; + flock (OUT, LOCK_EX) or die $!; + foreach my $line (@config) { + if ($line =~ /^USE_CONNTRACK =/) { + print OUT "USE_CONNTRACK = \"1\"\n"; + print "\n*** USE_CONNTRACK Enabled\n\n"; + } else { + print OUT $line."\n"; + } + } + close OUT; + &loadcsfconfig; + } + } + + my @ipdata; + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die "alarm\n"}; + alarm(3); + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, "$config{IPTABLES} --wait -L OUTPUT -nv"); + @ipdata = <$childout>; + waitpid ($cmdpid, 0); + chomp @ipdata; + if ($ipdata[0] =~ /# Warning: iptables-legacy tables present/) {shift @ipdata} + alarm(0); + }; + alarm(0); + if ($@ ne "alarm\n" and $ipdata[0] =~ /^Chain OUTPUT/) { + $config{IPTABLESWAIT} = "--wait"; + $config{WAITLOCK} = 1; + open (IN, "<", "/etc/csf/csf.conf") or die $!; + flock (IN, LOCK_SH) or die $!; + my @config = ; + close (IN); + chomp @config; + open (OUT, ">", "/etc/csf/csf.conf") or die $!; + flock (OUT, LOCK_EX) or die $!; + foreach my $line (@config) { + if ($line =~ /WAITLOCK =/) { + print OUT "WAITLOCK = \"1\"\n"; + } else { + print OUT $line."\n"; + } + } + close OUT; + &loadcsfconfig; + } + + if (-e $config{IP6TABLES} and !$vps) { + my ($childin, $childout); + my $cmdpid; + if (-e $config{IP}) {$cmdpid = open3($childin, $childout, $childout, $config{IP}, "-oneline", "addr")} + elsif (-e $config{IFCONFIG}) {$cmdpid = open3($childin, $childout, $childout, $config{IFCONFIG})} + my @ifconfig = <$childout>; + waitpid ($cmdpid, 0); + chomp @ifconfig; + if (grep {$_ =~ /\s*inet6/} @ifconfig) { + $config{IPV6} = 1; + open (FH, "<", "/proc/sys/kernel/osrelease"); + flock (FH, LOCK_SH); + my @data = ; + close (FH); + chomp @data; + if ($data[0] =~ /^(\d+)\.(\d+)\.(\d+)/) { + my $maj = $1; + my $mid = $2; + my $min = $3; + if (($maj > 2) or (($maj > 1) and ($mid > 6)) or (($maj > 1) and ($mid > 5) and ($min > 19))) { + $config{IPV6_SPI} = 1; + } else { + $config{IPV6_SPI} = 0; + } + } + open (IN, "<", "/etc/csf/csf.conf") or die $!; + flock (IN, LOCK_SH) or die $!; + my @config = ; + close (IN); + chomp @config; + open (OUT, ">", "/etc/csf/csf.conf") or die $!; + flock (OUT, LOCK_EX) or die $!; + foreach my $line (@config) { + if ($line =~ /^IPV6 =/) { + print OUT "IPV6 = \"$config{IPV6}\"\n"; + print "\n*** IPV6 Enabled\n\n"; + } else { + print OUT $line."\n"; + } + } + close OUT; + &loadcsfconfig; + } + } +} + +my $roundcube; +if (&checkversion("14.03") and !-e "/var/lib/csf/auto1403") { + $roundcube = 1.4; + open (my $RC, "<", "/var/www/html/roundcube/program/include/iniset.php"); + flock ($RC, LOCK_SH); + foreach my $line (<$RC>) { + chomp $line; + if ($line =~ /define\s*\(\s*'RCMAIL_VERSION'\s*,\s*'([^']*)'/) { + $roundcube = $1; + last; + } + } + close ($RC); + if ($roundcube < 1.4) {$roundcube = 0} else {$roundcube = 1} +} + +open (IN, "<", "csf.directadmin.conf") or die $!; +flock (IN, LOCK_SH) or die $!; +my @config = ; +close (IN); +chomp @config; +open (OUT, ">", "/etc/csf/csf.conf") or die $!; +flock (OUT, LOCK_EX) or die $!; +foreach my $line (@config) { + if ($line =~ /^\#/) { + print OUT $line."\n"; + next; + } + if ($line !~ /=/) { + print OUT $line."\n"; + next; + } + my ($name,$value) = split (/=/,$line,2); + $name =~ s/\s//g; + if ($value =~ /\"(.*)\"/) { + $value = $1; + } else { + print "Error: Invalid configuration line [$line]"; + } + if (&checkversion("10.15") and !-e "/var/lib/csf/auto1015") { + if ($name eq "MESSENGER_RATE" and $config{$name} eq "30/m") {$config{$name} = "100/s"} + if ($name eq "MESSENGER_BURST" and $config{$name} eq "5") {$config{$name} = "150"} + open (my $AUTO, ">", "/var/lib/csf/auto1015"); + flock ($AUTO, LOCK_EX); + print $AUTO time; + close ($AUTO); + } + if (&checkversion("14.03") and !-e "/var/lib/csf/auto1403" and $name eq "DIRECTADMIN_LOG_R") { + if ($roundcube and $config{$name} !~ /\.log$/) {$config{$name} = "/var/www/html/roundcube/logs/errors.log"} + } + if ($configsetting{$name}) { + print OUT "$name = \"$config{$name}\"\n"; + } else { + if (&checkversion("9.29") and !-e "/var/lib/csf/auto929" and $name eq "PT_USERRSS") { + $line = "PT_USERRSS = \"$config{PT_USERMEM}\""; + open (my $AUTO, ">", "/var/lib/csf/auto929"); + flock ($AUTO, LOCK_EX); + print $AUTO time; + close ($AUTO); + } + if ($name eq "CC_SRC") {$line = "CC_SRC = \"1\""} + print OUT $line."\n"; + print "New setting: $name\n"; + } +} +close OUT; + +if (&checkversion("14.03") and !-e "/var/lib/csf/auto1403") { + open (my $AUTO, ">", "/var/lib/csf/auto1403"); + flock ($AUTO, LOCK_EX); + print $AUTO time; + close ($AUTO); +} + +if ($config{TESTING}) { + my @netstat = `netstat -lpn`; + chomp @netstat; + my @tcpports; + my @udpports; + my @tcp6ports; + my @udp6ports; + foreach my $line (@netstat) { + if ($line =~ /^(\w+).* (\d+\.\d+\.\d+\.\d+):(\d+)/) { + if ($2 eq '127.0.0.1') {next} + if ($1 eq "tcp") { + push @tcpports, $3; + } + elsif ($1 eq "udp") { + push @udpports, $3; + } + } + if ($line =~ /^(\w+).* (::):(\d+) /) { + if ($1 eq "tcp") { + push @tcp6ports, $3; + } + elsif ($1 eq "udp") { + push @udp6ports, $3; + } + } + } + + @tcpports = sort { $a <=> $b } @tcpports; + @udpports = sort { $a <=> $b } @udpports; + @tcp6ports = sort { $a <=> $b } @tcp6ports; + @udp6ports = sort { $a <=> $b } @udp6ports; + + print "\nTCP ports currently listening for incoming connections:\n"; + my $last = ""; + foreach my $port (@tcpports) { + if ($port ne $last) { + if ($port ne $tcpports[0]) {print ","} + print $port; + $last = $port; + } + } + print "\n\nUDP ports currently listening for incoming connections:\n"; + $last = ""; + foreach my $port (@udpports) { + if ($port ne $last) { + if ($port ne $udpports[0]) {print ","} + print $port; + $last = $port; + } + } + my $opts = "TCP_*, UDP_*"; + if (@tcp6ports or @udp6ports) { + $opts .= ", IPV6, TCP6_*, UDP6_*"; + print "\n\nIPv6 TCP ports currently listening for incoming connections:\n"; + my $last = ""; + foreach my $port (@tcp6ports) { + if ($port ne $last) { + if ($port ne $tcp6ports[0]) {print ","} + print $port; + $last = $port; + } + } + print "\n"; + print "\nIPv6 UDP ports currently listening for incoming connections:\n"; + $last = ""; + foreach my $port (@udp6ports) { + if ($port ne $last) { + if ($port ne $udp6ports[0]) {print ","} + print $port; + $last = $port; + } + } + } + print "\n\nNote: The port details above are for information only, csf hasn't been auto-configured.\n\n"; + print "Don't forget to:\n"; + print "1. Configure the following options in the csf configuration to suite your server: $opts\n"; + print "2. Restart csf and lfd\n"; + print "3. Set TESTING to 0 once you're happy with the firewall, lfd will not run until you do so\n"; +} + +if ($ENV{SSH_CLIENT}) { + my $ip = (split(/ /,$ENV{SSH_CLIENT}))[0]; + if ($ip =~ /(\d+\.\d+\.\d+\.\d+)/) { + print "\nAdding current SSH session IP address to the csf whitelist in csf.allow:\n"; + system("/usr/sbin/csf -a $1 csf SSH installation/upgrade IP address"); + } +} + +exit; +############################################################################### +sub loadcsfconfig { + open (IN, "<", "/etc/csf/csf.conf") or die $!; + flock (IN, LOCK_SH) or die $!; + my @config = ; + close (IN); + chomp @config; + + foreach my $line (@config) { + if ($line =~ /^\#/) {next} + if ($line !~ /=/) {next} + my ($name,$value) = split (/=/,$line,2); + $name =~ s/\s//g; + if ($value =~ /\"(.*)\"/) { + $value = $1; + } else { + print "Error: Invalid configuration line [$line]"; + } + $config{$name} = $value; + $configsetting{$name} = 1; + } + return; +} +############################################################################### +sub checkversion { + my $version = shift; + my ($maj, $min) = split(/\./,$version); + my ($oldmaj, $oldmin) = split(/\./,$oldversion); + + if ($oldmaj == 0 or $oldmaj eq "") {return 0} + + if (($oldmaj < $maj) or ($oldmaj == $maj and $oldmin < $min)) {return 1} else {return 0} +} +############################################################################### diff --git a/csf/auto.generic.pl b/csf/auto.generic.pl new file mode 100644 index 0000000..283f45e --- /dev/null +++ b/csf/auto.generic.pl @@ -0,0 +1,589 @@ +#!/usr/bin/perl +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +## no critic (ProhibitBarewordFileHandles, ProhibitExplicitReturnUndef, ProhibitMixedBooleanOperators, RequireBriefOpen) +use strict; +use Fcntl qw(:DEFAULT :flock); +use IPC::Open3; + +umask(0177); + +our (%config, %configsetting, $vps, $oldversion); + +$oldversion = $ARGV[0]; + +open (VERSION, "<","/etc/csf/version.txt"); +flock (VERSION, LOCK_SH); +my $version = ; +close (VERSION); +chomp $version; +$version =~ s/\W/_/g; +system("/bin/cp","-avf","/etc/csf/csf.conf","/var/lib/csf/backup/".time."_pre_v${version}_upgrade"); + +&loadcsfconfig; + +if (-e "/proc/vz/veinfo") { + $vps = 1; +} else { + open (IN, "<","/proc/self/status"); + flock (IN, LOCK_SH); + while (my $line = ) { + chomp $line; + if ($line =~ /^envID:\s*(\d+)\s*$/) { + if ($1 > 0) { + $vps = 1; + last; + } + } + } + close (IN); +} + +foreach my $alertfile ("sshalert.txt","sualert.txt","sudoalert.txt","webminalert.txt","cpanelalert.txt") { + if (-e "/usr/local/csf/tpl/".$alertfile) { + sysopen (my $IN, "/usr/local/csf/tpl/".$alertfile, O_RDWR | O_CREAT); + flock ($IN, LOCK_EX); + my @data = <$IN>; + chomp @data; + my $hit = 0; + foreach my $line (@data) { + if ($line =~ /\[text\]/) {$hit = 1} + } + unless ($hit) { + print $IN "\nLog line:\n\n[text]\n"; + } + close ($IN); + } +} + +if (&checkversion("10.11") and !-e "/var/lib/csf/auto1011") { + if (-e "/var/lib/csf/stats/lfdstats") { + sysopen (STATS,"/var/lib/csf/stats/lfdstats", O_RDWR | O_CREAT); + flock (STATS, LOCK_EX); + my @stats = ; + chomp @stats; + my %ccs; + my @line = split(/\,/,$stats[69]); + for (my $x = 0; $x < @line; $x+=2) {$ccs{$line[$x]} = $line[$x+1]} + $stats[69] = ""; + foreach my $key (keys %ccs) {$stats[69] .= "$key,$ccs{$key},"} + seek (STATS, 0, 0); + truncate (STATS, 0); + foreach my $line (@stats) { + print STATS "$line\n"; + } + close (STATS); + } + + open (OUT, ">", "/var/lib/csf/auto1011"); + flock (OUT, LOCK_EX); + print OUT time; + close (OUT); +} +if (&checkversion("10.23") and !-e "/var/lib/csf/auto1023") { + if (-e "/etc/csf/csf.blocklists") { + sysopen (IN,"/etc/csf/csf.blocklists", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + my $SPAMDROPV6 = 0; + my $STOPFORUMSPAMV6 = 0; + foreach my $line (@data) { + if ($line =~ /^(\#)?SPAMDROPV6/) {$SPAMDROPV6 = 1} + if ($line =~ /^(\#)?STOPFORUMSPAMV6/) {$STOPFORUMSPAMV6 = 1} + print IN "$line\n"; + } + unless ($SPAMDROPV6) { + print IN "\n# Spamhaus IPv6 Don't Route Or Peer List (DROPv6)\n"; + print IN "# Details: http://www.spamhaus.org/drop/\n"; + print IN "#SPAMDROPV6|86400|0|https://www.spamhaus.org/drop/dropv6.txt\n"; + } + unless ($STOPFORUMSPAMV6) { + print IN "\n# Stop Forum Spam IPv6\n"; + print IN "# Details: http://www.stopforumspam.com/downloads/\n"; + print IN "# Many of the lists available contain a vast number of IP addresses so special\n"; + print IN "# care needs to be made when selecting from their lists\n"; + print IN "#STOPFORUMSPAMV6|86400|0|http://www.stopforumspam.com/downloads/listed_ip_1_ipv6.zip\n"; + } + close (IN); + } + + open (OUT, ">", "/var/lib/csf/auto1023"); + flock (OUT, LOCK_EX); + print OUT time; + close (OUT); +} +if (&checkversion("12.02") and !-e "/var/lib/csf/auto1202") { + if (-e "/etc/csf/csf.blocklists") { + sysopen (IN,"/etc/csf/csf.blocklists", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /greensnow/) {$line =~ s/http:/https:/g} + print IN "$line\n"; + } + close (IN); + } + + open (OUT, ">", "/var/lib/csf/auto1202"); + flock (OUT, LOCK_EX); + print OUT time; + close (OUT); +} +if (&checkversion("14.03") and !-e "/var/lib/csf/auto1403") { + if (-e "/etc/csf/csf.blocklists") { + sysopen (IN,"/etc/csf/csf.blocklists", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /dshield/) {$line =~ s/http:/https:/g} + print IN "$line\n"; + } + close (IN); + } + + open (OUT, ">", "/var/lib/csf/auto1403"); + flock (OUT, LOCK_EX); + print OUT time; + close (OUT); +} + +if (-e "/etc/csf/csf.allow") { + sysopen (IN,"/etc/csf/csf.allow", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /^Include \/etc\/csf\/cpanel\.comodo\.allow/) {next} + print IN "$line\n"; + } + close (IN); +} +if (-e "/etc/csf/csf.ignore") { + sysopen (IN,"/etc/csf/csf.ignore", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /^Include \/etc\/csf\/cpanel\.comodo\.ignore/) {next} + print IN "$line\n"; + } + close (IN); +} +if (-e "/usr/local/csf/bin/regex.custom.pm") { + sysopen (IN,"/usr/local/csf/bin/regex.custom.pm", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /^use strict;/) {next} + print IN "$line\n"; + } + close (IN); +} +if (-e "/etc/csf/csf.blocklists") { + sysopen (IN,"/etc/csf/csf.blocklists", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /feeds\.dshield\.org/) {$line =~ s/feeds\.dshield\.org/www\.dshield\.org/g} + if ($line =~ /openbl\.org/i) {next} + if ($line =~ /autoshun/i) {next} + print IN "$line\n"; + } + close (IN); +} +if (-e "/var/lib/csf/csf.tempban") { + sysopen (IN,"/var/lib/csf/csf.tempban", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /^\d+\:/) {$line =~ s/\:/\|/g} + print IN "$line\n"; + } + close (IN); +} +if (-e "/var/lib/csf/csf.tempallow") { + sysopen (IN,"/var/lib/csf/csf.tempallow", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /^\d+\:/) {$line =~ s/\:/\|/g} + print IN "$line\n"; + } + close (IN); +} + +if ($config{TESTING}) { + + open (IN, "<", "/etc/ssh/sshd_config") or die $!; + flock (IN, LOCK_SH) or die $!; + my @sshconfig = ; + close (IN); + chomp @sshconfig; + + my $sshport = "22"; + foreach my $line (@sshconfig) { + if ($line =~ /^Port (\d+)/) {$sshport = $1} + } + + $config{TCP_IN} =~ s/\s//g; + if ($config{TCP_IN} ne "") { + foreach my $port (split(/\,/,$config{TCP_IN})) { + if ($port eq $sshport) {$sshport = "22"} + } + } + + if ($sshport ne "22") { + $config{TCP_IN} .= ",$sshport"; + $config{TCP6_IN} .= ",$sshport"; + open (IN, "<", "/etc/csf/csf.conf") or die $!; + flock (IN, LOCK_SH) or die $!; + my @config = ; + close (IN); + chomp @config; + open (OUT, ">", "/etc/csf/csf.conf") or die $!; + flock (OUT, LOCK_EX) or die $!; + foreach my $line (@config) { + if ($line =~ /^TCP6_IN/) { + print OUT "TCP6_IN = \"$config{TCP6_IN}\"\n"; + print "\n*** SSH port $sshport added to the TCP6_IN port list\n\n"; + } + elsif ($line =~ /^TCP_IN/) { + print OUT "TCP_IN = \"$config{TCP_IN}\"\n"; + print "\n*** SSH port $sshport added to the TCP_IN port list\n\n"; + } + else { + print OUT $line."\n"; + } + } + close OUT; + &loadcsfconfig; + + } + + open (FH, "<", "/proc/sys/kernel/osrelease"); + flock (IN, LOCK_SH); + my @data = ; + close (FH); + chomp @data; + if ($data[0] =~ /^(\d+)\.(\d+)\.(\d+)/) { + my $maj = $1; + my $mid = $2; + my $min = $3; + if ($maj == 3 and $mid > 6) { + open (IN, "<", "/etc/csf/csf.conf") or die $!; + flock (IN, LOCK_SH) or die $!; + my @config = ; + close (IN); + chomp @config; + open (OUT, ">", "/etc/csf/csf.conf") or die $!; + flock (OUT, LOCK_EX) or die $!; + foreach my $line (@config) { + if ($line =~ /^USE_CONNTRACK =/) { + print OUT "USE_CONNTRACK = \"1\"\n"; + print "\n*** USE_CONNTRACK Enabled\n\n"; + } else { + print OUT $line."\n"; + } + } + close OUT; + &loadcsfconfig; + } + } + + my @ipdata; + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die "alarm\n"}; + alarm(3); + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, "$config{IPTABLES} --wait -L OUTPUT -nv"); + @ipdata = <$childout>; + waitpid ($cmdpid, 0); + chomp @ipdata; + if ($ipdata[0] =~ /# Warning: iptables-legacy tables present/) {shift @ipdata} + alarm(0); + }; + alarm(0); + if ($@ ne "alarm\n" and $ipdata[0] =~ /^Chain OUTPUT/) { + $config{IPTABLESWAIT} = "--wait"; + $config{WAITLOCK} = 1; + open (IN, "<", "/etc/csf/csf.conf") or die $!; + flock (IN, LOCK_SH) or die $!; + my @config = ; + close (IN); + chomp @config; + open (OUT, ">", "/etc/csf/csf.conf") or die $!; + flock (OUT, LOCK_EX) or die $!; + foreach my $line (@config) { + if ($line =~ /WAITLOCK =/) { + print OUT "WAITLOCK = \"1\"\n"; + } else { + print OUT $line."\n"; + } + } + close OUT; + &loadcsfconfig; + } + + if (-e $config{IP6TABLES} and !$vps) { + my ($childin, $childout); + my $cmdpid; + if (-e $config{IP}) {$cmdpid = open3($childin, $childout, $childout, $config{IP}, "-oneline", "addr")} + elsif (-e $config{IFCONFIG}) {$cmdpid = open3($childin, $childout, $childout, $config{IFCONFIG})} + my @ifconfig = <$childout>; + waitpid ($cmdpid, 0); + chomp @ifconfig; + if (grep {$_ =~ /\s*inet6/} @ifconfig) { + $config{IPV6} = 1; + open (FH, "<", "/proc/sys/kernel/osrelease"); + flock (IN, LOCK_SH); + my @data = ; + close (FH); + chomp @data; + if ($data[0] =~ /^(\d+)\.(\d+)\.(\d+)/) { + my $maj = $1; + my $mid = $2; + my $min = $3; + if (($maj > 2) or (($maj > 1) and ($mid > 6)) or (($maj > 1) and ($mid > 5) and ($min > 19))) { + $config{IPV6_SPI} = 1; + } else { + $config{IPV6_SPI} = 0; + } + } + open (IN, "<", "/etc/csf/csf.conf") or die $!; + flock (IN, LOCK_SH) or die $!; + my @config = ; + close (IN); + chomp @config; + open (OUT, ">", "/etc/csf/csf.conf") or die $!; + flock (OUT, LOCK_EX) or die $!; + foreach my $line (@config) { + if ($line =~ /^IPV6 =/) { + print OUT "IPV6 = \"$config{IPV6}\"\n"; + print "\n*** IPV6 Enabled\n\n"; + } + elsif ($line =~ /^IPV6_SPI =/) { + print OUT "IPV6_SPI = \"$config{IPV6_SPI}\"\n"; + print "\n*** IPV6_SPI set to $config{IPV6_SPI}\n\n"; + } else { + print OUT $line."\n"; + } + } + close OUT; + &loadcsfconfig; + } + } +} + +open (IN, "<", "csf.generic.conf") or die $!; +flock (IN, LOCK_SH) or die $!; +my @config = ; +close (IN); +chomp @config; +open (OUT, ">", "/etc/csf/csf.conf") or die $!; +flock (OUT, LOCK_EX) or die $!; +foreach my $line (@config) { + if ($line =~ /^\#/) { + print OUT $line."\n"; + next; + } + if ($line !~ /=/) { + print OUT $line."\n"; + next; + } + my ($name,$value) = split (/=/,$line,2); + $name =~ s/\s//g; + if ($value =~ /\"(.*)\"/) { + $value = $1; + } else { + print "Error: Invalid configuration line [$line]"; + } + if (&checkversion("10.15") and !-e "/var/lib/csf/auto1015") { + if ($name eq "MESSENGER_RATE" and $config{$name} eq "30/m") {$config{$name} = "100/s"} + if ($name eq "MESSENGER_BURST" and $config{$name} eq "5") {$config{$name} = "150"} + open (my $AUTO, ">", "/var/lib/csf/auto1015"); + flock ($AUTO, LOCK_EX); + print $AUTO time; + close ($AUTO); + } + if ($configsetting{$name}) { + print OUT "$name = \"$config{$name}\"\n"; + } else { + if (&checkversion("9.29") and !-e "/var/lib/csf/auto929" and $name eq "PT_USERRSS") { + $line = "PT_USERRSS = \"$config{PT_USERMEM}\""; + open (my $AUTO, ">", "/var/lib/csf/auto929"); + flock ($AUTO, LOCK_EX); + print $AUTO time; + close ($AUTO); + } + if ($name eq "CC_SRC") {$line = "CC_SRC = \"1\""} + print OUT $line."\n"; + print "New setting: $name\n"; + } +} +close OUT; + +if ($config{TESTING}) { + my @netstat = `netstat -lpn`; + chomp @netstat; + my @tcpports; + my @udpports; + my @tcp6ports; + my @udp6ports; + foreach my $line (@netstat) { + if ($line =~ /^(\w+).* (\d+\.\d+\.\d+\.\d+):(\d+)/) { + if ($2 eq '127.0.0.1') {next} + if ($1 eq "tcp") { + push @tcpports, $3; + } + elsif ($1 eq "udp") { + push @udpports, $3; + } + } + if ($line =~ /^(\w+).* (::):(\d+) /) { + if ($1 eq "tcp") { + push @tcp6ports, $3; + } + elsif ($1 eq "udp") { + push @udp6ports, $3; + } + } + } + + @tcpports = sort { $a <=> $b } @tcpports; + @udpports = sort { $a <=> $b } @udpports; + @tcp6ports = sort { $a <=> $b } @tcp6ports; + @udp6ports = sort { $a <=> $b } @udp6ports; + + print "\nTCP ports currently listening for incoming connections:\n"; + my $last = ""; + foreach my $port (@tcpports) { + if ($port ne $last) { + if ($port ne $tcpports[0]) {print ","} + print $port; + $last = $port; + } + } + print "\n\nUDP ports currently listening for incoming connections:\n"; + $last = ""; + foreach my $port (@udpports) { + if ($port ne $last) { + if ($port ne $udpports[0]) {print ","} + print $port; + $last = $port; + } + } + my $opts = "TCP_*, UDP_*"; + if (@tcp6ports or @udp6ports) { + $opts .= ", IPV6, TCP6_*, UDP6_*"; + print "\n\nIPv6 TCP ports currently listening for incoming connections:\n"; + my $last = ""; + foreach my $port (@tcp6ports) { + if ($port ne $last) { + if ($port ne $tcp6ports[0]) {print ","} + print $port; + $last = $port; + } + } + print "\n"; + print "\nIPv6 UDP ports currently listening for incoming connections:\n"; + $last = ""; + foreach my $port (@udp6ports) { + if ($port ne $last) { + if ($port ne $udp6ports[0]) {print ","} + print $port; + $last = $port; + } + } + } + print "\n\nNote: The port details above are for information only, csf hasn't been auto-configured.\n\n"; + print "Don't forget to:\n"; + print "1. Configure the following options in the csf configuration to suite your server: $opts\n"; + print "2. Restart csf and lfd\n"; + print "3. Set TESTING to 0 once you're happy with the firewall, lfd will not run until you do so\n"; +} + +if ($ENV{SSH_CLIENT}) { + my $ip = (split(/ /,$ENV{SSH_CLIENT}))[0]; + if ($ip =~ /(\d+\.\d+\.\d+\.\d+)/) { + print "\nAdding current SSH session IP address to the csf whitelist in csf.allow:\n"; + system("/usr/sbin/csf -a $1 csf SSH installation/upgrade IP address"); + } +} + +exit; +############################################################################### +sub loadcsfconfig { + open (IN, "<", "/etc/csf/csf.conf") or die $!; + flock (IN, LOCK_SH) or die $!; + my @config = ; + close (IN); + chomp @config; + + foreach my $line (@config) { + if ($line =~ /^\#/) {next} + if ($line !~ /=/) {next} + my ($name,$value) = split (/=/,$line,2); + $name =~ s/\s//g; + if ($value =~ /\"(.*)\"/) { + $value = $1; + } else { + print "Error: Invalid configuration line [$line]"; + } + $config{$name} = $value; + $configsetting{$name} = 1; + } + return; +} +############################################################################### +sub checkversion { + my $version = shift; + my ($maj, $min) = split(/\./,$version); + my ($oldmaj, $oldmin) = split(/\./,$oldversion); + + if ($oldmaj == 0 or $oldmaj eq "") {return 0} + + if (($oldmaj < $maj) or ($oldmaj == $maj and $oldmin < $min)) {return 1} else {return 0} +} +############################################################################### diff --git a/csf/auto.interworx.pl b/csf/auto.interworx.pl new file mode 100644 index 0000000..672909c --- /dev/null +++ b/csf/auto.interworx.pl @@ -0,0 +1,589 @@ +#!/usr/bin/perl +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +## no critic (ProhibitBarewordFileHandles, ProhibitExplicitReturnUndef, ProhibitMixedBooleanOperators, RequireBriefOpen) +use strict; +use Fcntl qw(:DEFAULT :flock); +use IPC::Open3; + +umask(0177); + +our (%config, %configsetting, $vps, $oldversion); + +$oldversion = $ARGV[0]; + +open (VERSION, "<","/etc/csf/version.txt"); +flock (VERSION, LOCK_SH); +my $version = ; +close (VERSION); +chomp $version; +$version =~ s/\W/_/g; +system("/bin/cp","-avf","/etc/csf/csf.conf","/var/lib/csf/backup/".time."_pre_v${version}_upgrade"); + +&loadcsfconfig; + +if (-e "/proc/vz/veinfo") { + $vps = 1; +} else { + open (IN, "<","/proc/self/status"); + flock (IN, LOCK_SH); + while (my $line = ) { + chomp $line; + if ($line =~ /^envID:\s*(\d+)\s*$/) { + if ($1 > 0) { + $vps = 1; + last; + } + } + } + close (IN); +} + +foreach my $alertfile ("sshalert.txt","sualert.txt","sudoalert.txt","webminalert.txt","cpanelalert.txt") { + if (-e "/usr/local/csf/tpl/".$alertfile) { + sysopen (my $IN, "/usr/local/csf/tpl/".$alertfile, O_RDWR | O_CREAT); + flock ($IN, LOCK_EX); + my @data = <$IN>; + chomp @data; + my $hit = 0; + foreach my $line (@data) { + if ($line =~ /\[text\]/) {$hit = 1} + } + unless ($hit) { + print $IN "\nLog line:\n\n[text]\n"; + } + close ($IN); + } +} + +if (&checkversion("10.11") and !-e "/var/lib/csf/auto1011") { + if (-e "/var/lib/csf/stats/lfdstats") { + sysopen (STATS,"/var/lib/csf/stats/lfdstats", O_RDWR | O_CREAT); + flock (STATS, LOCK_EX); + my @stats = ; + chomp @stats; + my %ccs; + my @line = split(/\,/,$stats[69]); + for (my $x = 0; $x < @line; $x+=2) {$ccs{$line[$x]} = $line[$x+1]} + $stats[69] = ""; + foreach my $key (keys %ccs) {$stats[69] .= "$key,$ccs{$key},"} + seek (STATS, 0, 0); + truncate (STATS, 0); + foreach my $line (@stats) { + print STATS "$line\n"; + } + close (STATS); + } + + open (OUT, ">", "/var/lib/csf/auto1011"); + flock (OUT, LOCK_EX); + print OUT time; + close (OUT); +} +if (&checkversion("10.23") and !-e "/var/lib/csf/auto1023") { + if (-e "/etc/csf/csf.blocklists") { + sysopen (IN,"/etc/csf/csf.blocklists", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + my $SPAMDROPV6 = 0; + my $STOPFORUMSPAMV6 = 0; + foreach my $line (@data) { + if ($line =~ /^(\#)?SPAMDROPV6/) {$SPAMDROPV6 = 1} + if ($line =~ /^(\#)?STOPFORUMSPAMV6/) {$STOPFORUMSPAMV6 = 1} + print IN "$line\n"; + } + unless ($SPAMDROPV6) { + print IN "\n# Spamhaus IPv6 Don't Route Or Peer List (DROPv6)\n"; + print IN "# Details: http://www.spamhaus.org/drop/\n"; + print IN "#SPAMDROPV6|86400|0|https://www.spamhaus.org/drop/dropv6.txt\n"; + } + unless ($STOPFORUMSPAMV6) { + print IN "\n# Stop Forum Spam IPv6\n"; + print IN "# Details: http://www.stopforumspam.com/downloads/\n"; + print IN "# Many of the lists available contain a vast number of IP addresses so special\n"; + print IN "# care needs to be made when selecting from their lists\n"; + print IN "#STOPFORUMSPAMV6|86400|0|http://www.stopforumspam.com/downloads/listed_ip_1_ipv6.zip\n"; + } + close (IN); + } + + open (OUT, ">", "/var/lib/csf/auto1023"); + flock (OUT, LOCK_EX); + print OUT time; + close (OUT); +} +if (&checkversion("12.02") and !-e "/var/lib/csf/auto1202") { + if (-e "/etc/csf/csf.blocklists") { + sysopen (IN,"/etc/csf/csf.blocklists", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /greensnow/) {$line =~ s/http:/https:/g} + print IN "$line\n"; + } + close (IN); + } + + open (OUT, ">", "/var/lib/csf/auto1202"); + flock (OUT, LOCK_EX); + print OUT time; + close (OUT); +} +if (&checkversion("14.03") and !-e "/var/lib/csf/auto1403") { + if (-e "/etc/csf/csf.blocklists") { + sysopen (IN,"/etc/csf/csf.blocklists", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /dshield/) {$line =~ s/http:/https:/g} + print IN "$line\n"; + } + close (IN); + } + + open (OUT, ">", "/var/lib/csf/auto1403"); + flock (OUT, LOCK_EX); + print OUT time; + close (OUT); +} + +if (-e "/etc/csf/csf.allow") { + sysopen (IN,"/etc/csf/csf.allow", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /^Include \/etc\/csf\/cpanel\.comodo\.allow/) {next} + print IN "$line\n"; + } + close (IN); +} +if (-e "/etc/csf/csf.ignore") { + sysopen (IN,"/etc/csf/csf.ignore", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /^Include \/etc\/csf\/cpanel\.comodo\.ignore/) {next} + print IN "$line\n"; + } + close (IN); +} +if (-e "/usr/local/csf/bin/regex.custom.pm") { + sysopen (IN,"/usr/local/csf/bin/regex.custom.pm", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /^use strict;/) {next} + print IN "$line\n"; + } + close (IN); +} +if (-e "/etc/csf/csf.blocklists") { + sysopen (IN,"/etc/csf/csf.blocklists", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /feeds\.dshield\.org/) {$line =~ s/feeds\.dshield\.org/www\.dshield\.org/g} + if ($line =~ /openbl\.org/i) {next} + if ($line =~ /autoshun/i) {next} + print IN "$line\n"; + } + close (IN); +} +if (-e "/var/lib/csf/csf.tempban") { + sysopen (IN,"/var/lib/csf/csf.tempban", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /^\d+\:/) {$line =~ s/\:/\|/g} + print IN "$line\n"; + } + close (IN); +} +if (-e "/var/lib/csf/csf.tempallow") { + sysopen (IN,"/var/lib/csf/csf.tempallow", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /^\d+\:/) {$line =~ s/\:/\|/g} + print IN "$line\n"; + } + close (IN); +} + +if ($config{TESTING}) { + + open (IN, "<", "/etc/ssh/sshd_config") or die $!; + flock (IN, LOCK_SH) or die $!; + my @sshconfig = ; + close (IN); + chomp @sshconfig; + + my $sshport = "22"; + foreach my $line (@sshconfig) { + if ($line =~ /^Port (\d+)/) {$sshport = $1} + } + + $config{TCP_IN} =~ s/\s//g; + if ($config{TCP_IN} ne "") { + foreach my $port (split(/\,/,$config{TCP_IN})) { + if ($port eq $sshport) {$sshport = "22"} + } + } + + if ($sshport ne "22") { + $config{TCP_IN} .= ",$sshport"; + $config{TCP6_IN} .= ",$sshport"; + open (IN, "<", "/etc/csf/csf.conf") or die $!; + flock (IN, LOCK_SH) or die $!; + my @config = ; + close (IN); + chomp @config; + open (OUT, ">", "/etc/csf/csf.conf") or die $!; + flock (OUT, LOCK_EX) or die $!; + foreach my $line (@config) { + if ($line =~ /^TCP6_IN/) { + print OUT "TCP6_IN = \"$config{TCP6_IN}\"\n"; + print "\n*** SSH port $sshport added to the TCP6_IN port list\n\n"; + } + elsif ($line =~ /^TCP_IN/) { + print OUT "TCP_IN = \"$config{TCP_IN}\"\n"; + print "\n*** SSH port $sshport added to the TCP_IN port list\n\n"; + } + else { + print OUT $line."\n"; + } + } + close OUT; + &loadcsfconfig; + + } + + open (FH, "<", "/proc/sys/kernel/osrelease"); + flock (IN, LOCK_SH); + my @data = ; + close (FH); + chomp @data; + if ($data[0] =~ /^(\d+)\.(\d+)\.(\d+)/) { + my $maj = $1; + my $mid = $2; + my $min = $3; + if ($maj == 3 and $mid > 6) { + open (IN, "<", "/etc/csf/csf.conf") or die $!; + flock (IN, LOCK_SH) or die $!; + my @config = ; + close (IN); + chomp @config; + open (OUT, ">", "/etc/csf/csf.conf") or die $!; + flock (OUT, LOCK_EX) or die $!; + foreach my $line (@config) { + if ($line =~ /^USE_CONNTRACK =/) { + print OUT "USE_CONNTRACK = \"1\"\n"; + print "\n*** USE_CONNTRACK Enabled\n\n"; + } else { + print OUT $line."\n"; + } + } + close OUT; + &loadcsfconfig; + } + } + + my @ipdata; + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die "alarm\n"}; + alarm(3); + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, "$config{IPTABLES} --wait -L OUTPUT -nv"); + @ipdata = <$childout>; + waitpid ($cmdpid, 0); + chomp @ipdata; + if ($ipdata[0] =~ /# Warning: iptables-legacy tables present/) {shift @ipdata} + alarm(0); + }; + alarm(0); + if ($@ ne "alarm\n" and $ipdata[0] =~ /^Chain OUTPUT/) { + $config{IPTABLESWAIT} = "--wait"; + $config{WAITLOCK} = 1; + open (IN, "<", "/etc/csf/csf.conf") or die $!; + flock (IN, LOCK_SH) or die $!; + my @config = ; + close (IN); + chomp @config; + open (OUT, ">", "/etc/csf/csf.conf") or die $!; + flock (OUT, LOCK_EX) or die $!; + foreach my $line (@config) { + if ($line =~ /WAITLOCK =/) { + print OUT "WAITLOCK = \"1\"\n"; + } else { + print OUT $line."\n"; + } + } + close OUT; + &loadcsfconfig; + } + + if (-e $config{IP6TABLES} and !$vps) { + my ($childin, $childout); + my $cmdpid; + if (-e $config{IP}) {$cmdpid = open3($childin, $childout, $childout, $config{IP}, "-oneline", "addr")} + elsif (-e $config{IFCONFIG}) {$cmdpid = open3($childin, $childout, $childout, $config{IFCONFIG})} + my @ifconfig = <$childout>; + waitpid ($cmdpid, 0); + chomp @ifconfig; + if (grep {$_ =~ /\s*inet6/} @ifconfig) { + $config{IPV6} = 1; + open (FH, "<", "/proc/sys/kernel/osrelease"); + flock (IN, LOCK_SH); + my @data = ; + close (FH); + chomp @data; + if ($data[0] =~ /^(\d+)\.(\d+)\.(\d+)/) { + my $maj = $1; + my $mid = $2; + my $min = $3; + if (($maj > 2) or (($maj > 1) and ($mid > 6)) or (($maj > 1) and ($mid > 5) and ($min > 19))) { + $config{IPV6_SPI} = 1; + } else { + $config{IPV6_SPI} = 0; + } + } + open (IN, "<", "/etc/csf/csf.conf") or die $!; + flock (IN, LOCK_SH) or die $!; + my @config = ; + close (IN); + chomp @config; + open (OUT, ">", "/etc/csf/csf.conf") or die $!; + flock (OUT, LOCK_EX) or die $!; + foreach my $line (@config) { + if ($line =~ /^IPV6 =/) { + print OUT "IPV6 = \"$config{IPV6}\"\n"; + print "\n*** IPV6 Enabled\n\n"; + } + elsif ($line =~ /^IPV6_SPI =/) { + print OUT "IPV6_SPI = \"$config{IPV6_SPI}\"\n"; + print "\n*** IPV6_SPI set to $config{IPV6_SPI}\n\n"; + } else { + print OUT $line."\n"; + } + } + close OUT; + &loadcsfconfig; + } + } +} + +open (IN, "<", "csf.interworx.conf") or die $!; +flock (IN, LOCK_SH) or die $!; +my @config = ; +close (IN); +chomp @config; +open (OUT, ">", "/etc/csf/csf.conf") or die $!; +flock (OUT, LOCK_EX) or die $!; +foreach my $line (@config) { + if ($line =~ /^\#/) { + print OUT $line."\n"; + next; + } + if ($line !~ /=/) { + print OUT $line."\n"; + next; + } + my ($name,$value) = split (/=/,$line,2); + $name =~ s/\s//g; + if ($value =~ /\"(.*)\"/) { + $value = $1; + } else { + print "Error: Invalid configuration line [$line]"; + } + if (&checkversion("10.15") and !-e "/var/lib/csf/auto1015") { + if ($name eq "MESSENGER_RATE" and $config{$name} eq "30/m") {$config{$name} = "100/s"} + if ($name eq "MESSENGER_BURST" and $config{$name} eq "5") {$config{$name} = "150"} + open (my $AUTO, ">", "/var/lib/csf/auto1015"); + flock ($AUTO, LOCK_EX); + print $AUTO time; + close ($AUTO); + } + if ($configsetting{$name}) { + print OUT "$name = \"$config{$name}\"\n"; + } else { + if (&checkversion("9.29") and !-e "/var/lib/csf/auto929" and $name eq "PT_USERRSS") { + $line = "PT_USERRSS = \"$config{PT_USERMEM}\""; + open (my $AUTO, ">", "/var/lib/csf/auto929"); + flock ($AUTO, LOCK_EX); + print $AUTO time; + close ($AUTO); + } + if ($name eq "CC_SRC") {$line = "CC_SRC = \"1\""} + print OUT $line."\n"; + print "New setting: $name\n"; + } +} +close OUT; + +if ($config{TESTING}) { + my @netstat = `netstat -lpn`; + chomp @netstat; + my @tcpports; + my @udpports; + my @tcp6ports; + my @udp6ports; + foreach my $line (@netstat) { + if ($line =~ /^(\w+).* (\d+\.\d+\.\d+\.\d+):(\d+)/) { + if ($2 eq '127.0.0.1') {next} + if ($1 eq "tcp") { + push @tcpports, $3; + } + elsif ($1 eq "udp") { + push @udpports, $3; + } + } + if ($line =~ /^(\w+).* (::):(\d+) /) { + if ($1 eq "tcp") { + push @tcp6ports, $3; + } + elsif ($1 eq "udp") { + push @udp6ports, $3; + } + } + } + + @tcpports = sort { $a <=> $b } @tcpports; + @udpports = sort { $a <=> $b } @udpports; + @tcp6ports = sort { $a <=> $b } @tcp6ports; + @udp6ports = sort { $a <=> $b } @udp6ports; + + print "\nTCP ports currently listening for incoming connections:\n"; + my $last = ""; + foreach my $port (@tcpports) { + if ($port ne $last) { + if ($port ne $tcpports[0]) {print ","} + print $port; + $last = $port; + } + } + print "\n\nUDP ports currently listening for incoming connections:\n"; + $last = ""; + foreach my $port (@udpports) { + if ($port ne $last) { + if ($port ne $udpports[0]) {print ","} + print $port; + $last = $port; + } + } + my $opts = "TCP_*, UDP_*"; + if (@tcp6ports or @udp6ports) { + $opts .= ", IPV6, TCP6_*, UDP6_*"; + print "\n\nIPv6 TCP ports currently listening for incoming connections:\n"; + my $last = ""; + foreach my $port (@tcp6ports) { + if ($port ne $last) { + if ($port ne $tcp6ports[0]) {print ","} + print $port; + $last = $port; + } + } + print "\n"; + print "\nIPv6 UDP ports currently listening for incoming connections:\n"; + $last = ""; + foreach my $port (@udp6ports) { + if ($port ne $last) { + if ($port ne $udp6ports[0]) {print ","} + print $port; + $last = $port; + } + } + } + print "\n\nNote: The port details above are for information only, csf hasn't been auto-configured.\n\n"; + print "Don't forget to:\n"; + print "1. Configure the following options in the csf configuration to suite your server: $opts\n"; + print "2. Restart csf and lfd\n"; + print "3. Set TESTING to 0 once you're happy with the firewall, lfd will not run until you do so\n"; +} + +if ($ENV{SSH_CLIENT}) { + my $ip = (split(/ /,$ENV{SSH_CLIENT}))[0]; + if ($ip =~ /(\d+\.\d+\.\d+\.\d+)/) { + print "\nAdding current SSH session IP address to the csf whitelist in csf.allow:\n"; + system("/usr/sbin/csf -a $1 csf SSH installation/upgrade IP address"); + } +} + +exit; +############################################################################### +sub loadcsfconfig { + open (IN, "<", "/etc/csf/csf.conf") or die $!; + flock (IN, LOCK_SH) or die $!; + my @config = ; + close (IN); + chomp @config; + + foreach my $line (@config) { + if ($line =~ /^\#/) {next} + if ($line !~ /=/) {next} + my ($name,$value) = split (/=/,$line,2); + $name =~ s/\s//g; + if ($value =~ /\"(.*)\"/) { + $value = $1; + } else { + print "Error: Invalid configuration line [$line]"; + } + $config{$name} = $value; + $configsetting{$name} = 1; + } + return; +} +############################################################################### +sub checkversion { + my $version = shift; + my ($maj, $min) = split(/\./,$version); + my ($oldmaj, $oldmin) = split(/\./,$oldversion); + + if ($oldmaj == 0 or $oldmaj eq "") {return 0} + + if (($oldmaj < $maj) or ($oldmaj == $maj and $oldmin < $min)) {return 1} else {return 0} +} +############################################################################### diff --git a/csf/auto.pl b/csf/auto.pl new file mode 100644 index 0000000..6f848a7 --- /dev/null +++ b/csf/auto.pl @@ -0,0 +1,1252 @@ +#!/usr/bin/perl +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +## no critic (ProhibitBarewordFileHandles, ProhibitExplicitReturnUndef, ProhibitMixedBooleanOperators, RequireBriefOpen) +use strict; +use lib '/usr/local/csf/lib'; +use Fcntl qw(:DEFAULT :flock); +use IPC::Open3; + +umask(0177); + +our (%config, %configsetting, $vps, $oldversion); + +$oldversion = $ARGV[0]; + +open (VERSION, "<","/etc/csf/version.txt"); +flock (VERSION, LOCK_SH); +my $version = ; +close (VERSION); +chomp $version; +$version =~ s/\W/_/g; +system("/bin/cp","-avf","/etc/csf/csf.conf","/var/lib/csf/backup/".time."_pre_v${version}_upgrade"); + +&loadcsfconfig; + +if (-e "/proc/vz/veinfo") { + $vps = 1; +} else { + open (IN, "<","/proc/self/status"); + flock (IN, LOCK_SH); + while (my $line = ) { + chomp $line; + if ($line =~ /^envID:\s*(\d+)\s*$/) { + if ($1 > 0) { + $vps = 1; + last; + } + } + } + close (IN); +} + +if ($config{GENERIC}) { + exec "./auto.generic.pl"; + exit; +} + +foreach my $alertfile ("sshalert.txt","sualert.txt","sudoalert.txt","webminalert.txt","cpanelalert.txt") { + if (-e "/usr/local/csf/tpl/".$alertfile) { + sysopen (my $IN, "/usr/local/csf/tpl/".$alertfile, O_RDWR | O_CREAT); + flock ($IN, LOCK_EX); + my @data = <$IN>; + chomp @data; + my $hit = 0; + foreach my $line (@data) { + if ($line =~ /\[text\]/) {$hit = 1} + } + unless ($hit) { + print $IN "\nLog line:\n\n[text]\n"; + } + close ($IN); + } +} + +if (&checkversion("7.72") and -e "/etc/csf/csf.pignore" and !-e "/var/lib/csf/auto772") { + my %pignore = ( + 'exe:/usr/libexec/dovecot/dict' => 1, + 'exe:/usr/libexec/mysqld' => 1, + 'exe:/usr/local/cpanel/3rdparty/sbin/p0f' => 1, + 'exe:/usr/local/cpanel/cpanel' => 1, + 'exe:/usr/sbin/chronyd' => 1, + 'exe:/usr/lib/polkit-1/polkitd' => 1, + '#cmd:/bin/sh /usr/bin/mysqld_safe' => 1, + 'exe:/usr/sbin/exim' => 1); + sysopen (IN,"/etc/csf/csf.pignore", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($pignore{lc $line}) {delete $pignore{$line}} + print IN "$line\n"; + } + foreach my $line (keys %pignore) { + print IN "$line\n"; + } + close (IN); + open (OUT, ">", "/var/lib/csf/auto772"); + flock (OUT, LOCK_EX); + print OUT time; + close (OUT); +} +if (&checkversion("8.04") and -e "/etc/csf/csf.pignore" and !-e "/var/lib/csf/auto804") { + my %pignore = ( + 'exe:/usr/local/cpanel/bin/pkgacct' => 1, + 'exe:/usr/libexec/dovecot/anvil' => 1, + 'exe:/usr/libexec/dovecot/auth' => 1, + 'exe:/usr/sbin/nscd' => 1); + sysopen (IN,"/etc/csf/csf.pignore", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($pignore{lc $line}) {delete $pignore{$line}} + print IN "$line\n"; + } + foreach my $line (keys %pignore) { + print IN "$line\n"; + } + close (IN); + open (OUT, ">", "/var/lib/csf/auto804"); + flock (OUT, LOCK_EX); + print OUT time; + close (OUT); +} +if (&checkversion("8.06") and -e "/etc/csf/csf.pignore" and !-e "/var/lib/csf/auto806") { + my %pignore = ( + 'exe:/usr/bin/dbus-daemon' => 1, + 'exe:/usr/sbin/httpd' => 1); + sysopen (IN,"/etc/csf/csf.pignore", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($pignore{lc $line}) {delete $pignore{$line}} + print IN "$line\n"; + } + foreach my $line (keys %pignore) { + print IN "$line\n"; + } + close (IN); + open (OUT, ">", "/var/lib/csf/auto806"); + flock (OUT, LOCK_EX); + print OUT time; + close (OUT); +} +if (&checkversion("8.13") and -e "/etc/csf/csf.pignore" and !-e "/var/lib/csf/auto813") { + my %pignore = ( + 'exe:/usr/local/cpanel/3rdparty/php/54/sbin/php-fpm' => 1); + sysopen (IN,"/etc/csf/csf.pignore", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($pignore{lc $line}) {delete $pignore{$line}} + print IN "$line\n"; + } + foreach my $line (keys %pignore) { + print IN "$line\n"; + } + close (IN); + open (OUT, ">", "/var/lib/csf/auto813"); + flock (OUT, LOCK_EX); + print OUT time; + close (OUT); +} +if (&checkversion("8.26") and -e "/etc/csf/csf.pignore" and !-e "/var/lib/csf/auto826") { + my %pignore = ( + 'exe:/usr/libexec/dovecot/quota-status' => 1, + 'exe:/usr/libexec/dovecot/stats' => 1); + sysopen (IN,"/etc/csf/csf.pignore", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($pignore{lc $line}) {delete $pignore{$line}} + print IN "$line\n"; + } + foreach my $line (keys %pignore) { + print IN "$line\n"; + } + close (IN); + open (OUT, ">", "/var/lib/csf/auto826"); + flock (OUT, LOCK_EX); + print OUT time; + close (OUT); +} +if (&checkversion("8.27") and -e "/etc/csf/csf.pignore" and !-e "/var/lib/csf/auto827") { + my %pignore = ( + 'exe:/usr/libexec/dovecot/lmtp' => 1); + sysopen (IN,"/etc/csf/csf.pignore", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($pignore{lc $line}) {delete $pignore{$line}} + print IN "$line\n"; + } + foreach my $line (keys %pignore) { + print IN "$line\n"; + } + close (IN); + open (OUT, ">", "/var/lib/csf/auto827"); + flock (OUT, LOCK_EX); + print OUT time; + close (OUT); +} +if (&checkversion("9.00") and !-e "/var/lib/csf/auto900") { + my %pignore = ( + 'exe:/usr/local/cpanel/3rdparty/php/54/bin/php-cgi' => 1, + 'exe:/usr/local/cpanel/3rdparty/php/56/bin/php-cgi' => 1, + 'exe:/usr/local/cpanel/3rdparty/php/56/sbin/php-fpm' => 1); + sysopen (IN,"/etc/csf/csf.pignore", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($pignore{lc $line}) {delete $pignore{$line}} + print IN "$line\n"; + } + foreach my $line (keys %pignore) { + print IN "$line\n"; + } + close (IN); + + my %allow = ( + 'Include /etc/csf/cpanel.comodo.allow' => 1); + sysopen (IN,"/etc/csf/csf.allow", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($allow{$line}) {delete $allow{$line}} + print IN "$line\n"; + } + foreach my $line (keys %allow) { + print IN "$line\n"; + } + close (IN); + + my %ignore = ( + 'Include /etc/csf/cpanel.comodo.ignore' => 1); + sysopen (IN,"/etc/csf/csf.ignore", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($ignore{$line}) {delete $ignore{$line}} + print IN "$line\n"; + } + foreach my $line (keys %ignore) { + print IN "$line\n"; + } + close (IN); + + open (OUT, ">", "/var/lib/csf/auto900"); + flock (OUT, LOCK_EX); + print OUT time; + close (OUT); +} +if (&checkversion("9.12") and -e "/etc/csf/csf.pignore" and !-e "/var/lib/csf/auto912") { + my %pignore = ( + 'exe:/usr/local/cpanel/bin/whm_xfer_download-ssl' => 1, + 'exe:/usr/local/cpanel/bin/autossl_check' => 1, + 'exe:/usr/sbin/pdns_server' => 1); + sysopen (IN,"/etc/csf/csf.pignore", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($pignore{lc $line}) {delete $pignore{$line}} + print IN "$line\n"; + } + foreach my $line (keys %pignore) { + print IN "$line\n"; + } + close (IN); + open (OUT, ">", "/var/lib/csf/auto912"); + flock (OUT, LOCK_EX); + print OUT time; + close (OUT); +} +if (&checkversion("10.02") and -e "/etc/csf/csf.pignore" and !-e "/var/lib/csf/auto1002") { + my %pignore = ( + 'pexe:^/usr/lib/jvm/java-.*/jre/bin/java$' => 1); + sysopen (IN,"/etc/csf/csf.pignore", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($pignore{lc $line}) {delete $pignore{$line}} + print IN "$line\n"; + } + foreach my $line (keys %pignore) { + print IN "$line\n"; + } + close (IN); + open (OUT, ">", "/var/lib/csf/auto1002"); + flock (OUT, LOCK_EX); + print OUT time; + close (OUT); +} +if (&checkversion("10.06") and -e "/etc/csf/csf.pignore" and !-e "/var/lib/csf/auto1006") { + my %pignore = ( + 'exe:/usr/libexec/dovecot/indexer' => 1, + 'exe:/usr/libexec/dovecot/indexer-worker' => 1); + sysopen (IN,"/etc/csf/csf.pignore", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($pignore{lc $line}) {delete $pignore{$line}} + print IN "$line\n"; + } + foreach my $line (keys %pignore) { + print IN "$line\n"; + } + close (IN); + open (OUT, ">", "/var/lib/csf/auto1006"); + flock (OUT, LOCK_EX); + print OUT time; + close (OUT); +} +if (&checkversion("10.08") and !-e "/var/lib/csf/auto1008") { + my %allow = ( + 'Include /etc/csf/cpanel.allow' => 1); + sysopen (IN,"/etc/csf/csf.allow", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($allow{$line}) {delete $allow{$line}} + print IN "$line\n"; + } + foreach my $line (keys %allow) { + print IN "$line\n"; + } + close (IN); + + my %ignore = ( + 'Include /etc/csf/cpanel.ignore' => 1); + sysopen (IN,"/etc/csf/csf.ignore", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($ignore{$line}) {delete $ignore{$line}} + print IN "$line\n"; + } + foreach my $line (keys %ignore) { + print IN "$line\n"; + } + close (IN); + + open (OUT, ">", "/var/lib/csf/auto1008"); + flock (OUT, LOCK_EX); + print OUT time; + close (OUT); +} +if (&checkversion("10.11") and !-e "/var/lib/csf/auto1011") { + if (-e "/var/lib/csf/stats/lfdstats") { + sysopen (STATS,"/var/lib/csf/stats/lfdstats", O_RDWR | O_CREAT); + flock (STATS, LOCK_EX); + my @stats = ; + chomp @stats; + my %ccs; + my @line = split(/\,/,$stats[69]); + for (my $x = 0; $x < @line; $x+=2) {$ccs{$line[$x]} = $line[$x+1]} + $stats[69] = ""; + foreach my $key (keys %ccs) {$stats[69] .= "$key,$ccs{$key},"} + seek (STATS, 0, 0); + truncate (STATS, 0); + foreach my $line (@stats) { + print STATS "$line\n"; + } + close (STATS); + } + + open (OUT, ">", "/var/lib/csf/auto1011"); + flock (OUT, LOCK_EX); + print OUT time; + close (OUT); +} +if (&checkversion("10.23") and !-e "/var/lib/csf/auto1023") { + if (-e "/etc/csf/csf.blocklists") { + sysopen (IN,"/etc/csf/csf.blocklists", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + my $SPAMDROPV6 = 0; + my $STOPFORUMSPAMV6 = 0; + foreach my $line (@data) { + if ($line =~ /^(\#)?SPAMDROPV6/) {$SPAMDROPV6 = 1} + if ($line =~ /^(\#)?STOPFORUMSPAMV6/) {$STOPFORUMSPAMV6 = 1} + print IN "$line\n"; + } + unless ($SPAMDROPV6) { + print IN "\n# Spamhaus IPv6 Don't Route Or Peer List (DROPv6)\n"; + print IN "# Details: http://www.spamhaus.org/drop/\n"; + print IN "#SPAMDROPV6|86400|0|https://www.spamhaus.org/drop/dropv6.txt\n"; + } + unless ($STOPFORUMSPAMV6) { + print IN "\n# Stop Forum Spam IPv6\n"; + print IN "# Details: http://www.stopforumspam.com/downloads/\n"; + print IN "# Many of the lists available contain a vast number of IP addresses so special\n"; + print IN "# care needs to be made when selecting from their lists\n"; + print IN "#STOPFORUMSPAMV6|86400|0|http://www.stopforumspam.com/downloads/listed_ip_1_ipv6.zip\n"; + } + close (IN); + } + + open (OUT, ">", "/var/lib/csf/auto1023"); + flock (OUT, LOCK_EX); + print OUT time; + close (OUT); +} +if (&checkversion("11.07") and -e "/etc/csf/csf.pignore" and !-e "/var/lib/csf/auto1107") { + my %pignore = ( + 'pexe:/usr/local/cpanel/3rdparty/bin/git.*' => 1, + 'pexe:/usr/local/cpanel/3rdparty/libexec/git-core/git.*' => 1); + sysopen (IN,"/etc/csf/csf.pignore", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($pignore{lc $line}) {delete $pignore{$line}} + print IN "$line\n"; + } + foreach my $line (keys %pignore) { + print IN "$line\n"; + } + close (IN); + open (OUT, ">", "/var/lib/csf/auto1107"); + flock (OUT, LOCK_EX); + print OUT time; + close (OUT); +} +if (&checkversion("12.02") and !-e "/var/lib/csf/auto1202") { + if (-e "/etc/csf/csf.blocklists") { + sysopen (IN,"/etc/csf/csf.blocklists", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /greensnow/) {$line =~ s/http:/https:/g} + print IN "$line\n"; + } + close (IN); + } + + open (OUT, ">", "/var/lib/csf/auto1202"); + flock (OUT, LOCK_EX); + print OUT time; + close (OUT); +} +if (&checkversion("12.05") and !-e "/var/lib/csf/auto1205") { + if (-e "/etc/csf/csf.blocklists") { + sysopen (IN,"/etc/csf/csf.blocklists", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /projecthoneypot/) {$line =~ s/http:/https:/g} + print IN "$line\n"; + } + close (IN); + } + + open (OUT, ">", "/var/lib/csf/auto1205"); + flock (OUT, LOCK_EX); + print OUT time; + close (OUT); +} +if (&checkversion("12.07") and -e "/etc/csf/csf.pignore" and !-e "/var/lib/csf/auto1207") { + my %pignore = ( + '#pcmd:ubic-guardian ubic-periodic.*' => 1, + '#pcmd:perl /usr/local/cpanel/3rdparty/perl/\d+/bin/ubic-periodic.*' => 1); + sysopen (IN,"/etc/csf/csf.pignore", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($pignore{lc $line}) {delete $pignore{$line}} + print IN "$line\n"; + } + foreach my $line (keys %pignore) { + print IN "$line\n"; + } + close (IN); + open (OUT, ">", "/var/lib/csf/auto1207"); + flock (OUT, LOCK_EX); + print OUT time; + close (OUT); +} +if (&checkversion("12.10") and -e "/etc/csf/csf.fignore" and !-e "/var/lib/csf/auto1210") { + my %fignore = ('/tmp/yarn--[\d\-\.]+/(node|yarn)' => 1); + sysopen (IN,"/etc/csf/csf.fignore", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($fignore{lc $line}) {delete $fignore{$line}} + print IN "$line\n"; + } + foreach my $line (keys %fignore) { + print IN "$line\n"; + } + close (IN); + open (OUT, ">", "/var/lib/csf/auto1210"); + flock (OUT, LOCK_EX); + print OUT time; + close (OUT); +} +if (&checkversion("14.01") and -e "/etc/csf/csf.pignore" and !-e "/var/lib/csf/auto1401") { + sysopen (IN,"/etc/csf/csf.pignore", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /pcmd:\/usr\/bin\/python \/usr\/local\/cpanel\/3rdparty\/mailman\/bin\//) { + $line =~ s/pcmd:\/usr\/bin\/python /pcmd:\/usr\/bin\/python\.\? /g; + } + print IN "$line\n"; + } + close (IN); + open (OUT, ">", "/var/lib/csf/auto1401"); + flock (OUT, LOCK_EX); + print OUT time; + close (OUT); +} +if (&checkversion("14.02") and -e "/etc/csf/csf.pignore" and !-e "/var/lib/csf/auto1402") { + my %pignore = ( + 'exe:/usr/libexec/dovecot/imap-hibernate' => 1); + sysopen (IN,"/etc/csf/csf.pignore", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($pignore{lc $line}) {delete $pignore{$line}} + print IN "$line\n"; + } + foreach my $line (keys %pignore) { + print IN "$line\n"; + } + close (IN); + open (OUT, ">", "/var/lib/csf/auto1402"); + flock (OUT, LOCK_EX); + print OUT time; + close (OUT); +} +if (&checkversion("14.03") and !-e "/var/lib/csf/auto1403") { + if (-e "/etc/csf/csf.blocklists") { + sysopen (IN,"/etc/csf/csf.blocklists", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /dshield/) {$line =~ s/http:/https:/g} + print IN "$line\n"; + } + close (IN); + } + + open (OUT, ">", "/var/lib/csf/auto1403"); + flock (OUT, LOCK_EX); + print OUT time; + close (OUT); +} +if (&checkversion("14.05") and -e "/etc/csf/csf.pignore" and !-e "/var/lib/csf/auto1405") { + my %pignore = ( + 'exe:/usr/sbin/imunify-notifier' => 1); + sysopen (IN,"/etc/csf/csf.pignore", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($pignore{lc $line}) {delete $pignore{$line}} + print IN "$line\n"; + } + foreach my $line (keys %pignore) { + print IN "$line\n"; + } + close (IN); + open (OUT, ">", "/var/lib/csf/auto1405"); + flock (OUT, LOCK_EX); + print OUT time; + close (OUT); +} +if (&checkversion("14.06") and -e "/etc/csf/csf.pignore" and !-e "/var/lib/csf/auto1406") { + my %pignore = ( + 'exe:/usr/bin/sw-engine' => 1, + 'exe:/usr/sbin/sw-engine-fpm' => 1, + 'exe:/usr/sbin/sw-cp-serverd' => 1); + sysopen (IN,"/etc/csf/csf.pignore", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($pignore{lc $line}) {delete $pignore{$line}} + print IN "$line\n"; + } + foreach my $line (keys %pignore) { + print IN "$line\n"; + } + close (IN); + open (OUT, ">", "/var/lib/csf/auto1406"); + flock (OUT, LOCK_EX); + print OUT time; + close (OUT); +} +if (&checkversion("14.18") and -e "/etc/csf/csf.pignore" and !-e "/var/lib/csf/auto1418") { + my %pignore = ( + 'exe:/usr/local/cpanel/3rdparty/wp-toolkit/bin/wpt-panopticon' => 1); + sysopen (IN,"/etc/csf/csf.pignore", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($pignore{lc $line}) {delete $pignore{$line}} + print IN "$line\n"; + } + foreach my $line (keys %pignore) { + print IN "$line\n"; + } + close (IN); + open (OUT, ">", "/var/lib/csf/auto1418"); + flock (OUT, LOCK_EX); + print OUT time; + close (OUT); +} + +if (-e "/usr/local/csf/bin/regex.custom.pm") { + sysopen (IN,"/usr/local/csf/bin/regex.custom.pm", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /^use strict;/) {next} + print IN "$line\n"; + } + close (IN); +} +if (-e "/etc/csf/csf.blocklists") { + sysopen (IN,"/etc/csf/csf.blocklists", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /feeds\.dshield\.org/) {$line =~ s/feeds\.dshield\.org/www\.dshield\.org/g} + if ($line =~ /openbl\.org/i) {next} + if ($line =~ /autoshun/i) {next} + print IN "$line\n"; + } + close (IN); +} +if (-e "/var/lib/csf/csf.tempban") { + sysopen (IN,"/var/lib/csf/csf.tempban", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /^\d+\:/) {$line =~ s/\:/\|/g} + print IN "$line\n"; + } + close (IN); +} +if (-e "/var/lib/csf/csf.tempallow") { + sysopen (IN,"/var/lib/csf/csf.tempallow", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /^\d+\:/) {$line =~ s/\:/\|/g} + print IN "$line\n"; + } + close (IN); +} +if (-e "/usr/local/csf/tpl/reselleralert.txt") { + sysopen (IN,"/usr/local/csf/tpl/reselleralert.txt", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + my $text = 0; + foreach my $line (@data) { + if ($line =~ /\[text\]/) {$text = 1} + print IN "$line\n"; + } + unless ($text) {print IN "\n[text]\n"} + close (IN); +} + +open (IN,"<", "/etc/chkserv.d/chkservd.conf"); +flock (IN, LOCK_SH); +my @chkservd = ; +close (IN); +chomp @chkservd; + +if (not grep {$_ =~ /^lfd/} @chkservd) { + open (OUT,">", "/etc/chkserv.d/lfd"); + flock (OUT, LOCK_EX); + print OUT "service[lfd]=x,x,x,service lfd restart,lfd,root\n"; + close (OUT); + + sysopen (OUT,"/etc/chkserv.d/chkservd.conf", O_WRONLY | O_CREAT); + flock (OUT, LOCK_EX); + foreach my $line (@chkservd) {print OUT "$line\n"} + print OUT "lfd:1\n"; + close OUT; +} + +if ($config{TESTING}) { + open (IN, "<", "/etc/ssh/sshd_config") or die $!; + flock (IN, LOCK_SH) or die $!; + my @sshconfig = ; + close (IN); + chomp @sshconfig; + + my $sshport = "22"; + foreach my $line (@sshconfig) { + if ($line =~ /^Port (\d+)/) {$sshport = $1} + } + + $config{TCP_IN} =~ s/\s//g; + if ($config{TCP_IN} ne "") { + foreach my $port (split(/\,/,$config{TCP_IN})) { + if ($port eq $sshport) {$sshport = "22"} + } + } + + if ($sshport ne "22") { + $config{TCP_IN} .= ",$sshport"; + $config{TCP6_IN} .= ",$sshport"; + open (IN, "<", "/etc/csf/csf.conf") or die $!; + flock (IN, LOCK_SH) or die $!; + my @config = ; + close (IN); + chomp @config; + open (OUT, ">", "/etc/csf/csf.conf") or die $!; + flock (OUT, LOCK_EX) or die $!; + foreach my $line (@config) { + if ($line =~ /^TCP6_IN/) { + print OUT "TCP6_IN = \"$config{TCP6_IN}\"\n"; + print "\n*** SSH port $sshport added to the TCP6_IN port list\n\n"; + } + elsif ($line =~ /^TCP_IN/) { + print OUT "TCP_IN = \"$config{TCP_IN}\"\n"; + print "\n*** SSH port $sshport added to the TCP_IN port list\n\n"; + } + else { + print OUT $line."\n"; + } + } + close OUT; + &loadcsfconfig; + } + + open (FH, "<", "/proc/sys/kernel/osrelease"); + flock (IN, LOCK_SH); + my @data = ; + close (FH); + chomp @data; + if ($data[0] =~ /^(\d+)\.(\d+)\.(\d+)/) { + my $maj = $1; + my $mid = $2; + my $min = $3; + if ($maj == 3 and $mid > 6) { + open (IN, "<", "/etc/csf/csf.conf") or die $!; + flock (IN, LOCK_SH) or die $!; + my @config = ; + close (IN); + chomp @config; + open (OUT, ">", "/etc/csf/csf.conf") or die $!; + flock (OUT, LOCK_EX) or die $!; + foreach my $line (@config) { + if ($line =~ /^USE_CONNTRACK =/) { + print OUT "USE_CONNTRACK = \"1\"\n"; + print "\n*** USE_CONNTRACK Enabled\n\n"; + } else { + print OUT $line."\n"; + } + } + close OUT; + &loadcsfconfig; + } + } + + open (FH, "<", "/etc/os-release"); + flock (IN, LOCK_SH); + @data = ; + close (FH); + chomp @data; + foreach my $line (@data) { + if ($line =~ /Name\s*=\s*"Ubuntu"/i) { + open (IN, "<", "/etc/csf/csf.conf") or die $!; + flock (IN, LOCK_SH) or die $!; + my @config = ; + close (IN); + chomp @config; + open (OUT, ">", "/etc/csf/csf.conf") or die $!; + flock (OUT, LOCK_EX) or die $!; + foreach my $line (@config) { + if ($line =~ /^SSHD_LOG/) {$line = 'SSHD_LOG = "/var/log/auth.log"'} + if ($line =~ /^WEBMIN_LOG/) {$line = 'WEBMIN_LOG = "/var/log/auth.log"'} + if ($line =~ /^SU_LOG/) {$line = 'SU_LOG = "/var/log/auth.log"'} + if ($line =~ /^SUDO_LOG/) {$line = 'SUDO_LOG = "/var/log/auth.log"'} + if ($line =~ /^POP3D_LOG/) {$line = 'POP3D_LOG = "/var/log/mail.log"'} + if ($line =~ /^IMAPD_LOG/) {$line = 'IMAPD_LOG = "/var/log/mail.log"'} + if ($line =~ /^IPTABLES_LOG/) {$line = 'IPTABLES_LOG = "/var/log/syslog"'} + if ($line =~ /^BIND_LOG/) {$line = 'BIND_LOG = "/var/log/syslog"'} + if ($line =~ /^SYSLOG_LOG/) {$line = 'SYSLOG_LOG = "/var/log/syslog"'} + if ($line =~ /^SUHOSIN_LOG/) {$line = 'SUHOSIN_LOG = "/var/log/syslog"'} + print OUT $line."\n"; + } + close OUT; + &loadcsfconfig; + } + } + + my @ipdata; + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die "alarm\n"}; + alarm(3); + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, "$config{IPTABLES} --wait -L OUTPUT -nv"); + @ipdata = <$childout>; + waitpid ($cmdpid, 0); + chomp @ipdata; + if ($ipdata[0] =~ /# Warning: iptables-legacy tables present/) {shift @ipdata} + alarm(0); + }; + alarm(0); + if ($@ ne "alarm\n" and $ipdata[0] =~ /^Chain OUTPUT/) { + $config{IPTABLESWAIT} = "--wait"; + $config{WAITLOCK} = 1; + open (IN, "<", "/etc/csf/csf.conf") or die $!; + flock (IN, LOCK_SH) or die $!; + my @config = ; + close (IN); + chomp @config; + open (OUT, ">", "/etc/csf/csf.conf") or die $!; + flock (OUT, LOCK_EX) or die $!; + foreach my $line (@config) { + if ($line =~ /WAITLOCK =/) { + print OUT "WAITLOCK = \"1\"\n"; + } else { + print OUT $line."\n"; + } + } + close OUT; + &loadcsfconfig; + } + + if (-e $config{IP6TABLES} and !$vps) { + my ($childin, $childout); + my $cmdpid; + if (-e $config{IP}) {$cmdpid = open3($childin, $childout, $childout, $config{IP}, "-oneline", "addr")} + elsif (-e $config{IFCONFIG}) {$cmdpid = open3($childin, $childout, $childout, $config{IFCONFIG})} + my @ifconfig = <$childout>; + waitpid ($cmdpid, 0); + chomp @ifconfig; + if (grep {$_ =~ /\s*inet6/} @ifconfig) { + $config{IPV6} = 1; + open (FH, "<", "/proc/sys/kernel/osrelease"); + flock (IN, LOCK_SH); + my @data = ; + close (FH); + chomp @data; + if ($data[0] =~ /^(\d+)\.(\d+)\.(\d+)/) { + my $maj = $1; + my $mid = $2; + my $min = $3; + if (($maj > 2) or (($maj > 1) and ($mid > 6)) or (($maj > 1) and ($mid > 5) and ($min > 19))) { + $config{IPV6_SPI} = 1; + } else { + $config{IPV6_SPI} = 0; + } + } + open (IN, "<", "/etc/csf/csf.conf") or die $!; + flock (IN, LOCK_SH) or die $!; + my @config = ; + close (IN); + chomp @config; + open (OUT, ">", "/etc/csf/csf.conf") or die $!; + flock (OUT, LOCK_EX) or die $!; + foreach my $line (@config) { + if ($line =~ /^IPV6 =/) { + print OUT "IPV6 = \"$config{IPV6}\"\n"; + print "\n*** IPV6 Enabled\n\n"; + } + elsif ($line =~ /^IPV6_SPI =/) { + print OUT "IPV6_SPI = \"$config{IPV6_SPI}\"\n"; + print "\n*** IPV6_SPI set to $config{IPV6_SPI}\n\n"; + } else { + print OUT $line."\n"; + } + } + close OUT; + &loadcsfconfig; + } + } + + my $exim = 0; + opendir (DIR, "/etc/chkserv.d"); + while (my $file = readdir (DIR)) { + if ($file =~ /exim-(\d+)/) {$exim = $1} + } + closedir (DIR); + + if ($exim ne "0") { + $config{TCP_IN} .= ",$exim"; + $config{SMTP_PORTS} .= ",$exim"; + open (IN, "<", "/etc/csf/csf.conf") or die $!; + flock (IN, LOCK_SH) or die $!; + my @config = ; + close (IN); + chomp @config; + open (OUT, ">", "/etc/csf/csf.conf") or die $!; + flock (OUT, LOCK_EX) or die $!; + foreach my $line (@config) { + if ($line =~ /^TCP_IN =/) { + print OUT "TCP_IN = \"$config{TCP_IN}\"\n"; + print "\n*** Additional Exim port $exim added to the TCP_IN port list\n\n"; + } + elsif ($line =~ /^SMTP_PORTS =/) { + print OUT "SMTP_PORTS = \"$config{SMTP_PORTS}\"\n"; + print "\n*** Additional Exim port $exim added to the SMTP_PORTS port list\n\n"; + } else { + print OUT $line."\n"; + } + } + close OUT; + &loadcsfconfig; + } + if ($vps) { + print "Adding passive port range for VZ servers\n"; + if (-e "/usr/local/cpanel/version") { + require Cpanel::Config; + import Cpanel::Config; + my $cpconf = Cpanel::Config::loadcpconf(); + my $cpftpfile = ""; + if ($cpconf->{ftpserver} eq "pure-ftpd") {$cpftpfile = "/etc/pure-ftpd.conf"} + elsif ($cpconf->{ftpserver} eq "proftpd") {$cpftpfile = "/etc/proftpd.conf"} + + if ($cpftpfile ne "") { + my $range; + open (my $FTPCONF,"<", $cpftpfile); + flock ($FTPCONF, LOCK_EX); + my @ftp = <$FTPCONF>; + close ($FTPCONF); + foreach my $line (@ftp) { + if ($line =~ /\s*(PassivePortRange|PassivePorts)\s+(\d+)\s+(\d+)/i) { + $range = $2.":".$3; + last; + } + } + if ($range ne "") { + if ($config{TCP_IN} =~ /$range/) { + print "PASV port range $range already exists in TCP_IN/TCP6_IN\n"; + } else { + $config{TCP_IN} .= ",$range"; + $config{TCP6_IN} .= ",$range"; + + sysopen (my $CSFCONF,"/etc/csf/csf.conf", O_RDWR | O_CREAT); + flock ($CSFCONF, LOCK_EX); + my @csf = <$CSFCONF>; + chomp @csf; + seek ($CSFCONF, 0, 0); + truncate ($CSFCONF, 0); + foreach my $line (@csf) { + if ($line =~ /^TCP6_IN/) { + print $CSFCONF "TCP6_IN = \"$config{TCP6_IN}\"\n"; + print "*** PASV port range $range added to the TCP6_IN port list\n"; + } + elsif ($line =~ /^TCP_IN/) { + print $CSFCONF "TCP_IN = \"$config{TCP_IN}\"\n"; + print "*** PASV port range $range added to the TCP_IN port list\n"; + } + else { + print $CSFCONF $line."\n"; + } + } + close ($CSFCONF); + &loadcsfconfig; + } + } + } + } + } +} + +open (IN, "<", "csf.conf") or die $!; +flock (IN, LOCK_SH) or die $!; +my @config = ; +close (IN); +chomp @config; +open (OUT, ">", "/etc/csf/csf.conf") or die $!; +flock (OUT, LOCK_EX) or die $!; +foreach my $line (@config) { + if ($line =~ /^\#/) { + print OUT $line."\n"; + next; + } + if ($line !~ /=/) { + print OUT $line."\n"; + next; + } + my ($name,$value) = split (/=/,$line,2); + $name =~ s/\s//g; + if ($value =~ /\"(.*)\"/) { + $value = $1; + } else { + print "Error: Invalid configuration line [$line]"; + } + if (&checkversion("10.15") and !-e "/var/lib/csf/auto1015") { + if ($name eq "MESSENGER_RATE" and $config{$name} eq "30/m") {$config{$name} = "100/s"} + if ($name eq "MESSENGER_BURST" and $config{$name} eq "5") {$config{$name} = "150"} + open (my $AUTO, ">", "/var/lib/csf/auto1015"); + flock ($AUTO, LOCK_EX); + print $AUTO time; + close ($AUTO); + } + if ($configsetting{$name}) { + print OUT "$name = \"$config{$name}\"\n"; + } else { + if (&checkversion("9.29") and !-e "/var/lib/csf/auto929" and $name eq "PT_USERRSS") { + $line = "PT_USERRSS = \"$config{PT_USERMEM}\""; + open (my $AUTO, ">", "/var/lib/csf/auto929"); + flock ($AUTO, LOCK_EX); + print $AUTO time; + close ($AUTO); + } + if ($name eq "CC_SRC") {$line = "CC_SRC = \"1\""} + print OUT $line."\n"; + print "New setting: $name\n"; + } +} +close OUT; + +if ($config{TESTING}) { + my @netstat = `netstat -lpn`; + chomp @netstat; + my @tcpports; + my @udpports; + my @tcp6ports; + my @udp6ports; + foreach my $line (@netstat) { + if ($line =~ /^(\w+).* (\d+\.\d+\.\d+\.\d+):(\d+)/) { + if ($2 eq '127.0.0.1') {next} + if ($1 eq "tcp") { + push @tcpports, $3; + } + elsif ($1 eq "udp") { + push @udpports, $3; + } + } + if ($line =~ /^(\w+).* (::):(\d+) /) { + if ($1 eq "tcp") { + push @tcp6ports, $3; + } + elsif ($1 eq "udp") { + push @udp6ports, $3; + } + } + } + + @tcpports = sort { $a <=> $b } @tcpports; + @udpports = sort { $a <=> $b } @udpports; + @tcp6ports = sort { $a <=> $b } @tcp6ports; + @udp6ports = sort { $a <=> $b } @udp6ports; + + print "\nTCP ports currently listening for incoming connections:\n"; + my $last = ""; + foreach my $port (@tcpports) { + if ($port ne $last) { + if ($port ne $tcpports[0]) {print ","} + print $port; + $last = $port; + } + } + print "\n\nUDP ports currently listening for incoming connections:\n"; + $last = ""; + foreach my $port (@udpports) { + if ($port ne $last) { + if ($port ne $udpports[0]) {print ","} + print $port; + $last = $port; + } + } + my $opts = "TCP_*, UDP_*"; + if (@tcp6ports or @udp6ports) { + $opts .= ", IPV6, TCP6_*, UDP6_*"; + print "\n\nIPv6 TCP ports currently listening for incoming connections:\n"; + my $last = ""; + foreach my $port (@tcp6ports) { + if ($port ne $last) { + if ($port ne $tcp6ports[0]) {print ","} + print $port; + $last = $port; + } + } + print "\n"; + print "\nIPv6 UDP ports currently listening for incoming connections:\n"; + $last = ""; + foreach my $port (@udp6ports) { + if ($port ne $last) { + if ($port ne $udp6ports[0]) {print ","} + print $port; + $last = $port; + } + } + } + print "\n\nNote: The port details above are for information only, csf hasn't been auto-configured.\n\n"; + print "Don't forget to:\n"; + print "1. Configure the following options in the csf configuration to suite your server: $opts\n"; + print "2. Restart csf and lfd\n"; + print "3. Set TESTING to 0 once you're happy with the firewall, lfd will not run until you do so\n"; +} + +if ($ENV{SSH_CLIENT}) { + my $ip = (split(/ /,$ENV{SSH_CLIENT}))[0]; + if ($ip =~ /(\d+\.\d+\.\d+\.\d+)/) { + print "\nAdding current SSH session IP address to the csf whitelist in csf.allow:\n"; + system("/usr/sbin/csf -a $1 csf SSH installation/upgrade IP address"); + } +} + +if ($config{MESSENGERV2}) { + my $hit; + open (my $ALIASES, "<", "/etc/aliases"); + flock ($ALIASES, LOCK_SH); + while (my $line = <$ALIASES>) { + chomp $line; + my ($alias,$to) = split(/\:\s*/, $line); + if ($alias eq "csf") { + $hit = 1; + last; + } + } + close ($ALIASES); + if (!$hit and !-e "/var/cpanel/users/csf") { + system("/bin/cp /etc/aliases /etc/aliases.".time); + open (my $ALIASESw, ">>", "/etc/aliases"); + flock ($ALIASESw, LOCK_EX); + print $ALIASESw "csf: root\n"; + close ($ALIASESw); + print "Account [csf] added /etc/aliases to prevent cPanel account with the same name (for MESSENGERV2)\n"; + } +} + +exit; +############################################################################### +sub loadcsfconfig { + open (IN, "<", "/etc/csf/csf.conf") or die $!; + flock (IN, LOCK_SH) or die $!; + my @config = ; + close (IN); + chomp @config; + + foreach my $line (@config) { + if ($line =~ /^\#/) {next} + if ($line !~ /=/) {next} + my ($name,$value) = split (/=/,$line,2); + $name =~ s/\s//g; + if ($value =~ /\"(.*)\"/) { + $value = $1; + } else { + print "Error: Invalid configuration line [$line]"; + } + $config{$name} = $value; + $configsetting{$name} = 1; + } + return; +} +############################################################################### +sub checkversion { + my $version = shift; + my ($maj, $min) = split(/\./,$version); + my ($oldmaj, $oldmin) = split(/\./,$oldversion); + + if ($oldmaj == 0 or $oldmaj eq "") {return 0} + + if (($oldmaj < $maj) or ($oldmaj == $maj and $oldmin < $min)) {return 1} else {return 0} +} +############################################################################### diff --git a/csf/auto.vesta.pl b/csf/auto.vesta.pl new file mode 100644 index 0000000..a8d9020 --- /dev/null +++ b/csf/auto.vesta.pl @@ -0,0 +1,605 @@ +#!/usr/bin/perl +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +## no critic (ProhibitBarewordFileHandles, ProhibitExplicitReturnUndef, ProhibitMixedBooleanOperators, RequireBriefOpen) +use strict; +use Fcntl qw(:DEFAULT :flock); +use IPC::Open3; + +umask(0177); + +our (%config, %configsetting, $vps, $oldversion); + +$oldversion = $ARGV[0]; + +open (VERSION, "<","/etc/csf/version.txt"); +flock (VERSION, LOCK_SH); +my $version = ; +close (VERSION); +chomp $version; +$version =~ s/\W/_/g; +system("/bin/cp","-avf","/etc/csf/csf.conf","/var/lib/csf/backup/".time."_pre_v${version}_upgrade"); + +&loadcsfconfig; + +if (-e "/proc/vz/veinfo") { + $vps = 1; +} else { + open (IN, "<","/proc/self/status"); + flock (IN, LOCK_SH); + while (my $line = ) { + chomp $line; + if ($line =~ /^envID:\s*(\d+)\s*$/) { + if ($1 > 0) { + $vps = 1; + last; + } + } + } + close (IN); +} +foreach my $alertfile ("sshalert.txt","sualert.txt","sudoalert.txt","webminalert.txt","cpanelalert.txt") { + if (-e "/usr/local/csf/tpl/".$alertfile) { + sysopen (my $IN, "/usr/local/csf/tpl/".$alertfile, O_RDWR | O_CREAT); + flock ($IN, LOCK_EX); + my @data = <$IN>; + chomp @data; + my $hit = 0; + foreach my $line (@data) { + if ($line =~ /\[text\]/) {$hit = 1} + } + unless ($hit) { + print $IN "\nLog line:\n\n[text]\n"; + } + close ($IN); + } +} + +if (-e "/usr/local/vesta") { + sysopen (my $VESTA, "/usr/local/vesta/web/templates/admin/panel.html", O_RDWR | O_CREAT); + flock ($VESTA, LOCK_EX); + my @data = <$VESTA>; + chomp @data; + seek ($VESTA, 0, 0); + truncate ($VESTA, 0); + foreach my $line (@data) { + if (!(grep {$_ =~ /CSF/} @data) and $line =~ /if\(\$TAB == 'SERVER'/) { + print $VESTA $line."\n"; + print $VESTA "
\">
\n"; + } else { + print $VESTA $line."\n"; + } + } + close ($VESTA); +} + +if (&checkversion("10.11") and !-e "/var/lib/csf/auto1011") { + if (-e "/var/lib/csf/stats/lfdstats") { + sysopen (STATS,"/var/lib/csf/stats/lfdstats", O_RDWR | O_CREAT); + flock (STATS, LOCK_EX); + my @stats = ; + chomp @stats; + my %ccs; + my @line = split(/\,/,$stats[69]); + for (my $x = 0; $x < @line; $x+=2) {$ccs{$line[$x]} = $line[$x+1]} + $stats[69] = ""; + foreach my $key (keys %ccs) {$stats[69] .= "$key,$ccs{$key},"} + seek (STATS, 0, 0); + truncate (STATS, 0); + foreach my $line (@stats) { + print STATS "$line\n"; + } + close (STATS); + } + + open (OUT, ">", "/var/lib/csf/auto1011"); + flock (OUT, LOCK_EX); + print OUT time; + close (OUT); +} +if (&checkversion("10.23") and !-e "/var/lib/csf/auto1023") { + if (-e "/etc/csf/csf.blocklists") { + sysopen (IN,"/etc/csf/csf.blocklists", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + my $SPAMDROPV6 = 0; + my $STOPFORUMSPAMV6 = 0; + foreach my $line (@data) { + if ($line =~ /^(\#)?SPAMDROPV6/) {$SPAMDROPV6 = 1} + if ($line =~ /^(\#)?STOPFORUMSPAMV6/) {$STOPFORUMSPAMV6 = 1} + print IN "$line\n"; + } + unless ($SPAMDROPV6) { + print IN "\n# Spamhaus IPv6 Don't Route Or Peer List (DROPv6)\n"; + print IN "# Details: http://www.spamhaus.org/drop/\n"; + print IN "#SPAMDROPV6|86400|0|https://www.spamhaus.org/drop/dropv6.txt\n"; + } + unless ($STOPFORUMSPAMV6) { + print IN "\n# Stop Forum Spam IPv6\n"; + print IN "# Details: http://www.stopforumspam.com/downloads/\n"; + print IN "# Many of the lists available contain a vast number of IP addresses so special\n"; + print IN "# care needs to be made when selecting from their lists\n"; + print IN "#STOPFORUMSPAMV6|86400|0|http://www.stopforumspam.com/downloads/listed_ip_1_ipv6.zip\n"; + } + close (IN); + } + + open (OUT, ">", "/var/lib/csf/auto1023"); + flock (OUT, LOCK_EX); + print OUT time; + close (OUT); +} +if (&checkversion("12.02") and !-e "/var/lib/csf/auto1202") { + if (-e "/etc/csf/csf.blocklists") { + sysopen (IN,"/etc/csf/csf.blocklists", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /greensnow/) {$line =~ s/http:/https:/g} + print IN "$line\n"; + } + close (IN); + } + + open (OUT, ">", "/var/lib/csf/auto1202"); + flock (OUT, LOCK_EX); + print OUT time; + close (OUT); +} +if (&checkversion("14.03") and !-e "/var/lib/csf/auto1403") { + if (-e "/etc/csf/csf.blocklists") { + sysopen (IN,"/etc/csf/csf.blocklists", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /dshield/) {$line =~ s/http:/https:/g} + print IN "$line\n"; + } + close (IN); + } + + open (OUT, ">", "/var/lib/csf/auto1403"); + flock (OUT, LOCK_EX); + print OUT time; + close (OUT); +} + +if (-e "/etc/csf/csf.allow") { + sysopen (IN,"/etc/csf/csf.allow", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /^Include \/etc\/csf\/cpanel\.comodo\.allow/) {next} + print IN "$line\n"; + } + close (IN); +} +if (-e "/etc/csf/csf.ignore") { + sysopen (IN,"/etc/csf/csf.ignore", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /^Include \/etc\/csf\/cpanel\.comodo\.ignore/) {next} + print IN "$line\n"; + } + close (IN); +} +if (-e "/usr/local/csf/bin/regex.custom.pm") { + sysopen (IN,"/usr/local/csf/bin/regex.custom.pm", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /^use strict;/) {next} + print IN "$line\n"; + } + close (IN); +} +if (-e "/etc/csf/csf.blocklists") { + sysopen (IN,"/etc/csf/csf.blocklists", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /feeds\.dshield\.org/) {$line =~ s/feeds\.dshield\.org/www\.dshield\.org/g} + if ($line =~ /openbl\.org/i) {next} + if ($line =~ /autoshun/i) {next} + print IN "$line\n"; + } + close (IN); +} +if (-e "/var/lib/csf/csf.tempban") { + sysopen (IN,"/var/lib/csf/csf.tempban", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /^\d+\:/) {$line =~ s/\:/\|/g} + print IN "$line\n"; + } + close (IN); +} +if (-e "/var/lib/csf/csf.tempallow") { + sysopen (IN,"/var/lib/csf/csf.tempallow", O_RDWR | O_CREAT); + flock (IN, LOCK_EX); + my @data = ; + chomp @data; + seek (IN, 0, 0); + truncate (IN, 0); + foreach my $line (@data) { + if ($line =~ /^\d+\:/) {$line =~ s/\:/\|/g} + print IN "$line\n"; + } + close (IN); +} + +if ($config{TESTING}) { + + open (IN, "<", "/etc/ssh/sshd_config") or die $!; + flock (IN, LOCK_SH) or die $!; + my @sshconfig = ; + close (IN); + chomp @sshconfig; + + my $sshport = "22"; + foreach my $line (@sshconfig) { + if ($line =~ /^Port (\d+)/) {$sshport = $1} + } + + $config{TCP_IN} =~ s/\s//g; + if ($config{TCP_IN} ne "") { + foreach my $port (split(/\,/,$config{TCP_IN})) { + if ($port eq $sshport) {$sshport = "22"} + } + } + + if ($sshport ne "22") { + $config{TCP_IN} .= ",$sshport"; + $config{TCP6_IN} .= ",$sshport"; + open (IN, "<", "/etc/csf/csf.conf") or die $!; + flock (IN, LOCK_SH) or die $!; + my @config = ; + close (IN); + chomp @config; + open (OUT, ">", "/etc/csf/csf.conf") or die $!; + flock (OUT, LOCK_EX) or die $!; + foreach my $line (@config) { + if ($line =~ /^TCP6_IN/) { + print OUT "TCP6_IN = \"$config{TCP6_IN}\"\n"; + print "\n*** SSH port $sshport added to the TCP6_IN port list\n\n"; + } + elsif ($line =~ /^TCP_IN/) { + print OUT "TCP_IN = \"$config{TCP_IN}\"\n"; + print "\n*** SSH port $sshport added to the TCP_IN port list\n\n"; + } + else { + print OUT $line."\n"; + } + } + close OUT; + &loadcsfconfig; + + } + + open (FH, "<", "/proc/sys/kernel/osrelease"); + flock (IN, LOCK_SH); + my @data = ; + close (FH); + chomp @data; + if ($data[0] =~ /^(\d+)\.(\d+)\.(\d+)/) { + my $maj = $1; + my $mid = $2; + my $min = $3; + if ($maj == 3 and $mid > 6) { + open (IN, "<", "/etc/csf/csf.conf") or die $!; + flock (IN, LOCK_SH) or die $!; + my @config = ; + close (IN); + chomp @config; + open (OUT, ">", "/etc/csf/csf.conf") or die $!; + flock (OUT, LOCK_EX) or die $!; + foreach my $line (@config) { + if ($line =~ /^USE_CONNTRACK =/) { + print OUT "USE_CONNTRACK = \"1\"\n"; + print "\n*** USE_CONNTRACK Enabled\n\n"; + } else { + print OUT $line."\n"; + } + } + close OUT; + &loadcsfconfig; + } + } + + my @ipdata; + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die "alarm\n"}; + alarm(3); + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, "$config{IPTABLES} --wait -L OUTPUT -nv"); + @ipdata = <$childout>; + waitpid ($cmdpid, 0); + chomp @ipdata; + if ($ipdata[0] =~ /# Warning: iptables-legacy tables present/) {shift @ipdata} + alarm(0); + }; + alarm(0); + if ($@ ne "alarm\n" and $ipdata[0] =~ /^Chain OUTPUT/) { + $config{IPTABLESWAIT} = "--wait"; + $config{WAITLOCK} = 1; + open (IN, "<", "/etc/csf/csf.conf") or die $!; + flock (IN, LOCK_SH) or die $!; + my @config = ; + close (IN); + chomp @config; + open (OUT, ">", "/etc/csf/csf.conf") or die $!; + flock (OUT, LOCK_EX) or die $!; + foreach my $line (@config) { + if ($line =~ /WAITLOCK =/) { + print OUT "WAITLOCK = \"1\"\n"; + } else { + print OUT $line."\n"; + } + } + close OUT; + &loadcsfconfig; + } + + if (-e $config{IP6TABLES} and !$vps) { + my ($childin, $childout); + my $cmdpid; + if (-e $config{IP}) {$cmdpid = open3($childin, $childout, $childout, $config{IP}, "-oneline", "addr")} + elsif (-e $config{IFCONFIG}) {$cmdpid = open3($childin, $childout, $childout, $config{IFCONFIG})} + my @ifconfig = <$childout>; + waitpid ($cmdpid, 0); + chomp @ifconfig; + if (grep {$_ =~ /\s*inet6/} @ifconfig) { + $config{IPV6} = 1; + open (FH, "<", "/proc/sys/kernel/osrelease"); + flock (IN, LOCK_SH); + my @data = ; + close (FH); + chomp @data; + if ($data[0] =~ /^(\d+)\.(\d+)\.(\d+)/) { + my $maj = $1; + my $mid = $2; + my $min = $3; + if (($maj > 2) or (($maj > 1) and ($mid > 6)) or (($maj > 1) and ($mid > 5) and ($min > 19))) { + $config{IPV6_SPI} = 1; + } else { + $config{IPV6_SPI} = 0; + } + } + open (IN, "<", "/etc/csf/csf.conf") or die $!; + flock (IN, LOCK_SH) or die $!; + my @config = ; + close (IN); + chomp @config; + open (OUT, ">", "/etc/csf/csf.conf") or die $!; + flock (OUT, LOCK_EX) or die $!; + foreach my $line (@config) { + if ($line =~ /^IPV6 =/) { + print OUT "IPV6 = \"$config{IPV6}\"\n"; + print "\n*** IPV6 Enabled\n\n"; + } + elsif ($line =~ /^IPV6_SPI =/) { + print OUT "IPV6_SPI = \"$config{IPV6_SPI}\"\n"; + print "\n*** IPV6_SPI set to $config{IPV6_SPI}\n\n"; + } else { + print OUT $line."\n"; + } + } + close OUT; + &loadcsfconfig; + } + } +} + +open (IN, "<", "csf.vesta.conf") or die $!; +flock (IN, LOCK_SH) or die $!; +my @config = ; +close (IN); +chomp @config; +open (OUT, ">", "/etc/csf/csf.conf") or die $!; +flock (OUT, LOCK_EX) or die $!; +foreach my $line (@config) { + if ($line =~ /^\#/) { + print OUT $line."\n"; + next; + } + if ($line !~ /=/) { + print OUT $line."\n"; + next; + } + my ($name,$value) = split (/=/,$line,2); + $name =~ s/\s//g; + if ($value =~ /\"(.*)\"/) { + $value = $1; + } else { + print "Error: Invalid configuration line [$line]"; + } + if (&checkversion("10.15") and !-e "/var/lib/csf/auto1015") { + if ($name eq "MESSENGER_RATE" and $config{$name} eq "30/m") {$config{$name} = "100/s"} + if ($name eq "MESSENGER_BURST" and $config{$name} eq "5") {$config{$name} = "150"} + open (my $AUTO, ">", "/var/lib/csf/auto1015"); + flock ($AUTO, LOCK_EX); + print $AUTO time; + close ($AUTO); + } + if ($configsetting{$name}) { + print OUT "$name = \"$config{$name}\"\n"; + } else { + if (&checkversion("9.29") and !-e "/var/lib/csf/auto929" and $name eq "PT_USERRSS") { + $line = "PT_USERRSS = \"$config{PT_USERMEM}\""; + open (my $AUTO, ">", "/var/lib/csf/auto929"); + flock ($AUTO, LOCK_EX); + print $AUTO time; + close ($AUTO); + } + print OUT $line."\n"; + print "New setting: $name\n"; + } +} +close OUT; + +if ($config{TESTING}) { + my @netstat = `netstat -lpn`; + chomp @netstat; + my @tcpports; + my @udpports; + my @tcp6ports; + my @udp6ports; + foreach my $line (@netstat) { + if ($line =~ /^(\w+).* (\d+\.\d+\.\d+\.\d+):(\d+)/) { + if ($2 eq '127.0.0.1') {next} + if ($1 eq "tcp") { + push @tcpports, $3; + } + elsif ($1 eq "udp") { + push @udpports, $3; + } + } + if ($line =~ /^(\w+).* (::):(\d+) /) { + if ($1 eq "tcp") { + push @tcp6ports, $3; + } + elsif ($1 eq "udp") { + push @udp6ports, $3; + } + } + } + + @tcpports = sort { $a <=> $b } @tcpports; + @udpports = sort { $a <=> $b } @udpports; + @tcp6ports = sort { $a <=> $b } @tcp6ports; + @udp6ports = sort { $a <=> $b } @udp6ports; + + print "\nTCP ports currently listening for incoming connections:\n"; + my $last = ""; + foreach my $port (@tcpports) { + if ($port ne $last) { + if ($port ne $tcpports[0]) {print ","} + print $port; + $last = $port; + } + } + print "\n\nUDP ports currently listening for incoming connections:\n"; + $last = ""; + foreach my $port (@udpports) { + if ($port ne $last) { + if ($port ne $udpports[0]) {print ","} + print $port; + $last = $port; + } + } + my $opts = "TCP_*, UDP_*"; + if (@tcp6ports or @udp6ports) { + $opts .= ", IPV6, TCP6_*, UDP6_*"; + print "\n\nIPv6 TCP ports currently listening for incoming connections:\n"; + my $last = ""; + foreach my $port (@tcp6ports) { + if ($port ne $last) { + if ($port ne $tcp6ports[0]) {print ","} + print $port; + $last = $port; + } + } + print "\n"; + print "\nIPv6 UDP ports currently listening for incoming connections:\n"; + $last = ""; + foreach my $port (@udp6ports) { + if ($port ne $last) { + if ($port ne $udp6ports[0]) {print ","} + print $port; + $last = $port; + } + } + } + print "\n\nNote: The port details above are for information only, csf hasn't been auto-configured.\n\n"; + print "Don't forget to:\n"; + print "1. Configure the following options in the csf configuration to suite your server: $opts\n"; + print "2. Restart csf and lfd\n"; + print "3. Set TESTING to 0 once you're happy with the firewall, lfd will not run until you do so\n"; +} + +if ($ENV{SSH_CLIENT}) { + my $ip = (split(/ /,$ENV{SSH_CLIENT}))[0]; + if ($ip =~ /(\d+\.\d+\.\d+\.\d+)/) { + print "\nAdding current SSH session IP address to the csf whitelist in csf.allow:\n"; + system("/usr/sbin/csf -a $1 csf SSH installation/upgrade IP address"); + } +} + +exit; +############################################################################### +sub loadcsfconfig { + open (IN, "<", "/etc/csf/csf.conf") or die $!; + flock (IN, LOCK_SH) or die $!; + my @config = ; + close (IN); + chomp @config; + + foreach my $line (@config) { + if ($line =~ /^\#/) {next} + if ($line !~ /=/) {next} + my ($name,$value) = split (/=/,$line,2); + $name =~ s/\s//g; + if ($value =~ /\"(.*)\"/) { + $value = $1; + } else { + print "Error: Invalid configuration line [$line]"; + } + $config{$name} = $value; + $configsetting{$name} = 1; + } + return; +} +############################################################################### +sub checkversion { + my $version = shift; + my ($maj, $min) = split(/\./,$version); + my ($oldmaj, $oldmin) = split(/\./,$oldversion); + + if ($oldmaj == 0 or $oldmaj eq "") {return 0} + + if (($oldmaj < $maj) or ($oldmaj == $maj and $oldmin < $min)) {return 1} else {return 0} +} +############################################################################### diff --git a/csf/changelog.txt b/csf/changelog.txt new file mode 100644 index 0000000..0e9acae --- /dev/null +++ b/csf/changelog.txt @@ -0,0 +1,6142 @@ +ChangeLog: + +15.00 - Changed license to GPLv3 + +14.24 - Fixed regression bug in v14.23 "Modified UI HTTP header checks to be + case agnostic" + +14.23 - Modified Apache regexes to detect "remote" or "client" as the IP trigger + Mdified UI HTTP header checks to be case agnostic + + Sanitise CC list strings + +14.22 - Removed session IP match check from DA login + + Added example spamassassin temp file regex to csf.fignore for + new installations + +14.21 - Modified IP lookup to strip some missed quotes + + Added exe:/usr/bin/dbus-broker-launch and exe:/usr/bin/dbus-broker to + csf.pignore for new installations + + Added check to ensure that only PUBLIC IP addresses are used when + loading IPv4 CC zone files + + Fixed issue when converting embedded IPv4 addresses in IPv6 connections + +14.20 - Modified MaxMind URLs to use https + + Fixed DOCTYPE print order for integrated UI login + + Added "Require all granted" to Messenger v3 .htaccess generation + + Normalise source IP during connection tracking for IPv6 comparisons + + Fixed regression for some IMAP logon failure detections + +14.19 - Switch to using iptables-nft if it exists in /usr/sbin/iptables-nft + + Added IO::Handle::clearerr() call before reading data from a log file + + Added "Require all granted" to the MESSENGER .htaccess file + + Added UID/GID rules to IPv6 if enabled + + Modified dovecot regex to look for "failed: Connection reset by peer" + +14.18 - Added port 853 for DoT to all new installs + + Added exe wpt-panopticon on cPanel servers to csf.pignore + + Updated list of EOL PHP versions + + Modified HTACCESS regex to include "remote" as well as "client" log + lines + + Implemented DA POST workaround for saving large text files via the UI + + Modified MESSENGER to only send unblock email if a valid IP is + requested + + Modified DA server check to look for multiple php versions in + /usr/local/php* + +14.17 - Removed Security Report recommendations that do not apply to + unsupported control panels + + Updated Security Report to show PHP v7.3 is EOL + + Confirmed support for RHEL v9 + +14.16 - Removed some spurious debug code + + Modified alert templates for: + LF_WEBMIN_EMAIL_ALERT + LF_CPANEL_ALERT + LF_SUDO_EMAIL_ALERT + LF_SU_EMAIL_ALERT + LF_SSH_EMAIL_ALERT + These have been changed to include the log line that triggered the + alert to help give context to the alert and the date/time from the + log to identify when the event occurred. All the relevant templates + are modified to include the log line for existing and new installs + + Implemented an addition check for webmin that we're in the csf module + before creating symlink to the UI script + + Fixed parameter checking for some dovecot regexes + + If DEBUG is enabled and the sendmail binary fails to send an lfd alert, + the email text will now be logged to /var/log/lfd.log with an error + +14.15 - Fixed regression issue with logfile regexes + + Implemented an improved email wrapper + +14.14 - Fixed issue with using Text::Wrap + +14.13 - Added inline pid match to all system regexes to cater for logging + changes + + Use Text::Wrap to ensure email line lengths are within specifications + + Updated dovecot log regexes to support the changed format in v2.3.15+ + +14.12 - Added cPanel SaaS servers to cpanel.allow + + Added a fix for RHEL v8 processes that were reporting excessive null or + whitespace characters at the end of /prod/[pid]/cmdline. This is turn + meant that such processes (e.g. spamd on cPanel servers) subverted some + entries in csf.pignore + + Updated systemd entries in csf.logignore for RHEL v8+ + + Updated dovecot log regexes to support the changed format in v2.3.15+ + + Modify LookUpIP to hopefully account for data inconsistencies from + Maxmind + +14.11 - Added entries in csf.pignore for new cPanel installations: + exe:/usr/sbin/mariadbd + exe:/usr/sbin/atd + exe:/usr/lib/systemd/systemd-timesyncd + exe:/usr/lib/systemd/systemd-networkd + exe:/usr/sbin/rsyslogd + + Updated configuration files to support cPanel on Ubuntu + + In Server Check don't check for Fork Bomb protection on cPanel servers + running CloudLinux + +14.10 - Fixed error message regarding location/permissions to the iptables + binary in correctly referencing ip6tables + + Added PASV port range hole for VZ servers on cPanel for new installs + + Fixed MESSENGERV3 Apache tree search where ServerRoot is not configured + so that csf defaults to /etc/apache2/ so that relative Includes are + still defined correctly + + Modified LF_BIND regex to deal with new log field + +14.09 - Improvements to CC IP lookup binary search + + Modified index.recaptcha.php and index.php to use square instead of + deprecated curly brackets on array index for PHP v7.4+ + + Modified Server Check regex matching on include in dovecot config files + in RHEL v8+ + + Added workaround for iOS issue with bootstrap modals + + Added EOL messages to Server Check report + + Modified dovecot.conf parsing on cPanel for include_try in Server Check + + Modified Apache 404 regex to check for either "info" or "error" + + Added two new CLI options: --temprma [ip], --temprmd [ip]. This allows + distinction between allow and deny that does not exist for + --temprm [ip] + + Updated UI to offer either --temprma [ip] or --temprmd [ip] instead of + --temprm [ip] + + Added PHP v7.2 EOL notice to Server Report + +14.08 - Added missing images/ subdir to webmin and interworx installers + + Added new option LF_TEMP_EMAIL_ALERT. This allows the disabling of temp + IP block emails. It is enabled by default (send temp email alerts as + before) + +14.07 - Added missing images/ subdir to DA installer + +14.06 - If DOCKER is enabled and the iptables nat table exists, csf now creates + a DOCKER chain in the nat table for IPv4 + + cPanel additions to csf.pignore on new and existing installs + + Disable reputation service on error + + Added new options MESSENGERV3PERMS and MESSENGERV3GROUP for the + creation of the MESSENGER_USER public_html directory. See csf.conf for + information, defaults set for each install control panel type where + possible + + Added exe:/sbin/rngd to csf.pignore for new installations + +14.05 - Modified dovecot pop3d/imapd log line parsing to repeat single lines + reporting multiple login failure attempts + + Additional entries in csf.pignore for new installs on CyberPanel v2 + + cPanel additions to csf.pignore on new and existing installs + + Convert embedded IPv4 addresses in /proc/net/tcp6 back to IPv4 + +14.04 - Added two new options: CC_MESSENGER_ALLOW, CC_MESSENGER_DENY. These + options can control which Country Code IP blocks are redirected to the + MESSENGER service, if it is enabled + + Fixed some typos in csf.conf + + Added DirectAdmin diagnostics to the admin UI for session security + checks, together with a method to skip the checks if desired + +14.03 - Updated DSHIELD blocklist to use https + + Updated Server Check PHP EOL information + + Improved DA session checking + + Improved DA Server Check report + + Modified cpanel.comodo.allow and cpanel.comodo.ignore with an + additional IP address + + MESSENGERv3 now out of BETA testing + + Added UDP ports 80 and 443 to UDP_IN/UDP6_IN for new installations to + support QUIC/HTTP3 + + Modified DA regex for Roundcube v1.4+ + + Modified DIRECTADMIN_LOG_R to point to + /var/www/html/roundcube/logs/errors.log for Roundcube v1.4+ by default + on new installs and change for old installs if not already set + + Added a new DA regex for phpMyAdmin + + Modified iframe resizer on DA, thank you to Martynas @ DirectAdmin + + Updated Integrated User Interface documentation to point to the latest + Apache docs + + Added newly generated self-signed keys for lfd UI + + Updated Server Report descriptions for cPanel + + Updated Server Report for systemd processes + + Added back cPanel update check to the Server Report now that it has + been reinstated by cPanel + + Removed outdated Server Report checks + +14.02 - Added new BETA TESTING option: MESSENGERV3. This provides the MESSENGER + service utilising the local webserver. It currently supports Apache + v2.4+ and Litespeed/Openlitespeed. As the first iteration this likely + contains bugs and may not be suitable for production environments. See + csf.conf and readme.txt for more information + + Changed Country Code Lookup source to ipdeny.com + + Added CC_ALLOW_SMTPAUTH to all configurations for the benefit of + servers other than cPanel running Exim + + Modify CC_ALLOW_FILTER to allow RELATED, ESTABLISHED connections + through so that outgoing connection replies from remote sites not in + CC_ALLOW_FILTER are accepted + + Added a note in csf.conf regarding MESSENGER_CHILDREN, that + consideration needs to be made for local images displayed on the page. + The default has also been increased to 20 for new installations + + Modifications to MESSENGER server to speed up connection response time + and improve stability + + Modifications to LFD UI and CLUSTER server to improve stability + + Added SUDO login alerts: LF_SUDO_EMAIL_ALERT. This will send an email + alert using the sudoalert.txt template whenever there is a failed or + successful SUDO connection. SUDO_LOG must be set to the correct log + file. LF_SUDO_EMAIL_ALERT is disabled by default + + Added new entry in csf.pignore on cPanel servers for v86+: + exe:/usr/libexec/dovecot/imap-hibernate + + Added Server Check for EOL PHP v7.1 + + Removed cPanel update checks from the Server Report now that the + options are no longer available in cPanel v86+ + + NOTICE: We are deprecating support for Virtuozzo/OpenVZ servers. Future + releases will not take into consideration those platforms which have + become onerous to support. The software application may continue to + work but support and functionality is no longer guaranteed + +14.01 - Changed mailman listings in csf.pignore on cPanel servers to cater for + changes in python versions in RHEL v6/7 and 8 + + Fixed issue with CC_ALLOW_FILTER when not using IPSET but using + SAFECHAINUPDATE would cause the new chain to be created in the wrong + place by lfd when the zone is retrieved/updated + + Fixed issue when using CC_ALLOW_FILTER with IPSET enabled not adding + the final DROP rule in lfd + + Further modifications to support RHEL/CentOS v8 + + Fixed issues with MESSENGER and CLUSTER server listeners terminating + prematurely + +14.00 - Added alternative database for Country Code Lists and Settings. These + do not currently require logins/keys and in some cases are better + optimised. A new setting CC_SRC allows switching between sources. For + new installations these new sources are used. Existing installations + are configured to continue to use the MaxMind databases. See the + "Country Code Lists and Settings" section in /etc/csf/csf.conf for + detailed information + + Added binary locations for CURL and WGET which will be tried if data + retrieval fails when using the LWP perl module, e.g. on outdated OS's + + Added new option for URLGET setting "3". This allow the use of either + CURL or WGET instead of the perl modules + +13.12 - Modified CyberPanel installation to support move to python3 + +13.11 - Fixed interdependence issue between Country Code lookups and Country + Code filters in lfd introduced in v13.09 + + Improved MM_LICENSE_KEY error messages + +13.10 - Removed hard-coded date from MaxMind ASN url + +13.09 - Due to MaxMind changing their free download policy to require signup + and a license key, a new option MUST be configured to continue to use + Country Code lookups (CC_LOOKUPS). The option MM_LICENSE_KEY must be + set to the key obtained from the MaxMind site. See: + https://blog.maxmind.com/2019/12/18/significant-changes-to-accessing-and-using-geolite2-databases/ + https://www.maxmind.com/en/geolite2/signup + Note: Existing installations will continue to use downloaded d/b's from + before the MaxMind change, though may be cleared after CC_INTERVAL + + Changed CC_LOOKUPS option 4 from freegeoip.net to db-ip.com as the + former no longer exists + + Fixed System Stats graphs not displaying on CyberPanel + + Updated csf control panel reporting in version display + +13.08 - Added official CyberPanel integration and CyberPanel panel specific + configuration (only tested on CentOS v7) + + More changes to support RHEL/CentOS v8 + +13.07 - Added format requirements for ASN entries in CC_* settings + + Removed SSHDSPAM exploit check as it's no longer critically relevant + + Modifications to support RHEL/CentOS v8 + + Modified systemd service to cater for RHEL/CentOS v7.7 pidfile symlink + check changes + + Fixes and improvements to UI Ajax code + + Removed legacy bandmin code for cPanel servers and LF_CPANEL_BANDMIN + setting + + Modified default InterWorx csf.conf to set SMTP_ALLOWGROUP + appropriately for SMTP_BLOCK + +13.06 - Removed debugging code from log file globbing routine + + Fixed reseller UI HTML text for each supported control panel + + Replaced the need in InterWorx for a custom Firewall.php with a + preAction to intercept calls instead + + Moved csf in InterWorx to the Advanced section in Plugins UI + + Updated the InterWorx plugin.ini information to be more descriptive + +13.05 - Added official CentOS Web Panel (CWP) integration and CWP panel + specific configuration. See /etc/csf/readme.txt for more information + (only tested on CentOS v7) + + Added official VestaCP integration and VestaCP specific configuration + (only tested on CentOS v7) + + Additional entries to csf.pignore for new DirectAdmin installations + + Corrected DirectAdmin UI link text + + Fixed UI presentation HTML + + Fixed vsftpd regex for single character date of the month + + Modified Debian installation to detect ip(6)tables-legacy and use + update-alternatives to switch to using them + + Modified InterWorx installation to not use chattr on /etc/apf/apf stub + which was preventing apf upgrading. The lfd daemon will now reapply + the stub if needed + + Modified Server Check on DA to get case-insensitive config from the + binary rather than the directadmin.conf file + + Modified csf warning text on cPanel DNSONLY servers regarding the + smtpgidonlytweak to disable it from CLI as it is not currently possible + from the DNSONLY WHM UI + +13.04 - Fixed issue with ConfigServer::CheckIP generating incorrect IPv6 + addresses during validation using Net::CIDR::Lite + + Added UI entry for editing csf.reseller for DirectAdmin and InterWorx + +13.03 - Fixed PATH issue in DirectAdmin installer when used from within the UI + to upgrade + +13.02 - Removed perl CGI::Carp module use from the DirectAdmin reseller UI as + the module may not be present + +13.01 - Added reseller support in InterWorx + + Added reseller support in DirectAdmin + + Added login failure detection on InterWorx (v6.3.16+). If LF_INTERWORX + is enabled, INTERWORX_LOG will be scanned for login failures to + NodeWorx and SiteWorx. This is enabled by default on all InterWorx + installations + + Fixed text in Firewall.php stub in InterWorx + + Improved UI display in DA + + Improved UI display in InterWorx + + Fixed InterWorx UI issue with "Service Status" NodeWorx feature caused + by Firewall.php stub + + Created cronjob to check for new product versions for the UI + (/etc/cron.daily/csget). A manual check is still available if needed. + This does not affect the daily upgrade check if enabled + +13.00 - Added InterWorx integration and InterWorx panel specific configuration. + See /etc/csf/readme.txt for more information (only tested on CentOS v7) + + Added InterWorx regex detection for proftpd, dovecot imap, dovecot pop3, + and smtp auth login failures. Added regex detection for LF_DISTSMTP and + LF_DISTFTP. Added regex detection for LF_CXS and LF_MODSEC. Added Login + Tracking for LT_POP3D and LT_IMAPD + + Ensure UI errors are displayed in browser to avoid blank pages + + Display install.txt if perl module checks fail + + Reworked DirectAdmin UI to display within the parent template + +12.12 - Updated CloudFlare code to use GET instead of POST to retrieve the id + of an entry as POST in the API is no longer working, which affected + entry deletion + + Modified --denyrm [ip] to not remove "do not delete" entries. This now + must be done by editing /etc/csf/csf.deny to prevent unintentional + unblocking, e.g. by MESSENGER reCAPTCHA or the UI + + MESSENGERv2: Set KeepAlive to Off + + Added new csf CLI cluster option: -cir, --cirm ip + This will remove the IP from each remote /etc/csf/csf.ignore member and + then restart lfd. This has also been added to the UI + + Added missing comment to cluster --ctempdeny entries + + Added missing timestamp to cluster --cignore entries + + Cluster command --cignore now checks for duplicates + +12.11 - Added port 8443/tcp to cPanel server new installs to cater for the v80 + calendar service. Existing installs will need to be modified manually + if the service is used by adding the port to TCP_IN and TCP6_IN + + Updated various EOL version checks in Server Report + + Updated version modification system to check existing version before + performing updates. Ensured that updates are applied chronologically + +12.10 - Added routine to select from multiple download servers for script + updates + + Added Sectigo (formerly Comodo) IPv6 DCV addresses to + cpanel.comodo.allow and cpanel.comodo.ignore + + Added support to LF_CXS for litespeed logs on cPanel + + Added exception to csf.fignore for NodeJS yarn temporary files in + cPanel v80 + +12.09 - Added new option CT_SUBNET_LIMIT. If the total number of connections + from a class C subnet is greater than this value then the offending + subnet is blocked according to the other CT_* settings. This option is + disabled by default + + Removed ALTTOR from csf.blocklists on new installations as it has been + discontinued + + Use ConfigServer::Slurp to read csf.resellers to avoid invalid line + endings + + Modified CLUSTER_SENDTO and CLUSTER_RECVFROM so that they can be set to + a file instead of listing IP's within the respective setting. See + csf.conf for more details + + Removed open_basedir check on cPanel servers in Server Check + + Fixed csf.conf typo + + Updates to Courier IMAP regexes for Plesk + +12.08 - Removed debugging code from lfd output + + Improvements for reason text information to IPs and CC_LOOKUPS to + netblocks for LF_PERMBLOCK and LF_NETBLOCK reports + +12.07 - Added commented out regex lines in csf.pignore on cPanel servers for + the upcoming ubic implementation by cPanel + + Added port 53 filters in cpanel.comodo.allow on cPanel servers + + Added postfix support for LF_DISTSMTP + + Switched Sendmail and URLGET modules from using croak to carp to avoid + unexpected parent death from child failure + + Double fork external commands in DA UI to work around DA mod_perl + restrictions, allowing full functionality + + Added reason text information to IPs and CC_LOOKUPS to netblocks for + LF_PERMBLOCK and LF_NETBLOCK reports and csf.deny entries + +12.06 - Removed new regex for LF_EXIMSYNTAX + +12.05 - Removed rbl.jp RBLs from csf.rbls + + Modify Project Honey Pot blocklist URLs to use https + + Ignore $SIG{PIPE} when running ipset + + Ensure csf shows ipset warnings + + Added osmd to lfd restart routine when cPanel upgrades + + Modified Server Check to look for underscore as well as dash settings + + Added test in lfd to ensure the pidfile is open before attempting to + close it + + Added new regex for LF_EXIMSYNTAX + + Added new option: URLPROXY. If you need csf/lfd to use a proxy, then + you can set this option to the URL of the proxy + +12.04 - Updated license terms for GDPR compliance + +12.03 - Make CC_IGNORE check case-insensitive + + Improved TCP/UDP port inspection for IPv6 connections (affecting CT_*, + PT_* and PT_SSHDKILL) + + Updated cxs FontAwsome to v5 + + Added fixes for additional Include line processing + + Fixed race condition when processing CC_* zip files that could + sometimes prevent the csv files from being extracted + + Updated HTTP::Tiny to v0.070 + +12.02 - Removed CC_OLDGEOLITE and associated code so that all installations + will now use the MaxMind GeoLite2 databases + + Added more CLI options that work if csf is disabled + + Added Include line support to 20 more /etc/csf/csf.* configuration + files. See /etc/csf/readme.txt under "Include statement in + configuration files" for the list of supported files + + Added mangle and raw tables to csf --grep [IP] and modified output to + show a new column with the table then the chain that a rule is in + + Added mangle and raw tables to csf --status output and modified output + to show a new header line with the table that a rule is in + + Added new option USE_FTPHELPER. This enables the ftp helper via the + iptables CT target on supporting kernels instead of the current method + via /proc/sys/net/netfilter/nf_conntrack_helper and unrestricted use of + RELATED state + + Modified ICMP_IN/ICMP_OUT to only affect PING (echo-request), all other + ICMP traffic is allowed (which can help network performance) unless + otherwise blocked. This is for IPv4, it does not affect IPv6 + + Improved rule placement to prevent existing connections bypassing + ICMP_IN_RATE/ICMP_OUT_RATE limits + + Updated csf.conf documentation relating to the ICMP/PING settings + + Added new option ICMP_TIMESTAMPDROP. For those with PCI Compliance + tools that state that ICMP timestamps should be dropped, you can enable + this option. Otherwise, there appears to be little evidence that it has + anything to do with a security risk but can impact network performance, + so should be left disabled by everyone else + + csf and lfd now exit with status 1 on error or if disabled. However, + this will not happen with csf if the CLI option used still works while + disabled + + USE_CONNTRACK is now enabled by default on new installations + + Fixed DOCKER IPv6 warning message when DOCKER not enabled + + Modified csf.blocklists for GREENSNOW to use https on existing and new + installations + +12.01 - Added missing DOCKER_DEVICE setting from the generic and directadmin + csf.conf files + + Ensure iptables/ip6tables mangle and raw tables are flushed on + stop/start if they exist + + CC_OLDGEOLITE set to "0" on new servers and those upgrading to v12.* + for the first time. This enables MaxMind GeoLite2 by default unless + already set + + Note: The old MaxMind Geolite v1 database code will be removed in the + near future, before the end of March, in favour of the v2 databases + +12.00 - Added support for GeoLite2 databases from Maxmind for CC_*. These + databases are significantly larger than the soon to be deprecated + GeoLite ones stored in /var/lib/csf/ + + Added support for GeoLite2 databases from Maxmind for CC_LOOKUPS and + CC6_LOOKUPS. + + Added new option: CC_OLDGEOLITE. This option is enabled by default to + continue using the old GeoLite databases. See csf.conf for more + information. This option will be removed in the near future so that all + installations use the new GeoLite2 databases + + GeoLite2 lookups now use the CSV files instead of the formatted Data + files because the Perl dependencies for the MaxMind Perl modules that + access the Data files are prohibitively excessive. We have developed + our own fast binary search module to perform the required lookups on + the CSV files for both IPv4 and IPv6 + + An advantage of the new GeoLite2 databases is that IPv6 lookups can now + be done to the same level as IPv4: Country Code; Country; Region; City; + ASN + + Unified storage of GeoLite2 database to avoid duplication between + CC_LOOKUPS and CC_* databases + + Added new CC_LOOKUPS value of "4". This option does not use the MaxMind + databases directly for lookups. Instead it uses a URL-based lookup from + a third-party provider at https://freegeoip.net and so avoids having to + download and process the large databases. See csf.conf for more + information and limitations + + Modified CC_INTERVAL default to 14 days on new installations + + Ensure MESSENGERV2 service will not start if using a valid cPanel + account in MESSENGER_USER (must be non-cPanel account) + + Create entry in /etc/aliases for "csf" if MESSENGERV2 is enabled on + cPanel servers to reserve the account name + + Added new feature: DOCKER support. This configures iptables rules to + allow Docker containers to communicate through the host. This is + currently in BETA testing. See csf.conf for more information. Thanks to + Marcele for the rules + + Removed redundant nat table check for ip6tables in Config.pm + + Replaced all remaining bareword file handles + +11.07 - Added missing WAITLOCK to iptables when processing advanced port + filters in csf and lfd and checking csf status in UI + + Added WAITLOCK, if enabled, to iptables-restore commands during + FASTSTART + + Server Check Report - removed ini_set check as so many scripts use + ini_set nowadays. Updated text on various checks + + Updated the postfix SMTP AUTH regex + + Added new SSHD "maximum authentication attempts exceeded" regex + + Set basic PATH before running csfpre.sh/csfpost.sh to avoid binary + location issues + + csf now runs csfpre.sh/csfpost.sh directly without forcing it through + /bin/sh. If present, csf chmods the script 0700 and checks for a + shebang. If the shebang is missing #!/bin/bash is added to the top. The + script is then run + + Added seventh parameter to regex.custom.pm to allow Cloudflare blocking + if a CUSTOM regex is triggered (see latest regex.custom.pm in distro) + + Rearranged UI tabs and shortened tab names. Moved quick actions to the + top of the "csf" tab pane + + Added "AUTH command used when not advertised" to the LF_EXIMSYNTAX + regex check + + Added new csf CLI cluster option: -ci, --cignore ip [comment] + This will add the IP to each remote /etc/csf/csf.ignore member and then + restart lfd. This has also been added to the UI + + Fixed cluster grep output in UI + + Modified MESSENGERV2 to support combined certificates+keys in cPanel + v68+ + + Added triggered setting and, if applicable, temporary TTL to the + "Blocked:" status in block alert emails + + Added "wildcard" option to "Search System Logs" UI to use ZGREP to + search the specified log with a wildcard suffix. ZGREP option added to + csf.conf which must point to the zgrep binary + + Added git binaries to csf.pignore on cPanel servers for upcoming v72/74 + features + +11.06 - Modified Integrated UI to use new cxs UI perl modules + + Added custom redirect line for webmin UI when STYLE_CUSTOM enabled + + Ensure ip6tables nat table is flushed if present whether MESSENGER is + enabled or not + +11.05 - Added new configuration option PT_SSHDKILL. This option will terminate + the SSH processes created when blocking an IP + + Added a "Fix Common Problems" section to the csf UI for various common + configuration issues + + Ensure application ports are always defined in lfd + +11.04 - Added new configuration option LF_APACHE_ERRPORT. This option is used + to determine if the Apache error_log format contains the client port + after the client IP. By default it is set to autodetect + +11.03 - Improvements to ajax output in integrated UI + +11.02 - Integrated UI fix for CloudFlare page + + Removed non-participated deny options for cxs reputation service + + Changed PT_SSHDHUNG to use a regex for process cmdline detection + + Fixed issue with IPv6 client detection in Apache logs + +11.01 - Corrections to readme.txt + + In UI, display long output into fixed height divs with scrollbars and + font size changer + + Modified Server Check to not display the mod_cloudflare warning if + CF_ENABLE enabled + + Modified Server Check to display a single warning for each PHP check + listing affected versions instead of multiple warnings + + Additional exim check added to Server Check + + Improvements to ajax output in UI + +11.00 - New Feature: CloudFlare Firewall integration. This feature provides + blocking and unblocking functionality with the CloudFlare Firewall from + within lfd, together with new CLI commands for direct access. See + documentation for CF_ENABLE in csf.conf, information in readme.txt as + well as the csf man page + + Added UI elements for CloudFlare Firewall integration + + New CLI command --trace [ip]. This replaces the --w, --watch CLI + command to Log SYN packets for an IP across iptables chains by using + the iptables TRACE module + + New Feature: Check the size of the ModSecurity IP D/B. This option will + send an alert if the ModSecurity IP persistent storage grows + excessively large. This is enabled on cPanel by default. See csf.conf + for more information + + New Feature: Allow use of comma separated list of ports in Advanced + Allow/Deny Filters + + WATCH_MODE in csf.conf and --w, --watch CLI commands removed in favour + of the new --trace [add/remove] [ip] CLI command + + Restrict the scope of Perl shebang replacement when installing on + cPanel servers + + Modifications and fixes for the example MESSENGERV2 templates + + Ensure /proc/sys/net/netfilter/nf_conntrack_helper is enabled at + startup to allow connection tracking to continue working on newer + kernels + + Stop needlessly setting and elements in Ajax returns + + Various corrections and updates to readme.txt + + Tweaks to the Mobile View UI button arrangement and spacing + +10.25 - CSS change to UI configuration page + + Remove refresh timer from UI log file grep + +10.24 - On webmin servers, added csf.body file to UI skinning (STYLE_CUSTOM). + See readme.txt for more information + +10.23 - On cPanel servers, ensure that the csf driver for WHM is removed on + uninstall + + Added hooks for upcoming cxs IP Reputation Service + + On webmin servers, added csf.htmltag and csf.bodytag files to UI + skinning (STYLE_CUSTOM). See readme.txt for more information + + MESSENGERV2 released as stable on cPanel servers. This uses the Apache + http daemon to provide the web service for MESSENGER HTML and HTTPS + + Additions to csf.logignore on new installs + + Added IPv6 support to BLOCKLISTS + + Added Spamhaus DROPv6 and Stop Forum Spam IPv6 blocklists to + csf.blocklists + + Removed Spamcannibal and added all.s5h.net from/to csf.rbls + + Fixed issues with IPv6 rule creation attempts when IPV6 disabled + + Automatically enable WAITLOCK on initial installation if supported + +10.22 - Fixed issue with the ModSecurity regex modification in v10.20 + +10.21 - Ensure /etc/logrotate.d/lfd is overwritten on upgrade + +10.20 - Prevent lfd logrotate from erroring if log files missing + + Modified Apache ModSecurity regex to cater for changes in logging + format on cPanel servers with ModSecurity v2.9.2 + + Modified Apache cxs regex to cater for changes in logging format on + cPanel servers with ModSecurity v2.9.2 + + Ensure destination files are owned by root during installation + +10.19 - MESSENGERV2: Take a copy of the live certs and keys and use these in + csf.messenger.conf to work around changing filenames for keys and certs + when they are regenerated which causes httpd to fail. This is done each + time lfd restarts + + Added CLI option csf --mregen: MESSENGERV2 + /etc/apache2/conf.d/csf_messenger.conf regeneration. This will also + gracefully restart httpd + +10.18 - Stability improvements to the UI daemon + + Fixed MESSENGER log entry spelling + +10.17 - Prevent Cluster and UI daemons from terminating the main process if + they themselves terminate + + Modify Cluster and UI daemons to restart if they are stopped or fail + + Modify Cluster and UI daemons to be more verbose about reasons for + stopping + + Fixed typos in readme.txt and csf.conf + + Added MESSENGER child logging to /var/log/lfd_messenger.log, also for + MESSENGERV2 via a new index.recaptcha.php + + Modified logrotate configuration to include /var/log/lfd_messenger.log + +10.16 - Fixed issue in 10.15 which was causing the Cluster daemon to exit + unexpectedly + +10.15 - New EXPERIMENTAL feature on cPanel servers: MESSENGERV2. This uses the + Apache http daemon to provide the web service for MESSENGER HTML and + HTTPS + + Added new option LF_APACHE_401 that works in a similar way to + LF_APACHE_404 and LF_APACHE_403 + + Added new option RECAPTCHA_ALERT. This will send an email when a + recaptcha unblock request is attempted by lfd. This option is enabled + by default + + Stability improvements to UI, MESSENGER and CLUSTER daemon processes + + Added memory usage information to lfd log when using MESSENGER_HTTPS + + Add limiter to enforce MESSENGER_CHILDREN when connections are waiting + for a child process + + Modify MESSENGER HTML examples for new installs to use inline images to + improve page load speed and reduce lfd overheads + + Modified network interface detection to allow dash (-) in name + + URL updates in Server Check + + Increased the default value for MESSENGER_RATE to 100/s (from 30/m) + and MESSENGER_BURST to 150 (from 5) for all installations to alleviate + slow MESSENGER response times + + Set the SELinux security context for systemd and executable files + + Ensure firewalld is masked on systemd servers + +10.14 - Made configuration checks on iptables more fault tolerant to avoid + unnecessary failures while loading + + Removed openbl.org from csf.blocklists for new and existing installs + + More generic binaries added to csf.pignore + +10.13 - Fixed looping/timeout of integrated UI children when Chrome client is + used + +10.12 - Configured UI to fully integrate with cPanel templates without using + iframes + + Configured UI to display full cPanel breadcrumbs + + Configured UI to support cPanel v66 WHM UI changes + +10.11 - Modified username regex for csf.syslogusers + + Fixed issue with /var/lib/csf/lfd.stats excessive growth + +10.10 - Modified HTML to cater for major change in cPanel v66 + +10.09 - Added new option DROP_OUT which is set to "REJECT" by default. This + option sets the default target for blocked outgoing ports. See csf.conf + for more information + + Added improved detection of xtables lock and recommend enabling + WAITLOCK on error + + Improved csf down detection when xtables lock in effect and WAITLOCK is + not enabled + + Added support for listing ASNs in CC_IGNORE + +10.08 - Added cpanel.allow and cpanel.ignore Include files for the cPanel + authentication servers. These are included on new installations and + added to existing files on cPanel installations + + If running cPanel 1:1 NAT, use the contents of /var/cpanel/cpnat to + whitelist/ignore the external IP addresses + +10.07 - Fixed bug when using RECAPTCHA_NAT where the listed IP's were not + correctly processed + + Server Check now follows includes in dovecot.conf + + Server Check now reports RHEL/CentOS/CloudLinux v5.* as EOL + +10.06 - Added new entry in csf.pignore on cPanel servers for: + exe:/usr/libexec/dovecot/indexer + exe:/usr/libexec/dovecot/indexer-worker + + Croak if IPTABLES is not set, incorrect or not present in csf.conf + + Set SELinux context for /etc/logrotate.d/lfd on new generic installs + +10.05 - Fixed table header html/css + + Added workaround for adding superusers listed in + /etc/csf/csf.syslogusers to the RESTRICT_SYSLOG_GROUP if the log socket + is not accessed via the owner permissions + + Changes for cPanel v64 template + + Updated text description in csf.dirwatch for new installs + +10.04 - Added error message to RECAPTCHA_* if the non-priveleged user cannot + write to its home directory + + Further improvements to RECAPTCHA_* hostname check + +10.03 - Added new option MESSENGER_HTTPS_SKIPMAIL on cPanel installations. This + option ignores ServerAlias definitions that begin with "mail.". This + can help with memory usage on systems that do not require the use + of MESSENGER_HTTPS on those subdomains. The option is enabled by + default on cPanel servers + + Improved RECAPTCHA_* hostname check + + Cluster CLI can now block CIDRs, e.g LF_NETBLOCK blocks will be applied + cluster-wide + +10.02 - Modified Messenger HTTPS to cater for a wider range of Apache + VirtualHost formatting + + Added Messenger HTTPS workaround for servers using PEM but a version + of IO::Socket::SSL that does not yet support it (pre v1.988) + + Added Messenger HTTPS warning in csf.conf regarding memory usage on + some servers using the option + + Added java binary for cPanel solr process to csf.pignore on new and + existing servers + +10.00 - Added new feature to MESSENGER: MESSENGER_HTTPS*. See /etc/csf/csf.conf + for more detail. This option redirects blocked IP addresses that + connect over an HTTPS connection (port 443) to the HTML MESSENGER + service. The option uses existing SSL certificates on the server for + each domain to maintain a secure SSL SNI connection without browser + warnings. The setting is disabled by default + + Note: The perl module IO::Socket::SSL (v1.83+) with support for SNI + must be available to use MESSENGER_HTTPS* otherwise it will be disabled + + Added new feature to MESSENGER: Google ReCAPTCHA (v2) to allow those + blocked in the firewall to unblock themselves. See RECAPTCHA_* in + /etc/csf/csf.conf for more details and limitations + + Added MESSENGER procedure to restart listening sub-process if it has + died + + Moved MESSENGER processes to a separate module + + Ensure that all forked processes terminate appropriately + + On cPanel servers, use the cPanel WHM Template to support the new v64 + UI layout (as best we can to maintain the look that we want) + + Modified the cPanel csf ACL metadata and driver Perl modules to match + new requirements for v64 and also maintain backwards compatibility + +9.30 - Fix to try and resolve cluster send/recv issues (Note: _All_ members of + the cluster need to be running v9.30 for clustering to function + correctly) + +9.29 - Fixed issue that was breaking LF_DISTSMTP + + Fixed issue in UI lfd Stats. Note: The lfd stats data file has been + renamed from /var/lib/csf/stats/lfdmain to /var/lib/csf/stats/lfdstats + Additionally, the stats for 2016-12-31 will reset to 0 due to this bug + + Corrected text in readme.txt + + Added new csf CLI cluster option: + -ctd, --ctempdeny ip ttl [-p port] [-d direction] [comment] + This sends a temporary deny request to the cluster + + Added new csf CLI cluster option: + -cta, --ctempallow ip ttl [-p port] [-d direction] [comment] + This sends a temporary allow request to the cluster + + Added new csf CLI cluster option: + -cg, --cgrep ip + This requests the --grep output for [ip] from each cluster member + + Modified cluster requests to respond with an acknowledgment to the + sender + + Modified --cdeny [ip] and --callow [ip] to include optional comment + + Added separate tab for Cluster options in UI if enabled and added new + cluster temp allow/deny commands to UI + + Modified Port Scan Tracking. UDP packets destined for the network + broadcast address(es) will now be ignored in Port Scan Tracking unless + BRD is added to PS_PORTS. The broadcast address(es) include the those + listed in IP or IFCONFIG plus the default (255.255.255.255) unless one + of the servers IPs + + Added new feature: PT_USERRSS. This User Process Tracking option sends + an alert if any user process exceeds the RSS memory limit set - RAM + used, not virtual. PT_USERRSS is set to 256 (MB) and PT_USERMEM is now + set to 512 (MB) by default on new installations. On existing installs + PT_USERRSS is set to the same value as PT_USERMEM + +9.28 - New logo added and configured for cPanel plugins + + HTML fixes + + STYLE_CUSTOM is now set to 0 by default on all new installations. If + you want to choose custom styling this option can be enabled + +9.27 - Fix for UI Quick Unblock button + + Fix for UI main page [ENTER] not working on all forms + +9.26 - Fix for webmin UI when watching logs + + Various UI html syntax fixes + + Reduced UI banner padding + + Port 23 added to DROP_NOLOG for new installations + + WAITLOCK taken out of beta + + Modified UI View Listening Ports + + Reworked main UI table to produce syntactically correct HTML + + Fixed duplicate HTML top and bottom page elements + +9.25 - Correct csf lookup failure message + + Converted UI icon for temp allow removal to new format + + Simplified Configuration display of radio toggles to help screen + readers + + Added patch to send message text for CLUSTER blocks + +9.24 - UI html fixes + +9.23 - Added upgrade note to the top of the UI if available + + UI improvements for integrated cse and interface to cxs + + Added Scroll to Top/Bottom buttons + + Consolidate images, css and javascript into a common directory in the + installer + +9.22 - Modify UI temporary IP deny buttons to not wrap in table + + Modified UI Statistics images to be responsive + + Modified readme.txt to detail additional UI styling options + + Added two new options STYLE_CUSTOM and STYLE_MOBILE relating to UI + styling + + Globalised SIGNALs where needed to help prevent zombie children + + Modified UI to use container-fluid to improve whitespace use + + Modified pre tags to wrap on whitespace + +9.20 - Redesigned UI based on Bootstrap + + New functionality: Added integrated mobile device view with subset of + functions + + Modified csf to not warn about the SENDMAIL binary if LF_ALERT_SMTP is + enabled + + Added use of the ace editor if present on cPanel installs to edit + files. Added toggle to switch back to textarea. Added buttons to + decrease and increase font size in editor + + Modified readme.txt to include information regarding changing styles + and disabling Mobile View + +9.14 - Fixed LOGSCANNER logging to only report to the log if DEBUG enabled + + Added new BETA options WAITLOCK and WAITLOCK_TIMEOUT which provide + support for the iptables --wait option + + Added UI support for cxs with Bootstrap + +9.13 - Modify Server Check to prevent hanging process for CloudLinux PHP + versions prior to v5.2 + +9.12 - Improved LOGSCANNER accuracy of hourly and daily runs between restarts + + Added more binaries on cPanel servers to csf.pignore for cPanel v60 + + Fixed repeated check for PHP open_basedir in Server Check + + Do not perform suexec check if mod_ruid2 enabled in Server Check + + Corrected text description of IPv6 port lists in non-cPanel csf.conf + + Export ConfigServer::Logger::logfile + + Detect mpm_itk_module and treat in a similar manner to ruid2_module in + Server Check + + Removed use of Cpanel::cPanelFunctions as it is now being withdrawn + + Updated common ConfigServer UI + + Fix instance where cluster block timeout for temporary blocks was not + being sent + + Check for EOL PHP v5.5 in Server Check + + Added detection of alt-php versions provided by CloudLinux, but do + not check them for EOL version status + +9.11 - Fixed issue with csf.allow Include checks when allowing an IP + + Added the Greensnow blocklist to csf.blocklists for new installs + + Fixed display of ports in CLI temporary blocks + + Fixed issue removing CIDR blocks via the CLI from csf.deny + +9.10 - Fix profile diff in the CLI + + Fixed issue with deny removal by IP address of advanced rules in the + CLI + +9.09 - Additional fix for ip6tables MESSENGER service when LF_IPSET not + enabled (ip6tables nat) + +9.08 - AUTOSHUN list removed from csf.blocklists as the public list is no + longer available + + Added support for ip6tables MESSENGER service when LF_IPSET not + enabled (ip6tables nat) + +9.07 - Fixed removal of complex allow and deny rules + + Fixed IPv6 implementation of CC_ALLOW_PORTS_* and CC_DENY_PORTS_* + + Fixed file upload in cse via the integrated UI + + Fixed "csf --cfile [file]" + + Removed setting: OLD_REAPER + + Localised SIGNALs + + Localised uid and gid change in MESSENGER + + Removed Bareword file handles + + Where ip6tables <= v1.3.5 and IPV6 is enabled, disable USE_CONNTRACK if + enabled as ip6tables does not support the conntrack module in older + versions. This will force the use of the state module instead + +9.06 - Fixed incorrect inclusion of cPanel Free SSL service include entries + on new non-cPanel installations + +9.05 - Fixed RT_AUTHRELAY_LIMIT detection + +9.04 - Fixed issue with custom regex rules where log hash was not being + passed to regex.custom.pm + + Fixed issue with custom regex rules where "use strict" was used + incorrectly + +9.03 - Fixed issue with LF_ALERT_TO and LF_ALERT_FROM not being used when set + +9.02 - Fixed Reseller UI command execution + +9.01 - Fixed graph display when using integrated UI + +9.00 - Convert csfui.pl, csfuir.pl and cseui.pl to perl modules and modify + the calling UI specific scripts + + Updated cseUI so that is passes perl strict module checks + + Fixed issue with deny removal of some IPv6 addresses + + Ensure /etc/chkservd/lfd is recreated when lfd is enabled via csf -e + on cPanel servers + + Added exes to csf.pignore on existing and new cPanel server: + /usr/libexec/dovecot/lmtp + /usr/local/cpanel/3rdparty/php/54/bin/php-cgi + /usr/local/cpanel/3rdparty/php/56/bin/php-cgi + /usr/local/cpanel/3rdparty/php/56/sbin/php-fpm + + Ensure all file opens are properly flocked + + Switch to using require instead of eval/use to load runtime modules + where possible + + Code review - started addressing perl critic suggestions in all + scripts and modules + + Moved regex.pm to a seperate perl module + + Moved email sending to a seperate perl module + + Moved lfd logging to a seperate perl module + + Add allow and ignore Include files for the cPanel Free SSL service + from Comodo in cPanel v58+. These are included on new installations + and added to existing files on cPanel installations + + Fixed spurious Include error in lfd for csf.ignore + +8.26 - Added more dovecot binaries to csf.pignore for new and existing cPanel + servers + + Updated lfd-cron to use the csf startup routines to restart lfd on + systemd servers correctly, existing cron jobs are also modified + + HTTP::Tiny upgraded to v0.058 + +8.25 - Modified Config loading to check for valid ip6tables location before + attempting to use it + + Modify Server Report to support checking of cPanel MultiPHP + configurations when using EasyApache v4 + + Removed PHP check for suhosin from Server Report + + Improved cipher check for pure-ftpd in Server Report + + Added password reset check for subaccounts in Server Report on cPanel + servers + + Added cPanelID check in Server Report on cPanel servers + +8.23 - On cPanel servers ensure the lfd service is always correctly appended + to chkservd.conf on csf installation + +8.22 - Fix csf --tempdeny from allowing blocking of local IPs + + Fix problem where LF_NETBLOCK was no longer affective after blocking + a its first netblock until it timed out from csf.tempip + + Modify UI table spacing + +8.21 - Modified cPanel version check to avoid restart loop if GENERIC set to + 1 in csf.conf + +8.20 - Modify Relay Alert email to specify "localhost" rather than "Local + Account" when localhost IPv6 address detected as it currently does for + IPv4 localhost + + Improvement to lfd restart routine for MailScanner and pure-ftpd when + cPanel upgrades on RHEL/CentOS/CloudLinux v7+ servers + +8.19 - Move SMTP_BLOCK rules to a separate chain to avoid conflicts with + other control panels deleting required rules + +8.18 - Reversed csf.tempip changes to avoid a possible locking issue in + csf.pl, lfd.pl changes retained + +8.17 - Fixed 12 month statistics pie chart rendering + + Increased default value and sanity range for PT_USERMEM + + Modified SMTP_BLOCK to use iptables multiport + + Added new feature: SMTP_REDIRECT. This redirects non-authorised + outbound SMTP connections to the local SMTP server + + Ensure LF_PERMBLOCK IP's are removed from csf.tempip when rotating + csf.deny after reaching DENY_IP_LIMIT + + Remove stale csf.tempip entries on lfd startup + + Added IPv6 support to RT_LOCALHOSTRELAY tracking + + Update binary locations for new installations on DirectAdmin Debian + + Improved fix for detection of ip6tables nat chains + + Added UI Firewall Configuration On/Off buttons + + Added UI Firewall Configuration dropdowns for some value ranges + + Updated UI restricted list + + Updated sanity checks + + Various UI updates and modifications + + Added a warning when using mod_cloudflare to Server Check Report + +8.16 - Removed UI integration from CentOS Web Panel as recent permission + changes break the implementation. The csf installer will restore the + original functionality + +8.15 - Added new configuration option IP to point to the IP binary. This will + be used in preference to IFCONFIG, the latter is no longer required + when the IP binary is correctly configured and executable + + Added full UI integration into CentOS Web Panel (CWP). To disable + integration: + Rename: /usr/local/cwpsrv/htdocs/resources/admin/modules/csf.orig.php + to: /usr/local/cwpsrv/htdocs/resources/admin/modules/csf.php + create: /etc/csf/cwp.disable + + Updated Postfix SMTP AUTH regex (thanks to Marcele) + + Added support for /etc/csf/csf.blocklists in ZIP format. The zip file + MUST only contain a single text file of a single IP/CIDR per line + + Added Stop Forum Spam (ZIP) example to csf.blocklists + + Added IPV6 support to csf.sips + + Fixed detection of ip6tables nat + + Removed development code for ispconfig from distribution as this + should NOT be used. It has never been implemented nor released as a + supported solution and is likely to be insecure. Upgrading will remove + any installations of this development code + +8.13 - Added /usr/local/cpanel/3rdparty/php/54/sbin/php-fpm to csf.pignore + for cPanel installs + + Clarify cluster CLI commands that refer to remote server actions + + Added number of failures to the RBL check Subject field + + Modified Port Scan checks for more kernel log line formats in regex.pm + +8.12 - Additional Feature: Added support for listing ASNs in all Country Code + (CC_*) options + + Fixed GLOBAL_ALLOW and GLOBAL_DENY when LF_IPSET is enabled + + Fixed GLOBAL_DYNDNS when LF_IPSET and LF_IPV6 are enabled + + IPSET binary location set to /sbin/ipset for Debian/Ubuntu new + installs + + Additional regex included for vsftp login failures + +8.11 - Fixed issue on non-RedHat OS installations that failed due to problems + whitelisting the installers IP address + +8.10 - Fixed issues with new non-RedHat OS installations by reasserting perl + module check to the start of the installation process but removing + included modules from checks + + Ports 2079 and 2080 added to TCP_IN for new cPanel installs to allow + CalDAV/CardDAV access + +8.09 - Check /sys/module/ipt_recent/parameters/ip_pkt_list_tot or + /sys/module/xt_recent/parameters/ip_pkt_list_tot if defined to allow + higher settings for PORTFLOOD than the default of 20 if configured + + Added LimitNOFILE to lfd.service on servers using systemd to allow for + large numbers of open files + + Cater for full stops (.) in ethernet device names + + Moved Perl module checks until after csf installation has completed so + that all included modules exist in /usr/local/csf/lib/ + +8.08 - Fixed csf.sips modification via UI on Redhat/CentOS v7.1 + + Raised csf.blocklist names from 9 to 25 characters long. This cannot + be greater due to limits on ipset names on some OS's and the use of + prepended names for new ipset list swapping + + Added output from netstat for PT_LOAD to loadalert.txt for new + installs. For existing installs, latest file copied to + /usr/local/csf/tpl/loadalert.txt.new + +8.07 - Ensure spaces are stripped from values in /etc/cpanel/ea4/paths.conf + on cPanel servers + + Fixed issue with csf --add [ip] not always removing [ip] if present + from csf.deny + + Modified the LF_QOS regex to cater for additional log formats + +8.06 - Added port 24441 to UDP_OUT and UDP6_OUT for new installs on cPanel + servers for Pyzor that was added by cPanel in v11.52 + + Support added for EasyApache4 log locations in cPanel from + /etc/cpanel/ea4/paths.conf + + Added more executable files to csf.pignore on cPanel servers for + cPanel EasyApache4 + + Modify Server Check to support cPanel EasyApache4 + + Added regex to support cPanel/WHM login failures with the new log + format in v11.52+ + + If mod_ruid2 is enabled do not check for mod_userdir in Server Check + + Always ensure binary exists and is executable before performing + processing during Server Check + + Modified ProFTPD regex to support more formats + + vsftpd inbuilt log file format regex added + + Modified cPanel antirelayd Server Check to also support popbeforesmtp + added in v11.52 + + Added dbus and time systemd regexes to csf.logignore for new installs + +8.05 - Added alarms to HOST binary calls + + Added new csf CLI option: --rbl [email]. This generates the report + checking IP addresses against a set of RBLs. Optional configuration is + available through /etc/csf/csf.rblconf + + Added UI to utilise the new --rbl [email] option + + Added systemd status output after lfd restart via the csf CLI + + Modified Server Check to only report bind if a named configuration + file exists + + Require cPanel resellers to enter a Comment when allowing or denying + an IP + + Added new option UI_IP to allow binding to a specific IP address for + the integrated UI + +8.04 - Added more executable files to csf.pignore on cPanel servers for + cPanel v11.5*+ + + Added warning to both csf output and Server Check report if + PT_USERKILL is enabled + +8.03 - Fixed bug where iptables nat tables were not being flushed or grepped + correctly + +8.02 - Modified DYNDNS and GLOBAL_DYNDNS to use the host binary if available + for more reliable IPv4 and IPv6 reverse lookups + + Fixed IPv6 use of ipset for DYNDNS and GLOBAL_DYNDNS + + Added new csf CLI option: --lfd [stop|start|restart|status]. Actions + to take with the lfd daemon + + Added new csf CLI option: -ra, --restartall. Restart firewall rules + (csf) and then restart lfd daemon + + Fixed several output message typos for "FASTSTART" + + Disable IPv6 nat support (and MESSENGER) if ip6tables nat not provided + by the local kernel + + Improve IPv6 detection on installation + + Implemented more efficient csf.conf loading in ConfigServer::Config + +8.01 - Modify ConfigServer::CheckIP to cope with entries not passed by reference + +8.00 - Added new option CC6_LOOKUPS. This adds IPv6 support for Country Code + and Country lookups + + Added new option LF_NETBLOCK_IPV6. This adds IPv6 support for + LF_NETBLOCK + + Modified LF_LOOKUPS to use the host binary if available for more + reliable IPv4 and IPv6 reverse lookups + + Added IPv6 support for LF_IPSET + + Added IPv6 support for CC_DENY, CC_ALLOW, CC_ALLOW_FILTER, + CC_ALLOW_PORTS, CC_DENY_PORTS, CC_IGNORE, CC_ALLOW_SMTPAUTH + (Requires CC6_LOOKUPS and CC_LOOKUPS to be enabled) + + Added IPv6 support for X_ARF report where found in the Abusix Contact + DB + + Added IPv6 nameserver support for /etc/resolv.conf + + Added IPv6 support for MESSENGER if ip6tables version >= 1.4.17 and + perl module IO::Socket::INET6 is installed + + Added IPv6 support for PORTFLOOD if ip6tables version >= 1.4.3 + + Added IPv6 support for CONNLIMIT if ip6tables version >= 1.4.3 + + Added IPv6 support for SYNFLOOD + + Added flush of ip6tables nat table if ip6tables version >= 1.4.17 + + Standardise all IPv6 addresses and networks to use the short form for + consist representation + + Added FASTSTART support to LF_IPSET + + Increased ulimit -n to 4096 in /etc/init.d/lfd + + Included Net::IP for IP address manipulation + + Included version perl module for version comparisons + + Added missing csf.allow search to csf --grep + + Added Server Check report for LF_IPSET when using Country Code filters + +7.73 - Fix for temporary denies allowing duplicate IP/Port blocks/allows + + Speedup csf --grep [ip] when searching IPSET sets. Note: This does + mean that partial IP queries will no longer match IPSET entries + + Added new options LF_IPSET_HASHSIZE and LF_IPSET_MAXELEM to allow for + larger ipset sets + + Added option HOST as the location of the "host" binary for DNS TXT + record lookups + + Modified X_ARF report to include the abuse contact for a reported IP + address where found in the Abusix Contact DB + + Added new option X_ARF_ABUSE. This option allows for automatic sending + of X_ARF reports to the IP addresses abuse contact. See csf.conf for + warnings about using this option + + Added binary location checking in csf and issue warnings if incorrect, + not installed or not executable + +7.72 - Added new option PT_SSHDHUNG. Terminate hung SSHD sessions. When under + an SSHD login attack, SSHD processes are often left hung after their + connecting IP addresses have been blocked. This option will terminate + such processes. See csf.conf for more info + + Added new binaries to csf.pignore on existing cPanel installations to + cater for v11.50 and CentOS v7 + + LF_CONSOLE_EMAIL_ALERT and LF_WEBMIN_EMAIL_ALERT now default to 1 for + new installations + + Updated Server Check ipv6 detection + + Updated sanity checks + +7.71 - Added warning on cPanel servers for GreyListing + + Fixed issue with RedHat/CentOS/CloudLinux v7 where local IPs were not + being successfully detected from IFCONFIG + +7.70 - Removed PayPal Donation buttons due to recent abuse + +7.69 - Modified LF_CSF on cPanel servers to detect a change in the cPanel + version and then trigger a restart of ConfigServer scripts (added + cxs pure-uploadscript restart) + +7.68 - Added Debian v8 and Ubuntu v15 support + + HTTP::Tiny upgraded to v0.054 + +7.67 - Added a workaround for Plesk sendmail wrapper SIGCHLD problem + +7.66 - Fixed UI status form tags + + Added new option LF_SPI. This option configures csf iptables as a + Stateful Packet Inspection (SPI) firewall - the default. If the server + has a broken stateful connection tracking kernel then this setting can + be set to 0 to configure csf iptables to be a Static firewall, though + some funtionality and security will be inevitably lost + + Added common systemd logs to csf.logignore for new installs + + Modify LF_IPSET in csf to print failure messages instead of aborting + on error + + On servers using systemd if firewalld found to be active, csf and lfd + will not start until is is stopped and disabled as csf cannot be used + with firewalld + + Added option SYSTEMCTL to csf.conf as the location of the systemctl + binary for use with servers using systemd + +7.65 - Fixed csf.blocklist for new installs which incorrectly had OPENBL + enabled by default + +7.64 - UI HTML updates and fixes + + Modified openbl.org URLs in csf.blocklist to use https - this will + likely need URLGET set to 2 (LWP) + +7.63 - Modified Server Check to highlight PHP v5.3.* as EOL and therefore a + security risk + + Port 587 added to TCP_OUT/TCP6_OUT on all new installations (previously + only on cPanel) + + Added new CLI option to csf, -i --iplookup will lookup IP address + geographical information using CC_LOOKUPS setting in /etc/csf/csf.conf + + Manually allowed/denied permanent/temporary IPs through the csf CLI + now include the CC information if no comment is used + + Renamed csf and lfd cron jobs in /etc/cron.d/ to cater for non-LSB + compliant Linux cron managers + + Modified Server Check report to cater for servers running systemd + + More Server Check fixes for out of date checks + + Added 2 new alert settings for FTP and SMTP distributed attacks: + LF_DISTFTP_ALERT and LF_DISTSMTP_ALERT + +7.62 - Modified ModSecurity regexes to be more generic + +7.61 - Fix issues with lfd restart via integrated UI and DA UI + +7.60 - Ensure that /usr/lib/systemd/system/ is created on install on systemd + servers + +7.59 - Fix sanity check for SMTPAUTH_RESTRICT + + Fixed incorrect reference to cxs in the generic csf installer + + Modified csf.conf to show that LWP::Protocol::https is needed for LWP + to retrieve https URLs and added examples of how to install these perl + modules + + Implemented native systemd support for startup and shutdown of csf and + lfd + + Added recommendation in csf.conf to use IPSET if wanting to set + DENY_IP_LIMIT to a high value + + If IPSET is enabled, no sanity warnings are issued for DENY_IP_LIMIT + + Also add SSH port to TCP6_IN on new installations + +7.58 - Display warning and revert to HTTP::Tiny if URLGET is set to use LWP + but the perl module is not installed + +7.57 - URLGET now set to "2" to use LWP by default on new installations + instead of HTTP::Tiny + + If URLGET set to use LWP, csf will perform upgrades over SSL to + https://download.configserver.com + + Added check for URLGET to Server Check + + Added option "3" for CC_LOOKUPS to also include IP ASNs via the + MaxMind GeoIPASNum database + + Updated SSH login regexes + + Updated named regex + + Added 30 second timeout for ST_IPTABLES iptables stats writing to + prevent a child creation loop + + Modified lfd to restart if more than 200 children are currently active + to prevent child creation loops + +7.56 - Fixed issue with Restricted UI item sanity checks failing + + Modified LF_CSF on cPanel servers to detect a change in the cPanel + version and then trigger a restart of ConfigServer scripts (lfd, + MailScanner cxs Watch). Restart triggers are limited to every 12 hours + and will only trigger if upcp is not running + +7.55 - If LF_SELECT is enabled the port(s) listed in PORTS_* can now be + specifed as port;protocol,port;protocol, e.g. "53;udp,53;tcp" to allow + for protocol specific port blocks. This port format can also now be + used in regex.custom.pm and csf --td/--ta to allow udp port blocks + + PORTS_bind now defaults to "53;udp,53;tcp" on new installations + + PORTS_directadmin added for DA installs to allow for per port blocks + if LF_SELECT is enabled + + Ports 993 and 995 now added to TCP_OUT and TCP6_OUT on new installs + + LF_IPSET taken out of BETA as it is proving stable + + Modified Server Check to skip checking xinetd on Plesk servers + + Modified UI_SSL_VERSION for new installations to use the new + IO::Socket::SSL default SSL_version setting of SSLv23:!SSLv3:!SSLv2 so + that SSLv3 is disabled + + If systemd is running the installer disables firewalld using systemctl + +7.54 - Added IPv4/IPv6 column to show whether the port in the csf --ports + option is listed in *_IN (e.g. TCP_IN) + + Added Conn column to show the number of ESTABLISHED connections to the + port in the csf --ports + + Modified Server Check text from "SMTP Tweak" to "SMTP Restrictions" + for cPanel/WHM UI + + Added the following to LF_IPSET for IPv4 IPs and CIDRs: + /etc/csf/csf.allow, /etc/csf/csf.deny, GLOBAL_DENY, GLOBAL_ALLOW, + DYNDNS, GLOBAL_DYNDNS, MESSENGER. + IPv6 IPs, Advanced Allow Filters and temporary blocks use traditional + iptables + + Modified ipset information in csf.conf including that only ipset v6+ + is supported + + Modified ConfigServer::Slurp to carp instead of croak + + Improvements to Server Check nameserver checking to include IPv6 + servers and better determine how many are local nameservers + + Modified csf --graphs to append a trailing slash if missing to + directory name + +7.53 - Modified Slurp.pm to use O_RDONLY instead of O_RDWR + +7.52 - Fixed issue with Restricted UI items sanity checks failing + +7.51 - Removed duplicate "Search System Logs" button from the UI + +7.50 - Added new BETA options LF_IPSET, IPSET. Use ipset for CC_* and + csf.blocklist bulk list matching. See csf.conf for more info + + Added new UI option to view ports on the server that have a running + process behind them listening for external connections + + Added new CLI option (csf -p, csf --ports) to view ports on the server + that have a running process behind them listening for external + connections + + Added new CLI option (csf --graphs) to Generate System Statistics html + pages and images for a given graph type into a given directory. See + ST_SYSTEM for requirements + + If using DYNDNS and the FQDN has multiple A records then all IP + addresses will now be allowed + + IPv6 support added to DYNDNS. Requires the Perl module Socket6 from + cpan.org to be installed + + On DA servers, if LF_DIRECTADMIN is enabled, DIRECTADMIN_LOG_* will be + scanned for login failures to Roundcube, SquirrelMail and phpMyAdmin + if installed and logging enabled via CustomBuild v2+. Failures will + contribute to the LF_DIRECTADMIN trigger level for that IP + + On DA servers, FTPD_LOG now defaults to /var/log/messages on new + installs + + Added exe:/usr/libexec/dovecot/anvil to csf.pignore for new installs + on DA + + Added to UI count of entries in /etc/csf/csf.allow + + Added blocklist.de to csf.blocklists for new installs, latest file + copied to /etc/csf/csf.blocklists.new on existing installs + + Started moving common functions to separate modules within csf + + HTTP::Tiny upgraded to v0.050 + + Fixed csf stop/start routines on reboot for servers using systemd + + Modified integrated UI to display die errors to browser + + Modified X_ARF report to use a self-published schema: + http://download.configserver.com/abuse_login-attack_0.2.json + + Modified X_ARF to lowercase the Source-Type field + + Modified X_ARF template to use the v0.2 "X-XARF: PLAIN" header field + + Updated restricted UI items + + Geo::IP upgraded to v1.45 + + Crypt::CBC upgraded to v2.33 + +7.15 - Updated installer to fix generic installs on some Redhat/CentOS setups + + Fixed issue with temporary allow/deny not applying individual port + rules for outgoing connections + +7.14 - Updated scripts to use download.configserver.com + +7.13 - Fixed issue with temporary allow/deny when issued through the UI + +7.12 - Reverted PACKET_FILTER rule changes + + OPEN added as an option to PS_PORTS so that TCP_IN and UDP_IN ports + will be ignored by Port Scan Tracking by default, but can be added if + desired + +7.11 - DROP_PF_LOGGING disabled by default on new installs as enabling by + default will just cause confusion + +7.10 - Removed debugging code from Port Scan Tracking + +7.09 - Set scripts (.pl,.cgi,.php,.sh,.py) in /etc/csf/ to chmod 700 + + Simplified PACKET_FILTER rules for dropping INVALID connection + tracking states. This feature now only applies a single rule for + incoming INVALID packets + + DROP_PF_LOGGING enabled by default on new installs + + INVALID added as an option to PS_PORTS so that PACKET_FILTER logs will + be ignored by Port Scan Tracking by default, but can be added if + desired + + Modified ST_ENABLE locking + + Regex updates to cater for Plesk 12 - thanks to Marcel Evenson + + Fixed issue with temporary allow/deny comment not being parsed + correctly when port * specified + +7.08 - Withdrawn + +7.07 - Modified lfd to silently drop ST_ENABLE lock queue entries unless + DEBUG is enabled + + Modified ST_ENABLE logging to append to data file and only truncate + when needed + +7.06 - Added locking to ST_ENABLE and ST_SYSTEM to prevent child process + queues + +7.05 - Fix SMTPAUTH_RESTRICT where IPv6 addresses need to be quoted for exim + +7.04 - Added new option LF_DIST_ACTION. If LF_DISTFTP or LF_DISTSMTP is + triggered, then if LF_DIST_ACTION is a path to a script, it will run + the script and pass arguments to it. See csf.conf for more info + + Added limit check on VPS servers when using FASTSTART to ensure there + are sufficient numiptents available for all of the iptables rules in + that block + + Modified SMTPAUTH_RESTRICT to add ::1 as a standalone IP to + /etc/exim.smtpauth + + Fixed LF_BIND - BIND_LOG was not being added to the log list to watch + + On DirectAdmin servers, added new feature LF_DIRECTADMIN. This option + scans DIRECTADMIN_LOG for failed logins and blocks accordingly + + Fixed typo in csf.conf + +7.03 - Added new option DROP_UID_LOGGING which allows UID logging to be + disabled for outgoing connections. This option is enabled by default + and can be disabled on OS's that do not support --log-uid + + Preupgrade copy of csf.conf now created in /var/lib/csf/backup/ for + use with the csf --profile option + + Updates to sanity.txt for new options + + Modified DSHIELD blocklist URL from feeds.dshield.org/block.txt to + www.dshield.org/block.txt for new and existing installs + +7.02 - Make auto.pl scripts more resilient to avoid leaving an incomplete + configuration file after upgrades + + Improved output errors if FASTSTART fails + + Ensure UNZIP binary exists before attempting to process GeoLite CSV + Country database + + Corrected FASTSTART description in Server Report check + + Modified auto.pl to not automatically enable IPV6 on Virtuozzo/OpenVZ + + Report all errors after csf starts in case they were missed in the + main output + +7.01 - Fixed issue with FASTSTART and DROP_PF_LOGGING + +7.00 - New feature SMTPAUTH_RESTRICT - This option will only allow SMTP AUTH + to be advertised to the IP addresses listed in /etc/csf/csf.smtpauth + on EXIM mail servers. The additional option CC_ALLOW_SMTPAUTH can be + used with this option to additionally restrict access to specific + countries. See csf.conf and readme.txt for more information + + New FASTSTART procedures in csf and lfd to centralise functions and + add error reporting + + FASTSTART added to GLOBAL_ALLOW, GLOBAL_DENY, GLOBAL_DYNDNS, csf.deny, + csf.allow, Port Settings, PACKET_FILTER, DROP_NOLOG, SMTP Block, DNS + + Remove duplicate IP addresses from individual blocklists + + Remove duplicate IP addresses (not CIDRs) across blocklists as they + are newly retrieved + + Ensure /usr/local/bandmin/bandminstart exists and is executable on + cPanel servers before using it + + Removed MySQL version check as it is currently redundant from Server + Report + + Improve Net::CIDR::Lite use integrity to prevent unnecessary lfd + failures + + Ensure GeoIPCountryWhois.csv is removed before processing a new d/b + download + + Add /etc/csf/csf.smtpauth to UI if SMTPAUTH_RESTRICT is enabled + + Fixed issue with IPv6 generation of SMTP_ALLOWUSER rules + +6.48 - Fixed csf --ta/d not accepting comma separated port list + + Modified csf -t multi-port reporting + + Modified csf UI to support specifying port list in temporary + allow/deny + + Modified integrated UI call to perform separate calls to + IO::Socket::SSL to use the appropriate AF_INET(6) call depending on + the setting for IPV6 + + Updates to integrated cse UI CSS + + Added regular expressions for courier-imap, Qmail SMTP AUTH and + Postfix SMTP_AUTH for Plesk servers + + Removed RBN from csf.blocklist for new installs as it is now obsolete + + Check for an apply correct permissions on /var/lib/csf and + /usr/local/csf in addition to /etc/csf + +6.47 - Overhaul of Apache regexes to cater for Apache v2.4 formats + + Fail with an appropriate error if attempting to use an IPv6 address + but IPV6 is not enabled + + Fix to OUTPUT chain final packet failure still logging to LOGDROPOUT + when DROP_OUT_LOGGING is disabled + + Strip leading and trailing spaces from form IP in csf UI + + DROP_OUT_LOGGING is now enabled by default on new installations + + ST_ENABLE is now enabled by default on new installations + + CC_IGNORE rewritten to use CC_LOOKUPS data to ignore countries. This + provides a more consistent approach and quicker lookups with reduced + memory footprint. CC_LOOKUPS must now be enabled to use CC_IGNORE + +6.46 - HTTP::Tiny reverted to v0.041 as it breaks on some installations + +6.45 - Modified LF_SCRIPT_ALERT to only report detected lines + + Modified Server Check for sshd_config port to be case-insensitive + + Modified PORTS_sshd check of sshd_config port to be case-insensitive + + HTTP::Tiny upgraded to v0.042 + + Reverse sort temp bans in UI + +6.44 - File globbing is now allowed for logs listed in csf.logfiles and + csf.syslogs + + Added Server Reports recommendation for CloudLinux if running CentOS + or RedHat + + Added Server Reports CloudLinux security feature checks + + Modified Server Report check for dovecot v2 + + Updated Server Report version checks for Fedora, MySQL and Apache + + Added missing bracket to regex.custom.pm example + + Added new PORTS_* options to csf.conf to allow custom modification of + LF_SELECT application ports + + Added Cached memory to the System Statistics + + Added full pseudo-breadcrumbs to cPanel csf UI + + Added new CLI and UI commands to backup/restore csf.conf and to apply + preconfigured csf.conf profiles. See "man csf" and UI for more details + of the "csf --profile [OPTIONS]" commands + + HTTP::Tiny upgraded to v0.041 + +6.43 - Modified RESTRICT_SYSLOG_GROUP to always include /dev/log and + /usr/share/cagefs-skeleton/dev/log, if a socket, if syslog/rsyslog + process is not found and also to cater for systems using systemd (e.g. + Fedora, RHEL v7, etc) + + RESTRICT_SYSLOG_GROUP taken out of BETA as it appears stable and + effective. Setting RESTRICT_SYSLOG to "3" is the recommended option + + Updated readme.txt RESTRICT_SYSLOG mitigations to include CloudLinux + method to disable access to caged /dev/log + + csf --dr modified to remove matching IPs from csf.tempip + + File globbing is now allowed for all *_LOG file settings in csf.conf. + However, be aware that the more files lfd has to track, the greater + the performance hit + +6.42 - New BETA option RESTRICT_SYSLOG_GROUP. This has been added for a new + RESTRICT_SYSLOG option "3" which restricts write access to the + syslog/rsyslog unix socket(s). See csf.conf and the new file + /etc/csf/csf.syslogusers for more information + + Those running our MailScanner implementation, you must be running + at least ConfigServer MailScanner Script v2.91 for logging to work + with RESTRICT_SYSLOG_GROUP + + csf UI option added for editing csf.syslogusers + + Fixed a bug in PT_LOAD not producing PS output + +6.41 - SECURITY WARNING: + + Unfortunately, syslog and rsyslog allow end-users to log messages to + some system logs via the same unix socket that other local services + use. This means that any log line shown in these system logs that + syslog or rsyslog maintain can be spoofed (they are exactly the same + as real log lines). + + Since some of the features of lfd rely on such log lines, spoofed + messages can cause false-positive matches which can lead to confusion + at best, or blocking of any innocent IP address or making the server + inaccessible at worst. + + Any option that relies on the log entries in the files listed in + /etc/syslog.conf and /etc/rsyslog.conf should therefore be considered + vulnerable to exploitation by end-users and scripts run by end-users. + + There is a new RESTRICT_SYSLOG option that disables all those features + that rely on affected logs. This option is NOT enabled by default. + + See /etc/csf/csf.conf and /etc/csf/readme.txt for more information + about this issue and mitigation advice + + NOTE: This issue affects all scripts that process information from + syslog/rsyslog logs, not just lfd. So you should use other such + scripts with care + + Our thanks go to Rack911.com for bringing this issue to our attention + + + UI design updates and fixes + + Modify Apache regex to support log lines containing thread ID + + Prevent lfd from blocking CIDRs triggered from log lines + +6.40 - Fix for LF_INTEGRITY which was non-functional after changes in v6.38 + +6.39 - Added error output from IO::Socket::INET for CLUSTER_* commands from + csf if present + + UI HTML fixes and form design elements added + + Improved error report for invalid csf.conf lines + + Removed Server Check tmp mountpoint checks + +6.38 - Parameterise calls to system and Open3 where possible + + HTTP::Tiny upgraded to v0.039 + + Modifications to csftest.pl + + Removed the UI "Pre-configured settings for Low, Medium or High" as + they are outdated and meaningless. Users should go through the csf + configuration and setup the firewall for their individual server needs + + Translate ampersand for HTML output + + Modified csf.blocklist for new installations to use the SSL URL for + the TOR exit list now that they have forced redirection from the + non-SSL URL, with a note to change URLGET to use LWP + + Modified csf.blocklist for new installations to specify an alternative + TOR exit node list + +6.37 - Fixed issue that produced false-positive failures for IP address + actions through UI when checking for a valid IP address + + Modified lfd to support the use of either "password" or "pass" in + /root/.my.cnf for ST_MYSQL + + Updated CLUSTER information in readme.txt + +6.36 - Removed VPS PASV check from Server Check in UI + + Added new option URLGET - This option can be used to select either + HTTP::Tiny or LWP::UserAgent to retrieve URL data. HTTP::Tiny is + faster than LWP::UserAgent and is included in the csf distribution. + LWP::UserAgent may have to be installed manually, but it can better + support https:// URL's. HTTP::Tiny is selected by default + + Removed extraneous bracket in UI output when reporting errors in user + supplied data + + Added new options LF_EXIMSYNTAX, LF_EXIMSYNTAX_PERM - These will block + IP addresses producing repeated exim syntax errors, typically seen + from: spammers, hackers and broken MUAs and MTAs. This option is + enabled by default + + HTTP::Tiny upgraded to v0.036 + +6.35 - Security fix with included cse when using inbuilt User Interface: + prevent XSS due to malicious directory/file names + +6.34 - Load DYNDNS and GLOBAL_DYNDNS from last known values when restarting + csf instead of waiting for lfd to load the initial rules + + Improved performance of file slurping + + Cluster documentation correction in readme.txt + + UI button style modifications + + Added specific check for Spamhaus drop lists so that retrieval is + never attempted before 2 hours elapses between attempts whether those + retrieval attempts are successful or not + + Improvements to SSHD regexes + + Modified mod_security logging to include the last triggered rule id if + present + +6.33 - Modified LF_PERMBLOCK to perform IP lookup on blocked IP + + Perform modprobe when using FASTSTART on server boot to ensure + iptables modules are loaded + + Modified migration detection for particularly old csf installations + + Check that TAIL and GREP exist and are executable in UI + +6.32 - Applied UI changes to inbuilt cse and Reseller UI's + + Improvements to Virtuozzo/OpenVZ system detection where + /proc/vz/veinfo does not exist + + Added System Check on cPanel servers for disable-security-tokens + + If /etc/csuibuttondisable exists then the UI buttons will revert for + those that cannot cope with the themed ones + +6.31 - Fixed "Deny Server IPs" option in UI + + Additional SSHD regex + + Enable account tracking for LF_CPANEL login failures to allow for + LF_DISTATTACK detection + + Ignore Server Check for register_globals for PHP v5.4+ + + Added new option UI_SSL_VERSION, to allow the setting of the SSL + protocol version that the UI server allows + + Added window Detach option to UI search system logs + + UI display changes + + Fixed files permissions issue affecting System Graphs and lfd Graphs + in DA + +6.30 - Prevent HTML rendering of watch and search system log file output + +6.29 - Removed CLUSTER_PORT from sanity checking + + Modified changelog to state that HTACCESS_LOG needs to be correct for + nginx LF_HTACCESS regexes + + Added new UI option to watch (tail) system log files listed in + /etc/csf/csf.syslogs + + Added new UI option to search (grep) system log files listed in + /etc/csf/csf.syslogs + + Improvements to "View iptables Log" output in UI + + Enable "SSL_honor_cipher_order" for UI IO::Socket::SSL sessions + +6.28 - Fixed sanity check for UID_INTERVAL + +6.27 - Modified Apache regexes for Apache v2.4+ + + Fixed UI configurable lines display for lfd.log + + Fixed length display text for CLUSTER_KEY in csf.conf + + Ignore suspendedpage.cgi triggers for LF_SYMLINK on cPanel servers + + Updated sanity checks and ranges for csf.conf settings + + Added RESTRICT_UI to Server Check recommended options + + Modified Virtuozzo/OpenVZ FTP port check to verify kernel version + before issuing PASV port warning + + Added new setting PS_DIVERSITY. To specify how many different ports + qualifies as a Port Scan you can increase this value. The risk in + doing so will mean that persistent attempts to attack a specific + closed port will not be detected and blocked. The setting defaults to + the original setting of 1 + + Added 3 LF_HTACCESS regexes for nginx. Remember to set HTACCESS_LOG + correctly for the location of the nginx error log + +6.26 - Fixed UI issue with some settings sent via the Cluster Config option + + Modified CONNLIMIT_LOGGING rule insertion point + + Added new feature: Outgoing UDP Flood Protection. This option limits + outbound UDP packet floods. These typically originate from exploit + scripts uploaded through vulnerable web scripts. The feature is + controlled by: UDPFLOOD, UDPFLOOD_LIMIT, UDPFLOOD_BURST, + UDPFLOOD_LOGGING, UDPFLOOD_ALLOWUSER + + Update the TOR URL in existing /etc/csf/csf.blocklists file if still + set to the old URL + +6.25 - Fixed UI "Temporary IP entries > Flush all temporary IP entries" + + Fixed UI_USER and UI_PASS being emptied on saving the firewall + configuration through the UI + + Fixed CLUSTER_KEY not displaying when RESTRICT_UI is disabled + +6.24 - Security - Removed items from Cluster Config UI option if RESTRICT_UI + enabled + +6.23 - Security - added new option RESTRICT_UI. This options restricts the + ability to modify settings within csf.conf from the csf UI. Should + the parent control panel be compromised, these restricted options + could be used to further compromise the server. This option is enabled + by default on all installations + + Added entries to csf.pignore on new installations on cPanel servers + for Dovecot v2.2 (cPanel v11.40+) + + Fixed UI Template validation error message + +6.22 - Security Fix - Sanitised user data input to prevent running + unauthorised commands via the UI. A user would require root access to + exploit this, so vulnerability is probably low. Thanks to Steven at + Rack911.com for reporting this issue + + Added Password ENV variable check to Server Check on cPanel servers + + Update cPanel ACL Driver installations to change force cache update + using "touch" instead of removing the cache + + Modified TOR URL in /etc/csf/csf.blocklists to use: + http://check.torproject.org/cgi-bin/TorBulkExitList.py?ip=1.1.1.1 + +6.21 - Modified auto-update logic to only create the /etc/cron.d/csf_update + file if it does not already exist + + Fix permissions on csf man file and directory + + Modified webmin module paths to be relative rather than absolute so + that webmin via mod_proxy works correctly + + Fixed "in" direction --tempallow/--tempdeny leaking into [comment] + + Added nginx regex for ModSecurity rule detection. Remember to set + MODSEC_LOG correctly for the location of the nginx error log + + Fixed file permission/ownership problem on DirectAdmin servers for the + /plugins directory + +6.20 - Introduced a new directory structure to get closer to the Linux + Filesystem Hierarchy Standard (FHS): + /etc/csf/ - (mostly) configuration files + /var/lib/csf/ - temporary data files + /usr/local/csf/bin/ - scripts + /usr/local/csf/lib/ - perl modules and static data + /usr/local/csf/tpl/ - email alert templates + Existing data and templates files are migrated into the new structure + automatically. Some files and directories are symlinked to /etc/csf/ + for backwards compatibility and ease of use. See the following for + individual file locations in the new configuration: + http://blog.configserver.com/?p=7 + + CC_LOOKUPS rDNS reporting improvements + + HTTP::Tiny upgraded to v0.033 + + Removed Security Token check from Server Check Report now that it is + implicitly set in v11.18.0+ + + Switched the location of the csf.pl and lfd.pl binaries with their + symlinks + + Code tidy for servercheck.pm, csfui.pl + + Allow comments to be appended to csf --tempdeny and csf --tempallow in + the same way as csf --deny and csf --allow. Also made the options more + flexible in usage of optional elements + + Added Comments field to UI for Quick Allow, Quick Deny, and Temporary + Allow/Deny + + Added csf(1) man page and changed csf --help to use a text version of + the new man page + + Fixed unnecessary open of csf.fignore + +6.15 - Modified MaxMind City Database lookup code to be more resilent + +6.14 - Added support for cPanel v11.38.1+ AppConfig addon registration + + NOTE: In accordance with the new conventions for v11.38.1+ AppConfig + the url to the csf WHM plugin will change from /cgi/addon_csf.cgi to + /cgi/configserver/csf.cgi. This will only happen with csf v6.14+ and + cPanel v11.38.1+. Older version of csf will continue to use the old + URL. This has no particular relevance to users accessing through WHM, + but will affect direct URL access by users or third party + applications + + Added support for cPanel v11.38.1+ Custom ACL driver. This creates an + ACL (software-ConfigServer-csf) which must be used to grant resellers + access via "WHM > Edit Reseller Nameservers and Privileges > Third + Party Services > ConfigServer Security & Firewall (Reseller UI)" when + running cPanel v11.38.1+ + + Added Server Check for AppConfig restrictions for cPanel v11.38.1+ + + Switched from using Geo::IP::PurePerl to Geo::IP perl module + + Added MaxMind GeoIP Anonymous Proxies to csf.blocklists for new + installs + + Added new setting CSFDATADIR. This is the location of the csf and lfd + temporary data. By default it is set to the current value of /etc/csf + with the intention of moving this data to /var/lib/csf in the future + in a move towards the Linux Filesystem Hierarchy Standard (FHS) + + Moved the default location for ST_DISKW_DD to /var/lib/dd_test for new + installations + +6.13 - Fixed Server Check for dhclient + +6.12 - Added iptables UID logging for dropped outgoing packets + + New feature - DROP_OUT_LOGGING. Enables iptables logging of dropped + outgoing connections. Where available, these logs will also include + the UID connecting out which can help track abuse. Note: Only outgoing + SYN packets for TCP connections are logged. The option is not enabled + by default, but we recommend that it is enabled + + Option DROP_ONLYRES now only applies to incoming port connections + + New feature - User ID Tracking. This feature tracks UID blocks logged + by iptables to syslog. If a UID generates a port block that is logged + more than UID_LIMIT times within UID_INTERVAL seconds, an alert will + be sent. Requires DROP_OUT_LOGGING to be enabled + + Modified Port Scan Tracking regexes to ensure only incoming + connections are tracked + + Added Server Check for dhclient running + + Added Server Check on cPanel servers for antirelayd + + Added Server Check for a swap file (don't bother on Virtuozo) + + Added Server Check for xinetd, qpidd, portreserve and rpcbind in + Services Check since most people won't use them + +6.11 - Fixed SMTP_ALLOWLOCAL not functioning correctly. Added IPv6 support + for SMTP_ALLOWLOCAL + + Removed SMTP_BLOCK restriction for IPv6 requiring port 25 to be + present in TCP6_OUT + +6.10 - New feature - separate Blocklist configuration file to allow for + expansion of the available block lists. The following options have + been removed from csf.conf and a new csf.blocklists file added to + configure blocklists: + LF_DSHIELD, LF_SPAMHAUS, LF_TOR, LF_BOGON + + During the upgrade if those options were enabled, then they will be + enabled in the new csf.blocklists file. If you used a custom blocklist + URL in one of those options you will have to manually add it to the + new configuration. + + Modified UI to provide edit function for csf.blocklists + +6.09 - Modified csf UI to detect Webmin install and symlink script and images + directory so as to no longer require Webmin module update on a new csf + version + + Tidied up csf UI html + + Fixed System Statistics graph display when using Webmin + + Modified Server Security check to only perform GENERIC test when using + Webmin to prevent hanging processes + + Added CLI options --car, --carm. This removes an allowed IP in a + Cluster and removes it from /etc/csf.allow + + Added new options LF_WEBMIN, LF_WEBMIN_PERM. This feature adds login + failure detection for Webmin in WEBMIN_LOG + + Added new option LF_WEBMIN_EMAIL_ALERT. This feature sends an email + if a successful login to Webmin is detected in WEBMIN_LOG + + Modified LF_SCRIPT_ALERT text in csf.conf for cPanel servers + + Modified proftpd regex to cope with non-standard format and to remove + trailing colons from account name + + Modified LF_SCRIPT_ALERT regex to cater for paths containing spaces + + Improvements to LF_SCRIPT_ALERT memory usage and possible script + detection + + Added alternative LF_SCRIPT_ALERT regex for specific 1H.com exim + logging ACL + +6.08 - Added IPV6_SPI workaround for CentOS/RedHat v5 and custom kernels that + do not support IPv6 connection tracking by opening ephemeral port + range 32768:61000. This is only applied if IPV6_SPI is not enabled. + This is the same workaround implemented by RedHat in their sample + default IPv6 rules + +6.07 - Fixed issue with processing /proc/PID/stat for process information + +6.06 - Prevent csf/lfd from failing to run if a non-critical configuration + file does not exist + + In webmin, force table stylesheet to override webmin css. Requires + webmin module reinstall on existing installations + +6.05 - Improvements to minimal perl module detection on new installs + + Bugfix for default lfd.pl perl shebang + +6.04 - Implement slurp routine for configuration files to cater for incorrect + linefeeds + + Ignore leading and trailing spaces from lines in configuration files + + Fixed Include statements in csf.ignore not implemented in lfd + + Additional debug logging for RT_*_LIMIT added + + Replaced call to Time::HiRes::sleep with standard sleep + + Additional dovecot entries in csf.pignore for new installations + +6.03 - Switched from using LWP to HTTP::Tiny to reduce memory footprint and + reliance on the LWP perl module. The HTTP::Tiny module is included in + the distribution, so no further action is necessary + + Modified lfd perl module loading to be conditional where possible to + reduce lfd memory footprint + + Modify initial file processing to reduce lfd memory footprint + + Modify PS_PORTS processing to reduce lfd memory footprint + + Moved init of Geo::IP::PurePerl into iplookup subroutine + + Removed "DEFERRED" login failure checking from CPANEL_LOG regex due to + false-positives + + Modify LF_DIRWATCH_DISABLE so that only files are added to + suspicious.tar and removed. Suspicious directories will no longer be + removed + + Removed File::Path - no longer required + +6.02 - Modify MESSENGER HTML header to return code 403 instead of 200 + + Modify UI daemon to fallback to IPv4 if IPV6 setting is not enabled + + Added new options LF_SYMLINK and LF_SYMLINK_PERM. This feature enables + detection of repeated Apache symlink race condition triggers from the + Apache patch provided by: + http://www.mail-archive.com/dev@httpd.apache.org/msg55666.html + This patch has also been included by cPanel via the easyapache option: + "Symlink Race Condition Protection" + +6.01 - Ensure all binaries are called with their full paths for the scheduled + Server Security Check reports + + Allow csf -u/-uf/--update and -c/--check when csf is disabled + + Make RT_* checks IPv6 compatible + + Added dns query caching for ip lookups during lfd process lifetime + + Modify TOR rule loading to use FASTSTART in lfd if enabled + + Added iptables locking to FASTSTART code + + LF_INTERVAL now defaults to 3600 on new installations to better cope + with slow brute force login attempts + + Removed references to .cpanel.net being ignored from the changelog as + they no longer apply and could cause confusion + + Fix csf.rignore loader regex causing unnecessary DNS lookups if file + has no entries + + Added "DEFERRED" login failure checking to CPANEL_LOG regex + +6.00 - Major new option - FASTSTART: + + This option uses IPTABLES_SAVE, IPTABLES_RESTORE and IP6TABLES_SAVE, + IP6TABLES_RESTORE in two ways: + + 1. On a clean server reboot the entire csf iptables configuration is + saved and then restored, where possible, to provide a near instant + firewall startup[*] during the boot sequence + + 2. On csf restart or lfd reloading tables, CC_* as well as SPAMHAUS, + DSHIELD, BOGON, TOR are loaded using this method in a fraction of + the time than if this setting is disabled + + [*] Not supported on all OS platforms + + FASTSTART allows for very quick startup at reboot and during + uptime. If the Country Code blocking options (CC_*) are used, their + tables are loaded by csf and lfd almost instantly, compared to many + minutes for large countries previously + + FASTSTART is enabled on new installations (or those in TESTING + mode). Existing installations will need to enable it manually + + Other Changes: + + Improvements to csf and lfd init routines + + LF_QUICKSTART renamed to LFDSTART, setting value preserved + + Fixed a problem with scheduled Server Security Check reports + + Crypt::CBC upgraded to v2.32 + +5.79 - Modified csf error routine to store failing error in csf.error and + display an instructional message + + Check for libkeyutils-1.2.so.2 in LF_EXPLOIT option SSHDSPAM + + Modified the Server Report proxysubdomains check on cPanel servers + + Added new options CC_DENY_PORTS, CC_DENY_PORTS_TCP, + CC_DENY_PORTS_UDP. This feature denies access from the countries + listed in CC_DENY_PORTS to listed TCP/UDP ports. For example, using + this FTP access port 21 could be blocked to only the specified + countries + +5.78 - Due to issues that some are experiencing with the switch from the + state to the conntrack module a new settings has been added + USE_CONNTRACK which is disabled by default except on servers running + kernel 3.7+ where on new installations it will be enabled + +5.77 - Add an exception for the useless Virtuozzo kernels iptables + implementation so that csf uses the deprecated state module instead of + conntrack + +5.76 - Only add the /128 IPv6 bound address per NIC instead of the whole /64 + to the local IPv6 addresses + + Modify SSHD and SU regexes to allow for empty hostname field in log + file + + Added new option UNBLOCK_REPORT. This option will run an external + script when a temporary block is unblocked + + Additional entries in csf.logignore on new installations + + Switched from using the iptables state module to using the conntrack + module in preparation of the formers obsolescence + + Removed LF_EXPLOIT_CHECK and replaced it with LF_EXPLOIT_IGNORE so + that new tests can be easily added and then ignored desired + + Added new LF_EXPLOIT check SSHDSPAM to check for the existence of + /lib64/libkeyutils.so.1.9 or /lib/libkeyutils.so.1.9, See: + http://www.webhostingtalk.com/showthread.php?t=1235797 + +5.75 - Fixed issue with single quotes appearing in CC lookup names leading to + lfd IP blocks to fail + +5.74 - Additional entries in csf.pignore for the cPanel installation to cater + for v11.36 processes on new installations + + Added workaround for cPanel /etc/cpupdate.conf check in Server Report + for changes in v11.36 + + Additional entries in csf.logignore on new installations + + Try harder to get a CPU temperature if lm_sensors is installed for + System Statistics + + Enforce PORTFLOOD setting restrictions and issue warning if entry + discarded + + Correct location of CC_ALLOWF in LOCALINPUT after update from lfd + + Make CC_[chain] actions more verbose in lfd.log + + Added new options CC_ALLOW_PORTS, CC_ALLOW_PORTS_TCP, + CC_ALLOW_PORTS_UDP. This feature allows access from the countries + listed in CC_ALLOW_PORTS to listed TCP/UDP ports. For example, using + this FTP access port 21 could be restricted to only the specified + countries + + Moved temporary and csf.allow/csf.deny rules from + LOCALINPUT/LOCALOUTPUT chains to ALLOWIN/ALLOWOUT to allow for the new + CC_ALLOW_PORTS feature + + Modified SMTP_PORTS to include ports 465 and 587 on new installations + + Added new option PT_FORKBOMB. Fork Bomb Protection. This option checks + the number of processes with the same session id and if greater than + the value set, the whole session tree is terminated and an alert sent + +5.73 - Fixed issue with crontab line for TESTING option not being detected + and removed when TESTING mode is disabled + +5.72 - Added missing DD setting in DA and generic installations for ST_DISKW + + Modified IPv6 port settings to reflect IPv4 port settings for new + installs in csf.conf + + If a deleted executable process is detected and reported then do not + further report children of the parent (or the parent itself if a child + triggered the report) if the parent is also a deleted executable + process + + Parent PID added to PT_DELETED_ACTION parameters + + In the Server Report allow for spaces before Apache directives + + Updated instructions for modifying log_selector for exim + configurations in readme.txt and Server Report + + Modify DD calculation for ST_DISKW for disks that report in GB/s + + Updated to use the new cPanel 11.36+ integrated perl binary if exists + +5.71 - Fixed problem processing dd output for ST_DISKW on some systems + + Fixed dovecot imap login failure regex processing + + Added regexes for dovecot pop3 and imap raw logs (i.e. not syslog) + +5.70 - Fixed an issue with PERMBLOCK introduced in v5.68 + +5.69 - Fixed duplicate entries in csf.conf on GENERIC installations + +5.68 - New feature added - LF_DIST_INTERVAL. This option provides a separate + timing interval for both LF_DISTFTP and LF_DISTSMTP. By default it is + set to 300 seconds + + Implemented better handling of repeat blocks when an IP is already + temporarily or permanenetly blocked + + Added missing inclusion of Time::HiRes in csf.pl + + Silence LF_DISTFTP and LF_DISTSMTP ignored IP logging to lfd.log + unless DEBUG enabled + + Silence DYNDNS IP address updates to lfd.log unless DEBUG enabled + + RELAYHOSTS setting now defaults to "0" to improve security on cPanel + servers + + Increased default value of DENY_IP_LIMIT to 200 + +5.67 - Fixed a problem with permanent IP blocking when using LF_SELECT + +5.66 - Implemented a new locking system to try to mitigate an iptables bug + when issuing concurrent iptables commands + + Implement flushing on the lfd pid file so that it is always accurate + + Improvements to csf --grep [ip] to escape regular expression matching + + New feature added - LF_REPEATBLOCK. This option instructs csf to deny + an already blocked IP address the number of times set. See csf.conf + for more information + + New feature added - LF_BLOCKINONLY. This option instructs csf to only + block inbound traffic from those IP's and so reduces the number of + iptables rules, but at the expense of effectiveness. See csf.conf for + more information + + New feature added - ST_DISKW. This option adds disk write performance + statistics to the stats graphs. See csf.conf for more information + + Fixed file location for Debian and derivative OS's for + /etc/mysql/my.cnf in Server Check + +5.65 - Removed some of the command locking as it was causing hangs + +5.63 - Implemented a locking and retry system to try to mitigate an iptables + bug when issuing concurrent iptables commands + +5.62 - Added ModSecurity connection dropping to the LF_MODSEC regex + + Added new option - ETH6_DEVICE. By adding a device to this option, + ip6tables can be configured only on the specified device. Otherwise, + ETH_DEVICE and then the default setting will be used + + Added new option - LF_SCRIPT_ACTION. On cPanel servers, this can + contain the path to a script that is run whenever LF_SCRIPT_ALERT is + triggered + + Fixed stats graph average calculation and display if average equals 0 + + Split Slow MySQL Queries stats graphs from MySQL Queries + + Improvements to Apache CPU Usage stats graphs + +5.61 - On Debian systems, check for my.cnf in /etc/mysql/my.cnf in Server + Check + + Add missing/changed images in the DA/Webmin installs. For webmin, the + csf webmin module will need to be reinstalled + + Another fix for LF_NETBLOCK to skip IPv6 addresses + + Fixed csf --tempallow where -d [direction] was performing inout when + in requested + + Fixed UI option "Edit the Log Scanner file (csf.logfiles)" which was + incorrectly overwriting csf.dyndns instead of writing to csf.logfiles + + Changed ETH_DEVICE_SKIP device check from a failure to a warning + + Skip checks for register_globals and suhosin if running PHP v5.4.* in + Server Check report + +5.60 - Added new options to include the Spamhaus Extended DROP list. These + additional netblocks are included in the main Spamhaus chain. The + feature uses LF_SPAMHAUS_EXTENDED and LF_SPAMHAUS_EXTENDED_URL which + are enabled by default, but used only if LF_SPAMHAUS is enabled. To + force a reload of the SPAMHAUS list to include the Extended list, + delete /etc/csf/csf.spamhaus file after upgrading to this version and + then restart lfd + + Added new options to allow blocking of TOR Bulk Exit nodes. This works + in the same manner as the LF_SPAMHAUS and LF_DSHIELD options. The + feature uses LF_TOR and LF_TOR_URL and is disabled by default. + Warning: This could block legitimate users who are trying to protect + their anonymity, so use with caution + + Fix LF_NETBLOCK to skip IPv6 addresses as it is unsupported as has + long been stated in csf.conf + + Added missing html elements in UI + + Added unblock button to UI IP searches when results is either in + csf.deny or a temporary block + + Implemented a locking system to mitigate iptables stability issues + when loading concurrent iptables chains in lfd + + Fixed bug in the display of the 30 days ST_SYSTEM stats + + Added new option ST_SYSTEM_MAXDAYS. This allows you to define the + maximum number of days of stats to collect (default 30 days) + + Increased stats graph sizes + + Added CIDR checking of csf.allow to the CLI command csf --deny + + Added checking of csf.ignore to the CLI command csf --deny + +5.59 - Fixed a loop which caused high load when using GLOBAL_IGNORE + + Improvements to GLOBAL_IGNORE load speed and effectiveness + + Improvements to CC_IGNORE load speed + +5.58 - Corrected ST_APACHE error message return text + + Add meaningful message if stats graph generation fails in UI + + Added new icon in UI for "Quick Allow" that inserts the current + visitors IP address + + Added new icon in UI for "Quick Ignore" that inserts the current + visitors IP address + + Replaced some of the included icons + +5.57 - Added new option PT_APACHESTATUS to configure the URL to the Apache + Status URL during PT_LOAD alert report + + Added Apache Statistics to ST_SYSTEM. A new option ST_APACHE must be + set to collect these statistics and PT_APACHESTATUS must be correctly + set. ST_APACHE is disabled by default + + Modification to SYSLOG option to remove the later introduced "nofatal" + option to improve backwards compatibility, also enable the "pid" + option to log the process ID + + Added new options SYSLOG_CHECK and SYSLOG_LOG to check whether syslog + is running. See csf.conf for more information. This option is disabled + by default, but we recommend that it is enabled on all servers + + Added SYSLOG_CHECK to Server Check Report recommended settings + +5.56 - Improvements to ST_MYSQL password detection in /root/.my.cnf where the + password is quoted + + Improvements to the SMTP AUTH regex to cope with differing settings in + exim log_selector + + Removed debugging code in SMTP AUTH regex detection + +5.55 - Update Fedora version check now that v17 has been released + + Added MySQL Connection and Thread statistics to ST_MYSQL/ST_SYSTEM + + Modified Server Check Report for cPanel servers see whether mod_ruid2 + has been enabled making the Apache suEXEC check moot + + Improvements to the SMTP AUTH regex to cope with differing settings in + exim log_selector + +5.54 - Modified ST_MYSQL connection errors to advise disabling ST_MYSQL if it + is not used + + ST_MYSQL now disabled by default on new csf installations + +5.53 - Added Email Usage to the ST_SYSTEM System Statistics feature when RT_* + options are enabled + + Fixed incorrect Min/Max calculations in System Statistics + + Improvements to Disk Usage stats in System Statistics for some virtual + environments + + Added CPU Temperature to the ST_SYSTEM System Statistics feature when + lm-sensors/coretemp installed and enabled (highest core temp recorded) + + Added MySQL graphs to the ST_SYSTEM System Statistics feature when + ST_MYSQL is installed and enabled - requires DBI and DBD::mysql perl + modules. Authentication is via new ST_MYSQL* options. The option is + enabled on cPanel servers by default, disabled on others + + Modified stats collection routine to append data to the stats file on + each minute interval and to clean up only on lfd startup. This is to + help minimise the risk of the stats file being incomplete due to + process termination + + Added new options LF_DISTSMTP, LF_DISTSMTP_UNIQ and LF_DISTSMTP_PERM. + This option will keep track of successful SMTP logins. If the number + of successful logins to an individual account is at least LF_DISTSMTP + in LF_INTERVAL from at least LF_DISTSMTP_UNIQ IP addresses, then all + of the IP addresses will be blocked. This option can help mitigate the + common SMTP account compromise attacks that use a distributed network + of zombies to send spam (exim MTA only). Not enabled by default + + Modified Server Check Report for cPanel servers see whether mod_ruid2 + has been enabled making the PHP Handler check moot + + Modified the ModSecurity regex to cater for the paid Atomic rules + Apache error log non-standard format + + Modified non-cPanel new installs to disable ST_SYSTEM by default + +5.52 - Alternative kill and status methods employed for lfd init process on + Debian/Ubuntu + + Added new feature: System Statistics. This option will gather basic + system statstics. Through the UI it displays various graphs for disk, + cpu, memory, network, etc usage. The feature requires the perl module + GD::Graph. It is enabled by default with the ST_SYSTEM option + +5.51 - Updated Donation buttons + +5.50 - Removed check for Melange on cPanel servers from Server Check Report + + Improvements to the cPanel exim SMTP AUTH login failure regex after + changes in cPanel v11.32 + + Added exe:/usr/local/cpanel/3rdparty/sbin/mydns to csf.pignore for new + installs on cPanel servers + + Additional cmd/pcmd suggestions added to csf.pignore for new installs + on cPanel servers (not enabled) + +5.49 - Remove atd from Service Check in Server Check Report + + Ensure all DNS traffic between non-local IP addresses in + /etc/resolv.conf is allowed through the firewall when DNS_STRICT_NS is + not enabled + + Added exim to example script pt_deleted_action.pl + + Added /var/log/cxswatch.log to csf.logfiles for new installations + + Added new option LF_ALERT_SMTP which allows lfd to be configured to + send alert emails via SMTP instead of through the SENDMAIL binary. + LF_ALERT_SMTP needs to be set to the name or IP address of the SMTP + server to use this feature + + Added new option CC_DROP_CIDR. Set this option to a valid CIDR to + ignore CIDR blocks smaller than this value when implementing + CC_DENY/CC_ALLOW/CC_ALLOW_FILTER. This can help reduce the number of + CC entries and may improve iptables throughput + + Improved installation procedure for checking required perl modules + +5.48 - New option LF_QOS added which matches hits against the mod_qos Apache + module + + New option LF_CXS added which matches hits against the mod_security + Apache module rule for cxs if implemented + +5.47 - Improvements to non-core perl module loading + + Improvements to PT_LOAD Apache Status retrieval and messages + + Regex modifications to cater for Dovecot v2.1+ + + On cPanel servers, block additional ports that exim uses in the WHM > + Service Manager for RT_*_BLOCK + +5.46 - Modified upgrade warning for integrated UI to not use the DA warning + text + + Validate local IP addresses + + Only check local IPv6 addresses if IPV6 is enabled in config + + Separate IPv4 from IPv6 ignore CIDRs due to Net::CIDR::Lite + restrictions + + Improvements to ignore files IP address validation + + Add server check for PHP v5.2.* to the obsolete/security risk list + + Add server check for RedHat/CentOS v4.* and Fedora < v15 to the + obsolete/security risk list + + Removed server checks for RLimitMEM/RLimitCPU + +5.45 - Only log Log Scanner in lfd.log if DEBUG set to 2 to allow empty + reports if monitoring lfd.log + + Added new option LF_BOGON_SKIP. If you don't want BOGON rules applied + to specific NICs, then list them in a comma separated list + + Added new option LF_CONSOLE_EMAIL_ALERT which will send an email if + there is a root login to the server console. This is enabled by + default + +5.44 - New feature - Log Scanner. This feature will send out an email summary + of the log lines of each log listed in /etc/csf/csf.logfiles. All + lines will be reported unless they match a regular expression in + /etc/csf/csf.logignore + + Set LWP::UserAgent agent to "csf/[version]" instead of the default + +5.43 - csf and lfd modified to better handle !lo interface for compatibility + with newer iptables versions + + Removed use of Sys::Hostname::Long + + Added new options LF_APACHE_403 and LF_APACHE_403_PERM. This option + will keep track of the number of "client denied by server + configuration" errors in HTACCESS_LOG. If the number of hits is more + than LF_APACHE_403 in LF_INTERVAL seconds then the IP address will be + blocked. See csf.conf for more information + +5.42 - SECURITY FIX. Anyone running csf on a DirectAdmin server should + upgrade to this release immediately: + + Add check for successful open of admin.list on DA servers to avoid + a segfault, which could lead to a buffer overflow + +5.41 - Added text description of allow/deny made by cPanel Resellers via UI + in csf.allow and csf.deny + + If cPanel UI Resellers email alerts are enabled, a csf grep will be + performed before an IP adress is unblocked and the output included in + the alert email, together with the results of the UNBLOCK + + If cPanel UI Resellers email alerts are enabled, the results of an + ALLOW or DENY will be included in the alert email + + Added logging of cPanel UI Reseller actions ALLOW/DENY/UNBLOCK to + /var/log/lfd.log + + Update to urlget to not fail on empty file if successfully retrieved + + Take Integrated UI out of BETA as no reported issues + + Take csf.redirect out of BETA as no reported issues + +5.40 - Added new feature - csf UI Reseller functions for cPanel. See + /etc/csf/csf.resellers and WHM UI + + Improvements to cse Integrated UI + + Modified redundant cPanel function calls in UI + + Removed ModSecurity functionality in UI + + Modified WHM UI "Remove Deny" to be "Quick Unblock" that now removes + a specified IP address entries from csf.deny and/or temporary blocks + +5.39 - Fixed detection of the nat tables on some Virtuozzo VPS servers + +5.38 - Modification to the Integrated UI to allow access to cxs if it is + installed via UI_CXS + + Include an updated cse with csf for use with the Integrated UI via + UI_CSE + + Added option UI_CIPHER to allow the SSL cipher suite to be set + manually for the Integrated UI + + Added HTTP request internal memory limits to the Integrated UI + +5.37 - Added new BETA feature - User Interface. This feature provides a HTML + UI to csf and lfd, without requiring a control panel or web server. + The UI runs as a sub process to the lfd daemon. See csf.conf and + readme.txt for information and requirements + + Fixed issue with RT_* regex routine ignoring 127.0.0.1 + + Fixed detection of DNSONLY cPanel installs + + Added Security Check on cPanel server checks for disabled "Proxy + subdomains" and "Proxy subdomain creation" + + Added new option LF_CPANEL_ALERT_ACTION. If a LF_CPANEL_ALERT event is + triggered, then if LF_CPANEL_ALERT_ACTION contains the path to a + script, it will run the script and passed the ip and username and the + DNS IP lookup result as 3 arguments + +5.36 - Fix for the lfd child lock mechanism effectiveness + +5.35 - Added new BETA feature - Port/IP address Redirection. This feature + uses the file /etc/csf/csf.redirect to redirect connections from/to + IP/port combinations to alternative IP/ports. See readme.txt for more + information + + Updated syslog daemon checking in Server Report + + Set PT_DELETED to 0 by default on new installations + + Improvements to csf startup locking within lfd + + Improvements to error trapping between csf and lfd + + Check minimum values for interval settings and set to recommended + values if too low during lfd startup to improve stability + + Added lfd child locks to improve stability due too server or network + resource issues or too low an interval setting + + Updated Sanity Checks for settings + + lfd will now not start if TESTING is enabled + + Do not require write permissions to /etc/crontab when no changes + required for TESTING mode enable/disable + + Prevent parricide by lfd children unless required + + Added nat table check in csf + + Fixed bug in csf --grep not matching the nat table + +5.34 - Improvement to dovecot account name sanitisation checks in lfd + + Modified cronjobs for new installs to be compatible with anacron + + Added new option CLUSTER_BLOCK which is enabled by default. This + allows you to disable automatic sharing of lfd blocks around a csf + cluster, e.g. if you only wish to use the CLUSTER option to share + settings and manual blocks and allows + + Added new option RT_ACTION. If an RT_* event is triggered, + then if RT_ACTION contains the path to a script, it will be run in a + child process and be passed a list of items (see csf.conf - for cPanel + and DA only) + + Fix to DYNDNS Advanced Allow/Deny Filters using pipe separator + + Set permissions to 700 on *.sh, *.pl and *.php in /etc/csf/ instead of + a blanket 600 of non-csf scripts + +5.33 - Add link to the Changelog when csf is upgraded + + Extended urlget timeout to 300 seconds to help cope with the large + MaxMind City Database download where enabled + + Include cpdavd login failures for LF_CPANEL. Added port 2077 and 2078 + to the cPanel block ports when LF_SELECT enabled + + Disable ftp Server Check reports if ftp server disabled in cPanel + + Added regex validation to any specified csf.pignore or csf.figonre + entries to lfd + + Updated cPanel tier checks to cope with old STABLE and DNSONLY + releases and newer v11.30+ + + Improvement to account name sanitisation checks in lfd + +5.32 - AUTO_UPDATES enabled for new installations in csf.conf + + Removed the JS LF_EXPLOIT_CHECK as it is no longer prevalent. If still + set in csf.conf it will be ignored + + Check MESSENGER service to ensure privileges are dropped before + starting the daemon + + Drop privileges when performing removal during LF_DIRWATCH_DISABLE + + For new installations, IPV6 enabled if IP6TABLES exists and an IPv6 + address is found in the output from IFCONFIG. IPV6_SPI is set + according to the kernel version (i.e. whether SPI is supported or not) + +5.31 - Updated the LF_TRIGGER_PERM explaination in csf.conf to properly + reflect the possible settings of LF_TRIGGER + + Perform account name sanitisation checks in lfd + +5.30 - Fixed a SECURITY BUG that can be exploited remotely via log file + spoofing resulting in root privilege escalation. Our thanks to Jeff + Petersen for reporting this issue + + All csf users should upgrade to this release immediately + +5.22 - New feature: Connection Limit Protection (CONNLIMIT, + CONNLIMIT_LOGGING). This option configures iptables to offer more + protection from DOS attacks against specific ports. It can also be + used as a way to simply limit resource usage by IP address to specific + server services. This option limits the number of concurrent new + connections per IP address that can be made to specific ports. See + csf.conf and readme.txt for more information and about the format of + the CONNLIMIT option and its limitations + + Minor csf UI Firewall Configuration virtual pagination improvements + + Updated cPanel Server Check update settings for v11.30+ + + Removed cPanel Server Check for new versions due to changes in the + v11.30+ versioning system making this redundant + + Updated MySQL Server Check for v5.1.* + + Added a warning to csf.conf for SYNFLOOD to only enable the option if + you know you are under a SYN flood attack as it will restrict all new + connection to the server if triggered + +5.21 - Added port 500 to DROP_NOLOG for new installations + + Corrected the LF_APACHE_404 lfd log line output + + Added startup failure on invalid PORTFLOOD settings + + Make csf.pignore item selector case-insensitive (e.g. exe: and EXE:) + + All user: item selector examples removed from the default csf.pignore + for all new installations (e.g. user:mailman). csf.pignore examples + for some common processes can be found here: + http://forum.configserver.com/viewtopic.php?f=6&t=2059 + + Updated DA and GENERIC default csf.pignore files for new installations + + csf UI Firewall Configuration virtual pagination improvements + + Updated Sanity checks for settings in csf.conf + + Modified Sanity checks for settings in csf.conf to always show the + recommended range in the UI + + Set LF_GLOBAL to 0 instead of an empty string by default on new + installations + + Added new option LF_LOOKUPS to toggle rDNS IP address lookups + +5.20 - Updated installation scripts to distinguish between IPv4 and IPv6 port + report + + Modified Virtuozzo VPS numiptent check to distinguish between host and + client servers + + Added exe:/usr/sbin/ntpd to csf.pignore on new installations + + Don't perform the runlevel check on Debian/Ubuntu servers as it isn't + indicative of a potential security issue as with other Linux distros + + Added new option PT_DELETED_ACTION which if defined with an executable + script will run if PT_DELETED is triggered passing the process PID, + executable and account. An example script is provided in: + /etc/csf/pt_deleted_action.pl + + If CC_LOOKUPS enable for the MaxMind City Database then also display + the Region, where available + + Added csf UI Firewall Configuration virtual pagination + + Rearranged csf.conf for csf UI Firewall Configuration virtual + pagination + + Re-instated sanity check highlights in csf UI Firewall Configuration + + Improved Server Check recursion checking in included configuration + files + + Added new options LF_APACHE_404 and LF_APACHE_404_PERM. This option + will keep track of the number of "File does not exist" errors in + HTACCESS_LOG. If the number of hits is more than LF_APACHE_404 in + LF_INTERVAL seconds then the IP address will be blocked. See csf.conf + for more information + +5.19 - Added stats workaround for February/March calculations + + Added new option CC_IGNORE - this Country Code list will prevent lfd + from blocking IP address hits for the listed CC's + + Reduced CC_* memory usage when loading zones + + Modified lfd logging for regex.pm and regex.custom.pm login failures + to lfd.log to use the return reason from the regex match instead of a + generic message. This does mean that the format for these messages has + changed + + DA Server Check for proftpd - check whether pureftp=1 in DA config + + Replaced IP::Country and Geography::Countries with Geo::IP::PurePerl + using the MaxMind GeoLite Country database for CC_LOOKUPS + + Added new option GUNZIP which is required to expand the MaxMind + GeoLite Country database + + Extended CC_LOOKUPS which can now be configured to report Country Code + and Country and City using the MaxMind City Database. See csf.conf for + more information + + Added Donation buttons to csf UI main page + +5.18 - Remove RT_POPRELAY_* from csf.conf on DA servers as it does not apply + + Improved Server Check for cPanel Update configuration check + + Modifed csf restart to not start bandmin during the stop phase + + Modified LF_DIRWATCH to remove dependency on File::Type + + Modified LF_DIRWATCH for speedups and removed the need for a file size + limit + + Debian v6 support confirmed + + Added /etc/bind/named.conf.options to the list of named.conf files to + check for recursion settings (for Debian) + +5.17 - Updated Server Check for cPanel Update configuration check to cater + for the new format + + Disable LFD service in DA on uninstall of csf using SED instead of + REPLACE + +5.16 - Fixed missing perm.png from DA install + + Fixed Temporary IP Entries table headers in UI + + If DENY_IP_LIMIT is reached, remove excess IPs from iptables as well + as csf.deny (previously only removed from csf.deny) + + csf on cPanel servers automatically re-enables the cPanel Bandwith + chains after iptables is configured. If bandmin is not functioning, or + you don't use the bandmin stats you can disable this new option + LF_CPANEL_BANDMIN (enabled by default on cPanel servers) + +5.15 - Check for multiple Ports settings for sshd in /etc/ssh/sshd_config + when the LF_SELECT option is enabled + + Updated SMTPAUTH regex to detect more login authentication methods + + Updated AUTHRELAY regex to detect more login authentication methods + + Added option to UI to permanently block temporarily blocked IP's + +5.14 - Updated RELAY regex to detect the dovecot/courier login authentication + methods on cPanel servers + + Updated Server Check Report to reflect cPanel/WHM changes in v11.28, + including additional checks and updating reference text + + Added checks to LF_DIRWATCH_FILE to ensure watched resources exist on + startup and while running a check. Those that do not exist are ignored + and logged in lfd.log + +5.13 - Added obsolete OS checks for Fedora v11 and v12, plus RedHat/CentOS v2 + and v3 in Server Check + + Fixed broken reference URL's in Server Check for cPanel servers + + Modified statistics to not display pie chart if no data is available + + Sort LF_DIRWATCHFILE output by time to improve the reported results + + Added new setting for AT_ALERT to only trigger on modification to the + root account (i.e. not all superuser accounts) + + Tested successfully for support on Fedora v14 and Ubuntu v10.10 + +5.12 - Added some lfd blocking statistics which can be viewed via the UI. + Requires gd graphics library and the GD::Graph perl module with all + dependent modules + + Added 8th argument to BLOCK_REPORT for the setting that triggered the + block + + Added setting that triggered a block to lfd log lines + +5.11 - Removed erroneous Port Knocking messages in lfd.log when + PORTKNOCKING_ALERT not enabled + + Added 'exe:/usr/bin/postgres' to the cPanel csf.pignore for new + installations + + Added retry timeout in WHM UI for checking www.configserver.com for + new version information (to avoid repeated hangs when unreachable) + + Fixed LF_PERMBLOCK issue that flushed all temporary IP blocks, not + just the IP being permanently blocked + + Added check to PHP Server Check that php -i output is complete + +5.10 - Always report UID:GID of a DIRWATCH file incase the user account + owning a reported file no longer exists + + Report error gracefully on CIDR->add failures and continue + + Added "query (cache)" check to BIND flooding regex + + Fix issue with killing Advanced Port blocks using the pipe separator + + Update warning messages to include xt_owner with ipt_owner + + Replace URL in Server Check for instructions on disabling IPv6 + + Fixed a bug in LF_CPANEL_ALERT ip address tracking + + Added new option LF_CPANEL_ALERT_USERS to be used with LF_CPANEL_ALERT + to alert for a specified list of WHM/cPanel account logins. See + csf.conf for more information + + Added new feature: Port Knocking. See csf.conf and readme.txt for more + information on the PORTKNOCKING, PORTKNOCKING_LOG and + PORTKNOCKING_ALERT options + + Added new UI option: Quick Ignore, for IP addresses + +5.09 - Added Server Check report check that klogd is running if using syslogd + or that klog module is loaded if running rsyslogd + + Added Server Check report, checks for apache settings: TraceEnable, + ServerSignature, ServerTokens and FileETag on cPanel servers + + Fixed ip6tables IPV6_SPI check warning for older kernels + + Added instruction to open outgoing TCP6 and UDP6 ports when using an + older kernel for ip6tables + + IPv6 Final (no longer Beta) + + Added new option LT_SKIPPERMBLOCK. If LF_PERMBLOCK is enabled but you + do not want this to apply to LT_POP3D/LT_IMAPD, then enable this + option + + Added new option PT_USER_ACTION. If a PT_* event is triggered, then + PT_USER_ACTION will be run in a child process and passed the PID(s) of + the process(es) + +5.08 - New option CLUSTER_MASTER which is the IP of the master node in a + cluster allowed to send CLUSTER_CONFIG changes. This must be set in + order to use CLUSTER_CONFIG options + + Added new Cluster CLI option --cfile (-cf) for sending a file to + cluster members. The file will only be uploaded to the /etc/csf/ + directory + + Added new Cluster CLI option --crestart (-crs) to initiate a restart + of csf and lfd on all cluster members + + Removed CLI option -ccr, --cconfigr [name] [value] in favour of the + new --crs, --crestart option + + Modified regular expressions to cater for RFC3339 date format in log + files. For example, RFC3339 date format used by default in rsyslog on + CentOS v5.5 + +5.07 - Fixed bug introduced in v5.04 that ommitted two outgoing DNS lookup + rules that could affect servers where iptables connection tracking + isn't working correctly + +5.06 - Increased PT_USERMEM default to 200 from 100 for new installations + + Fixed bug introduced in 5.04 when checking the GLOBAL_ALLOW list for + report generation in lfd which caused lfd to fail in Net::CIDR::Lite + +5.05 - Updated the Server Check report IPv6 text + + Fixed ip6tables command execution in iptables firewall during startup + +5.04 - Added BETA IPv6 support. See csf.conf for more information on the new + settings: IPV6 IP6TABLES IPV6_ICMP_STRICT IPV6_SPI TCP6_IN TCP6_OUT + UDP6_IN UDP6_OUT + + New CLI option csf --status6 (csf -l6) added to list ip6tables rules + + Changed temporary DENY and ACCEPT working file formats to use a + different record separator to cater for future IPv6 support + + Advanced Allow/Deny Filters now use | as the separator character to + cope with IPv6 addresses. Legacy support remains for the old : + separator for IPv4 addresses, though these should also now use | as + the field separator + + In Server Check report, don't issue IPv6 warning if only ::1/128 is + bound to a NIC (i.e. loopback) + + Upgraded Net::CIDR::Lite to v0.21 + + Upgraded from IP::Countries to Geography::Countries + +5.03 - Added new option LF_DISTATTACK_UNIQ so that you can specify how many + unique IP addresses are required to trigger LF_DISTATTACK + + Added new options LF_DISTFTP, LF_DISTFTP_UNIQ and LF_DISTFTP_PERM. + This option will keep track of successful FTP logins. If the number of + successful logins to an individual account is at least LF_DISTFTP in + LF_INTERVAL from at least LF_DISTFTP_UNIQ IP addresses, then all of + the IP addresses will be blocked. This option can help mitigate the + common FTP account compromise attacks that use a distributed network + of zombies to deface websites + + Changed DA default configuration of FTPD_LOG to "/var/log/secure" + +5.02 - Added new options X_ARF, X_ARF_FROM and X_ARF_TO which allows sending + X_ARF reports (see http://www.x-arf.org/specification.html). See + csf.conf for more information + + Added new options SMTP_ALLOWUSER and SMTP_ALLOWGROUP so that users and + groups that can bypass SMTP_BLOCK can be easily added. These default + to the original values previously hard-coded + + Modified SMTP_ALLOWLOCAL to use the loopback device (lo) instead of + 127.0.0.1 to cater for multiple loopback devices and allows connection + to locally configured IPs as well + + Modified lfd code to ignore any 127.0.0.0/8 address not just 127.0.0.1 + + Added new option CLUSTER_LOCALADDR to send out cluster requests on an + IP other than the default IP + + Added lfd check to enforce 0600 permissions on /etc/csf/ + +5.01 - Added a new 7th argument to BLOCK_REPORT that includes the log lines + that triggered the block (excludes LF_NETBLOCK and LF_PERMBLOCK) + + Added new CLI option csf --tempallow (csf -ta) which works in exactly + the same way as csf --tempdeny (csf -td) except it provides a method + of temporary IP allows for a given duration. csf -t, csf -tf and + csf -tr now apply to both deny and allow entries + + Allow the use of a duration suffix in csf -ta and csf -td for m, h and + d (minutes, hours and days). Only one suffix allowed and only integers + + Updated UI entry for adding and removing temporary allows and blocks + + Display temporary block TTL in days hours minutes and seconds + + Added new CLI option csf --watch [ip] (csf -w [ip]) and configuration + option WATCH_MODE. This new option logs SYN packets from a specified + source as they traverse the iptables chains. This can be extremely + useful in tracking where that IP is being DROPed or ACCEPTed by + iptables. See readme.txt for more information + + Modified csf and lfd init scripts to be LSB-compliant + + Modified BOGON/DSHIELD/SPAMHAUS block list retrieval to only download + the list if it has not already been retrieved within the configured + interval. This is to help prevent blacklisting by the list provider + for repeated downloads after frequent lfd restarts + + Fixed problem with csf -q and csf -sf not restarting the firewall if + there was a previous startup error + +5.00 - lfd Clustering, final release. This new set of options (CLUSTER*) in + csf.conf allows the configuration of an lfd cluster environment where + a group of servers can share blocks and, via the CLI, configuration + option changes, allows and removes. See the readme.txt file for more + information and details, setup and security implications + + Added new option LF_DISTATTACK. Distributed Account Attack detection. + This option will keep track of login failures from distributed IPs to + a specific application account. If the number of failures matches the + trigger value, ALL of the IP addresses involved in the attack will be + blocked. This option is currently disabled by default - see csf.conf + for more information + + Added new option PT_USERKILL_ALERT if you want to disable email alerts + for PT_USERKILL triggers. This option is enabled by default, i.e. + alerts are sent + + Added new options LF_QUICKSTART in csf.conf and CLI options -q, + --startq, -sf, --startf to allow deferral of csf startup to lfd + instead of waiting for the CLI to perform the work. See the CLI help + and csf.conf for more information + + Added UI option for "Firewall Quick Restart" which uses csf -q, + "Firewall Restart" uses csf -sf + + lfd now restarts csf (if stopped and LF_CSF enabled) within the main + process to enhance the integrity of the firewall + + Multiple login failure regex detection improvements + + Fixed typos in permblock.txt + +4.99 - Improved csf locking to enhance the integrity of the firewall + + Log lfd csf deny failures + + New SSHD regex added + + Improved the dovecot regex's + + New Beta option: lfd Clustering. This new set of options (CLUSTER*) in + csf.conf allows the configuration of an lfd cluster environment where + a group of servers can share blocks and, via the CLI, configuration + option changes, allows and removes. See the readme.txt file for more + information and details, setup and security implications + +4.89 - New SSHD regex added + + Added Server Check to check whether SSHD UseDNS is set to "no" - it + should be disabled + + Added an Important Note to the readme.txt regarding the sshd UseDNS + setting + + Speedup for LF_DIRWATCH regex matching + +4.88 - Fixed URL's in Server Check report for cPanel if Security Tokens are + enabled in v11.25+ + + Added ipv6 explanation that the information is determined from the + output from ifconfig and display ipv6 addresses found + + Added the ability to use Include statements in csf.deny and csf.allow, + see readme.txt for information and restrictions + +4.87 - Ignore csf.rignore for LT_POP3D and LT_IMAPD + + Removed unnecessary csf.locks during some GLOBAL list updates + + Updated Copyright notice + + Modified the block message for LF_MODSEC and LF_SUHOSIN to be more + appropriate (i.e. not "login failures") + + Added new block options for BIND denied requests: LF_BIND, + LF_BIND_PERM, BIND_LOG. This works in the same way as the other + similar blocks, e.g. LF_SUHOSIN. It will block IP addresses that have + had BIND (named) requests denied more than LF_BIND times in + LF_INTERVAL seconds. Currently named client denied log lines for + "update" and "zone transfer" trigger the option + + Modified GLOBAL_ routines to continue if retrieval for one fails + instead of immediately exiting + + Added IPv6 check to Server Check + + Display DNS lookup results for IP addresses if CC_LOOKUPS is enabled + on single line comments (lfd.log, csf.deny, etc) + + Added new options LF_PERMBLOCK_ALERT and LF_NETBLOCK_ALERT so that the + respective email alerts can be disabled + + Updated IP::Country + +4.86 - Added Dovecot regex checking for LT_POP3D and LT_IMAPD + + Modified Server Check for Fedora v10 EOL now that Fedora v12 has been + released + + Improved Dovecot IMAP and POP3D login failure regex + + Ignore RELAYHOSTS setting for LT_POP3D and LT_IMAPD + + Fixed TLSCipherSuite Server Check for proftpd + + Added SSHD regex for "Did not receive identification string from IP" + failures + +4.85 - Further improvements to ICMP rule filters + + - Added backup mod_security log viewer for non-cPanel servers + +4.84 - Mod_security log viewer removed from csf in favour of cmc + + Improved ICMP rule filters. This could help some hosts that experience + connection issues with csf + + Added ICMP regex checking to Port Scan Tracking. Add ICMP to PS_PORTS + to include this, i.e. to Port Scan for all ports use: + PS_PORTS = "0:65535,ICMP" + This is now the default on new installations + +4.83 - Added multiple checks to the Server Check for new cPanel v11.25 + security settings + + Tidied up and rearranged the main UI + + Removed redundant UI options + + Added total perm bans to UI + +4.82 - Removed the need for UI lfd cron restart jobs on Direct Admin + +4.81 - Fixed case sensitivity issue introduced in v4.80 with port specific + lfd deny lines being ignored + +4.80 - Modified WHM login regex to only trap successful root page displays + for LF_CPANEL_ALERT + + Apache status for PT_LOAD now checks http://127.0.0.1/server-status on + GENERIC/DA servers. You need to ensure that the server-status page + has access from 127.0.0.1 in the apache server-status Location + container + + Extended SU log file regex for Debian servers + + Sanitise UI file edit HTML output + + Improvements to the removal of alternative firewalls script + + Added new options GLOBAL_DYNDNS, GLOBAL_DYNDNS_INTERVAL and + GLOBAL_DYNDNS_IGNORE which provide for retrieval of a global DYNDNS + list via URL + + Improved firewall log lines detection for PS_INTERVAL and ST_ENABLE, + especially on Debian + + Improved detection of already blocked IP addresses + +4.79 - Withdrawn + +4.78 - Modified DA installation to overcome permissions problems on some + systems preventing the UI from working + +4.77 - Expanded dovecot regex matching + + Fixed the generic installation to install regex.custom.pm + +4.76 - Added check for FrontPage extensions to Server Check as they should be + considered a security risk as they were EOL in 2006 + + Added support for the impending cPanel v11.25 Security Tokens feature + +4.75 - Added a [block] section to the Login Failure alert.txt template. This + new report template will be copied to /etc/csf/alert.txt.new on + existing installations, rename it to alert.txt to use it + + Modified existing lfd alerts to use currently used tags instead of + appending block information to the IP address (alert.txt modified as + above) + + Added new options trigger for RT_LOCALHOSTRELAY_* to csf.conf for + email sent via a local IP addresses, separating the trigger from + RT_LOCALRELAY_* which is now only for /usr/sbin/sendmail. See csf.conf + for more information + + Added Relay Tracking to Direct Admin running exim. See RT_* and + SMTPRELAY_LOG in csf.conf for more information + + Added csf.mignore to allow ignoring of specified usernames or local IP + addresses from RT_LOCALRELAY_ALERT + + Modified csf UI to use a single dropdown for all lfd ignore files + + Added proftpd regex matching for "UseReverseDNS on" in proftpd config + +4.74 - Removed FUSER from csf.conf as it is no longer used + + Added UNZIP to csf.conf which is required for Country Code to CIDR + functions + + Modified the Country Code allow/deny/allow_filter feature to generate + CC CIDRs from the Maxmind GeoLite Country database instead of using + iplocationtools.com. Note: GeoLite is much more accurate that the + previous zones used. This also means that there are usually more CIDRs + for each CC which adds to the burden of using this feature + +4.73 - Added checks before Net::CIDR:Lite calls to ensure inputs are CIDR's + to prevent module failures + + New feature - LF_CPANEL_ALERT. Send an email alert if anyone accesses + WHM via root. An IP address will be reported again 1 hour after the + last tracked access (or if lfd is restarted) + +4.72 - Modified mail sending code to use a common procedure that copes better + with differing combinations and variations of From:, To:, LF_ALERT_TO + and LF_ALERT_FROM settings for lfd alerts + +4.71 - Code speedups in csf --grep + + Added csf.allow and GLOBAL_ALLOW lookups during lfd blocking and note + added to alert if ip match found + + Modified Server Check for Fedora v9 EOL now that Fedora v11 has been + released + + Modified iptables output from csf.pl to exclude the Fedora v11 + intrapositioned negation messages + + Fixed typo in integrity.txt alert template for new installations + + Modified the email header for csf --mail + + Fix Relay Tracking from 127.0.0.1 to always report as a LOCALRELAY + + Modified lfd output filehandle names to avoid read/write conflicts + + Added Advanced Allow/Deny Filters for csf.dyndns. See readme.txt for + an example + + Added new option CC_ALLOW_FILTER as an alternative to CC_ALLOW where + only listed Country Codes are allowed, however normal port and packet + filter rules are still applied to those connections. All other + connections are dropped + +4.70 - Modified UI access to csf.sips to display checkboxes instead of direct + editing, for ease of use + + Fixed problem where RELAYHOSTS setting wasn't always being honoured + + Modified mod_security configuration editor to handle HTML elements + + Rewritten RT_*_ALERT regex and counting code to better deal with a + variety of exim log output formats + + Added recipient count to RT_*_ALERT to include emails sent to multiple + recipients. This option requires that the exim log_selector setting in + the exim configuration includes the option: +received_recipients + So, the recommended log_selector setting is now: + log_selector = +subject +arguments +received_recipients + + Modified Server Check cPanel version check to cater for x86_64 OS's + + Added check to prevent Server Check mail report cron duplicates + + Added abbreviated UI for mobile phone access to Quick Allow, Quick + Deny and Remove Deny. Direct URLs: + cPanel: https://1.2.3.4:2087/cgi/addon_csf.cgi?mobi=1 + DA: https://1.2.3.4:2222/CMD_PLUGINS_ADMIN/csf/index.html?mobi=1 + Webmin: https://1.2.3.4:10000/csf/?mobi=1 + +4.69 - Added Gentoo (generic) support + + Added Server Check for MySQL LOAD DATA LOCAL + + Modified Server Check for enable_dl to also check whether dl is in + disable_functions + +4.68 - Added ipv6 IP detection for proftpd login failures + + Removed ossec and webmin from the Server Check services section + +4.67 - Modified the Country Code allow/deny feature to use + iplocationtools.com now that ipdeny.com has gone offline + +4.66 - Modified OS version check to prevent Fedora v10 obsolete + false-positive in Server Check + + Modified the exim SMTP AUTH regex to use the latest cPanel/exim format + + Added failure notification for DYNDNS entry lookups in lfd if they + fail to resolve or timeout + +4.65 - Modified Firewall Security Level UI to set PS_LIMIT within range + + Fixed problem processing template for SU_ALERT + + Empty csf.dshield on upgrade to work around problem where DSHIELD + blocked themselves in their own BLOCK list + +4.64 - Removed SMTP_BLOCK warning on VPS servers where ipt_owner doesn't work + if SMTP_BLOCK isn't actually enabled + + Added new CLI option (csf -uf) which forces an update of csf+lfd + + Added new CLI option (csf -df) which removes and unblocks all entries + in /etc/csf.deny (excluding those marked "do not delete") + + Added new UI option to that removes and unblocks all entries in + csf.deny (excluding those marked "do not delete") and all temporary IP + bans + + Added csf file names to the csf UI options + +4.63 - New feature - Added new CLI option: csf --mail (or csf -m) which can + take an email address as an argument. It will display the Server Check + in HTML or send the output to the email address if present + + Added option to UI Server Check to schedule csf to generate the report + and email the results to the address specied at the interval specified + + Removed MySQL check from cPanel DNSOnly Server Check + + Updated the perl v5.8.8 Server Check comment + + Fixed sanity check for RT_*_BLOCK + + Fixed copy of install.txt for generic installs and upgrades + + Modified UI for Deny Servers IPs > Change to indicate that csf needs + restarting, not lfd + + Added built-in replacement function for the Messenger Service message + files for [HOSTNAME] which will be replaced by the servers FQDN + hostname. Updated the sample Messenger index templates + + Updated the uninstall scripts to remove the cronjob and logrotate + files + + Added colour highlights to the Quick Allow and Quick Deny UI boxes + +4.62 - Fixed problem with SU_ALERT alert report in v4.61 + + Modified the Server Check for cPanel update settings to check for + daily updates more accurately + + Added Server Check for cPanel tree + + Upgraded IP::Country + + New feature - Added sanity check to configuration values in csf, UI + Server Check and UI Firewall Configuration. In the UI Firewall + Configuration: lines highlighted in red fall outside the recommended + range; lines highlighted in pale green differ from the default on + installation + + Added cPanel Security Check to check that at least one configured + nameserver is on a different server + + Added proftpd checks to csf (for VPS servers) and in Server Check + + Added DirectAdmin Checks to UI Server Check for: SSL login to DA; + proftpd cipher; nameserver on a different server; PHP version and + configuration checks; Apache version; dovecot cipher + + Removed resolv.conf localhost check + +4.61 - Modified lfd iptables command error handling to log errors and + continue instead of terminating when in TESTING mode + + Removed loading of iptables modules from csftest.pl to avoid modprobe + problems with some OS kernels + + Added Connection Tracking check for pre-existing block to cater for + linux connection status timeouts + + Moved LF_CSF check to the start of the lfd processing interval + + New option LF_ALERT_FROM. If set, the value of this option will + override the From: field in all of the lfd alert templates. This + change also uses the From: field in the template (or this option if + set) as the value for the SENDMAIL -f option + + Modified POP/IMAP Server Checks for the chosen mail server only on + cPanel servers + + Modified FTP Server Checks for the chosen ftp server only on cPanel + servers + + Added SMTP Tweak to Server Check on cPanel servers and removed block + on csf starting if enabled + +4.60 - Modified cipher checks to strip out quotes + + Modified Apache cipher message to remoind that you have to rebuild the + Apache configuration and restart for changes to be effective + +4.59 - Added proftpd regex for Plesk server log file format + + Modifed the Server Check cipher checks for pure-ftpd and Apache to use + openssl to ensure SSLv2 is disabled + + Added cPanel Server Check checks for dovecot, courier-imap IMAP and + POP3D SSL cipher list + + New option SAFECHAINUPDATE added. If enabled, all dynamic update + chains (GALLOW, GDENY, SPAMHAUS, DSHIELD, BOGON, CC_ALLOW, CC_DENY, + ALLOWDYN) will create a new chain when updating, and insert it into + the relevant LOCALINPUT/LOCALOUTPUT chain, then flush and delete the + old dynamic chain and rename the new chain. See csf.conf for more + information. This option is disabled by default, but we do recommend + that it is enabled on non-VPS servers with restrictive numiptent + values + + Added SAFECHAINUPDATE to the firewall Server Check (except for + Virtuozzo VPS servers) + + Modified Server Check on cPanel to make the PHP v4 warning clear and + to warn where PHP v5 and v4 have both been compiled (PHP v4 is + obsolete and should not be used at all anymore) + + Added WHM checks for skipparentcheck and cpsrvd-domainlookup to + Security Check + + New option LF_ALERT_TO. If set, the value of this option will override + the To: field in all of the lfd alert templates + +4.58 - Modified exim cipher check in Server Check to use openssl to test the + expanded configured cipher suites to ensure SSLv2 is disabled + +4.57 - Improved exim configuration option detection in Server Check + + Added Exim Configuration checks to DirectAdmin Server Check + + Modified csftest.pl to perform a modprobe on all used iptables modules + before testing + + Added PASV port hole warning on VPS servers to the output of csf on + start and to the cPanel (if using pure-ftpd) Server Check + + Added lfd to the DirectAdmin Service Monitor + + Added back a revised Firewall Security Level option to UI + +4.56 - Added TCP_OUT port 2222 for the DA default configuration for new + installations + + Added ICMP protocol to Advanced Allow/Deny Filters. See readme.txt for + more information and examples + + Updated readme.txt to reflect the Control Panel UI availability for + cPanel, DirectAdmin and Webmin + + Modified mod_security configuration file check to the TLD only of + /usr/local/apache/conf/ and only files ending in .conf + +4.55 - Fixed issue with csf.conf not being loaded for the Server Check Report + + Removed erroneous chkconfig check from Server Check Report + + Disabled various checks in Server Check Report for non-cPanel servers + + Modified Debian/Ubuntu init entry creation and removal procedure + + Modified Server Check to search for multiple named.conf locations + +4.54 - Bug fix to Exploit Check code + + Fixed problem with iptables logs not being collated if PS_INTERVAL is + disabled but ST_ENABLE is enabled + + Fixed potential problem with SMTPRELAY_LOG not being scanned when + RT_RELAY_ALERT, RT_AUTHRELAY_ALERT or RT_POPRELAY_ALERT enabled + +4.53 - Upgraded the csf Webmin UI module to the new csf UI and added + installation/upgrade instructions to the install.txt for Webmin + + Fixed image locations and javascript in DA and webmin UI + + Updated the uninstall scripts and the uninstall section of install.txt + +4.52 - Reverted lfd signalling on cPanel servers to allow UI restarts of lfd + + Added warning in DA UI to upgrade csf from the root shell due to + restrictions in DirectAdmin + + NOTE: DA users should upgrade csf to this version from the root shell + using "csf -u" and not use the Upgrade button in the UI + +4.51 - Fixed csf --upgrade (csf -u) for DA installations + +4.50 - Added restrictions information regarding the PORTFLOOD setting and + ipt_recent to readme.txt (i.e. hit count max is 20) + + Modular development of csf UI + + Added DirectAdmin UI and installation support for csf/lfd + + Added Statistics options (ST_ENABLE, etc) to generic csf installation + + Added SMTP options (SMTP_BLOCK, etc) to generic csf installation + + Removed pre-configured firewall settings through UI for redevelopment + as it has become out-dated + + Modify csf UI to signal lfd to start/restart/enable only. A one + minute cron job will actually perform the signalled function. The CLI + is unaffected and performs the command immediately. This is introduced + to overcome fork issues from within an Apache session + +4.41 - Added information about runing external iptables commands using + csfpre.sh and/or csfpost.sh to readme.txt + + Added new CLI option csf --addrm (csf -ar) to remove an IP address + from csf.allow and delete the associated iptables rules + + Removed the need for the MONOLITHIC_KERNEL option and made modprobe + perform silently on csf startup. Added the relevant information + regarding some Monolithic kernels and the need for a PASV port range + hole to readme.txt + + Added timeout to csf modprobe to avoid startup hanging on buggy + kernels + +4.40 - Added workaround for php --info bug in Server Report when checking PHP + configuration settings + + Modified LF_INTEGRITY to regenerate the md5sum comparison file + immediately after a match is found instead of waitng for the next + cycle + + Fixed LF_INTEGRITY aborting if the temporary md5sum file is empty + +4.39 - Updated csf.conf to clarify that LF_PERMBLOCK_COUNT and + LF_NETBLOCK_COUNT with act if more than the number of hits are + detected, not on the exact number set + + Modified csf WHM UI to use csf -u to upgrade csf when a new version is + available + + Added new script /etc/csf/csftest.pl which will test the servers + iptables modules for functionality. The tests are for the required + iptables modules and the optional modules for the SMTP_BLOCK, + PORTFLOOD and MESSENGER features. This adds a useful diagnostic tool + for kernel/iptables problems and to check whether the features above + will function + + Added csf WHM UI option to run csftest.pl + + Updated the csf install.txt to run csftest.pl before running up csf + +4.38 - Improved detection of working ipt_owner iptables module on VPS servers + such that if ipt_owner does not work SMTP_BLOCK and UID/GID blocks + will be automatically disabled and csf will continue to start + +4.37 - Default setting for ICMP_OUT_RATE set to 0 - this is the recommended + setting for cPanel servers which use ping times to determine fastest + mirrors for various update functions + + Modified PT_LOAD_ACTION code to stop duplicate load emails from being + send by lfd + + Moved ETH_DEVICE_SKIP to the top of the INPUT/OUTPUT chains + + Allow enabling of SMTP_BLOCK and use of UID/GID advanced port filter + rules on VPS Servers for as ipt_owner is now apparently supported on + the latest kernels. However, if the latest kernel isn't being used or + the VPS host hasn't included the ipt_owner iptables module for the + client VPS, then csf will fail with an error + +4.36 - Modified Process Tracking to allow regex exceptions in csf.pignore for + deleted executable processes + +4.35 - Modified regex.pm detection of iptables kernel log lines to cater for + alternative formatting + + Restored the substitution of the NULL separator with spaces for the + /proc/PID/cmdline in Process Tracking + +4.34 - Added code to Process Tracking to translate non-printable characters to + especially help detect and report deleted executable file processes + + WARNING: Removed hard-coded exceptions for spamd, cpanellogd, cpdavd + and awstats.pl from lfd.pl. If you want to ignore such processes for + Process Tracking, you will need to add appropriate ignore rules to + csf.pignore for them + +4.33 - Disable ST_LOOKUP by default on new installations + + Modified lfd stats performance when ST_LOOKUP is enabled and added a + warning for this setting to csf.conf for when DROP_IP_LOGGING is + enabled + +4.32 - Modified the su tracking regex to better trap RHE/CentOS v5 su login + attempts + + Added a Server Check for "FTP Logins with Root Password" + + Added new WHM UI option to display Last X iptables Log Lines. Note + that the report will only display log lines since this update. The + new statistics will be expanded in future developments. Added new ST_* + options to the cPanel csf.conf to control the recording of stats + + Removed fwlogwatch from distro and will use self-produced reports + +4.31 - Added warning for those that enable PT_USERKILL in csf.conf - i.e. It + is not a good idea to use that option + + Modified PT_USERKILL to not kill (deleted) processes (these should be + restarted manually after investigation) as per the documentation + +4.30 - If you add the text "do not delete" to the comments of an entry in + csf.deny then DENY_IP_LIMIT will ignore those entries and not remove + them. Updated csf.deny information text for new installations + + Made the (deleted) process text even more explicit for those that are + not reading csf.conf or the FAQ for their explanation + + Updated DSHIELD information URL in csf.conf + + Added new feature - csf.rignore is an ignore file that lists domains + and partial domains that lfd should ignore. Read /etc/csf/csf.rignore + for more information + + Option GOOGLEBOT removed. This feature is now performed using + csf.rignore. If GOOGLEBOT was previously enabled it will be added to + csf.rignore + +4.29 - Added Slackware support (tested on v12.2.0) + + Added Fedora v10 support + + Added new option GOOGLEBOT - Prevent *.googlebot.com from being + blocked by lfd. See csf.conf for more information + + Added csf version from/to to output from csf --update when upgrading + +4.28 - Fixed GENERIC csf problem with csf.pl perl modules + +4.27 - New Feature - Port Flood Protection. This option configures iptables + to offer protection from DOS attacks against specific ports. This + option limits the number of connections per time interval that new + connections can be made to specific ports. See csf.conf and readme.txt + for more information. This option is only available on servers with + the ipt_recent kernel module + + cPanel DNSONLY compatibility added - Thanks to JJ for the assistance + + Improved Cipher suite checking and advice for Apache and FTP in Server + Check + + Remove md5sum check from JS exploit check as it is covered by + LF_INTEGRITY and causes confusion + + Added new option LOGFLOOD_ALERT which will send an email alert based + on logfloodalert.txt if lfd skips logs lines due to log file + processing problems + + Added new option PT_DELETED together with the FAQ explaination as to + why lfd reports deleted processes. The option can be disabled to + ignore such processes + + Rearranged LOCALINPUT and LOCALOUTPUT rule positions to allow + exceptions to SMTP_BLOCK + +4.26 - New Feature - Country Code to CIDR allow/deny. This feature can allow + or deny whole country CIDR ranges. The CIDR blocks are downloaded from + http://www.ipdeny.com/ipblocks/. For more information, see CC_ALLOW, + CC_DENY and CC_INTERVAL in csf.conf + + Expanded the dovecot regex to include more login failure permutations + + Added exe:/var/cpanel/3rdparty/bin/php to csf.pignore on cPanel + servers + + SMTP_ALLOWLOCAL set to 1 on new cPanel installations by default + +4.25 - Fixed bug in csf --grep when CIDRs used in advanced port filters + + Fixed problems with aborted Server Check Report + + Fixed position of the lo device rule in the OUTPUT chain which broke + SMTP_BLOCK + + Added new option SMTP_PORTS which is used by SMTP_BLOCK to block all + listed ports (not just port 25). This is populated on installation or + when TESTING = 1 if an additional port is listed in "WHM > Service + Manager > exim on another port". Otherwise, SMTP_PORTS needs to be + updated manually. The default setting contains port 25 + + SMTP_BLOCKs will now log if DROP_IP_LOGGING is enabled + +4.24 - Added workaround for issue with WHM image display in the addon header + for cPanel v11.24 + + *Added cPanel v11.24 FTP Anonymous Upload checks in Server Report + + *Added cPanel v11.24 FTP Cipher Suite checks in Server Report + + *Added cPanel v11.24 Apache Cipher Suite checks in Server Report + + *Added cPanel v11.24 Exim Cipher Suite checks in Server Report + + Added Fedora v8 to the obsolete OS list now that v10 is out + + Updated dovecot regex in regex.pm for v1.1.6 used by cPanel + + * Will only display if cPanel version is >= 11.24 + +4.23 - Added skip to connection and process tracking for empty tcp6 + connection data + + Fixed PT_LOAD email output of ps and vmstat + +4.22 - Additional fixes for an issue on VPS servers where temporary block + removal from csf.tempban failed + +4.21 - Fixed an issue on VPS servers where temporary block removal from + csf.tempban failed + +4.20 - Modified csf.tempban processing code in lfd to perform more stringent + file locking to preserve temporary bans if lfd is writing during + shutdown + + Modified Port Scan tracking of IP's to not attempt multiple blocks on + the same IP address in the same log line processing batch + + Fixed broken timestamp in lfd.log for dates < 10th of the month + + Various code modifications to improve performance and stability + +4.19 - Reverted the tied file changes as they were causing a deadlock + situation locking csf.tempban + + Improved the process tracking detection of deleted executables of + running processes + +4.18 - Modified temporary IP address storage to use a tied file to preserve + temporary bans if lfd is writing during shutdown + +4.17 - Replaced the use of backticks in csf, lfd and the WHM UI with calls to + IPC::Open3 + + Various lfd and csf code improvements and tidy up + + Ensure lfd parent dies cleanly on error + + Debug information improved and timer modified to use Time::HiRes for + more accuracy + +4.16 - Removed port 953 from the TCP and UDP allow lists for new csf + installations as it's not necessary to whitelist as bind listens on + the localhost device for such control connections by default + + Added exe:/usr/sbin/nsd, exe:/usr/libexec/dovecot/pop3-login, + exe:/usr/libexec/dovecot/imap-login to new and old cPanel + installations csf.pignore to cater for cPanel support for both nsd and + dovecot (currently in EDGE) + + Only use Cpanel::Rlimit if it's available in WHM UI + +4.15 - Fixed a problem in v4.* where use of GALLOW and ALLOWDYN was allowing + connections from blocked IP addresses in csf.deny or temporary blocks. + The GALLOW, GDENY and ALLOWDYN chains have been split into GALLOWIN, + GALLOWOUT, GDENYIN, GDENYOUT, ALLOWDYNIN and ALLOWDYNOUT to correct + this. Many thanks to Brian for his help in tracking this issue down. + +4.14 - Implemented the use of cPanel routine Cpanel::Rlimit to remove process + resource limit restrictions as the cPanel memory limitation setting + was causing the Server Check to abort with memory allocations problems + through WHM on some servers + + Modified port checking for 23 and 53 in Server Check to no longer use + the fuser binary and use the port mappings directly from /proc + + Modified lfd and Server Check to check for IPv6 bound processes as the + IPv4 and IPv6 connections are stored in a different file to IPv4 only + bound processes + +4.13 - Updated various comments in csf.conf + + Fixed call to csfpost.sh from csf + +4.12 - Modified lfd Login Failure tracking to use a per IP address rolling + LF_INTERVAL window rather than a static one for all tracked IPs. This + makes login failure counting more accurate and blocking more + responsive + + Added new feature - Block Reporting. lfd can run an external script + when it performs and IP address block following for example a login + failure. BLOCK_REPORT is to the full path of the external script. See + readme.txt for format details + + If csf is installed or upgraded via an SSH session the connecting IP + address will now be automatically added to csf.allow (note: it is not + added to csf.ignore so lfd may still block it). This IP can be removed + after testing if desired + + Modified the lfd.log format to the standard: + :: lfd[]: + If you parse lfd.log you will need to update your scripts! + + Added DEBUG option - for internal use only + +4.11 - Fixed addition of exe:/usr/libexec/hald-addon-keyboard to csf.pignore + for existing installations + + Modified the calculation for the position of LOCALOUTPUT in the OUTPUT + chain + + Added /etc/cron.d/lfdcron.sh to restart lfd daily + + Added exe:/usr/libexec/dovecot/imap and exe:/usr/libexec/dovecot/pop3 + and exe:/usr/sbin/mysqld_safe to csf.pignore + + Modified SCRIPT_ALERT regex to cope with exim log format changes in + FC8+ + + As per RFC5322, adding port 587 to the default TCP_IN list of ports + for new installations (i.e. it is now recommended for SMTP servers to + offer port 587 access for MUA to MTA traffic rather than port 25 which + is for MTA to MTA traffic) + + Added informational text to Process Tracking email report if a process + is running an executable that has been deleted + + Added csf version to the daemon startup log line in lfd.log + +4.10 - Added /usr/libexec/hald-addon-keyboard to csf.pignore + + Modified the static DNS port rules to always allow all OUTGOING (only) + connections to/from port 53 udp/tcp. This should help the situation + where some servers iptables block outgoing port 53 udp connections + despite the port being open + + Added new option DNS_STRICT which will remove all static DNS rules and + allow access only through SPI. For stability reasons, it would be + advisable to leave this option disabled (default) + +4.09 - Modification to cPanel version to restart chkservd using + /scripts/restartsr_chkservd instead of the init script as the latter + is removed in the latest EDGE release that puts chkservd under the + control of tailwatchd (/scripts/restartsrv_chkservd is a stub for + restarting tailwatchd in the latest EDGE instead of a direct restart + script in older cPanel versions). chkservd is restarted when csf + is installed/uninstalled/upgraded/disabled/enabled + +4.08 - Added a new timing system to more accurately trigger lfd tasks. This + should alleviate timing issues such as those seen with LT_POP3D and + LT_IMAPD and improve the overall effectiveness and performance of lfd + + Added new method for reaping child processes. If you find that zombie + lfd processes start to build up you can revert to the old reaper by + enabling new option OLD_REAPER + +4.07 - Messenger service now supports advanced filter permanent port block + redirection + +4.06 - Moved the GALLOW, GDENY, SPAMHAUS, DSHIELD and DYNDNS rules to the + LOCALxxPUT chains so that the entries can be correctly listed with + ACCEPT's at the top and DENY's at the bottom of the chain + + Repositioned the cPanel Bandmin acctboth rule entry in the INPUT and + OUTPUT chains so that bandwidth accounting is kept accurate + + Fixed a problem processing advanced port filters in GLOBAL_ALLOW and + GLOBAL_DENY + +4.05 - Moved resolver ACCEPT rules to the top of the INPUT and OUTPUT chains + +4.04 - Fixed problem with rule placement for ETH_DEVICE_SKIP + + Ensure all ALLOW requests are inserted before DENY requests after csf + has been restarted + + Ensure that fwlogwatch stats creation uses IPTABLES_LOG file + + Only perform operations on the nat table if MESSENGER service is + enabled + + lfd Process Tracking will now ignore MESSENGER_USER messenger services + + Added new option PT_ALL_USERS so that all Linux accounts on a cPanel + server are checked in Process Tracking, not just cPanel users. This + option is disabled by default on cPanel servers. Enabling this option + may require adding exceptions to csf.pignore + + Additional exceptions added to csf.pignore for cPanel servers for the + new PT_ALL_USERS option + + PT_SKIP_HTTP now disabled by default for new installations + + Added PT_ALL_USERS and PT_SKIP_HTTP checks to the WHM Server Check + +4.03 - Fixed problem where the new LOCALxxPUT chains were only processing tcp + requests + + Fixed problem with insertion of SMTP_BLOCK rules exceeding the rule + count in the OUTPUT chain under certain circumstances + +4.02 - If csf fails with an error lfd will now die and require a restart + after the issue with csf is resolved. csf commands apart from start + and restart are also disabled + + Released from BETA + +4.01 - Allow the Messenger Service to be used on VPS servers. However, if the + ipt_REDIRECT module is missing csf will fail to start correctly and + abort + + HTML Messenger service server now only reads a limited line length + instead of unlimited input to prevent overflows + +4.00 - New feature - Messenger Service. This feature allows the display of a + message to a blocked connecting IP address to inform the user that + they are blocked in the firewall. This can help when users get + themselves blocked, e.g. due to multiple login failures. The service + is provided by two daemons running on ports providing either an HTML + or TEXT message. See csf.conf and readme.txt for more information + (not available on VPS platforms and others missing the ipt_REDIRECT + kernel module) + + Moved INPUT and OUTPUT chain rules for blocks and allows to their own + respective chains LOCALINPUT and LOCALOUTPUT. This means that no IP + blocks will be listed in the INPUT or OUTPUT chains, but in the new + ones + + Re-organised all of the INPUT and OUTPUT chain rules to give + precedence to the LOCALINPUT rules before invoking other chains and + port ALLOW rules + + Moved the SYNFLOOD protection chain rule to be the first chain rule + after the LOCALINPUT chain rule + + Moved the lo device rules to the always be at the top of the INPUT and + OUTPUT chains + + Modified the syslog regex matches to only match on local entries to + cope with centralised syslog configurations + +3.43 - Improved application IP block checking + + Restored the option LF_SCRIPT_PERM with additional checks for + directories within the cPanel homedirs and for symlinks. Warning + added to csf.conf for this option + + Added random query-source port setting for BIND to the Server Report + +3.42 - Corrected information for LF_TRIGGER_PERM in the generic csf.conf to + be the same as the cPanel csf.conf + + If LF_SELECT is enabled make sure all cPanel ports are blocked on + cpanel login failure. This was only doing ports 2082,2083 and will now + block 2082,2083,2086,2087,2095,2096 + +3.41 - Added new mechanism to allow custom regular expression matching with + individual settings for lfd login failure detection. See + /etc/csf/regex.custom.pm for details + + Modified all timestamps in lfd reports to also include the standard + timezone offset (i.e. from GMT) + + Added new setting CC_LOOKUPS to control the new Country Code lookups + (enabled by default) + + DROP_IP_LOGGING automatically disabled if PS_INTERVAL is enabled + + PS_INTERVAL enabled by default on new installations + + Doubled the number of lines before log file flooding detection will be + triggered + +3.40 - Added queuealert.txt to the WHM UI dropdown list for editing + + Clarified in csf.conf that setting LF_QUEUE_ALERT to 0 disables the + check + + Added Country Code lookups for IP addresses. Any reported IP addresses + will include the international CC where available. It should be noted + that with international ISPs this may not be wholly accurate. Where + possible the CC will be translated into the associated country name + +3.39 - Added new option IGNORE_ALLOW which, if enabled, lfd will ignore IP + addresses listed in the csf.allow file and not block them + + Added new option LF_QUEUE_ALERT, which will send an email alert using + queuealert.txt if the exim queue length exceeds the value it is set + to. The check is repeated every LF_QUEUE_INTERVAL seconds. If the + ConfigServer MailScanner configuration is being used, both the + MailScanner pending and exim delivery queues will be checked. This is + a cPanel only option + + Added new option CT_PORTS to Connection Tracking so that you can + specify which ports you want to count towards CT_LIMIT, e.g. 80,443 + + Modified Server Report check for register_globals in cPanel's php.ini + incase the new cPanel WHM setting is being bypassed + +3.38 - Additional SSHD regex added to regex.pm + + Improved the WHM UI reporting of the csf status: disabled, running, + testing mode + + Added Enable/Start buttons to WHM UI next to the csf status if + disabled/stopped + + Updated Server Report checks for csf status + + Changed the destination of the ConfigServer Services link at the + bottom of the WHM UI to go to the csf web page + +3.37 - Fixed an issue currently in cPanel EDGE that affects the use of the + cPanel SafeFile module in WHM scripts + +3.36 - Increased the IP lookup timeout for reported IP's from 5 to 10 seconds + + Improved lfd internal timing system for event triggers + + Added new feature - Account Tracking. The new AT_* options configure + an alert system for account modifications which will send an email if + there are new accounts added, existing accounts deleted plus password + uid gid login dir and login shell changes. Each of these changes can + be enabled or disabled. You can also enable tracking for superuser + accounts only. That latter is the default setting. This feature uses + the email template accounttracking.txt + + Added reason text to temporary IP bans + + Added Server Report check for ini_set in PHP disable_functions + + Added ossec to list of processes to disable as it will conflict and + duplicate csf functionality + + Changed Server Check scoring text to instead show a coloured table + indicating score + +3.35 - Changes to WHM UI script for cPanel v11 + + Removed cPanel v10 backported WHM UI settings, i.e. v10 no longer + supported + + Added # of temp blocks to WHM UI "Temporary IP Bans" on main page + + Modified Server Report check for register_globals in cPanel's php.ini + to use the new cPanel WHM setting + + Added Server Report check for passwords in WHM email setting + + Added Server Report check for WHM root/reseller login to users cPanel + + Modified Server Report nobody cron check to only fail on non-zero cron + file + + Modified Server Report check for Fedora now that Fedora 7 is EOL + (2008-06-13) + + Added new option DYNDNS_IGNORE to ignore DYNDNS entries when lfd + blocking + +3.34 - Modified regex matching to allow for trailing spaces in log lines + + Modified PT_LOAD routine to prevent multiple triggers resulting in + more than one alert being email sent + + Removed the need for NETSTAT from lfd to reduce overheads and improve + performance allowing CT_INTERVAL to be set lower. Now uses + /proc/net/[protocol] + +3.33 - Modified skip for su login checking from root to cater for (uid=0) + + Added option SYNFLOOD_BURST to allow configuration of --limit-burst + when SYNFLOOD is enabled. Changed default values + + Added to --grep searches to csf.deny and temporary blocks in addition + to iptables + + Modified SSH regex to improve login failures detection further + + Enabled LF_PERMBLOCK, PT_USERPROC by default on new installations + + Added vsftpd regex for ftp login failures + +3.32 - Modified SSH regex to check for ipv6 addresses + + Added another regex to improve SSH matching + +3.31 - Modified -denyrm to abort if left blank instead of clearing all blocks + + Added lfd check for existing temporary block to avoid duplicates + + Fixed regex handling for courier-imap POP and IMAP login failures + + Added --full-time to the ls command for LF_DIRWATCH_FILE. If you use + this option, LF_DIRWATCH_FILE will likely trigger due to the changed + output the first time you restart lfd after upgrading + + Fixed typo in Suhosin description in the Server Check Report + + Added Referrer Security to the Server Check Report + + Added register_globals check in cPanel php.ini to Server Check Report + +3.30 - Security Fix: lfd vulnerabilities found which could lead to Local and + Remote DOS attacks against the server running csf+lfd + + The DOS attacks could make lfd block innocent IP addresses and one + attack could cause lfd to deplete server resources + + Modified the regular expressions in regex.pm to prevent them from + being triggered by spoofed log line entries + + Option LF_SCRIPT_PERM removed + + Our thanks to Jeff Petersen for the detailed information describing + these issues + + We recommend that all users of csf upgrade to this new version + +3.28 - Fixed a bug with LT_POP3D and LT_IMAPD introduced in v2.88 which broke + login tracking + + Modified relay tracking to not ignore RELAYHOST IP's + + Modified LF_SSH_EMAIL_ALERT to not ignore RELAYHOST IP's + + LF_SUHOSIN will now skip matches for "script tried to increase + memory_limit" + +3.27 - Modified csf -dr option to delete advanced filter IP matches as well + as simple matches in csf.deny + +3.26 - Added new CLI option to csf, -g --grep will search the iptables chains + for a specified match which is either explicit or part of a CIDR + + Added WHM UI option for csf --grep + + Added new CLI option to csf, -dr --denyrm will remove an IP address + from csf.deny and unblock it + + Added WHM UI option for csf --denyrm + +3.25 - Added csf.suignore file where you can list usernames that are ignored + during the LF_EXPLOIT SUPERUSER test + + New option PT_LOAD_ACTION added that can contain a script to be run if + PT_LOAD triggers an event. See csf.conf for more information + + Added SUPERUSER check to Server Check Report + + Added Suhosin check to Server Check Report + +3.24 - Allow comments after IP addresses in csf.dyndns + + Added new login failure option LF_SUHOSIN which detects alert messages + and blocks the attacker IP after the configured number of matches + + Added a new exploit check for non-root superuser accounts + + Added a new configuration option LF_EXPLOIT_CHECK which allows you to + configure which tests are performed by LF_EXPLOIT + +3.23 - Modified the Server Report code for checking PHP variables to be more + lenient when checking the output from /usr/local/bin/php -i + + Modified lfd calculation of Jiffies to use the POSIX::sysconf function + to obtain the clock ticks instead of assuming 100 ticks for Linux + + Fix duplicate LF_INTEGRITY emails + +3.22 - Changed DROP_IP_LOGGING logging advice in csf.conf to NOT use this + setting if you use Port Scan Tracking as it will cause redundant + blocks + + Added tag [hostname] to all of the alert reports. You will need to add + this manually to the report text Subject: line (or anywhere else in + the report that you would like it) for existing installations + + Added "A note about FTP over TLS/SSL" to readme.txt + +3.21 - Fixed problem in Server Check that caused an error in some situations + + Modified netblock caching code to prevent repeated block attempts + +3.20 - Corrected net block logic so that after a net or perm block occurs, + subsequent log entries that would incur the same block are ignored + +3.19 - New feature - LF_PERMBLOCK. Permanently blocks IP addresses that have + had X temporary blocks in the last Y seconds. Uses email template + permblock.txt + + New feature - LF_NETBLOCK. Permanently blocks network classes (A, B or + C) if more than X IP addresses in a specified class have been blocked + in the last Y seconds. This may help within some DDOS attacks launched + from within a specific network class. Uses email template netblock.txt + + Modified MD5SUM comparision code to better reset md5sum checks after a + hit + + Only issue Random JS Tookit warning if all the MD5SUM checks fail for + the relevant files + + Removed POP flood Protection setting check from Server Report as it's + no longer relevant to courier-imap + + Rewritten the Apache Check code for the Server Report to better + detect the current running settings on all Apache and PHP versions + + Don't check Apache RLimitCPU/RLimitCPU limits on VPS servers as they + aren't relevant (as they apply to the host VPS configuration) for the + Server Report + +3.18 - Fixed bug in the generic csf release where the default csf.conf was + missing the DROP, CT_STATES and GLOBAL_IGNORE settings - Thanks to Jim + for the help in tracking the issue down + +3.17 - Rewritten the update code so that a new csf.conf is creating when + upgrading. It now uses the latest csf.conf and transfers the existing + settings to the new configuration file. This way all installations are + sure to have all new settings and the latest comments. It also makes + the release process for new builds much simpler + + Other installation/update improvements + + Updated APF/BFD removal procedure + +3.16 - Fixed bug introduced in v3.14 for generic installation only + +3.15 - Auto-whitelist all DNS traffic to/from IPs in /etc/resolv.conf + + Modified csf.conf text for new installations to account for + auto-configuration of ETH_DEV which has been the case for some time: + +# By default, csf will auto-configure iptables to filter all traffic except on +# the local (lo:) device. If you only want iptables rules applied to a specific +# NIC, then list it here (e.g. eth1, or eth+) +ETH_DEVICE = "" + +# If you don't want iptables rules applied to specific NICs, then list them in +# a comma separated list (e.g "eth1,eth2") +ETH_DEVICE_SKIP = "" + +3.14 - Added new format for cPanel (v11.18.3) login failures to regex.pm + + Added exe:/usr/libexec/gam_server to the default list of ignored + binaries + + Fixed problem with SCRIPT_ALERT not picking up alternative /home + directories from wwwacct.conf + +3.13 - Added new option DENY_TEMP_IP_LIMIT which limits the number of IP bans + held in the temporary IP ban list to prevent iptables flooding. If the + limit is reached, the oldest bans will be removed/allowed by lfd on + the next unblock cycle regardless of remaining TTL for the entry + + Added LF_FLUSH for the flush interval of reported usernames, files and + pids so that persistent problems continue to be reported. Default is + set to the previously hard-coded value of 3600 seconds + + Fixed uw-imap ipop3d regex + + Added check for TESTING mode when using csf -a or csf -d to only add + to the respective csf.allow or csf.deny files and not insert into + iptables to prevent errors if iptables has been flushed after reaching + TESTING_INTERVAL + +3.12 - Added SMTP AUTH failure regex for Kerio MailServers + + Fixed an issue where a permanent Port Scanning alert would report as + a temporary block, eventhough a permanent block was performed + + Added regex for failed SSH key authentication logins (thanks to Paul) + +3.11 - Use /proc for Process Tracking instead of ps output incase of + exploited system binaries and to better determine resource usage of + each process + +3.10 - Modified INPUT and OUTPUT chain rules to always specify the ethernet + device + + csf now re-applies temporary IP blocks on restart + + Added new CLI command to add temporary IP bans. See csf -h for the + new csf -td command + + Added new options to WHM csf UI to unblock temporary IP bans + + Added new option to WHM csf UI to block IP temporarily for a specified + TTL + +3.09 - Fixed missing copy for the portscan.txt report for generic + installations + + Added new option PS_EMAIL_ALERT to enable/disable Port Scan Tracking + email alerts + + Added a sample of the port blocks that trigger the Port Scan to the + report. This new report will be copied to /etc/csf/portscan.txt.new on + existing installations, rename it to portscan.txt to use it + + Added Port Scan Tracking to WHM UI Firewall Security Level + + Added cPAddon update email setting check to Server Security Report + + Modified the SuEXEC link location to the cPanel v11 location in Server + Security Report + + Added portscan.txt template to editable list in WHM UI + + Updated readme.txt + +3.08 - Modified Port Scan Tracking to ignore blocked IP addresses incase + DROP_IP_LOGGING is enabled + +3.07 - Added Apache Server Status report to PT_LOAD for load average report + monitoring. To benefit from this feature you will need to rename the + new report file /etc/csf/loadalert.txt.new to loadalert.txt. The + reports (ps, vmstat and apache) are now included as MIME attachments + in the email report instead of inline text + + New feature: Port Scan Tracking. This feature tracks port blocks + logged by iptables to syslog. It can help block hackers attempting to + scan the server for open ports, or to block them while trying to + access blocked standard ports, e.g. SSH. See csf.conf for more + information + + Upgraded the urlget module + +3.06 - Added System Exploit Checking. This enables lfd to check for the + Random JS Toolkit and may check for others in the future: + http://www.cpanel.net/security/notes/random_js_toolkit.html + It compares md5sums of the binaries listed in the exploit above for + changes and also attempts to create and remove a number directory. The + open is enabled by default. The report is generated from the + exploitalert.txt template file + +3.05 - Added perl regex checking to csf.pignore with the new options puser, + pexe and pcmd. Text added to csf.pignore for new installations: + +# Or, perl regular expression matching (regex): +# +# pexe:/full/path/to/file as a perl regex[*] +# puser:username as a perl regex[*] +# pcmd:command line as a perl regex[*] +# +# [*]You must remember to escape characters correctly when using regex's, e.g.: +# pexe:/home/.*/public_html/cgi-bin/script\.cgi +# puser:bob\d.* +# pcmd:/home/.*/command\s\to\smatch\s\.pl\s.* + +3.04 - Added two new options ICMP_IN_RATE and ICMP_OUT_RATE which allow you + to set the incoming and outgoing ICMP rate limits independently, or to + disable rate limiting in either direction completely for ICMP packets + +3.03 - Modified LF_DIRWATCH_FILE to use the output from "ls -lAR" instead of + "ls -laAR" + + Modified rules so that only icmp ping is blocked and all other icmp + packets allowed if ping disabled in csf configuration. This may well + help improve iptables performance if ping was disabled + + Added rate-limiting for all icmp packets to prevent inbound flooding + + New option SYNFLOOD configures iptables to offer some protection from + tcp SYN packet DOS attempts. SYNFLOOD_RATE sets the inbound packet + rate per IP so the option can be tailored + + Added SYN flag checking of state NEW tcp connections if PACKET_FILTER + is enabled. NEW tcp connections should always starts with a SYN + + Moved PACKET_FILTER rules to their own iptables chain called INVALID + + Fixed issue where some drops were not logging when logging enabled + + Added hourly flush interval of reported usernames, files and pids so + that persistent problems continue to be reported + + Added RELAYHOSTS and SYNFLOOD to Firewall Security Level in UI + +3.02 - Modified the text comments at the top of csf.allow for new installs: + +# Note: IP addressess listed in this file will NOT be ignored by lfd, so they +# can still be blocked. If you do not want lfd to block an IP address you must +# add it to csf.ignore + + Removed RELAYHOSTS check from Server Check report + + Don't show SMTP_BLOCK check if on a VPS in Server Check report + + PT_USERKILL, if set, will now also kill user processes that exceed + PT_USERPROC + + Fixed problem where csf.tempusers was not being cleared down on an lfd + restart + + Added two new csf command line options to flush IP's from the + temporary ban list: -tr -tf (see csf -h for more information) + +3.01 - Tightened DNS port configuration restrictions as the old rules were + being catered for by iptables connection + + Added Kerio Mailserver POP3/IMAP regex's + +3.00 - Added progress information to LWP downloads within csf + + Added numiptent checking for VPS servers. csf will flush iptables and + lfd will stop blocking IP's if numiptent is nearly depleted. This + should help prevent VPS lockouts due to insufficient server + resources. If this happens, you will either need to reduce the number + of iptables rules (e.g. disable Block List usage) or have the VPS + provider increase numiptent. A value of ~700-1000 should be fine for + most SPI firewall applications with full Block List configuration + + Added support for the BOGON List (Block List) with LF_BOGON - + http://www.cymru.com/Bogons/ + See link and csf.conf for more information + + Fixed problem with RELAYHOSTS not working + + Removed use of the replace binary + +2.95 - Reduced memory overhead and added large file skipping for LF_DIRWATCH + + Improved performance of LF_DIRWATCH trigger checks + + Fixed problem with LF_SELECT temporarily blocking outbound access on + all ports. Now now only the relevant inbound only port(s) will be + blocked if triggered + +2.94 - Fixed linux line-endings in some configuration files from v2.93 - + doesn't affect existing installations + +2.93 - Improved mod_security v2 regex for filter triggers + + Added MySQL v5 check + +2.92 - Improved the cPanel version check for < v11 and whether up to date + + Added new CLI option -t (--temp) which lists the temporary IP bans and + the TTL before the IP is flushed from iptables + + Added "View Temporary IP Bans" to WHM UI + + Changed WHM UI lfd Log auto-refresh default to unchecked + + Added regex for dovecot "Aborted login" messages in /var/log/maillog + + Added support for displaying mod_security v2 logs in WHM UI + +2.91 - Added Fedora Core v6 to the obsolete OS check + + Added php v4 check + + Added apache v2.2 check + + Added Perl v5.8.8 check + + Added cPanel v11 check + + Modified Sys::Syslog use to utilise the ndelay and nofatal options + + Added new option GLOBAL_IGNORE which makes lfd ignore IP's listed in + a globally located ignore file + + Added new option CT_STATES to Connection Tracking so that you can + specify which connection states you want to count towards CT_LIMIT, + e.g. SYN_RECV + +2.90 - Ensured that Process Tracking doesn't affect processes running under + root + + Added /usr/local/cpanel/bin/cpwrap to the csf.pignore file for new and + existing installations + + Added Apache v2 checks to Server Checks Report + + Removed mod_evasive from Server Checks Report as it appears to be less + relevant, especially with Apache v2 + +2.89 - Fixed the csf webmin module + + Added updates to the webmin module + + Completely removed use of cat in the WHM module and wget/cat from the + webmin module + +2.88 - Fixed typo in csf.conf for new installs LF_LOAD -> PT_LOAD + + Modified the courier IMAP and POP3D regex's to include connections + over SSL in lfd + + Modified lfd to ignore cpdavd processes + + Modified the cPanel regex's to include cPanel v11 variants in lfd + +2.87 - Fixed duplication of settings during generic configuration upgrade + procedure + + Only display version confirmation update message when running csf -u + interactively (Thanks to Brian Coogan for the perl tip) + + Fixed issue with temporary files not being truncated before being + written to, which caused problems e.g. with global allow/deny files + + Added new option CT_SKIP_TIME_WAIT to exclude TIME_WAIT state from + connection tracking + + Updated the csf webmin module to use the &ReadParse() routine to + overcome problems when running through SSL (Thanks to Tim Ballantine + for this tip) + +2.86 - Added regex for SSH on Debian v4 and for "Failed keyboard-interactive" + on RedHat + +2.85 - Fixed a problem with v2.84 which broke permanent IP blocking in lfd - + it's been a long week :-/ + +2.84 - Fixed problem with permanent LF blocks in lfd for individual + application port blocks when set to permanent + + Added new SYSLOG option to csf.conf to allow additional lfd logging to + SYSLOG (requires perl module Sys::Syslog) + + Added a minimum to LF_DSHIELD and LF_SPAMHAUS ip block lists refresh + interval of 3600 to prevent getting yourself blocked! + +2.83 - Fixed broken Server Check from v2.82 + +2.82 - Fixed a documentation for LF_TRIGGER_PERM + + Fixed issue where RT_[relay]_ALERT set to "0" was being ignored + + Fixed condition from v2.80 which prevented SCRIPT_ALERT from working + + If killproc.conf does not exist the Server Check now links to the + Background Process Killer page instead of issuing a file missing error + +2.81 - Added exe:/usr/local/cpanel/cpdavd to csf.pignore + + Added option to disable refresh in WHM csf UI when viewing lfd.log + + Removed debug code that prevented IP blocking -- oops + +2.80 - Added new lfd feature - Relay Tracking. This allows you to track email + that is relayed through the server (cPanel only). It tracks general + email sent into the server, email sent out after POP before SMTP and + SMTP_AUTH authentication, local email sent from the server (e.g. web + scripts). There are also options to send alerts and block IP addresses + if the number of emails relayed per hour exceeds configured limits. + The blocks can be either permanent or temporary. Currently blocking + does not function for LOCALRELAY email. + + Introduced a new blocking mechanism in lfd that allows a choice of + permanent or temporary IP blocking. See csf.conf (LF_TRIGGER_PERM) for + details on how to configure the various blocking options to use + temporary instead of permanent blocks, e.g. for Login Failure blocking + + Modified new installations to default to using seperate triggers for + login failures, instead of the global LF_TRIGGER value + +2.79 - Bug fixes + + Added ACCEPT rule to 127.0.0.1:25 for the "cpanel" user if SMTP_BLOCK + is enabled for the new cPanel Webmail configuration in v11 + + Added new configuration option DROP that allows you to choose the drop + target for rejected packets (see csf.conf for more information) + + Remove /etc/cron.d/csf_update on uninstall + +2.77 - Closed vulnerability with temporary file checking + + Tighted log file regex's to prevent spoofed remote IP block attacks + +2.76 - Improved file checking in Server Check script to prevent WHM failures + +2.75 - Modified Server Check to only look at pure-ftpd settings if installed + + Simplified throttling mechanism + + +2.74 - Modified PHP Server Checks to use the php binary output instead of + trying to find the active php.ini file + + Added PHP Server Check for register_globals + + Improvements to the Server Check code + + Fixed bug in TCP port 23 check in Server Check + + Added new option --check (-c) to check whether the installed verison + of csf is the latest, no update is performed + + Added multiple csf configuration checks to the Server Check report + + Added throttling to LF_INTEGRITY and increased the timeout + proportionally + +2.73 - Modified SMTP_BLOCK warning on VPS servers to only display if the + option is enabled + + Modifed the Server Services Check text to omit using -del with + chkconfig and better explain that a process is enabled even if it is + not currently running and needs to be disabled to prevent startup on + boot + + Removed reliance on wget for updates and version checks + + Coding improvements in csf.pl and addon_csf.cgi + + Added /var/log/lfd.log tail automatic refresh to WHM UI + +2.72 - Fixed problem with DENY_IP_LIMIT not counting all IP entries in + csf.deny correctly + + Ignore and issue a warning if SMTP_BLOCK is enabled on a Vituozzo VPS + since the Virtuozzo VPS kernel does not support ipt_owner + + Remove Shell/Fork Bomb Protection check in Server Check as the option + breaks a Virtuozzo VPS if enabled + + Added more processes to check in Server Services Check + + Removed restriction on outbound source port rule construction + +2.71 - Added CSS settings to support pre-v11 cPanel installations + +2.70 - Modified to adopt cPanel v11 WHM theme + + Added ports 2077 and 2078 (cPanel WebDAV server) to csf.conf for new + installations for v11 cPanel + + Added FC5 to the list of (or soon to be) unsupported OS's + + Fixed LF_SMTPAUTH not correctly being set to LF_FTPD when upgrading + +2.69 - Added back LF_DIRWATCH_DISABLE functionality securely. Fixed bug where + a suspicious directory would not be removed + + Added perl module check for File::Path + + Added path configuration to tar and chattr in csf.conf + + Added new option LF_SMTPAUTH which checks for SMTP AUTH exim login + failures. When upgrading the new setting will be set to whatever you + have LF_FTPD set to + +2.68 - Security Fix - If you have LF_DIRWATCH_DISABLE on then this can lead + to arbitray code being executed in the context of the user running lfd + , i.e. root. This option has been disabled in the code until further + notice. You will have to manually remove any reported files. + + Tightened csf file ownerships on installation + +2.67 - Security fix - A major security issue has been found in the + LF_DIRWATCH code that can lead to arbitrary code being executed in the + context of the user running lfd, i.e. root, if that option is enabled + and a hacker has access to create a crafted filename in one of the + watched directories. This update closes this hole. + + *ALL INSTALLATIONS SHOULD BE UPGRADED ASAP TO AVOID POTENTIAL + EXPLOITATION* + +2.66 - Modified LF_CPANEL text in csf.conf for new installations to reflect + the change in the SSL login handling by cPanel (i.e. it does now log + SSL login IP's) + + Modified the log line monitoring in lfd to cope with log line flooding + to prevent looping/excessive resource usage. Also recoded without the + use of the POSIX routines + + lfd process name now shows which log file it is scanning + +2.65 - New Feature: System Integrity Checking. This enables lfd to compare + md5sums of the servers OS binary application files from the time when + lfd starts. If the md5sum of a monitored file changes an alert is + sent. This option is intended as an IDS (Intrusion Detection System) + and is the last line of detection for a possible root compromise. See + csf.conf for more information + +2.64 - Modified lfd check for rotated system logs to re-open a log file if + logs are emptied instead of rotated + +2.63 - Added regex support for uw-imap (imap and pop3) login failures + + Added regex support for proftpd login failures + + Timeout version check incase version server is unavailable + +2.62 - Fixed CIDR support issue with csf.ignore only recognising the first + listed entry + +2.61 - Fixed problem with lfd not being killed by /etc/init.d/lfd + +2.60 - Added log file locations to csf.conf + + openSUSE v10 compatible (generic) + + Debian v3.1 (sarge) compatible (generic) + + Unbuntu v6.06 LTS compatible (generic) + + Added installation check for the LWP (libwww-perl) perl module + + Ran spell checker against the readme.txt file + +2.59 - Fixed mod_security report not displaying if only 1 entry + +2.58 - Tweaked the mod_security entry layout + +2.57 - New feature: WHM UI mod_security v1 display last X entries in the + audit_log + + New feature: WHM UI mod_security v1 edit files or directories in + /usr/local/apache/conf/ that are prefixed with modsec or mod_sec + + Tweaked the pre-configured Firewall Security Level settings + +2.56 - Fixed v2.55 fix for non-EDGE versions + +2.55 - Fix to to support current EDGE in csf WHM UI + +2.54 - Tightened the mod_security v1 regex after the changes in v2.52 + +2.53 - Modified Server Check to reflect withdrawn FedoraLegacy support for + FC3 and FC4 which should now be considered insecure + +2.52 - Separated the log file regex's into regex.pm for those feeling brave + to tailor them for non-cPanel servers + + Unified installer for cPanel and non-cPanel installations - so that + only install.sh needs to be run (checks for the existence of: + /usr/local/cpanel/version + If you install on a server intending to use cPanel before cPanel is + installed, run the install.cpanel.sh script instead + + Added mod_security v2 regex when running Apache2 to lfd + + Added [iptext] tag for connectiontracking.txt to list all the + connections of an offending IP. Add this manually for existing + installations + +2.51 - Major Enhancement: csf+lfd can now be installed and used on a generic + Linux OS without cPanel using install.generic.sh - see readme.txt for + more information + + PF INVDROP entries made bi-directional if PF logging enabled (reduces + the number of INVDROP LOG rules by half) + + Fixed Process Tracking throttle control to correctly use PT_INTERVAL + +2.50 - Removed option ALLOW_RES_PORTS from new installs, setting is ignored + + Check for LF at the end of form data for files edited through the WHM + UI and append one if omitted + + Following the changes in 2.48 the LOGDROP chain doesn't distinguish + between incoming and outgoing blocks. So, LOGDROP has now been split + into LOGDROPIN and LOGDROPOUT + +2.49 - Fixed issue if ETH_DEVICE was set and from changes in 2.48 + +2.48 - csf will now specify ! lo as the main ethernet device unless otherwise + defined in ETH_DEVICE. This will mean that the firewall is applied to + all ethernet devices on the server unless otherwise specified in the + configuration + +2.47 - Modified DYNDNS code to set listed domains IP addresses to be ignored + as if they were listed in csf.ignore + + If adding an IP address to csf.allow that is already in csf.deny, the + IP address will now be removed from csf.deny first and the DROP + removed from iptables. It will then be added to csf.allow as normal + +2.46 - Added auto-detection of additional exim port (same as SSH port) which + will be added to TCP_IN on csf installation (or if in TESTING mode) + + Only report PT_USERMEM and PT_USERTIME PIDs once + +2.45 - Added workaround to restart the bandmin acctboth chains if csf is + stopped or (re)started + + Rewritten the way RELAYHOSTS works so instead of using an iptables + chain a check is done at block time on the IP address and if it is in + /etc/relayhosts then it will be treated as if it is listed in + csf.ignore + + Enabled RELAYHOSTS by default, which is now a boolean on off (1 or 0) + instead of a time interval + + Added exe:/usr/local/cpanel/bin/logrunner to csf.pignore + + Added new options PT_USERMEM and PT_USERTIME to report excessive user + process usage and optionally PT_USERKILL to kill such processes. An + alert is sent using resalert.txt + +2.44 - Added new option PT_LOAD which will detect if the server load average + of choice exceeds a set threshold and send an alert + + Reduced the DROP_NOLOG default setting to not include ephemeral ports + for new installations + + Moved DROP_NOLOG rules to the LOGDROP chain + +2.43 - Added new option DROP_PF_LOGGING which will give detailed iptables log + information on dropped packets that are INVALID or out of sequence. + This can help tracking down why iptables may be blocking certain IP + connections + +2.42 - Improved the csf locking mechanism to avoid deadlocks + +2.41 - Fixed syntax in lfd procedure for csf locking + + Added pre and post csf job detection. If /etc/csf/csfpre.sh exists it + will be run before any of the csf iptables rules are applied. If + /etc/csf/csfpost.sh exists it will be run after all of the csf rules + have been applied. This allows you run your own iptables commands + within those files. Each file is passed through /bin/sh + + Added two new command line options to completely enable and disable + csf and lfd + + Added Enable and Disable options to WHM UI + +2.40 - Added csf lock procedure to avoid iptables race conditions if multiple + /simultaneous instances of csf or lfd are executed + + Added check for child reaper looping to dramatically reduce lfd load + +2.39 - Added OS check to Security Check to warn if using RH7/9 FC1/2 which + are no longer supported (or about to be retired) + + Made lfd more lenient when it cannot open a log file (reports the + error but continues to function) + + PHP Server Check - if /opt/suphp_php_bin/php.ini exists use that for + php settings + + Added new option RELAYHOSTS to csf.conf which allows you to + automatically allow access to IP's listed in /etc/relayhosts at a + specified interval + +2.38 - Fixed DYDNS (forgot to add the rule to redirect packets to the + ALLOWDYN iptables chain) + +2.37 - Added canna to the Security Check + + New feature - added support for dynamic dns (DYNDNS) records. See + csf.conf for more information + + Added dyndns file edit to WHM UI + +2.36 - Added runlevel check to Security Check + + Added nobody cron check to Security Check + + Added melange server check to Security Check + + Modified the regex for the php.ini disable_functions check + + Added timing function to lfd that logs how long each stage takes. This + can be enabled by editing lfd.pl and setting $timing=1 - this can help + in tracking down performance issues with lfd + +2.35 - Added specific exclusion for proftpd in lfd.pl process tracking + + Fixed bug with LF_GLOBAL being ignored + +2.34 - Added a new option (beta for now) PT_SMTP. This option will check for + outgoing connections to port 25, ecluding root, exim and mailman. The + purpose of the feature is to log SMTP connections if you believe you + have a spammer on the server who is bypassing exim to send out spam + emails - this is traditionally a very difficult form of spam to track + down. The option currently logs relevant process information to + lfd.log to avoid an email alert flood. + +2.33 - Code modification to allow csf+lfd to run without erroring on cPanel + DNS-Only installations + + Added forced error checking on SMTP blocking iptables commands + + Added check in csf and lfd for duplicate settings in csf.conf + +2.32 - Added new option SMTP_ALLOWLOCAL to allow local connections to port 25 + for web scripts, etc, if SMTP_BLOCK is enabled + + Added check to csf startup to fail if "WHM > Tweak Security > SMTP + Tweak" is enabled otherwise it can break SMTP traffic completely. The + SMTP_BLOCK and SMTP_ALLOWLOCAL options in csf.conf should be used + instead + +2.31 - Added automatic throttling code to help prevent lfd using excessive + resources. Currently only added for LF_DIRWATCH and PT_INTERVAL. If + the sub process takes too long to run, the interval between its next + run is increased temporarily (for the duration lfd runs for, a restart + will reset it) and will continue to extend this time to prevent + excessive server load. However, it will also proportionately increase + the time given for the sub process to complete so that it can at least + attempt to get the check done. If you see throttling messages + appearing in the lfd.log you should consider increasing the process + interval as indicated permanently (i.e. within csf.conf) + + Added throttling to CT_INTERVAL + +2.30 - Modified PT_USERPROC to respect all ignore entries in csf.pignore + +2.29 - New feature - User Process Tracking. This option enables the tracking + of the number of process any given cPanel account is running at one + time. If the number of processes exceeds the value of the PT_USERPROC + setting an email alert is sent with details of those processes. A user + is only reported once, so lfd must be restarted to reinstate checking + of all users. If you specify a user in csf.pignore it will be ignored. + The alert file is useralert.txt + + Added useralert.txt for editing through the WHM UI + + Added PT_USERPROC to the Firewall Security Level settings + +2.28 - Added /usr/local/apache1/bin/httpd and /usr/local/apache2/bin/httpd to + csf.pignore + + Only perform strict iptables error checking when in TESTING mode + +2.27 - Fixed another mis-configuation for outgoing global deny rule - Thanks + again to Marie from Jagwire Hosting + +2.26 - Fixed a mis-configuation for outgoing global deny rule - Thanks to + Marie from Jagwire Hosting + + Allow advanced allow and block filters using the -a and -d options + when running csf in CLI + + Added new option LF_SELECT. If you have LF_TRIGGER set to "0" and the + application trigger levels set, you can now set LF_SELECT to "1" if + you only want to block IP access to that application instead of a + complete block + + Changed installer behaviour to only add SSH port to TCP_IN if TESTING + is set to "1" - done to help those that don't want to always have the + SSH port opened + +2.25 - Modified lfd init procedure to use the init functions + + Modified behaviour of LF_TRIGGER. If LF_TRIGGER is set to "0" then lfd + will instead trigger blocks based on the value of the application + trigger, e.g. if LF_MODSEC is set to "3" then it will trigger on 3 + mod_security alerts. Or if LF_POP3D is set to "10" then it will + trigger on 10 pop3d login failures. When in this mode, i.e. with + LF_TRIGGER set to "0", login failures for different triggers are not + cumulative, whereis LF_TRIGGER set to a number > "0" they are + cumulative as before + + Modification to csf.conf to reflect the changes to LF_TRIGGER - only + applied to new installations + + Rewrite of the iptables command invocation in lfd.pl to trap iptables + errors and shutdown firewall if any found - should help prevent + lockouts + + Allow advanced rules in Global Allow and Deny lists. Input and Output + direction support included. + + Added Global Allow and Deny lists to the OUTPUT chain as well as the + INPUT chain + + Added csf.signore where you can list scripts for LF_SCRIPT_ALERT to + ignore. Updated WHM UI to allow easy file edits + +2.24 - Fixed global allow/deny lists so that you can correctly not have to + specify both an allow and a deny file + +2.23 - Modified LF_SCRIPT checking to also look for HOMEDIR and HOMEMATCH + from the cPanel configuration + + Added maildir check to Security Check + + Fixed a typo in advanced rules - Thank you to Victor from Touch + Support for pointing this out + + Added binary executable check for LF_DIRWATCH files + + Added core dump check in cron directories to LF_DIRWATCH + + Added /var/tmp check to LF_DIRWATCH if inode with /tmp does not match + + Increased LF_DIRWATCH timeout from 10 to 20 seconds - if you still + find it timing out, make sure that you have been clearing down your + tmp directories + +2.22 - Added CIDR recognition to csf.ignore + + Rewrite of the iptables command invocation in csf.pl to trap iptables + errors and shutdown firewall if any found - should help prevent + lockouts + +2.21 - Fixed a problem on some installations where the update process emptied + out csf.conf. If this has happened, you will need to remove + /etc/csf/csf.conf and then rerun the installation procedure and + reconfigure the firewall. If you're already running at least v2.18 you + can probably simply restore /etc/csf/csf.conf.preupdate to csf.conf + and then upgrade to this release + +2.20 - Added workaround for different output from the fuser application in + different OS's + +2.19 - Added Security Check for recurions restrictions in named.conf + + Modified port 23 check to be quicker + + Added Security Check for localhost/127.0.0.1 entry in resolv.conf + + Added Security Check for webmin if running + + Added 3 more WHM Security Checks for domain parking + + Added Security Check for boxtrapper + + Added a Run Again button to the Security Check page + + Added Security Checks for cPanel and security package updates + +2.18 - Fixed an issue with checking the /var/tmp symlink by comparing the + inodes of /tmp and the symlink destination of /var/tmp + + Added checking of /usr/tmp + + Added checking of SSH PasswordAuthentication + + Modified update routine to take a copy of csf.conf before upgrading - + the backup file is /etc/csf/csf.conf.preupdate + + Added check in /etc/cron.daily/logrotate for /tmp noexec workaround + +2.17 - Fixed installation process where duplicate entries were being added to + csf.conf for new settings. Routine added to remove duplicates and + redundant settings + + Added logrotate script for for the lfd.log file + +2.16 - Fixed syntax issue with the csf.deny application feature added in + v2.15 that prevents csf adding the IP to csf.deny + +2.15 - Added a list of the applications that lfd blocks a login failure for + into csf.deny, e.g. (ftpd,mod_security) + + Extended LF_DIRWATCH with a new option LF_DIRWATCH_FILE. This feature + will watch for changes in directories and files listed in csf.dirwatch + using an md5sum for the ls output. If the md5sum changes between + checks an email alert is sent using watchalert.txt + + Modified pid file locking for the lfd process to ensure duplicate + processes won't run + + Completely reworked the child reaper code to prevent SIG_CHLD kernel + errors. Removed DISABLE_SIG_CHLD_IGNORE from csf.conf for new installs + + Added new option to csf.fignore that allows you to ignore files owned + by a specific user by adding an entry in the format user:bob + + Fixed bug in LF_DSHIELD timer code + + Wrapped LF_DSHIELD and LF_SPAMHAUS in a 10 second timeout to fetch + their respective data + + New Feature - GLOBAL_ALLOW and GLOBAL_DENY options allow you to + specify a URL where csf can grab a centralised copy of an IP allow + and/or deny block list of your own. They are both retrieved after a + LF_GLOBAL interval in seconds by lfd + + Added WHM UI changes for LF_DIRWATCH_FILE + +2.14 - Modification to /var/tmp check to cater for symlinks with a trailing + slash + + Added check for native SSL support in cPanel in Server Check for those + versions that now support it + + Added MySQL port check to Server Check + + Added missing comments when clickcing Display All Comments + +2.13 - Added cPanel version check to Security Check + + Added suspicious symlink checking to LF_DIRWATCH + + Added a Display All Comments to Security Check + + Added hyperlinks to WHM URLs in Security Check comments + + Fixed the Apache Limits comments of the Security Check + + Added shell limit checks to Security Check + + Added Background Process Killer to Security Check + +2.12 - Removed duplicate /var/tmp tests + + Fixed another typo + +2.11 - Typo corrections in output text + + Removed dependencies on external modules for the Server Check report + +2.10 - Fixed /dev/shm test + +2.09 - Removed the nodev check on /tmp etc + +2.08 - Changed app name to ConfigServer Security & Firewall + + New Feature - Added Server Security Check report to WHM UI + +2.07 - Improved suspicious directory detection + +2.06 - Document update + + Change directory watching to only check for suspicious sub directories + +2.05 - Fixed log file error if DShield or Spamhaus block list retrieval fails + + Added perl regex matching in csf.fignore (see updated readme.txt) + +2.04 - Added /tmp/.horde/* to csf.fignore + +2.03 - Fixed a looping issue with the temporary Connection Tracking block + code + + Added a 10 second timeout for the LF_DIRWATCH child to prevent looping + +2.02 - In LF_DIRWATCH, allow wildcard matching at the end of a file name in + csf.fignore, such that /tmp/clamav* will ignore any files starting + with /tmp/clamav, e.g. /tmp/clamav-1234 + + Added a throttle to LF_DIRWATCH - if more than 10 emails are being + emailed in one pass, LF_DIRWATCH will create the file + /etc/csf/csf.dwdisable and then disable itself. To get it watching + again, either restart lfd or delete that file + + Fixed a bug where LF_DIRWATCH always reported the same file when + different files had been detected in a pass + +2.01 - Added an LF_DIRWATCH exception for postgres /tmp files + + Prevent a file being reported more than once in an LF_DIRWATCH run + + Removed LF_DIRWATCH check for files being excecutable since too many + apps set temporary files with the flag set, e.g. mod_gzip + +2.00 - New feature: Directory Watching. LF_DIRWATCH enables lfd to check /tmp + and /dev/shm and other pertinent directories for suspicious files, + i.e. script exploits. These can optionally be moved into a tarball + + Directory Watching false-positives can be listed in csf.fignore which + is accessible from the WHM UI + +1.99 - Bug fix for multiple NICs in the lfd code + +1.98 - Modified code to allow for multiple ethernet NICs so that all rules + are applied to all NICs, for example, if you have IP's spread over + eth0 and eth1. To do this you have to set ETH_DEVICE = "eth+" + +1.97 - Tightened DNS port 53 connections in accordance with: + http://www.oreillynet.com/pub/a/network/excerpt/dnsbindcook_ch07 + + Moved no log dropping to the end of the chains + + Moved allowed IP's to before Block Lists + +1.96 - Liberalised connections allowed to and from DNS port 53 + +1.95 - Fixed WHM UI update. If you're running v1.93 or v1.94 you'll have to + update from shell to get to v1.95 using: + csf -u + +1.94 - Set DROP_IP_LOGGING to 0 by default to cut down on syslog traffic + + Added exe:/usr/local/cpanel/bin/cppop-ssl to csf.pignore + +1.93 - Fixed problem where external resolvers were being used and responses + from them were being dropped because they were coming back on + ephemeral ports - added a scan of /etc/resolv.conf and external + nameservers now have whitelisted source port 53 to ephemeral ports + + Drop logging of failed attempts to access port 53 so they don't + consume syslog + + Moved update from /tmp do /usr/src + +1.92 - Fixed bug where the DShield and Spamhaus block lists weren't being + periodically updated by lfd + +1.90 - Minor fix to pre-configured settings + +1.89 - Added Pre-configured settings for Low, Medium or High firewall security + to WHM UI + +1.88 - Fixed csf DSHIELD block logging so it now goes to the BLOCKDROP chain + +1.87 - Modified drop list chains to use their own drop logging to + differentiate from normal drop - if drop logging enabled + +1.86 - Modified lfd connection tracking to drop udp as well as tcp packets + when blocking + + Added support for the DShield Block List with LF_DSHIELD - + http://www.dshield.org/block_list_info.php + See csf.conf for more information + + Added support for the Spamhaus DROP List with LF_SPAMHAUS - + http://www.spamhaus.org/drop/index.lasso + See csf.conf for more information + +1.85 - Workaround for spam PT false-positives + + Added exe:/usr/bin/spamc to csf.pignore + + Added csf version to title bar in WHM + +1.84 - Added new cpsrvd-ssl executable to csf.pignore for the new SSL native + cPanel setup (currently in EDGE) + +1.83 - Enhanced lfd.log logging for application failure detection lines + + Set lfd to ignore child processes to get rid of zombie children. If + you see kernel messages regarding SIG_CHLD (it's a kernel bug) you can + revert to the child reaper method by enabling DISABLE_SIG_CHLD_IGNORE, + but you are likely to see harmless lfd zombie processes + +1.82 - Modified to only load LKM ipt_owner if SMTP_BLOCK enabled + + Extended the Advanced Allow/Deny Filters to allow use of UID and GID + filtering for outgoing packets - see readme.txt for more details + + Modified code to deal with modprobe command output more cleanly + +1.81 - Further modification for the newer xt iptables modules + +1.80 - Modified iptables LKM modprobe code to cater for newer xt_* module + naming scheme + +1.79 - Added new feature to send an alert email if su is used to login from + one account to another. Alerts are sent whether the attempt was + successful or failed + +1.78 - Added workaround for non-ASCII codes after /usr/sbin/pure-ftpd in lfd + process tracking + +1.77 - Added option DISABLE_SIG_CHLD_IGNORE for servers running old kernels, + e.g. RH9/FC1 + + Modified WHM UI textareas to expand to fit file contents + +1.76 - Changed WHM interface to restart csf before lfd when restarting both + +1.75 - Fix to prevent duplicates in csf.deny + + Added a slight pause between stop and start when restarting + + Code fix for TESTING mode crontab entry removal + +1.74 - Fixed lfd to when reading csf.ignore when comments present + +1.73 - Added new option LF_CSF to restart csf if iptables appears to have + been flushed (i.e. stopped) + + Added new option LF_SCRIPT_PERM to disable directories identified by + LF_SCRIPT_ALERT - see csf.conf for more information + + Workaround to child reaper when 2 children die at the same time + + Added workaround for PT spamd false-positives + +1.72 - Fixed bug in (deleted) lfd checks + +1.71 - Added some more exceptions to csf.pignore + + Lowered the default setting for LF_SCRIPT_LIMIT to 100 + + Modified PT to check for deleted binaries on exemptions which happen + when upcp runs and the binaries are replaced + +1.70 - PT now only reports processes with open ports + +1.69 - lfd tweaks + +1.68 - Additions to csf.pignore + + Added new option PT_SKIP_HTTP - see csf.conf/readme.txt + + Updated readme.txt regarding unavoidable false-positives and possible + mitigation. + +1.67 - More tweaks to PT with additions to csf.pignore + +1.66 - Updated csf.pignore file with additional executables + + lfd code tweaks + +1.65 - Added very simple ASCII obfuscation for lfd PT skip lines + + Fixed port typo for entropychat port + +1.64 - Updated CLI help and readme.txt for new csf -u command from v1.63 + + Changed the format of the email templates for new installations - + if you want to use the new format remove /etc/csf/*.txt and then + install csf + + Added mechanism to prevent multiple email/block attempts from login + attacks in lfd + + Added new feature - Process Tracking. This option enables tracking of + user and nobody processes and examines them for suspicious executables + or open network ports. Its purpose is to identify potential exploit + processes that are running on the server, even if they are obfuscated + to appear as system services. If a suspicious process is found an + alert email is sent with relevant information - readme.txt for details + +1.63 - Added feature to WHM UI to enable editing of the email templates + + Modified WHM UI to use fixed-width larger font for command output and + edit boxes + + Added notice to install.txt and readme.txt about enabling klogd (on + VPS systems in particular) + + Added autoupdates system using AUTO_UPDATES - see csf.conf for details + +1.62 - Added to APF/BFD removal in WHM UI the logrotate configuration files + + Added comments system to csf.allow and csf.deny - see readme.txt for + more information + +1.61 - Tighten up some of the csf rules + + Added new fature - LF_SCRIPT_ALERT when enabled will scan + /var/log/exim_mainlog for extended exim logging lines that show the + cwd= line for paths in /home which indicate emails sent from scripts. + If LF_SCRIPT_LIMIT emails from the same path are sent within an hour, + an email alert is sent using scriptalert.txt containing the first 10 + probably exim mainlog line matches and also likely mailing scripts + within the identifed path - an ideal tool to help identify spamming + scripts sending out email through exim. The option is disabled by + default as you do need to enable extended exim logging first as + explained in the csf.conf file + +1.60 - Modified lfd to use a child reaper instead of ignoring the CHLD signal + + Added login failure detection of cpanel, webmail and whm connections - + this will only work for access to non-secure ports as cPanel doesn't + know the IP address of the user when connection are over SSL due to + the way stunnel works + +1.59 - Added workaround to ethernet device detection for VPS servers + +1.58 - Fixed problem where SSH port detection on installation would add an emtpy , if + the SSH port had not been explicitly defined in sshd_config + + Modified csf and lfd ethernet device detection so that if specified in either + csf.conf or /etc/wwwacct.conf dup IP's aren't checked - useful for bonded + ethernet devices on some OS's + +1.57 - Removed erroneous 's in lfd.log + + csf start automatically does a restart to avoid problems with any + existing iptables rules or chains + + Added new option "Deny Server IPs" and associated file csf.sips to + allow blocking of all traffic on server configured IP's if they're + not in use + + Added notification to CLI and WHM UI if TESTING still enabled + +1.56 - lfd modification to avoid a race condition with the ALRM calls + + Added new feature - /etc/csf/csf.ignore can contain IP addresses that + are ignored by lfd. If an event is triggered it may be logged in + lfd.log but will not result in an email alert - e.g. you could list + your own IP address to avoid alerts from when you login over SSH, etc + + Added WHM UI option to edit the ignore file + +1.55 - Fixed a strict refs issue in lfd + +1.54 - Fixed IP DNS lookup routine to avoid empty () when no host found + + Added local DIE for ALRM calls for IP lookups and netstat commands + + Removed chkservd restart from /etc/init.d/lfd so that it behaves like + other monitored services + + Improved error trapping routines to better report to lfd.log if the + process dies + +1.53 - Optimised logging in lfd + + Improved error handling and reporting in lfd + + Modified WHM UI report to include all data, not just a single day + + Improved DROP logging to SYSLOG + + Added logging of dropped ICMP connections + + Added new option DROP_IP_LOGGING to log IP addresses that have been + blocked in csf.deny or by lfd with temporary connection tracking + blocks + +1.52 - beta test release + +1.51 - Added DNS lookups for IP addresses in all lfd alert emails + +1.5 - Added new feature - Connection Tracking. Enables tracking of all + connections from IP addresses to the server. If the total number of + connections is greater than CT_LIMIT then the offending IP address is + blocked in csf, or temporarily blocked in iptables. This can be used + to help prevent some types of DOS attack + + Added new feature - SSH login alerts. An email is sent if a successful + SSH login is detected + + Fixed a descriptive issue with the WHM UI + + Modified so that lfd checks that it doesn't block a server IP + +1.42 - Modified lfd login tracking to check the csf.allow file for an + offending IP address and to skip it if it's allowed - note this only + works for specified full IP addresses (not CIDRs or advanced port/IP) + +1.41 - Added an exception for 127.0.0.1 when checking ethernet interfaces as + VPS servers are setup with that IP on both the loopback and main + interface + +1.4 - Fixed error routine iptables flush command typo + + Modified interface checking for non-english Linux distributions + + Modified interface checking for IP addresses assigned to multiple + interfaces by mistake (I've just seen this happen!) + + Set FORWARD chain to ACCEPT on stopping firewall + + Reorganised csf.pl code + + Added advanced port+ip filtering within csf.allow and csf.deny with + the format: tcp/udp:in/out:s/d=port:s/d=ip (see readme.txt for info) + + Added link to readme.txt in WHM interface + + Added iptables status (Running/Stopped) to WHM interface + + Added Quick Allow and Quick Deny IP address options to WHM interface + +1.33 - Added blocking of SSL POP3 and IMAP ports to LT (993/995) + + Added option to Restart csf+lfd within WHM interface when appropriate + + Added buttons to WHM interface to remove APF or BFD if still installed + + Removed csf nat and mangle chain actions + +1.32 - Modified log line checking to deal with syslog compression. This is + where syslog will add a line "last message repeated X times" if the + next line it were to add is identical to the last. This could lead to + login attempts being missed. But no more - lfd now checks for that + line and repeats the processing of the previous log line X times to + count all the login failures + +1.31 - Removed some redundant code from csf + + Display error in csf if IP already in allow/deny file + + Stopped install.sh from overwriting email templates + + Added email notification for login tracking including a new email + template tracking.txt + + Added mod_security apache module IP blocking in lfd + +1.3 - Fixed a problem with the tick time in the alert report + + Changed the way allow and deny IP addresses are inserted into iptables + so that using the command line -a or -d doesn't require a firewall + restart + + csf -l now shows iptables line numbers + + Added login tracking (LT) options to keep track of POP3 and IMAP + logins and limit them to X connections per hour per account per IP + address. Uses iptables to block offenders to the appropriate protocol + port only and flushes them every hour. All of these blocks are + temporary and can be cleared by restarting csf + +1.21 - Added the real log file failure entry matches to the alert email. Existing + installations will need to add a [text] variable into + /etc/csf/alert.txt + + Added link in WHM to the ChangeLog if a new version is available + +1.2 - Fixed uninstall script to remove lfd from chkservd + + Fixed lfd so that checks were not made on options where a log file is + shared + + Fixed lfd stop/start to dis/enable chkservd option + + Added upgrade feature to WHM when a new version of csf is available + +1.11 - Use full paths to chkconfig within the csf installation scripts + + Documentation improvements + +1.1 - Added option LF_EMAIL_ALERT which enables email alerts if lfd blocks + an IP address. lfd now forks a child process to handle the IP blocking + and email so that it doesn't hinder the daemon process from scanning + the logs. It uses a template file for the email. + +1.0 - Initial public release + + Set ALLOW_RES_PORTS to default to 1 after further RFC 1700 reading + + Check /var/log/messages and /var/log/secure for SSHD logins + + Clarified in the configuration file that only courier-imap/pop3 + connections are trapped in lfd + +1.0RC2 - Added filtering out of \r in WHM interface for allow and deny + + Fixed typo in WHM addon + + Added new configuration option ALLOW_RES_PORTS + +1.0RC1 - Added iptables reporting to WHM interface using fwlogwatch: + http://sourceforge.net/projects/fwlogwatch/ + This processes /var/log/messages and extracts the iptables log entries + (if logging is enabled) and produces a simple HTML summary report + +0.2b - Fixed modprobe errors on MONOLITHIC kernels that don't have the nat + module installed + + Modified lfd to use asterix in the log message when blocking to + highlight in Thunderbird in the same way as the kernel log messages if + you use the "Quote Colors" extension - http://quotecolors.mozdev.org/ + + Added list of TCP and UDP ports currently being listened on to install + + Set DNS_ZONE to default to 1 + + Removed backups of csf.conf files as the WHM interface is stable + + Added ipt_owner module load for SMTP Tweak on LKM kernels + + Added ipt_LOG to the required module list for LKM kernels to ensure + drop logging to syslog + + Added new configuration option DENY_IP_LIMIT + +0.1b - Initial beta release (24 May 2006) diff --git a/csf/connectiontracking.txt b/csf/connectiontracking.txt new file mode 100644 index 0000000..5aa06a4 --- /dev/null +++ b/csf/connectiontracking.txt @@ -0,0 +1,11 @@ +From: root +To: root +Subject: lfd on [hostname]: [ip] blocked with too many connections + +Time: [time] +IP: [ip] +Connections: [ipcount] +Blocked: [temp] + +Connections: +[iptext] diff --git a/csf/consolealert.txt b/csf/consolealert.txt new file mode 100644 index 0000000..ece9ad7 --- /dev/null +++ b/csf/consolealert.txt @@ -0,0 +1,5 @@ +From: root +To: root +Subject: lfd on [hostname]: console login alert + +[line] diff --git a/csf/cpanel.allow b/csf/cpanel.allow new file mode 100644 index 0000000..56009bd --- /dev/null +++ b/csf/cpanel.allow @@ -0,0 +1,100 @@ +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +# The following IP addresses will be allowed through iptables and ignored by +# lfd to allow for unimpeded access to the cPanel license service +# +# Each IP address belongs to cPanel and is responsibly for authenticating +# cPanel licenses +# +# Note: This file will be replaced when csf is upgraded - do NOT make any +# changes to this file. If you do not want to whitelist these IP addresses you +# need to remove the Include line from csf.allow as this is only added there +# once + +tcp|in|d=4|s=208.74.123.2 # cPanel Auth Server +tcp|in|d=8|s=208.74.123.2 # cPanel Auth Server +tcp|in|d=10|s=208.74.123.2 # cPanel Auth Server +tcp|in|d=14|s=208.74.123.2 # cPanel Auth Server +tcp|in|d=16|s=208.74.123.2 # cPanel Auth Server +tcp|in|d=40|s=208.74.123.2 # cPanel Auth Server +tcp|in|d=1020|s=208.74.123.2 # cPanel Auth Server +tcp|in|d=1021|s=208.74.123.2 # cPanel Auth Server +tcp|in|d=1022|s=208.74.123.2 # cPanel Auth Server + +tcp|in|d=4|s=208.74.123.3 # cPanel Auth Server +tcp|in|d=8|s=208.74.123.3 # cPanel Auth Server +tcp|in|d=10|s=208.74.123.3 # cPanel Auth Server +tcp|in|d=14|s=208.74.123.3 # cPanel Auth Server +tcp|in|d=16|s=208.74.123.3 # cPanel Auth Server +tcp|in|d=40|s=208.74.123.3 # cPanel Auth Server +tcp|in|d=1020|s=208.74.123.3 # cPanel Auth Server +tcp|in|d=1021|s=208.74.123.3 # cPanel Auth Server +tcp|in|d=1022|s=208.74.123.3 # cPanel Auth Server + +tcp|in|d=4|s=208.74.121.82 # cPanel Auth Server +tcp|in|d=8|s=208.74.121.82 # cPanel Auth Server +tcp|in|d=10|s=208.74.121.82 # cPanel Auth Server +tcp|in|d=14|s=208.74.121.82 # cPanel Auth Server +tcp|in|d=16|s=208.74.121.82 # cPanel Auth Server +tcp|in|d=40|s=208.74.121.82 # cPanel Auth Server +tcp|in|d=1020|s=208.74.121.82 # cPanel Auth Server +tcp|in|d=1021|s=208.74.121.82 # cPanel Auth Server +tcp|in|d=1022|s=208.74.121.82 # cPanel Auth Server + +tcp|in|d=4|s=208.74.121.83 # cPanel Auth Server +tcp|in|d=8|s=208.74.121.83 # cPanel Auth Server +tcp|in|d=10|s=208.74.121.83 # cPanel Auth Server +tcp|in|d=14|s=208.74.121.83 # cPanel Auth Server +tcp|in|d=16|s=208.74.121.83 # cPanel Auth Server +tcp|in|d=40|s=208.74.121.83 # cPanel Auth Server +tcp|in|d=1020|s=208.74.121.83 # cPanel Auth Server +tcp|in|d=1021|s=208.74.121.83 # cPanel Auth Server +tcp|in|d=1022|s=208.74.121.83 # cPanel Auth Server + +tcp|in|d=4|s=208.74.121.85 # cPanel Auth Server +tcp|in|d=8|s=208.74.121.85 # cPanel Auth Server +tcp|in|d=10|s=208.74.121.85 # cPanel Auth Server +tcp|in|d=14|s=208.74.121.85 # cPanel Auth Server +tcp|in|d=16|s=208.74.121.85 # cPanel Auth Server +tcp|in|d=40|s=208.74.121.85 # cPanel Auth Server +tcp|in|d=1020|s=208.74.121.85 # cPanel Auth Server +tcp|in|d=1021|s=208.74.121.85 # cPanel Auth Server +tcp|in|d=1022|s=208.74.121.85 # cPanel Auth Server + +tcp|in|d=4|s=208.74.121.86 # cPanel Auth Server +tcp|in|d=8|s=208.74.121.86 # cPanel Auth Server +tcp|in|d=10|s=208.74.121.86 # cPanel Auth Server +tcp|in|d=14|s=208.74.121.86 # cPanel Auth Server +tcp|in|d=16|s=208.74.121.86 # cPanel Auth Server +tcp|in|d=40|s=208.74.121.86 # cPanel Auth Server +tcp|in|d=1020|s=208.74.121.86 # cPanel Auth Server +tcp|in|d=1021|s=208.74.121.86 # cPanel Auth Server +tcp|in|d=1022|s=208.74.121.86 # cPanel Auth Server + +tcp|in|d=80|s=52.51.23.204 # cPanel SaaS Server +tcp|in|d=443|s=52.51.23.204 # cPanel SaaS Server +tcp|in|d=8443|s=52.51.23.204 # cPanel SaaS Server + +tcp|in|d=80|s=52.213.169.7 # cPanel SaaS Server +tcp|in|d=443|s=52.213.169.7 # cPanel SaaS Server +tcp|in|d=8443|s=52.213.169.7 # cPanel SaaS Server + +tcp|in|d=80|s=34.254.37.129 # cPanel SaaS Server +tcp|in|d=443|s=34.254.37.129 # cPanel SaaS Server +tcp|in|d=8443|s=34.254.37.129 # cPanel SaaS Server diff --git a/csf/cpanel.comodo.allow b/csf/cpanel.comodo.allow new file mode 100644 index 0000000..bb8ede0 --- /dev/null +++ b/csf/cpanel.comodo.allow @@ -0,0 +1,56 @@ +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +# The following IP addresses will be allowed through iptables and ignored by +# lfd to allow for unimpeded access to cPanels free SSL certificate service +# available in cPanel v58+ +# +# Each IP address belongs to the Sectigo SSL provider (formerly Comodo) +# +# Note: This file will be replaced when csf is upgraded - do NOT make any +# changes to this file. If you do not want to whitelist these IP addresses you +# need to remove the Include line from csf.allow as this is only added there +# once + +tcp|in|d=80|s=178.255.81.12 # Sectigo SSL Resolver +tcp|in|d=443|s=178.255.81.12 # Sectigo SSL Resolver +tcp|in|d=53|s=178.255.81.12 # Sectigo SSL Resolver + +tcp|in|d=80|s=178.255.81.13 # Sectigo SSL Resolver +tcp|in|d=443|s=178.255.81.13 # Sectigo SSL Resolver +tcp|in|d=53|s=178.255.81.13 # Sectigo SSL Resolver + +tcp|in|d=80|s=91.199.212.52 # Sectigo DCV Server +tcp|in|d=443|s=91.199.212.52 # Sectigo DCV Server +tcp|in|d=53|s=91.199.212.52 # Sectigo DCV Server + +tcp|in|d=80|s=91.199.212.132 # Sectigo DCV Server +tcp|in|d=443|s=91.199.212.132 # Sectigo DCV Server +tcp|in|d=53|s=91.199.212.132 # Sectigo DCV Server + +tcp|in|d=80|s=199.66.201.132 # Sectigo DCV Server +tcp|in|d=443|s=199.66.201.132 # Sectigo DCV Server +tcp|in|d=53|s=199.66.201.132 # Sectigo DCV Server + +tcp|in|d=80|s=2a02:1788:402:1c80::/64 # Sectigo DCV Server +tcp|in|d=443|s=2a02:1788:402:1c80::/64 # Sectigo DCV Server +tcp|in|d=53|s=2a02:1788:402:1c80::/64 # Sectigo DCV Server + +tcp|in|d=80|s=2a02:1788:400:1ce4::/64 # Sectigo DCV Server +tcp|in|d=443|s=2a02:1788:400:1ce4::/64 # Sectigo DCV Server +tcp|in|d=53|s=2a02:1788:400:1ce4::/64 # Sectigo DCV Server diff --git a/csf/cpanel.comodo.ignore b/csf/cpanel.comodo.ignore new file mode 100644 index 0000000..de8858f --- /dev/null +++ b/csf/cpanel.comodo.ignore @@ -0,0 +1,36 @@ +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +# The following IP addresses will be allowed through iptables and ignored by +# lfd to allow for unimpeded access to cPanels free SSL certificate service +# available in cPanel v58+ +# +# Each IP address belongs to the Sectigo SSL provider (formerly Comodo) +# +# Note: This file will be replaced when csf is upgraded - do NOT make any +# changes to this file. If you do not want to whitelist these IP addresses you +# need to remove the Include line from csf.ignore as this is only added there +# once + +178.255.81.12 # Sectigo SSL Resolver +178.255.81.13 # Sectigo SSL Resolver +91.199.212.52 # Sectigo DCV Server +91.199.212.132 # Sectigo DCV Server +199.66.201.132 # Sectigo DCV Backup Server +2a02:1788:400:1ce4::/64 # Sectigo DCV Server +2a02:1788:400:1ce4::/64 # Sectigo DCV Server diff --git a/csf/cpanel.ignore b/csf/cpanel.ignore new file mode 100644 index 0000000..7bf61c2 --- /dev/null +++ b/csf/cpanel.ignore @@ -0,0 +1,35 @@ +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +# The following IP addresses will be allowed through iptables and ignored by +# lfd to allow for unimpeded access to the cPanel license service +# +# Each IP address belongs to cPanel and is responsibly for authenticating +# cPanel licenses +# +# Note: This file will be replaced when csf is upgraded - do NOT make any +# changes to this file. If you do not want to whitelist these IP addresses you +# need to remove the Include line from csf.ignore as this is only added there +# once + +208.74.123.2 # cPanel Auth Server +208.74.123.3 # cPanel Auth Server +208.74.121.82 # cPanel Auth Server +208.74.121.83 # cPanel Auth Server +208.74.121.85 # cPanel Auth Server +208.74.121.86 # cPanel Auth Server diff --git a/csf/cpanel/Driver/ConfigServercsf.pm b/csf/cpanel/Driver/ConfigServercsf.pm new file mode 100644 index 0000000..9613164 --- /dev/null +++ b/csf/cpanel/Driver/ConfigServercsf.pm @@ -0,0 +1,51 @@ +package Cpanel::Config::ConfigObj::Driver::ConfigServercsf; + +use strict; +use Cpanel::Config::ConfigObj::Driver::ConfigServercsf::META (); +*VERSION = \$Cpanel::Config::ConfigObj::Driver::ConfigServercsf::META::VERSION; + +#use parent qw(Cpanel::Config::ConfigObj::Interface::Config::v1); +our @ISA = qw(Cpanel::Config::ConfigObj::Interface::Config::v1); + +sub init { + my ( $class, $software_obj ) = @_; + + my $ConfigServercsf_defaults = { + 'thirdparty_ns' => "ConfigServercsf", + 'meta' => {}, + }; + my $self = $class->SUPER::base( $ConfigServercsf_defaults, $software_obj ); + + return $self; +} + +sub enable { + my ( $self, $input ) = @_; + return 1; +} + +sub disable { + my ( $self, $input ) = @_; + return 1; +} + +sub info { + my ($self) = @_; + my $meta_obj = $self->meta(); + my $abstract = $meta_obj->abstract(); + return $abstract; +} + +sub acl_desc { + return [ + { + 'acl' => 'software-ConfigServer-csf', #this should be "software-$key" + 'default_value' => 0, + 'default_ui_value' => 0, # NOTE: this is for ui; first time setting reseller privs + 'name' => 'ConfigServer Security & Firewall (Reseller UI)', + 'acl_subcat' => 'Third Party Services', + }, + ]; +} + +1; diff --git a/csf/cpanel/Driver/ConfigServercsf/META.pm b/csf/cpanel/Driver/ConfigServercsf/META.pm new file mode 100644 index 0000000..e9d73f5 --- /dev/null +++ b/csf/cpanel/Driver/ConfigServercsf/META.pm @@ -0,0 +1,46 @@ +package Cpanel::Config::ConfigObj::Driver::ConfigServercsf::META; + +use strict; + +our $VERSION = 1.1; + +#use parent qw(Cpanel::Config::ConfigObj::Interface::Config::Version::v1); +sub spec_version { + return 1; +} + +sub meta_version { + return 1; +} + +sub get_driver_name { + return 'ConfigServercsf_driver'; +} + +sub content { + my ($locale_handle) = @_; + + my $content = { + 'vendor' => 'Jonathan Michaelson', + 'url' => 'www.configserver.com', + 'name' => { + 'short' => 'ConfigServercsf Driver', + 'long' => 'ConfigServercsf Driver', + 'driver' => get_driver_name(), + }, + 'since' => 'cPanel 11.38.1', + 'abstract' => "A ConfigServercsf driver", + 'version' => $VERSION, + }; + + if ($locale_handle) { + $content->{'abstract'} = $locale_handle->maketext("ConfigServer csf driver"); + } + + return $content; +} + +sub showcase { + return; +} +1; diff --git a/csf/cpanel/csf.cgi b/csf/cpanel/csf.cgi new file mode 100644 index 0000000..fa61547 --- /dev/null +++ b/csf/cpanel/csf.cgi @@ -0,0 +1,340 @@ +#!/usr/bin/perl +#WHMADDON:csf:ConfigServer Security & Firewall +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +## no critic (RequireUseWarnings, ProhibitExplicitReturnUndef, ProhibitMixedBooleanOperators, RequireBriefOpen) +use strict; +use File::Find; +use Fcntl qw(:DEFAULT :flock); +use Sys::Hostname qw(hostname); +use IPC::Open3; + +use lib '/usr/local/csf/lib'; +use ConfigServer::DisplayUI; +use ConfigServer::DisplayResellerUI; +use ConfigServer::Config; +use ConfigServer::Slurp qw(slurp); + +use lib '/usr/local/cpanel'; +require Cpanel::Form; +require Cpanel::Config; +require Whostmgr::ACLS; +require Cpanel::Rlimit; +require Cpanel::Template; +require Cpanel::Version::Tiny; +############################################################################### +# start main + +our ($reseller, $script, $images, %rprivs, $myv, %FORM); + +Whostmgr::ACLS::init_acls(); + +%FORM = Cpanel::Form::parseform(); + +my $config = ConfigServer::Config->loadconfig(); +my %config = $config->config; +my $slurpreg = ConfigServer::Slurp->slurpreg; +my $cleanreg = ConfigServer::Slurp->cleanreg; + +Cpanel::Rlimit::set_rlimit_to_infinity(); + +if (-e "/usr/local/cpanel/bin/register_appconfig") { + $script = "csf.cgi"; + $images = "csf"; +} else { + $script = "addon_csf.cgi"; + $images = "csf"; +} + +foreach my $line (slurp("/etc/csf/csf.resellers")) { + $line =~ s/$cleanreg//g; + my ($user,$alert,$privs) = split(/\:/,$line); + $privs =~ s/\s//g; + foreach my $priv (split(/\,/,$privs)) { + $rprivs{$user}{$priv} = 1; + } + $rprivs{$user}{ALERT} = $alert; +} + +$reseller = 0; +if (!Whostmgr::ACLS::hasroot()) { + if ($rprivs{$ENV{REMOTE_USER}}{USE}) { + $reseller = 1; + } else { + print "Content-type: text/html\r\n\r\n"; + print "You do not have access to this feature\n"; + exit(); + } +} + +open (my $IN, "<", "/etc/csf/version.txt") or die $!; +$myv = <$IN>; +close ($IN); +chomp $myv; + +my $bootstrapcss = ""; +my $jqueryjs = ""; +my $bootstrapjs = ""; + +my @header; +my @footer; +my $htmltag = "data-post='$FORM{action}'"; +if (-e "/etc/csf/csf.header") { + open (my $HEADER, "<", "/etc/csf/csf.header"); + flock ($HEADER, LOCK_SH); + @header = <$HEADER>; + close ($HEADER); +} +if (-e "/etc/csf/csf.footer") { + open (my $FOOTER, "<", "/etc/csf/csf.footer"); + flock ($FOOTER, LOCK_SH); + @footer = <$FOOTER>; + close ($FOOTER); +} +unless ($config{STYLE_CUSTOM}) { + undef @header; + undef @footer; + $htmltag = ""; +} + +my $thisapp = "csf"; +my $reregister; +my $modalstyle; +if ($Cpanel::Version::Tiny::major_version >= 65) { + if (-e "/usr/local/cpanel/whostmgr/docroot/cgi/configserver/${thisapp}/${thisapp}.conf") { + sysopen (my $CONF, "/usr/local/cpanel/whostmgr/docroot/cgi/configserver/${thisapp}/${thisapp}.conf", O_RDWR | O_CREAT); + flock ($CONF, LOCK_EX); + my @confdata = <$CONF>; + chomp @confdata; + for (0..scalar(@confdata)) { + if ($confdata[$_] =~ /^target=mainFrame/) { + $confdata[$_] = "target=_self"; + $reregister = 1; + } + } + if ($reregister) { + seek ($CONF, 0, 0); + truncate ($CONF, 0); + foreach (@confdata) { + print $CONF "$_\n"; + } + &printcmd("/usr/local/cpanel/bin/register_appconfig","/usr/local/cpanel/whostmgr/docroot/cgi/configserver/${thisapp}/${thisapp}.conf"); + $reregister = "

Updated application. The next time you login to WHM this will open within the native WHM main window instead of launching a separate window

\n"; + } + close ($CONF); + } +} + +print "Content-type: text/html\r\n\r\n"; +#if ($Cpanel::Version::Tiny::major_version < 65) {$modalstyle = "style='top:120px'"} + +my $templatehtml; +my $SCRIPTOUT; +unless ($FORM{action} eq "tailcmd" or $FORM{action} =~ /^cf/ or $FORM{action} eq "logtailcmd" or $FORM{action} eq "loggrepcmd") { +# open(STDERR, ">&STDOUT"); + open ($SCRIPTOUT, '>', \$templatehtml); + select $SCRIPTOUT; + + print < + + $jqueryjs + $bootstrapjs +\n"; + print @header; +} + +unless ($FORM{action} eq "tailcmd" or $FORM{action} =~ /^cf/ or $FORM{action} eq "logtailcmd" or $FORM{action} eq "loggrepcmd") { + print <
+
+

ConfigServer Security & Firewall - csf v$myv

+EOF + if ($reregister ne "") {print $reregister} +} + +#eval { +if ($reseller) { + ConfigServer::DisplayResellerUI::main(\%FORM, $script, 0, $images, $myv); +} else { + ConfigServer::DisplayUI::main(\%FORM, $script, 0, $images, $myv); +} +#}; +#if ($@) { +# print "Error during UI output generation: [$@]\n"; +# warn "Error during UI output generation: [$@]\n"; +#} + +unless ($FORM{action} eq "tailcmd" or $FORM{action} =~ /^cf/ or $FORM{action} eq "logtailcmd" or $FORM{action} eq "loggrepcmd") { + print < +function getCookie(cname) { + var name = cname + "="; + var ca = document.cookie.split(';'); + for(var i = 0; i 500) { + \$('#botlink').fadeIn(); + } else { + \$('#botlink').fadeOut(); + } + if (\$(this).scrollBottom() > 500) { + \$('#toplink').fadeIn(); + } else { + \$('#toplink').fadeOut(); + } + }); +EOF + if ($config{STYLE_MOBILE} or $reseller) { + print <\n"; + print @footer; +} +unless ($FORM{action} eq "tailcmd" or $FORM{action} =~ /^cf/ or $FORM{action} eq "logtailcmd" or $FORM{action} eq "loggrepcmd") { + close ($SCRIPTOUT); + select STDOUT; + Cpanel::Template::process_template( + 'whostmgr', + { + "template_file" => "${thisapp}.tmpl", + "${thisapp}_output" => $templatehtml, + "print" => 1, + } + ); +} +# end main +############################################################################### +## start printcmd +sub printcmd { + my @command = @_; + my ($childin, $childout); + my $pid = open3($childin, $childout, $childout, @command); + while (<$childout>) {print $_} + waitpid ($pid, 0); + return; +} +## end printcmd +############################################################################### + +1; diff --git a/csf/cpanel/csf.conf b/csf/cpanel/csf.conf new file mode 100644 index 0000000..8dbadc7 --- /dev/null +++ b/csf/cpanel/csf.conf @@ -0,0 +1,28 @@ +# name +name=csf + +# Service that will serve this app +service=whostmgr + +# Physical path: /usr/local/cpanel/3rdparty/Foo.php +# Literal URL path: $server:$port/$cpsession/3rdparty/Foo.php +url=/cgi/configserver/csf.cgi + +# System user to run process as +user=root + +# Required acls +acls=software-ConfigServer-csf + +# Display name as show in the service ui +displayname=ConfigServer Security & Firewall + +# Url to show in the service ui (relative to install path for whm this is cgi/) +entryurl=configserver/csf.cgi + +# Path to upgrade script +upgradecall=/usr/local/cpanel/whostmgr/docroot/cgi/configserver/csf/upgrade.sh + +icon=csf_small.png + +target=_self diff --git a/csf/cpanel/csf.tmpl b/csf/cpanel/csf.tmpl new file mode 100644 index 0000000..bbd9088 --- /dev/null +++ b/csf/cpanel/csf.tmpl @@ -0,0 +1,29 @@ +[% +USE Whostmgr; +USE JSON; + +WRAPPER 'master_templates/master.tmpl' + header = 'ConfigServer Security & Firewall' + skipsupport = 1 + skipheader = 1 + hide_license_warnings = 1 + theme='bootstrap' + breadcrumbdata = { + previous = [ + { + name = "Home", + url = "/scripts/command?PFILE=main", + }, + { + name = "Plugins", + url = "/scripts/command?PFILE=Plugins", + } + ], + name = 'ConfigServer Security & Firewall', + url = '/cgi/configserver/csf.cgi', + }; +%] + +[% csf_output %] + +[% END %] diff --git a/csf/cpanel/upgrade.sh b/csf/cpanel/upgrade.sh new file mode 100644 index 0000000..d7f75b1 --- /dev/null +++ b/csf/cpanel/upgrade.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +if [ -e "/usr/local/cpanel/bin/register_appconfig" ]; then + if [ -e "/usr/local/cpanel/whostmgr/docroot/cgi/addon_csf.cgi" ]; then + /bin/cp -af /usr/local/cpanel/whostmgr/docroot/cgi/configserver/csf/Driver/* /usr/local/cpanel/Cpanel/Config/ConfigObj/Driver/ + /bin/touch /usr/local/cpanel/Cpanel/Config/ConfigObj/Driver + /usr/local/cpanel/bin/register_appconfig /usr/local/cpanel/whostmgr/docroot/cgi/configserver/csf/csf.conf + + /bin/rm -f /usr/local/cpanel/whostmgr/docroot/cgi/addon_csf.cgi + /bin/rm -Rf /usr/local/cpanel/whostmgr/docroot/cgi/csf + fi +fi diff --git a/csf/cpanelalert.txt b/csf/cpanelalert.txt new file mode 100644 index 0000000..507230e --- /dev/null +++ b/csf/cpanelalert.txt @@ -0,0 +1,11 @@ +From: root +To: root +Subject: lfd on [hostname]: WHM/cPanel [user] access alert from [ip] + +Time: [time] +IP: [ip] +User: [user] + +Log line: + +[text] diff --git a/csf/csf.1.txt b/csf/csf.1.txt new file mode 100644 index 0000000..c1c5858 --- /dev/null +++ b/csf/csf.1.txt @@ -0,0 +1,284 @@ +.TH csf 1 +.SH NAME +csf \- ConfigServer & Security Firewall +.SH SYNOPSIS +.B csf [OPTIONS] +.SH DESCRIPTION +This manual documents the csf command line options for the ConfigServer & Security Firewall. See /etc/csf/csf.conf and /etc/csf/readme.txt for more detailed information on how to use and configure this application. +.SH OPTIONS +.TP +.B +-h, --help +Show this message +.TP +.B +-l, --status +List/Show the IPv4 iptables configuration +.TP +.B +-l6, --status6 +List/Show the IPv6 ip6tables configuration +.TP +.B +-s, --start +Start the firewall rules +.TP +.B +-f, --stop +Flush/Stop firewall rules (Note: lfd may restart csf) +.TP +.B +-r, --restart +Restart firewall rules (csf) +.TP +.B +-q, --startq +Quick restart (csf restarted by lfd) +.TP +.B +-sf, --startf +Force CLI restart regardless of LFDSTART setting +.TP +.B +-ra, --restartall +Restart firewall rules (csf) and then restart lfd daemon. Both csf and then lfd should be restarted after making any changes to the configuration files +.TP +.B +--lfd [\fIstop\fP|\fIstart\fP|\fIrestart\fP|\fIstatus\fP] +Actions to take with the lfd daemon +.TP +.B +-a, --add \fIip\fP [\fIcomment\fP] +Allow an IP and add to /etc/csf/csf.allow +.TP +.B +-ar, --addrm \fIip\fP +Remove an IP from /etc/csf/csf.allow and delete rule +.TP +.B +-d, --deny \fIip\fP [\fIcomment\fP] +Deny an IP and add to /etc/csf/csf.deny +.TP +.B +-dr, --denyrm \fIip\fP +Unblock an IP and remove from /etc/csf/csf.deny +.TP +.B +-df, --denyf +Remove and unblock all entries in /etc/csf/csf.deny +.TP +.B +-g, --grep \fIip\fP +Search the iptables and ip6tables rules for a match (e.g. IP, CIDR, Port Number) +.TP +.B +-i, --iplookup \fIip\fP +Lookup IP address geographical information using CC_LOOKUPS setting in /etc/csf/csf.conf +.TP +.B +-t, --temp +Displays the current list of temporary allow and deny IP entries with their TTL and comment +.TP +.B +-tr, --temprm \fIip\fP +Remove an IP from the temporary IP ban or allow list +.TP +.B +-trd, --temprmd \fIip\fP +Remove an IP from the temporary IP ban list only +.TP +.B +-tra, --temprma \fIip\fP +Remove an IP from the temporary IP allow list only +.TP +.B +-td, --tempdeny \fIip\fP \fIttl\fP [-p \fIport\fP] [-d \fIdirection\fP] [\fIcomment\fP] +Add an IP to the temp IP ban list. ttl is how long to blocks for (default:seconds, can use one suffix of h/m/d). Optional port. Optional direction of block can be one of: in, out or inout (default:in) +.TP +.B +-ta, --tempallow \fIip\fP \fIttl\fP [-p \fIport\fP] [-d \fIdirection\fP] [\fIcomment\fP] +Add an IP to the temp IP allow list (default:inout) +.TP +.B +-tf, --tempf +Flush all IPs from the temporary IP entries +.TP +.B +-cp, --cping +PING all members in an lfd Cluster +.TP +.B +-cg, --cgrep \fIip\fP +Requests the --grep output for IP from each member in an lfd Cluster +.TP +.B +-cd, --cdeny \fIip\fP [\fIcomment\fP] +Deny an IP in a Cluster and add to each remote /etc/csf/csf.deny +.TP +.B +-ctd, --ctempdeny \fIip\fP \fIttl\fP [-p \fIport\fP] [-d \fIdirection\fP] [\fIcomment\fP] +Add an IP in a Cluster to the temp IP ban list (default:in) +.TP +.B +-cr, --crm \fIip\fP +Unblock an IP in a Cluster and remove from each remote /etc/csf/csf.deny and temporary list +.TP +.B +-ca, --callow \fIip\fP [\fIcomment\fP] +Allow an IP in a Cluster and add to each remote /etc/csf/csf.allow +.TP +.B +-cta, --ctempallow \fIip\fP \fIttl\fP [-p \fIport\fP] [-d \fIdirection\fP] [\fIcomment\fP] +Add an IP in a Cluster to the temp IP allow list (default:in) +.TP +.B +-car, --carm \fIip\fP +Remove allowed IP in a Cluster and remove from each remote /etc/csf/csf.allow and temporary list +.TP +.B +-ci, --cignore \fIip\fP [\fIcomment\fP] +Ignore an IP in a Cluster and add to each remote /etc/csf/csf.ignore. Note: This will result in lfd being restarted +.TP +.B +-cir, --cirm \fIip\fP +Remove ignored IP in a Cluster and remove from each remote /etc/csf/csf.ignore. Note: This will result in lfd being restarted +.TP +.B +-cc, --cconfig [\fIname\fP] [\fIvalue\fP] +Change configuration option [name] to [value] in a Cluster +.TP +.B +-cf, --cfile [\fIfile\fP] +Send [file] in a Cluster to /etc/csf/ +.TP +.B +-crs, --crestart +Cluster restart csf and lfd +.TP +.B +--trace [\fIadd\fP|\fIremove\fP] \fIip\fP +Log SYN packets for an IP across iptables chains. Note, this can create a LOT of logging information in /var/log/messages so should only be used for a short period of time. This option requires the iptables TRACE module and access to the raw PREROUTING chain to function +.TP +.B +-m, --mail [\fIemail\fP] +Display Server Check in HTML or email to [email] if present +.TP +.B +--rbl [\fIemail\fP] +Process and display RBL Check in HTML or email to [email] if present +.TP +.B +-lr, --logrun +Initiate Log Scanner report via lfd +.TP +.B +-p, --ports +View ports on the server that have a running process behind them listening for external connections +.TP +.B +--graphs [\fIgraph type\fP] [\fIdirectory\fP] +Generate System Statistics html pages and images for a given graph type into a given directory. See ST_SYSTEM for requirements +.TP +.B +--profile [\fIcommand\fP] [\fIprofile\fP|\fIbackup\fP] [\fIprofile\fP|\fIbackup\fP] +Configuration profile functions for /etc/csf/csf.conf +.br +You can create your own profiles using the examples provided in /usr/local/csf/profiles/ +.br +The profile reset_to_defaults.conf is a special case and will always be the latest default csf.conf +.IP +.B +list +.br +Lists available profiles and backups +.IP +.B +apply [\fIprofile\fP] +.br +Modify csf.conf with Configuration Profile +.IP +.B +backup "\fIname\fP" +.br +Create Configuration Backup with optional "\fIname\fP" stored in /var/lib/csf/backup/ +.IP +.B +restore [\fIbackup\fP] +.br +Restore a Configuration Backup +.IP +.B +keep [\fInum\fP] +.br +Remove old Configuration Backups and keep the latest [\fInum\fP] +.IP +.B +diff [\fIprofile\fP|\fIbackup\fP] [\fIprofile\fP|\fIbackup\fP] +.br +Report differences between Configuration Profiles or Configuration Backups, only specify one [\fIprofile\fP|\fIbackup\fP] to compare to the current Configuration +.TP +.B +--mregen +MESSENGERV2 /etc/apache2/conf.d/csf_messenger.conf regeneration. This will also gracefully restart httpd +.TP +.B +--cloudflare [\fIcommand\fP] +Commands for interacting with the CloudFlare firewall. See /etc/csf/readme.txt and CF_ENABLE for more detailed information + +Note: target can be one of: An IP address; 2 letter Country Code; IP range CIDR. Only Enterprise customers can block a Country Code, but all can allow and challenge. IP range CIDR is limited to /16 and /24 +.IP +.B +list [\fIall\fP|\fIblock\fP|\fIchallenge\fP|\fIwhitelist\fP] [\fIuser1\fP,\fIuser2\fP,\fIdomain1\fP...] +.br +List specified type of CloudFlare Firewall rules for comma separated list of users/domains +.IP +.B +add [\fIblock\fP|\fIchallenge\fP|\fIwhitelist\fP] \fItarget\fP [\fIuser1\fP,\fIuser2\fP,\fIdomain1\fP...] +.br +Add CloudFlare Firewall rule action for target for comma separated list of users/domains only +.IP +.B +del \fItarget\fP [\fIuser1\fP,\fIuser2\fP,\fIdomain1\fP...] +.br +Delete CloudFlare Firewall rule for target for comma separated list of users/domains only +.IP +.B +tempadd [\fIallow\fP|\fIdeny\fP] \fIip\fP [\fIuser1\fP,\fIuser2\fP,\fIdomain1\fP...] +.br +Add a temporary block for CF_TEMP seconds to both csf and the CloudFlare Firewall rule for ip for comma separated list of users/domains as well as any user set to "any" +.TP +.B +-c, --check +Check for updates to csf but do not upgrade +.TP +.B +-u, --update +Check for updates to csf and upgrade if available +.TP +.B +-uf +Force an update of csf whether and upgrade is required or not +.TP +.B +-x, --disable +Disable csf and lfd completely +.TP +.B +-e, --enable +Enable csf and lfd if previously disabled +.TP +.B +-v, --version +Show csf version +.SH FILES +.I /etc/csf/csf.conf +.RS +The system wide configuration file +.RE +.I /etc/csf/readme.txt +.RS +Detailed information about csf and lfd +.SH BUGS +Report bugs on the forums at http://forum.configserver.com +.SH AUTHOR +(c)2006-2023, Jonathan Michaelson (http://www.configserver.com) diff --git a/csf/csf.allow b/csf/csf.allow new file mode 100644 index 0000000..77bf88f --- /dev/null +++ b/csf/csf.allow @@ -0,0 +1,33 @@ +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +# The following IP addresses will be allowed through iptables. +# One IP address per line. +# CIDR addressing allowed with a quaded IP (e.g. 192.168.254.0/24). +# Only list IP addresses, not domain names (they will be ignored) +# +# Advanced port+ip filtering allowed with the following format +# tcp/udp|in/out|s/d=port,port,...|s/d=ip +# See readme.txt for more information +# +# Note: IP addressess listed in this file will NOT be ignored by lfd, so they +# can still be blocked. If you do not want lfd to block an IP address you must +# add it to csf.ignore + +Include /etc/csf/cpanel.comodo.allow +Include /etc/csf/cpanel.allow diff --git a/csf/csf.blocklists b/csf/csf.blocklists new file mode 100644 index 0000000..90da66d --- /dev/null +++ b/csf/csf.blocklists @@ -0,0 +1,116 @@ +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +# This file contains definitions to IP BLOCK lists. +# +# Uncomment the line starting with the rule name to use it, then restart csf +# and then lfd +# +# Each block list must be listed on per line: as NAME|INTERVAL|MAX|URL +# NAME : List name with all uppercase alphabetic characters with no +# spaces and a maximum of 25 characters - this will be used as the +# iptables chain name +# INTERVAL: Refresh interval to download the list, must be a minimum of 3600 +# seconds (an hour), but 86400 (a day) should be more than enough +# MAX : This is the maximum number of IP addresses to use from the list, +# a value of 0 means all IPs +# URL : The URL to download the list from +# +# Note: Some of these lists may be very long and could cause serious network +# and/or performance issues unless you are using LF_IPSET in csf, so setting a +# value for the MAX field should be considered +# +# After making any changes to this file you must restart csf and then lfd +# +# If you want to redownload a blocklist you must first delete +# /var/lib/csf/csf.block.NAME and then restart csf and then lfd +# +# Each URL is scanned for an IP/CIDR address per line and if found is blocked +# +# The downloaded list can be a zip file. The zip file MUST only contain a +# single text file of a single IP/CIDR per line +# +# Note: CXS_ is a reserved prefix for the blocklist name and MUST NOT be used + +# Spamhaus Don't Route Or Peer List (DROP) +# Details: http://www.spamhaus.org/drop/ +#SPAMDROP|86400|0|http://www.spamhaus.org/drop/drop.txt + +# Spamhaus IPv6 Don't Route Or Peer List (DROPv6) +# Details: http://www.spamhaus.org/drop/ +#SPAMDROPV6|86400|0|https://www.spamhaus.org/drop/dropv6.txt + +# Spamhaus Extended DROP List (EDROP) +# Details: http://www.spamhaus.org/drop/ +#SPAMEDROP|86400|0|http://www.spamhaus.org/drop/edrop.txt + +# DShield.org Recommended Block List +# Details: https://dshield.org +#DSHIELD|86400|0|https://www.dshield.org/block.txt + +# TOR Exit Nodes List +# Set URLGET in csf.conf to use LWP as this list uses an SSL connection +# Details: https://trac.torproject.org/projects/tor/wiki/doc/TorDNSExitList +#TOR|86400|0|https://check.torproject.org/cgi-bin/TorBulkExitList.py?ip=1.2.3.4 + +# BOGON list +# Details: http://www.team-cymru.org/Services/Bogons/ +#BOGON|86400|0|http://www.cymru.com/Documents/bogon-bn-agg.txt + +# Project Honey Pot Directory of Dictionary Attacker IPs +# Details: http://www.projecthoneypot.org +#HONEYPOT|86400|0|https://www.projecthoneypot.org/list_of_ips.php?t=d&rss=1 + +# C.I. Army Malicious IP List +# Details: http://www.ciarmy.com +#CIARMY|86400|0|http://www.ciarmy.com/list/ci-badguys.txt + +# BruteForceBlocker IP List +# Details: http://danger.rulez.sk/index.php/bruteforceblocker/ +#BFB|86400|0|http://danger.rulez.sk/projects/bruteforceblocker/blist.php + +# MaxMind GeoIP Anonymous Proxies +# Set URLGET in csf.conf to use LWP as this list uses an SSL connection +# Details: https://www.maxmind.com/en/anonymous_proxies +#MAXMIND|86400|0|https://www.maxmind.com/en/anonymous_proxies + +# Blocklist.de +# Set URLGET in csf.conf to use LWP as this list uses an SSL connection +# Details: https://www.blocklist.de +# This first list only retrieves the IP addresses added in the last hour +#BDE|3600|0|https://api.blocklist.de/getlast.php?time=3600 +# This second list retrieves all the IP addresses added in the last 48 hours +# and is usually a very large list (over 10000 entries), so be sure that you +# have the resources available to use it +#BDEALL|86400|0|http://lists.blocklist.de/lists/all.txt + +# Stop Forum Spam +# Details: http://www.stopforumspam.com/downloads/ +# Many of the lists available contain a vast number of IP addresses so special +# care needs to be made when selecting from their lists +#STOPFORUMSPAM|86400|0|http://www.stopforumspam.com/downloads/listed_ip_1.zip + +# Stop Forum Spam IPv6 +# Details: http://www.stopforumspam.com/downloads/ +# Many of the lists available contain a vast number of IP addresses so special +# care needs to be made when selecting from their lists +#STOPFORUMSPAMV6|86400|0|http://www.stopforumspam.com/downloads/listed_ip_1_ipv6.zip + +# GreenSnow Hack List +# Details: https://greensnow.co +#GREENSNOW|86400|0|https://blocklist.greensnow.co/greensnow.txt diff --git a/csf/csf.c b/csf/csf.c new file mode 100644 index 0000000..74da25f --- /dev/null +++ b/csf/csf.c @@ -0,0 +1,85 @@ +/* + # Copyright (C) 2006-2025 Jonathan Michaelson + # + # https://github.com/waytotheweb/scripts + # + # This program is free software; you can redistribute it and/or modify it under + # the terms of the GNU General Public License as published by the Free Software + # Foundation; either version 3 of the License, or (at your option) any later + # version. + # + # This program is distributed in the hope that it will be useful, but WITHOUT + # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + # details. + # + # You should have received a copy of the GNU General Public License along with + # this program; if not, see . +*/ +#include +#include +#include +#include +#include +main () +{ + FILE *adminFile; + FILE *resellerFile; + uid_t ruid; + char name[100]; + struct passwd *pw; + int admin = 0; + int reseller = 0; + + setenv("CSF_RESELLER", "", 1); + ruid = getuid(); + pw = getpwuid(ruid); + + adminFile=fopen ("/usr/local/directadmin/data/admin/admin.list","r"); + if (adminFile!=NULL) + { + while(fgets(name,100,adminFile) != NULL) + { + int end = strlen(name) - 1; + if (end >= 0 && name[end] == '\n') name[end] = '\0'; + //printf("Name [%s]\n", name); + if (strcmp(pw->pw_name, name) == 0) admin = 1; + } + fclose(adminFile); + } + if (admin == 1) + { + setuid(0); + setgid(0); + + execv("/usr/local/directadmin/plugins/csf/exec/da_csf.cgi", NULL); + } else { + resellerFile=fopen ("/usr/local/directadmin/data/admin/reseller.list","r"); + if (resellerFile!=NULL) + { + while(fgets(name,100,resellerFile) != NULL) + { + int end = strlen(name) - 1; + if (end >= 0 && name[end] == '\n') name[end] = '\0'; + //printf("Name [%s]\n", name); + if (strcmp(pw->pw_name, name) == 0) + { + reseller = 1; + setenv("CSF_RESELLER", pw->pw_name, 1); + } + } + fclose(resellerFile); + } + if (reseller == 1) + { + setuid(0); + setgid(0); + + execv("/usr/local/directadmin/plugins/csf/exec/da_csf_reseller.cgi", NULL); + } else { + printf("Permission denied [User:%s UID:%d]\n", pw->pw_name, ruid); + } + } + + return 0; +} diff --git a/csf/csf.cloudflare b/csf/csf.cloudflare new file mode 100644 index 0000000..920f47e --- /dev/null +++ b/csf/csf.cloudflare @@ -0,0 +1,63 @@ +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +# This file contains configuration elements for the CF_ENABLE CloudFlare +# feature +# +# Entries: +# +# DOMAIN: +# These list the per domain CloudFlare credientials for each matching domain +# for all relevant triggers (i.e. LF_MODSEC) +# +# The special case "any" can be used as the domain name for all relevant +# triggers regardless of domain +# +# USER: +# This must be a unique name for the entry, but does not have to be a local +# linux account name +# +# CFACCOUNT: +# This is the CloudFlare login user (email address) +# +# CFAPIKEY: +# This is the CloudFlare Client API Key +# +# DISABLE: +# Normally, comment out a line to disable it. On servers with CF_CPANEL enabled +# a cPanel user can be disabled here +# +# ANY: +# On servers with CF_CPANEL enabled a cPanel user can be configured to use the +# special "any" case (see above) +# + +# CloudFlare client credientials for any domain triggered: +#DOMAIN:any:USER:myuser:CFACCOUNT:sales@hostsdomain.com:CFAPIKEY:12345abcdef6789 + +# CloudFlare client credientials for domain.com involved in trigger: +#DOMAIN:domain.com:USER:myuser:CFACCOUNT:sales@domain.com:CFAPIKEY:12345abcdef6789 + +# CloudFlare client credientials for domain2.com involved in trigger: +#DOMAIN:domain2.com:USER:myuser:CFACCOUNT:myuser@hotmail.com:CFAPIKEY:12345abcdef6789 + +# Disable CloudFlare cPanel user mycpanel from this feature: +#DISABLE:mycpanel + +# Enable a cPanel user mycpanel to use the "any" feature: +#ANY:mycpanel diff --git a/csf/csf.conf b/csf/csf.conf new file mode 100644 index 0000000..ad57ac5 --- /dev/null +++ b/csf/csf.conf @@ -0,0 +1,2825 @@ +############################################################################### +# SECTION:Initial Settings +############################################################################### +# Testing flag - enables a CRON job that clears iptables incase of +# configuration problems when you start csf. This should be enabled until you +# are sure that the firewall works - i.e. incase you get locked out of your +# server! Then do remember to set it to 0 and restart csf when you're sure +# everything is OK. Stopping csf will remove the line from /etc/crontab +# +# lfd will not start while this is enabled +TESTING = "1" + +# The interval for the crontab in minutes. Since this uses the system clock the +# CRON job will run at the interval past the hour and not from when you issue +# the start command. Therefore an interval of 5 minutes means the firewall +# will be cleared in 0-5 minutes from the firewall start +TESTING_INTERVAL = "5" + +# SECURITY WARNING +# ================ +# +# Unfortunately, syslog and rsyslog allow end-users to log messages to some +# system logs via the same unix socket that other local services use. This +# means that any log line shown in these system logs that syslog or rsyslog +# maintain can be spoofed (they are exactly the same as real log lines). +# +# Since some of the features of lfd rely on such log lines, spoofed messages +# can cause false-positive matches which can lead to confusion at best, or +# blocking of any innocent IP address or making the server inaccessible at +# worst. +# +# Any option that relies on the log entries in the files listed in +# /etc/syslog.conf and /etc/rsyslog.conf should therefore be considered +# vulnerable to exploitation by end-users and scripts run by end-users. +# +# NOTE: Not all log files are affected as they may not use syslog/rsyslog +# +# The option RESTRICT_SYSLOG disables all these features that rely on affected +# logs. These options are: +# LF_SSHD LF_FTPD LF_IMAPD LF_POP3D LF_BIND LF_SUHOSIN LF_SSH_EMAIL_ALERT +# LF_SU_EMAIL_ALERT LF_CONSOLE_EMAIL_ALERT LF_DISTATTACK LF_DISTFTP +# LT_POP3D LT_IMAPD PS_INTERVAL UID_INTERVAL WEBMIN_LOG LF_WEBMIN_EMAIL_ALERT +# PORTKNOCKING_ALERT LF_SUDO_EMAIL_ALERT +# +# This list of options use the logs but are not disabled by RESTRICT_SYSLOG: +# ST_ENABLE SYSLOG_CHECK LOGSCANNER CUSTOM*_LOG +# +# The following options are still enabled by default on new installations so +# that, on balance, csf/lfd still provides expected levels of security: +# LF_SSHD LF_FTPD LF_POP3D LF_IMAPD LF_SSH_EMAIL_ALERT LF_SU_EMAIL_ALERT +# +# If you set RESTRICT_SYSLOG to "0" or "2" and enable any of the options listed +# above, it should be done with the knowledge that any of the those options +# that are enabled could be triggered by spoofed log lines and lead to the +# server being inaccessible in the worst case. If you do not want to take that +# risk you should set RESTRICT_SYSLOG to "1" and those features will not work +# but you will not be protected from the exploits that they normally help block +# +# The recommended setting for RESTRICT_SYSLOG is "3" to restrict who can access +# the syslog/rsyslog unix socket. +# +# For further advice on how to help mitigate these issues, see +# /etc/csf/readme.txt +# +# 0 = Allow those options listed above to be used and configured +# 1 = Disable all the options listed above and prevent them from being used +# 2 = Disable only alerts about this feature and do nothing else +# 3 = Restrict syslog/rsyslog access to RESTRICT_SYSLOG_GROUP ** RECOMMENDED ** +RESTRICT_SYSLOG = "0" + +# The following setting is used if RESTRICT_SYSLOG is set to 3. It restricts +# write access to the syslog/rsyslog unix socket(s). The group must not already +# exists in /etc/group before setting RESTRICT_SYSLOG to 3, so set the option +# to a unique name for the server +# +# You can add users to this group by changing /etc/csf/csf.syslogusers and then +# restarting lfd afterwards. This will create the system group and add the +# users from csf.syslogusers if they exist to that group and will change the +# permissions on the syslog/rsyslog unix socket(s). The socket(s) will be +# monitored and the permissions re-applied should syslog/rsyslog be restarted +# +# Using this option will prevent some legitimate logging, e.g. end-user cron +# job logs +# +# If you want to revert RESTRICT_SYSLOG to another option and disable this +# feature, change the setting of RESTRICT_SYSLOG and then restart lfd and then +# syslog/rsyslog and the unix sockets will be reset +RESTRICT_SYSLOG_GROUP = "mysyslog" + +# This options restricts the ability to modify settings within this file from +# the csf UI. Should the parent control panel be compromised, these restricted +# options could be used to further compromise the server. For this reason we +# recommend leaving this option set to at least "1" and if any of the +# restricted items need to be changed, they are done so from the root shell +# +# 0 = Unrestricted UI +# 1 = Restricted UI +# 2 = Disabled UI +RESTRICT_UI = "1" + +# Enabling auto updates creates a cron job called /etc/cron.d/csf_update which +# runs once per day to see if there is an update to csf+lfd and upgrades if +# available and restarts csf and lfd +# +# You should check for new version announcements at http://blog.configserver.com +AUTO_UPDATES = "1" + +############################################################################### +# SECTION:IPv4 Port Settings +############################################################################### +# Lists of ports in the following comma separated lists can be added using a +# colon (e.g. 30000:35000). + +# Some kernel/iptables setups do not perform stateful connection tracking +# correctly (typically some virtual servers or custom compiled kernels), so a +# SPI firewall will not function correctly. If this happens, LF_SPI can be set +# to 0 to reconfigure csf as a static firewall. +# +# As connection tracking will not be configured, applications that rely on it +# will not function unless all outgoing ports are opened. Therefore, all +# outgoing connections will be allowed once all other tests have completed. So +# TCP_OUT, UDP_OUT and ICMP_OUT will not have any affect. +# +# If you allow incoming DNS lookups you may need to use the following +# directive in the options{} section of your named.conf: +# +# query-source port 53; +# +# This will force incoming DNS traffic only through port 53 +# +# Disabling this option will break firewall functionality that relies on +# stateful packet inspection (e.g. DNAT, PACKET_FILTER) and makes the firewall +# less secure +# +# This option should be set to "1" in all other circumstances +LF_SPI = "1" + +# Allow incoming TCP ports +TCP_IN = "20,21,22,25,53,80,110,143,443,465,587,853,993,995,2077,2078,2079,2080,2082,2083,2086,2087,2095,2096,8443" + +# Allow outgoing TCP ports +TCP_OUT = "20,21,22,25,37,43,53,80,110,113,443,587,853,873,993,995,2086,2087,2089,2703" + +# Allow incoming UDP ports +UDP_IN = "20,21,53,80,443,853" + +# Allow outgoing UDP ports +# To allow outgoing traceroute add 33434:33523 to this list +UDP_OUT = "20,21,53,113,123,853,873,6277,24441" + +# Allow incoming PING. Disabling PING will likely break external uptime +# monitoring +ICMP_IN = "1" + +# Set the per IP address incoming ICMP packet rate for PING requests. This +# ratelimits PING requests which if exceeded results in silently rejected +# packets. Disable or increase this value if you are seeing PING drops that you +# do not want +# +# To disable rate limiting set to "0", otherwise set according to the iptables +# documentation for the limit module. For example, "1/s" will limit to one +# packet per second +ICMP_IN_RATE = "1/s" + +# Allow outgoing PING +# +# Unless there is a specific reason, this option should NOT be disabled as it +# could break OS functionality +ICMP_OUT = "1" + +# Set the per IP address outgoing ICMP packet rate for PING requests. This +# ratelimits PING requests which if exceeded results in silently rejected +# packets. Disable or increase this value if you are seeing PING drops that you +# do not want +# +# Unless there is a specific reason, this option should NOT be enabled as it +# could break OS functionality +# +# To disable rate limiting set to "0", otherwise set according to the iptables +# documentation for the limit module. For example, "1/s" will limit to one +# packet per second +ICMP_OUT_RATE = "0" + +# For those with PCI Compliance tools that state that ICMP timestamps (type 13) +# should be dropped, you can enable the following option. Otherwise, there +# appears to be little evidence that it has anything to do with a security risk +# and can impact network performance, so should be left disabled by everyone +# else +ICMP_TIMESTAMPDROP = "0" + +############################################################################### +# SECTION:IPv6 Port Settings +############################################################################### +# IPv6: (Requires ip6tables) +# +# Pre v2.6.20 kernels do not perform stateful connection tracking, so a static +# firewall is configured as a fallback instead if IPV6_SPI is set to 0 below +# +# Supported: +# Temporary ACCEPT/DENY, GLOBAL_DENY, GLOBAL_ALLOW, SMTP_BLOCK, LF_PERMBLOCK, +# PACKET_FILTER, Advanced Allow/Deny Filters, RELAY_*, CLUSTER_*, CC6_LOOKUPS, +# SYNFLOOD, LF_NETBLOCK +# +# Supported if CC6_LOOKUPS and CC_LOOKUPS are enabled +# CC_DENY, CC_ALLOW, CC_ALLOW_FILTER, CC_IGNORE, CC_ALLOW_PORTS, CC_DENY_PORTS, +# CC_ALLOW_SMTPAUTH +# +# Supported if ip6tables >= 1.4.3: +# PORTFLOOD, CONNLIMIT +# +# Supported if ip6tables >= 1.4.17 and perl module IO::Socket::INET6 is +# installed: +# MESSENGER DOCKER SMTP_REDIRECT +# +# Not supported: +# ICMP_IN, ICMP_OUT +# +IPV6 = "0" + +# IPv6 uses icmpv6 packets very heavily. By default, csf will allow all icmpv6 +# traffic in the INPUT and OUTPUT chains. However, this could increase the risk +# of icmpv6 attacks. To restrict incoming icmpv6, set to "1" but may break some +# connection types +IPV6_ICMP_STRICT = "0" + +# Pre v2.6.20 kernel must set this option to "0" as no working state module is +# present, so a static firewall is configured as a fallback +# +# A workaround has been added for CentOS/RedHat v5 and custom kernels that do +# not support IPv6 connection tracking by opening ephemeral port range +# 32768:61000. This is only applied if IPV6_SPI is not enabled. This is the +# same workaround implemented by RedHat in the sample default IPv6 rules +# +# As connection tracking will not be configured, applications that rely on it +# will not function unless all outgoing ports are opened. Therefore, all +# outgoing connections will be allowed once all other tests have completed. So +# TCP6_OUT, UDP6_OUT and ICMP6_OUT will not have any affect. +# +# If you allow incoming ipv6 DNS lookups you may need to use the following +# directive in the options{} section of your named.conf: +# +# query-source-v6 port 53; +# +# This will force ipv6 incoming DNS traffic only through port 53 +# +# These changes are not necessary if the SPI firewall is used +IPV6_SPI = "1" + +# Allow incoming IPv6 TCP ports +TCP6_IN = "20,21,22,25,53,80,110,143,443,465,587,853,993,995,2077,2078,2082,2083,2086,2087,2095,2096,8443" + +# Allow outgoing IPv6 TCP ports +TCP6_OUT = "20,21,22,25,37,43,53,80,110,113,443,587,853,873,993,995,2086,2087,2089,2703" + +# Allow incoming IPv6 UDP ports +UDP6_IN = "20,21,53,80,443" + +# Allow outgoing IPv6 UDP ports +# To allow outgoing traceroute add 33434:33523 to this list +UDP6_OUT = "20,21,53,113,123,873,6277,24441" + +############################################################################### +# SECTION:General Settings +############################################################################### +# By default, csf will auto-configure iptables to filter all traffic except on +# the loopback device. If you only want iptables rules applied to a specific +# NIC, then list it here (e.g. eth1, or eth+) +ETH_DEVICE = "" + +# By adding a device to this option, ip6tables can be configured only on the +# specified device. Otherwise, ETH_DEVICE and then the default setting will be +# used +ETH6_DEVICE = "" + +# If you don't want iptables rules applied to specific NICs, then list them in +# a comma separated list (e.g "eth1,eth2") +ETH_DEVICE_SKIP = "" + +# This option should be enabled unless the kernel does not support the +# "conntrack" module +# +# To use the deprecated iptables "state" module, change this to 0 +USE_CONNTRACK = "1" + +# Enable ftp helper via the iptables CT target on supporting kernels (v2.6.34+) +# instead of the current method via /proc/sys/net/netfilter/nf_conntrack_helper +# This will also remove the RELATED target from the global state iptables rule +# +# This is not needed (and will be ignored) if LF_SPI/IPV6_SPI is disabled or +# the raw tables do not exist. The USE_CONNTRACK option should be enabled +# +# To enable this option, set it to your FTP server listening port number +# (normally 21), do NOT set it to "1" +USE_FTPHELPER = "0" + +# Check whether syslog is running. Many of the lfd checks require syslog to be +# running correctly. This test will send a coded message to syslog every +# SYSLOG_CHECK seconds. lfd will check SYSLOG_LOG log lines for the coded +# message. If it fails to do so within SYSLOG_CHECK seconds an alert using +# syslogalert.txt is sent +# +# A value of between 300 and 3600 seconds is suggested. Set to 0 to disable +SYSLOG_CHECK = "0" + +# Enable this option if you do not wish to block all IP's that have +# authenticated using POP before SMTP (i.e. are valid clients). This option +# checks for IP addresses in /etc/relayhosts, which last for 30 minutes in that +# file after a successful POP authentication. +# +# Set the value to 0 to disable the feature +RELAYHOSTS = "0" + +# Enable this option if you want lfd to ignore (i.e. don't block) IP addresses +# listed in csf.allow in addition to csf.ignore (the default). This option +# should be used with caution as it would mean that IP's allowed through the +# firewall from infected PC's could launch attacks on the server that lfd +# would ignore +IGNORE_ALLOW = "0" + +# Enable the following option if you want to apply strict iptables rules to DNS +# traffic (i.e. relying on iptables connection tracking). Enabling this option +# could cause DNS resolution issues both to and from the server but could help +# prevent abuse of the local DNS server +DNS_STRICT = "0" + +# Enable the following option if you want to apply strict iptables rules to DNS +# traffic between the server and the nameservers listed in /etc/resolv.conf +# Enabling this option could cause DNS resolution issues both to and from the +# server but could help prevent abuse of the local DNS server +DNS_STRICT_NS = "0" + +# Limit the number of IP's kept in the /etc/csf/csf.deny file +# +# Care should be taken when increasing this value on servers with low memory +# resources or hard limits (such as Virtuozzo/OpenVZ) as too many rules (in the +# thousands) can sometimes cause network slowdown +# +# The value set here is the maximum number of IPs/CIDRs allowed +# if the limit is reached, the entries will be rotated so that the oldest +# entries (i.e. the ones at the top) will be removed and the latest is added. +# The limit is only checked when using csf -d (which is what lfd also uses) +# Set to 0 to disable limiting +# +# For implementations wishing to set this value significantly higher, we +# recommend using the IPSET option +DENY_IP_LIMIT = "200" + +# Limit the number of IP's kept in the temprary IP ban list. If the limit is +# reached the oldest IP's in the ban list will be removed and allowed +# regardless of the amount of time remaining for the block +# Set to 0 to disable limiting +DENY_TEMP_IP_LIMIT = "100" + +# Enable login failure detection daemon (lfd). If set to 0 none of the +# following settings will have any effect as the daemon won't start. +LF_DAEMON = "1" + +# Check whether csf appears to have been stopped and restart if necessary, +# unless TESTING is enabled above. The check is done every 300 seconds +LF_CSF = "1" + +# This option uses IPTABLES_SAVE, IPTABLES_RESTORE and IP6TABLES_SAVE, +# IP6TABLES_RESTORE in two ways: +# +# 1. On a clean server reboot the entire csf iptables configuration is saved +# and then restored where possible to provide a near instant firewall +# startup[*] +# +# 2. On csf restart or lfd reloading tables, CC_* as well as SPAMHAUS, DSHIELD, +# BOGON, TOR are loaded using this method in a fraction of the time than if +# this setting is disabled +# +# [*]Not supported on all OS platforms +# +# Set to "0" to disable this functionality +FASTSTART = "1" + +# This option allows you to use ipset v6+ for the following csf options: +# CC_* and /etc/csf/csf.blocklist, /etc/csf/csf.allow, /etc/csf/csf.deny, +# GLOBAL_DENY, GLOBAL_ALLOW, DYNDNS, GLOBAL_DYNDNS, MESSENGER +# +# ipset will only be used with the above options when listing IPs and CIDRs. +# Advanced Allow Filters and temporary blocks use traditional iptables +# +# Using ipset moves the onus of ip matching against large lists away from +# iptables rules and to a purpose built and optimised database matching +# utility. It also simplifies the switching in of updated lists +# +# To use this option you must have a fully functioning installation of ipset +# installed either via rpm or source from http://ipset.netfilter.org/ +# +# Note: Using ipset has many advantages, some disadvantages are that you will +# no longer see packet and byte counts against IPs and it makes identifying +# blocked/allowed IPs that little bit harder +# +# Note: If you mainly use IP address only entries in csf.deny, you can increase +# the value of DENY_IP_LIMIT significantly if you wish +# +# Note: It's highly unlikely that ipset will function on Virtuozzo/OpenVZ +# containers even if it has been installed +# +# If you find any problems, please post on forums.configserver.com with full +# details of the issue +LF_IPSET = "0" + +# Versions of iptables greater or equal to v1.4.20 should support the --wait +# option. This forces iptables commands that use the option to wait until a +# lock by any other process using iptables completes, rather than simply +# failing +# +# Enabling this feature will add the --wait option to iptables commands +# +# NOTE: The disadvantage of using this option is that any iptables command that +# uses it will hang until the lock is released. This could cause a cascade of +# hung processes trying to issue iptables commands. To try and avoid this issue +# csf uses a last ditch timeout, WAITLOCK_TIMEOUT in seconds, that will trigger +# a failure if reached +WAITLOCK = "0" +WAITLOCK_TIMEOUT = "300" + +# The following sets the hashsize for ipset sets, which must be a power of 2. +# +# Note: Increasing this value will consume more memory for all sets +# Default: "1024" +LF_IPSET_HASHSIZE = "1024" + +# The following sets the maxelem for ipset sets. +# +# Note: Increasing this value will consume more memory for all sets +# Default: "65536" +LF_IPSET_MAXELEM = "65536" + +# If you enable this option then whenever a CLI request to restart csf is used +# lfd will restart csf instead within LF_PARSE seconds +# +# This feature can be helpful for restarting configurations that cannot use +# FASTSTART +LFDSTART = "0" + +# Enable verbose output of iptables commands +VERBOSE = "1" + +# Drop out of order packets and packets in an INVALID state in iptables +# connection tracking +PACKET_FILTER = "1" + +# Perform reverse DNS lookups on IP addresses. See also CC_LOOKUPS +LF_LOOKUPS = "1" + +# Custom styling is possible in the csf UI. See the readme.txt for more +# information under "UI skinning and Mobile View" +# +# This option enables the use of custom styling. If the styling fails to work +# correctly, e.g. custom styling does not take into account a change in the +# standard csf UI, then disabling this option will return the standard UI +STYLE_CUSTOM = "0" + +# This option disables the presence of the Mobile View in the csf UI +STYLE_MOBILE = "1" + +############################################################################### +# SECTION:SMTP Settings +############################################################################### +# Block outgoing SMTP except for root, exim and mailman (forces scripts/users +# to use the exim/sendmail binary instead of sockets access). This replaces the +# protection as WHM > Tweak Settings > SMTP Tweaks +# +# This option uses the iptables ipt_owner/xt_owner module and must be loaded +# for it to work. It may not be available on some VPS platforms +# +# Note: Run /etc/csf/csftest.pl to check whether this option will function on +# this server +SMTP_BLOCK = "0" + +# If SMTP_BLOCK is enabled but you want to allow local connections to port 25 +# on the server (e.g. for webmail or web scripts) then enable this option to +# allow outgoing SMTP connections to the loopback device +SMTP_ALLOWLOCAL = "1" + +# This option redirects outgoing SMTP connections destined for remote servers +# for non-bypass users to the local SMTP server to force local relaying of +# email. Such email may require authentication (SMTP AUTH) +SMTP_REDIRECT = "0" + +# This is a comma separated list of the ports to block. You should list all +# ports that exim is configured to listen on +SMTP_PORTS = "25,465,587" + +# Always allow the following comma separated users and groups to bypass +# SMTP_BLOCK +# +# Note: root (UID:0) is always allowed +SMTP_ALLOWUSER = "cpanel" +SMTP_ALLOWGROUP = "mail,mailman" + +# This option will only allow SMTP AUTH to be advertised to the IP addresses +# listed in /etc/csf/csf.smtpauth on EXIM mail servers +# +# The additional option CC_ALLOW_SMTPAUTH can be used with this option to +# additionally restrict access to specific countries +# +# This is to help limit attempts at distributed attacks against SMTP AUTH which +# are difficult to achieve since port 25 needs to be open to relay email +# +# The reason why this works is that if EXIM does not advertise SMTP AUTH on a +# connection, then SMTP AUTH will not accept logins, defeating the attacks +# without restricting mail relaying +# +# Note: csf and lfd must be restarted if /etc/csf/csf.smtpauth is modified so +# that the lookup file in /etc/exim.smtpauth is regenerated from the +# information from /etc/csf/csf.smtpauth plus any countries listed in +# CC_ALLOW_SMTPAUTH +# +# NOTE: To make this option work you MUST make the modifications to exim.conf +# as explained in "Exim SMTP AUTH Restriction" section in /etc/csf/readme.txt +# after enabling the option here, otherwise this option will not work +# +# To enable this option, set to 1 and make the exim configuration changes +# To disable this option, set to 0 and undo the exim configuration changes +SMTPAUTH_RESTRICT = "0" + +############################################################################### +# SECTION:Port Flood Settings +############################################################################### +# Enable SYN Flood Protection. This option configures iptables to offer some +# protection from tcp SYN packet DOS attempts. You should set the RATE so that +# false-positives are kept to a minimum otherwise visitors may see connection +# issues (check /var/log/messages for *SYNFLOOD Blocked*). See the iptables +# man page for the correct --limit rate syntax +# +# Note: This option should ONLY be enabled if you know you are under a SYN +# flood attack as it will slow down all new connections from any IP address to +# the server if triggered +SYNFLOOD = "0" +SYNFLOOD_RATE = "100/s" +SYNFLOOD_BURST = "150" + +# Connection Limit Protection. This option configures iptables to offer more +# protection from DOS attacks against specific ports. It can also be used as a +# way to simply limit resource usage by IP address to specific server services. +# This option limits the number of concurrent new connections per IP address +# that can be made to specific ports +# +# This feature does not work on servers that do not have the iptables module +# xt_connlimit loaded. Typically, this will be with MONOLITHIC kernels. VPS +# server admins should check with their VPS host provider that the iptables +# module is included +# +# For further information and syntax refer to the Connection Limit Protection +# section of the csf readme.txt +# +# Note: Run /etc/csf/csftest.pl to check whether this option will function on +# this server +CONNLIMIT = "" + +# Port Flood Protection. This option configures iptables to offer protection +# from DOS attacks against specific ports. This option limits the number of +# new connections per time interval that can be made to specific ports +# +# This feature does not work on servers that do not have the iptables module +# ipt_recent loaded. Typically, this will be with MONOLITHIC kernels. VPS +# server admins should check with their VPS host provider that the iptables +# module is included +# +# For further information and syntax refer to the Port Flood Protection +# section of the csf readme.txt +# +# Note: Run /etc/csf/csftest.pl to check whether this option will function on +# this server +PORTFLOOD = "" + +# Outgoing UDP Flood Protection. This option limits outbound UDP packet floods. +# These typically originate from exploit scripts uploaded through vulnerable +# web scripts. Care should be taken on servers that use services that utilise +# high levels of UDP outbound traffic, such as SNMP, so you may need to alter +# the UDPFLOOD_LIMIT and UDPFLOOD_BURST options to suit your environment +# +# We recommend enabling User ID Tracking (UID_INTERVAL) with this feature +UDPFLOOD = "0" +UDPFLOOD_LIMIT = "100/s" +UDPFLOOD_BURST = "500" + +# This is a list of usernames that should not be rate limited, such as "named" +# to prevent bind traffic from being limited. +# +# Note: root (UID:0) is always allowed +UDPFLOOD_ALLOWUSER = "named" + +############################################################################### +# SECTION:Logging Settings +############################################################################### +# Log lfd messages to SYSLOG in addition to /var/log/lfd.log. You must have the +# perl module Sys::Syslog installed to use this feature +SYSLOG = "0" + +# Drop target for incoming iptables rules. This can be set to either DROP or +# REJECT. REJECT will send back an error packet, DROP will not respond at all. +# REJECT is more polite, however it does provide extra information to a hacker +# and lets them know that a firewall is blocking their attempts. DROP hangs +# their connection, thereby frustrating attempts to port scan the server +DROP = "DROP" + +# Drop target for outgoing iptables rules. This can be set to either DROP or +# REJECT as with DROP, however as such connections are from this server it is +# better to REJECT connections to closed ports rather than to DROP them. This +# helps to immediately free up server resources rather than tying them up until +# a connection times out. It also tells the process making the connection that +# it has immediately failed +# +# It is possible that some monolithic kernels may not support the REJECT +# target. If this is the case, csf checks before using REJECT and falls back to +# using DROP, issuing a warning to set this to DROP instead +DROP_OUT = "REJECT" + +# Enable logging of dropped connections to blocked ports to syslog, usually +# /var/log/messages. This option needs to be enabled to use Port Scan Tracking +DROP_LOGGING = "1" + +# Enable logging of dropped incoming connections from blocked IP addresses +# +# This option will be disabled if you enable Port Scan Tracking (PS_INTERVAL) +DROP_IP_LOGGING = "0" + +# Enable logging of dropped outgoing connections +# +# Note: Only outgoing SYN packets for TCP connections are logged, other +# protocols log all packets +# +# We recommend that you enable this option +DROP_OUT_LOGGING = "1" + +# Together with DROP_OUT_LOGGING enabled, this option logs the UID connecting +# out (where available) which can help track abuse +DROP_UID_LOGGING = "1" + +# Only log incoming reserved port dropped connections (0:1023). This can reduce +# the amount of log noise from dropped connections, but will affect options +# such as Port Scan Tracking (PS_INTERVAL) +DROP_ONLYRES = "0" + +# Commonly blocked ports that you do not want logging as they tend to just fill +# up the log file. These ports are specifically blocked (applied to TCP and UDP +# protocols) for incoming connections +DROP_NOLOG = "23,67,68,111,113,135:139,445,500,513,520" + +# Log packets dropped by the packet filtering option PACKET_FILTER +DROP_PF_LOGGING = "0" + +# Log packets dropped by the Connection Limit Protection option CONNLIMIT. If +# this is enabled and Port Scan Tracking (PS_INTERVAL) is also enabled, IP +# addresses breaking the Connection Limit Protection will be blocked +CONNLIMIT_LOGGING = "0" + +# Enable logging of UDP floods. This should be enabled, especially with User ID +# Tracking enabled +UDPFLOOD_LOGGING = "1" + +# Send an alert if log file flooding is detected which causes lfd to skip log +# lines to prevent lfd from looping. If this alert is sent you should check the +# reported log file for the reason for the flooding +LOGFLOOD_ALERT = "0" + +############################################################################### +# SECTION:Reporting Settings +############################################################################### +# By default, lfd will send alert emails using the relevant alert template to +# the To: address configured within that template. Setting the following +# option will override the configured To: field in all lfd alert emails +# +# Leave this option empty to use the To: field setting in each alert template +LF_ALERT_TO = "" + +# By default, lfd will send alert emails using the relevant alert template from +# the From: address configured within that template. Setting the following +# option will override the configured From: field in all lfd alert emails +# +# Leave this option empty to use the From: field setting in each alert template +LF_ALERT_FROM = "" + +# By default, lfd will send all alerts using the SENDMAIL binary. To send using +# SMTP directly, you can set the following to a relaying SMTP server, e.g. +# "127.0.0.1". Leave this setting blank to use SENDMAIL +LF_ALERT_SMTP = "" + +# Block Reporting. lfd can run an external script when it performs and IP +# address block following for example a login failure. The following setting +# is to the full path of the external script which must be executable. See +# readme.txt for format details +# +# Leave this setting blank to disable +BLOCK_REPORT = "" + +# To also run an external script when a temporary block is unblocked: the +# following setting can be the full path of the external script which must be +# executable. See readme.txt for format details +# +# Leave this setting blank to disable +UNBLOCK_REPORT = "" + +# In addition to the standard lfd email alerts, you can additionally enable the +# sending of X-ARF reports (see http://www.xarf.org/specification.html). Only +# block alert messages will be sent. The reports use our schema at: +# https://download.configserver.com/abuse_login-attack_0.2.json +# +# These reports are in a format accepted by many Netblock owners and should +# help them investigate abuse. This option is not designed to automatically +# forward these reports to the Netblock owners and should be checked for +# false-positive blocks before reporting +# +# If available, the report will also include the abuse contact for the IP from +# the Abusix Contact DB: https://abusix.com/contactdb.html +# +# Note: The following block types are not reported through this feature: +# LF_PERMBLOCK, LF_NETBLOCK, LF_DISTATTACK, LF_DISTFTP, RT_*_ALERT +X_ARF = "0" + +# By default, lfd will send emails from the root forwarder. Setting the +# following option will override this +X_ARF_FROM = "" + +# By default, lfd will send emails to the root forwarder. Setting the following +# option will override this +X_ARF_TO = "" + +# If you want to automatically send reports to the abuse contact where found, +# you can enable the following option +# +# Note: You MUST set X_ARF_FROM to a valid email address for this option to +# work. This is so that the abuse contact can reply to the report +# +# However, you should be aware that without manual checking you could be +# reporting innocent IP addresses, including your own clients, yourself and +# your own servers +# +# Additionally, just because a contact address is found, does not mean that +# there is anyone on the end of it reading, processing or acting on such +# reports and you could conceivably reported for sending spam +# +# We do not recommend enabling this option. Abuse reports should be checked and +# verified before being forwarded to the abuse contact +X_ARF_ABUSE = "0" + +############################################################################### +# SECTION:Temp to Perm/Netblock Settings +############################################################################### +# Temporary to Permanent IP blocking. The following enables this feature to +# permanently block IP addresses that have been temporarily blocked more than +# LF_PERMBLOCK_COUNT times in the last LF_PERMBLOCK_INTERVAL seconds. Set +# LF_PERMBLOCK to "1" to enable this feature +# +# Care needs to be taken when setting LF_PERMBLOCK_INTERVAL as it needs to be +# at least LF_PERMBLOCK_COUNT multiplied by the longest temporary time setting +# (TTL) for blocked IPs, to be effective +# +# Set LF_PERMBLOCK to "0" to disable this feature +LF_PERMBLOCK = "1" +LF_PERMBLOCK_INTERVAL = "86400" +LF_PERMBLOCK_COUNT = "4" +LF_PERMBLOCK_ALERT = "1" + +# Permanently block IPs by network class. The following enables this feature +# to permanently block classes of IP address where individual IP addresses +# within the same class LF_NETBLOCK_CLASS have already been blocked more than +# LF_NETBLOCK_COUNT times in the last LF_NETBLOCK_INTERVAL seconds. Set +# LF_NETBLOCK to "1" to enable this feature +# +# This can be an affective way of blocking DDOS attacks launched from within +# the same network class +# +# Valid settings for LF_NETBLOCK_CLASS are "A", "B" and "C", care and +# consideration is required when blocking network classes A or B +# +# Set LF_NETBLOCK to "0" to disable this feature +LF_NETBLOCK = "0" +LF_NETBLOCK_INTERVAL = "86400" +LF_NETBLOCK_COUNT = "4" +LF_NETBLOCK_CLASS = "C" +LF_NETBLOCK_ALERT = "1" + +# Valid settings for LF_NETBLOCK_IPV6 are "/64", "/56", "/48", "/32" and "/24" +# Great care should be taken with IPV6 netblock ranges due to the large number +# of addresses involved +# +# To disable IPv6 netblocks set to "" +LF_NETBLOCK_IPV6 = "" + +############################################################################### +# SECTION:Global Lists/DYNDNS/Blocklists +############################################################################### +# Safe Chain Update. If enabled, all dynamic update chains (GALLOW*, GDENY*, +# SPAMHAUS, DSHIELD, BOGON, CC_ALLOW, CC_DENY, ALLOWDYN*) will create a new +# chain when updating, and insert it into the relevant LOCALINPUT/LOCALOUTPUT +# chain, then flush and delete the old dynamic chain and rename the new chain. +# +# This prevents a small window of opportunity opening when an update occurs and +# the dynamic chain is flushed for the new rules. +# +# This option should not be enabled on servers with long dynamic chains (e.g. +# CC_DENY/CC_ALLOW lists) and low memory. It should also not be enabled on +# Virtuozzo VPS servers with a restricted numiptent value. This is because each +# chain will effectively be duplicated while the update occurs, doubling the +# number of iptables rules +SAFECHAINUPDATE = "0" + +# If you wish to allow access from dynamic DNS records (for example if your IP +# address changes whenever you connect to the internet but you have a dedicated +# dynamic DNS record from the likes of dyndns.org) then you can list the FQDN +# records in csf.dyndns and then set the following to the number of seconds to +# poll for a change in the IP address. If the IP address has changed iptables +# will be updated. +# +# If the FQDN has multiple A records then all of the IP addresses will be +# processed. If IPV6 is enabled, then all IPv6 AAAA IP address records will +# also be allowed. +# +# A setting of 600 would check for IP updates every 10 minutes. Set the value +# to 0 to disable the feature +DYNDNS = "0" + +# To always ignore DYNDNS IP addresses in lfd blocking, set the following +# option to 1 +DYNDNS_IGNORE = "0" + +# The follow Global options allow you to specify a URL where csf can grab a +# centralised copy of an IP allow or deny block list of your own. You need to +# specify the full URL in the following options, i.e.: +# http://www.somelocation.com/allow.txt +# +# The actual retrieval of these IP's is controlled by lfd, so you need to set +# LF_GLOBAL to the interval (in seconds) when you want lfd to retrieve. lfd +# will perform the retrieval when it runs and then again at the specified +# interval. A sensible interval would probably be every 3600 seconds (1 hour). +# A minimum value of 300 is enforced for LF_GLOBAL if enabled +# +# You do not have to specify both an allow and a deny file +# +# You can also configure a global ignore file for IP's that lfd should ignore +LF_GLOBAL = "0" + +GLOBAL_ALLOW = "" +GLOBAL_DENY = "" +GLOBAL_IGNORE = "" + +# Provides the same functionality as DYNDNS but with a GLOBAL URL file. Set +# this to the URL of the file containing DYNDNS entries +GLOBAL_DYNDNS = "" + +# Set the following to the number of seconds to poll for a change in the IP +# address resoved from GLOBAL_DYNDNS +GLOBAL_DYNDNS_INTERVAL = "600" + +# To always ignore GLOBAL_DYNDNS IP addresses in lfd blocking, set the following +# option to 1 +GLOBAL_DYNDNS_IGNORE = "0" + +# Blocklists are controlled by modifying /etc/csf/csf.blocklists +# +# If you don't want BOGON rules applied to specific NICs, then list them in +# a comma separated list (e.g "eth1,eth2") +LF_BOGON_SKIP = "" + +# The following option can be used to select the method csf will use to +# retrieve URL data and files +# +# This can be set to use: +# +# 1. Perl module HTTP::Tiny +# 2. Perl module LWP::UserAgent +# 3. CURL/WGET (set location at the bottom of csf.conf if installed) +# +# HTTP::Tiny is much faster than LWP::UserAgent and is included in the csf +# distribution. LWP::UserAgent may have to be installed manually, but it can +# better support https:// URL's which also needs the LWP::Protocol::https perl +# module +# +# CURL/WGET uses the system binaries if installed but does not always provide +# good feedback when it fails. The script will first look for CURL, if that +# does not exist at the configured location it will then look for WGET +# +# Additionally, 1 or 2 are used and the retrieval fails, then if either CURL or +# WGET are available, an additional attempt will be using CURL/WGET. This is +# useful if the perl distribution has outdated modules that do not support +# modern SSL/TLS implementations +# +# To install the LWP perl modules required: +# +# On rpm based systems: +# +# yum install perl-libwww-perl.noarch perl-LWP-Protocol-https.noarch +# +# On APT based systems: +# +# apt-get install libwww-perl liblwp-protocol-https-perl +# +# Via cpan: +# +# perl -MCPAN -eshell +# cpan> install LWP LWP::Protocol::https +# +# We recommend setting this set to "2" or "3" as upgrades to csf will be +# performed over SSL as well as other URLs used when retrieving external data +# +# "1" = HTTP::Tiny +# "2" = LWP::UserAgent +# "3" = CURL/WGET (set location at the bottom of csf.conf) +URLGET = "2" + +# If you need csf/lfd to use a proxy, then you can set this option to the URL +# of the proxy. The proxy provided will be used for both HTTP and HTTPS +# connections +URLPROXY = "" + +############################################################################### +# SECTION:Country Code Lists and Settings +############################################################################### +# Country Code to CIDR allow/deny. In the following options you can allow or +# deny whole country CIDR ranges. The CIDR blocks are obtained from a selected +# source below. They also display Country Code Country and City for reported IP +# addresses and lookups +# +# There are a number of sources for these databases, before utilising them you +# need to visit each site and ensure you abide by their license provisions +# where stated: + +# 1. MaxMind +# +# MaxMind GeoLite2 Country/City and ASN databases at: +# https://dev.MaxMind.com/geoip/geoip2/geolite2/ +# This feature relies entirely on that service being available +# +# Advantages: This is a one stop shop for all of the databases required for +# these features. They provide a consistent dataset for blocking and reporting +# purposes +# +# Disadvantages: MaxMind require a license key to download their databases. +# This is free of charge, but requires the user to create an account on their +# website to generate the required key: +# +# WARNING: As of 2019-12-29, MaxMind REQUIRES you to create an account on their +# site and to generate a license key to use their databases. See: +# https://www.maxmind.com/en/geolite2/signup +# https://blog.maxmind.com/2019/12/18/significant-changes-to-accessing-and-using-geolite2-databases/ +# +# You MUST set the following to continue using the IP lookup features of csf, +# otherwise an error will be generated and the features will not work. +# Alternatively set CC_SRC below to a different provider +# +# MaxMind License Key: +MM_LICENSE_KEY = "" + +# 2. DB-IP, ipdeny.com, iptoasn.com +# +# Advantages: The ipdeny.com databases form CC blocking are better optimised +# and so are quicker to process and create fewer iptables entries. All of these +# databases are free to download without requiring login or key +# +# Disadvantages: Multiple sources mean that any one of the three could +# interrupt the provision of these features. It may also mean that there are +# inconsistences between them +# +# https://db-ip.com/db/lite.php +# http://ipdeny.com/ +# https://iptoasn.com/ +# http://download.geonames.org/export/dump/readme.txt + +# Set the following to your preferred source: +# +# "1" - MaxMind +# "2" - db-ip, ipdeny, iptoasn +# +# The default is "2" on new installations of csf, or set to "1" to use the +# MaxMind databases after obtaining a license key +CC_SRC = "2" + +# In the following options, specify the the two-letter ISO Country Code(s). +# The iptables rules are for incoming connections only +# +# Additionally, ASN numbers can also be added to the comma separated lists +# below that also list Country Codes. The same WARNINGS for Country Codes apply +# to the use of ASNs. More about Autonomous System Numbers (ASN): +# http://www.iana.org/assignments/as-numbers/as-numbers.xhtml +# ASNs must be listed as ASnnnn (where nnnn is the ASN number) +# +# You should consider using LF_IPSET when using any of the following options +# +# WARNING: These lists are never 100% accurate and some ISP's (e.g. AOL) use +# non-geographic IP address designations for their clients +# +# WARNING: Some of the CIDR lists are huge and each one requires a rule within +# the incoming iptables chain. This can result in significant performance +# overheads and could render the server inaccessible in some circumstances. For +# this reason (amongst others) we do not recommend using these options +# +# WARNING: Due to the resource constraints on VPS servers this feature should +# not be used on such systems unless you choose very small CC zones +# +# WARNING: CC_ALLOW allows access through all ports in the firewall. For this +# reason CC_ALLOW probably has very limited use and CC_ALLOW_FILTER is +# preferred +# +# Each option is a comma separated list of CC's, e.g. "US,GB,DE" +CC_DENY = "" +CC_ALLOW = "" + +# An alternative to CC_ALLOW is to only allow access from the following +# countries but still filter based on the port and packets rules. All other +# connections are dropped +CC_ALLOW_FILTER = "" + +# This option allows access from the following countries to specific ports +# listed in CC_ALLOW_PORTS_TCP and CC_ALLOW_PORTS_UDP +# +# Note: The rules for this feature are inserted after the allow and deny +# rules to still allow blocking of IP addresses +# +# Each option is a comma separated list of CC's, e.g. "US,GB,DE" +CC_ALLOW_PORTS = "" + +# All listed ports should be removed from TCP_IN/UDP_IN to block access from +# elsewhere. This option uses the same format as TCP_IN/UDP_IN +# +# An example would be to list port 21 here and remove it from TCP_IN/UDP_IN +# then only countries listed in CC_ALLOW_PORTS can access FTP +CC_ALLOW_PORTS_TCP = "" +CC_ALLOW_PORTS_UDP = "" + +# This option denies access from the following countries to specific ports +# listed in CC_DENY_PORTS_TCP and CC_DENY_PORTS_UDP +# +# Note: The rules for this feature are inserted after the allow and deny +# rules to still allow allowing of IP addresses +# +# Each option is a comma separated list of CC's, e.g. "US,GB,DE" +CC_DENY_PORTS = "" + +# This option uses the same format as TCP_IN/UDP_IN. The ports listed should +# NOT be removed from TCP_IN/UDP_IN +# +# An example would be to list port 21 here then countries listed in +# CC_DENY_PORTS cannot access FTP +CC_DENY_PORTS_TCP = "" +CC_DENY_PORTS_UDP = "" + +# This Country Code list will prevent lfd from blocking IP address hits for the +# listed CC's +# +# CC_LOOKUPS must be enabled to use this option +CC_IGNORE = "" + +# This Country Code list will only allow SMTP AUTH to be advertised to the +# listed countries in EXIM. This is to help limit attempts at distributed +# attacks against SMTP AUTH which are difficult to achive since port 25 needs +# to be open to relay email +# +# The reason why this works is that if EXIM does not advertise SMTP AUTH on a +# connection, then SMTP AUTH will not accept logins, defeating the attacks +# without restricting mail relaying +# +# This option can generate a very large list of IP addresses that could easily +# severely impact on SMTP (mail) performance, so care must be taken when +# selecting countries and if performance issues ensue +# +# The option SMTPAUTH_RESTRICT must be enabled to use this option +CC_ALLOW_SMTPAUTH = "" + +# These options can control which IP blocks are redirected to the MESSENGER +# service, if it is enabled +# +# If Country Codes are listed in CC_MESSENGER_ALLOW, then only a blocked IP +# that resolves to one of those Country Codes will be redirected to the +# MESSENGER service +# +# If Country Codes are listed in CC_MESSENGER_DENY, then a blocked IP that +# resolves to one of those Country Codes will NOT be redirected to the +# MESSENGER service +# +CC_MESSENGER_ALLOW = "" +CC_MESSENGER_DENY = "" + +# Set this option to a valid CIDR (i.e. 1 to 32) to ignore CIDR blocks smaller +# than this value when implementing CC_DENY/CC_ALLOW/CC_ALLOW_FILTER. This can +# help reduce the number of CC entries and may improve iptables throughput. +# Obviously, this will deny/allow fewer IP addresses depending on how small you +# configure the option +# +# For example, to ignore all CIDR (and single IP) entries small than a /16, set +# this option to "16". Set to "" to block all CC IP addresses +CC_DROP_CIDR = "" + +# Display Country Code and Country for reported IP addresses. This option can +# be configured to use the databases enabled at the top of this section. An +# additional option is also available if you cannot use those databases: +# +# "0" - disable +# "1" - Reports: Country Code and Country +# "2" - Reports: Country Code and Country and Region and City +# "3" - Reports: Country Code and Country and Region and City and ASN +# "4" - Reports: Country Code and Country and Region and City (db-ip.com) +# +# Note: "4" does not use the databases enabled at the top of this section +# directly for lookups. Instead it uses a URL-based lookup from +# https://db-ip.com and so avoids having to download and process the large +# databases. Please visit the https://db-ip.com and read their limitations and +# understand that this option will either cease to function or be removed by us +# if that site is abused or overloaded. ONLY use this option if you have +# difficulties using the databases enabled at the top of this section. This +# option is ONLY for IP lookups, NOT when using the CC_* options above, which +# will continue to use the databases enabled at the top of this section +# +CC_LOOKUPS = "1" + +# Display Country Code and Country for reported IPv6 addresses using the +# databases enabled at the top of this section +# +# "0" - disable +# "1" - enable and report the detail level as specified in CC_LOOKUPS +# +# This option must also be enabled to allow IPv6 support to CC_*, MESSENGER and +# PORTFLOOD +CC6_LOOKUPS = "0" + +# This option tells lfd how often to retrieve the databases for CC_ALLOW, +# CC_ALLOW_FILTER, CC_DENY, CC_IGNORE and CC_LOOKUPS (in days) +CC_INTERVAL = "14" + +############################################################################### +# SECTION:Login Failure Blocking and Alerts +############################################################################### +# The following[*] triggers are application specific. If you set LF_TRIGGER to +# "0" the value of each trigger is the number of failures against that +# application that will trigger lfd to block the IP address +# +# If you set LF_TRIGGER to a value greater than "0" then the following[*] +# application triggers are simply on or off ("0" or "1") and the value of +# LF_TRIGGER is the total cumulative number of failures that will trigger lfd +# to block the IP address +# +# Setting the application trigger to "0" disables it +LF_TRIGGER = "0" + +# If LF_TRIGGER is > "0" then LF_TRIGGER_PERM can be set to "1" to permanently +# block the IP address, or LF_TRIGGER_PERM can be set to a value greater than +# "1" and the IP address will be blocked temporarily for that value in seconds. +# For example: +# LF_TRIGGER_PERM = "1" => the IP is blocked permanently +# LF_TRIGGER_PERM = "3600" => the IP is blocked temporarily for 1 hour +# +# If LF_TRIGGER is "0", then the application LF_[application]_PERM value works +# in the same way as above and LF_TRIGGER_PERM serves no function +LF_TRIGGER_PERM = "1" + +# To only block access to the failed application instead of a complete block +# for an ip address, you can set the following to "1", but LF_TRIGGER must be +# set to "0" with specific application[*] trigger levels also set appropriately +# +# The ports that are blocked can be configured by changing the PORTS_* options +LF_SELECT = "0" + +# Send an email alert if an IP address is blocked by one of the [*] triggers +LF_EMAIL_ALERT = "1" + +# Send an email alert if an IP address is only temporarily blocked by one of +# the [*] triggers +# +# Note: LF_EMAIL_ALERT must still be enabled to get permanent block emails +LF_TEMP_EMAIL_ALERT = "1" + +# [*]Enable login failure detection of sshd connections +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_SSHD = "5" +LF_SSHD_PERM = "1" + +# [*]Enable login failure detection of ftp connections +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_FTPD = "10" +LF_FTPD_PERM = "1" + +# [*]Enable login failure detection of SMTP AUTH connections +LF_SMTPAUTH = "5" +LF_SMTPAUTH_PERM = "1" + +# [*]Enable syntax failure detection of Exim connections +LF_EXIMSYNTAX = "10" +LF_EXIMSYNTAX_PERM = "1" + +# [*]Enable login failure detection of pop3 connections +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_POP3D = "10" +LF_POP3D_PERM = "1" + +# [*]Enable login failure detection of imap connections +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_IMAPD = "10" +LF_IMAPD_PERM = "1" + +# [*]Enable login failure detection of Apache .htpasswd connections +# Due to the often high logging rate in the Apache error log, you might want to +# enable this option only if you know you are suffering from attacks against +# password protected directories +LF_HTACCESS = "5" +LF_HTACCESS_PERM = "1" + +# [*]Enable login failure detection of cpanel, webmail and whm connections +LF_CPANEL = "5" +LF_CPANEL_PERM = "1" + +# [*]Enable failure detection of repeated Apache mod_security rule triggers +LF_MODSEC = "5" +LF_MODSEC_PERM = "1" + +# [*]Enable detection of repeated BIND denied requests +# This option should be enabled with care as it will prevent blocked IPs from +# resolving any domains on the server. You might want to set the trigger value +# reasonably high to avoid this +# Example: LF_BIND = "100" +LF_BIND = "0" +LF_BIND_PERM = "1" + +# [*]Enable detection of repeated suhosin ALERTs +# Example: LF_SUHOSIN = "5" +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_SUHOSIN = "0" +LF_SUHOSIN_PERM = "1" + +# [*]Enable detection of repeated cxs ModSecurity mod_security rule triggers +# This option will block IP addresses if cxs detects a hits from the +# ModSecurity rule associated with it +# +# Note: This option takes precedence over LF_MODSEC and removes any hits +# counted towards LF_MODSEC for the cxs rule +# +# This setting should probably set very low, perhaps to 1, if you want to +# effectively block IP addresses for this trigger option +LF_CXS = "0" +LF_CXS_PERM = "1" + +# [*]Enable detection of repeated Apache mod_qos rule triggers +LF_QOS = "0" +LF_QOS_PERM = "1" + +# [*]Enable detection of repeated Apache symlink race condition triggers from +# the Apache patch provided by: +# http://www.mail-archive.com/dev@httpd.apache.org/msg55666.html +# This patch has also been included by cPanel via the easyapache option: +# "Symlink Race Condition Protection" +LF_SYMLINK = "0" +LF_SYMLINK_PERM = "1" + +# [*]Enable login failure detection of webmin connections +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_WEBMIN = "0" +LF_WEBMIN_PERM = "1" + +# Send an email alert if anyone logs in successfully using SSH +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_SSH_EMAIL_ALERT = "1" + +# Send an email alert if anyone uses su to access another account. This will +# send an email alert whether the attempt to use su was successful or not +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_SU_EMAIL_ALERT = "1" + +# Send an email alert if anyone uses sudo to access another account. This will +# send an email alert whether the attempt to use sudo was successful or not +# +# NOTE: This option could become onerous if sudo is used extensively for root +# access by administrators or control panels. It is provided for those where +# this is not the case +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_SUDO_EMAIL_ALERT = "0" + +# Send an email alert if anyone accesses webmin +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_WEBMIN_EMAIL_ALERT = "1" + +# Send an email alert if anyone logs in successfully to root on the console +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_CONSOLE_EMAIL_ALERT = "1" + +# This option will keep track of the number of "File does not exist" errors in +# HTACCESS_LOG. If the number of hits is more than LF_APACHE_404 in LF_INTERVAL +# seconds then the IP address will be blocked +# +# Care should be used with this option as it could generate many +# false-positives, especially Search Bots (use csf.rignore to ignore such bots) +# so only use this option if you know you are under this type of attack +# +# A sensible setting for this would be quite high, perhaps 200 +# +# To disable set to "0" +LF_APACHE_404 = "0" + +# If this option is set to 1 the blocks will be permanent +# If this option is > 1, the blocks will be temporary for the specified number +# of seconds +LF_APACHE_404_PERM = "3600" + +# This option will keep track of the number of "client denied by server +# configuration" errors in HTACCESS_LOG. If the number of hits is more than +# LF_APACHE_403 in LF_INTERVAL seconds then the IP address will be blocked +# +# Care should be used with this option as it could generate many +# false-positives, especially Search Bots (use csf.rignore to ignore such bots) +# so only use this option if you know you are under this type of attack +# +# To disable set to "0" +LF_APACHE_403 = "0" + +# If this option is set to 1 the blocks will be permanent +# If this option is > 1, the blocks will be temporary for the specified number +# of seconds +LF_APACHE_403_PERM = "3600" + +# This option will keep track of the number of 401 failures in HTACCESS_LOG. +# If the number of hits is more than LF_APACHE_401 in LF_INTERVAL seconds then +# the IP address will be blocked +# +# To disable set to "0" +LF_APACHE_401 = "0" + +# If this option is set to 1 the blocks will be permanent +# If this option is > 1, the blocks will be temporary for the specified number +# of seconds +LF_APACHE_401_PERM = "3600" + +# This option is used to determine if the Apache error_log format contains the +# client port after the client IP. In Apache prior to v2.4, this was not the +# case. In Apache v2.4+ the error_log format can be configured using +# ErrorLogFormat, making the port directive optional +# +# Unfortunately v2.4 ErrorLogFormat places the port number after a colon next +# to the client IP by default. This makes determining client IPv6 addresses +# difficult unless we know whether the port is being appended or not +# +# lfd will attempt to autodetect the correct value if this option is set to "0" +# from the httpd binary found in common locations. If it fails to find a binary +# it will be set to "2", unless specified here +# +# The value can be set here explicitly if the autodetection does not work: +# 0 - autodetect +# 1 - no port directive after client IP +# 2 - port directive after client IP +LF_APACHE_ERRPORT = "0" + +# Send an email alert if anyone accesses WHM/cPanel via an account listed in +# LF_CPANEL_ALERT_USERS. An IP address will be reported again 1 hour after the +# last tracked access (or if lfd is restarted) +LF_CPANEL_ALERT = "1" + +# If a LF_CPANEL_ALERT event is triggered, then if the following contains the +# path to a script, it will run the script and passed the ip and username and +# the DNS IP lookup result as 3 arguments +# +# The action script must have the execute bit and interpreter (shebang) set +LF_CPANEL_ALERT_ACTION = "" + +# This is a comma separated list of accounts to send alerts for. To send an +# alert for all accounts set this to "all" +LF_CPANEL_ALERT_USERS = "root" + +# Enable scanning of the exim mainlog for repeated emails sent from scripts. +# To use this feature the exim log_selector option must at least be set to: +# +# log_selector = +arguments +subject +received_recipients +# +# If you already use extended exim logging, then you need to either include +# +arguments +received_recipients or use +all +# +# This setting will then send an alert email if more than LF_SCRIPT_LIMIT lines +# appear with the same cwd= path in them within an hour. This can be useful in +# identifying spamming scripts on a server, especially PHP scripts running +# under the nobody account. The email that is sent includes the exim log lines +# and also attempts to find scripts that send email in the path that may be the +# culprit +LF_SCRIPT_ALERT = "0" + +# The limit afterwhich the email alert for email scripts is sent. Care should +# be taken with this value if you allow clients to use web scripts to maintain +# pseudo-mailing lists which have large recipients +LF_SCRIPT_LIMIT = "100" + +# If an LF_SCRIPT_ALERT event is triggered, then if the following can contain +# the path to a script, it will be run in a child process and passed the +# following information as parameters which also appears in the email alert: +# Path to the directory containing the script that is sending the email +# Count of emails sent +# Sample of the first 10 emails +# List of possible email scripts within Path +# +# The action script must have the execute bit and interpreter (shebang) set +LF_SCRIPT_ACTION = "" + +# If this option is enabled, the directory identified by LF_SCRIPT_ALERT will +# be chmod 0 and chattr +i to prevent it being accessed. Set the option to 1 +# to enable. +# +# WARNING: This option could cause serious system problems if the identified +# directory is within the OS directory hierarchy. For this reason we do not +# recommend enabling it unless absolutely necessary. +LF_SCRIPT_PERM = "0" + +# Checks the length of the exim queue and sends an alert email if the value of +# settings is exceeded. If the ConfigServer MailScanner configuration is used +# then both the pending and delivery queues will be checked. +# +# Note: If there are problems sending out email, this alert may not be received +# To disable set to "0" +LF_QUEUE_ALERT = "2000" + +# The interval between mail queue checks in seconds. This should not be set too +# low on servers that often have long queues as the exim binary can use +# significant resources when checking its queue length +LF_QUEUE_INTERVAL = "300" + +# This option will send an alert if the ModSecurity IP persistent storage grows +# excessively large: https://goo.gl/rGh5sF +# +# More information on cPanel servers here: https://goo.gl/vo6xTE +# +# The check is performed at lfd startup and then once per hour, the template +# used is modsecipdbalert.txt +# +# LF_MODSECIPDB_FILE must be set to the correct location of the database file +# +# Set to "0" to disable this option, otherwise it is the threshold size of the +# file to report in gigabytes, e.g. set to 5 for 5GB +LF_MODSECIPDB_ALERT = "5" + +# This is the location of the persistent IP storage file on the server, e.g.: +# /var/run/modsecurity/data/ip.pag +# /var/cpanel/secdatadir/ip.pag +# /var/cache/modsecurity/ip.pag +# /usr/local/apache/conf/modsec/data/msa/ip.pag +# /var/tmp/ip.pag +# /tmp/ip.pag +LF_MODSECIPDB_FILE = "/var/cpanel/secdatadir/ip.pag" + +# System Exploit Checking. This option is designed to perform a series of tests +# to send an alert in case a possible server compromise is detected +# +# To enable this feature set the following to the checking interval in seconds +# (a value of 300 would seem sensible). +# +# To disable set to "0" +LF_EXPLOIT = "300" + +# This comma separated list allows you to ignore tests LF_EXPLOIT performs +# +# For the SUPERUSER check, you can list usernames in csf.suignore to have them +# ignored for that test +# +# Valid tests are: +# SUPERUSER +# +# If you want to ignore a test add it to this as a comma separated list, e.g. +# "SUPERUSER" +LF_EXPLOIT_IGNORE = "" + +# Set the time interval to track login and other LF_ failures within (seconds), +# i.e. LF_TRIGGER failures within the last LF_INTERVAL seconds +LF_INTERVAL = "3600" + +# This is how long the lfd process sleeps (in seconds) before processing the +# log file entries and checking whether other events need to be triggered +LF_PARSE = "5" + +# This is the interval that is used to flush reports of usernames, files and +# pids so that persistent problems continue to be reported, in seconds. +# A value of 3600 seems sensible +LF_FLUSH = "3600" + +# Under some circumstances iptables can fail to include a rule instruction, +# especially if more than one request is made concurrently. In this event, a +# permanent block entry may exist in csf.deny, but not in iptables. +# +# This option instructs csf to deny an already blocked IP address the number +# of times set. The downside, is that there will be multiple entries for an IP +# address in csf.deny and possibly multiple rules for the same IP address in +# iptables. This needs to be taken into consideration when unblocking such IP +# addresses. +# +# Set to "0" to disable this feature. Do not set this too high for the reasons +# detailed above (e.g. "5" should be more than enough) +LF_REPEATBLOCK = "0" + +# By default csf will create both an inbound and outbound blocks from/to an IP +# unless otherwise specified in csf.deny and GLOBAL_DENY. This is the most +# effective way to block IP traffic. This option instructs csf to only block +# inbound traffic from those IP's and so reduces the number of iptables rules, +# but at the expense of less effectiveness. For this reason we recommend +# leaving this option disabled +# +# Set to "0" to disable this feature - the default +LF_BLOCKINONLY = "0" + +############################################################################### +# SECTION:CloudFlare +############################################################################### +# This features provides interaction with the CloudFlare Firewall +# +# As CloudFlare is a reverse proxy, any attacking IP addresses (so far as +# iptables is concerned) come from the CloudFlare IP's. To counter this, an +# Apache module (mod_cloudflare) is available that obtains the true attackers +# IP from a custom HTTP header record (similar functionality is available +# for other HTTP daemons +# +# However, despite now knowing the true attacking IP address, iptables cannot +# be used to block that IP as the traffic is still coming from the CloudFlare +# servers +# +# CloudFlare have provided a Firewall feature within the user account where +# rules can be added to block, challenge or whitelist IP addresses +# +# Using the CloudFlare API, this feature adds and removes attacking IPs from +# that firewall and provides CLI (and via the UI) additional commands +# +# See /etc/csf/readme.txt for more information about this feature and the +# restrictions for its use BEFORE enabling this feature +CF_ENABLE = "0" + +# If the CloudFlare user plugin has been installed, enable this setting to use +# per cPanel account settings rather than listing each account in +# /etc/csf/csf.cloudflare +CF_CPANEL = "" + +# This can be set to either "block" or "challenge" (see CloudFlare docs) +CF_BLOCK = "block" + +# This setting determines how long the temporary block will apply within csf +# and CloudFlare, keeping them in sync +# +# Block duration in seconds - overrides perm block or time of individual blocks +# in lfd for block triggers +CF_TEMP = "3600" + +############################################################################### +# SECTION:Directory Watching & Integrity +############################################################################### +# Enable Directory Watching. This enables lfd to check /tmp and /dev/shm +# directories for suspicious files, i.e. script exploits. If a suspicious +# file is found an email alert is sent. One alert per file per LF_FLUSH +# interval is sent +# +# To enable this feature set the following to the checking interval in seconds. +# To disable set to "0" +LF_DIRWATCH = "300" + +# To remove any suspicious files found during directory watching, enable the +# following. These files will be appended to a tarball in +# /var/lib/suspicious.tar +LF_DIRWATCH_DISABLE = "0" + +# This option allows you to have lfd watch a particular file or directory for +# changes and should they change and email alert using watchalert.txt is sent +# +# To enable this feature set the following to the checking interval in seconds +# (a value of 60 would seem sensible) and add your entries to csf.dirwatch +# +# Set to disable set to "0" +LF_DIRWATCH_FILE = "0" + +# System Integrity Checking. This enables lfd to compare md5sums of the +# servers OS binary application files from the time when lfd starts. If the +# md5sum of a monitored file changes an alert is sent. This option is intended +# as an IDS (Intrusion Detection System) and is the last line of detection for +# a possible root compromise. +# +# There will be constant false-positives as the servers OS is updated or +# monitored application binaries are updated. However, unexpected changes +# should be carefully inspected. +# +# Modified files will only be reported via email once. +# +# To enable this feature set the following to the checking interval in seconds +# (a value of 3600 would seem sensible). This option may increase server I/O +# load onto the server as it checks system binaries. +# +# To disable set to "0" +LF_INTEGRITY = "3600" + +############################################################################### +# SECTION:Distributed Attacks +############################################################################### +# Distributed Account Attack. This option will keep track of login failures +# from distributed IP addresses to a specific application account. If the +# number of failures matches the trigger value above, ALL of the IP addresses +# involved in the attack will be blocked according to the temp/perm rules above +# +# Tracking applies to LF_SSHD, LF_FTPD, LF_SMTPAUTH, LF_POP3D, LF_IMAPD, +# LF_HTACCESS +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_DISTATTACK = "0" + +# Set the following to the minimum number of unique IP addresses that trigger +# LF_DISTATTACK +LF_DISTATTACK_UNIQ = "2" + +# Distributed FTP Logins. This option will keep track of successful FTP logins. +# If the number of successful logins to an individual account is at least +# LF_DISTFTP in LF_DIST_INTERVAL from at least LF_DISTFTP_UNIQ IP addresses, +# then all of the IP addresses will be blocked +# +# This option can help mitigate the common FTP account compromise attacks that +# use a distributed network of zombies to deface websites +# +# A sensible setting for this might be 5, depending on how many different +# IP addresses you expect to an individual FTP account within LF_DIST_INTERVAL +# +# To disable set to "0" +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_DISTFTP = "0" + +# Set the following to the minimum number of unique IP addresses that trigger +# LF_DISTFTP. LF_DISTFTP_UNIQ must be <= LF_DISTFTP for this to work +LF_DISTFTP_UNIQ = "3" + +# If this option is set to 1 the blocks will be permanent +# If this option is > 1, the blocks will be temporary for the specified number +# of seconds +LF_DISTFTP_PERM = "1" + +# Send an email alert if LF_DISTFTP is triggered +LF_DISTFTP_ALERT = "1" + +# Distributed SMTP Logins. This option will keep track of successful SMTP +# logins. If the number of successful logins to an individual account is at +# least LF_DISTSMTP in LF_DIST_INTERVAL from at least LF_DISTSMTP_UNIQ IP +# addresses, then all of the IP addresses will be blocked. These options only +# apply to the exim MTA +# +# This option can help mitigate the common SMTP account compromise attacks that +# use a distributed network of zombies to send spam +# +# A sensible setting for this might be 5, depending on how many different +# IP addresses you expect to an individual SMTP account within LF_DIST_INTERVAL +# +# To disable set to "0" +LF_DISTSMTP = "0" + +# Set the following to the minimum number of unique IP addresses that trigger +# LF_DISTSMTP. LF_DISTSMTP_UNIQ must be <= LF_DISTSMTP for this to work +LF_DISTSMTP_UNIQ = "3" + +# If this option is set to 1 the blocks will be permanent +# If this option is > 1, the blocks will be temporary for the specified number +# of seconds +LF_DISTSMTP_PERM = "1" + +# Send an email alert if LF_DISTSMTP is triggered +LF_DISTSMTP_ALERT = "1" + +# This is the interval during which a distributed FTP or SMTP attack is +# measured +LF_DIST_INTERVAL = "300" + +# If LF_DISTFTP or LF_DISTSMTP is triggered, then if the following contains the +# path to a script, it will run the script and pass the following as arguments: +# +# LF_DISTFTP/LF_DISTSMTP +# account name +# log file text +# +# The action script must have the execute bit and interpreter (shebang) set +LF_DIST_ACTION = "" + +############################################################################### +# SECTION:Login Tracking +############################################################################### +# Block POP3 logins if greater than LT_POP3D times per hour per account per IP +# address (0=disabled) +# +# This is a temporary block for the rest of the hour, afterwhich the IP is +# unblocked +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LT_POP3D = "0" + +# Block IMAP logins if greater than LT_IMAPD times per hour per account per IP +# address (0=disabled) - not recommended for IMAP logins due to the ethos +# within which IMAP works. If you want to use this, setting it quite high is +# probably a good idea +# +# This is a temporary block for the rest of the hour, afterwhich the IP is +# unblocked +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LT_IMAPD = "0" + +# Send an email alert if an account exceeds LT_POP3D/LT_IMAPD logins per hour +# per IP +LT_EMAIL_ALERT = "1" + +# If LF_PERMBLOCK is enabled but you do not want this to apply to +# LT_POP3D/LT_IMAPD, then enable this option +LT_SKIPPERMBLOCK = "0" + +############################################################################### +# SECTION:Relay Tracking +############################################################################### +# Relay Tracking. This allows you to track email that is relayed through the +# server. There are also options to send alerts and block external IP addresses +# if the number of emails relayed per hour exceeds configured limits. The +# blocks can be either permanent or temporary. +# +# The following information applies to each of the following types of relay +# check: +# RT_[relay type]_ALERT: 0 = disable, 1 = enable +# RT_[relay type]_LIMIT: the limit/hour afterwhich an email alert will be sent +# RT_[relay type]_BLOCK: 0 = no block;1 = perm block;nn=temp block for nn secs + +# This option triggers for external email +RT_RELAY_ALERT = "1" +RT_RELAY_LIMIT = "100" +RT_RELAY_BLOCK = "0" + +# This option triggers for email authenticated by SMTP AUTH +RT_AUTHRELAY_ALERT = "1" +RT_AUTHRELAY_LIMIT = "100" +RT_AUTHRELAY_BLOCK = "0" + +# This option triggers for email authenticated by POP before SMTP +RT_POPRELAY_ALERT = "1" +RT_POPRELAY_LIMIT = "100" +RT_POPRELAY_BLOCK = "0" + +# This option triggers for email sent via /usr/sbin/sendmail or /usr/sbin/exim +RT_LOCALRELAY_ALERT = "1" +RT_LOCALRELAY_LIMIT = "100" + +# This option triggers for email sent via a local IP addresses +RT_LOCALHOSTRELAY_ALERT = "1" +RT_LOCALHOSTRELAY_LIMIT = "100" + +# If an RT_* event is triggered, then if the following contains the path to +# a script, it will be run in a child process and passed the following: +# information as parameters which also appears in the email alert: +# IP Address +# Relay Type (RELAY/AUTHRELAY/POPRELAY/LOCALRELAY/LOCALHOSTRELAY) +# Block Message (Temporary/Permanent Block) +# Count of emails relayed +# Sample of the first 10 emails +# +# The action script must have the execute bit and interpreter (shebang) set +RT_ACTION = "" + +############################################################################### +# SECTION:Connection Tracking +############################################################################### +# Connection Tracking. This option enables tracking of all connections from IP +# addresses to the server. If the total number of connections is greater than +# this value then the offending IP address is blocked. This can be used to help +# prevent some types of DOS attack. +# +# Care should be taken with this option. It's entirely possible that you will +# see false-positives. Some protocols can be connection hungry, e.g. FTP, IMAPD +# and HTTP so it could be quite easy to trigger, especially with a lot of +# closed connections in TIME_WAIT. However, for a server that is prone to DOS +# attacks this may be very useful. A reasonable setting for this option might +# be around 300 +# +# To disable this feature, set this to 0 +CT_LIMIT = "0" + +# Connection Tracking interval. Set this to the the number of seconds between +# connection tracking scans +CT_INTERVAL = "30" + +# Send an email alert if an IP address is blocked due to connection tracking +CT_EMAIL_ALERT = "1" + +# If you want to make IP blocks permanent then set this to 1, otherwise blocks +# will be temporary and will be cleared after CT_BLOCK_TIME seconds +CT_PERMANENT = "0" + +# If you opt for temporary IP blocks for CT, then the following is the interval +# in seconds that the IP will remained blocked for (e.g. 1800 = 30 mins) +CT_BLOCK_TIME = "1800" + +# If you don't want to count the TIME_WAIT state against the connection count +# then set the following to "1" +CT_SKIP_TIME_WAIT = "0" + +# If you only want to count specific states (e.g. SYN_RECV) then add the states +# to the following as a comma separated list. E.g. "SYN_RECV,TIME_WAIT" +# +# Leave this option empty to count all states against CT_LIMIT +CT_STATES = "" + +# If you only want to count specific ports (e.g. 80,443) then add the ports +# to the following as a comma separated list. E.g. "80,443" +# +# Leave this option empty to count all ports against CT_LIMIT +CT_PORTS = "" + +# If the total number of connections from a class C subnet is greater than this +# value then the offending subnet is blocked according to the other CT_* +# settings +# +# This option can be used to help prevent some types of DOS attack where a +# range of IP's between x.y.z.1-255 has connected to the server +# +# If you use a reverse proxy service such as Cloudflare you should not enable +# this option, or should exclude the ports that you have proxied in CT_PORTS +# +# To disable this feature, set this to 0 +CT_SUBNET_LIMIT = "0" + +############################################################################### +# SECTION:Process Tracking +############################################################################### +# Process Tracking. This option enables tracking of user and nobody processes +# and examines them for suspicious executables or open network ports. Its +# purpose is to identify potential exploit processes that are running on the +# server, even if they are obfuscated to appear as system services. If a +# suspicious process is found an alert email is sent with relevant information. +# It is then the responsibility of the recipient to investigate the process +# further as the script takes no further action +# +# The following is the number of seconds a process has to be active before it +# is inspected. If you set this time too low, then you will likely trigger +# false-positives with CGI or PHP scripts. +# Set the value to 0 to disable this feature +PT_LIMIT = "60" + +# How frequently processes are checked in seconds +PT_INTERVAL = "60" + +# If you want process tracking to highlight php or perl scripts that are run +# through apache then disable the following, +# i.e. set it to 0 +# +# While enabling this setting will reduce false-positives, having it set to 0 +# does provide better checking for exploits running on the server +PT_SKIP_HTTP = "0" + +# If you want to track all linux accounts on a cPanel server, not just users +# that are part of cPanel, then enable this option. This is recommended to +# improve security from compromised accounts +# +# Set to 0 to disable the feature, 1 to enable it +PT_ALL_USERS = "0" + +# lfd will report processes, even if they're listed in csf.pignore, if they're +# tagged as (deleted) by Linux. This information is provided in Linux under +# /proc/PID/exe. A (deleted) process is one that is running a binary that has +# the inode for the file removed from the file system directory. This usually +# happens when the binary has been replaced due to an upgrade for it by the OS +# vendor or another third party (e.g. cPanel). You need to investigate whether +# this is indeed the case to be sure that the original binary has not been +# replaced by a rootkit or is running an exploit. +# +# Note: If a deleted executable process is detected and reported then lfd will +# not report children of the parent (or the parent itself if a child triggered +# the report) if the parent is also a deleted executable process +# +# To stop lfd reporting such process you need to restart the daemon to which it +# belongs and therefore run the process using the replacement binary (presuming +# one exists). This will normally mean running the associated startup script in +# /etc/init.d/ +# +# If you do want lfd to report deleted binary processes, set to 1 +PT_DELETED = "0" + +# If a PT_DELETED event is triggered, then if the following contains the path to +# a script, it will be run in a child process and passed the executable, pid, +# account for the process, and parent pid +# +# The action script must have the execute bit and interpreter (shebang) set. An +# example is provided in /usr/local/csf/bin/pt_deleted_action.pl +# +# WARNING: Make sure you read and understand the potential security +# implications of such processes in PT_DELETED above before simply restarting +# such processes with a script +PT_DELETED_ACTION = "" + +# User Process Tracking. This option enables the tracking of the number of +# process any given account is running at one time. If the number of processes +# exceeds the value of the following setting an email alert is sent with +# details of those processes. If you specify a user in csf.pignore it will be +# ignored +# +# Set to 0 to disable this feature +PT_USERPROC = "10" + +# This User Process Tracking option sends an alert if any user process exceeds +# the virtual memory usage set (MB). To ignore specific processes or users use +# csf.pignore +# +# Set to 0 to disable this feature +PT_USERMEM = "512" + +# This User Process Tracking option sends an alert if any user process exceeds +# the RSS memory usage set (MB) - RAM used, not virtual. To ignore specific +# processes or users use csf.pignore +# +# Set to 0 to disable this feature +PT_USERRSS = "256" + +# This User Process Tracking option sends an alert if any cPanel user process +# exceeds the time usage set (seconds). To ignore specific processes or users +# use csf.pignore +# +# Set to 0 to disable this feature +PT_USERTIME = "1800" + +# If this option is set then processes detected by PT_USERMEM, PT_USERTIME or +# PT_USERPROC are killed +# +# Warning: We don't recommend enabling this option unless absolutely necessary +# as it can cause unexpected problems when processes are suddenly terminated. +# It can also lead to system processes being terminated which could cause +# stability issues. It is much better to leave this option disabled and to +# investigate each case as it is reported when the triggers above are breached +# +# Note: Processes that are running deleted excecutables (see PT_DELETED) will +# not be killed by lfd +PT_USERKILL = "0" + +# If you want to disable email alerts if PT_USERKILL is triggered, then set +# this option to 0 +PT_USERKILL_ALERT = "1" + +# If a PT_* event is triggered, then if the following contains the path to +# a script, it will be run in a child process and passed the PID(s) of the +# process(es) in a comma separated list. +# +# The action script must have the execute bit and interpreter (shebang) set +PT_USER_ACTION = "" + +# Check the PT_LOAD_AVG minute Load Average (can be set to 1 5 or 15 and +# defaults to 5 if set otherwise) on the server every PT_LOAD seconds. If the +# load average is greater than or equal to PT_LOAD_LEVEL then an email alert is +# sent. lfd then does not report subsequent high load until PT_LOAD_SKIP +# seconds has passed to prevent email floods. +# +# Set PT_LOAD to "0" to disable this feature +PT_LOAD = "30" +PT_LOAD_AVG = "5" +PT_LOAD_LEVEL = "6" +PT_LOAD_SKIP = "3600" + +# This is the Apache Server Status URL used in the email alert. Requires the +# Apache mod_status module to be installed and configured correctly +PT_APACHESTATUS = "http://127.0.0.1/whm-server-status" + +# If a PT_LOAD event is triggered, then if the following contains the path to +# a script, it will be run in a child process. For example, the script could +# contain commands to terminate and restart httpd, php, exim, etc incase of +# looping processes. The action script must have the execute bit an +# interpreter (shebang) set +PT_LOAD_ACTION = "" + +# Fork Bomb Protection. This option checks the number of processes with the +# same session id and if greater than the value set, the whole session tree is +# terminated and an alert sent +# +# You can see an example of common session id processes on most Linux systems +# using: "ps axf -O sid" +# +# On cPanel servers, PT_ALL_USERS should be enabled to use this option +# effectively +# +# This option will check root owned processes. Session id 0 and 1 will always +# be ignored as they represent kernel and init processes. csf.pignore will be +# honoured, but bear in mind that a session tree can contain a variety of users +# and executables +# +# Care needs to be taken to ensure that this option only detects runaway fork +# bombs, so should be set higher than any session tree is likely to get (e.g. +# httpd could have 100s of legitimate children on very busy systems). A +# sensible starting point on most servers might be 250 +PT_FORKBOMB = "0" + +# Terminate hung SSHD sessions. When under an SSHD login attack, SSHD processes +# are often left hanging after their connecting IP addresses have been blocked +# +# This option will terminate the SSH processes created by the blocked IP. This +# option is preferred over PT_SSHDHUNG +PT_SSHDKILL = "0" + +# This option will terminate all processes with the cmdline of "sshd: unknown +# [net]" or "sshd: unknown [priv]" if they have been running for more than 60 +# seconds +# +# This option is now deprecated and will be removed in the future. PT_SSHDKILL +# should be used instead +PT_SSHDHUNG = "0" + +############################################################################### +# SECTION:Port Scan Tracking +############################################################################### +# Port Scan Tracking. This feature tracks port blocks logged by iptables to +# syslog. If an IP address generates a port block that is logged more than +# PS_LIMIT within PS_INTERVAL seconds, the IP address will be blocked. +# +# This feature could, for example, be useful for blocking hackers attempting +# to access the standard SSH port if you have moved it to a port other than 22 +# and have removed 22 from the TCP_IN list so that connection attempts to the +# old port are being logged +# +# This feature blocks all iptables blocks from the iptables logs, including +# repeated attempts to one port or SYN flood blocks, etc +# +# Note: This feature will only track iptables blocks from the log file set in +# IPTABLES_LOG below and if you have DROP_LOGGING enabled. However, it will +# cause redundant blocking with DROP_IP_LOGGING enabled +# +# Warning: It's possible that an elaborate DDOS (i.e. from multiple IP's) +# could very quickly fill the iptables rule chains and cause a DOS in itself. +# The DENY_IP_LIMIT should help to mitigate such problems with permanent blocks +# and the DENY_TEMP_IP_LIMIT with temporary blocks +# +# Set PS_INTERVAL to "0" to disable this feature. A value of between 60 and 300 +# would be sensible to enable this feature +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +PS_INTERVAL = "0" +PS_LIMIT = "10" + +# You can specify the ports and/or port ranges that should be tracked by the +# Port Scan Tracking feature. The following setting is a comma separated list +# of those ports and uses the same format as TCP_IN. The setting of +# 0:65535,ICMP,INVALID,OPEN,BRD covers all ports +# +# Special values are: +# ICMP - include ICMP blocks (see ICMP_*) +# INVALID - include INVALID blocks (see PACKET_FILTER) +# OPEN - include TCP_IN and UDP_IN open port blocks - *[proto]_IN Blocked* +# BRD - include UDP Broadcast IPs, otherwise they are ignored +PS_PORTS = "0:65535,ICMP" + +# To specify how many different ports qualifies as a Port Scan you can increase +# the following from the default value of 1. The risk in doing so will mean +# that persistent attempts to attack a specific closed port will not be +# detected and blocked +PS_DIVERSITY = "1" + +# You can select whether IP blocks for Port Scan Tracking should be temporary +# or permanent. Set PS_PERMANENT to "0" for temporary and "1" for permanent +# blocking. If set to "0" PS_BLOCK_TIME is the amount of time in seconds to +# temporarily block the IP address for +PS_PERMANENT = "0" +PS_BLOCK_TIME = "3600" + +# Set the following to "1" to enable Port Scan Tracking email alerts, set to +# "0" to disable them +PS_EMAIL_ALERT = "1" + +############################################################################### +# SECTION:User ID Tracking +############################################################################### +# User ID Tracking. This feature tracks UID blocks logged by iptables to +# syslog. If a UID generates a port block that is logged more than UID_LIMIT +# times within UID_INTERVAL seconds, an alert will be sent +# +# Note: This feature will only track iptables blocks from the log file set in +# IPTABLES_LOG and if DROP_OUT_LOGGING and DROP_UID_LOGGING are enabled. +# +# To ignore specific UIDs list them in csf.uidignore and then restart lfd +# +# Set UID_INTERVAL to "0" to disable this feature. A value of between 60 and 300 +# would be sensible to enable this feature +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +UID_INTERVAL = "0" +UID_LIMIT = "10" + +# You can specify the ports and/or port ranges that should be tracked by the +# User ID Tracking feature. The following setting is a comma separated list +# of those ports and uses the same format as TCP_OUT. The default setting of +# 0:65535,ICMP covers all ports +UID_PORTS = "0:65535,ICMP" + +############################################################################### +# SECTION:Account Tracking +############################################################################### +# Account Tracking. The following options enable the tracking of modifications +# to the accounts on a server. If any of the enabled options are triggered by +# a modifications to an account, an alert email is sent. Only the modification +# is reported. The cause of the modification will have to be investigated +# manually +# +# You can set AT_ALERT to the following: +# 0 = disable this feature +# 1 = enable this feature for all accounts +# 2 = enable this feature only for superuser accounts (UID = 0, e.g. root, etc) +# 3 = enable this feature only for the root account +AT_ALERT = "2" + +# This options is the interval between checks in seconds +AT_INTERVAL = "60" + +# Send alert if a new account is created +AT_NEW = "1" + +# Send alert if an existing account is deleted +AT_OLD = "1" + +# Send alert if an account password has changed +AT_PASSWD = "1" + +# Send alert if an account uid has changed +AT_UID = "1" + +# Send alert if an account gid has changed +AT_GID = "1" + +# Send alert if an account login directory has changed +AT_DIR = "1" + +# Send alert if an account login shell has changed +AT_SHELL = "1" + +############################################################################### +# SECTION:Integrated User Interface +############################################################################### +# Integrated User Interface. This feature provides a HTML UI to csf and lfd, +# without requiring a control panel or web server. The UI runs as a sub process +# to the lfd daemon +# +# As it runs under the root account and successful login provides root access +# to the server, great care should be taken when configuring and using this +# feature. There are additional restrictions to enhance secure access to the UI +# +# See readme.txt for more information about using this feature BEFORE enabling +# it for security and access reasons +# +# 1 to enable, 0 to disable +UI = "0" + +# Set this to the port that want to bind this service to. You should configure +# this port to be >1023 and different from any other port already being used +# +# Do NOT enable access to this port in TCP_IN, instead only allow trusted IP's +# to the port using Advanced Allow Filters (see readme.txt) +UI_PORT = "6666" + +# Optionally set the IP address to bind to. Normally this should be left blank +# to bind to all IP addresses on the server. +# +# If the server is configured for IPv6 but the IP to bind to is IPv4, then the +# IP address MUST use the IPv6 representation. For example 1.2.3.4 must use +# ::ffff:1.2.3.4 +# +# Leave blank to bind to all IP addresses on the server +UI_IP = "" + +# This should be a secure, hard to guess username +# +# This must be changed from the default +UI_USER = "username" + +# This should be a secure, hard to guess password. That is, at least 8 +# characters long with a mixture of upper and lowercase characters plus +# numbers and non-alphanumeric characters +# +# This must be changed from the default +UI_PASS = "password" + +# This is the login session timeout. If there is no activity for a logged in +# session within this number of seconds, the session will timeout and a new +# login will be required +# +# For security reasons, you should always keep this option low (i.e 60-300) +UI_TIMEOUT = "300" + +# This is the maximum concurrent connections allowed to the server. The default +# value should be sufficient +UI_CHILDREN = "5" + +# The number of login retries allowed within a 24 hour period. A successful +# login from the IP address will clear the failures +# +# For security reasons, you should always keep this option low (i.e 0-10) +UI_RETRY = "5" + +# If enabled, this option will add the connecting IP address to the file +# /etc/csf/ui/ui.ban after UI_RETRY login failures. The IP address will not be +# able to login to the UI while it is listed in this file. The UI_BAN setting +# does not refer to any of the csf/lfd allow or ignore files, e.g. csf.allow, +# csf.ignore, etc. +# +# For security reasons, you should always enable this option +UI_BAN = "1" + +# If enabled, only IPs (or CIDR's) listed in the file /etc/csf/ui/ui.allow will +# be allowed to login to the UI. The UI_ALLOW setting does not refer to any of +# the csf/lfd allow or ignore files, e.g. csf.allow, csf.ignore, etc. +# +# For security reasons, you should always enable this option and use ui.allow +UI_ALLOW = "1" + +# If enabled, this option will trigger an iptables block through csf after +# UI_RETRY login failures +# +# 0 = no block;1 = perm block;nn=temp block for nn secs +UI_BLOCK = "1" + +# This controls what email alerts are sent with regards to logins to the UI. It +# uses the uialert.txt template +# +# 4 = login success + login failure/ban/block + login attempts +# 3 = login success + login failure/ban/block +# 2 = login failure/ban/block +# 1 = login ban/block +# 0 = disabled +UI_ALERT = "4" + +# This is the SSL cipher list that the Integrated UI will negotiate from +UI_CIPHER = "ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:-LOW:-SSLv2:-EXP:!kEDH" + +# This is the SSL protocol version used. See IO::Socket::SSL if you wish to +# change this and to understand the implications of changing it +UI_SSL_VERSION = "SSLv23:!SSLv3:!SSLv2" + +# If cxs is installed then enabling this option will provide a dropdown box to +# switch between applications +UI_CXS = "0" + +# There is a modified installation of ConfigServer Explorer (cse) provided with +# the csf distribution. If this option is enabled it will provide a dropdown +# box to switch between applications +UI_CSE = "0" + +############################################################################### +# SECTION:Messenger service +############################################################################### +# Messenger service. This feature allows the display of a message to a blocked +# connecting IP address to inform the user that they are blocked in the +# firewall. This can help when users get themselves blocked, e.g. due to +# multiple login failures. The service is provided by two daemons running on +# ports providing either an HTML or TEXT message +# +# This feature does not work on servers that do not have the iptables module +# ipt_REDIRECT loaded. Typically, this will be with MONOLITHIC kernels. VPS +# server admins should check with their VPS host provider that the iptables +# module is included +# +# IPv6 will need the IO::Socket::INET6 perl module +# +# For further information on features and limitations refer to the csf +# readme.txt +# +# Note: Run /etc/csf/csftest.pl to check whether this option will function on +# this server +# +# 1 to enable, 0 to disable +MESSENGER = "0" + +# Provide this service to temporary IP address blocks +MESSENGER_TEMP = "1" + +# Provide this service to permanent IP address blocks +MESSENGER_PERM = "1" + +# User account to run the service servers under. We recommend creating a +# specific non-priv, non-shell account for this purpose +# +# Note: When using MESSENGERV2, this account must NOT be a valid control panel +# account, it must be created manually as explained in the csf readme.txt +MESSENGER_USER = "csf" + +# This option points to the file(s) containing the Apache VirtualHost SSL +# definitions. This can be a file glob if there are multiple files to search. +# Only Apache v2 SSL VirtualHost definitions are supported +# +# This is used by MESSENGERV1 and MESSENGERV2 only +MESSENGER_HTTPS_CONF = "/usr/local/apache/conf/httpd.conf" + +# The following options can be specified to provide a default fallback +# certificate to be used if either SNI is not supported or a hosted domain does +# not have an SSL certificate. If a fallback is not provided, one of the certs +# obtained from MESSENGER_HTTPS_CONF will be used +# +# This is used by MESSENGERV1 and MESSENGERV2 only +MESSENGER_HTTPS_KEY = "/var/cpanel/ssl/cpanel/mycpanel.pem" +MESSENGER_HTTPS_CRT = "/var/cpanel/ssl/cpanel/mycpanel.pem" + +# Set this to the port that will receive the HTTPS HTML message. You should +# configure this port to be >1023 and different from the TEXT and HTML port. Do +# NOT enable access to this port in TCP_IN. This option requires the perl +# module IO::Socket::SSL at a version level that supports SNI (1.83+). +# Additionally the version of openssl on the server must also support SNI +# +# The option uses existing SSL certificates on the server for each domain to +# maintain a secure connection without browser warnings. It uses SNI to choose +# the correct certificate to use for each client connection +# +# Warning: On some servers the amount of memory used by the HTTPS MESSENGER +# service can become significant depending on various factors associated with +# the use of IO::Socket::SSL including the number of domains and certificates +# served. This is normally only an issue if using MESSENGERV1 +MESSENGER_HTTPS = "8887" + +# This comma separated list are the HTTPS HTML ports that will be redirected +# for the blocked IP address. If you are using per application blocking +# (LF_TRIGGER) then only the relevant block port will be redirected to the +# messenger port +# +# Recommended setting "443" plus any end-user control panel SSL ports. So, for +# cPanel: "443,2083,2096" +MESSENGER_HTTPS_IN = "443,2083,2096" + +# Set this to the port that will receive the HTML message. You should configure +# this port to be >1023 and different from the TEXT port. Do NOT enable access +# to this port in TCP_IN +MESSENGER_HTML = "8888" + +# This comma separated list are the HTML ports that will be redirected for the +# blocked IP address. If you are using per application blocking (LF_TRIGGER) +# then only the relevant block port will be redirected to the messenger port +MESSENGER_HTML_IN = "80,2082,2095" + +# Set this to the port that will receive the TEXT message. You should configure +# this port to be >1023 and different from the HTML port. Do NOT enable access +# to this port in TCP_IN +MESSENGER_TEXT = "8889" + +# This comma separated list are the TEXT ports that will be redirected for the +# blocked IP address. If you are using per application blocking (LF_TRIGGER) +# then only the relevant block port will be redirected to the messenger port +MESSENGER_TEXT_IN = "21" + +# These settings limit the rate at which connections can be made to the +# messenger service servers. Its intention is to provide protection from +# attacks or excessive connections to the servers. If the rate is exceeded then +# iptables will revert for the duration to the normal blocking activity +# +# See the iptables man page for the correct --limit rate syntax +MESSENGER_RATE = "100/s" +MESSENGER_BURST = "150" + +# MESSENGERV1 only: +#------------------------------------------------------------------------------ +# This is the maximum concurrent connections allowed to each service server +# +# Note: This number should be increased to cater for the number of local images +# served by this page, including one for favicon.ico. This is because each +# image displayed counts as an additional connection +MESSENGER_CHILDREN = "20" + +# This options ignores ServerAlias definitions that begin with "mail.". This +# can help reduce memory usage on systems that do not require the use of +# MESSENGER_HTTPS on those subdomains +# +# Set to 0 to include these ServerAlias definitions +MESSENGER_HTTPS_SKIPMAIL = "1" + +# MESSENGERV2 only: +#------------------------------------------------------------------------------ +# MESSENGERV2. This option is available on cPanel servers running Apache v2.4+ +# under EA4. +# +# This uses the Apache http daemon to provide the web server functionality for +# the MESSENGER HTML and HTTPS services. It uses a fraction of the resources +# that the lfd inbuilt service uses and overcomes the memory overhead of using +# the MESSENGER HTTPS service +# +# For more information consult readme.txt before enabling this option +MESSENGERV2 = "0" + +# MESSENGERV3 only: +#------------------------------------------------------------------------------ +# MESSENGERV3. This option is available on any server running Apache v2.4+, +# Litespeed or Openlitespeed +# +# This uses the web server http daemon to provide the web server functionality +# for the MESSENGER HTML and HTTPS services. It uses a fraction of the +# resources that the lfd inbuilt service uses and overcomes the memory overhead +# of using the MESSENGER HTTPS service +# +# For more information consult readme.txt before enabling this option +MESSENGERV3 = "0" + +# This is the file or directory where the additional web server configuration +# file should be included +MESSENGERV3LOCATION = "/etc/apache2/conf.d/" + +# This is the command to restart the web server +MESSENGERV3RESTART = "/scripts/restartsrv_httpd" + +# This is the command to test the validity of the web server configuration. If +# using Litespeed, set to "" +MESSENGERV3TEST = "/usr/sbin/apachectl -t" + +# This must be set to the main httpd.conf file for either Apache or Litespeed +MESSENGERV3HTTPS_CONF = "/usr/local/apache/conf/httpd.conf" + +# This can be set to either: +# "apache" - for servers running Apache v2.4+ or Litespeed using Apache +# configuration +# "litespeed" - for Litespeed or Openlitespeed +MESSENGERV3WEBSERVER = "apache" + +# On creation, set the MESSENGER_USER public_html directory permissions to +# Note: If you precreate this directory the following setting will be ignored +MESSENGERV3PERMS = "711" + +# On creation, set the MESSENGER_USER public_html directory group user to +# Note: If you precreate this directory the following setting will be ignored +MESSENGERV3GROUP = "nobody" + +# This is the web server configuration to allow PHP scripts to run. If left +# empty, the MESSENGER service will try to configure this. If this does not +# work, this should be set as an "Include /path/to/csf_php.conf" or similar +# file which must contain appropriate web server configuration to allow PHP +# scripts to run. This line will be included within each MESSENGER VirtualHost +# container. This will replace the [MESSENGERV3PHPHANDLER] line from the csf +# webserver template files +MESSENGERV3PHPHANDLER = "" + +# RECAPTCHA: +#------------------------------------------------------------------------------ +# The RECAPTCHA options provide a way for end-users that have blocked +# themselves in the firewall to unblock themselves. +# +# A valid Google ReCAPTCHA (v2) key set is required for this feature from: +# https://www.google.com/recaptcha/intro/index.html +# +# When configuring a new reCAPTCHA API key set you must ensure that the option +# for "Domain Name Validation" is unticked so that the same reCAPTCHA can be +# used for all domains hosted on the server. lfd then checks that the hostname +# of the request resolves to an IP on this server +# +# This feature requires the installation of the LWP::UserAgent perl module (see +# option URLGET for more details) +# +# The template used for this feature is /etc/csf/messenger/index.recaptcha.html +# +# Note: An unblock will fail if the end-users IP is located in a netblock, +# blocklist or CC_* deny entry +RECAPTCHA_SITEKEY = "" +RECAPTCHA_SECRET = "" + +# Send an email when an IP address successfully attempts to unblock themselves. +# This does not necessarily mean the IP was unblocked, only that the +# post-recaptcha unblock request was attempted +# +# Set to "0" to disable +RECAPTCHA_ALERT = "1" + +# If the server uses NAT then resolving the hostname to hosted IPs will likely +# not succeed. In that case, the external IP addresses must be listed as comma +# separated list here +RECAPTCHA_NAT = "" + +############################################################################### +# SECTION:lfd Clustering +############################################################################### +# lfd Clustering. This allows the configuration of an lfd cluster environment +# where a group of servers can share blocks and configuration option changes. +# Included are CLI and UI options to send requests to the cluster. +# +# See the readme.txt file for more information and details on setup and +# security risks. +# +# Set this to a comma separated list of cluster member IP addresses to send +# requests to. Alternatively, it can be set to the full path of a file that +# will read in one IP per line, e.g.: +# "/etc/csf/cluster_sendto.txt" +CLUSTER_SENDTO = "" + +# Set this to a comma separated list of cluster member IP addresses to receive +# requests from. Alternatively, it can be set to the full path of a file that +# will read in one IP per line, e.g.: +# "/etc/csf/cluster_recvfrom.txt" +CLUSTER_RECVFROM = "" + +# IP address of the master node in the cluster allowed to send CLUSTER_CONFIG +# changes +CLUSTER_MASTER = "" + +# If this is a NAT server, set this to the public IP address of this server +CLUSTER_NAT = "" + +# If a cluster member should send requests on an IP other than the default IP, +# set it here +CLUSTER_LOCALADDR = "" + +# Cluster communication port (must be the same on all member servers). There +# is no need to open this port in the firewall as csf will automatically add +# in and out bound rules to allow communication between cluster members +CLUSTER_PORT = "7777" + +# This is a secret key used to encrypt cluster communications using the +# Blowfish algorithm. It should be between 8 and 56 characters long, +# preferably > 20 random characters +# 56 chars: 01234567890123456789012345678901234567890123456789012345 +CLUSTER_KEY = "" + +# Automatically send lfd blocks to all members of CLUSTER_SENDTO. Those +# servers must have this servers IP address listed in their CLUSTER_RECVFROM +# +# Set to 0 to disable this feature +CLUSTER_BLOCK = "1" + +# This option allows the enabling and disabling of the Cluster configuration +# changing options --cconfig, --cconfigr, --cfile, --ccfile sent from the +# CLUSTER_MASTER server +# +# Set this option to 1 to allow Cluster configurations to be received +CLUSTER_CONFIG = "0" + +# Maximum number of child processes to listen on. High blocking rates or large +# clusters may need to increase this +CLUSTER_CHILDREN = "10" + +############################################################################### +# SECTION:Port Knocking +############################################################################### +# Port Knocking. This feature allows port knocking to be enabled on multiple +# ports with a variable number of knocked ports and a timeout. There must be a +# minimum of 3 ports to knock for an entry to be valid +# +# See the following for information regarding Port Knocking: +# http://www.portknocking.org/ +# +# This feature does not work on servers that do not have the iptables module +# ipt_recent loaded. Typically, this will be with MONOLITHIC kernels. VPS +# server admins should check with their VPS host provider that the iptables +# module is included +# +# For further information and syntax refer to the Port Knocking section of the +# csf readme.txt +# +# Note: Run /etc/csf/csftest.pl to check whether this option will function on +# this server +# +# openport;protocol;timeout;kport1;kport2;kport3[...;kportN],... +# e.g.: 22;TCP;20;100;200;300;400 +PORTKNOCKING = "" + +# Enable PORTKNOCKING logging by iptables +PORTKNOCKING_LOG = "1" + +# Send an email alert if the PORTKNOCKING port is opened. PORTKNOCKING_LOG must +# also be enabled to use this option +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +PORTKNOCKING_ALERT = "0" + +############################################################################### +# SECTION:Log Scanner +############################################################################### +# Log Scanner. This feature will send out an email summary of the log lines of +# each log listed in /etc/csf/csf.logfiles. All lines will be reported unless +# they match a regular expression in /etc/csf/csf.logignore +# +# File globbing is supported for logs listed in /etc/csf/csf.logfiles. However, +# be aware that the more files lfd has to track, the greater the performance +# hit. Note: File globs are only evaluated when lfd is started +# +# Note: lfd builds the report continuously from lines logged after lfd has +# started, so any lines logged when lfd is not running will not be reported +# (e.g. during reboot). If lfd is restarted, then the report will include any +# lines logged during the previous lfd logging period that weren't reported +# +# 1 to enable, 0 to disable +LOGSCANNER = "0" + +# This is the interval each report will be sent based on the logalert.txt +# template +# +# The interval can be set to: +# "hourly" - sent on the hour +# "daily" - sent at midnight (00:00) +# "manual" - sent whenever "csf --logrun" is run. This allows for scheduling +# via cron job +LOGSCANNER_INTERVAL = "hourly" + +# Report Style +# 1 = Separate chronological log lines per log file +# 2 = Simply chronological log of all lines +LOGSCANNER_STYLE = "1" + +# Send the report email even if no log lines reported +# 1 to enable, 0 to disable +LOGSCANNER_EMPTY = "1" + +# Maximum number of lines in the report before it is truncated. This is to +# prevent log lines flooding resulting in an excessively large report. This +# might need to be increased if you choose a daily report +LOGSCANNER_LINES = "5000" + +############################################################################### +# SECTION:Statistics Settings +############################################################################### +# Statistics +# +# Some of the Statistics output requires the gd graphics library and the +# GD::Graph perl module with all dependent modules to be installed for the UI +# for them to be displayed +# +# This option enabled statistical data gathering +ST_ENABLE = "1" + +# This option determines how many iptables log lines to store for reports +ST_IPTABLES = "100" + +# This option indicates whether rDNS and CC lookups are performed at the time +# the log line is recorded (this is not performed when viewing the reports) +# +# Warning: If DROP_IP_LOGGING is enabled and there are frequent iptables hits, +# then enabling this setting could cause serious performance problems +ST_LOOKUP = "0" + +# This option will gather basic system statstics. Through the UI it displays +# various graphs for disk, cpu, memory, network, etc usage over 4 intervals: +# . Hourly (per minute) +# . 24 hours (per minute) +# . 7 days (per minute averaged over an hour) +# . 30 days (per minute averaged over an hour) - user definable +# The data is stored in /var/lib/csf/stats/system and the option requires the +# perl GD::Graph module +# +# Note: Disk graphs do not show on Virtuozzo/OpenVZ servers as the kernel on +# those systems do not store the required information in /proc/diskstats +# On new installations or when enabling this option it will take time for these +# graphs to be populated +ST_SYSTEM = "1" + +# Set the maximum days to collect statistics for. The default is 30 days, the +# more data that is collected the longer it will take for each of the graphs to +# be generated +ST_SYSTEM_MAXDAYS = "30" + +# If ST_SYSTEM is enabled, then these options can collect MySQL statistical +# data. To use this option the server must have the perl modules DBI and +# DBD::mysql installed. +# +# Set this option to "0" to disable MySQL data collection +ST_MYSQL = "0" + +# The following options are for authentication for MySQL data collection. If +# the password is left blank and the user set to "root" then the procedure will +# look for authentication data in /root/.my.cnf. Otherwise, you will need to +# provide a MySQL username and password to collect the data. Any MySQL user +# account can be used +ST_MYSQL_USER = "root" +ST_MYSQL_PASS = "" +ST_MYSQL_HOST = "localhost" + +# If ST_SYSTEM is enabled, then this option can collect Apache statistical data +# The value for PT_APACHESTATUS must be correctly set +ST_APACHE = "0" + +# The following options measure disk write performance using dd (location set +# via the DD setting). It creates a 64MB file called /var/lib/dd_write_test and +# the statistics will plot the MB/s response time of the disk. As this is an IO +# intensive operation, it may not be prudent to run this test too often, so by +# default it is only run every 5 minutes and the result duplicated for each +# intervening minute for the statistics +# +# This is not necessrily a good measure of disk performance, primarily because +# the measurements are for relatively small amounts of data over a small amount +# of time. To properly test disk performance there are a variety of tools +# available that should be run for extended periods of time to obtain an +# accurate measurement. This metric is provided to give an idea of how the disk +# is performing over time +# +# Note: There is a 15 second timeout performing the check +# +# Set to 0 to disable, 1 to enable +ST_DISKW = "0" + +# The number of minutes that elapse between tests. Default is 5, minimum is 1. +ST_DISKW_FREQ = "5" + +# This is the command line passed to dd. If you are familiar with dd, or wish +# to move the output file (of) to a different disk, then you can alter this +# command. Take great care when making any changes to this command as it is +# very easy to overwrite a disk using dd if you make a mistake +ST_DISKW_DD = "if=/dev/zero of=/var/lib/csf/dd_test bs=1MB count=64 conv=fdatasync" + +############################################################################### +# SECTION:Docker Settings +############################################################################### +# This section provides the configuration of iptables rules to allow Docker +# containers to communicate through the host. If the generated rules do not +# work with your setup you will have to use a /etc/csf/csfpost.sh file and add +# your own iptables configuration instead +# +# 1 to enable, 0 to disable +DOCKER = "0" + +# The network device on the host +DOCKER_DEVICE = "docker0" + +# Docker container IPv4 range +DOCKER_NETWORK4 = "172.17.0.0/16" + +# Docker container IPv6 range. IPV6 must be enabled and the IPv6 nat table +# available (see IPv6 section). Leave blank to disable +DOCKER_NETWORK6 = "2001:db8:1::/64" + +############################################################################### +# SECTION:OS Specific Settings +############################################################################### +# Binary locations +IPTABLES = "/sbin/iptables" +IPTABLES_SAVE = "/sbin/iptables-save" +IPTABLES_RESTORE = "/sbin/iptables-restore" +IP6TABLES = "/sbin/ip6tables" +IP6TABLES_SAVE = "/sbin/ip6tables-save" +IP6TABLES_RESTORE = "/sbin/ip6tables-restore" +MODPROBE = "/sbin/modprobe" +IFCONFIG = "/sbin/ifconfig" +SENDMAIL = "/usr/sbin/sendmail" +PS = "/bin/ps" +VMSTAT = "/usr/bin/vmstat" +NETSTAT = "/bin/netstat" +LS = "/bin/ls" +MD5SUM = "/usr/bin/md5sum" +TAR = "/bin/tar" +CHATTR = "/usr/bin/chattr" +UNZIP = "/usr/bin/unzip" +GUNZIP = "/bin/gunzip" +DD = "/bin/dd" +TAIL = "/usr/bin/tail" +GREP = "/bin/grep" +ZGREP = "/usr/bin/zgrep" +IPSET = "/usr/sbin/ipset" +SYSTEMCTL = "/usr/bin/systemctl" +HOST = "/usr/bin/host" +IP = "/sbin/ip" +CURL = "/usr/bin/curl" +WGET = "/usr/bin/wget" + +# Log file locations +# +# File globbing is allowed for the following logs. However, be aware that the +# more files lfd has to track, the greater the performance hit +# +# Note: File globs are only evaluated when lfd is started +# +HTACCESS_LOG = "/usr/local/apache/logs/error_log" +MODSEC_LOG = "/usr/local/apache/logs/error_log" +SSHD_LOG = "/var/log/secure" +SU_LOG = "/var/log/secure" +SUDO_LOG = "/var/log/secure" +FTPD_LOG = "/var/log/messages" +SMTPAUTH_LOG = "/var/log/exim_mainlog" +SMTPRELAY_LOG = "/var/log/exim_mainlog" +POP3D_LOG = "/var/log/maillog" +IMAPD_LOG = "/var/log/maillog" +CPANEL_LOG = "/usr/local/cpanel/logs/login_log" +CPANEL_ACCESSLOG = "/usr/local/cpanel/logs/access_log" +SCRIPT_LOG = "/var/log/exim_mainlog" +IPTABLES_LOG = "/var/log/messages" +SUHOSIN_LOG = "/var/log/messages" +BIND_LOG = "/var/log/messages" +SYSLOG_LOG = "/var/log/messages" +WEBMIN_LOG = "/var/log/secure" + +CUSTOM1_LOG = "/var/log/customlog" +CUSTOM2_LOG = "/var/log/customlog" +CUSTOM3_LOG = "/var/log/customlog" +CUSTOM4_LOG = "/var/log/customlog" +CUSTOM5_LOG = "/var/log/customlog" +CUSTOM6_LOG = "/var/log/customlog" +CUSTOM7_LOG = "/var/log/customlog" +CUSTOM8_LOG = "/var/log/customlog" +CUSTOM9_LOG = "/var/log/customlog" + +# The following are comma separated lists used if LF_SELECT is enabled, +# otherwise they are not used. They are derived from the application returned +# from a regex match in /usr/local/csf/bin/regex.pm +# +# All ports default to tcp blocks. To specify udp or tcp use the format: +# port;protocol,port;protocol,... For example, "53;udp,53;tcp" +PORTS_pop3d = "110,995" +PORTS_imapd = "143,993" +PORTS_htpasswd = "80,443" +PORTS_mod_security = "80,443" +PORTS_mod_qos = "80,443" +PORTS_symlink = "80,443" +PORTS_suhosin = "80,443" +PORTS_cxs = "80,443" +PORTS_bind = "53;udp,53;tcp" +PORTS_ftpd = "20,21" +PORTS_webmin = "10000" +PORTS_cpanel = "2077,2078,2082,2083,2086,2087,2095,2096" +# This list is extended, if present, by the ports defined by +# /etc/chkservd/exim-* +PORTS_smtpauth = "25,465,587" +PORTS_eximsyntax = "25,465,587" +# This list is replaced, if present, by "Port" definitions in +# /etc/ssh/sshd_config +PORTS_sshd = "22" + +# For internal use only. You should not enable this option as it could cause +# instability in csf and lfd +DEBUG = "0" +############################################################################### diff --git a/csf/csf.cwp.allow b/csf/csf.cwp.allow new file mode 100644 index 0000000..19ec008 --- /dev/null +++ b/csf/csf.cwp.allow @@ -0,0 +1,30 @@ +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +# The following IP addresses will be allowed through iptables. +# One IP address per line. +# CIDR addressing allowed with a quaded IP (e.g. 192.168.254.0/24). +# Only list IP addresses, not domain names (they will be ignored) +# +# Advanced port+ip filtering allowed with the following format +# tcp/udp|in/out|s/d=port|s/d=ip +# See readme.txt for more information +# +# Note: IP addressess listed in this file will NOT be ignored by lfd, so they +# can still be blocked. If you do not want lfd to block an IP address you must +# add it to csf.ignore diff --git a/csf/csf.cwp.conf b/csf/csf.cwp.conf new file mode 100644 index 0000000..feae1b9 --- /dev/null +++ b/csf/csf.cwp.conf @@ -0,0 +1,2685 @@ +############################################################################### +# SECTION:Initial Settings +############################################################################### +# Testing flag - enables a CRON job that clears iptables incase of +# configuration problems when you start csf. This should be enabled until you +# are sure that the firewall works - i.e. incase you get locked out of your +# server! Then do remember to set it to 0 and restart csf when you're sure +# everything is OK. Stopping csf will remove the line from /etc/crontab +# +# lfd will not start while this is enabled +TESTING = "1" + +# The interval for the crontab in minutes. Since this uses the system clock the +# CRON job will run at the interval past the hour and not from when you issue +# the start command. Therefore an interval of 5 minutes means the firewall +# will be cleared in 0-5 minutes from the firewall start +TESTING_INTERVAL = "5" + +# SECURITY WARNING +# ================ +# +# Unfortunately, syslog and rsyslog allow end-users to log messages to some +# system logs via the same unix socket that other local services use. This +# means that any log line shown in these system logs that syslog or rsyslog +# maintain can be spoofed (they are exactly the same as real log lines). +# +# Since some of the features of lfd rely on such log lines, spoofed messages +# can cause false-positive matches which can lead to confusion at best, or +# blocking of any innocent IP address or making the server inaccessible at +# worst. +# +# Any option that relies on the log entries in the files listed in +# /etc/syslog.conf and /etc/rsyslog.conf should therefore be considered +# vulnerable to exploitation by end-users and scripts run by end-users. +# +# NOTE: Not all log files are affected as they may not use syslog/rsyslog +# +# The option RESTRICT_SYSLOG disables all these features that rely on affected +# logs. These options are: +# LF_SSHD LF_FTPD LF_IMAPD LF_POP3D LF_BIND LF_SUHOSIN LF_SSH_EMAIL_ALERT +# LF_SU_EMAIL_ALERT LF_CONSOLE_EMAIL_ALERT LF_DISTATTACK LF_DISTFTP +# LT_POP3D LT_IMAPD PS_INTERVAL UID_INTERVAL WEBMIN_LOG LF_WEBMIN_EMAIL_ALERT +# PORTKNOCKING_ALERT LF_SUDO_EMAIL_ALERT +# +# This list of options use the logs but are not disabled by RESTRICT_SYSLOG: +# ST_ENABLE SYSLOG_CHECK LOGSCANNER CUSTOM*_LOG +# +# The following options are still enabled by default on new installations so +# that, on balance, csf/lfd still provides expected levels of security: +# LF_SSHD LF_FTPD LF_POP3D LF_IMAPD LF_SSH_EMAIL_ALERT LF_SU_EMAIL_ALERT +# +# If you set RESTRICT_SYSLOG to "0" or "2" and enable any of the options listed +# above, it should be done with the knowledge that any of the those options +# that are enabled could be triggered by spoofed log lines and lead to the +# server being inaccessible in the worst case. If you do not want to take that +# risk you should set RESTRICT_SYSLOG to "1" and those features will not work +# but you will not be protected from the exploits that they normally help block +# +# The recommended setting for RESTRICT_SYSLOG is "3" to restrict who can access +# the syslog/rsyslog unix socket. +# +# For further advice on how to help mitigate these issues, see +# /etc/csf/readme.txt +# +# 0 = Allow those options listed above to be used and configured +# 1 = Disable all the options listed above and prevent them from being used +# 2 = Disable only alerts about this feature and do nothing else +# 3 = Restrict syslog/rsyslog access to RESTRICT_SYSLOG_GROUP ** RECOMMENDED ** +RESTRICT_SYSLOG = "0" + +# The following setting is used if RESTRICT_SYSLOG is set to 3. It restricts +# write access to the syslog/rsyslog unix socket(s). The group must not already +# exists in /etc/group before setting RESTRICT_SYSLOG to 3, so set the option +# to a unique name for the server +# +# You can add users to this group by changing /etc/csf/csf.syslogusers and then +# restarting lfd afterwards. This will create the system group and add the +# users from csf.syslogusers if they exist to that group and will change the +# permissions on the syslog/rsyslog unix socket(s). The socket(s) will be +# monitored and the permissions re-applied should syslog/rsyslog be restarted +# +# Using this option will prevent some legitimate logging, e.g. end-user cron +# job logs +# +# If you want to revert RESTRICT_SYSLOG to another option and disable this +# feature, change the setting of RESTRICT_SYSLOG and then restart lfd and then +# syslog/rsyslog and the unix sockets will be reset +RESTRICT_SYSLOG_GROUP = "mysyslog" + +# This options restricts the ability to modify settings within this file from +# the csf UI. Should the parent control panel be compromised, these restricted +# options could be used to further compromise the server. For this reason we +# recommend leaving this option set to at least "1" and if any of the +# restricted items need to be changed, they are done so from the root shell +# +# 0 = Unrestricted UI +# 1 = Restricted UI +# 2 = Disabled UI +RESTRICT_UI = "1" + +# Enabling auto updates creates a cron job called /etc/cron.d/csf_update which +# runs once per day to see if there is an update to csf+lfd and upgrades if +# available and restarts csf and lfd +# +# You should check for new version announcements at http://blog.configserver.com +AUTO_UPDATES = "1" + +############################################################################### +# SECTION:IPv4 Port Settings +############################################################################### +# Lists of ports in the following comma separated lists can be added using a +# colon (e.g. 30000:35000). + +# Some kernel/iptables setups do not perform stateful connection tracking +# correctly (typically some virtual servers or custom compiled kernels), so a +# SPI firewall will not function correctly. If this happens, LF_SPI can be set +# to 0 to reconfigure csf as a static firewall. +# +# As connection tracking will not be configured, applications that rely on it +# will not function unless all outgoing ports are opened. Therefore, all +# outgoing connections will be allowed once all other tests have completed. So +# TCP_OUT, UDP_OUT and ICMP_OUT will not have any affect. +# +# If you allow incoming DNS lookups you may need to use the following +# directive in the options{} section of your named.conf: +# +# query-source port 53; +# +# This will force incoming DNS traffic only through port 53 +# +# Disabling this option will break firewall functionality that relies on +# stateful packet inspection (e.g. DNAT, PACKET_FILTER) and makes the firewall +# less secure +# +# This option should be set to "1" in all other circumstances +LF_SPI = "1" + +# Allow incoming TCP ports +TCP_IN = "20,21,22,25,53,80,110,143,443,465,853,587,993,995,2030,2031,2082,2083,2086,2087,2095,2096" + +# Allow outgoing TCP ports +TCP_OUT = "20,21,22,25,53,80,110,113,443,853,587,993,995,2080,2443" + +# Allow incoming UDP ports +UDP_IN = "20,21,53,80,443,853" + +# Allow outgoing UDP ports +# To allow outgoing traceroute add 33434:33523 to this list +UDP_OUT = "20,21,53,113,123,853" + +# Allow incoming PING. Disabling PING will likely break external uptime +# monitoring +ICMP_IN = "1" + +# Set the per IP address incoming ICMP packet rate for PING requests. This +# ratelimits PING requests which if exceeded results in silently rejected +# packets. Disable or increase this value if you are seeing PING drops that you +# do not want +# +# To disable rate limiting set to "0", otherwise set according to the iptables +# documentation for the limit module. For example, "1/s" will limit to one +# packet per second +ICMP_IN_RATE = "1/s" + +# Allow outgoing PING +# +# Unless there is a specific reason, this option should NOT be disabled as it +# could break OS functionality +ICMP_OUT = "1" + +# Set the per IP address outgoing ICMP packet rate for PING requests. This +# ratelimits PING requests which if exceeded results in silently rejected +# packets. Disable or increase this value if you are seeing PING drops that you +# do not want +# +# Unless there is a specific reason, this option should NOT be enabled as it +# could break OS functionality +# +# To disable rate limiting set to "0", otherwise set according to the iptables +# documentation for the limit module. For example, "1/s" will limit to one +# packet per second +ICMP_OUT_RATE = "0" + +# For those with PCI Compliance tools that state that ICMP timestamps (type 13) +# should be dropped, you can enable the following option. Otherwise, there +# appears to be little evidence that it has anything to do with a security risk +# and can impact network performance, so should be left disabled by everyone +# else +ICMP_TIMESTAMPDROP = "0" + +############################################################################### +# SECTION:IPv6 Port Settings +############################################################################### +# IPv6: (Requires ip6tables) +# +# Pre v2.6.20 kernels do not perform stateful connection tracking, so a static +# firewall is configured as a fallback instead if IPV6_SPI is set to 0 below +# +# Supported: +# Temporary ACCEPT/DENY, GLOBAL_DENY, GLOBAL_ALLOW, SMTP_BLOCK, LF_PERMBLOCK, +# PACKET_FILTER, Advanced Allow/Deny Filters, RELAY_*, CLUSTER_*, CC6_LOOKUPS, +# SYNFLOOD, LF_NETBLOCK +# +# Supported if CC6_LOOKUPS and CC_LOOKUPS are enabled +# CC_DENY, CC_ALLOW, CC_ALLOW_FILTER, CC_IGNORE, CC_ALLOW_PORTS, CC_DENY_PORTS, +# CC_ALLOW_SMTPAUTH +# +# Supported if ip6tables >= 1.4.3: +# PORTFLOOD, CONNLIMIT +# +# Supported if ip6tables >= 1.4.17 and perl module IO::Socket::INET6 is +# installed: +# MESSENGER DOCKER SMTP_REDIRECT +# +# Not supported: +# ICMP_IN, ICMP_OUT +# +IPV6 = "0" + +# IPv6 uses icmpv6 packets very heavily. By default, csf will allow all icmpv6 +# traffic in the INPUT and OUTPUT chains. However, this could increase the risk +# of icmpv6 attacks. To restrict incoming icmpv6, set to "1" but may break some +# connection types +IPV6_ICMP_STRICT = "0" + +# Pre v2.6.20 kernel must set this option to "0" as no working state module is +# present, so a static firewall is configured as a fallback +# +# A workaround has been added for CentOS/RedHat v5 and custom kernels that do +# not support IPv6 connection tracking by opening ephemeral port range +# 32768:61000. This is only applied if IPV6_SPI is not enabled. This is the +# same workaround implemented by RedHat in the sample default IPv6 rules +# +# As connection tracking will not be configured, applications that rely on it +# will not function unless all outgoing ports are opened. Therefore, all +# outgoing connections will be allowed once all other tests have completed. So +# TCP6_OUT, UDP6_OUT and ICMP6_OUT will not have any affect. +# +# If you allow incoming ipv6 DNS lookups you may need to use the following +# directive in the options{} section of your named.conf: +# +# query-source-v6 port 53; +# +# This will force ipv6 incoming DNS traffic only through port 53 +# +# These changes are not necessary if the SPI firewall is used +IPV6_SPI = "1" + +# Allow incoming IPv6 TCP ports +TCP6_IN = "20,21,22,25,53,80,110,143,443,465,853,587,993,995,2030,2031,2082,2083,2086,2087,2095,2096" + +# Allow outgoing IPv6 TCP ports +TCP6_OUT = "20,21,22,25,53,80,110,113,443,853,587,993,995,2080,2443" + +# Allow incoming IPv6 UDP ports +UDP6_IN = "20,21,53,80,443,853" + +# Allow outgoing IPv6 UDP ports +# To allow outgoing traceroute add 33434:33523 to this list +UDP6_OUT = "20,21,53,113,123,853" + +############################################################################### +# SECTION:General Settings +############################################################################### +# By default, csf will auto-configure iptables to filter all traffic except on +# the loopback device. If you only want iptables rules applied to a specific +# NIC, then list it here (e.g. eth1, or eth+) +ETH_DEVICE = "" + +# By adding a device to this option, ip6tables can be configured only on the +# specified device. Otherwise, ETH_DEVICE and then the default setting will be +# used +ETH6_DEVICE = "" + +# If you don't want iptables rules applied to specific NICs, then list them in +# a comma separated list (e.g "eth1,eth2") +ETH_DEVICE_SKIP = "" + +# This option should be enabled unless the kernel does not support the +# "conntrack" module +# +# To use the deprecated iptables "state" module, change this to 0 +USE_CONNTRACK = "1" + +# Enable ftp helper via the iptables CT target on supporting kernels (v2.6.34+) +# instead of the current method via /proc/sys/net/netfilter/nf_conntrack_helper +# This will also remove the RELATED target from the global state iptables rule +# +# This is not needed (and will be ignored) if LF_SPI/IPV6_SPI is disabled or +# the raw tables do not exist. The USE_CONNTRACK option should be enabled +# +# To enable this option, set it to your FTP server listening port number +# (normally 21), do NOT set it to "1" +USE_FTPHELPER = "0" + +# Check whether syslog is running. Many of the lfd checks require syslog to be +# running correctly. This test will send a coded message to syslog every +# SYSLOG_CHECK seconds. lfd will check SYSLOG_LOG log lines for the coded +# message. If it fails to do so within SYSLOG_CHECK seconds an alert using +# syslogalert.txt is sent +# +# A value of between 300 and 3600 seconds is suggested. Set to 0 to disable +SYSLOG_CHECK = "0" + +# Enable this option if you want lfd to ignore (i.e. don't block) IP addresses +# listed in csf.allow in addition to csf.ignore (the default). This option +# should be used with caution as it would mean that IP's allowed through the +# firewall from infected PC's could launch attacks on the server that lfd +# would ignore +IGNORE_ALLOW = "0" + +# Enable the following option if you want to apply strict iptables rules to DNS +# traffic (i.e. relying on iptables connection tracking). Enabling this option +# could cause DNS resolution issues both to and from the server but could help +# prevent abuse of the local DNS server +DNS_STRICT = "0" + +# Enable the following option if you want to apply strict iptables rules to DNS +# traffic between the server and the nameservers listed in /etc/resolv.conf +# Enabling this option could cause DNS resolution issues both to and from the +# server but could help prevent abuse of the local DNS server +DNS_STRICT_NS = "0" + +# Limit the number of IP's kept in the /etc/csf/csf.deny file +# +# Care should be taken when increasing this value on servers with low memory +# resources or hard limits (such as Virtuozzo/OpenVZ) as too many rules (in the +# thousands) can sometimes cause network slowdown +# +# The value set here is the maximum number of IPs/CIDRs allowed +# if the limit is reached, the entries will be rotated so that the oldest +# entries (i.e. the ones at the top) will be removed and the latest is added. +# The limit is only checked when using csf -d (which is what lfd also uses) +# Set to 0 to disable limiting +# +# For implementations wishing to set this value significantly higher, we +# recommend using the IPSET option +DENY_IP_LIMIT = "200" + +# Limit the number of IP's kept in the temprary IP ban list. If the limit is +# reached the oldest IP's in the ban list will be removed and allowed +# regardless of the amount of time remaining for the block +# Set to 0 to disable limiting +DENY_TEMP_IP_LIMIT = "100" + +# Enable login failure detection daemon (lfd). If set to 0 none of the +# following settings will have any effect as the daemon won't start. +LF_DAEMON = "1" + +# Check whether csf appears to have been stopped and restart if necessary, +# unless TESTING is enabled above. The check is done every 300 seconds +LF_CSF = "1" + +# This option uses IPTABLES_SAVE, IPTABLES_RESTORE and IP6TABLES_SAVE, +# IP6TABLES_RESTORE in two ways: +# +# 1. On a clean server reboot the entire csf iptables configuration is saved +# and then restored where possible to provide a near instant firewall +# startup[*] +# +# 2. On csf restart or lfd reloading tables, CC_* as well as SPAMHAUS, DSHIELD, +# BOGON, TOR are loaded using this method in a fraction of the time than if +# this setting is disabled +# +# [*]Not supported on all OS platforms +# +# Set to "0" to disable this functionality +FASTSTART = "1" + +# This option allows you to use ipset v6+ for the following csf options: +# CC_* and /etc/csf/csf.blocklist, /etc/csf/csf.allow, /etc/csf/csf.deny, +# GLOBAL_DENY, GLOBAL_ALLOW, DYNDNS, GLOBAL_DYNDNS, MESSENGER +# +# ipset will only be used with the above options when listing IPs and CIDRs. +# Advanced Allow Filters and temporary blocks use traditional iptables +# +# Using ipset moves the onus of ip matching against large lists away from +# iptables rules and to a purpose built and optimised database matching +# utility. It also simplifies the switching in of updated lists +# +# To use this option you must have a fully functioning installation of ipset +# installed either via rpm or source from http://ipset.netfilter.org/ +# +# Note: Using ipset has many advantages, some disadvantages are that you will +# no longer see packet and byte counts against IPs and it makes identifying +# blocked/allowed IPs that little bit harder +# +# Note: If you mainly use IP address only entries in csf.deny, you can increase +# the value of DENY_IP_LIMIT significantly if you wish +# +# Note: It's highly unlikely that ipset will function on Virtuozzo/OpenVZ +# containers even if it has been installed +# +# If you find any problems, please post on forums.configserver.com with full +# details of the issue +LF_IPSET = "0" + +# Versions of iptables greater or equal to v1.4.20 should support the --wait +# option. This forces iptables commands that use the option to wait until a +# lock by any other process using iptables completes, rather than simply +# failing +# +# Enabling this feature will add the --wait option to iptables commands +# +# NOTE: The disadvantage of using this option is that any iptables command that +# uses it will hang until the lock is released. This could cause a cascade of +# hung processes trying to issue iptables commands. To try and avoid this issue +# csf uses a last ditch timeout, WAITLOCK_TIMEOUT in seconds, that will trigger +# a failure if reached +WAITLOCK = "0" +WAITLOCK_TIMEOUT = "300" + +# The following sets the hashsize for ipset sets, which must be a power of 2. +# +# Note: Increasing this value will consume more memory for all sets +# Default: "1024" +LF_IPSET_HASHSIZE = "1024" + +# The following sets the maxelem for ipset sets. +# +# Note: Increasing this value will consume more memory for all sets +# Default: "65536" +LF_IPSET_MAXELEM = "65536" + +# If you enable this option then whenever a CLI request to restart csf is used +# lfd will restart csf instead within LF_PARSE seconds +# +# This feature can be helpful for restarting configurations that cannot use +# FASTSTART +LFDSTART = "0" + +# Enable verbose output of iptables commands +VERBOSE = "1" + +# Drop out of order packets and packets in an INVALID state in iptables +# connection tracking +PACKET_FILTER = "1" + +# Perform reverse DNS lookups on IP addresses. (See also CC_LOOKUPS) +LF_LOOKUPS = "1" + +# Custom styling is possible in the csf UI. See the readme.txt for more +# information under "UI skinning and Mobile View" +# +# This option enables the use of custom styling. If the styling fails to work +# correctly, e.g. custom styling does not take into account a change in the +# standard csf UI, then disabling this option will return the standard UI +STYLE_CUSTOM = "0" + +# This option disables the presence of the Mobile View in the csf UI +STYLE_MOBILE = "1" + +############################################################################### +# SECTION:SMTP Settings +############################################################################### +# Block outgoing SMTP except for root, exim and mailman (forces scripts/users +# to use the exim/sendmail binary instead of sockets access). This replaces the +# protection as WHM > Tweak Settings > SMTP Tweaks +# +# This option uses the iptables ipt_owner/xt_owner module and must be loaded +# for it to work. It may not be available on some VPS platforms +# +# Note: Run /etc/csf/csftest.pl to check whether this option will function on +# this server +SMTP_BLOCK = "0" + +# If SMTP_BLOCK is enabled but you want to allow local connections to port 25 +# on the server (e.g. for webmail or web scripts) then enable this option to +# allow outgoing SMTP connections to the loopback device +SMTP_ALLOWLOCAL = "1" + +# This option redirects outgoing SMTP connections destined for remote servers +# for non-bypass users to the local SMTP server to force local relaying of +# email. Such email may require authentication (SMTP AUTH) +SMTP_REDIRECT = "0" + +# This is a comma separated list of the ports to block. You should list all +# ports that exim is configured to listen on +SMTP_PORTS = "25,465,587" + +# Always allow the following comma separated users and groups to bypass +# SMTP_BLOCK +# +# Note: root (UID:0) is always allowed +SMTP_ALLOWUSER = "" +SMTP_ALLOWGROUP = "mail,mailman" + +# This option will only allow SMTP AUTH to be advertised to the IP addresses +# listed in /etc/csf/csf.smtpauth on EXIM mail servers +# +# The additional option CC_ALLOW_SMTPAUTH can be used with this option to +# additionally restrict access to specific countries +# +# This is to help limit attempts at distributed attacks against SMTP AUTH which +# are difficult to achive since port 25 needs to be open to relay email +# +# The reason why this works is that if EXIM does not advertise SMTP AUTH on a +# connection, then SMTP AUTH will not accept logins, defeating the attacks +# without restricting mail relaying +# +# Note: csf and lfd must be restarted if /etc/csf/csf.smtpauth is modified so +# that the lookup file in /etc/exim.smtpauth is regenerated from the +# information from /etc/csf/csf.smtpauth plus any countries listed in +# CC_ALLOW_SMTPAUTH +# +# NOTE: To make this option work you MUST make the modifications to exim.conf +# as explained in "Exim SMTP AUTH Restriction" section in /etc/csf/readme.txt +# after enabling the option here, otherwise this option will not work +# +# To enable this option, set to 1 and make the exim configuration changes +# To disable this option, set to 0 and undo the exim configuration changes +SMTPAUTH_RESTRICT = "0" + +############################################################################### +# SECTION:Port Flood Settings +############################################################################### +# Enable SYN Flood Protection. This option configures iptables to offer some +# protection from tcp SYN packet DOS attempts. You should set the RATE so that +# false-positives are kept to a minimum otherwise visitors may see connection +# issues (check /var/log/messages for *SYNFLOOD Blocked*). See the iptables +# man page for the correct --limit rate syntax +# +# Note: This option should ONLY be enabled if you know you are under a SYN +# flood attack as it will slow down all new connections from any IP address to +# the server if triggered +SYNFLOOD = "0" +SYNFLOOD_RATE = "100/s" +SYNFLOOD_BURST = "150" + +# Connection Limit Protection. This option configures iptables to offer more +# protection from DOS attacks against specific ports. It can also be used as a +# way to simply limit resource usage by IP address to specific server services. +# This option limits the number of concurrent new connections per IP address +# that can be made to specific ports +# +# This feature does not work on servers that do not have the iptables module +# xt_connlimit loaded. Typically, this will be with MONOLITHIC kernels. VPS +# server admins should check with their VPS host provider that the iptables +# module is included +# +# For further information and syntax refer to the Connection Limit Protection +# section of the csf readme.txt +# +# Note: Run /etc/csf/csftest.pl to check whether this option will function on +# this server +CONNLIMIT = "" + +# Port Flood Protection. This option configures iptables to offer protection +# from DOS attacks against specific ports. This option limits the number of +# new connections per time interval that can be made to specific ports +# +# This feature does not work on servers that do not have the iptables module +# ipt_recent loaded. Typically, this will be with MONOLITHIC kernels. VPS +# server admins should check with their VPS host provider that the iptables +# module is included +# +# For further information and syntax refer to the Port Flood Protection +# section of the csf readme.txt +# +# Note: Run /etc/csf/csftest.pl to check whether this option will function on +# this server +PORTFLOOD = "" + +# Outgoing UDP Flood Protection. This option limits outbound UDP packet floods. +# These typically originate from exploit scripts uploaded through vulnerable +# web scripts. Care should be taken on servers that use services that utilise +# high levels of UDP outbound traffic, such as SNMP, so you may need to alter +# the UDPFLOOD_LIMIT and UDPFLOOD_BURST options to suit your environment +# +# We recommend enabling User ID Tracking (UID_INTERVAL) with this feature +UDPFLOOD = "0" +UDPFLOOD_LIMIT = "100/s" +UDPFLOOD_BURST = "500" + +# This is a list of usernames that should not be rate limited, such as "named" +# to prevent bind traffic from being limited. +# +# Note: root (UID:0) is always allowed +UDPFLOOD_ALLOWUSER = "named" + +############################################################################### +# SECTION:Logging Settings +############################################################################### +# Log lfd messages to SYSLOG in addition to /var/log/lfd.log. You must have the +# perl module Sys::Syslog installed to use this feature +SYSLOG = "0" + +# Drop target for incoming iptables rules. This can be set to either DROP or +# REJECT. REJECT will send back an error packet, DROP will not respond at all. +# REJECT is more polite, however it does provide extra information to a hacker +# and lets them know that a firewall is blocking their attempts. DROP hangs +# their connection, thereby frustrating attempts to port scan the server +DROP = "DROP" + +# Drop target for outgoing iptables rules. This can be set to either DROP or +# REJECT as with DROP, however as such connections are from this server it is +# better to REJECT connections to closed ports rather than to DROP them. This +# helps to immediately free up server resources rather than tying them up until +# a connection times out. It also tells the process making the connection that +# it has immediately failed +# +# It is possible that some monolithic kernels may not support the REJECT +# target. If this is the case, csf checks before using REJECT and falls back to +# using DROP, issuing a warning to set this to DROP instead +DROP_OUT = "REJECT" + +# Enable logging of dropped connections to blocked ports to syslog, usually +# /var/log/messages. This option needs to be enabled to use Port Scan Tracking +DROP_LOGGING = "1" + +# Enable logging of dropped incoming connections from blocked IP addresses +# +# This option will be disabled if you enable Port Scan Tracking (PS_INTERVAL) +DROP_IP_LOGGING = "0" + +# Enable logging of dropped outgoing connections +# +# Note: Only outgoing SYN packets for TCP connections are logged, other +# protocols log all packets +# +# We recommend that you enable this option +DROP_OUT_LOGGING = "1" + +# Together with DROP_OUT_LOGGING enabled, this option logs the UID connecting +# out (where available) which can help track abuse +DROP_UID_LOGGING = "1" + +# Only log incoming reserved port dropped connections (0:1023). This can reduce +# the amount of log noise from dropped connections, but will affect options +# such as Port Scan Tracking (PS_INTERVAL) +DROP_ONLYRES = "0" + +# Commonly blocked ports that you do not want logging as they tend to just fill +# up the log file. These ports are specifically blocked (applied to TCP and UDP +# protocols) for incoming connections +DROP_NOLOG = "23,67,68,111,113,135:139,445,500,513,520" + +# Log packets dropped by the packet filtering option PACKET_FILTER +DROP_PF_LOGGING = "0" + +# Log packets dropped by the Connection Limit Protection option CONNLIMIT. If +# this is enabled and Port Scan Tracking (PS_INTERVAL) is also enabled, IP +# addresses breaking the Connection Limit Protection will be blocked +CONNLIMIT_LOGGING = "0" + +# Enable logging of UDP floods. This should be enabled, especially with User ID +# Tracking enabled +UDPFLOOD_LOGGING = "1" + +# Send an alert if log file flooding is detected which causes lfd to skip log +# lines to prevent lfd from looping. If this alert is sent you should check the +# reported log file for the reason for the flooding +LOGFLOOD_ALERT = "0" + +############################################################################### +# SECTION:Reporting Settings +############################################################################### +# By default, lfd will send alert emails using the relevant alert template to +# the To: address configured within that template. Setting the following +# option will override the configured To: field in all lfd alert emails +# +# Leave this option empty to use the To: field setting in each alert template +LF_ALERT_TO = "" + +# By default, lfd will send alert emails using the relevant alert template from +# the From: address configured within that template. Setting the following +# option will override the configured From: field in all lfd alert emails +# +# Leave this option empty to use the From: field setting in each alert template +LF_ALERT_FROM = "" + +# By default, lfd will send all alerts using the SENDMAIL binary. To send using +# SMTP directly, you can set the following to a relaying SMTP server, e.g. +# "127.0.0.1". Leave this setting blank to use SENDMAIL +LF_ALERT_SMTP = "" + +# Block Reporting. lfd can run an external script when it performs and IP +# address block following for example a login failure. The following setting +# is to the full path of the external script which must be executable. See +# readme.txt for format details +# +# Leave this setting blank to disable +BLOCK_REPORT = "" + +# To also run an external script when a temporary block is unblocked. The +# following setting can be the full path of the external script which must be +# executable. See readme.txt for format details +# +# Leave this setting blank to disable +UNBLOCK_REPORT = "" + +# In addition to the standard lfd email alerts, you can additionally enable the +# sending of X-ARF reports (see http://www.xarf.org/specification.html). Only +# block alert messages will be sent. The reports use our schema at: +# https://download.configserver.com/abuse_login-attack_0.2.json +# +# These reports are in a format accepted by many Netblock owners and should +# help them investigate abuse. This option is not designed to automatically +# forward these reports to the Netblock owners and should be checked for +# false-positive blocks before reporting +# +# If available, the report will also include the abuse contact for the IP from +# the Abusix Contact DB: https://abusix.com/contactdb.html +# +# Note: The following block types are not reported through this feature: +# LF_PERMBLOCK, LF_NETBLOCK, LF_DISTATTACK, LF_DISTFTP, RT_*_ALERT +X_ARF = "0" + +# By default, lfd will send emails from the root forwarder. Setting the +# following option will override this +X_ARF_FROM = "" + +# By default, lfd will send emails to the root forwarder. Setting the following +# option will override this +X_ARF_TO = "" + +# If you want to automatically send reports to the abuse contact where found, +# you can enable the following option +# +# Note: You MUST set X_ARF_FROM to a valid email address for this option to +# work. This is so that the abuse contact can reply to the report +# +# However, you should be aware that without manual checking you could be +# reporting innocent IP addresses, including your own clients, yourself and +# your own servers +# +# Additionally, just because a contact address is found, does not mean that +# there is anyone on the end of it reading, processing or acting on such +# reports and you could conceivably reported for sending spam +# +# We do not recommend enabling this option. Abuse reports should be checked and +# verified before being forwarded to the abuse contact +X_ARF_ABUSE = "0" + +############################################################################### +# SECTION:Temp to Perm/Netblock Settings +############################################################################### +# Temporary to Permanent IP blocking. The following enables this feature to +# permanently block IP addresses that have been temporarily blocked more than +# LF_PERMBLOCK_COUNT times in the last LF_PERMBLOCK_INTERVAL seconds. Set +# LF_PERMBLOCK to "1" to enable this feature +# +# Care needs to be taken when setting LF_PERMBLOCK_INTERVAL as it needs to be +# at least LF_PERMBLOCK_COUNT multiplied by the longest temporary time setting +# (TTL) for blocked IPs, to be effective +# +# Set LF_PERMBLOCK to "0" to disable this feature +LF_PERMBLOCK = "1" +LF_PERMBLOCK_INTERVAL = "86400" +LF_PERMBLOCK_COUNT = "4" +LF_PERMBLOCK_ALERT = "1" + +# Permanently block IPs by network class. The following enables this feature +# to permanently block classes of IP address where individual IP addresses +# within the same class LF_NETBLOCK_CLASS have already been blocked more than +# LF_NETBLOCK_COUNT times in the last LF_NETBLOCK_INTERVAL seconds. Set +# LF_NETBLOCK to "1" to enable this feature +# +# This can be an affective way of blocking DDOS attacks launched from within +# the same network class +# +# Valid settings for LF_NETBLOCK_CLASS are "A", "B" and "C", care and +# consideration is required when blocking network classes A or B +# +# Set LF_NETBLOCK to "0" to disable this feature +LF_NETBLOCK = "0" +LF_NETBLOCK_INTERVAL = "86400" +LF_NETBLOCK_COUNT = "4" +LF_NETBLOCK_CLASS = "C" +LF_NETBLOCK_ALERT = "1" + +# Valid settings for LF_NETBLOCK_IPV6 are "/64", "/56", "/48", "/32" and "/24" +# Great care should be taken with IPV6 netblock ranges due to the large number +# of addresses involved +# +# To disable IPv6 netblocks set to "" +LF_NETBLOCK_IPV6 = "" + +############################################################################### +# SECTION:Global Lists/DYNDNS/Blocklists +############################################################################### +# Safe Chain Update. If enabled, all dynamic update chains (GALLOW*, GDENY*, +# SPAMHAUS, DSHIELD, BOGON, CC_ALLOW, CC_DENY, ALLOWDYN*) will create a new +# chain when updating, and insert it into the relevant LOCALINPUT/LOCALOUTPUT +# chain, then flush and delete the old dynamic chain and rename the new chain. +# +# This prevents a small window of opportunity opening when an update occurs and +# the dynamic chain is flushed for the new rules. +# +# This option should not be enabled on servers with long dynamic chains (e.g. +# CC_DENY/CC_ALLOW lists) and low memory. It should also not be enabled on +# Virtuozzo VPS servers with a restricted numiptent value. This is because each +# chain will effectively be duplicated while the update occurs, doubling the +# number of iptables rules +SAFECHAINUPDATE = "0" + +# If you wish to allow access from dynamic DNS records (for example if your IP +# address changes whenever you connect to the internet but you have a dedicated +# dynamic DNS record from the likes of dyndns.org) then you can list the FQDN +# records in csf.dyndns and then set the following to the number of seconds to +# poll for a change in the IP address. If the IP address has changed iptables +# will be updated. +# +# If the FQDN has multiple A records then all of the IP addresses will be +# processed. If IPV6 is enabled, then all IPv6 AAAA IP address records will +# also be allowed. +# +# A setting of 600 would check for IP updates every 10 minutes. Set the value +# to 0 to disable the feature +DYNDNS = "0" + +# To always ignore DYNDNS IP addresses in lfd blocking, set the following +# option to 1 +DYNDNS_IGNORE = "0" + +# The follow Global options allow you to specify a URL where csf can grab a +# centralised copy of an IP allow or deny block list of your own. You need to +# specify the full URL in the following options, i.e.: +# http://www.somelocation.com/allow.txt +# +# The actual retrieval of these IP's is controlled by lfd, so you need to set +# LF_GLOBAL to the interval (in seconds) when you want lfd to retrieve. lfd +# will perform the retrieval when it runs and then again at the specified +# interval. A sensible interval would probably be every 3600 seconds (1 hour). +# A minimum value of 300 is enforced for LF_GLOBAL if enabled +# +# You do not have to specify both an allow and a deny file +# +# You can also configure a global ignore file for IP's that lfd should ignore +LF_GLOBAL = "0" + +GLOBAL_ALLOW = "" +GLOBAL_DENY = "" +GLOBAL_IGNORE = "" + +# Provides the same functionality as DYNDNS but with a GLOBAL URL file. Set +# this to the URL of the file containing DYNDNS entries +GLOBAL_DYNDNS = "" + +# Set the following to the number of seconds to poll for a change in the IP +# address resoved from GLOBAL_DYNDNS +GLOBAL_DYNDNS_INTERVAL = "600" + +# To always ignore GLOBAL_DYNDNS IP addresses in lfd blocking, set the following +# option to 1 +GLOBAL_DYNDNS_IGNORE = "0" + +# Blocklists are controlled by modifying /etc/csf/csf.blocklists +# +# If you don't want BOGON rules applied to specific NICs, then list them in +# a comma separated list (e.g "eth1,eth2") +LF_BOGON_SKIP = "" + +# The following option can be used to select the method csf will use to +# retrieve URL data and files +# +# This can be set to use: +# +# 1. Perl module HTTP::Tiny +# 2. Perl module LWP::UserAgent +# 3. CURL/WGET (set location at the bottom of csf.conf if installed) +# +# HTTP::Tiny is much faster than LWP::UserAgent and is included in the csf +# distribution. LWP::UserAgent may have to be installed manually, but it can +# better support https:// URL's which also needs the LWP::Protocol::https perl +# module +# +# CURL/WGET uses the system binaries if installed but does not always provide +# good feedback when it fails. The script will first look for CURL, if that +# does not exist at the configured location it will then look for WGET +# +# Additionally, 1 or 2 are used and the retrieval fails, then if either CURL or +# WGET are available, an additional attempt will be using CURL/WGET. This is +# useful if the perl distribution has outdated modules that do not support +# modern SSL/TLS implementations +# +# To install the LWP perl modules required: +# +# On rpm based systems: +# +# yum install perl-libwww-perl.noarch perl-LWP-Protocol-https.noarch +# +# On APT based systems: +# +# apt-get install libwww-perl liblwp-protocol-https-perl +# +# Via cpan: +# +# perl -MCPAN -eshell +# cpan> install LWP LWP::Protocol::https +# +# We recommend setting this set to "2" or "3" as upgrades to csf will be +# performed over SSL as well as other URLs used when retrieving external data +# +# "1" = HTTP::Tiny +# "2" = LWP::UserAgent +# "3" = CURL/WGET (set location at the bottom of csf.conf) +URLGET = "2" + +# If you need csf/lfd to use a proxy, then you can set this option to the URL +# of the proxy. The proxy provided will be used for both HTTP and HTTPS +# connections +URLPROXY = "" + +############################################################################### +# SECTION:Country Code Lists and Settings +############################################################################### +# Country Code to CIDR allow/deny. In the following options you can allow or +# deny whole country CIDR ranges. The CIDR blocks are obtained from a selected +# source below. They also display Country Code Country and City for reported IP +# addresses and lookups +# +# There are a number of sources for these databases, before utilising them you +# need to visit each site and ensure you abide by their license provisions +# where stated: + +# 1. MaxMind +# +# MaxMind GeoLite2 Country/City and ASN databases at: +# https://dev.MaxMind.com/geoip/geoip2/geolite2/ +# This feature relies entirely on that service being available +# +# Advantages: This is a one stop shop for all of the databases required for +# these features. They provide a consistent dataset for blocking and reporting +# purposes +# +# Disadvantages: MaxMind require a license key to download their databases. +# This is free of charge, but requires the user to create an account on their +# website to generate the required key: +# +# WARNING: As of 2019-12-29, MaxMind REQUIRES you to create an account on their +# site and to generate a license key to use their databases. See: +# https://www.maxmind.com/en/geolite2/signup +# https://blog.maxmind.com/2019/12/18/significant-changes-to-accessing-and-using-geolite2-databases/ +# +# You MUST set the following to continue using the IP lookup features of csf, +# otherwise an error will be generated and the features will not work. +# Alternatively set CC_SRC below to a different provider +# +# MaxMind License Key: +MM_LICENSE_KEY = "" + +# 2. DB-IP, ipdeny.com, iptoasn.com +# +# Advantages: The ipdeny.com databases form CC blocking are better optimised +# and so are quicker to process and create fewer iptables entries. All of these +# databases are free to download without requiring login or key +# +# Disadvantages: Multiple sources mean that any one of the three could +# interrupt the provision of these features. It may also mean that there are +# inconsistences between them +# +# https://db-ip.com/db/lite.php +# http://ipdeny.com/ +# https://iptoasn.com/ +# http://download.geonames.org/export/dump/readme.txt + +# Set the following to your preferred source: +# +# "1" - MaxMind +# "2" - db-ip, ipdeny, iptoasn +# +# The default is "2" on new installations of csf, or set to "1" to use the +# MaxMind databases after obtaining a license key +CC_SRC = "2" + +# In the following options, specify the the two-letter ISO Country Code(s). +# The iptables rules are for incoming connections only +# +# Additionally, ASN numbers can also be added to the comma separated lists +# below that also list Country Codes. The same WARNINGS for Country Codes apply +# to the use of ASNs. More about Autonomous System Numbers (ASN): +# http://www.iana.org/assignments/as-numbers/as-numbers.xhtml +# ASNs must be listed as ASnnnn (where nnnn is the ASN number) +# +# You should consider using LF_IPSET when using any of the following options +# +# WARNING: These lists are never 100% accurate and some ISP's (e.g. AOL) use +# non-geographic IP address designations for their clients +# +# WARNING: Some of the CIDR lists are huge and each one requires a rule within +# the incoming iptables chain. This can result in significant performance +# overheads and could render the server inaccessible in some circumstances. For +# this reason (amongst others) we do not recommend using these options +# +# WARNING: Due to the resource constraints on VPS servers this feature should +# not be used on such systems unless you choose very small CC zones +# +# WARNING: CC_ALLOW allows access through all ports in the firewall. For this +# reason CC_ALLOW probably has very limited use and CC_ALLOW_FILTER is +# preferred +# +# Each option is a comma separated list of CC's, e.g. "US,GB,DE" +CC_DENY = "" +CC_ALLOW = "" + +# An alternative to CC_ALLOW is to only allow access from the following +# countries but still filter based on the port and packets rules. All other +# connections are dropped +CC_ALLOW_FILTER = "" + +# This option allows access from the following countries to specific ports +# listed in CC_ALLOW_PORTS_TCP and CC_ALLOW_PORTS_UDP +# +# Note: The rules for this feature are inserted after the allow and deny +# rules to still allow blocking of IP addresses +# +# Each option is a comma separated list of CC's, e.g. "US,GB,DE" +CC_ALLOW_PORTS = "" + +# All listed ports should be removed from TCP_IN/UDP_IN to block access from +# elsewhere. This option uses the same format as TCP_IN/UDP_IN +# +# An example would be to list port 21 here and remove it from TCP_IN/UDP_IN +# then only countries listed in CC_ALLOW_PORTS can access FTP +CC_ALLOW_PORTS_TCP = "" +CC_ALLOW_PORTS_UDP = "" + +# This option denies access from the following countries to specific ports +# listed in CC_DENY_PORTS_TCP and CC_DENY_PORTS_UDP +# +# Note: The rules for this feature are inserted after the allow and deny +# rules to still allow allowing of IP addresses +# +# Each option is a comma separated list of CC's, e.g. "US,GB,DE" +CC_DENY_PORTS = "" + +# This option uses the same format as TCP_IN/UDP_IN. The ports listed should +# NOT be removed from TCP_IN/UDP_IN +# +# An example would be to list port 21 here then countries listed in +# CC_DENY_PORTS cannot access FTP +CC_DENY_PORTS_TCP = "" +CC_DENY_PORTS_UDP = "" + +# This Country Code list will prevent lfd from blocking IP address hits for the +# listed CC's +# +# CC_LOOKUPS must be enabled to use this option +CC_IGNORE = "" + +# This Country Code list will only allow SMTP AUTH to be advertised to the +# listed countries in EXIM. This is to help limit attempts at distributed +# attacks against SMTP AUTH which are difficult to achive since port 25 needs +# to be open to relay email +# +# The reason why this works is that if EXIM does not advertise SMTP AUTH on a +# connection, then SMTP AUTH will not accept logins, defeating the attacks +# without restricting mail relaying +# +# This option can generate a very large list of IP addresses that could easily +# severely impact on SMTP (mail) performance, so care must be taken when +# selecting countries and if performance issues ensue +# +# The option SMTPAUTH_RESTRICT must be enabled to use this option +CC_ALLOW_SMTPAUTH = "" + +# These options can control which IP blocks are redirected to the MESSENGER +# service, if it is enabled +# +# If Country Codes are listed in CC_MESSENGER_ALLOW, then only a blocked IP +# that resolves to one of those Country Codes will be redirected to the +# MESSENGER service +# +# If Country Codes are listed in CC_MESSENGER_DENY, then a blocked IP that +# resolves to one of those Country Codes will NOT be redirected to the +# MESSENGER service +# +CC_MESSENGER_ALLOW = "" +CC_MESSENGER_DENY = "" + +# Set this option to a valid CIDR (i.e. 1 to 32) to ignore CIDR blocks smaller +# than this value when implementing CC_DENY/CC_ALLOW/CC_ALLOW_FILTER. This can +# help reduce the number of CC entries and may improve iptables throughput. +# Obviously, this will deny/allow fewer IP addresses depending on how small you +# configure the option +# +# For example, to ignore all CIDR (and single IP) entries small than a /16, set +# this option to "16". Set to "" to block all CC IP addresses +CC_DROP_CIDR = "" + +# Display Country Code and Country for reported IP addresses. This option can +# be configured to use the databases enabled at the top of this section. An +# additional option is also available if you cannot use those databases: +# +# "0" - disable +# "1" - Reports: Country Code and Country +# "2" - Reports: Country Code and Country and Region and City +# "3" - Reports: Country Code and Country and Region and City and ASN +# "4" - Reports: Country Code and Country and Region and City (db-ip.com) +# +# Note: "4" does not use the databases enabled at the top of this section +# directly for lookups. Instead it uses a URL-based lookup from +# https://db-ip.com and so avoids having to download and process the large +# databases. Please visit the https://db-ip.com and read their limitations and +# understand that this option will either cease to function or be removed by us +# if that site is abused or overloaded. ONLY use this option if you have +# difficulties using the databases enabled at the top of this section. This +# option is ONLY for IP lookups, NOT when using the CC_* options above, which +# will continue to use the databases enabled at the top of this section +# +CC_LOOKUPS = "1" + +# Display Country Code and Country for reported IPv6 addresses using the +# databases enabled at the top of this section +# +# "0" - disable +# "1" - enable and report the detail level as specified in CC_LOOKUPS +# +# This option must also be enabled to allow IPv6 support to CC_*, MESSENGER and +# PORTFLOOD +CC6_LOOKUPS = "0" + +# This option tells lfd how often to retrieve the databases for CC_ALLOW, +# CC_ALLOW_FILTER, CC_DENY, CC_IGNORE and CC_LOOKUPS (in days) +CC_INTERVAL = "14" + +############################################################################### +# SECTION:Login Failure Blocking and Alerts +############################################################################### +# The following[*] triggers are application specific. If you set LF_TRIGGER to +# "0" the value of each trigger is the number of failures against that +# application that will trigger lfd to block the IP address +# +# If you set LF_TRIGGER to a value greater than "0" then the following[*] +# application triggers are simply on or off ("0" or "1") and the value of +# LF_TRIGGER is the total cumulative number of failures that will trigger lfd +# to block the IP address +# +# Setting the application trigger to "0" disables it +LF_TRIGGER = "0" + +# If LF_TRIGGER is > "0" then LF_TRIGGER_PERM can be set to "1" to permanently +# block the IP address, or LF_TRIGGER_PERM can be set to a value greater than +# "1" and the IP address will be blocked temporarily for that value in seconds. +# For example: +# LF_TRIGGER_PERM = "1" => the IP is blocked permanently +# LF_TRIGGER_PERM = "3600" => the IP is blocked temporarily for 1 hour +# +# If LF_TRIGGER is "0", then the application LF_[application]_PERM value works +# in the same way as above and LF_TRIGGER_PERM serves no function +LF_TRIGGER_PERM = "1" + +# To only block access to the failed application instead of a complete block +# for an ip address, you can set the following to "1", but LF_TRIGGER must be +# set to "0" with specific application[*] trigger levels also set appropriately +# +# The ports that are blocked can be configured by changing the PORTS_* options +LF_SELECT = "0" + +# Send an email alert if an IP address is blocked by one of the [*] triggers +LF_EMAIL_ALERT = "1" + +# Send an email alert if an IP address is only temporarily blocked by one of +# the [*] triggers +# +# Note: LF_EMAIL_ALERT must still be enabled to get permanent block emails +LF_TEMP_EMAIL_ALERT = "1" + +# [*]Enable login failure detection of sshd connections +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_SSHD = "5" +LF_SSHD_PERM = "1" + +# [*]Enable login failure detection of ftp connections +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_FTPD = "10" +LF_FTPD_PERM = "1" + +# [*]Enable login failure detection of SMTP AUTH connections +LF_SMTPAUTH = "5" +LF_SMTPAUTH_PERM = "1" + +# [*]Enable syntax failure detection of Exim connections +LF_EXIMSYNTAX = "10" +LF_EXIMSYNTAX_PERM = "1" + +# [*]Enable login failure detection of pop3 connections +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_POP3D = "0" +LF_POP3D_PERM = "1" + +# [*]Enable login failure detection of imap connections +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_IMAPD = "0" +LF_IMAPD_PERM = "1" + +# [*]Enable login failure detection of Apache .htpasswd connections +# Due to the often high logging rate in the Apache error log, you might want to +# enable this option only if you know you are suffering from attacks against +# password protected directories +LF_HTACCESS = "5" +LF_HTACCESS_PERM = "1" + +# [*]Enable failure detection of repeated Apache mod_security rule triggers +LF_MODSEC = "5" +LF_MODSEC_PERM = "1" + +# [*]Enable login failure detection of CWP connections +LF_CWP = "0" +LF_CWP_PERM = "1" + +# [*]Enable detection of repeated BIND denied requests +# This option should be enabled with care as it will prevent blocked IPs from +# resolving any domains on the server. You might want to set the trigger value +# reasonably high to avoid this +# Example: LF_BIND = "100" +LF_BIND = "0" +LF_BIND_PERM = "1" + +# [*]Enable detection of repeated suhosin ALERTs +# Example: LF_SUHOSIN = "5" +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_SUHOSIN = "0" +LF_SUHOSIN_PERM = "1" + +# [*]Enable detection of repeated cxs ModSecurity mod_security rule triggers +# This option will block IP addresses if cxs detects a hits from the +# ModSecurity rule associated with it +# +# Note: This option takes precedence over LF_MODSEC and removes any hits +# counted towards LF_MODSEC for the cxs rule +# +# This setting should probably set very low, perhaps to 1, if you want to +# effectively block IP addresses for this trigger option +LF_CXS = "0" +LF_CXS_PERM = "1" + +# [*]Enable detection of repeated Apache mod_qos rule triggers +LF_QOS = "0" +LF_QOS_PERM = "1" + +# [*]Enable detection of repeated Apache symlink race condition triggers from +# the Apache patch provided by: +# http://www.mail-archive.com/dev@httpd.apache.org/msg55666.html +# This patch has also been included by cPanel via the easyapache option: +# "Symlink Race Condition Protection" +LF_SYMLINK = "0" +LF_SYMLINK_PERM = "1" + +# [*]Enable login failure detection of webmin connections +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_WEBMIN = "0" +LF_WEBMIN_PERM = "1" + +# Send an email alert if anyone logs in successfully using SSH +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_SSH_EMAIL_ALERT = "1" + +# Send an email alert if anyone uses su to access another account. This will +# send an email alert whether the attempt to use su was successful or not +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_SU_EMAIL_ALERT = "1" + +# Send an email alert if anyone uses sudo to access another account. This will +# send an email alert whether the attempt to use sudo was successful or not +# +# NOTE: This option could become onerous if sudo is used extensively for root +# access by administrators or control panels. It is provided for those where +# this is not the case +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_SUDO_EMAIL_ALERT = "0" + +# Send an email alert if anyone accesses webmin +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_WEBMIN_EMAIL_ALERT = "1" + +# Send an email alert if anyone logs in successfully to root on the console +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_CONSOLE_EMAIL_ALERT = "1" + +# This option will keep track of the number of "File does not exist" errors in +# HTACCESS_LOG. If the number of hits is more than LF_APACHE_404 in LF_INTERVAL +# seconds then the IP address will be blocked +# +# Care should be used with this option as it could generate many +# false-positives, especially Search Bots (use csf.rignore to ignore such bots) +# so only use this option if you know you are under this type of attack +# +# A sensible setting for this would be quite high, perhaps 200 +# +# To disable set to "0" +LF_APACHE_404 = "0" + +# If this option is set to 1 the blocks will be permanent +# If this option is > 1, the blocks will be temporary for the specified number +# of seconds +LF_APACHE_404_PERM = "3600" + +# This option will keep track of the number of "client denied by server +# configuration" errors in HTACCESS_LOG. If the number of hits is more than +# LF_APACHE_403 in LF_INTERVAL seconds then the IP address will be blocked +# +# Care should be used with this option as it could generate many +# false-positives, especially Search Bots (use csf.rignore to ignore such bots) +# so only use this option if you know you are under this type of attack +# +# A sensible setting for this would be quite high, perhaps 200 +# +# To disable set to "0" +LF_APACHE_403 = "0" + +# If this option is set to 1 the blocks will be permanent +# If this option is > 1, the blocks will be temporary for the specified number +# of seconds +LF_APACHE_403_PERM = "3600" + +# This option will keep track of the number of 401 failures in HTACCESS_LOG. +# If the number of hits is more than LF_APACHE_401 in LF_INTERVAL seconds then +# the IP address will be blocked +# +# To disable set to "0" +LF_APACHE_401 = "0" + +# This option is used to determine if the Apache error_log format contains the +# client port after the client IP. In Apache prior to v2.4, this was not the +# case. In Apache v2.4+ the error_log format can be configured using +# ErrorLogFormat, making the port directive optional +# +# Unfortunately v2.4 ErrorLogFormat places the port number after a colon next +# to the client IP by default. This makes determining client IPv6 addresses +# difficult unless we know whether the port is being appended or not +# +# lfd will attempt to autodetect the correct value if this option is set to "0" +# from the httpd binary found in common locations. If it fails to find a binary +# it will be set to "2", unless specified here +# +# The value can be set here explicitly if the autodetection does not work: +# 0 - autodetect +# 1 - no port directive after client IP +# 2 - port directive after client IP +LF_APACHE_ERRPORT = "0" + +# If this option is set to 1 the blocks will be permanent +# If this option is > 1, the blocks will be temporary for the specified number +# of seconds +LF_APACHE_401_PERM = "3600" + +# This option will send an alert if the ModSecurity IP persistent storage grows +# excessively large: https://goo.gl/rGh5sF +# +# More information on cPanel servers here: https://goo.gl/vo6xTE +# +# LF_MODSECIPDB_FILE must be set to the correct location of the database file +# +# The check is performed at lfd startup and then once per hour, the template +# used is modsecipdbalert.txt +# +# Set to "0" to disable this option, otherwise it is the threshold size of the +# file to report in gigabytes, e.g. set to 5 for 5GB +LF_MODSECIPDB_ALERT = "0" + +# This is the location of the persistent IP storage file on the server, e.g.: +# /var/run/modsecurity/data/ip.pag +# /var/cpanel/secdatadir/ip.pag +# /var/cache/modsecurity/ip.pag +# /usr/local/apache/conf/modsec/data/msa/ip.pag +# /var/tmp/ip.pag +# /tmp/ip.pag +LF_MODSECIPDB_FILE = "/var/run/modsecurity/data/ip.pag" + +# System Exploit Checking. This option is designed to perform a series of tests +# to send an alert in case a possible server compromise is detected +# +# To enable this feature set the following to the checking interval in seconds +# (a value of 300 would seem sensible). +# +# To disable set to "0" +LF_EXPLOIT = "300" + +# This comma separated list allows you to ignore tests LF_EXPLOIT performs +# +# For the SUPERUSER check, you can list usernames in csf.suignore to have them +# ignored for that test +# +# Valid tests are: +# SUPERUSER +# +# If you want to ignore a test add it to this as a comma separated list, e.g. +# "SUPERUSER" +LF_EXPLOIT_IGNORE = "" + +# Set the time interval to track login and other LF_ failures within (seconds), +# i.e. LF_TRIGGER failures within the last LF_INTERVAL seconds +LF_INTERVAL = "3600" + +# This is how long the lfd process sleeps (in seconds) before processing the +# log file entries and checking whether other events need to be triggered +LF_PARSE = "5" + +# This is the interval that is used to flush reports of usernames, files and +# pids so that persistent problems continue to be reported, in seconds. +# A value of 3600 seems sensible +LF_FLUSH = "3600" + +# Under some circumstances iptables can fail to include a rule instruction, +# especially if more than one request is made concurrently. In this event, a +# permanent block entry may exist in csf.deny, but not in iptables. +# +# This option instructs csf to deny an already blocked IP address the number +# of times set. The downside, is that there will be multiple entries for an IP +# address in csf.deny and possibly multiple rules for the same IP address in +# iptables. This needs to be taken into consideration when unblocking such IP +# addresses. +# +# Set to "0" to disable this feature. Do not set this too high for the reasons +# detailed above (e.g. "5" should be more than enough) +LF_REPEATBLOCK = "0" + +# By default csf will create both an inbound and outbound blocks from/to an IP +# unless otherwise specified in csf.deny and GLOBAL_DENY. This is the most +# effective way to block IP traffic. This option instructs csf to only block +# inbound traffic from those IP's and so reduces the number of iptables rules, +# but at the expense of less effectiveness. For this reason we recommend +# leaving this option disabled +# +# Set to "0" to disable this feature - the default +LF_BLOCKINONLY = "0" + +############################################################################### +# SECTION:CloudFlare +############################################################################### +# This features provides interaction with the CloudFlare Firewall +# +# As CloudFlare is a reverse proxy, any attacking IP addresses (so far as +# iptables is concerned) come from the CloudFlare IP's. To counter this, an +# Apache module (mod_cloudflare) is available that obtains the true attackers +# IP from a custom HTTP header record (similar functionality is available +# for other HTTP daemons +# +# However, despite now knowing the true attacking IP address, iptables cannot +# be used to block that IP as the traffic is still coming from the CloudFlare +# servers +# +# CloudFlare have provided a Firewall feature within the user account where +# rules can be added to block, challenge or whitelist IP addresses +# +# Using the CloudFlare API, this feature adds and removes attacking IPs from +# that firewall and provides CLI (and via the UI) additional commands +# +# See /etc/csf/readme.txt for more information about this feature and the +# restrictions for its use BEFORE enabling this feature +CF_ENABLE = "0" + +# This can be set to either "block" or "challenge" (see CloudFlare docs) +CF_BLOCK = "block" + +# This setting determines how long the temporary block will apply within csf +# and CloudFlare, keeping them in sync +# +# Block duration in seconds - overrides perm block or time of individual blocks +# in lfd for block triggers +CF_TEMP = "3600" + +############################################################################### +# SECTION:Directory Watching & Integrity +############################################################################### +# Enable Directory Watching. This enables lfd to check /tmp and /dev/shm +# directories for suspicious files, i.e. script exploits. If a suspicious +# file is found an email alert is sent. One alert per file per LF_FLUSH +# interval is sent +# +# To enable this feature set the following to the checking interval in seconds. +# To disable set to "0" +LF_DIRWATCH = "300" + +# To remove any suspicious files found during directory watching, enable the +# following. These files will be appended to a tarball in +# /var/lib/csf/suspicious.tar +LF_DIRWATCH_DISABLE = "0" + +# This option allows you to have lfd watch a particular file or directory for +# changes and should they change and email alert using watchalert.txt is sent +# +# To enable this feature set the following to the checking interval in seconds +# (a value of 60 would seem sensible) and add your entries to csf.dirwatch +# +# Set to disable set to "0" +LF_DIRWATCH_FILE = "0" + +# System Integrity Checking. This enables lfd to compare md5sums of the +# servers OS binary application files from the time when lfd starts. If the +# md5sum of a monitored file changes an alert is sent. This option is intended +# as an IDS (Intrusion Detection System) and is the last line of detection for +# a possible root compromise. +# +# There will be constant false-positives as the servers OS is updated or +# monitored application binaries are updated. However, unexpected changes +# should be carefully inspected. +# +# Modified files will only be reported via email once. +# +# To enable this feature set the following to the checking interval in seconds +# (a value of 3600 would seem sensible). This option may increase server I/O +# load onto the server as it checks system binaries. +# +# To disable set to "0" +LF_INTEGRITY = "3600" + +############################################################################### +# SECTION:Distributed Attacks +############################################################################### +# Distributed Account Attack. This option will keep track of login failures +# from distributed IP addresses to a specific application account. If the +# number of failures matches the trigger value above, ALL of the IP addresses +# involved in the attack will be blocked according to the temp/perm rules above +# +# Tracking applies to LF_SSHD, LF_FTPD, LF_SMTPAUTH, LF_POP3D, LF_IMAPD, +# LF_HTACCESS +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_DISTATTACK = "0" + +# Set the following to the minimum number of unique IP addresses that trigger +# LF_DISTATTACK +LF_DISTATTACK_UNIQ = "2" + +# Distributed FTP Logins. This option will keep track of successful FTP logins. +# If the number of successful logins to an individual account is at least +# LF_DISTFTP in LF_DIST_INTERVAL from at least LF_DISTFTP_UNIQ IP addresses, +# then all of the IP addresses will be blocked +# +# This option can help mitigate the common FTP account compromise attacks that +# use a distributed network of zombies to deface websites +# +# A sensible setting for this might be 5, depending on how many different +# IP addresses you expect to an individual FTP account within LF_DIST_INTERVAL +# +# To disable set to "0" +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_DISTFTP = "0" + +# Set the following to the minimum number of unique IP addresses that trigger +# LF_DISTFTP. LF_DISTFTP_UNIQ must be <= LF_DISTFTP for this to work +LF_DISTFTP_UNIQ = "3" + +# If this option is set to 1 the blocks will be permanent +# If this option is > 1, the blocks will be temporary for the specified number +# of seconds +LF_DISTFTP_PERM = "1" + +# Send an email alert if LF_DISTFTP is triggered +LF_DISTFTP_ALERT = "1" + +# Distributed SMTP Logins. This option will keep track of successful SMTP +# logins. If the number of successful logins to an individual account is at +# least LF_DISTSMTP in LF_DIST_INTERVAL from at least LF_DISTSMTP_UNIQ IP +# addresses, then all of the IP addresses will be blocked. These options only +# apply to the exim MTA +# +# This option can help mitigate the common SMTP account compromise attacks that +# use a distributed network of zombies to send spam +# +# A sensible setting for this might be 5, depending on how many different +# IP addresses you expect to an individual SMTP account within LF_DIST_INTERVAL +# +# To disable set to "0" +LF_DISTSMTP = "0" + +# Set the following to the minimum number of unique IP addresses that trigger +# LF_DISTSMTP. LF_DISTSMTP_UNIQ must be <= LF_DISTSMTP for this to work +LF_DISTSMTP_UNIQ = "3" + +# If this option is set to 1 the blocks will be permanent +# If this option is > 1, the blocks will be temporary for the specified number +# of seconds +LF_DISTSMTP_PERM = "1" + +# Send an email alert if LF_DISTSMTP is triggered +LF_DISTSMTP_ALERT = "1" + +# This is the interval during which a distributed FTP or SMTP attack is +# measured +LF_DIST_INTERVAL = "300" + +# If LF_DISTFTP or LF_DISTSMTP is triggered, then if the following contains the +# path to a script, it will run the script and pass the following as arguments: +# +# LF_DISTFTP/LF_DISTSMTP +# account name +# log file text +# +# The action script must have the execute bit and interpreter (shebang) set +LF_DIST_ACTION = "" + +############################################################################### +# SECTION:Login Tracking +############################################################################### +# Block POP3 logins if greater than LT_POP3D times per hour per account per IP +# address (0=disabled) +# +# This is a temporary block for the rest of the hour, afterwhich the IP is +# unblocked +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LT_POP3D = "0" + +# Block IMAP logins if greater than LT_IMAPD times per hour per account per IP +# address (0=disabled) - not recommended for IMAP logins due to the ethos +# within which IMAP works. If you want to use this, setting it quite high is +# probably a good idea +# +# This is a temporary block for the rest of the hour, afterwhich the IP is +# unblocked +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LT_IMAPD = "0" + +# Send an email alert if an account exceeds LT_POP3D/LT_IMAPD logins per hour +# per IP +LT_EMAIL_ALERT = "1" + +# If LF_PERMBLOCK is enabled but you do not want this to apply to +# LT_POP3D/LT_IMAPD, then enable this option +LT_SKIPPERMBLOCK = "0" + +############################################################################### +# SECTION:Connection Tracking +############################################################################### +# Connection Tracking. This option enables tracking of all connections from IP +# addresses to the server. If the total number of connections is greater than +# this value then the offending IP address is blocked. This can be used to help +# prevent some types of DOS attack. +# +# Care should be taken with this option. It's entirely possible that you will +# see false-positives. Some protocols can be connection hungry, e.g. FTP, IMAPD +# and HTTP so it could be quite easy to trigger, especially with a lot of +# closed connections in TIME_WAIT. However, for a server that is prone to DOS +# attacks this may be very useful. A reasonable setting for this option might +# be around 300. +# +# To disable this feature, set this to 0 +CT_LIMIT = "0" + +# Connection Tracking interval. Set this to the the number of seconds between +# connection tracking scans +CT_INTERVAL = "30" + +# Send an email alert if an IP address is blocked due to connection tracking +CT_EMAIL_ALERT = "1" + +# If you want to make IP blocks permanent then set this to 1, otherwise blocks +# will be temporary and will be cleared after CT_BLOCK_TIME seconds +CT_PERMANENT = "0" + +# If you opt for temporary IP blocks for CT, then the following is the interval +# in seconds that the IP will remained blocked for (e.g. 1800 = 30 mins) +CT_BLOCK_TIME = "1800" + +# If you don't want to count the TIME_WAIT state against the connection count +# then set the following to "1" +CT_SKIP_TIME_WAIT = "0" + +# If you only want to count specific states (e.g. SYN_RECV) then add the states +# to the following as a comma separated list. E.g. "SYN_RECV,TIME_WAIT" +# +# Leave this option empty to count all states against CT_LIMIT +CT_STATES = "" + +# If you only want to count specific ports (e.g. 80,443) then add the ports +# to the following as a comma separated list. E.g. "80,443" +# +# Leave this option empty to count all ports against CT_LIMIT +CT_PORTS = "" + +# If the total number of connections from a class C subnet is greater than this +# value then the offending subnet is blocked according to the other CT_* +# settings +# +# This option can be used to help prevent some types of DOS attack where a +# range of IP's between x.y.z.1-255 has connected to the server +# +# If you use a reverse proxy service such as Cloudflare you should not enable +# this option, or should exclude the ports that you have proxied in CT_PORTS +# +# To disable this feature, set this to 0 +CT_SUBNET_LIMIT = "0" + +############################################################################### +# SECTION:Process Tracking +############################################################################### +# Process Tracking. This option enables tracking of user and nobody processes +# and examines them for suspicious executables or open network ports. Its +# purpose is to identify potential exploit processes that are running on the +# server, even if they are obfuscated to appear as system services. If a +# suspicious process is found an alert email is sent with relevant information. +# It is then the responsibility of the recipient to investigate the process +# further as the script takes no further action +# +# The following is the number of seconds a process has to be active before it +# is inspected. If you set this time too low, then you will likely trigger +# false-positives with CGI or PHP scripts. +# Set the value to 0 to disable this feature +PT_LIMIT = "60" + +# How frequently processes are checked in seconds +PT_INTERVAL = "60" + +# If you want process tracking to highlight php or perl scripts that are run +# through apache then disable the following, +# i.e. set it to 0 +# +# While enabling this setting will reduce false-positives, having it set to 0 +# does provide better checking for exploits running on the server +PT_SKIP_HTTP = "0" + +# lfd will report processes, even if they're listed in csf.pignore, if they're +# tagged as (deleted) by Linux. This information is provided in Linux under +# /proc/PID/exe. A (deleted) process is one that is running a binary that has +# the inode for the file removed from the file system directory. This usually +# happens when the binary has been replaced due to an upgrade for it by the OS +# vendor or another third party (e.g. cPanel). You need to investigate whether +# this is indeed the case to be sure that the original binary has not been +# replaced by a rootkit or is running an exploit. +# +# Note: If a deleted executable process is detected and reported then lfd will +# not report children of the parent (or the parent itself if a child triggered +# the report) if the parent is also a deleted executable process +# +# To stop lfd reporting such process you need to restart the daemon to which it +# belongs and therefore run the process using the replacement binary (presuming +# one exists). This will normally mean running the associated startup script in +# /etc/init.d/ +# +# If you do want lfd to report deleted binary processes, set to 1 +PT_DELETED = "0" + +# If a PT_DELETED event is triggered, then if the following contains the path to +# a script, it will be run in a child process and passed the executable, pid, +# account for the process, and parent pid +# +# The action script must have the execute bit and interpreter (shebang) set. An +# example is provided in /usr/local/csf/bin/pt_deleted_action.pl +# +# WARNING: Make sure you read and understand the potential security +# implications of such processes in PT_DELETED above before simply restarting +# such processes with a script +PT_DELETED_ACTION = "" + +# User Process Tracking. This option enables the tracking of the number of +# process any given account is running at one time. If the number of processes +# exceeds the value of the following setting an email alert is sent with +# details of those processes. If you specify a user in csf.pignore it will be +# ignored +# +# Set to 0 to disable this feature +PT_USERPROC = "10" + +# This User Process Tracking option sends an alert if any user process exceeds +# the virtual memory usage set (MB). To ignore specific processes or users use +# csf.pignore +# +# Set to 0 to disable this feature +PT_USERMEM = "512" + +# This User Process Tracking option sends an alert if any user process exceeds +# the RSS memory usage set (MB) - RAM used, not virtual. To ignore specific +# processes or users use csf.pignore +# +# Set to 0 to disable this feature +PT_USERRSS = "256" + +# This User Process Tracking option sends an alert if any linux user process +# exceeds the time usage set (seconds). To ignore specific processes or users +# use csf.pignore +# +# Set to 0 to disable this feature +PT_USERTIME = "1800" + +# If this option is set then processes detected by PT_USERMEM, PT_USERTIME or +# PT_USERPROC are killed +# +# Warning: We don't recommend enabling this option unless absolutely necessary +# as it can cause unexpected problems when processes are suddenly terminated. +# It can also lead to system processes being terminated which could cause +# stability issues. It is much better to leave this option disabled and to +# investigate each case as it is reported when the triggers above are breached +# +# Note: Processes that are running deleted excecutables (see PT_DELETED) will +# not be killed by lfd +PT_USERKILL = "0" + +# If you want to disable email alerts if PT_USERKILL is triggered, then set +# this option to 0 +PT_USERKILL_ALERT = "1" + +# If a PT_* event is triggered, then if the following contains the path to +# a script, it will be run in a child process and passed the PID(s) of the +# process(es) in a comma separated list. +# +# The action script must have the execute bit and interpreter (shebang) set +PT_USER_ACTION = "" + +# Check the PT_LOAD_AVG minute Load Average (can be set to 1 5 or 15 and +# defaults to 5 if set otherwise) on the server every PT_LOAD seconds. If the +# load average is greater than or equal to PT_LOAD_LEVEL then an email alert is +# sent. lfd then does not report subsequent high load until PT_LOAD_SKIP +# seconds has passed to prevent email floods. +# +# Set PT_LOAD to "0" to disable this feature +PT_LOAD = "30" +PT_LOAD_AVG = "5" +PT_LOAD_LEVEL = "6" +PT_LOAD_SKIP = "3600" + +# This is the Apache Server Status URL used in the email alert. Requires the +# Apache mod_status module to be installed and configured correctly +PT_APACHESTATUS = "http://127.0.0.1/server-status" + +# If a PT_LOAD event is triggered, then if the following contains the path to +# a script, it will be run in a child process. For example, the script could +# contain commands to terminate and restart httpd, php, exim, etc incase of +# looping processes. The action script must have the execute bit an +# interpreter (shebang) set +PT_LOAD_ACTION = "" + +# Fork Bomb Protection. This option checks the number of processes with the +# same session id and if greater than the value set, the whole session tree is +# terminated and an alert sent +# +# You can see an example of common session id processes on most Linux systems +# using: "ps axf -O sid" +# +# On cPanel servers, PT_ALL_USERS should be enabled to use this option +# effectively +# +# This option will check root owned processes. Session id 0 and 1 will always +# be ignored as they represent kernel and init processes. csf.pignore will be +# honoured, but bear in mind that a session tree can contain a variety of users +# and executables +# +# Care needs to be taken to ensure that this option only detects runaway fork +# bombs, so should be set higher than any session tree is likely to get (e.g. +# httpd could have 100s of legitimate children on very busy systems). A +# sensible starting point on most servers might be 250 +PT_FORKBOMB = "0" + +# Terminate hung SSHD sessions. When under an SSHD login attack, SSHD processes +# are often left hanging after their connecting IP addresses have been blocked +# +# This option will terminate the SSH processes created by the blocked IP. This +# option is preferred over PT_SSHDHUNG +PT_SSHDKILL = "0" + +# This option will terminate all processes with the cmdline of "sshd: unknown +# [net]" or "sshd: unknown [priv]" if they have been running for more than 60 +# seconds +PT_SSHDHUNG = "0" + +############################################################################### +# SECTION:Port Scan Tracking +############################################################################### +# Port Scan Tracking. This feature tracks port blocks logged by iptables to +# syslog. If an IP address generates a port block that is logged more than +# PS_LIMIT within PS_INTERVAL seconds, the IP address will be blocked. +# +# This feature could, for example, be useful for blocking hackers attempting +# to access the standard SSH port if you have moved it to a port other than 22 +# and have removed 22 from the TCP_IN list so that connection attempts to the +# old port are being logged +# +# This feature blocks all iptables blocks from the iptables logs, including +# repeated attempts to one port or SYN flood blocks, etc +# +# Note: This feature will only track iptables blocks from the log file set in +# IPTABLES_LOG below and if you have DROP_LOGGING enabled. However, it will +# cause redundant blocking with DROP_IP_LOGGING enabled +# +# Warning: It's possible that an elaborate DDOS (i.e. from multiple IP's) +# could very quickly fill the iptables rule chains and cause a DOS in itself. +# The DENY_IP_LIMIT should help to mitigate such problems with permanent blocks +# and the DENY_TEMP_IP_LIMIT with temporary blocks +# +# Set PS_INTERVAL to "0" to disable this feature. A value of between 60 and 300 +# would be sensible to enable this feature +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +PS_INTERVAL = "0" +PS_LIMIT = "10" + +# You can specify the ports and/or port ranges that should be tracked by the +# Port Scan Tracking feature. The following setting is a comma separated list +# of those ports and uses the same format as TCP_IN. The setting of +# 0:65535,ICMP,INVALID,OPEN,BRD covers all ports +# +# Special values are: +# ICMP - include ICMP blocks (see ICMP_*) +# INVALID - include INVALID blocks (see PACKET_FILTER) +# OPEN - include TCP_IN and UDP_IN open port blocks - *[proto]_IN Blocked* +# BRD - include UDP Broadcast IPs, otherwise they are ignored +PS_PORTS = "0:65535,ICMP" + +# To specify how many different ports qualifies as a Port Scan you can increase +# the following from the default value of 1. The risk in doing so will mean +# that persistent attempts to attack a specific closed port will not be +# detected and blocked +PS_DIVERSITY = "1" + +# You can select whether IP blocks for Port Scan Tracking should be temporary +# or permanent. Set PS_PERMANENT to "0" for temporary and "1" for permanent +# blocking. If set to "0" PS_BLOCK_TIME is the amount of time in seconds to +# temporarily block the IP address for +PS_PERMANENT = "0" +PS_BLOCK_TIME = "3600" + +# Set the following to "1" to enable Port Scan Tracking email alerts, set to +# "0" to disable them +PS_EMAIL_ALERT = "1" + +############################################################################### +# SECTION:User ID Tracking +############################################################################### +# User ID Tracking. This feature tracks UID blocks logged by iptables to +# syslog. If a UID generates a port block that is logged more than UID_LIMIT +# times within UID_INTERVAL seconds, an alert will be sent +# +# Note: This feature will only track iptables blocks from the log file set in +# IPTABLES_LOG and if DROP_OUT_LOGGING and DROP_UID_LOGGING are enabled. +# +# To ignore specific UIDs list them in csf.uidignore and then restart lfd +# +# Set UID_INTERVAL to "0" to disable this feature. A value of between 60 and 300 +# would be sensible to enable this feature +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +UID_INTERVAL = "0" +UID_LIMIT = "10" + +# You can specify the ports and/or port ranges that should be tracked by the +# User ID Tracking feature. The following setting is a comma separated list +# of those ports and uses the same format as TCP_OUT. The default setting of +# 0:65535,ICMP covers all ports +UID_PORTS = "0:65535,ICMP" + +############################################################################### +# SECTION:Account Tracking +############################################################################### +# Account Tracking. The following options enable the tracking of modifications +# to the accounts on a server. If any of the enabled options are triggered by +# a modifications to an account, an alert email is sent. Only the modification +# is reported. The cause of the modification will have to be investigated +# manually +# +# You can set AT_ALERT to the following: +# 0 = disable this feature +# 1 = enable this feature for all accounts +# 2 = enable this feature only for superuser accounts (UID = 0, e.g. root, etc) +# 3 = enable this feature only for the root account +AT_ALERT = "2" + +# This options is the interval between checks in seconds +AT_INTERVAL = "60" + +# Send alert if a new account is created +AT_NEW = "1" + +# Send alert if an existing account is deleted +AT_OLD = "1" + +# Send alert if an account password has changed +AT_PASSWD = "1" + +# Send alert if an account uid has changed +AT_UID = "1" + +# Send alert if an account gid has changed +AT_GID = "1" + +# Send alert if an account login directory has changed +AT_DIR = "1" + +# Send alert if an account login shell has changed +AT_SHELL = "1" + +############################################################################### +# SECTION:Integrated User Interface +############################################################################### +# Integrated User Interface. This feature provides a HTML UI to csf and lfd, +# without requiring a control panel or web server. The UI runs as a sub process +# to the lfd daemon +# +# As it runs under the root account and successful login provides root access +# to the server, great care should be taken when configuring and using this +# feature. There are additional restrictions to enhance secure access to the UI +# +# See readme.txt for more information about using this feature BEFORE enabling +# it for security and access reasons +# +# 1 to enable, 0 to disable +UI = "0" + +# Set this to the port that want to bind this service to. You should configure +# this port to be >1023 and different from any other port already being used +# +# Do NOT enable access to this port in TCP_IN, instead only allow trusted IP's +# to the port using Advanced Allow Filters (see readme.txt) +UI_PORT = "6666" + +# Optionally set the IP address to bind to. Normally this should be left blank +# to bind to all IP addresses on the server. +# +# If the server is configured for IPv6 but the IP to bind to is IPv4, then the +# IP address MUST use the IPv6 representation. For example 1.2.3.4 must use +# ::ffff:1.2.3.4 +# +# Leave blank to bind to all IP addresses on the server +UI_IP = "" + +# This should be a secure, hard to guess username +# +# This must be changed from the default +UI_USER = "username" + +# This should be a secure, hard to guess password. That is, at least 8 +# characters long with a mixture of upper and lowercase characters plus +# numbers and non-alphanumeric characters +# +# This must be changed from the default +UI_PASS = "password" + +# This is the login session timeout. If there is no activity for a logged in +# session within this number of seconds, the session will timeout and a new +# login will be required +# +# For security reasons, you should always keep this option low (i.e 60-300) +UI_TIMEOUT = "300" + +# This is the maximum concurrent connections allowed to the server. The default +# value should be sufficient +UI_CHILDREN = "5" + +# The number of login retries allowed within a 24 hour period. A successful +# login from the IP address will clear the failures +# +# For security reasons, you should always keep this option low (i.e 0-10) +UI_RETRY = "5" + +# If enabled, this option will add the connecting IP address to the file +# /etc/csf/ui/ui.ban after UI_RETRY login failures. The IP address will not be +# able to login to the UI while it is listed in this file. The UI_BAN setting +# does not refer to any of the csf/lfd allow or ignore files, e.g. csf.allow, +# csf.ignore, etc. +# +# For security reasons, you should always enable this option +UI_BAN = "1" + +# If enabled, only IPs (or CIDR's) listed in the file /etc/csf/ui/ui.allow will +# be allowed to login to the UI. The UI_ALLOW setting does not refer to any of +# the csf/lfd allow or ignore files, e.g. csf.allow, csf.ignore, etc. +# +# For security reasons, you should always enable this option and use ui.allow +UI_ALLOW = "1" + +# If enabled, this option will trigger an iptables block through csf after +# UI_RETRY login failures +# +# 0 = no block;1 = perm block;nn=temp block for nn secs +UI_BLOCK = "1" + +# This controls what email alerts are sent with regards to logins to the UI. It +# uses the uialert.txt template +# +# 4 = login success + login failure/ban/block + login attempts +# 3 = login success + login failure/ban/block +# 2 = login failure/ban/block +# 1 = login ban/block +# 0 = disabled +UI_ALERT = "4" + +# This is the SSL cipher list that the Integrated UI will negotiate from +UI_CIPHER = "ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:-LOW:-SSLv2:-EXP:!kEDH" + +# This is the SSL protocol version used. See IO::Socket::SSL if you wish to +# change this and to understand the implications of changing it +UI_SSL_VERSION = "SSLv23:!SSLv3:!SSLv2" + +# If cxs is installed then enabling this option will provide a dropdown box to +# switch between applications +UI_CXS = "0" + +# There is a modified installation of ConfigServer Explorer (cse) provided with +# the csf distribution. If this option is enabled it will provide a dropdown +# box to switch between applications +UI_CSE = "0" + +############################################################################### +# SECTION:Messenger service +############################################################################### +# Messenger service. This feature allows the display of a message to a blocked +# connecting IP address to inform the user that they are blocked in the +# firewall. This can help when users get themselves blocked, e.g. due to +# multiple login failures. The service is provided by two daemons running on +# ports providing either an HTML or TEXT message +# +# This feature does not work on servers that do not have the iptables module +# ipt_REDIRECT loaded. Typically, this will be with MONOLITHIC kernels. VPS +# server admins should check with their VPS host provider that the iptables +# module is included +# +# IPv6 will need the IO::Socket::INET6 perl module +# +# For further information on features and limitations refer to the csf +# readme.txt +# +# Note: Run /etc/csf/csftest.pl to check whether this option will function on +# this server +# +# 1 to enable, 0 to disable +MESSENGER = "0" + +# Provide this service to temporary IP address blocks +MESSENGER_TEMP = "1" + +# Provide this service to permanent IP address blocks +MESSENGER_PERM = "1" + +# User account to run the service servers under. We recommend creating a +# specific non-priv, non-shell account for this purpose +# +# Note: When using MESSENGERV2, this account must NOT be a valid control panel +# account, it must be created manually as explained in the csf readme.txt +MESSENGER_USER = "csf" + +# This option points to the file(s) containing the Apache VirtualHost SSL +# definitions. This can be a file glob if there are multiple files to search. +# Only Apache v2 SSL VirtualHost definitions are supported +# +# This is used by MESSENGERV1 and MESSENGERV2 only +MESSENGER_HTTPS_CONF = "/etc/httpd/conf.d/ssl.conf" + +# The following options can be specified to provide a default fallback +# certificate to be used if either SNI is not supported or a hosted domain does +# not have an SSL certificate. If a fallback is not provided, one of the certs +# obtained from MESSENGER_HTTPS_CONF will be used +# +# This is used by MESSENGERV1 and MESSENGERV2 only +MESSENGER_HTTPS_KEY = "/etc/pki/tls/private/localhost.key" +MESSENGER_HTTPS_CRT = "/etc/pki/tls/certs/localhost.crt" + +# Set this to the port that will receive the HTTPS HTML message. You should +# configure this port to be >1023 and different from the TEXT and HTML port. Do +# NOT enable access to this port in TCP_IN. This option requires the perl +# module IO::Socket::SSL at a version level that supports SNI (1.83+). +# Additionally the version of openssl on the server must also support SNI +# +# The option uses existing SSL certificates on the server for each domain to +# maintain a secure connection without browser warnings. It uses SNI to choose +# the correct certificate to use for each client connection +# +# Warning: On some servers the amount of memory used by the HTTPS MESSENGER +# service can become significant depending on various factors associated with +# the use of IO::Socket::SSL including the number of domains and certificates +# served. This is normally only an issue if using MESSENGERV1 +MESSENGER_HTTPS = "8887" + +# This comma separated list are the HTTPS HTML ports that will be redirected +# for the blocked IP address. If you are using per application blocking +# (LF_TRIGGER) then only the relevant block port will be redirected to the +# messenger port +# +# Recommended setting "443" plus any end-user control panel SSL ports. So, for +# cPanel: "443,2083,2096" +MESSENGER_HTTPS_IN = "443" + +# Set this to the port that will receive the HTML message. You should configure +# this port to be >1023 and different from the TEXT port. Do NOT enable access +# to this port in TCP_IN +MESSENGER_HTML = "8888" + +# This comma separated list are the HTML ports that will be redirected for the +# blocked IP address. If you are using per application blocking (LF_TRIGGER) +# then only the relevant block port will be redirected to the messenger port +MESSENGER_HTML_IN = "80" + +# Set this to the port that will receive the TEXT message. You should configure +# this port to be >1023 and different from the HTML port. Do NOT enable access +# to this port in TCP_IN +MESSENGER_TEXT = "8889" + +# This comma separated list are the TEXT ports that will be redirected for the +# blocked IP address. If you are using per application blocking (LF_TRIGGER) +# then only the relevant block port will be redirected to the messenger port +MESSENGER_TEXT_IN = "21" + +# These settings limit the rate at which connections can be made to the +# messenger service servers. Its intention is to provide protection from +# attacks or excessive connections to the servers. If the rate is exceeded then +# iptables will revert for the duration to the normal blocking activity +# +# See the iptables man page for the correct --limit rate syntax +MESSENGER_RATE = "100/s" +MESSENGER_BURST = "150" + +# MESSENGERV1 only: +#------------------------------------------------------------------------------ +# This is the maximum concurrent connections allowed to each service server +# +# Note: This number should be increased to cater for the number of local images +# served by this page, including one for favicon.ico. This is because each +# image displayed counts as an additional connection +MESSENGER_CHILDREN = "20" + +# This options ignores ServerAlias definitions that begin with "mail.". This +# can help reduce memory usage on systems that do not require the use of +# MESSENGER_HTTPS on those subdomains +# +# Set to 0 to include these ServerAlias definitions +MESSENGER_HTTPS_SKIPMAIL = "1" + +# MESSENGERV2 only: +#------------------------------------------------------------------------------ +# MESSENGERV2. This option is available on cPanel servers running Apache v2.4+ +# under EA4. +# +# This uses the Apache http daemon to provide the web server functionality for +# the MESSENGER HTML and HTTPS services. It uses a fraction of the resources +# that the lfd inbuilt service uses and overcomes the memory overhead of using +# the MESSENGER HTTPS service +# +# For more information consult readme.txt before enabling this option +#MESSENGERV2 = "0" + +# MESSENGERV3 only: +#------------------------------------------------------------------------------ +# MESSENGERV3. This option is available on any server running Apache v2.4+, +# Litespeed or Openlitespeed +# +# This uses the web server http daemon to provide the web server functionality +# for the MESSENGER HTML and HTTPS services. It uses a fraction of the +# resources that the lfd inbuilt service uses and overcomes the memory overhead +# of using the MESSENGER HTTPS service +# +# For more information consult readme.txt before enabling this option +MESSENGERV3 = "0" + +# This is the file or directory where the additional web server configuration +# file should be included +MESSENGERV3LOCATION = "/etc/httpd/conf.d/" + +# This is the command to restart the web server +MESSENGERV3RESTART = "service httpd restart" + +# This is the command to test the validity of the web server configuration. If +# using Litespeed, set to "" +MESSENGERV3TEST = "/usr/sbin/apachectl -t" + +# This must be set to the main httpd.conf file for either Apache or Litespeed +MESSENGERV3HTTPS_CONF = "/etc/httpd/conf/httpd.conf" + +# This can be set to either: +# "apache" - for servers running Apache v2.4+ or Litespeed using Apache +# configuration +# "litespeed" - for Litespeed or Openlitespeed +MESSENGERV3WEBSERVER = "apache" + +# On creation, set the MESSENGER_USER public_html directory permissions to +# Note: If you precreate this directory the following setting will be ignored +MESSENGERV3PERMS = "711" + +# On creation, set the MESSENGER_USER public_html directory group user to +# Note: If you precreate this directory the following setting will be ignored +MESSENGERV3GROUP = "nobody" + +# This is the web server configuration to allow PHP scripts to run. If left +# empty, the MESSENGER service will try to configure this. If this does not +# work, this should be set as an "Include /path/to/csf_php.conf" or similar +# file which must contain appropriate web server configuration to allow PHP +# scripts to run. This line will be included within each MESSENGER VirtualHost +# container. This will replace the [MESSENGERV3PHPHANDLER] line from the csf +# webserver template files +MESSENGERV3PHPHANDLER = "" + +# RECAPTCHA: +#------------------------------------------------------------------------------ +# The RECAPTCHA options provide a way for end-users that have blocked +# themselves in the firewall to unblock themselves. +# +# A valid Google ReCAPTCHA (v2) key set is required for this feature from: +# https://www.google.com/recaptcha/intro/index.html +# +# When configuring a new reCAPTCHA API key set you must ensure that the option +# for "Domain Name Validation" is unticked so that the same reCAPTCHA can be +# used for all domains hosted on the server. lfd then checks that the hostname +# of the request resolves to an IP on this server +# +# This feature requires the installation of the LWP::UserAgent perl module (see +# option URLGET for more details) +# +# The template used for this feature is /etc/csf/messenger/index.recaptcha.html +# +# Note: An unblock will fail if the end-users IP is located in a netblock, +# blocklist or CC_* deny entry +RECAPTCHA_SITEKEY = "" +RECAPTCHA_SECRET = "" + +# Send an email when an IP address successfully attempts to unblock themselves. +# This does not necessarily mean the IP was unblocked, only that the +# post-recaptcha unblock request was attempted +# +# Set to "0" to disable +RECAPTCHA_ALERT = "1" + +# If the server uses NAT then resolving the hostname to hosted IPs will likely +# not succeed. In that case, the external IP addresses must be listed as comma +# separated list here +RECAPTCHA_NAT = "" + +############################################################################### +# SECTION:lfd Clustering +############################################################################### +# lfd Clustering. This allows the configuration of an lfd cluster environment +# where a group of servers can share blocks and configuration option changes. +# Included are CLI and UI options to send requests to the cluster. +# +# See the readme.txt file for more information and details on setup and +# security risks. +# +# Set this to a comma separated list of cluster member IP addresses to send +# requests to. Alternatively, it can be set to the full path of a file that +# will read in one IP per line, e.g.: +# "/etc/csf/cluster_sendto.txt" +CLUSTER_SENDTO = "" + +# Set this to a comma separated list of cluster member IP addresses to receive +# requests from. Alternatively, it can be set to the full path of a file that +# will read in one IP per line, e.g.: +# "/etc/csf/cluster_recvfrom.txt" +CLUSTER_RECVFROM = "" + +# IP address of the master node in the cluster allowed to send CLUSTER_CONFIG +# changes +CLUSTER_MASTER = "" + +# If this is a NAT server, set this to the public IP address of this server +CLUSTER_NAT = "" + +# If a cluster member should send requests on an IP other than the default IP, +# set it here +CLUSTER_LOCALADDR = "" + +# Cluster communication port (must be the same on all member servers). There +# is no need to open this port in the firewall as csf will automatically add +# in and out bound rules to allow communication between cluster members +CLUSTER_PORT = "7777" + +# This is a secret key used to encrypt cluster communications using the +# Blowfish algorithm. It should be between 8 and 56 characters long, +# preferably > 20 random characters +# 56 chars: 01234567890123456789012345678901234567890123456789012345 +CLUSTER_KEY = "" + +# Automatically send lfd blocks to all members of CLUSTER_SENDTO. Those +# servers must have this servers IP address listed in their CLUSTER_RECVFROM +# +# Set to 0 to disable this feature +CLUSTER_BLOCK = "1" + +# This option allows the enabling and disabling of the Cluster configuration +# changing options --cconfig, --cconfigr, --cfile, --ccfile sent from the +# CLUSTER_MASTER server +# +# Set this option to 1 to allow Cluster configurations to be received +CLUSTER_CONFIG = "0" + +# Maximum number of child processes to listen on. High blocking rates or large +# clusters may need to increase this +CLUSTER_CHILDREN = "10" + +############################################################################### +# SECTION:Port Knocking +############################################################################### +# Port Knocking. This feature allows port knocking to be enabled on multiple +# ports with a variable number of knocked ports and a timeout. There must be a +# minimum of 3 ports to knock for an entry to be valid +# +# See the following for information regarding Port Knocking: +# http://www.portknocking.org/ +# +# This feature does not work on servers that do not have the iptables module +# ipt_recent loaded. Typically, this will be with MONOLITHIC kernels. VPS +# server admins should check with their VPS host provider that the iptables +# module is included +# +# For further information and syntax refer to the Port Knocking section of the +# csf readme.txt +# +# Note: Run /etc/csf/csftest.pl to check whether this option will function on +# this server +# +# openport;protocol;timeout;kport1;kport2;kport3[...;kportN],... +# e.g.: 22;TCP;20;100;200;300;400 +PORTKNOCKING = "" + +# Enable PORTKNOCKING logging by iptables +PORTKNOCKING_LOG = "1" + +# Send an email alert if the PORTKNOCKING port is opened. PORTKNOCKING_LOG must +# also be enabled to use this option +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +PORTKNOCKING_ALERT = "0" + +############################################################################### +# SECTION:Log Scanner +############################################################################### +# Log Scanner. This feature will send out an email summary of the log lines of +# each log listed in /etc/csf/csf.logfiles. All lines will be reported unless +# they match a regular expression in /etc/csf/csf.logignore +# +# File globbing is supported for logs listed in /etc/csf/csf.logfiles. However, +# be aware that the more files lfd has to track, the greater the performance +# hit. Note: File globs are only evaluated when lfd is started +# +# Note: lfd builds the report continuously from lines logged after lfd has +# started, so any lines logged when lfd is not running will not be reported +# (e.g. during reboot). If lfd is restarted, then the report will include any +# lines logged during the previous lfd logging period that weren't reported +# +# 1 to enable, 0 to disable +LOGSCANNER = "0" + +# This is the interval each report will be sent based on the logalert.txt +# template +# +# The interval can be set to: +# "hourly" - sent on the hour +# "daily" - sent at midnight (00:00) +# "manual" - sent whenever "csf --logrun" is run. This allows for scheduling +# via cron job +LOGSCANNER_INTERVAL = "hourly" + +# Report Style +# 1 = Separate chronological log lines per log file +# 2 = Simply chronological log of all lines +LOGSCANNER_STYLE = "1" + +# Send the report email even if no log lines reported +# 1 to enable, 0 to disable +LOGSCANNER_EMPTY = "1" + +# Maximum number of lines in the report before it is truncated. This is to +# prevent log lines flooding resulting in an excessively large report. This +# might need to be increased if you choose a daily report +LOGSCANNER_LINES = "5000" + +############################################################################### +# SECTION:Statistics Settings +############################################################################### +# Statistics +# +# Some of the Statistics output requires the gd graphics library and the +# GD::Graph perl module with all dependent modules to be installed for the UI +# for them to be displayed +# +# This option enabled statistical data gathering +ST_ENABLE = "1" + +# This option determines how many iptables log lines to store for reports +ST_IPTABLES = "100" + +# This option indicates whether rDNS and CC lookups are performed at the time +# the log line is recorded (this is not performed when viewing the reports) +# +# Warning: If DROP_IP_LOGGING is enabled and there are frequent iptables hits, +# then enabling this setting could cause serious performance problems +ST_LOOKUP = "0" + +# This option will gather basic system statstics. Through the UI it displays +# various graphs for disk, cpu, memory, network, etc usage over 4 intervals: +# . Hourly (per minute) +# . 24 hours (per minute) +# . 7 days (per minute averaged over an hour) +# . 30 days (per minute averaged over an hour) - user definable +# The data is stored in /var/lib/csf/stats/system and the option requires the +# perl GD::Graph module +# +# Note: Disk graphs do not show on Virtuozzo/OpenVZ servers as the kernel on +# those systems do not store the required information in /proc/diskstats +# On new installations or when enabling this option it will take time for these +# graphs to be populated +ST_SYSTEM = "0" + +# Set the maximum days to collect statistics for. The default is 30 days, the +# more data that is collected the longer it will take for each of the graphs to +# be generated +ST_SYSTEM_MAXDAYS = "30" + +# If ST_SYSTEM is enabled, then these options can collect MySQL statistical +# data. To use this option the server must have the perl modules DBI and +# DBD::mysql installed. +# +# Set this option to "0" to disable MySQL data collection +ST_MYSQL = "0" + +# The following options are for authentication for MySQL data collection. If +# the password is left blank and the user set to "root" then the procedure will +# look for authentication data in /root/.my.cnf. Otherwise, you will need to +# provide a MySQL username and password to collect the data. Any MySQL user +# account can be used +ST_MYSQL_USER = "root" +ST_MYSQL_PASS = "" +ST_MYSQL_HOST = "localhost" + +# If ST_SYSTEM is enabled, then this option can collect Apache statistical data +# The value for PT_APACHESTATUS must be correctly set +ST_APACHE = "0" + +# The following options measure disk write performance using dd (location set +# via the DD setting). It creates a 64MB file called /var/lib/dd_write_test and +# the statistics will plot the MB/s response time of the disk. As this is an IO +# intensive operation, it may not be prudent to run this test too often, so by +# default it is only run every 5 minutes and the result duplicated for each +# intervening minute for the statistics +# +# This is not necessrily a good measure of disk performance, primarily because +# the measurements are for relatively small amounts of data over a small amount +# of time. To properly test disk performance there are a variety of tools +# available that should be run for extended periods of time to obtain an +# accurate measurement. This metric is provided to give an idea of how the disk +# is performing over time +# +# Note: There is a 15 second timeout performing the check +# +# Set to 0 to disable, 1 to enable +ST_DISKW = "0" + +# The number of minutes that elapse between tests. Default is 5, minimum is 1. +ST_DISKW_FREQ = "5" + +# This is the command line passed to dd. If you are familiar with dd, or wish +# to move the output file (of) to a different disk, then you can alter this +# command. Take great care when making any changes to this command as it is +# very easy to overwrite a disk using dd if you make a mistake +ST_DISKW_DD = "if=/dev/zero of=/var/lib/csf/dd_test bs=1MB count=64 conv=fdatasync" + +############################################################################### +# SECTION:Docker Settings +############################################################################### +# This section provides the configuration of iptables rules to allow Docker +# containers to communicate through the host. If the generated rules do not +# work with your setup you will have to use a /etc/csf/csfpost.sh file and add +# your own iptables configuration instead +# +# 1 to enable, 0 to disable +DOCKER = "0" + +# The network device on the host +DOCKER_DEVICE = "docker0" + +# Docker container IPv4 range +DOCKER_NETWORK4 = "172.17.0.0/16" + +# Docker container IPv6 range. IPV6 must be enabled and the IPv6 nat table +# available (see IPv6 section). Leave blank to disable +DOCKER_NETWORK6 = "2001:db8:1::/64" + +############################################################################### +# SECTION:OS Specific Settings +############################################################################### +# Binary locations +IPTABLES = "/sbin/iptables" +IPTABLES_SAVE = "/sbin/iptables-save" +IPTABLES_RESTORE = "/sbin/iptables-restore" +IP6TABLES = "/sbin/ip6tables" +IP6TABLES_SAVE = "/sbin/ip6tables-save" +IP6TABLES_RESTORE = "/sbin/ip6tables-restore" +MODPROBE = "/sbin/modprobe" +IFCONFIG = "/sbin/ifconfig" +SENDMAIL = "/usr/sbin/sendmail" +PS = "/bin/ps" +VMSTAT = "/usr/bin/vmstat" +NETSTAT = "/bin/netstat" +LS = "/bin/ls" +MD5SUM = "/usr/bin/md5sum" +TAR = "/bin/tar" +CHATTR = "/usr/bin/chattr" +UNZIP = "/usr/bin/unzip" +GUNZIP = "/bin/gunzip" +DD = "/bin/dd" +TAIL = "/usr/bin/tail" +GREP = "/bin/grep" +ZGREP = "/usr/bin/zgrep" +IPSET = "/usr/sbin/ipset" +SYSTEMCTL = "/usr/bin/systemctl" +HOST = "/usr/bin/host" +IP = "/sbin/ip" +CURL = "/usr/bin/curl" +WGET = "/usr/bin/wget" + +# Log file locations +# +# File globbing is allowed for the following logs. However, be aware that the +# more files lfd has to track, the greater the performance hit +# +# Note: File globs are only evaluated when lfd is started +# +HTACCESS_LOG = "/var/log/httpd/error_log" +MODSEC_LOG = "/var/log/httpd/error_log" +SSHD_LOG = "/var/log/secure" +SU_LOG = "/var/log/secure" +SUDO_LOG = "/var/log/secure" +FTPD_LOG = "/var/log/proftpd/auth.log" +SMTPAUTH_LOG = "/var/log/smtp/current" +POP3D_LOG = "/var/log/dovecot/dovecot.log" +IMAPD_LOG = "/var/log/dovecot/dovecot.log" +IPTABLES_LOG = "/var/log/messages" +SUHOSIN_LOG = "/var/log/messages" +BIND_LOG = "/var/log/messages" +SYSLOG_LOG = "/var/log/messages" +WEBMIN_LOG = "/var/log/secure" +CWP_LOG = "/var/log/cwp_client_login.log" + +CUSTOM1_LOG = "/var/log/customlog" +CUSTOM2_LOG = "/var/log/customlog" +CUSTOM3_LOG = "/var/log/customlog" +CUSTOM4_LOG = "/var/log/customlog" +CUSTOM5_LOG = "/var/log/customlog" +CUSTOM6_LOG = "/var/log/customlog" +CUSTOM7_LOG = "/var/log/customlog" +CUSTOM8_LOG = "/var/log/customlog" +CUSTOM9_LOG = "/var/log/customlog" + +# The following are comma separated lists used if LF_SELECT is enabled, +# otherwise they are not used. They are derived from the application returned +# from a regex match in /usr/local/csf/bin/regex.pm +# +# All ports default to tcp blocks. To specify udp or tcp use the format: +# port;protocol,port;protocol,... For example, "53;udp,53;tcp" +PORTS_pop3d = "110,995" +PORTS_imapd = "143,993" +PORTS_htpasswd = "80,443" +PORTS_mod_security = "80,443" +PORTS_mod_qos = "80,443" +PORTS_symlink = "80,443" +PORTS_suhosin = "80,443" +PORTS_cxs = "80,443" +PORTS_bind = "53;udp,53;tcp" +PORTS_ftpd = "20,21" +PORTS_webmin = "10000" +PORTS_smtpauth = "25,465,587" +PORTS_eximsyntax = "25,465,587" +PORTS_cwp = "2030,2031" +# This list is replaced, if present, by "Port" definitions in +# /etc/ssh/sshd_config +PORTS_sshd = "22" + +# This configuration is for use with generic Linux servers, do not change the +# following settings: +GENERIC = "1" +CWP = "1" + +# For internal use only. You should not enable this option as it could cause +# instability in csf and lfd +DEBUG = "0" +############################################################################### diff --git a/csf/csf.cwp.ignore b/csf/csf.cwp.ignore new file mode 100644 index 0000000..bf3fb2a --- /dev/null +++ b/csf/csf.cwp.ignore @@ -0,0 +1,25 @@ +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +# The following IP addresses will be ignored by all lfd checks +# One IP address per line +# CIDR addressing allowed with a quaded IP (e.g. 192.168.254.0/24) +# Only list IP addresses, not domain names (they will be ignored) +# + +127.0.0.1 diff --git a/csf/csf.cwp.pignore b/csf/csf.cwp.pignore new file mode 100644 index 0000000..4a36a0d --- /dev/null +++ b/csf/csf.cwp.pignore @@ -0,0 +1,116 @@ +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +# The following is a list of executables (exe) command lines (cmd) and +# usernames (user) that lfd process tracking will ignore. +# +# You must use the following format: +# +# exe:/full/path/to/file +# user:username +# cmd:command line +# +# Or, perl regular expression matching (regex): +# +# pexe:/full/path/to/file as a perl regex[*] +# puser:username as a perl regex[*] +# pcmd:command line as a perl regex[*] +# +# [*]You must remember to escape characters correctly when using regex's, e.g.: +# pexe:/home/.*/public_html/cgi-bin/script\.cgi +# puser:bob\d.* +# pcmd:/home/.*/command\s\to\smatch\s\.pl\s.* +# +# It is strongly recommended that you use command line ignores very carefully +# as any process can change what is reported to the OS. +# +# For more information see readme.txt + +exe:/bin/dbus-daemon +exe:/sbin/ntpd +exe:/usr/bin/dbus-daemon +exe:/usr/bin/lsmd +exe:/usr/lib/courier-imap/bin/imapd +exe:/usr/lib/courier-imap/bin/pop3d +exe:/usr/lib/polkit-1/polkitd +exe:/usr/libexec/dovecot/imap +exe:/usr/libexec/dovecot/imap +exe:/usr/libexec/dovecot/pop3 +exe:/usr/libexec/dovecot/pop3 +exe:/usr/libexec/dovecot/stats +exe:/usr/libexec/dovecot/auth +exe:/usr/libexec/mysqld +exe:/usr/local/apache/bin/httpd +exe:/usr/local/libexec/dovecot/imap +exe:/usr/local/libexec/dovecot/imap-login +exe:/usr/local/libexec/dovecot/pop3 +exe:/usr/local/libexec/dovecot/pop3-login +exe:/usr/local/libexec/dovecot/stats +exe:/usr/sbin/chronyd +exe:/usr/sbin/exim +exe:/usr/sbin/exim4 +exe:/usr/sbin/named +exe:/usr/sbin/nscd +exe:/usr/sbin/ntpd +exe:/usr/sbin/ntpd +exe:/usr/sbin/proftpd +exe:/usr/sbin/pure-ftpd +exe:/usr/sbin/sshd +exe:/usr/sbin/apache2 +exe:/usr/sbin/mysqld +exe:/lib/systemd/systemd-timesyncd +exe:/sbin/rngd + +exe:/usr/sbin/clamd +exe:/usr/sbin/opendkim +exe:/usr/libexec/mysqld +exe:/usr/sbin/mysqld +exe:/usr/bin/postgres +exe:/usr/bin/mongod +exe:/usr/libexec/dovecot/anvil +exe:/usr/libexec/dovecot/auth +exe:/usr/libexec/dovecot/imap-login +exe:/usr/libexec/dovecot/dict +exe:/usr/libexec/dovecot/pop3-login +exe:/usr/local/cwp/php71/sbin/php-fpm +exe:/usr/libexec/postfix/tlsmgr +exe:/usr/libexec/postfix/qmgr +exe:/usr/libexec/postfix/pickup +exe:/usr/libexec/postfix/smtpd +exe:/usr/libexec/postfix/smtp +exe:/usr/libexec/postfix/bounce +exe:/usr/libexec/postfix/scache +exe:/usr/libexec/postfix/anvil +exe:/usr/libexec/postfix/cleanup +exe:/usr/libexec/postfix/proxymap +exe:/usr/libexec/postfix/trivial-rewrite +exe:/usr/libexec/postfix/local +exe:/usr/libexec/postfix/pipe +exe:/usr/libexec/postfix/spawn +exe:/usr/sbin/varnishd +exe:/usr/sbin/nginx +exe:/usr/sbin/mariadbd +exe:/usr/bin/dbus-broker-launch +exe:/usr/bin/dbus-broker + +# Some additional entries that you might want to ignore on cPanel servers. +# However, be aware of the security implications under "Process Tracking" in +# the csf readme.txt when using these: +# +#cmd:spamd child +#cmd:/bin/sh /usr/bin/mysqld_safe --basedir=/usr diff --git a/csf/csf.cyberpanel.allow b/csf/csf.cyberpanel.allow new file mode 100644 index 0000000..19ec008 --- /dev/null +++ b/csf/csf.cyberpanel.allow @@ -0,0 +1,30 @@ +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +# The following IP addresses will be allowed through iptables. +# One IP address per line. +# CIDR addressing allowed with a quaded IP (e.g. 192.168.254.0/24). +# Only list IP addresses, not domain names (they will be ignored) +# +# Advanced port+ip filtering allowed with the following format +# tcp/udp|in/out|s/d=port|s/d=ip +# See readme.txt for more information +# +# Note: IP addressess listed in this file will NOT be ignored by lfd, so they +# can still be blocked. If you do not want lfd to block an IP address you must +# add it to csf.ignore diff --git a/csf/csf.cyberpanel.conf b/csf/csf.cyberpanel.conf new file mode 100644 index 0000000..5c18538 --- /dev/null +++ b/csf/csf.cyberpanel.conf @@ -0,0 +1,2679 @@ +############################################################################### +# SECTION:Initial Settings +############################################################################### +# Testing flag - enables a CRON job that clears iptables incase of +# configuration problems when you start csf. This should be enabled until you +# are sure that the firewall works - i.e. incase you get locked out of your +# server! Then do remember to set it to 0 and restart csf when you're sure +# everything is OK. Stopping csf will remove the line from /etc/crontab +# +# lfd will not start while this is enabled +TESTING = "1" + +# The interval for the crontab in minutes. Since this uses the system clock the +# CRON job will run at the interval past the hour and not from when you issue +# the start command. Therefore an interval of 5 minutes means the firewall +# will be cleared in 0-5 minutes from the firewall start +TESTING_INTERVAL = "5" + +# SECURITY WARNING +# ================ +# +# Unfortunately, syslog and rsyslog allow end-users to log messages to some +# system logs via the same unix socket that other local services use. This +# means that any log line shown in these system logs that syslog or rsyslog +# maintain can be spoofed (they are exactly the same as real log lines). +# +# Since some of the features of lfd rely on such log lines, spoofed messages +# can cause false-positive matches which can lead to confusion at best, or +# blocking of any innocent IP address or making the server inaccessible at +# worst. +# +# Any option that relies on the log entries in the files listed in +# /etc/syslog.conf and /etc/rsyslog.conf should therefore be considered +# vulnerable to exploitation by end-users and scripts run by end-users. +# +# NOTE: Not all log files are affected as they may not use syslog/rsyslog +# +# The option RESTRICT_SYSLOG disables all these features that rely on affected +# logs. These options are: +# LF_SSHD LF_FTPD LF_IMAPD LF_POP3D LF_BIND LF_SUHOSIN LF_SSH_EMAIL_ALERT +# LF_SU_EMAIL_ALERT LF_CONSOLE_EMAIL_ALERT LF_DISTATTACK LF_DISTFTP +# LT_POP3D LT_IMAPD PS_INTERVAL UID_INTERVAL WEBMIN_LOG LF_WEBMIN_EMAIL_ALERT +# PORTKNOCKING_ALERT LF_SUDO_EMAIL_ALERT +# +# This list of options use the logs but are not disabled by RESTRICT_SYSLOG: +# ST_ENABLE SYSLOG_CHECK LOGSCANNER CUSTOM*_LOG +# +# The following options are still enabled by default on new installations so +# that, on balance, csf/lfd still provides expected levels of security: +# LF_SSHD LF_FTPD LF_POP3D LF_IMAPD LF_SSH_EMAIL_ALERT LF_SU_EMAIL_ALERT +# +# If you set RESTRICT_SYSLOG to "0" or "2" and enable any of the options listed +# above, it should be done with the knowledge that any of the those options +# that are enabled could be triggered by spoofed log lines and lead to the +# server being inaccessible in the worst case. If you do not want to take that +# risk you should set RESTRICT_SYSLOG to "1" and those features will not work +# but you will not be protected from the exploits that they normally help block +# +# The recommended setting for RESTRICT_SYSLOG is "3" to restrict who can access +# the syslog/rsyslog unix socket. +# +# For further advice on how to help mitigate these issues, see +# /etc/csf/readme.txt +# +# 0 = Allow those options listed above to be used and configured +# 1 = Disable all the options listed above and prevent them from being used +# 2 = Disable only alerts about this feature and do nothing else +# 3 = Restrict syslog/rsyslog access to RESTRICT_SYSLOG_GROUP ** RECOMMENDED ** +RESTRICT_SYSLOG = "0" + +# The following setting is used if RESTRICT_SYSLOG is set to 3. It restricts +# write access to the syslog/rsyslog unix socket(s). The group must not already +# exists in /etc/group before setting RESTRICT_SYSLOG to 3, so set the option +# to a unique name for the server +# +# You can add users to this group by changing /etc/csf/csf.syslogusers and then +# restarting lfd afterwards. This will create the system group and add the +# users from csf.syslogusers if they exist to that group and will change the +# permissions on the syslog/rsyslog unix socket(s). The socket(s) will be +# monitored and the permissions re-applied should syslog/rsyslog be restarted +# +# Using this option will prevent some legitimate logging, e.g. end-user cron +# job logs +# +# If you want to revert RESTRICT_SYSLOG to another option and disable this +# feature, change the setting of RESTRICT_SYSLOG and then restart lfd and then +# syslog/rsyslog and the unix sockets will be reset +RESTRICT_SYSLOG_GROUP = "mysyslog" + +# This options restricts the ability to modify settings within this file from +# the csf UI. Should the parent control panel be compromised, these restricted +# options could be used to further compromise the server. For this reason we +# recommend leaving this option set to at least "1" and if any of the +# restricted items need to be changed, they are done so from the root shell +# +# 0 = Unrestricted UI +# 1 = Restricted UI +# 2 = Disabled UI +RESTRICT_UI = "1" + +# Enabling auto updates creates a cron job called /etc/cron.d/csf_update which +# runs once per day to see if there is an update to csf+lfd and upgrades if +# available and restarts csf and lfd +# +# You should check for new version announcements at http://blog.configserver.com +AUTO_UPDATES = "1" + +############################################################################### +# SECTION:IPv4 Port Settings +############################################################################### +# Lists of ports in the following comma separated lists can be added using a +# colon (e.g. 30000:35000). + +# Some kernel/iptables setups do not perform stateful connection tracking +# correctly (typically some virtual servers or custom compiled kernels), so a +# SPI firewall will not function correctly. If this happens, LF_SPI can be set +# to 0 to reconfigure csf as a static firewall. +# +# As connection tracking will not be configured, applications that rely on it +# will not function unless all outgoing ports are opened. Therefore, all +# outgoing connections will be allowed once all other tests have completed. So +# TCP_OUT, UDP_OUT and ICMP_OUT will not have any affect. +# +# If you allow incoming DNS lookups you may need to use the following +# directive in the options{} section of your named.conf: +# +# query-source port 53; +# +# This will force incoming DNS traffic only through port 53 +# +# Disabling this option will break firewall functionality that relies on +# stateful packet inspection (e.g. DNAT, PACKET_FILTER) and makes the firewall +# less secure +# +# This option should be set to "1" in all other circumstances +LF_SPI = "1" + +# Allow incoming TCP ports +TCP_IN = "20,21,22,25,53,853,853,80,110,143,443,465,587,993,995,7080,8090" + +# Allow outgoing TCP ports +TCP_OUT = "20,21,22,25,53,853,853,80,110,113,443,587,993,995" + +# Allow incoming UDP ports +UDP_IN = "20,21,53,853,80,443" + +# Allow outgoing UDP ports +# To allow outgoing traceroute add 33434:33523 to this list +UDP_OUT = "20,21,53,853,113,123" + +# Allow incoming PING. Disabling PING will likely break external uptime +# monitoring +ICMP_IN = "1" + +# Set the per IP address incoming ICMP packet rate for PING requests. This +# ratelimits PING requests which if exceeded results in silently rejected +# packets. Disable or increase this value if you are seeing PING drops that you +# do not want +# +# To disable rate limiting set to "0", otherwise set according to the iptables +# documentation for the limit module. For example, "1/s" will limit to one +# packet per second +ICMP_IN_RATE = "1/s" + +# Allow outgoing PING +# +# Unless there is a specific reason, this option should NOT be disabled as it +# could break OS functionality +ICMP_OUT = "1" + +# Set the per IP address outgoing ICMP packet rate for PING requests. This +# ratelimits PING requests which if exceeded results in silently rejected +# packets. Disable or increase this value if you are seeing PING drops that you +# do not want +# +# Unless there is a specific reason, this option should NOT be enabled as it +# could break OS functionality +# +# To disable rate limiting set to "0", otherwise set according to the iptables +# documentation for the limit module. For example, "1/s" will limit to one +# packet per second +ICMP_OUT_RATE = "0" + +# For those with PCI Compliance tools that state that ICMP timestamps (type 13) +# should be dropped, you can enable the following option. Otherwise, there +# appears to be little evidence that it has anything to do with a security risk +# and can impact network performance, so should be left disabled by everyone +# else +ICMP_TIMESTAMPDROP = "0" + +############################################################################### +# SECTION:IPv6 Port Settings +############################################################################### +# IPv6: (Requires ip6tables) +# +# Pre v2.6.20 kernels do not perform stateful connection tracking, so a static +# firewall is configured as a fallback instead if IPV6_SPI is set to 0 below +# +# Supported: +# Temporary ACCEPT/DENY, GLOBAL_DENY, GLOBAL_ALLOW, SMTP_BLOCK, LF_PERMBLOCK, +# PACKET_FILTER, Advanced Allow/Deny Filters, RELAY_*, CLUSTER_*, CC6_LOOKUPS, +# SYNFLOOD, LF_NETBLOCK +# +# Supported if CC6_LOOKUPS and CC_LOOKUPS are enabled +# CC_DENY, CC_ALLOW, CC_ALLOW_FILTER, CC_IGNORE, CC_ALLOW_PORTS, CC_DENY_PORTS, +# CC_ALLOW_SMTPAUTH +# +# Supported if ip6tables >= 1.4.3: +# PORTFLOOD, CONNLIMIT +# +# Supported if ip6tables >= 1.4.17 and perl module IO::Socket::INET6 is +# installed: +# MESSENGER DOCKER SMTP_REDIRECT +# +# Not supported: +# ICMP_IN, ICMP_OUT +# +IPV6 = "0" + +# IPv6 uses icmpv6 packets very heavily. By default, csf will allow all icmpv6 +# traffic in the INPUT and OUTPUT chains. However, this could increase the risk +# of icmpv6 attacks. To restrict incoming icmpv6, set to "1" but may break some +# connection types +IPV6_ICMP_STRICT = "0" + +# Pre v2.6.20 kernel must set this option to "0" as no working state module is +# present, so a static firewall is configured as a fallback +# +# A workaround has been added for CentOS/RedHat v5 and custom kernels that do +# not support IPv6 connection tracking by opening ephemeral port range +# 32768:61000. This is only applied if IPV6_SPI is not enabled. This is the +# same workaround implemented by RedHat in the sample default IPv6 rules +# +# As connection tracking will not be configured, applications that rely on it +# will not function unless all outgoing ports are opened. Therefore, all +# outgoing connections will be allowed once all other tests have completed. So +# TCP6_OUT, UDP6_OUT and ICMP6_OUT will not have any affect. +# +# If you allow incoming ipv6 DNS lookups you may need to use the following +# directive in the options{} section of your named.conf: +# +# query-source-v6 port 53; +# +# This will force ipv6 incoming DNS traffic only through port 53 +# +# These changes are not necessary if the SPI firewall is used +IPV6_SPI = "1" + +# Allow incoming IPv6 TCP ports +TCP6_IN = "20,21,22,25,53,853,80,110,143,443,465,587,993,995,7080,8090" + +# Allow outgoing IPv6 TCP ports +TCP6_OUT = "20,21,22,25,53,853,80,110,113,443,587,993,995" + +# Allow incoming IPv6 UDP ports +UDP6_IN = "20,21,53,853,80,443" + +# Allow outgoing IPv6 UDP ports +# To allow outgoing traceroute add 33434:33523 to this list +UDP6_OUT = "20,21,53,853,113,123" + +############################################################################### +# SECTION:General Settings +############################################################################### +# By default, csf will auto-configure iptables to filter all traffic except on +# the loopback device. If you only want iptables rules applied to a specific +# NIC, then list it here (e.g. eth1, or eth+) +ETH_DEVICE = "" + +# By adding a device to this option, ip6tables can be configured only on the +# specified device. Otherwise, ETH_DEVICE and then the default setting will be +# used +ETH6_DEVICE = "" + +# If you don't want iptables rules applied to specific NICs, then list them in +# a comma separated list (e.g "eth1,eth2") +ETH_DEVICE_SKIP = "" + +# This option should be enabled unless the kernel does not support the +# "conntrack" module +# +# To use the deprecated iptables "state" module, change this to 0 +USE_CONNTRACK = "1" + +# Enable ftp helper via the iptables CT target on supporting kernels (v2.6.34+) +# instead of the current method via /proc/sys/net/netfilter/nf_conntrack_helper +# This will also remove the RELATED target from the global state iptables rule +# +# This is not needed (and will be ignored) if LF_SPI/IPV6_SPI is disabled or +# the raw tables do not exist. The USE_CONNTRACK option should be enabled +# +# To enable this option, set it to your FTP server listening port number +# (normally 21), do NOT set it to "1" +USE_FTPHELPER = "0" + +# Check whether syslog is running. Many of the lfd checks require syslog to be +# running correctly. This test will send a coded message to syslog every +# SYSLOG_CHECK seconds. lfd will check SYSLOG_LOG log lines for the coded +# message. If it fails to do so within SYSLOG_CHECK seconds an alert using +# syslogalert.txt is sent +# +# A value of between 300 and 3600 seconds is suggested. Set to 0 to disable +SYSLOG_CHECK = "0" + +# Enable this option if you want lfd to ignore (i.e. don't block) IP addresses +# listed in csf.allow in addition to csf.ignore (the default). This option +# should be used with caution as it would mean that IP's allowed through the +# firewall from infected PC's could launch attacks on the server that lfd +# would ignore +IGNORE_ALLOW = "0" + +# Enable the following option if you want to apply strict iptables rules to DNS +# traffic (i.e. relying on iptables connection tracking). Enabling this option +# could cause DNS resolution issues both to and from the server but could help +# prevent abuse of the local DNS server +DNS_STRICT = "0" + +# Enable the following option if you want to apply strict iptables rules to DNS +# traffic between the server and the nameservers listed in /etc/resolv.conf +# Enabling this option could cause DNS resolution issues both to and from the +# server but could help prevent abuse of the local DNS server +DNS_STRICT_NS = "0" + +# Limit the number of IP's kept in the /etc/csf/csf.deny file +# +# Care should be taken when increasing this value on servers with low memory +# resources or hard limits (such as Virtuozzo/OpenVZ) as too many rules (in the +# thousands) can sometimes cause network slowdown +# +# The value set here is the maximum number of IPs/CIDRs allowed +# if the limit is reached, the entries will be rotated so that the oldest +# entries (i.e. the ones at the top) will be removed and the latest is added. +# The limit is only checked when using csf -d (which is what lfd also uses) +# Set to 0 to disable limiting +# +# For implementations wishing to set this value significantly higher, we +# recommend using the IPSET option +DENY_IP_LIMIT = "200" + +# Limit the number of IP's kept in the temprary IP ban list. If the limit is +# reached the oldest IP's in the ban list will be removed and allowed +# regardless of the amount of time remaining for the block +# Set to 0 to disable limiting +DENY_TEMP_IP_LIMIT = "100" + +# Enable login failure detection daemon (lfd). If set to 0 none of the +# following settings will have any effect as the daemon won't start. +LF_DAEMON = "1" + +# Check whether csf appears to have been stopped and restart if necessary, +# unless TESTING is enabled above. The check is done every 300 seconds +LF_CSF = "1" + +# This option uses IPTABLES_SAVE, IPTABLES_RESTORE and IP6TABLES_SAVE, +# IP6TABLES_RESTORE in two ways: +# +# 1. On a clean server reboot the entire csf iptables configuration is saved +# and then restored where possible to provide a near instant firewall +# startup[*] +# +# 2. On csf restart or lfd reloading tables, CC_* as well as SPAMHAUS, DSHIELD, +# BOGON, TOR are loaded using this method in a fraction of the time than if +# this setting is disabled +# +# [*]Not supported on all OS platforms +# +# Set to "0" to disable this functionality +FASTSTART = "1" + +# This option allows you to use ipset v6+ for the following csf options: +# CC_* and /etc/csf/csf.blocklist, /etc/csf/csf.allow, /etc/csf/csf.deny, +# GLOBAL_DENY, GLOBAL_ALLOW, DYNDNS, GLOBAL_DYNDNS, MESSENGER +# +# ipset will only be used with the above options when listing IPs and CIDRs. +# Advanced Allow Filters and temporary blocks use traditional iptables +# +# Using ipset moves the onus of ip matching against large lists away from +# iptables rules and to a purpose built and optimised database matching +# utility. It also simplifies the switching in of updated lists +# +# To use this option you must have a fully functioning installation of ipset +# installed either via rpm or source from http://ipset.netfilter.org/ +# +# Note: Using ipset has many advantages, some disadvantages are that you will +# no longer see packet and byte counts against IPs and it makes identifying +# blocked/allowed IPs that little bit harder +# +# Note: If you mainly use IP address only entries in csf.deny, you can increase +# the value of DENY_IP_LIMIT significantly if you wish +# +# Note: It's highly unlikely that ipset will function on Virtuozzo/OpenVZ +# containers even if it has been installed +# +# If you find any problems, please post on forums.configserver.com with full +# details of the issue +LF_IPSET = "0" + +# Versions of iptables greater or equal to v1.4.20 should support the --wait +# option. This forces iptables commands that use the option to wait until a +# lock by any other process using iptables completes, rather than simply +# failing +# +# Enabling this feature will add the --wait option to iptables commands +# +# NOTE: The disadvantage of using this option is that any iptables command that +# uses it will hang until the lock is released. This could cause a cascade of +# hung processes trying to issue iptables commands. To try and avoid this issue +# csf uses a last ditch timeout, WAITLOCK_TIMEOUT in seconds, that will trigger +# a failure if reached +WAITLOCK = "0" +WAITLOCK_TIMEOUT = "300" + +# The following sets the hashsize for ipset sets, which must be a power of 2. +# +# Note: Increasing this value will consume more memory for all sets +# Default: "1024" +LF_IPSET_HASHSIZE = "1024" + +# The following sets the maxelem for ipset sets. +# +# Note: Increasing this value will consume more memory for all sets +# Default: "65536" +LF_IPSET_MAXELEM = "65536" + +# If you enable this option then whenever a CLI request to restart csf is used +# lfd will restart csf instead within LF_PARSE seconds +# +# This feature can be helpful for restarting configurations that cannot use +# FASTSTART +LFDSTART = "0" + +# Enable verbose output of iptables commands +VERBOSE = "1" + +# Drop out of order packets and packets in an INVALID state in iptables +# connection tracking +PACKET_FILTER = "1" + +# Perform reverse DNS lookups on IP addresses. (See also CC_LOOKUPS) +LF_LOOKUPS = "1" + +# Custom styling is possible in the csf UI. See the readme.txt for more +# information under "UI skinning and Mobile View" +# +# This option enables the use of custom styling. If the styling fails to work +# correctly, e.g. custom styling does not take into account a change in the +# standard csf UI, then disabling this option will return the standard UI +STYLE_CUSTOM = "0" + +# This option disables the presence of the Mobile View in the csf UI +STYLE_MOBILE = "1" + +############################################################################### +# SECTION:SMTP Settings +############################################################################### +# Block outgoing SMTP except for root, exim and mailman (forces scripts/users +# to use the exim/sendmail binary instead of sockets access). This replaces the +# protection as WHM > Tweak Settings > SMTP Tweaks +# +# This option uses the iptables ipt_owner/xt_owner module and must be loaded +# for it to work. It may not be available on some VPS platforms +# +# Note: Run /etc/csf/csftest.pl to check whether this option will function on +# this server +SMTP_BLOCK = "0" + +# If SMTP_BLOCK is enabled but you want to allow local connections to port 25 +# on the server (e.g. for webmail or web scripts) then enable this option to +# allow outgoing SMTP connections to the loopback device +SMTP_ALLOWLOCAL = "1" + +# This option redirects outgoing SMTP connections destined for remote servers +# for non-bypass users to the local SMTP server to force local relaying of +# email. Such email may require authentication (SMTP AUTH) +SMTP_REDIRECT = "0" + +# This is a comma separated list of the ports to block. You should list all +# ports that exim is configured to listen on +SMTP_PORTS = "25,465,587" + +# Always allow the following comma separated users and groups to bypass +# SMTP_BLOCK +# +# Note: root (UID:0) is always allowed +SMTP_ALLOWUSER = "" +SMTP_ALLOWGROUP = "mail,mailman" + +# This option will only allow SMTP AUTH to be advertised to the IP addresses +# listed in /etc/csf/csf.smtpauth on EXIM mail servers +# +# The additional option CC_ALLOW_SMTPAUTH can be used with this option to +# additionally restrict access to specific countries +# +# This is to help limit attempts at distributed attacks against SMTP AUTH which +# are difficult to achive since port 25 needs to be open to relay email +# +# The reason why this works is that if EXIM does not advertise SMTP AUTH on a +# connection, then SMTP AUTH will not accept logins, defeating the attacks +# without restricting mail relaying +# +# Note: csf and lfd must be restarted if /etc/csf/csf.smtpauth is modified so +# that the lookup file in /etc/exim.smtpauth is regenerated from the +# information from /etc/csf/csf.smtpauth plus any countries listed in +# CC_ALLOW_SMTPAUTH +# +# NOTE: To make this option work you MUST make the modifications to exim.conf +# as explained in "Exim SMTP AUTH Restriction" section in /etc/csf/readme.txt +# after enabling the option here, otherwise this option will not work +# +# To enable this option, set to 1 and make the exim configuration changes +# To disable this option, set to 0 and undo the exim configuration changes +SMTPAUTH_RESTRICT = "0" + +############################################################################### +# SECTION:Port Flood Settings +############################################################################### +# Enable SYN Flood Protection. This option configures iptables to offer some +# protection from tcp SYN packet DOS attempts. You should set the RATE so that +# false-positives are kept to a minimum otherwise visitors may see connection +# issues (check /var/log/messages for *SYNFLOOD Blocked*). See the iptables +# man page for the correct --limit rate syntax +# +# Note: This option should ONLY be enabled if you know you are under a SYN +# flood attack as it will slow down all new connections from any IP address to +# the server if triggered +SYNFLOOD = "0" +SYNFLOOD_RATE = "100/s" +SYNFLOOD_BURST = "150" + +# Connection Limit Protection. This option configures iptables to offer more +# protection from DOS attacks against specific ports. It can also be used as a +# way to simply limit resource usage by IP address to specific server services. +# This option limits the number of concurrent new connections per IP address +# that can be made to specific ports +# +# This feature does not work on servers that do not have the iptables module +# xt_connlimit loaded. Typically, this will be with MONOLITHIC kernels. VPS +# server admins should check with their VPS host provider that the iptables +# module is included +# +# For further information and syntax refer to the Connection Limit Protection +# section of the csf readme.txt +# +# Note: Run /etc/csf/csftest.pl to check whether this option will function on +# this server +CONNLIMIT = "" + +# Port Flood Protection. This option configures iptables to offer protection +# from DOS attacks against specific ports. This option limits the number of +# new connections per time interval that can be made to specific ports +# +# This feature does not work on servers that do not have the iptables module +# ipt_recent loaded. Typically, this will be with MONOLITHIC kernels. VPS +# server admins should check with their VPS host provider that the iptables +# module is included +# +# For further information and syntax refer to the Port Flood Protection +# section of the csf readme.txt +# +# Note: Run /etc/csf/csftest.pl to check whether this option will function on +# this server +PORTFLOOD = "" + +# Outgoing UDP Flood Protection. This option limits outbound UDP packet floods. +# These typically originate from exploit scripts uploaded through vulnerable +# web scripts. Care should be taken on servers that use services that utilise +# high levels of UDP outbound traffic, such as SNMP, so you may need to alter +# the UDPFLOOD_LIMIT and UDPFLOOD_BURST options to suit your environment +# +# We recommend enabling User ID Tracking (UID_INTERVAL) with this feature +UDPFLOOD = "0" +UDPFLOOD_LIMIT = "100/s" +UDPFLOOD_BURST = "500" + +# This is a list of usernames that should not be rate limited, such as "named" +# to prevent bind traffic from being limited. +# +# Note: root (UID:0) is always allowed +UDPFLOOD_ALLOWUSER = "named" + +############################################################################### +# SECTION:Logging Settings +############################################################################### +# Log lfd messages to SYSLOG in addition to /var/log/lfd.log. You must have the +# perl module Sys::Syslog installed to use this feature +SYSLOG = "0" + +# Drop target for incoming iptables rules. This can be set to either DROP or +# REJECT. REJECT will send back an error packet, DROP will not respond at all. +# REJECT is more polite, however it does provide extra information to a hacker +# and lets them know that a firewall is blocking their attempts. DROP hangs +# their connection, thereby frustrating attempts to port scan the server +DROP = "DROP" + +# Drop target for outgoing iptables rules. This can be set to either DROP or +# REJECT as with DROP, however as such connections are from this server it is +# better to REJECT connections to closed ports rather than to DROP them. This +# helps to immediately free up server resources rather than tying them up until +# a connection times out. It also tells the process making the connection that +# it has immediately failed +# +# It is possible that some monolithic kernels may not support the REJECT +# target. If this is the case, csf checks before using REJECT and falls back to +# using DROP, issuing a warning to set this to DROP instead +DROP_OUT = "REJECT" + +# Enable logging of dropped connections to blocked ports to syslog, usually +# /var/log/messages. This option needs to be enabled to use Port Scan Tracking +DROP_LOGGING = "1" + +# Enable logging of dropped incoming connections from blocked IP addresses +# +# This option will be disabled if you enable Port Scan Tracking (PS_INTERVAL) +DROP_IP_LOGGING = "0" + +# Enable logging of dropped outgoing connections +# +# Note: Only outgoing SYN packets for TCP connections are logged, other +# protocols log all packets +# +# We recommend that you enable this option +DROP_OUT_LOGGING = "1" + +# Together with DROP_OUT_LOGGING enabled, this option logs the UID connecting +# out (where available) which can help track abuse +DROP_UID_LOGGING = "1" + +# Only log incoming reserved port dropped connections (0:1023). This can reduce +# the amount of log noise from dropped connections, but will affect options +# such as Port Scan Tracking (PS_INTERVAL) +DROP_ONLYRES = "0" + +# Commonly blocked ports that you do not want logging as they tend to just fill +# up the log file. These ports are specifically blocked (applied to TCP and UDP +# protocols) for incoming connections +DROP_NOLOG = "23,67,68,111,113,135:139,445,500,513,520" + +# Log packets dropped by the packet filtering option PACKET_FILTER +DROP_PF_LOGGING = "0" + +# Log packets dropped by the Connection Limit Protection option CONNLIMIT. If +# this is enabled and Port Scan Tracking (PS_INTERVAL) is also enabled, IP +# addresses breaking the Connection Limit Protection will be blocked +CONNLIMIT_LOGGING = "0" + +# Enable logging of UDP floods. This should be enabled, especially with User ID +# Tracking enabled +UDPFLOOD_LOGGING = "1" + +# Send an alert if log file flooding is detected which causes lfd to skip log +# lines to prevent lfd from looping. If this alert is sent you should check the +# reported log file for the reason for the flooding +LOGFLOOD_ALERT = "0" + +############################################################################### +# SECTION:Reporting Settings +############################################################################### +# By default, lfd will send alert emails using the relevant alert template to +# the To: address configured within that template. Setting the following +# option will override the configured To: field in all lfd alert emails +# +# Leave this option empty to use the To: field setting in each alert template +LF_ALERT_TO = "" + +# By default, lfd will send alert emails using the relevant alert template from +# the From: address configured within that template. Setting the following +# option will override the configured From: field in all lfd alert emails +# +# Leave this option empty to use the From: field setting in each alert template +LF_ALERT_FROM = "" + +# By default, lfd will send all alerts using the SENDMAIL binary. To send using +# SMTP directly, you can set the following to a relaying SMTP server, e.g. +# "127.0.0.1". Leave this setting blank to use SENDMAIL +LF_ALERT_SMTP = "" + +# Block Reporting. lfd can run an external script when it performs and IP +# address block following for example a login failure. The following setting +# is to the full path of the external script which must be executable. See +# readme.txt for format details +# +# Leave this setting blank to disable +BLOCK_REPORT = "" + +# To also run an external script when a temporary block is unblocked. The +# following setting can be the full path of the external script which must be +# executable. See readme.txt for format details +# +# Leave this setting blank to disable +UNBLOCK_REPORT = "" + +# In addition to the standard lfd email alerts, you can additionally enable the +# sending of X-ARF reports (see http://www.xarf.org/specification.html). Only +# block alert messages will be sent. The reports use our schema at: +# https://download.configserver.com/abuse_login-attack_0.2.json +# +# These reports are in a format accepted by many Netblock owners and should +# help them investigate abuse. This option is not designed to automatically +# forward these reports to the Netblock owners and should be checked for +# false-positive blocks before reporting +# +# If available, the report will also include the abuse contact for the IP from +# the Abusix Contact DB: https://abusix.com/contactdb.html +# +# Note: The following block types are not reported through this feature: +# LF_PERMBLOCK, LF_NETBLOCK, LF_DISTATTACK, LF_DISTFTP, RT_*_ALERT +X_ARF = "0" + +# By default, lfd will send emails from the root forwarder. Setting the +# following option will override this +X_ARF_FROM = "" + +# By default, lfd will send emails to the root forwarder. Setting the following +# option will override this +X_ARF_TO = "" + +# If you want to automatically send reports to the abuse contact where found, +# you can enable the following option +# +# Note: You MUST set X_ARF_FROM to a valid email address for this option to +# work. This is so that the abuse contact can reply to the report +# +# However, you should be aware that without manual checking you could be +# reporting innocent IP addresses, including your own clients, yourself and +# your own servers +# +# Additionally, just because a contact address is found, does not mean that +# there is anyone on the end of it reading, processing or acting on such +# reports and you could conceivably reported for sending spam +# +# We do not recommend enabling this option. Abuse reports should be checked and +# verified before being forwarded to the abuse contact +X_ARF_ABUSE = "0" + +############################################################################### +# SECTION:Temp to Perm/Netblock Settings +############################################################################### +# Temporary to Permanent IP blocking. The following enables this feature to +# permanently block IP addresses that have been temporarily blocked more than +# LF_PERMBLOCK_COUNT times in the last LF_PERMBLOCK_INTERVAL seconds. Set +# LF_PERMBLOCK to "1" to enable this feature +# +# Care needs to be taken when setting LF_PERMBLOCK_INTERVAL as it needs to be +# at least LF_PERMBLOCK_COUNT multiplied by the longest temporary time setting +# (TTL) for blocked IPs, to be effective +# +# Set LF_PERMBLOCK to "0" to disable this feature +LF_PERMBLOCK = "1" +LF_PERMBLOCK_INTERVAL = "86400" +LF_PERMBLOCK_COUNT = "4" +LF_PERMBLOCK_ALERT = "1" + +# Permanently block IPs by network class. The following enables this feature +# to permanently block classes of IP address where individual IP addresses +# within the same class LF_NETBLOCK_CLASS have already been blocked more than +# LF_NETBLOCK_COUNT times in the last LF_NETBLOCK_INTERVAL seconds. Set +# LF_NETBLOCK to "1" to enable this feature +# +# This can be an affective way of blocking DDOS attacks launched from within +# the same network class +# +# Valid settings for LF_NETBLOCK_CLASS are "A", "B" and "C", care and +# consideration is required when blocking network classes A or B +# +# Set LF_NETBLOCK to "0" to disable this feature +LF_NETBLOCK = "0" +LF_NETBLOCK_INTERVAL = "86400" +LF_NETBLOCK_COUNT = "4" +LF_NETBLOCK_CLASS = "C" +LF_NETBLOCK_ALERT = "1" + +# Valid settings for LF_NETBLOCK_IPV6 are "/64", "/56", "/48", "/32" and "/24" +# Great care should be taken with IPV6 netblock ranges due to the large number +# of addresses involved +# +# To disable IPv6 netblocks set to "" +LF_NETBLOCK_IPV6 = "" + +############################################################################### +# SECTION:Global Lists/DYNDNS/Blocklists +############################################################################### +# Safe Chain Update. If enabled, all dynamic update chains (GALLOW*, GDENY*, +# SPAMHAUS, DSHIELD, BOGON, CC_ALLOW, CC_DENY, ALLOWDYN*) will create a new +# chain when updating, and insert it into the relevant LOCALINPUT/LOCALOUTPUT +# chain, then flush and delete the old dynamic chain and rename the new chain. +# +# This prevents a small window of opportunity opening when an update occurs and +# the dynamic chain is flushed for the new rules. +# +# This option should not be enabled on servers with long dynamic chains (e.g. +# CC_DENY/CC_ALLOW lists) and low memory. It should also not be enabled on +# Virtuozzo VPS servers with a restricted numiptent value. This is because each +# chain will effectively be duplicated while the update occurs, doubling the +# number of iptables rules +SAFECHAINUPDATE = "0" + +# If you wish to allow access from dynamic DNS records (for example if your IP +# address changes whenever you connect to the internet but you have a dedicated +# dynamic DNS record from the likes of dyndns.org) then you can list the FQDN +# records in csf.dyndns and then set the following to the number of seconds to +# poll for a change in the IP address. If the IP address has changed iptables +# will be updated. +# +# If the FQDN has multiple A records then all of the IP addresses will be +# processed. If IPV6 is enabled, then all IPv6 AAAA IP address records will +# also be allowed. +# +# A setting of 600 would check for IP updates every 10 minutes. Set the value +# to 0 to disable the feature +DYNDNS = "0" + +# To always ignore DYNDNS IP addresses in lfd blocking, set the following +# option to 1 +DYNDNS_IGNORE = "0" + +# The follow Global options allow you to specify a URL where csf can grab a +# centralised copy of an IP allow or deny block list of your own. You need to +# specify the full URL in the following options, i.e.: +# http://www.somelocation.com/allow.txt +# +# The actual retrieval of these IP's is controlled by lfd, so you need to set +# LF_GLOBAL to the interval (in seconds) when you want lfd to retrieve. lfd +# will perform the retrieval when it runs and then again at the specified +# interval. A sensible interval would probably be every 3600 seconds (1 hour). +# A minimum value of 300 is enforced for LF_GLOBAL if enabled +# +# You do not have to specify both an allow and a deny file +# +# You can also configure a global ignore file for IP's that lfd should ignore +LF_GLOBAL = "0" + +GLOBAL_ALLOW = "" +GLOBAL_DENY = "" +GLOBAL_IGNORE = "" + +# Provides the same functionality as DYNDNS but with a GLOBAL URL file. Set +# this to the URL of the file containing DYNDNS entries +GLOBAL_DYNDNS = "" + +# Set the following to the number of seconds to poll for a change in the IP +# address resoved from GLOBAL_DYNDNS +GLOBAL_DYNDNS_INTERVAL = "600" + +# To always ignore GLOBAL_DYNDNS IP addresses in lfd blocking, set the following +# option to 1 +GLOBAL_DYNDNS_IGNORE = "0" + +# Blocklists are controlled by modifying /etc/csf/csf.blocklists +# +# If you don't want BOGON rules applied to specific NICs, then list them in +# a comma separated list (e.g "eth1,eth2") +LF_BOGON_SKIP = "" + +# The following option can be used to select the method csf will use to +# retrieve URL data and files +# +# This can be set to use: +# +# 1. Perl module HTTP::Tiny +# 2. Perl module LWP::UserAgent +# 3. CURL/WGET (set location at the bottom of csf.conf if installed) +# +# HTTP::Tiny is much faster than LWP::UserAgent and is included in the csf +# distribution. LWP::UserAgent may have to be installed manually, but it can +# better support https:// URL's which also needs the LWP::Protocol::https perl +# module +# +# CURL/WGET uses the system binaries if installed but does not always provide +# good feedback when it fails. The script will first look for CURL, if that +# does not exist at the configured location it will then look for WGET +# +# Additionally, 1 or 2 are used and the retrieval fails, then if either CURL or +# WGET are available, an additional attempt will be using CURL/WGET. This is +# useful if the perl distribution has outdated modules that do not support +# modern SSL/TLS implementations +# +# To install the LWP perl modules required: +# +# On rpm based systems: +# +# yum install perl-libwww-perl.noarch perl-LWP-Protocol-https.noarch +# +# On APT based systems: +# +# apt-get install libwww-perl liblwp-protocol-https-perl +# +# Via cpan: +# +# perl -MCPAN -eshell +# cpan> install LWP LWP::Protocol::https +# +# We recommend setting this set to "2" or "3" as upgrades to csf will be +# performed over SSL as well as other URLs used when retrieving external data +# +# "1" = HTTP::Tiny +# "2" = LWP::UserAgent +# "3" = CURL/WGET (set location at the bottom of csf.conf) +URLGET = "2" + +# If you need csf/lfd to use a proxy, then you can set this option to the URL +# of the proxy. The proxy provided will be used for both HTTP and HTTPS +# connections +URLPROXY = "" + +############################################################################### +# SECTION:Country Code Lists and Settings +############################################################################### +# Country Code to CIDR allow/deny. In the following options you can allow or +# deny whole country CIDR ranges. The CIDR blocks are obtained from a selected +# source below. They also display Country Code Country and City for reported IP +# addresses and lookups +# +# There are a number of sources for these databases, before utilising them you +# need to visit each site and ensure you abide by their license provisions +# where stated: + +# 1. MaxMind +# +# MaxMind GeoLite2 Country/City and ASN databases at: +# https://dev.MaxMind.com/geoip/geoip2/geolite2/ +# This feature relies entirely on that service being available +# +# Advantages: This is a one stop shop for all of the databases required for +# these features. They provide a consistent dataset for blocking and reporting +# purposes +# +# Disadvantages: MaxMind require a license key to download their databases. +# This is free of charge, but requires the user to create an account on their +# website to generate the required key: +# +# WARNING: As of 2019-12-29, MaxMind REQUIRES you to create an account on their +# site and to generate a license key to use their databases. See: +# https://www.maxmind.com/en/geolite2/signup +# https://blog.maxmind.com/2019/12/18/significant-changes-to-accessing-and-using-geolite2-databases/ +# +# You MUST set the following to continue using the IP lookup features of csf, +# otherwise an error will be generated and the features will not work. +# Alternatively set CC_SRC below to a different provider +# +# MaxMind License Key: +MM_LICENSE_KEY = "" + +# 2. DB-IP, ipdeny.com, iptoasn.com +# +# Advantages: The ipdeny.com databases form CC blocking are better optimised +# and so are quicker to process and create fewer iptables entries. All of these +# databases are free to download without requiring login or key +# +# Disadvantages: Multiple sources mean that any one of the three could +# interrupt the provision of these features. It may also mean that there are +# inconsistences between them +# +# https://db-ip.com/db/lite.php +# http://ipdeny.com/ +# https://iptoasn.com/ +# http://download.geonames.org/export/dump/readme.txt + +# Set the following to your preferred source: +# +# "1" - MaxMind +# "2" - db-ip, ipdeny, iptoasn +# +# The default is "2" on new installations of csf, or set to "1" to use the +# MaxMind databases after obtaining a license key +CC_SRC = "2" + +# In the following options, specify the the two-letter ISO Country Code(s). +# The iptables rules are for incoming connections only +# +# Additionally, ASN numbers can also be added to the comma separated lists +# below that also list Country Codes. The same WARNINGS for Country Codes apply +# to the use of ASNs. More about Autonomous System Numbers (ASN): +# http://www.iana.org/assignments/as-numbers/as-numbers.xhtml +# ASNs must be listed as ASnnnn (where nnnn is the ASN number) +# +# You should consider using LF_IPSET when using any of the following options +# +# WARNING: These lists are never 100% accurate and some ISP's (e.g. AOL) use +# non-geographic IP address designations for their clients +# +# WARNING: Some of the CIDR lists are huge and each one requires a rule within +# the incoming iptables chain. This can result in significant performance +# overheads and could render the server inaccessible in some circumstances. For +# this reason (amongst others) we do not recommend using these options +# +# WARNING: Due to the resource constraints on VPS servers this feature should +# not be used on such systems unless you choose very small CC zones +# +# WARNING: CC_ALLOW allows access through all ports in the firewall. For this +# reason CC_ALLOW probably has very limited use and CC_ALLOW_FILTER is +# preferred +# +# Each option is a comma separated list of CC's, e.g. "US,GB,DE" +CC_DENY = "" +CC_ALLOW = "" + +# An alternative to CC_ALLOW is to only allow access from the following +# countries but still filter based on the port and packets rules. All other +# connections are dropped +CC_ALLOW_FILTER = "" + +# This option allows access from the following countries to specific ports +# listed in CC_ALLOW_PORTS_TCP and CC_ALLOW_PORTS_UDP +# +# Note: The rules for this feature are inserted after the allow and deny +# rules to still allow blocking of IP addresses +# +# Each option is a comma separated list of CC's, e.g. "US,GB,DE" +CC_ALLOW_PORTS = "" + +# All listed ports should be removed from TCP_IN/UDP_IN to block access from +# elsewhere. This option uses the same format as TCP_IN/UDP_IN +# +# An example would be to list port 21 here and remove it from TCP_IN/UDP_IN +# then only countries listed in CC_ALLOW_PORTS can access FTP +CC_ALLOW_PORTS_TCP = "" +CC_ALLOW_PORTS_UDP = "" + +# This option denies access from the following countries to specific ports +# listed in CC_DENY_PORTS_TCP and CC_DENY_PORTS_UDP +# +# Note: The rules for this feature are inserted after the allow and deny +# rules to still allow allowing of IP addresses +# +# Each option is a comma separated list of CC's, e.g. "US,GB,DE" +CC_DENY_PORTS = "" + +# This option uses the same format as TCP_IN/UDP_IN. The ports listed should +# NOT be removed from TCP_IN/UDP_IN +# +# An example would be to list port 21 here then countries listed in +# CC_DENY_PORTS cannot access FTP +CC_DENY_PORTS_TCP = "" +CC_DENY_PORTS_UDP = "" + +# This Country Code list will prevent lfd from blocking IP address hits for the +# listed CC's +# +# CC_LOOKUPS must be enabled to use this option +CC_IGNORE = "" + +# This Country Code list will only allow SMTP AUTH to be advertised to the +# listed countries in EXIM. This is to help limit attempts at distributed +# attacks against SMTP AUTH which are difficult to achive since port 25 needs +# to be open to relay email +# +# The reason why this works is that if EXIM does not advertise SMTP AUTH on a +# connection, then SMTP AUTH will not accept logins, defeating the attacks +# without restricting mail relaying +# +# This option can generate a very large list of IP addresses that could easily +# severely impact on SMTP (mail) performance, so care must be taken when +# selecting countries and if performance issues ensue +# +# The option SMTPAUTH_RESTRICT must be enabled to use this option +CC_ALLOW_SMTPAUTH = "" + +# These options can control which IP blocks are redirected to the MESSENGER +# service, if it is enabled +# +# If Country Codes are listed in CC_MESSENGER_ALLOW, then only a blocked IP +# that resolves to one of those Country Codes will be redirected to the +# MESSENGER service +# +# If Country Codes are listed in CC_MESSENGER_DENY, then a blocked IP that +# resolves to one of those Country Codes will NOT be redirected to the +# MESSENGER service +# +CC_MESSENGER_ALLOW = "" +CC_MESSENGER_DENY = "" + +# Set this option to a valid CIDR (i.e. 1 to 32) to ignore CIDR blocks smaller +# than this value when implementing CC_DENY/CC_ALLOW/CC_ALLOW_FILTER. This can +# help reduce the number of CC entries and may improve iptables throughput. +# Obviously, this will deny/allow fewer IP addresses depending on how small you +# configure the option +# +# For example, to ignore all CIDR (and single IP) entries small than a /16, set +# this option to "16". Set to "" to block all CC IP addresses +CC_DROP_CIDR = "" + +# Display Country Code and Country for reported IP addresses. This option can +# be configured to use the databases enabled at the top of this section. An +# additional option is also available if you cannot use those databases: +# +# "0" - disable +# "1" - Reports: Country Code and Country +# "2" - Reports: Country Code and Country and Region and City +# "3" - Reports: Country Code and Country and Region and City and ASN +# "4" - Reports: Country Code and Country and Region and City (db-ip.com) +# +# Note: "4" does not use the databases enabled at the top of this section +# directly for lookups. Instead it uses a URL-based lookup from +# https://db-ip.com and so avoids having to download and process the large +# databases. Please visit the https://db-ip.com and read their limitations and +# understand that this option will either cease to function or be removed by us +# if that site is abused or overloaded. ONLY use this option if you have +# difficulties using the databases enabled at the top of this section. This +# option is ONLY for IP lookups, NOT when using the CC_* options above, which +# will continue to use the databases enabled at the top of this section +# +CC_LOOKUPS = "1" + +# Display Country Code and Country for reported IPv6 addresses using the +# databases enabled at the top of this section +# +# "0" - disable +# "1" - enable and report the detail level as specified in CC_LOOKUPS +# +# This option must also be enabled to allow IPv6 support to CC_*, MESSENGER and +# PORTFLOOD +CC6_LOOKUPS = "0" + +# This option tells lfd how often to retrieve the databases for CC_ALLOW, +# CC_ALLOW_FILTER, CC_DENY, CC_IGNORE and CC_LOOKUPS (in days) +CC_INTERVAL = "14" + +############################################################################### +# SECTION:Login Failure Blocking and Alerts +############################################################################### +# The following[*] triggers are application specific. If you set LF_TRIGGER to +# "0" the value of each trigger is the number of failures against that +# application that will trigger lfd to block the IP address +# +# If you set LF_TRIGGER to a value greater than "0" then the following[*] +# application triggers are simply on or off ("0" or "1") and the value of +# LF_TRIGGER is the total cumulative number of failures that will trigger lfd +# to block the IP address +# +# Setting the application trigger to "0" disables it +LF_TRIGGER = "0" + +# If LF_TRIGGER is > "0" then LF_TRIGGER_PERM can be set to "1" to permanently +# block the IP address, or LF_TRIGGER_PERM can be set to a value greater than +# "1" and the IP address will be blocked temporarily for that value in seconds. +# For example: +# LF_TRIGGER_PERM = "1" => the IP is blocked permanently +# LF_TRIGGER_PERM = "3600" => the IP is blocked temporarily for 1 hour +# +# If LF_TRIGGER is "0", then the application LF_[application]_PERM value works +# in the same way as above and LF_TRIGGER_PERM serves no function +LF_TRIGGER_PERM = "1" + +# To only block access to the failed application instead of a complete block +# for an ip address, you can set the following to "1", but LF_TRIGGER must be +# set to "0" with specific application[*] trigger levels also set appropriately +# +# The ports that are blocked can be configured by changing the PORTS_* options +LF_SELECT = "0" + +# Send an email alert if an IP address is blocked by one of the [*] triggers +LF_EMAIL_ALERT = "1" + +# Send an email alert if an IP address is only temporarily blocked by one of +# the [*] triggers +# +# Note: LF_EMAIL_ALERT must still be enabled to get permanent block emails +LF_TEMP_EMAIL_ALERT = "1" + +# [*]Enable login failure detection of sshd connections +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_SSHD = "5" +LF_SSHD_PERM = "1" + +# [*]Enable login failure detection of ftp connections +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_FTPD = "10" +LF_FTPD_PERM = "1" + +# [*]Enable login failure detection of SMTP AUTH connections +LF_SMTPAUTH = "5" +LF_SMTPAUTH_PERM = "1" + +# [*]Enable syntax failure detection of Exim connections +LF_EXIMSYNTAX = "10" +LF_EXIMSYNTAX_PERM = "1" + +# [*]Enable login failure detection of pop3 connections +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_POP3D = "0" +LF_POP3D_PERM = "1" + +# [*]Enable login failure detection of imap connections +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_IMAPD = "0" +LF_IMAPD_PERM = "1" + +# [*]Enable login failure detection of Apache .htpasswd connections +# Due to the often high logging rate in the Apache error log, you might want to +# enable this option only if you know you are suffering from attacks against +# password protected directories +LF_HTACCESS = "5" +LF_HTACCESS_PERM = "1" + +# [*]Enable failure detection of repeated Apache mod_security rule triggers +LF_MODSEC = "5" +LF_MODSEC_PERM = "1" + +# [*]Enable detection of repeated BIND denied requests +# This option should be enabled with care as it will prevent blocked IPs from +# resolving any domains on the server. You might want to set the trigger value +# reasonably high to avoid this +# Example: LF_BIND = "100" +LF_BIND = "0" +LF_BIND_PERM = "1" + +# [*]Enable detection of repeated suhosin ALERTs +# Example: LF_SUHOSIN = "5" +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_SUHOSIN = "0" +LF_SUHOSIN_PERM = "1" + +# [*]Enable detection of repeated cxs ModSecurity mod_security rule triggers +# This option will block IP addresses if cxs detects a hits from the +# ModSecurity rule associated with it +# +# Note: This option takes precedence over LF_MODSEC and removes any hits +# counted towards LF_MODSEC for the cxs rule +# +# This setting should probably set very low, perhaps to 1, if you want to +# effectively block IP addresses for this trigger option +LF_CXS = "0" +LF_CXS_PERM = "1" + +# [*]Enable detection of repeated Apache mod_qos rule triggers +LF_QOS = "0" +LF_QOS_PERM = "1" + +# [*]Enable detection of repeated Apache symlink race condition triggers from +# the Apache patch provided by: +# http://www.mail-archive.com/dev@httpd.apache.org/msg55666.html +# This patch has also been included by cPanel via the easyapache option: +# "Symlink Race Condition Protection" +LF_SYMLINK = "0" +LF_SYMLINK_PERM = "1" + +# [*]Enable login failure detection of webmin connections +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_WEBMIN = "0" +LF_WEBMIN_PERM = "1" + +# Send an email alert if anyone logs in successfully using SSH +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_SSH_EMAIL_ALERT = "1" + +# Send an email alert if anyone uses su to access another account. This will +# send an email alert whether the attempt to use su was successful or not +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_SU_EMAIL_ALERT = "1" + +# Send an email alert if anyone uses sudo to access another account. This will +# send an email alert whether the attempt to use sudo was successful or not +# +# NOTE: This option could become onerous if sudo is used extensively for root +# access by administrators or control panels. It is provided for those where +# this is not the case +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_SUDO_EMAIL_ALERT = "0" + +# Send an email alert if anyone accesses webmin +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_WEBMIN_EMAIL_ALERT = "1" + +# Send an email alert if anyone logs in successfully to root on the console +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_CONSOLE_EMAIL_ALERT = "1" + +# This option will keep track of the number of "File does not exist" errors in +# HTACCESS_LOG. If the number of hits is more than LF_APACHE_404 in LF_INTERVAL +# seconds then the IP address will be blocked +# +# Care should be used with this option as it could generate many +# false-positives, especially Search Bots (use csf.rignore to ignore such bots) +# so only use this option if you know you are under this type of attack +# +# A sensible setting for this would be quite high, perhaps 200 +# +# To disable set to "0" +LF_APACHE_404 = "0" + +# If this option is set to 1 the blocks will be permanent +# If this option is > 1, the blocks will be temporary for the specified number +# of seconds +LF_APACHE_404_PERM = "3600" + +# This option will keep track of the number of "client denied by server +# configuration" errors in HTACCESS_LOG. If the number of hits is more than +# LF_APACHE_403 in LF_INTERVAL seconds then the IP address will be blocked +# +# Care should be used with this option as it could generate many +# false-positives, especially Search Bots (use csf.rignore to ignore such bots) +# so only use this option if you know you are under this type of attack +# +# A sensible setting for this would be quite high, perhaps 200 +# +# To disable set to "0" +LF_APACHE_403 = "0" + +# If this option is set to 1 the blocks will be permanent +# If this option is > 1, the blocks will be temporary for the specified number +# of seconds +LF_APACHE_403_PERM = "3600" + +# This option will keep track of the number of 401 failures in HTACCESS_LOG. +# If the number of hits is more than LF_APACHE_401 in LF_INTERVAL seconds then +# the IP address will be blocked +# +# To disable set to "0" +LF_APACHE_401 = "0" + +# This option is used to determine if the Apache error_log format contains the +# client port after the client IP. In Apache prior to v2.4, this was not the +# case. In Apache v2.4+ the error_log format can be configured using +# ErrorLogFormat, making the port directive optional +# +# Unfortunately v2.4 ErrorLogFormat places the port number after a colon next +# to the client IP by default. This makes determining client IPv6 addresses +# difficult unless we know whether the port is being appended or not +# +# lfd will attempt to autodetect the correct value if this option is set to "0" +# from the httpd binary found in common locations. If it fails to find a binary +# it will be set to "2", unless specified here +# +# The value can be set here explicitly if the autodetection does not work: +# 0 - autodetect +# 1 - no port directive after client IP +# 2 - port directive after client IP +LF_APACHE_ERRPORT = "0" + +# If this option is set to 1 the blocks will be permanent +# If this option is > 1, the blocks will be temporary for the specified number +# of seconds +LF_APACHE_401_PERM = "3600" + +# This option will send an alert if the ModSecurity IP persistent storage grows +# excessively large: https://goo.gl/rGh5sF +# +# More information on cPanel servers here: https://goo.gl/vo6xTE +# +# LF_MODSECIPDB_FILE must be set to the correct location of the database file +# +# The check is performed at lfd startup and then once per hour, the template +# used is modsecipdbalert.txt +# +# Set to "0" to disable this option, otherwise it is the threshold size of the +# file to report in gigabytes, e.g. set to 5 for 5GB +LF_MODSECIPDB_ALERT = "0" + +# This is the location of the persistent IP storage file on the server, e.g.: +# /var/run/modsecurity/data/ip.pag +# /var/cpanel/secdatadir/ip.pag +# /var/cache/modsecurity/ip.pag +# /usr/local/apache/conf/modsec/data/msa/ip.pag +# /var/tmp/ip.pag +# /tmp/ip.pag +LF_MODSECIPDB_FILE = "/var/run/modsecurity/data/ip.pag" + +# System Exploit Checking. This option is designed to perform a series of tests +# to send an alert in case a possible server compromise is detected +# +# To enable this feature set the following to the checking interval in seconds +# (a value of 300 would seem sensible). +# +# To disable set to "0" +LF_EXPLOIT = "300" + +# This comma separated list allows you to ignore tests LF_EXPLOIT performs +# +# For the SUPERUSER check, you can list usernames in csf.suignore to have them +# ignored for that test +# +# Valid tests are: +# SUPERUSER +# +# If you want to ignore a test add it to this as a comma separated list, e.g. +# "SUPERUSER" +LF_EXPLOIT_IGNORE = "" + +# Set the time interval to track login and other LF_ failures within (seconds), +# i.e. LF_TRIGGER failures within the last LF_INTERVAL seconds +LF_INTERVAL = "3600" + +# This is how long the lfd process sleeps (in seconds) before processing the +# log file entries and checking whether other events need to be triggered +LF_PARSE = "5" + +# This is the interval that is used to flush reports of usernames, files and +# pids so that persistent problems continue to be reported, in seconds. +# A value of 3600 seems sensible +LF_FLUSH = "3600" + +# Under some circumstances iptables can fail to include a rule instruction, +# especially if more than one request is made concurrently. In this event, a +# permanent block entry may exist in csf.deny, but not in iptables. +# +# This option instructs csf to deny an already blocked IP address the number +# of times set. The downside, is that there will be multiple entries for an IP +# address in csf.deny and possibly multiple rules for the same IP address in +# iptables. This needs to be taken into consideration when unblocking such IP +# addresses. +# +# Set to "0" to disable this feature. Do not set this too high for the reasons +# detailed above (e.g. "5" should be more than enough) +LF_REPEATBLOCK = "0" + +# By default csf will create both an inbound and outbound blocks from/to an IP +# unless otherwise specified in csf.deny and GLOBAL_DENY. This is the most +# effective way to block IP traffic. This option instructs csf to only block +# inbound traffic from those IP's and so reduces the number of iptables rules, +# but at the expense of less effectiveness. For this reason we recommend +# leaving this option disabled +# +# Set to "0" to disable this feature - the default +LF_BLOCKINONLY = "0" + +############################################################################### +# SECTION:CloudFlare +############################################################################### +# This features provides interaction with the CloudFlare Firewall +# +# As CloudFlare is a reverse proxy, any attacking IP addresses (so far as +# iptables is concerned) come from the CloudFlare IP's. To counter this, an +# Apache module (mod_cloudflare) is available that obtains the true attackers +# IP from a custom HTTP header record (similar functionality is available +# for other HTTP daemons +# +# However, despite now knowing the true attacking IP address, iptables cannot +# be used to block that IP as the traffic is still coming from the CloudFlare +# servers +# +# CloudFlare have provided a Firewall feature within the user account where +# rules can be added to block, challenge or whitelist IP addresses +# +# Using the CloudFlare API, this feature adds and removes attacking IPs from +# that firewall and provides CLI (and via the UI) additional commands +# +# See /etc/csf/readme.txt for more information about this feature and the +# restrictions for its use BEFORE enabling this feature +CF_ENABLE = "0" + +# This can be set to either "block" or "challenge" (see CloudFlare docs) +CF_BLOCK = "block" + +# This setting determines how long the temporary block will apply within csf +# and CloudFlare, keeping them in sync +# +# Block duration in seconds - overrides perm block or time of individual blocks +# in lfd for block triggers +CF_TEMP = "3600" + +############################################################################### +# SECTION:Directory Watching & Integrity +############################################################################### +# Enable Directory Watching. This enables lfd to check /tmp and /dev/shm +# directories for suspicious files, i.e. script exploits. If a suspicious +# file is found an email alert is sent. One alert per file per LF_FLUSH +# interval is sent +# +# To enable this feature set the following to the checking interval in seconds. +# To disable set to "0" +LF_DIRWATCH = "300" + +# To remove any suspicious files found during directory watching, enable the +# following. These files will be appended to a tarball in +# /var/lib/csf/suspicious.tar +LF_DIRWATCH_DISABLE = "0" + +# This option allows you to have lfd watch a particular file or directory for +# changes and should they change and email alert using watchalert.txt is sent +# +# To enable this feature set the following to the checking interval in seconds +# (a value of 60 would seem sensible) and add your entries to csf.dirwatch +# +# Set to disable set to "0" +LF_DIRWATCH_FILE = "0" + +# System Integrity Checking. This enables lfd to compare md5sums of the +# servers OS binary application files from the time when lfd starts. If the +# md5sum of a monitored file changes an alert is sent. This option is intended +# as an IDS (Intrusion Detection System) and is the last line of detection for +# a possible root compromise. +# +# There will be constant false-positives as the servers OS is updated or +# monitored application binaries are updated. However, unexpected changes +# should be carefully inspected. +# +# Modified files will only be reported via email once. +# +# To enable this feature set the following to the checking interval in seconds +# (a value of 3600 would seem sensible). This option may increase server I/O +# load onto the server as it checks system binaries. +# +# To disable set to "0" +LF_INTEGRITY = "3600" + +############################################################################### +# SECTION:Distributed Attacks +############################################################################### +# Distributed Account Attack. This option will keep track of login failures +# from distributed IP addresses to a specific application account. If the +# number of failures matches the trigger value above, ALL of the IP addresses +# involved in the attack will be blocked according to the temp/perm rules above +# +# Tracking applies to LF_SSHD, LF_FTPD, LF_SMTPAUTH, LF_POP3D, LF_IMAPD, +# LF_HTACCESS +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_DISTATTACK = "0" + +# Set the following to the minimum number of unique IP addresses that trigger +# LF_DISTATTACK +LF_DISTATTACK_UNIQ = "2" + +# Distributed FTP Logins. This option will keep track of successful FTP logins. +# If the number of successful logins to an individual account is at least +# LF_DISTFTP in LF_DIST_INTERVAL from at least LF_DISTFTP_UNIQ IP addresses, +# then all of the IP addresses will be blocked +# +# This option can help mitigate the common FTP account compromise attacks that +# use a distributed network of zombies to deface websites +# +# A sensible setting for this might be 5, depending on how many different +# IP addresses you expect to an individual FTP account within LF_DIST_INTERVAL +# +# To disable set to "0" +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_DISTFTP = "0" + +# Set the following to the minimum number of unique IP addresses that trigger +# LF_DISTFTP. LF_DISTFTP_UNIQ must be <= LF_DISTFTP for this to work +LF_DISTFTP_UNIQ = "3" + +# If this option is set to 1 the blocks will be permanent +# If this option is > 1, the blocks will be temporary for the specified number +# of seconds +LF_DISTFTP_PERM = "1" + +# Send an email alert if LF_DISTFTP is triggered +LF_DISTFTP_ALERT = "1" + +# Distributed SMTP Logins. This option will keep track of successful SMTP +# logins. If the number of successful logins to an individual account is at +# least LF_DISTSMTP in LF_DIST_INTERVAL from at least LF_DISTSMTP_UNIQ IP +# addresses, then all of the IP addresses will be blocked. These options only +# apply to the exim MTA +# +# This option can help mitigate the common SMTP account compromise attacks that +# use a distributed network of zombies to send spam +# +# A sensible setting for this might be 5, depending on how many different +# IP addresses you expect to an individual SMTP account within LF_DIST_INTERVAL +# +# To disable set to "0" +LF_DISTSMTP = "0" + +# Set the following to the minimum number of unique IP addresses that trigger +# LF_DISTSMTP. LF_DISTSMTP_UNIQ must be <= LF_DISTSMTP for this to work +LF_DISTSMTP_UNIQ = "3" + +# If this option is set to 1 the blocks will be permanent +# If this option is > 1, the blocks will be temporary for the specified number +# of seconds +LF_DISTSMTP_PERM = "1" + +# Send an email alert if LF_DISTSMTP is triggered +LF_DISTSMTP_ALERT = "1" + +# This is the interval during which a distributed FTP or SMTP attack is +# measured +LF_DIST_INTERVAL = "300" + +# If LF_DISTFTP or LF_DISTSMTP is triggered, then if the following contains the +# path to a script, it will run the script and pass the following as arguments: +# +# LF_DISTFTP/LF_DISTSMTP +# account name +# log file text +# +# The action script must have the execute bit and interpreter (shebang) set +LF_DIST_ACTION = "" + +############################################################################### +# SECTION:Login Tracking +############################################################################### +# Block POP3 logins if greater than LT_POP3D times per hour per account per IP +# address (0=disabled) +# +# This is a temporary block for the rest of the hour, afterwhich the IP is +# unblocked +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LT_POP3D = "0" + +# Block IMAP logins if greater than LT_IMAPD times per hour per account per IP +# address (0=disabled) - not recommended for IMAP logins due to the ethos +# within which IMAP works. If you want to use this, setting it quite high is +# probably a good idea +# +# This is a temporary block for the rest of the hour, afterwhich the IP is +# unblocked +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LT_IMAPD = "0" + +# Send an email alert if an account exceeds LT_POP3D/LT_IMAPD logins per hour +# per IP +LT_EMAIL_ALERT = "1" + +# If LF_PERMBLOCK is enabled but you do not want this to apply to +# LT_POP3D/LT_IMAPD, then enable this option +LT_SKIPPERMBLOCK = "0" + +############################################################################### +# SECTION:Connection Tracking +############################################################################### +# Connection Tracking. This option enables tracking of all connections from IP +# addresses to the server. If the total number of connections is greater than +# this value then the offending IP address is blocked. This can be used to help +# prevent some types of DOS attack. +# +# Care should be taken with this option. It's entirely possible that you will +# see false-positives. Some protocols can be connection hungry, e.g. FTP, IMAPD +# and HTTP so it could be quite easy to trigger, especially with a lot of +# closed connections in TIME_WAIT. However, for a server that is prone to DOS +# attacks this may be very useful. A reasonable setting for this option might +# be around 300. +# +# To disable this feature, set this to 0 +CT_LIMIT = "0" + +# Connection Tracking interval. Set this to the the number of seconds between +# connection tracking scans +CT_INTERVAL = "30" + +# Send an email alert if an IP address is blocked due to connection tracking +CT_EMAIL_ALERT = "1" + +# If you want to make IP blocks permanent then set this to 1, otherwise blocks +# will be temporary and will be cleared after CT_BLOCK_TIME seconds +CT_PERMANENT = "0" + +# If you opt for temporary IP blocks for CT, then the following is the interval +# in seconds that the IP will remained blocked for (e.g. 1800 = 30 mins) +CT_BLOCK_TIME = "1800" + +# If you don't want to count the TIME_WAIT state against the connection count +# then set the following to "1" +CT_SKIP_TIME_WAIT = "0" + +# If you only want to count specific states (e.g. SYN_RECV) then add the states +# to the following as a comma separated list. E.g. "SYN_RECV,TIME_WAIT" +# +# Leave this option empty to count all states against CT_LIMIT +CT_STATES = "" + +# If you only want to count specific ports (e.g. 80,443) then add the ports +# to the following as a comma separated list. E.g. "80,443" +# +# Leave this option empty to count all ports against CT_LIMIT +CT_PORTS = "" + +# If the total number of connections from a class C subnet is greater than this +# value then the offending subnet is blocked according to the other CT_* +# settings +# +# This option can be used to help prevent some types of DOS attack where a +# range of IP's between x.y.z.1-255 has connected to the server +# +# If you use a reverse proxy service such as Cloudflare you should not enable +# this option, or should exclude the ports that you have proxied in CT_PORTS +# +# To disable this feature, set this to 0 +CT_SUBNET_LIMIT = "0" + +############################################################################### +# SECTION:Process Tracking +############################################################################### +# Process Tracking. This option enables tracking of user and nobody processes +# and examines them for suspicious executables or open network ports. Its +# purpose is to identify potential exploit processes that are running on the +# server, even if they are obfuscated to appear as system services. If a +# suspicious process is found an alert email is sent with relevant information. +# It is then the responsibility of the recipient to investigate the process +# further as the script takes no further action +# +# The following is the number of seconds a process has to be active before it +# is inspected. If you set this time too low, then you will likely trigger +# false-positives with CGI or PHP scripts. +# Set the value to 0 to disable this feature +PT_LIMIT = "60" + +# How frequently processes are checked in seconds +PT_INTERVAL = "60" + +# If you want process tracking to highlight php or perl scripts that are run +# through apache then disable the following, +# i.e. set it to 0 +# +# While enabling this setting will reduce false-positives, having it set to 0 +# does provide better checking for exploits running on the server +PT_SKIP_HTTP = "0" + +# lfd will report processes, even if they're listed in csf.pignore, if they're +# tagged as (deleted) by Linux. This information is provided in Linux under +# /proc/PID/exe. A (deleted) process is one that is running a binary that has +# the inode for the file removed from the file system directory. This usually +# happens when the binary has been replaced due to an upgrade for it by the OS +# vendor or another third party (e.g. cPanel). You need to investigate whether +# this is indeed the case to be sure that the original binary has not been +# replaced by a rootkit or is running an exploit. +# +# Note: If a deleted executable process is detected and reported then lfd will +# not report children of the parent (or the parent itself if a child triggered +# the report) if the parent is also a deleted executable process +# +# To stop lfd reporting such process you need to restart the daemon to which it +# belongs and therefore run the process using the replacement binary (presuming +# one exists). This will normally mean running the associated startup script in +# /etc/init.d/ +# +# If you do want lfd to report deleted binary processes, set to 1 +PT_DELETED = "0" + +# If a PT_DELETED event is triggered, then if the following contains the path to +# a script, it will be run in a child process and passed the executable, pid, +# account for the process, and parent pid +# +# The action script must have the execute bit and interpreter (shebang) set. An +# example is provided in /usr/local/csf/bin/pt_deleted_action.pl +# +# WARNING: Make sure you read and understand the potential security +# implications of such processes in PT_DELETED above before simply restarting +# such processes with a script +PT_DELETED_ACTION = "" + +# User Process Tracking. This option enables the tracking of the number of +# process any given account is running at one time. If the number of processes +# exceeds the value of the following setting an email alert is sent with +# details of those processes. If you specify a user in csf.pignore it will be +# ignored +# +# Set to 0 to disable this feature +PT_USERPROC = "10" + +# This User Process Tracking option sends an alert if any user process exceeds +# the virtual memory usage set (MB). To ignore specific processes or users use +# csf.pignore +# +# Set to 0 to disable this feature +PT_USERMEM = "512" + +# This User Process Tracking option sends an alert if any user process exceeds +# the RSS memory usage set (MB) - RAM used, not virtual. To ignore specific +# processes or users use csf.pignore +# +# Set to 0 to disable this feature +PT_USERRSS = "256" + +# This User Process Tracking option sends an alert if any linux user process +# exceeds the time usage set (seconds). To ignore specific processes or users +# use csf.pignore +# +# Set to 0 to disable this feature +PT_USERTIME = "1800" + +# If this option is set then processes detected by PT_USERMEM, PT_USERTIME or +# PT_USERPROC are killed +# +# Warning: We don't recommend enabling this option unless absolutely necessary +# as it can cause unexpected problems when processes are suddenly terminated. +# It can also lead to system processes being terminated which could cause +# stability issues. It is much better to leave this option disabled and to +# investigate each case as it is reported when the triggers above are breached +# +# Note: Processes that are running deleted excecutables (see PT_DELETED) will +# not be killed by lfd +PT_USERKILL = "0" + +# If you want to disable email alerts if PT_USERKILL is triggered, then set +# this option to 0 +PT_USERKILL_ALERT = "1" + +# If a PT_* event is triggered, then if the following contains the path to +# a script, it will be run in a child process and passed the PID(s) of the +# process(es) in a comma separated list. +# +# The action script must have the execute bit and interpreter (shebang) set +PT_USER_ACTION = "" + +# Check the PT_LOAD_AVG minute Load Average (can be set to 1 5 or 15 and +# defaults to 5 if set otherwise) on the server every PT_LOAD seconds. If the +# load average is greater than or equal to PT_LOAD_LEVEL then an email alert is +# sent. lfd then does not report subsequent high load until PT_LOAD_SKIP +# seconds has passed to prevent email floods. +# +# Set PT_LOAD to "0" to disable this feature +PT_LOAD = "30" +PT_LOAD_AVG = "5" +PT_LOAD_LEVEL = "6" +PT_LOAD_SKIP = "3600" + +# This is the Apache Server Status URL used in the email alert. Requires the +# Apache mod_status module to be installed and configured correctly +PT_APACHESTATUS = "http://127.0.0.1/server-status" + +# If a PT_LOAD event is triggered, then if the following contains the path to +# a script, it will be run in a child process. For example, the script could +# contain commands to terminate and restart httpd, php, exim, etc incase of +# looping processes. The action script must have the execute bit an +# interpreter (shebang) set +PT_LOAD_ACTION = "" + +# Fork Bomb Protection. This option checks the number of processes with the +# same session id and if greater than the value set, the whole session tree is +# terminated and an alert sent +# +# You can see an example of common session id processes on most Linux systems +# using: "ps axf -O sid" +# +# On cPanel servers, PT_ALL_USERS should be enabled to use this option +# effectively +# +# This option will check root owned processes. Session id 0 and 1 will always +# be ignored as they represent kernel and init processes. csf.pignore will be +# honoured, but bear in mind that a session tree can contain a variety of users +# and executables +# +# Care needs to be taken to ensure that this option only detects runaway fork +# bombs, so should be set higher than any session tree is likely to get (e.g. +# httpd could have 100s of legitimate children on very busy systems). A +# sensible starting point on most servers might be 250 +PT_FORKBOMB = "0" + +# Terminate hung SSHD sessions. When under an SSHD login attack, SSHD processes +# are often left hanging after their connecting IP addresses have been blocked +# +# This option will terminate the SSH processes created by the blocked IP. This +# option is preferred over PT_SSHDHUNG +PT_SSHDKILL = "0" + +# This option will terminate all processes with the cmdline of "sshd: unknown +# [net]" or "sshd: unknown [priv]" if they have been running for more than 60 +# seconds +PT_SSHDHUNG = "0" + +############################################################################### +# SECTION:Port Scan Tracking +############################################################################### +# Port Scan Tracking. This feature tracks port blocks logged by iptables to +# syslog. If an IP address generates a port block that is logged more than +# PS_LIMIT within PS_INTERVAL seconds, the IP address will be blocked. +# +# This feature could, for example, be useful for blocking hackers attempting +# to access the standard SSH port if you have moved it to a port other than 22 +# and have removed 22 from the TCP_IN list so that connection attempts to the +# old port are being logged +# +# This feature blocks all iptables blocks from the iptables logs, including +# repeated attempts to one port or SYN flood blocks, etc +# +# Note: This feature will only track iptables blocks from the log file set in +# IPTABLES_LOG below and if you have DROP_LOGGING enabled. However, it will +# cause redundant blocking with DROP_IP_LOGGING enabled +# +# Warning: It's possible that an elaborate DDOS (i.e. from multiple IP's) +# could very quickly fill the iptables rule chains and cause a DOS in itself. +# The DENY_IP_LIMIT should help to mitigate such problems with permanent blocks +# and the DENY_TEMP_IP_LIMIT with temporary blocks +# +# Set PS_INTERVAL to "0" to disable this feature. A value of between 60 and 300 +# would be sensible to enable this feature +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +PS_INTERVAL = "0" +PS_LIMIT = "10" + +# You can specify the ports and/or port ranges that should be tracked by the +# Port Scan Tracking feature. The following setting is a comma separated list +# of those ports and uses the same format as TCP_IN. The setting of +# 0:65535,ICMP,INVALID,OPEN,BRD covers all ports +# +# Special values are: +# ICMP - include ICMP blocks (see ICMP_*) +# INVALID - include INVALID blocks (see PACKET_FILTER) +# OPEN - include TCP_IN and UDP_IN open port blocks - *[proto]_IN Blocked* +# BRD - include UDP Broadcast IPs, otherwise they are ignored +PS_PORTS = "0:65535,ICMP" + +# To specify how many different ports qualifies as a Port Scan you can increase +# the following from the default value of 1. The risk in doing so will mean +# that persistent attempts to attack a specific closed port will not be +# detected and blocked +PS_DIVERSITY = "1" + +# You can select whether IP blocks for Port Scan Tracking should be temporary +# or permanent. Set PS_PERMANENT to "0" for temporary and "1" for permanent +# blocking. If set to "0" PS_BLOCK_TIME is the amount of time in seconds to +# temporarily block the IP address for +PS_PERMANENT = "0" +PS_BLOCK_TIME = "3600" + +# Set the following to "1" to enable Port Scan Tracking email alerts, set to +# "0" to disable them +PS_EMAIL_ALERT = "1" + +############################################################################### +# SECTION:User ID Tracking +############################################################################### +# User ID Tracking. This feature tracks UID blocks logged by iptables to +# syslog. If a UID generates a port block that is logged more than UID_LIMIT +# times within UID_INTERVAL seconds, an alert will be sent +# +# Note: This feature will only track iptables blocks from the log file set in +# IPTABLES_LOG and if DROP_OUT_LOGGING and DROP_UID_LOGGING are enabled. +# +# To ignore specific UIDs list them in csf.uidignore and then restart lfd +# +# Set UID_INTERVAL to "0" to disable this feature. A value of between 60 and 300 +# would be sensible to enable this feature +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +UID_INTERVAL = "0" +UID_LIMIT = "10" + +# You can specify the ports and/or port ranges that should be tracked by the +# User ID Tracking feature. The following setting is a comma separated list +# of those ports and uses the same format as TCP_OUT. The default setting of +# 0:65535,ICMP covers all ports +UID_PORTS = "0:65535,ICMP" + +############################################################################### +# SECTION:Account Tracking +############################################################################### +# Account Tracking. The following options enable the tracking of modifications +# to the accounts on a server. If any of the enabled options are triggered by +# a modifications to an account, an alert email is sent. Only the modification +# is reported. The cause of the modification will have to be investigated +# manually +# +# You can set AT_ALERT to the following: +# 0 = disable this feature +# 1 = enable this feature for all accounts +# 2 = enable this feature only for superuser accounts (UID = 0, e.g. root, etc) +# 3 = enable this feature only for the root account +AT_ALERT = "2" + +# This options is the interval between checks in seconds +AT_INTERVAL = "60" + +# Send alert if a new account is created +AT_NEW = "1" + +# Send alert if an existing account is deleted +AT_OLD = "1" + +# Send alert if an account password has changed +AT_PASSWD = "1" + +# Send alert if an account uid has changed +AT_UID = "1" + +# Send alert if an account gid has changed +AT_GID = "1" + +# Send alert if an account login directory has changed +AT_DIR = "1" + +# Send alert if an account login shell has changed +AT_SHELL = "1" + +############################################################################### +# SECTION:Integrated User Interface +############################################################################### +# Integrated User Interface. This feature provides a HTML UI to csf and lfd, +# without requiring a control panel or web server. The UI runs as a sub process +# to the lfd daemon +# +# As it runs under the root account and successful login provides root access +# to the server, great care should be taken when configuring and using this +# feature. There are additional restrictions to enhance secure access to the UI +# +# See readme.txt for more information about using this feature BEFORE enabling +# it for security and access reasons +# +# 1 to enable, 0 to disable +UI = "0" + +# Set this to the port that want to bind this service to. You should configure +# this port to be >1023 and different from any other port already being used +# +# Do NOT enable access to this port in TCP_IN, instead only allow trusted IP's +# to the port using Advanced Allow Filters (see readme.txt) +UI_PORT = "6666" + +# Optionally set the IP address to bind to. Normally this should be left blank +# to bind to all IP addresses on the server. +# +# If the server is configured for IPv6 but the IP to bind to is IPv4, then the +# IP address MUST use the IPv6 representation. For example 1.2.3.4 must use +# ::ffff:1.2.3.4 +# +# Leave blank to bind to all IP addresses on the server +UI_IP = "" + +# This should be a secure, hard to guess username +# +# This must be changed from the default +UI_USER = "username" + +# This should be a secure, hard to guess password. That is, at least 8 +# characters long with a mixture of upper and lowercase characters plus +# numbers and non-alphanumeric characters +# +# This must be changed from the default +UI_PASS = "password" + +# This is the login session timeout. If there is no activity for a logged in +# session within this number of seconds, the session will timeout and a new +# login will be required +# +# For security reasons, you should always keep this option low (i.e 60-300) +UI_TIMEOUT = "300" + +# This is the maximum concurrent connections allowed to the server. The default +# value should be sufficient +UI_CHILDREN = "5" + +# The number of login retries allowed within a 24 hour period. A successful +# login from the IP address will clear the failures +# +# For security reasons, you should always keep this option low (i.e 0-10) +UI_RETRY = "5" + +# If enabled, this option will add the connecting IP address to the file +# /etc/csf/ui/ui.ban after UI_RETRY login failures. The IP address will not be +# able to login to the UI while it is listed in this file. The UI_BAN setting +# does not refer to any of the csf/lfd allow or ignore files, e.g. csf.allow, +# csf.ignore, etc. +# +# For security reasons, you should always enable this option +UI_BAN = "1" + +# If enabled, only IPs (or CIDR's) listed in the file /etc/csf/ui/ui.allow will +# be allowed to login to the UI. The UI_ALLOW setting does not refer to any of +# the csf/lfd allow or ignore files, e.g. csf.allow, csf.ignore, etc. +# +# For security reasons, you should always enable this option and use ui.allow +UI_ALLOW = "1" + +# If enabled, this option will trigger an iptables block through csf after +# UI_RETRY login failures +# +# 0 = no block;1 = perm block;nn=temp block for nn secs +UI_BLOCK = "1" + +# This controls what email alerts are sent with regards to logins to the UI. It +# uses the uialert.txt template +# +# 4 = login success + login failure/ban/block + login attempts +# 3 = login success + login failure/ban/block +# 2 = login failure/ban/block +# 1 = login ban/block +# 0 = disabled +UI_ALERT = "4" + +# This is the SSL cipher list that the Integrated UI will negotiate from +UI_CIPHER = "ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:-LOW:-SSLv2:-EXP:!kEDH" + +# This is the SSL protocol version used. See IO::Socket::SSL if you wish to +# change this and to understand the implications of changing it +UI_SSL_VERSION = "SSLv23:!SSLv3:!SSLv2" + +# If cxs is installed then enabling this option will provide a dropdown box to +# switch between applications +UI_CXS = "0" + +# There is a modified installation of ConfigServer Explorer (cse) provided with +# the csf distribution. If this option is enabled it will provide a dropdown +# box to switch between applications +UI_CSE = "0" + +############################################################################### +# SECTION:Messenger service +############################################################################### +# Messenger service. This feature allows the display of a message to a blocked +# connecting IP address to inform the user that they are blocked in the +# firewall. This can help when users get themselves blocked, e.g. due to +# multiple login failures. The service is provided by two daemons running on +# ports providing either an HTML or TEXT message +# +# This feature does not work on servers that do not have the iptables module +# ipt_REDIRECT loaded. Typically, this will be with MONOLITHIC kernels. VPS +# server admins should check with their VPS host provider that the iptables +# module is included +# +# IPv6 will need the IO::Socket::INET6 perl module +# +# For further information on features and limitations refer to the csf +# readme.txt +# +# Note: Run /etc/csf/csftest.pl to check whether this option will function on +# this server +# +# 1 to enable, 0 to disable +MESSENGER = "0" + +# Provide this service to temporary IP address blocks +MESSENGER_TEMP = "1" + +# Provide this service to permanent IP address blocks +MESSENGER_PERM = "1" + +# User account to run the service servers under. We recommend creating a +# specific non-priv, non-shell account for this purpose +# +# Note: When using MESSENGERV2, this account must NOT be a valid control panel +# account, it must be created manually as explained in the csf readme.txt +MESSENGER_USER = "csf" + +# This option points to the file(s) containing the Apache VirtualHost SSL +# definitions. This can be a file glob if there are multiple files to search. +# Only Apache v2 SSL VirtualHost definitions are supported +# +# This is used by MESSENGERV1 and MESSENGERV2 only +MESSENGER_HTTPS_CONF = "/etc/httpd/conf.d/ssl.conf" + +# The following options can be specified to provide a default fallback +# certificate to be used if either SNI is not supported or a hosted domain does +# not have an SSL certificate. If a fallback is not provided, one of the certs +# obtained from MESSENGER_HTTPS_CONF will be used +# +# This is used by MESSENGERV1 and MESSENGERV2 only +MESSENGER_HTTPS_KEY = "/etc/pki/tls/private/localhost.key" +MESSENGER_HTTPS_CRT = "/etc/pki/tls/certs/localhost.crt" + +# Set this to the port that will receive the HTTPS HTML message. You should +# configure this port to be >1023 and different from the TEXT and HTML port. Do +# NOT enable access to this port in TCP_IN. This option requires the perl +# module IO::Socket::SSL at a version level that supports SNI (1.83+). +# Additionally the version of openssl on the server must also support SNI +# +# The option uses existing SSL certificates on the server for each domain to +# maintain a secure connection without browser warnings. It uses SNI to choose +# the correct certificate to use for each client connection +# +# Warning: On some servers the amount of memory used by the HTTPS MESSENGER +# service can become significant depending on various factors associated with +# the use of IO::Socket::SSL including the number of domains and certificates +# served. This is normally only an issue if using MESSENGERV1 +MESSENGER_HTTPS = "8887" + +# This comma separated list are the HTTPS HTML ports that will be redirected +# for the blocked IP address. If you are using per application blocking +# (LF_TRIGGER) then only the relevant block port will be redirected to the +# messenger port +# +# Recommended setting "443" plus any end-user control panel SSL ports. So, for +# cPanel: "443,2083,2096" +MESSENGER_HTTPS_IN = "443" + +# Set this to the port that will receive the HTML message. You should configure +# this port to be >1023 and different from the TEXT port. Do NOT enable access +# to this port in TCP_IN +MESSENGER_HTML = "8888" + +# This comma separated list are the HTML ports that will be redirected for the +# blocked IP address. If you are using per application blocking (LF_TRIGGER) +# then only the relevant block port will be redirected to the messenger port +MESSENGER_HTML_IN = "80" + +# Set this to the port that will receive the TEXT message. You should configure +# this port to be >1023 and different from the HTML port. Do NOT enable access +# to this port in TCP_IN +MESSENGER_TEXT = "8889" + +# This comma separated list are the TEXT ports that will be redirected for the +# blocked IP address. If you are using per application blocking (LF_TRIGGER) +# then only the relevant block port will be redirected to the messenger port +MESSENGER_TEXT_IN = "21" + +# These settings limit the rate at which connections can be made to the +# messenger service servers. Its intention is to provide protection from +# attacks or excessive connections to the servers. If the rate is exceeded then +# iptables will revert for the duration to the normal blocking activity +# +# See the iptables man page for the correct --limit rate syntax +MESSENGER_RATE = "100/s" +MESSENGER_BURST = "150" + +# MESSENGERV1 only: +#------------------------------------------------------------------------------ +# This is the maximum concurrent connections allowed to each service server +# +# Note: This number should be increased to cater for the number of local images +# served by this page, including one for favicon.ico. This is because each +# image displayed counts as an additional connection +MESSENGER_CHILDREN = "20" + +# This options ignores ServerAlias definitions that begin with "mail.". This +# can help reduce memory usage on systems that do not require the use of +# MESSENGER_HTTPS on those subdomains +# +# Set to 0 to include these ServerAlias definitions +MESSENGER_HTTPS_SKIPMAIL = "1" + +# MESSENGERV2 only: +#------------------------------------------------------------------------------ +# MESSENGERV2. This option is available on cPanel servers running Apache v2.4+ +# under EA4. +# +# This uses the Apache http daemon to provide the web server functionality for +# the MESSENGER HTML and HTTPS services. It uses a fraction of the resources +# that the lfd inbuilt service uses and overcomes the memory overhead of using +# the MESSENGER HTTPS service +# +# For more information consult readme.txt before enabling this option +#MESSENGERV2 = "0" + +# MESSENGERV3 only: +#------------------------------------------------------------------------------ +# MESSENGERV3. This option is available on any server running Apache v2.4+, +# Litespeed or Openlitespeed +# +# This uses the web server http daemon to provide the web server functionality +# for the MESSENGER HTML and HTTPS services. It uses a fraction of the +# resources that the lfd inbuilt service uses and overcomes the memory overhead +# of using the MESSENGER HTTPS service +# +# For more information consult readme.txt before enabling this option +MESSENGERV3 = "0" + +# This is the file or directory where the additional web server configuration +# file should be included +MESSENGERV3LOCATION = "/usr/local/lsws/conf/httpd_config.conf" + +# This is the command to restart the web server +MESSENGERV3RESTART = "service lsws restart" + +# This is the command to test the validity of the web server configuration. If +# using Litespeed, set to "" +MESSENGERV3TEST = "" + +# This must be set to the main httpd.conf file for either Apache or Litespeed +MESSENGERV3HTTPS_CONF = "/usr/local/lsws/conf/httpd_config.conf" + +# This can be set to either: +# "apache" - for servers running Apache v2.4+ or Litespeed using Apache +# configuration +# "litespeed" - for Litespeed or Openlitespeed +MESSENGERV3WEBSERVER = "litespeed" + +# On creation, set the MESSENGER_USER public_html directory permissions to +# Note: If you precreate this directory the following setting will be ignored +MESSENGERV3PERMS = "711" + +# On creation, set the MESSENGER_USER public_html directory group user to +# Note: If you precreate this directory the following setting will be ignored +MESSENGERV3GROUP = "nobody" + +# This is the web server configuration to allow PHP scripts to run. If left +# empty, the MESSENGER service will try to configure this. If this does not +# work, this should be set as an "Include /path/to/csf_php.conf" or similar +# file which must contain appropriate web server configuration to allow PHP +# scripts to run. This line will be included within each MESSENGER VirtualHost +# container. This will replace the [MESSENGERV3PHPHANDLER] line from the csf +# webserver template files +MESSENGERV3PHPHANDLER = "" + +# RECAPTCHA: +#------------------------------------------------------------------------------ +# The RECAPTCHA options provide a way for end-users that have blocked +# themselves in the firewall to unblock themselves. +# +# A valid Google ReCAPTCHA (v2) key set is required for this feature from: +# https://www.google.com/recaptcha/intro/index.html +# +# When configuring a new reCAPTCHA API key set you must ensure that the option +# for "Domain Name Validation" is unticked so that the same reCAPTCHA can be +# used for all domains hosted on the server. lfd then checks that the hostname +# of the request resolves to an IP on this server +# +# This feature requires the installation of the LWP::UserAgent perl module (see +# option URLGET for more details) +# +# The template used for this feature is /etc/csf/messenger/index.recaptcha.html +# +# Note: An unblock will fail if the end-users IP is located in a netblock, +# blocklist or CC_* deny entry +RECAPTCHA_SITEKEY = "" +RECAPTCHA_SECRET = "" + +# Send an email when an IP address successfully attempts to unblock themselves. +# This does not necessarily mean the IP was unblocked, only that the +# post-recaptcha unblock request was attempted +# +# Set to "0" to disable +RECAPTCHA_ALERT = "1" + +# If the server uses NAT then resolving the hostname to hosted IPs will likely +# not succeed. In that case, the external IP addresses must be listed as comma +# separated list here +RECAPTCHA_NAT = "" + +############################################################################### +# SECTION:lfd Clustering +############################################################################### +# lfd Clustering. This allows the configuration of an lfd cluster environment +# where a group of servers can share blocks and configuration option changes. +# Included are CLI and UI options to send requests to the cluster. +# +# See the readme.txt file for more information and details on setup and +# security risks. +# +# Set this to a comma separated list of cluster member IP addresses to send +# requests to. Alternatively, it can be set to the full path of a file that +# will read in one IP per line, e.g.: +# "/etc/csf/cluster_sendto.txt" +CLUSTER_SENDTO = "" + +# Set this to a comma separated list of cluster member IP addresses to receive +# requests from. Alternatively, it can be set to the full path of a file that +# will read in one IP per line, e.g.: +# "/etc/csf/cluster_recvfrom.txt" +CLUSTER_RECVFROM = "" + +# IP address of the master node in the cluster allowed to send CLUSTER_CONFIG +# changes +CLUSTER_MASTER = "" + +# If this is a NAT server, set this to the public IP address of this server +CLUSTER_NAT = "" + +# If a cluster member should send requests on an IP other than the default IP, +# set it here +CLUSTER_LOCALADDR = "" + +# Cluster communication port (must be the same on all member servers). There +# is no need to open this port in the firewall as csf will automatically add +# in and out bound rules to allow communication between cluster members +CLUSTER_PORT = "7777" + +# This is a secret key used to encrypt cluster communications using the +# Blowfish algorithm. It should be between 8 and 56 characters long, +# preferably > 20 random characters +# 56 chars: 01234567890123456789012345678901234567890123456789012345 +CLUSTER_KEY = "" + +# Automatically send lfd blocks to all members of CLUSTER_SENDTO. Those +# servers must have this servers IP address listed in their CLUSTER_RECVFROM +# +# Set to 0 to disable this feature +CLUSTER_BLOCK = "1" + +# This option allows the enabling and disabling of the Cluster configuration +# changing options --cconfig, --cconfigr, --cfile, --ccfile sent from the +# CLUSTER_MASTER server +# +# Set this option to 1 to allow Cluster configurations to be received +CLUSTER_CONFIG = "0" + +# Maximum number of child processes to listen on. High blocking rates or large +# clusters may need to increase this +CLUSTER_CHILDREN = "10" + +############################################################################### +# SECTION:Port Knocking +############################################################################### +# Port Knocking. This feature allows port knocking to be enabled on multiple +# ports with a variable number of knocked ports and a timeout. There must be a +# minimum of 3 ports to knock for an entry to be valid +# +# See the following for information regarding Port Knocking: +# http://www.portknocking.org/ +# +# This feature does not work on servers that do not have the iptables module +# ipt_recent loaded. Typically, this will be with MONOLITHIC kernels. VPS +# server admins should check with their VPS host provider that the iptables +# module is included +# +# For further information and syntax refer to the Port Knocking section of the +# csf readme.txt +# +# Note: Run /etc/csf/csftest.pl to check whether this option will function on +# this server +# +# openport;protocol;timeout;kport1;kport2;kport3[...;kportN],... +# e.g.: 22;TCP;20;100;200;300;400 +PORTKNOCKING = "" + +# Enable PORTKNOCKING logging by iptables +PORTKNOCKING_LOG = "1" + +# Send an email alert if the PORTKNOCKING port is opened. PORTKNOCKING_LOG must +# also be enabled to use this option +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +PORTKNOCKING_ALERT = "0" + +############################################################################### +# SECTION:Log Scanner +############################################################################### +# Log Scanner. This feature will send out an email summary of the log lines of +# each log listed in /etc/csf/csf.logfiles. All lines will be reported unless +# they match a regular expression in /etc/csf/csf.logignore +# +# File globbing is supported for logs listed in /etc/csf/csf.logfiles. However, +# be aware that the more files lfd has to track, the greater the performance +# hit. Note: File globs are only evaluated when lfd is started +# +# Note: lfd builds the report continuously from lines logged after lfd has +# started, so any lines logged when lfd is not running will not be reported +# (e.g. during reboot). If lfd is restarted, then the report will include any +# lines logged during the previous lfd logging period that weren't reported +# +# 1 to enable, 0 to disable +LOGSCANNER = "0" + +# This is the interval each report will be sent based on the logalert.txt +# template +# +# The interval can be set to: +# "hourly" - sent on the hour +# "daily" - sent at midnight (00:00) +# "manual" - sent whenever "csf --logrun" is run. This allows for scheduling +# via cron job +LOGSCANNER_INTERVAL = "hourly" + +# Report Style +# 1 = Separate chronological log lines per log file +# 2 = Simply chronological log of all lines +LOGSCANNER_STYLE = "1" + +# Send the report email even if no log lines reported +# 1 to enable, 0 to disable +LOGSCANNER_EMPTY = "1" + +# Maximum number of lines in the report before it is truncated. This is to +# prevent log lines flooding resulting in an excessively large report. This +# might need to be increased if you choose a daily report +LOGSCANNER_LINES = "5000" + +############################################################################### +# SECTION:Statistics Settings +############################################################################### +# Statistics +# +# Some of the Statistics output requires the gd graphics library and the +# GD::Graph perl module with all dependent modules to be installed for the UI +# for them to be displayed +# +# This option enabled statistical data gathering +ST_ENABLE = "1" + +# This option determines how many iptables log lines to store for reports +ST_IPTABLES = "100" + +# This option indicates whether rDNS and CC lookups are performed at the time +# the log line is recorded (this is not performed when viewing the reports) +# +# Warning: If DROP_IP_LOGGING is enabled and there are frequent iptables hits, +# then enabling this setting could cause serious performance problems +ST_LOOKUP = "0" + +# This option will gather basic system statstics. Through the UI it displays +# various graphs for disk, cpu, memory, network, etc usage over 4 intervals: +# . Hourly (per minute) +# . 24 hours (per minute) +# . 7 days (per minute averaged over an hour) +# . 30 days (per minute averaged over an hour) - user definable +# The data is stored in /var/lib/csf/stats/system and the option requires the +# perl GD::Graph module +# +# Note: Disk graphs do not show on Virtuozzo/OpenVZ servers as the kernel on +# those systems do not store the required information in /proc/diskstats +# On new installations or when enabling this option it will take time for these +# graphs to be populated +ST_SYSTEM = "0" + +# Set the maximum days to collect statistics for. The default is 30 days, the +# more data that is collected the longer it will take for each of the graphs to +# be generated +ST_SYSTEM_MAXDAYS = "30" + +# If ST_SYSTEM is enabled, then these options can collect MySQL statistical +# data. To use this option the server must have the perl modules DBI and +# DBD::mysql installed. +# +# Set this option to "0" to disable MySQL data collection +ST_MYSQL = "0" + +# The following options are for authentication for MySQL data collection. If +# the password is left blank and the user set to "root" then the procedure will +# look for authentication data in /root/.my.cnf. Otherwise, you will need to +# provide a MySQL username and password to collect the data. Any MySQL user +# account can be used +ST_MYSQL_USER = "root" +ST_MYSQL_PASS = "" +ST_MYSQL_HOST = "localhost" + +# If ST_SYSTEM is enabled, then this option can collect Apache statistical data +# The value for PT_APACHESTATUS must be correctly set +ST_APACHE = "0" + +# The following options measure disk write performance using dd (location set +# via the DD setting). It creates a 64MB file called /var/lib/dd_write_test and +# the statistics will plot the MB/s response time of the disk. As this is an IO +# intensive operation, it may not be prudent to run this test too often, so by +# default it is only run every 5 minutes and the result duplicated for each +# intervening minute for the statistics +# +# This is not necessrily a good measure of disk performance, primarily because +# the measurements are for relatively small amounts of data over a small amount +# of time. To properly test disk performance there are a variety of tools +# available that should be run for extended periods of time to obtain an +# accurate measurement. This metric is provided to give an idea of how the disk +# is performing over time +# +# Note: There is a 15 second timeout performing the check +# +# Set to 0 to disable, 1 to enable +ST_DISKW = "0" + +# The number of minutes that elapse between tests. Default is 5, minimum is 1. +ST_DISKW_FREQ = "5" + +# This is the command line passed to dd. If you are familiar with dd, or wish +# to move the output file (of) to a different disk, then you can alter this +# command. Take great care when making any changes to this command as it is +# very easy to overwrite a disk using dd if you make a mistake +ST_DISKW_DD = "if=/dev/zero of=/var/lib/csf/dd_test bs=1MB count=64 conv=fdatasync" + +############################################################################### +# SECTION:Docker Settings +############################################################################### +# This section provides the configuration of iptables rules to allow Docker +# containers to communicate through the host. If the generated rules do not +# work with your setup you will have to use a /etc/csf/csfpost.sh file and add +# your own iptables configuration instead +# +# 1 to enable, 0 to disable +DOCKER = "0" + +# The network device on the host +DOCKER_DEVICE = "docker0" + +# Docker container IPv4 range +DOCKER_NETWORK4 = "172.17.0.0/16" + +# Docker container IPv6 range. IPV6 must be enabled and the IPv6 nat table +# available (see IPv6 section). Leave blank to disable +DOCKER_NETWORK6 = "2001:db8:1::/64" + +############################################################################### +# SECTION:OS Specific Settings +############################################################################### +# Binary locations +IPTABLES = "/sbin/iptables" +IPTABLES_SAVE = "/sbin/iptables-save" +IPTABLES_RESTORE = "/sbin/iptables-restore" +IP6TABLES = "/sbin/ip6tables" +IP6TABLES_SAVE = "/sbin/ip6tables-save" +IP6TABLES_RESTORE = "/sbin/ip6tables-restore" +MODPROBE = "/sbin/modprobe" +IFCONFIG = "/sbin/ifconfig" +SENDMAIL = "/usr/sbin/sendmail" +PS = "/bin/ps" +VMSTAT = "/usr/bin/vmstat" +NETSTAT = "/bin/netstat" +LS = "/bin/ls" +MD5SUM = "/usr/bin/md5sum" +TAR = "/bin/tar" +CHATTR = "/usr/bin/chattr" +UNZIP = "/usr/bin/unzip" +GUNZIP = "/bin/gunzip" +DD = "/bin/dd" +TAIL = "/usr/bin/tail" +GREP = "/bin/grep" +ZGREP = "/usr/bin/zgrep" +IPSET = "/usr/sbin/ipset" +SYSTEMCTL = "/usr/bin/systemctl" +HOST = "/usr/bin/host" +IP = "/sbin/ip" +CURL = "/usr/bin/curl" +WGET = "/usr/bin/wget" + +# Log file locations +# +# File globbing is allowed for the following logs. However, be aware that the +# more files lfd has to track, the greater the performance hit +# +# Note: File globs are only evaluated when lfd is started +# +HTACCESS_LOG = "/var/log/httpd/error_log" +MODSEC_LOG = "/var/log/httpd/error_log" +SSHD_LOG = "/var/log/secure" +SU_LOG = "/var/log/secure" +SUDO_LOG = "/var/log/secure" +FTPD_LOG = "/var/log/messages" +SMTPAUTH_LOG = "/var/log/secure" +POP3D_LOG = "/var/log/maillog" +IMAPD_LOG = "/var/log/maillog" +IPTABLES_LOG = "/var/log/messages" +SUHOSIN_LOG = "/var/log/messages" +BIND_LOG = "/var/log/messages" +SYSLOG_LOG = "/var/log/messages" +WEBMIN_LOG = "/var/log/secure" + +CUSTOM1_LOG = "/var/log/customlog" +CUSTOM2_LOG = "/var/log/customlog" +CUSTOM3_LOG = "/var/log/customlog" +CUSTOM4_LOG = "/var/log/customlog" +CUSTOM5_LOG = "/var/log/customlog" +CUSTOM6_LOG = "/var/log/customlog" +CUSTOM7_LOG = "/var/log/customlog" +CUSTOM8_LOG = "/var/log/customlog" +CUSTOM9_LOG = "/var/log/customlog" + +# The following are comma separated lists used if LF_SELECT is enabled, +# otherwise they are not used. They are derived from the application returned +# from a regex match in /usr/local/csf/bin/regex.pm +# +# All ports default to tcp blocks. To specify udp or tcp use the format: +# port;protocol,port;protocol,... For example, "53;udp,53;tcp" +PORTS_pop3d = "110,995" +PORTS_imapd = "143,993" +PORTS_htpasswd = "80,443" +PORTS_mod_security = "80,443" +PORTS_mod_qos = "80,443" +PORTS_symlink = "80,443" +PORTS_suhosin = "80,443" +PORTS_cxs = "80,443" +PORTS_bind = "53;udp,53;tcp" +PORTS_ftpd = "20,21" +PORTS_webmin = "10000" +PORTS_smtpauth = "25,465,587" +PORTS_eximsyntax = "25,465,587" +# This list is replaced, if present, by "Port" definitions in +# /etc/ssh/sshd_config +PORTS_sshd = "22" + +# This configuration is for use with generic Linux servers, do not change the +# following setting: +GENERIC = "1" +CYBERPANEL = "1" + +# For internal use only. You should not enable this option as it could cause +# instability in csf and lfd +DEBUG = "0" +############################################################################### diff --git a/csf/csf.cyberpanel.ignore b/csf/csf.cyberpanel.ignore new file mode 100644 index 0000000..bf3fb2a --- /dev/null +++ b/csf/csf.cyberpanel.ignore @@ -0,0 +1,25 @@ +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +# The following IP addresses will be ignored by all lfd checks +# One IP address per line +# CIDR addressing allowed with a quaded IP (e.g. 192.168.254.0/24) +# Only list IP addresses, not domain names (they will be ignored) +# + +127.0.0.1 diff --git a/csf/csf.cyberpanel.pignore b/csf/csf.cyberpanel.pignore new file mode 100644 index 0000000..2b56d46 --- /dev/null +++ b/csf/csf.cyberpanel.pignore @@ -0,0 +1,108 @@ +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +# The following is a list of executables (exe) command lines (cmd) and +# usernames (user) that lfd process tracking will ignore. +# +# You must use the following format: +# +# exe:/full/path/to/file +# user:username +# cmd:command line +# +# Or, perl regular expression matching (regex): +# +# pexe:/full/path/to/file as a perl regex[*] +# puser:username as a perl regex[*] +# pcmd:command line as a perl regex[*] +# +# [*]You must remember to escape characters correctly when using regex's, e.g.: +# pexe:/home/.*/public_html/cgi-bin/script\.cgi +# puser:bob\d.* +# pcmd:/home/.*/command\s\to\smatch\s\.pl\s.* +# +# It is strongly recommended that you use command line ignores very carefully +# as any process can change what is reported to the OS. +# +# For more information see readme.txt + +exe:/bin/dbus-daemon +exe:/sbin/ntpd +exe:/usr/bin/dbus-daemon +exe:/usr/bin/lsmd +exe:/usr/lib/courier-imap/bin/imapd +exe:/usr/lib/courier-imap/bin/pop3d +exe:/usr/lib/polkit-1/polkitd +exe:/usr/libexec/dovecot/imap +exe:/usr/libexec/mysqld +exe:/usr/local/apache/bin/httpd +exe:/usr/sbin/chronyd +exe:/usr/sbin/exim +exe:/usr/sbin/exim4 +exe:/usr/sbin/named +exe:/usr/sbin/nscd +exe:/usr/sbin/ntpd +exe:/usr/sbin/ntpd +exe:/usr/sbin/proftpd +exe:/usr/sbin/pure-ftpd +exe:/usr/sbin/sshd +exe:/usr/sbin/apache2 +exe:/usr/sbin/mysqld +exe:/lib/systemd/systemd-timesyncd +exe:/sbin/rngd +exe:/usr/bin/dbus-broker-launch +exe:/usr/bin/dbus-broker + +# CyberPanel: +exe:/usr/sbin/pdns_server +exe:/usr/sbin/opendkim +exe:/usr/bin/redis-server +exe:/usr/sbin/pure-ftpd-mysql +exe:/usr/libexec/postfix/qmgr +exe:/usr/libexec/postfix/pickup +exe:/usr/libexec/postfix/tlsmgr +exe:/usr/libexec/postfix/master +exe:/usr/lib/postfix/sbin/tlsmgr +exe:/usr/lib/postfix/sbin/master +exe:/usr/lib/postfix/sbin/qmgr +exe:/usr/lib/postfix/sbin/pickup +exe:/usr/sbin/dovecot +exe:/usr/lib/dovecot/imap-login +exe:/usr/libexec/dovecot/anvil +exe:/usr/libexec/dovecot/auth +exe:/usr/libexec/dovecot/dict +exe:/usr/libexec/dovecot/imap +exe:/usr/libexec/dovecot/imap-login +exe:/usr/libexec/dovecot/lmtp +exe:/usr/libexec/dovecot/pop3 +exe:/usr/libexec/dovecot/pop3-login +exe:/usr/libexec/dovecot/quota-status +exe:/usr/libexec/dovecot/stats +exe:/usr/lib/dovecot/anvil +exe:/usr/lib/dovecot/auth +exe:/usr/lib/dovecot/dict +exe:/usr/lib/dovecot/imap +exe:/usr/lib/dovecot/imap-login +exe:/usr/lib/dovecot/lmtp +exe:/usr/lib/dovecot/pop3 +exe:/usr/lib/dovecot/pop3-login +exe:/usr/lib/dovecot/quota-status +exe:/usr/lib/dovecot/stats +exe:/usr/local/lsws/bin/openlitespeed +exe:/usr/local/CyberCP/bin/lswsgi +exe:/usr/sbin/mariadbd diff --git a/csf/csf.deny b/csf/csf.deny new file mode 100644 index 0000000..ac2b688 --- /dev/null +++ b/csf/csf.deny @@ -0,0 +1,31 @@ +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +# The following IP addresses will be blocked in iptables +# One IP address per line +# CIDR addressing allowed with a quaded IP (e.g. 192.168.254.0/24) +# Only list IP addresses, not domain names (they will be ignored) +# +# Note: If you add the text "do not delete" to the comments of an entry then +# DENY_IP_LIMIT will ignore those entries and not remove them +# +# Advanced port+ip filtering allowed with the following format +# tcp/udp|in/out|s/d=port,port,...|s/d=ip +# +# See readme.txt for more information regarding advanced port filtering +# diff --git a/csf/csf.directadmin.allow b/csf/csf.directadmin.allow new file mode 100644 index 0000000..19ec008 --- /dev/null +++ b/csf/csf.directadmin.allow @@ -0,0 +1,30 @@ +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +# The following IP addresses will be allowed through iptables. +# One IP address per line. +# CIDR addressing allowed with a quaded IP (e.g. 192.168.254.0/24). +# Only list IP addresses, not domain names (they will be ignored) +# +# Advanced port+ip filtering allowed with the following format +# tcp/udp|in/out|s/d=port|s/d=ip +# See readme.txt for more information +# +# Note: IP addressess listed in this file will NOT be ignored by lfd, so they +# can still be blocked. If you do not want lfd to block an IP address you must +# add it to csf.ignore diff --git a/csf/csf.directadmin.conf b/csf/csf.directadmin.conf new file mode 100644 index 0000000..97ae202 --- /dev/null +++ b/csf/csf.directadmin.conf @@ -0,0 +1,2739 @@ +############################################################################### +# SECTION:Initial Settings +############################################################################### +# Testing flag - enables a CRON job that clears iptables incase of +# configuration problems when you start csf. This should be enabled until you +# are sure that the firewall works - i.e. incase you get locked out of your +# server! Then do remember to set it to 0 and restart csf when you're sure +# everything is OK. Stopping csf will remove the line from /etc/crontab +# +# lfd will not start while this is enabled +TESTING = "1" + +# The interval for the crontab in minutes. Since this uses the system clock the +# CRON job will run at the interval past the hour and not from when you issue +# the start command. Therefore an interval of 5 minutes means the firewall +# will be cleared in 0-5 minutes from the firewall start +TESTING_INTERVAL = "5" + +# SECURITY WARNING +# ================ +# +# Unfortunately, syslog and rsyslog allow end-users to log messages to some +# system logs via the same unix socket that other local services use. This +# means that any log line shown in these system logs that syslog or rsyslog +# maintain can be spoofed (they are exactly the same as real log lines). +# +# Since some of the features of lfd rely on such log lines, spoofed messages +# can cause false-positive matches which can lead to confusion at best, or +# blocking of any innocent IP address or making the server inaccessible at +# worst. +# +# Any option that relies on the log entries in the files listed in +# /etc/syslog.conf and /etc/rsyslog.conf should therefore be considered +# vulnerable to exploitation by end-users and scripts run by end-users. +# +# NOTE: Not all log files are affected as they may not use syslog/rsyslog +# +# The option RESTRICT_SYSLOG disables all these features that rely on affected +# logs. These options are: +# LF_SSHD LF_FTPD LF_IMAPD LF_POP3D LF_BIND LF_SUHOSIN LF_SSH_EMAIL_ALERT +# LF_SU_EMAIL_ALERT LF_CONSOLE_EMAIL_ALERT LF_DISTATTACK LF_DISTFTP +# LT_POP3D LT_IMAPD PS_INTERVAL UID_INTERVAL WEBMIN_LOG LF_WEBMIN_EMAIL_ALERT +# PORTKNOCKING_ALERT LF_SUDO_EMAIL_ALERT +# +# This list of options use the logs but are not disabled by RESTRICT_SYSLOG: +# ST_ENABLE SYSLOG_CHECK LOGSCANNER CUSTOM*_LOG +# +# The following options are still enabled by default on new installations so +# that, on balance, csf/lfd still provides expected levels of security: +# LF_SSHD LF_FTPD LF_POP3D LF_IMAPD LF_SSH_EMAIL_ALERT LF_SU_EMAIL_ALERT +# +# If you set RESTRICT_SYSLOG to "0" or "2" and enable any of the options listed +# above, it should be done with the knowledge that any of the those options +# that are enabled could be triggered by spoofed log lines and lead to the +# server being inaccessible in the worst case. If you do not want to take that +# risk you should set RESTRICT_SYSLOG to "1" and those features will not work +# but you will not be protected from the exploits that they normally help block +# +# The recommended setting for RESTRICT_SYSLOG is "3" to restrict who can access +# the syslog/rsyslog unix socket. +# +# For further advice on how to help mitigate these issues, see +# /etc/csf/readme.txt +# +# 0 = Allow those options listed above to be used and configured +# 1 = Disable all the options listed above and prevent them from being used +# 2 = Disable only alerts about this feature and do nothing else +# 3 = Restrict syslog/rsyslog access to RESTRICT_SYSLOG_GROUP ** RECOMMENDED ** +RESTRICT_SYSLOG = "0" + +# The following setting is used if RESTRICT_SYSLOG is set to 3. It restricts +# write access to the syslog/rsyslog unix socket(s). The group must not already +# exists in /etc/group before setting RESTRICT_SYSLOG to 3, so set the option +# to a unique name for the server +# +# You can add users to this group by changing /etc/csf/csf.syslogusers and then +# restarting lfd afterwards. This will create the system group and add the +# users from csf.syslogusers if they exist to that group and will change the +# permissions on the syslog/rsyslog unix socket(s). The socket(s) will be +# monitored and the permissions re-applied should syslog/rsyslog be restarted +# +# Using this option will prevent some legitimate logging, e.g. end-user cron +# job logs +# +# If you want to revert RESTRICT_SYSLOG to another option and disable this +# feature, change the setting of RESTRICT_SYSLOG and then restart lfd and then +# syslog/rsyslog and the unix sockets will be reset +RESTRICT_SYSLOG_GROUP = "mysyslog" + +# This options restricts the ability to modify settings within this file from +# the csf UI. Should the parent control panel be compromised, these restricted +# options could be used to further compromise the server. For this reason we +# recommend leaving this option set to at least "1" and if any of the +# restricted items need to be changed, they are done so from the root shell +# +# 0 = Unrestricted UI +# 1 = Restricted UI +# 2 = Disabled UI +RESTRICT_UI = "1" + +# Enabling auto updates creates a cron job called /etc/cron.d/csf_update which +# runs once per day to see if there is an update to csf+lfd and upgrades if +# available and restarts csf and lfd +# +# You should check for new version announcements at http://blog.configserver.com +AUTO_UPDATES = "1" + +############################################################################### +# SECTION:IPv4 Port Settings +############################################################################### +# Lists of ports in the following comma separated lists can be added using a +# colon (e.g. 30000:35000). + +# Some kernel/iptables setups do not perform stateful connection tracking +# correctly (typically some virtual servers or custom compiled kernels), so a +# SPI firewall will not function correctly. If this happens, LF_SPI can be set +# to 0 to reconfigure csf as a static firewall. +# +# As connection tracking will not be configured, applications that rely on it +# will not function unless all outgoing ports are opened. Therefore, all +# outgoing connections will be allowed once all other tests have completed. So +# TCP_OUT, UDP_OUT and ICMP_OUT will not have any affect. +# +# If you allow incoming DNS lookups you may need to use the following +# directive in the options{} section of your named.conf: +# +# query-source port 53; +# +# This will force incoming DNS traffic only through port 53 +# +# Disabling this option will break firewall functionality that relies on +# stateful packet inspection (e.g. DNAT, PACKET_FILTER) and makes the firewall +# less secure +# +# This option should be set to "1" in all other circumstances +LF_SPI = "1" + +# Allow incoming TCP ports +TCP_IN = "20,21,22,25,53,853,80,110,143,443,465,587,993,995,2222" + +# Allow outgoing TCP ports +TCP_OUT = "20,21,22,25,53,853,80,110,113,443,587,993,995,2222" + +# Allow incoming UDP ports +UDP_IN = "20,21,53,853,80,443" + +# Allow outgoing UDP ports +# To allow outgoing traceroute add 33434:33523 to this list +UDP_OUT = "20,21,53,853,113,123" + +# Allow incoming PING. Disabling PING will likely break external uptime +# monitoring +ICMP_IN = "1" + +# Set the per IP address incoming ICMP packet rate for PING requests. This +# ratelimits PING requests which if exceeded results in silently rejected +# packets. Disable or increase this value if you are seeing PING drops that you +# do not want +# +# To disable rate limiting set to "0", otherwise set according to the iptables +# documentation for the limit module. For example, "1/s" will limit to one +# packet per second +ICMP_IN_RATE = "1/s" + +# Allow outgoing PING +# +# Unless there is a specific reason, this option should NOT be disabled as it +# could break OS functionality +ICMP_OUT = "1" + +# Set the per IP address outgoing ICMP packet rate for PING requests. This +# ratelimits PING requests which if exceeded results in silently rejected +# packets. Disable or increase this value if you are seeing PING drops that you +# do not want +# +# Unless there is a specific reason, this option should NOT be enabled as it +# could break OS functionality +# +# To disable rate limiting set to "0", otherwise set according to the iptables +# documentation for the limit module. For example, "1/s" will limit to one +# packet per second +ICMP_OUT_RATE = "0" + +# For those with PCI Compliance tools that state that ICMP timestamps (type 13) +# should be dropped, you can enable the following option. Otherwise, there +# appears to be little evidence that it has anything to do with a security risk +# and can impact network performance, so should be left disabled by everyone +# else +ICMP_TIMESTAMPDROP = "0" + +############################################################################### +# SECTION:IPv6 Port Settings +############################################################################### +# IPv6: (Requires ip6tables) +# +# Pre v2.6.20 kernels do not perform stateful connection tracking, so a static +# firewall is configured as a fallback instead if IPV6_SPI is set to 0 below +# +# Supported: +# Temporary ACCEPT/DENY, GLOBAL_DENY, GLOBAL_ALLOW, SMTP_BLOCK, LF_PERMBLOCK, +# PACKET_FILTER, Advanced Allow/Deny Filters, RELAY_*, CLUSTER_*, CC6_LOOKUPS, +# SYNFLOOD, LF_NETBLOCK +# +# Supported if CC6_LOOKUPS and CC_LOOKUPS are enabled +# CC_DENY, CC_ALLOW, CC_ALLOW_FILTER, CC_IGNORE, CC_ALLOW_PORTS, CC_DENY_PORTS, +# CC_ALLOW_SMTPAUTH +# +# Supported if ip6tables >= 1.4.3: +# PORTFLOOD, CONNLIMIT +# +# Supported if ip6tables >= 1.4.17 and perl module IO::Socket::INET6 is +# installed: +# MESSENGER DOCKER SMTP_REDIRECT +# +# Not supported: +# ICMP_IN, ICMP_OUT +# +IPV6 = "0" + +# IPv6 uses icmpv6 packets very heavily. By default, csf will allow all icmpv6 +# traffic in the INPUT and OUTPUT chains. However, this could increase the risk +# of icmpv6 attacks. To restrict incoming icmpv6, set to "1" but may break some +# connection types +IPV6_ICMP_STRICT = "0" + +# Pre v2.6.20 kernel must set this option to "0" as no working state module is +# present, so a static firewall is configured as a fallback +# +# A workaround has been added for CentOS/RedHat v5 and custom kernels that do +# not support IPv6 connection tracking by opening ephemeral port range +# 32768:61000. This is only applied if IPV6_SPI is not enabled. This is the +# same workaround implemented by RedHat in the sample default IPv6 rules +# +# As connection tracking will not be configured, applications that rely on it +# will not function unless all outgoing ports are opened. Therefore, all +# outgoing connections will be allowed once all other tests have completed. So +# TCP6_OUT, UDP6_OUT and ICMP6_OUT will not have any affect. +# +# If you allow incoming ipv6 DNS lookups you may need to use the following +# directive in the options{} section of your named.conf: +# +# query-source-v6 port 53; +# +# This will force ipv6 incoming DNS traffic only through port 53 +# +# These changes are not necessary if the SPI firewall is used +IPV6_SPI = "1" + +# Allow incoming IPv6 TCP ports +TCP6_IN = "20,21,22,25,53,853,80,110,143,443,465,587,993,995,2222" + +# Allow outgoing IPv6 TCP ports +TCP6_OUT = "20,21,22,25,53,853,80,110,113,443,587,993,995,2222" + +# Allow incoming IPv6 UDP ports +UDP6_IN = "20,21,53,853,80,443" + +# Allow outgoing IPv6 UDP ports +# To allow outgoing traceroute add 33434:33523 to this list +UDP6_OUT = "20,21,53,853,113,123" + +############################################################################### +# SECTION:General Settings +############################################################################### +# By default, csf will auto-configure iptables to filter all traffic except on +# the loopback device. If you only want iptables rules applied to a specific +# NIC, then list it here (e.g. eth1, or eth+) +ETH_DEVICE = "" + +# By adding a device to this option, ip6tables can be configured only on the +# specified device. Otherwise, ETH_DEVICE and then the default setting will be +# used +ETH6_DEVICE = "" + +# If you don't want iptables rules applied to specific NICs, then list them in +# a comma separated list (e.g "eth1,eth2") +ETH_DEVICE_SKIP = "" + +# This option should be enabled unless the kernel does not support the +# "conntrack" module +# +# To use the deprecated iptables "state" module, change this to 0 +USE_CONNTRACK = "1" + +# Enable ftp helper via the iptables CT target on supporting kernels (v2.6.34+) +# Enable ftp helper via the iptables CT target on supporting kernels (v2.6.34+) +# instead of the current method via /proc/sys/net/netfilter/nf_conntrack_helper +# This will also remove the RELATED target from the global state iptables rule +# +# This is not needed (and will be ignored) if LF_SPI/IPV6_SPI is disabled or +# the raw tables do not exist. The USE_CONNTRACK option should be enabled +# +# To enable this option, set it to your FTP server listening port number +# (normally 21), do NOT set it to "1" +USE_FTPHELPER = "0" + +# Check whether syslog is running. Many of the lfd checks require syslog to be +# running correctly. This test will send a coded message to syslog every +# SYSLOG_CHECK seconds. lfd will check SYSLOG_LOG log lines for the coded +# message. If it fails to do so within SYSLOG_CHECK seconds an alert using +# syslogalert.txt is sent +# +# A value of between 300 and 3600 seconds is suggested. Set to 0 to disable +SYSLOG_CHECK = "0" + +# Enable this option if you want lfd to ignore (i.e. don't block) IP addresses +# listed in csf.allow in addition to csf.ignore (the default). This option +# should be used with caution as it would mean that IP's allowed through the +# firewall from infected PC's could launch attacks on the server that lfd +# would ignore +IGNORE_ALLOW = "0" + +# Enable the following option if you want to apply strict iptables rules to DNS +# traffic (i.e. relying on iptables connection tracking). Enabling this option +# could cause DNS resolution issues both to and from the server but could help +# prevent abuse of the local DNS server +DNS_STRICT = "0" + +# Enable the following option if you want to apply strict iptables rules to DNS +# traffic between the server and the nameservers listed in /etc/resolv.conf +# Enabling this option could cause DNS resolution issues both to and from the +# server but could help prevent abuse of the local DNS server +DNS_STRICT_NS = "0" + +# Limit the number of IP's kept in the /etc/csf/csf.deny file +# +# Care should be taken when increasing this value on servers with low memory +# resources or hard limits (such as Virtuozzo/OpenVZ) as too many rules (in the +# thousands) can sometimes cause network slowdown +# +# The value set here is the maximum number of IPs/CIDRs allowed +# if the limit is reached, the entries will be rotated so that the oldest +# entries (i.e. the ones at the top) will be removed and the latest is added. +# The limit is only checked when using csf -d (which is what lfd also uses) +# Set to 0 to disable limiting +# +# For implementations wishing to set this value significantly higher, we +# recommend using the IPSET option +DENY_IP_LIMIT = "200" + +# Limit the number of IP's kept in the temprary IP ban list. If the limit is +# reached the oldest IP's in the ban list will be removed and allowed +# regardless of the amount of time remaining for the block +# Set to 0 to disable limiting +DENY_TEMP_IP_LIMIT = "100" + +# Enable login failure detection daemon (lfd). If set to 0 none of the +# following settings will have any effect as the daemon won't start. +LF_DAEMON = "1" + +# Check whether csf appears to have been stopped and restart if necessary, +# unless TESTING is enabled above. The check is done every 300 seconds +LF_CSF = "1" + +# This option uses IPTABLES_SAVE, IPTABLES_RESTORE and IP6TABLES_SAVE, +# IP6TABLES_RESTORE in two ways: +# +# 1. On a clean server reboot the entire csf iptables configuration is saved +# and then restored where possible to provide a near instant firewall +# startup[*] +# +# 2. On csf restart or lfd reloading tables, CC_* as well as SPAMHAUS, DSHIELD, +# BOGON, TOR are loaded using this method in a fraction of the time than if +# this setting is disabled +# +# [*]Not supported on all OS platforms +# +# Set to "0" to disable this functionality +FASTSTART = "1" + +# This option allows you to use ipset v6+ for the following csf options: +# CC_* and /etc/csf/csf.blocklist, /etc/csf/csf.allow, /etc/csf/csf.deny, +# GLOBAL_DENY, GLOBAL_ALLOW, DYNDNS, GLOBAL_DYNDNS, MESSENGER +# +# ipset will only be used with the above options when listing IPs and CIDRs. +# Advanced Allow Filters and temporary blocks use traditional iptables +# +# Using ipset moves the onus of ip matching against large lists away from +# iptables rules and to a purpose built and optimised database matching +# utility. It also simplifies the switching in of updated lists +# +# To use this option you must have a fully functioning installation of ipset +# installed either via rpm or source from http://ipset.netfilter.org/ +# +# Note: Using ipset has many advantages, some disadvantages are that you will +# no longer see packet and byte counts against IPs and it makes identifying +# blocked/allowed IPs that little bit harder +# +# Note: If you mainly use IP address only entries in csf.deny, you can increase +# the value of DENY_IP_LIMIT significantly if you wish +# +# Note: It's highly unlikely that ipset will function on Virtuozzo/OpenVZ +# containers even if it has been installed +# +# If you find any problems, please post on forums.configserver.com with full +# details of the issue +LF_IPSET = "0" + +# Versions of iptables greater or equal to v1.4.20 should support the --wait +# option. This forces iptables commands that use the option to wait until a +# lock by any other process using iptables completes, rather than simply +# failing +# +# Enabling this feature will add the --wait option to iptables commands +# +# NOTE: The disadvantage of using this option is that any iptables command that +# uses it will hang until the lock is released. This could cause a cascade of +# hung processes trying to issue iptables commands. To try and avoid this issue +# csf uses a last ditch timeout, WAITLOCK_TIMEOUT in seconds, that will trigger +# a failure if reached +WAITLOCK = "0" +WAITLOCK_TIMEOUT = "300" + +# The following sets the hashsize for ipset sets, which must be a power of 2. +# +# Note: Increasing this value will consume more memory for all sets +# Default: "1024" +LF_IPSET_HASHSIZE = "1024" + +# The following sets the maxelem for ipset sets. +# +# Note: Increasing this value will consume more memory for all sets +# Default: "65536" +LF_IPSET_MAXELEM = "65536" + +# If you enable this option then whenever a CLI request to restart csf is used +# lfd will restart csf instead within LF_PARSE seconds +# +# This feature can be helpful for restarting configurations that cannot use +# FASTSTART +LFDSTART = "0" + +# Enable verbose output of iptables commands +VERBOSE = "1" + +# Drop out of order packets and packets in an INVALID state in iptables +# connection tracking +PACKET_FILTER = "1" + +# Perform reverse DNS lookups on IP addresses. (See also CC_LOOKUPS) +LF_LOOKUPS = "1" + +# Custom styling is possible in the csf UI. See the readme.txt for more +# information under "UI skinning and Mobile View" +# +# This option enables the use of custom styling. If the styling fails to work +# correctly, e.g. custom styling does not take into account a change in the +# standard csf UI, then disabling this option will return the standard UI +STYLE_CUSTOM = "0" + +# This option disables the presence of the Mobile View in the csf UI +STYLE_MOBILE = "1" + +############################################################################### +# SECTION:SMTP Settings +############################################################################### +# Block outgoing SMTP except for root, exim and mailman (forces scripts/users +# to use the exim/sendmail binary instead of sockets access). This replaces the +# protection as WHM > Tweak Settings > SMTP Tweaks +# +# This option uses the iptables ipt_owner/xt_owner module and must be loaded +# for it to work. It may not be available on some VPS platforms +# +# Note: Run /etc/csf/csftest.pl to check whether this option will function on +# this server +SMTP_BLOCK = "0" + +# If SMTP_BLOCK is enabled but you want to allow local connections to port 25 +# on the server (e.g. for webmail or web scripts) then enable this option to +# allow outgoing SMTP connections to the loopback device +SMTP_ALLOWLOCAL = "1" + +# This option redirects outgoing SMTP connections destined for remote servers +# for non-bypass users to the local SMTP server to force local relaying of +# email. Such email may require authentication (SMTP AUTH) +SMTP_REDIRECT = "0" + +# This is a comma separated list of the ports to block. You should list all +# ports that exim is configured to listen on +SMTP_PORTS = "25,465,587" + +# Always allow the following comma separated users and groups to bypass +# SMTP_BLOCK +# +# Note: root (UID:0) is always allowed +SMTP_ALLOWUSER = "" +SMTP_ALLOWGROUP = "mail,mailman" + +# This option will only allow SMTP AUTH to be advertised to the IP addresses +# listed in /etc/csf/csf.smtpauth on EXIM mail servers +# +# The additional option CC_ALLOW_SMTPAUTH can be used with this option to +# additionally restrict access to specific countries +# +# This is to help limit attempts at distributed attacks against SMTP AUTH which +# are difficult to achive since port 25 needs to be open to relay email +# +# The reason why this works is that if EXIM does not advertise SMTP AUTH on a +# connection, then SMTP AUTH will not accept logins, defeating the attacks +# without restricting mail relaying +# +# Note: csf and lfd must be restarted if /etc/csf/csf.smtpauth is modified so +# that the lookup file in /etc/exim.smtpauth is regenerated from the +# information from /etc/csf/csf.smtpauth plus any countries listed in +# CC_ALLOW_SMTPAUTH +# +# NOTE: To make this option work you MUST make the modifications to exim.conf +# as explained in "Exim SMTP AUTH Restriction" section in /etc/csf/readme.txt +# after enabling the option here, otherwise this option will not work +# +# To enable this option, set to 1 and make the exim configuration changes +# To disable this option, set to 0 and undo the exim configuration changes +SMTPAUTH_RESTRICT = "0" + +############################################################################### +# SECTION:Port Flood Settings +############################################################################### +# Enable SYN Flood Protection. This option configures iptables to offer some +# protection from tcp SYN packet DOS attempts. You should set the RATE so that +# false-positives are kept to a minimum otherwise visitors may see connection +# issues (check /var/log/messages for *SYNFLOOD Blocked*). See the iptables +# man page for the correct --limit rate syntax +# +# Note: This option should ONLY be enabled if you know you are under a SYN +# flood attack as it will slow down all new connections from any IP address to +# the server if triggered +SYNFLOOD = "0" +SYNFLOOD_RATE = "100/s" +SYNFLOOD_BURST = "150" + +# Connection Limit Protection. This option configures iptables to offer more +# protection from DOS attacks against specific ports. It can also be used as a +# way to simply limit resource usage by IP address to specific server services. +# This option limits the number of concurrent new connections per IP address +# that can be made to specific ports +# +# This feature does not work on servers that do not have the iptables module +# xt_connlimit loaded. Typically, this will be with MONOLITHIC kernels. VPS +# server admins should check with their VPS host provider that the iptables +# module is included +# +# For further information and syntax refer to the Connection Limit Protection +# section of the csf readme.txt +# +# Note: Run /etc/csf/csftest.pl to check whether this option will function on +# this server +CONNLIMIT = "" + +# Port Flood Protection. This option configures iptables to offer protection +# from DOS attacks against specific ports. This option limits the number of +# new connections per time interval that can be made to specific ports +# +# This feature does not work on servers that do not have the iptables module +# ipt_recent loaded. Typically, this will be with MONOLITHIC kernels. VPS +# server admins should check with their VPS host provider that the iptables +# module is included +# +# For further information and syntax refer to the Port Flood Protection +# section of the csf readme.txt +# +# Note: Run /etc/csf/csftest.pl to check whether this option will function on +# this server +PORTFLOOD = "" + +# Outgoing UDP Flood Protection. This option limits outbound UDP packet floods. +# These typically originate from exploit scripts uploaded through vulnerable +# web scripts. Care should be taken on servers that use services that utilise +# high levels of UDP outbound traffic, such as SNMP, so you may need to alter +# the UDPFLOOD_LIMIT and UDPFLOOD_BURST options to suit your environment +# +# We recommend enabling User ID Tracking (UID_INTERVAL) with this feature +UDPFLOOD = "0" +UDPFLOOD_LIMIT = "100/s" +UDPFLOOD_BURST = "500" + +# This is a list of usernames that should not be rate limited, such as "named" +# to prevent bind traffic from being limited. +# +# Note: root (UID:0) is always allowed +UDPFLOOD_ALLOWUSER = "named" + +############################################################################### +# SECTION:Logging Settings +############################################################################### +# Log lfd messages to SYSLOG in addition to /var/log/lfd.log. You must have the +# perl module Sys::Syslog installed to use this feature +SYSLOG = "0" + +# Drop target for incoming iptables rules. This can be set to either DROP or +# REJECT. REJECT will send back an error packet, DROP will not respond at all. +# REJECT is more polite, however it does provide extra information to a hacker +# and lets them know that a firewall is blocking their attempts. DROP hangs +# their connection, thereby frustrating attempts to port scan the server +DROP = "DROP" + +# Drop target for outgoing iptables rules. This can be set to either DROP or +# REJECT as with DROP, however as such connections are from this server it is +# better to REJECT connections to closed ports rather than to DROP them. This +# helps to immediately free up server resources rather than tying them up until +# a connection times out. It also tells the process making the connection that +# it has immediately failed +# +# It is possible that some monolithic kernels may not support the REJECT +# target. If this is the case, csf checks before using REJECT and falls back to +# using DROP, issuing a warning to set this to DROP instead +DROP_OUT = "REJECT" + +# Enable logging of dropped connections to blocked ports to syslog, usually +# /var/log/messages. This option needs to be enabled to use Port Scan Tracking +DROP_LOGGING = "1" + +# Enable logging of dropped incoming connections from blocked IP addresses +# +# This option will be disabled if you enable Port Scan Tracking (PS_INTERVAL) +DROP_IP_LOGGING = "0" + +# Enable logging of dropped outgoing connections +# +# Note: Only outgoing SYN packets for TCP connections are logged, other +# protocols log all packets +# +# We recommend that you enable this option +DROP_OUT_LOGGING = "1" + +# Together with DROP_OUT_LOGGING enabled, this option logs the UID connecting +# out (where available) which can help track abuse +DROP_UID_LOGGING = "1" + +# Only log incoming reserved port dropped connections (0:1023). This can reduce +# the amount of log noise from dropped connections, but will affect options +# such as Port Scan Tracking (PS_INTERVAL) +DROP_ONLYRES = "0" + +# Commonly blocked ports that you do not want logging as they tend to just fill +# up the log file. These ports are specifically blocked (applied to TCP and UDP +# protocols) for incoming connections +DROP_NOLOG = "23,67,68,111,113,135:139,445,500,513,520" + +# Log packets dropped by the packet filtering option PACKET_FILTER +DROP_PF_LOGGING = "0" + +# Log packets dropped by the Connection Limit Protection option CONNLIMIT. If +# this is enabled and Port Scan Tracking (PS_INTERVAL) is also enabled, IP +# addresses breaking the Connection Limit Protection will be blocked +CONNLIMIT_LOGGING = "0" + +# Enable logging of UDP floods. This should be enabled, especially with User ID +# Tracking enabled +UDPFLOOD_LOGGING = "1" + +# Send an alert if log file flooding is detected which causes lfd to skip log +# lines to prevent lfd from looping. If this alert is sent you should check the +# reported log file for the reason for the flooding +LOGFLOOD_ALERT = "0" + +############################################################################### +# SECTION:Reporting Settings +############################################################################### +# By default, lfd will send alert emails using the relevant alert template to +# the To: address configured within that template. Setting the following +# option will override the configured To: field in all lfd alert emails +# +# Leave this option empty to use the To: field setting in each alert template +LF_ALERT_TO = "" + +# By default, lfd will send alert emails using the relevant alert template from +# the From: address configured within that template. Setting the following +# option will override the configured From: field in all lfd alert emails +# +# Leave this option empty to use the From: field setting in each alert template +LF_ALERT_FROM = "" + +# By default, lfd will send all alerts using the SENDMAIL binary. To send using +# SMTP directly, you can set the following to a relaying SMTP server, e.g. +# "127.0.0.1". Leave this setting blank to use SENDMAIL +LF_ALERT_SMTP = "" + +# Block Reporting. lfd can run an external script when it performs and IP +# address block following for example a login failure. The following setting +# is to the full path of the external script which must be executable. See +# readme.txt for format details +# +# Leave this setting blank to disable +BLOCK_REPORT = "" + +# To also run an external script when a temporary block is unblocked. The +# following setting can be the full path of the external script which must be +# executable. See readme.txt for format details +# +# Leave this setting blank to disable +UNBLOCK_REPORT = "" + +# In addition to the standard lfd email alerts, you can additionally enable the +# sending of X-ARF reports (see http://www.xarf.org/specification.html). Only +# block alert messages will be sent. The reports use our schema at: +# https://download.configserver.com/abuse_login-attack_0.2.json +# +# These reports are in a format accepted by many Netblock owners and should +# help them investigate abuse. This option is not designed to automatically +# forward these reports to the Netblock owners and should be checked for +# false-positive blocks before reporting +# +# If available, the report will also include the abuse contact for the IP from +# the Abusix Contact DB: https://abusix.com/contactdb.html +# +# Note: The following block types are not reported through this feature: +# LF_PERMBLOCK, LF_NETBLOCK, LF_DISTATTACK, LF_DISTFTP, RT_*_ALERT +X_ARF = "0" + +# By default, lfd will send emails from the root forwarder. Setting the +# following option will override this +X_ARF_FROM = "" + +# By default, lfd will send emails to the root forwarder. Setting the following +# option will override this +X_ARF_TO = "" + +# If you want to automatically send reports to the abuse contact where found, +# you can enable the following option +# +# Note: You MUST set X_ARF_FROM to a valid email address for this option to +# work. This is so that the abuse contact can reply to the report +# +# However, you should be aware that without manual checking you could be +# reporting innocent IP addresses, including your own clients, yourself and +# your own servers +# +# Additionally, just because a contact address is found, does not mean that +# there is anyone on the end of it reading, processing or acting on such +# reports and you could conceivably reported for sending spam +# +# We do not recommend enabling this option. Abuse reports should be checked and +# verified before being forwarded to the abuse contact +X_ARF_ABUSE = "0" + +############################################################################### +# SECTION:Temp to Perm/Netblock Settings +############################################################################### +# Temporary to Permanent IP blocking. The following enables this feature to +# permanently block IP addresses that have been temporarily blocked more than +# LF_PERMBLOCK_COUNT times in the last LF_PERMBLOCK_INTERVAL seconds. Set +# LF_PERMBLOCK to "1" to enable this feature +# +# Care needs to be taken when setting LF_PERMBLOCK_INTERVAL as it needs to be +# at least LF_PERMBLOCK_COUNT multiplied by the longest temporary time setting +# (TTL) for blocked IPs, to be effective +# +# Set LF_PERMBLOCK to "0" to disable this feature +LF_PERMBLOCK = "1" +LF_PERMBLOCK_INTERVAL = "86400" +LF_PERMBLOCK_COUNT = "4" +LF_PERMBLOCK_ALERT = "1" + +# Permanently block IPs by network class. The following enables this feature +# to permanently block classes of IP address where individual IP addresses +# within the same class LF_NETBLOCK_CLASS have already been blocked more than +# LF_NETBLOCK_COUNT times in the last LF_NETBLOCK_INTERVAL seconds. Set +# LF_NETBLOCK to "1" to enable this feature +# +# This can be an affective way of blocking DDOS attacks launched from within +# the same network class +# +# Valid settings for LF_NETBLOCK_CLASS are "A", "B" and "C", care and +# consideration is required when blocking network classes A or B +# +# Set LF_NETBLOCK to "0" to disable this feature +LF_NETBLOCK = "0" +LF_NETBLOCK_INTERVAL = "86400" +LF_NETBLOCK_COUNT = "4" +LF_NETBLOCK_CLASS = "C" +LF_NETBLOCK_ALERT = "1" + +# Valid settings for LF_NETBLOCK_IPV6 are "/64", "/56", "/48", "/32" and "/24" +# Great care should be taken with IPV6 netblock ranges due to the large number +# of addresses involved +# +# To disable IPv6 netblocks set to "" +LF_NETBLOCK_IPV6 = "" + +############################################################################### +# SECTION:Global Lists/DYNDNS/Blocklists +############################################################################### +# Safe Chain Update. If enabled, all dynamic update chains (GALLOW*, GDENY*, +# SPAMHAUS, DSHIELD, BOGON, CC_ALLOW, CC_DENY, ALLOWDYN*) will create a new +# chain when updating, and insert it into the relevant LOCALINPUT/LOCALOUTPUT +# chain, then flush and delete the old dynamic chain and rename the new chain. +# +# This prevents a small window of opportunity opening when an update occurs and +# the dynamic chain is flushed for the new rules. +# +# This option should not be enabled on servers with long dynamic chains (e.g. +# CC_DENY/CC_ALLOW lists) and low memory. It should also not be enabled on +# Virtuozzo VPS servers with a restricted numiptent value. This is because each +# chain will effectively be duplicated while the update occurs, doubling the +# number of iptables rules +SAFECHAINUPDATE = "0" + +# If you wish to allow access from dynamic DNS records (for example if your IP +# address changes whenever you connect to the internet but you have a dedicated +# dynamic DNS record from the likes of dyndns.org) then you can list the FQDN +# records in csf.dyndns and then set the following to the number of seconds to +# poll for a change in the IP address. If the IP address has changed iptables +# will be updated. +# +# If the FQDN has multiple A records then all of the IP addresses will be +# processed. If IPV6 is enabled, then all IPv6 AAAA IP address records will +# also be allowed. +# +# A setting of 600 would check for IP updates every 10 minutes. Set the value +# to 0 to disable the feature +DYNDNS = "0" + +# To always ignore DYNDNS IP addresses in lfd blocking, set the following +# option to 1 +DYNDNS_IGNORE = "0" + +# The follow Global options allow you to specify a URL where csf can grab a +# centralised copy of an IP allow or deny block list of your own. You need to +# specify the full URL in the following options, i.e.: +# http://www.somelocation.com/allow.txt +# +# The actual retrieval of these IP's is controlled by lfd, so you need to set +# LF_GLOBAL to the interval (in seconds) when you want lfd to retrieve. lfd +# will perform the retrieval when it runs and then again at the specified +# interval. A sensible interval would probably be every 3600 seconds (1 hour). +# A minimum value of 300 is enforced for LF_GLOBAL if enabled +# +# You do not have to specify both an allow and a deny file +# +# You can also configure a global ignore file for IP's that lfd should ignore +LF_GLOBAL = "0" + +GLOBAL_ALLOW = "" +GLOBAL_DENY = "" +GLOBAL_IGNORE = "" + +# Provides the same functionality as DYNDNS but with a GLOBAL URL file. Set +# this to the URL of the file containing DYNDNS entries +GLOBAL_DYNDNS = "" + +# Set the following to the number of seconds to poll for a change in the IP +# address resoved from GLOBAL_DYNDNS +GLOBAL_DYNDNS_INTERVAL = "600" + +# To always ignore GLOBAL_DYNDNS IP addresses in lfd blocking, set the following +# option to 1 +GLOBAL_DYNDNS_IGNORE = "0" + +# Blocklists are controlled by modifying /etc/csf/csf.blocklists +# +# If you don't want BOGON rules applied to specific NICs, then list them in +# a comma separated list (e.g "eth1,eth2") +LF_BOGON_SKIP = "" + +# The following option can be used to select the method csf will use to +# retrieve URL data and files +# +# This can be set to use: +# +# 1. Perl module HTTP::Tiny +# 2. Perl module LWP::UserAgent +# 3. CURL/WGET (set location at the bottom of csf.conf if installed) +# +# HTTP::Tiny is much faster than LWP::UserAgent and is included in the csf +# distribution. LWP::UserAgent may have to be installed manually, but it can +# better support https:// URL's which also needs the LWP::Protocol::https perl +# module +# +# CURL/WGET uses the system binaries if installed but does not always provide +# good feedback when it fails. The script will first look for CURL, if that +# does not exist at the configured location it will then look for WGET +# +# Additionally, 1 or 2 are used and the retrieval fails, then if either CURL or +# WGET are available, an additional attempt will be using CURL/WGET. This is +# useful if the perl distribution has outdated modules that do not support +# modern SSL/TLS implementations +# +# To install the LWP perl modules required: +# +# On rpm based systems: +# +# yum install perl-libwww-perl.noarch perl-LWP-Protocol-https.noarch +# +# On APT based systems: +# +# apt-get install libwww-perl liblwp-protocol-https-perl +# +# Via cpan: +# +# perl -MCPAN -eshell +# cpan> install LWP LWP::Protocol::https +# +# We recommend setting this set to "2" or "3" as upgrades to csf will be +# performed over SSL as well as other URLs used when retrieving external data +# +# "1" = HTTP::Tiny +# "2" = LWP::UserAgent +# "3" = CURL/WGET (set location at the bottom of csf.conf) +URLGET = "2" + +# If you need csf/lfd to use a proxy, then you can set this option to the URL +# of the proxy. The proxy provided will be used for both HTTP and HTTPS +# connections +URLPROXY = "" + +############################################################################### +# SECTION:Country Code Lists and Settings +############################################################################### +# Country Code to CIDR allow/deny. In the following options you can allow or +# deny whole country CIDR ranges. The CIDR blocks are obtained from a selected +# source below. They also display Country Code Country and City for reported IP +# addresses and lookups +# +# There are a number of sources for these databases, before utilising them you +# need to visit each site and ensure you abide by their license provisions +# where stated: + +# 1. MaxMind +# +# MaxMind GeoLite2 Country/City and ASN databases at: +# https://dev.MaxMind.com/geoip/geoip2/geolite2/ +# This feature relies entirely on that service being available +# +# Advantages: This is a one stop shop for all of the databases required for +# these features. They provide a consistent dataset for blocking and reporting +# purposes +# +# Disadvantages: MaxMind require a license key to download their databases. +# This is free of charge, but requires the user to create an account on their +# website to generate the required key: +# +# WARNING: As of 2019-12-29, MaxMind REQUIRES you to create an account on their +# site and to generate a license key to use their databases. See: +# https://www.maxmind.com/en/geolite2/signup +# https://blog.maxmind.com/2019/12/18/significant-changes-to-accessing-and-using-geolite2-databases/ +# +# You MUST set the following to continue using the IP lookup features of csf, +# otherwise an error will be generated and the features will not work. +# Alternatively set CC_SRC below to a different provider +# +# MaxMind License Key: +MM_LICENSE_KEY = "" + +# 2. DB-IP, ipdeny.com, iptoasn.com +# +# Advantages: The ipdeny.com databases form CC blocking are better optimised +# and so are quicker to process and create fewer iptables entries. All of these +# databases are free to download without requiring login or key +# +# Disadvantages: Multiple sources mean that any one of the three could +# interrupt the provision of these features. It may also mean that there are +# inconsistences between them +# +# https://db-ip.com/db/lite.php +# http://ipdeny.com/ +# https://iptoasn.com/ +# http://download.geonames.org/export/dump/readme.txt + +# Set the following to your preferred source: +# +# "1" - MaxMind +# "2" - db-ip, ipdeny, iptoasn +# +# The default is "2" on new installations of csf, or set to "1" to use the +# MaxMind databases after obtaining a license key +CC_SRC = "2" + +# In the following options, specify the the two-letter ISO Country Code(s). +# The iptables rules are for incoming connections only +# +# Additionally, ASN numbers can also be added to the comma separated lists +# below that also list Country Codes. The same WARNINGS for Country Codes apply +# to the use of ASNs. More about Autonomous System Numbers (ASN): +# http://www.iana.org/assignments/as-numbers/as-numbers.xhtml +# ASNs must be listed as ASnnnn (where nnnn is the ASN number) +# +# You should consider using LF_IPSET when using any of the following options +# +# WARNING: These lists are never 100% accurate and some ISP's (e.g. AOL) use +# non-geographic IP address designations for their clients +# +# WARNING: Some of the CIDR lists are huge and each one requires a rule within +# the incoming iptables chain. This can result in significant performance +# overheads and could render the server inaccessible in some circumstances. For +# this reason (amongst others) we do not recommend using these options +# +# WARNING: Due to the resource constraints on VPS servers this feature should +# not be used on such systems unless you choose very small CC zones +# +# WARNING: CC_ALLOW allows access through all ports in the firewall. For this +# reason CC_ALLOW probably has very limited use and CC_ALLOW_FILTER is +# preferred +# +# Each option is a comma separated list of CC's, e.g. "US,GB,DE" +CC_DENY = "" +CC_ALLOW = "" + +# An alternative to CC_ALLOW is to only allow access from the following +# countries but still filter based on the port and packets rules. All other +# connections are dropped +CC_ALLOW_FILTER = "" + +# This option allows access from the following countries to specific ports +# listed in CC_ALLOW_PORTS_TCP and CC_ALLOW_PORTS_UDP +# +# Note: The rules for this feature are inserted after the allow and deny +# rules to still allow blocking of IP addresses +# +# Each option is a comma separated list of CC's, e.g. "US,GB,DE" +CC_ALLOW_PORTS = "" + +# All listed ports should be removed from TCP_IN/UDP_IN to block access from +# elsewhere. This option uses the same format as TCP_IN/UDP_IN +# +# An example would be to list port 21 here and remove it from TCP_IN/UDP_IN +# then only countries listed in CC_ALLOW_PORTS can access FTP +CC_ALLOW_PORTS_TCP = "" +CC_ALLOW_PORTS_UDP = "" + +# This option denies access from the following countries to specific ports +# listed in CC_DENY_PORTS_TCP and CC_DENY_PORTS_UDP +# +# Note: The rules for this feature are inserted after the allow and deny +# rules to still allow allowing of IP addresses +# +# Each option is a comma separated list of CC's, e.g. "US,GB,DE" +CC_DENY_PORTS = "" + +# This option uses the same format as TCP_IN/UDP_IN. The ports listed should +# NOT be removed from TCP_IN/UDP_IN +# +# An example would be to list port 21 here then countries listed in +# CC_DENY_PORTS cannot access FTP +CC_DENY_PORTS_TCP = "" +CC_DENY_PORTS_UDP = "" + +# This Country Code list will prevent lfd from blocking IP address hits for the +# listed CC's +# +# CC_LOOKUPS must be enabled to use this option +CC_IGNORE = "" + +# This Country Code list will only allow SMTP AUTH to be advertised to the +# listed countries in EXIM. This is to help limit attempts at distributed +# attacks against SMTP AUTH which are difficult to achive since port 25 needs +# to be open to relay email +# +# The reason why this works is that if EXIM does not advertise SMTP AUTH on a +# connection, then SMTP AUTH will not accept logins, defeating the attacks +# without restricting mail relaying +# +# This option can generate a very large list of IP addresses that could easily +# severely impact on SMTP (mail) performance, so care must be taken when +# selecting countries and if performance issues ensue +# +# The option SMTPAUTH_RESTRICT must be enabled to use this option +CC_ALLOW_SMTPAUTH = "" + +# These options can control which IP blocks are redirected to the MESSENGER +# service, if it is enabled +# +# If Country Codes are listed in CC_MESSENGER_ALLOW, then only a blocked IP +# that resolves to one of those Country Codes will be redirected to the +# MESSENGER service +# +# If Country Codes are listed in CC_MESSENGER_DENY, then a blocked IP that +# resolves to one of those Country Codes will NOT be redirected to the +# MESSENGER service +# +CC_MESSENGER_ALLOW = "" +CC_MESSENGER_DENY = "" + +# Set this option to a valid CIDR (i.e. 1 to 32) to ignore CIDR blocks smaller +# than this value when implementing CC_DENY/CC_ALLOW/CC_ALLOW_FILTER. This can +# help reduce the number of CC entries and may improve iptables throughput. +# Obviously, this will deny/allow fewer IP addresses depending on how small you +# configure the option +# +# For example, to ignore all CIDR (and single IP) entries small than a /16, set +# this option to "16". Set to "" to block all CC IP addresses +CC_DROP_CIDR = "" + +# Display Country Code and Country for reported IP addresses. This option can +# be configured to use the databases enabled at the top of this section. An +# additional option is also available if you cannot use those databases: +# +# "0" - disable +# "1" - Reports: Country Code and Country +# "2" - Reports: Country Code and Country and Region and City +# "3" - Reports: Country Code and Country and Region and City and ASN +# "4" - Reports: Country Code and Country and Region and City (db-ip.com) +# +# Note: "4" does not use the databases enabled at the top of this section +# directly for lookups. Instead it uses a URL-based lookup from +# https://db-ip.com and so avoids having to download and process the large +# databases. Please visit the https://db-ip.com and read their limitations and +# understand that this option will either cease to function or be removed by us +# if that site is abused or overloaded. ONLY use this option if you have +# difficulties using the databases enabled at the top of this section. This +# option is ONLY for IP lookups, NOT when using the CC_* options above, which +# will continue to use the databases enabled at the top of this section +# +CC_LOOKUPS = "1" + +# Display Country Code and Country for reported IPv6 addresses using the +# databases enabled at the top of this section +# +# "0" - disable +# "1" - enable and report the detail level as specified in CC_LOOKUPS +# +# This option must also be enabled to allow IPv6 support to CC_*, MESSENGER and +# PORTFLOOD +CC6_LOOKUPS = "0" + +# This option tells lfd how often to retrieve the databases for CC_ALLOW, +# CC_ALLOW_FILTER, CC_DENY, CC_IGNORE and CC_LOOKUPS (in days) +CC_INTERVAL = "14" + +############################################################################### +# SECTION:Login Failure Blocking and Alerts +############################################################################### +# The following[*] triggers are application specific. If you set LF_TRIGGER to +# "0" the value of each trigger is the number of failures against that +# application that will trigger lfd to block the IP address +# +# If you set LF_TRIGGER to a value greater than "0" then the following[*] +# application triggers are simply on or off ("0" or "1") and the value of +# LF_TRIGGER is the total cumulative number of failures that will trigger lfd +# to block the IP address +# +# Setting the application trigger to "0" disables it +LF_TRIGGER = "0" + +# If LF_TRIGGER is > "0" then LF_TRIGGER_PERM can be set to "1" to permanently +# block the IP address, or LF_TRIGGER_PERM can be set to a value greater than +# "1" and the IP address will be blocked temporarily for that value in seconds. +# For example: +# LF_TRIGGER_PERM = "1" => the IP is blocked permanently +# LF_TRIGGER_PERM = "3600" => the IP is blocked temporarily for 1 hour +# +# If LF_TRIGGER is "0", then the application LF_[application]_PERM value works +# in the same way as above and LF_TRIGGER_PERM serves no function +LF_TRIGGER_PERM = "1" + +# To only block access to the failed application instead of a complete block +# for an ip address, you can set the following to "1", but LF_TRIGGER must be +# set to "0" with specific application[*] trigger levels also set appropriately +# +# The ports that are blocked can be configured by changing the PORTS_* options +LF_SELECT = "0" + +# Send an email alert if an IP address is blocked by one of the [*] triggers +LF_EMAIL_ALERT = "1" + +# Send an email alert if an IP address is only temporarily blocked by one of +# the [*] triggers +# +# Note: LF_EMAIL_ALERT must still be enabled to get permanent block emails +LF_TEMP_EMAIL_ALERT = "1" + +# [*]Enable login failure detection of sshd connections +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_SSHD = "5" +LF_SSHD_PERM = "1" + +# [*]Enable login failure detection of ftp connections +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_FTPD = "10" +LF_FTPD_PERM = "1" + +# [*]Enable login failure detection of SMTP AUTH connections +LF_SMTPAUTH = "5" +LF_SMTPAUTH_PERM = "1" + +# [*]Enable syntax failure detection of Exim connections +LF_EXIMSYNTAX = "10" +LF_EXIMSYNTAX_PERM = "1" + +# [*]Enable login failure detection of pop3 connections +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_POP3D = "10" +LF_POP3D_PERM = "1" + +# [*]Enable login failure detection of imap connections +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_IMAPD = "10" +LF_IMAPD_PERM = "1" + +# [*]Enable login failure detection of Apache .htpasswd connections +# Due to the often high logging rate in the Apache error log, you might want to +# enable this option only if you know you are suffering from attacks against +# password protected directories +LF_HTACCESS = "5" +LF_HTACCESS_PERM = "1" + +# [*]Enable failure detection of repeated Apache mod_security rule triggers +LF_MODSEC = "5" +LF_MODSEC_PERM = "1" + +# [*]Enable login failure detection of DirectAdmin connections +# This option also detects login failures on DA for Roundcube, SquirrelMail and +# phpMyAdmin if installed and logging enabled via CustomBuild v2+ +# +# If you do not want to scan for one or more of DIRECTADMIN_LOG_*, simply set +# the respective option to "" +LF_DIRECTADMIN = "5" +LF_DIRECTADMIN_PERM = "1" + +# [*]Enable detection of repeated BIND denied requests +# This option should be enabled with care as it will prevent blocked IPs from +# resolving any domains on the server. You might want to set the trigger value +# reasonably high to avoid this +# Example: LF_BIND = "100" +LF_BIND = "0" +LF_BIND_PERM = "1" + +# [*]Enable detection of repeated suhosin ALERTs +# Example: LF_SUHOSIN = "5" +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_SUHOSIN = "0" +LF_SUHOSIN_PERM = "1" + +# [*]Enable detection of repeated cxs ModSecurity mod_security rule triggers +# This option will block IP addresses if cxs detects a hits from the +# ModSecurity rule associated with it +# +# Note: This option takes precedence over LF_MODSEC and removes any hits +# counted towards LF_MODSEC for the cxs rule +# +# This setting should probably set very low, perhaps to 1, if you want to +# effectively block IP addresses for this trigger option +LF_CXS = "0" +LF_CXS_PERM = "1" + +# [*]Enable detection of repeated Apache mod_qos rule triggers +LF_QOS = "0" +LF_QOS_PERM = "1" + +# [*]Enable detection of repeated Apache symlink race condition triggers from +# the Apache patch provided by: +# http://www.mail-archive.com/dev@httpd.apache.org/msg55666.html +# This patch has also been included by cPanel via the easyapache option: +# "Symlink Race Condition Protection" +LF_SYMLINK = "0" +LF_SYMLINK_PERM = "1" + +# [*]Enable login failure detection of webmin connections +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_WEBMIN = "0" +LF_WEBMIN_PERM = "1" + +# Send an email alert if anyone logs in successfully using SSH +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_SSH_EMAIL_ALERT = "1" + +# Send an email alert if anyone uses su to access another account. This will +# send an email alert whether the attempt to use su was successful or not +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_SU_EMAIL_ALERT = "1" + +# Send an email alert if anyone uses sudo to access another account. This will +# send an email alert whether the attempt to use sudo was successful or not +# +# NOTE: This option could become onerous if sudo is used extensively for root +# access by administrators or control panels. It is provided for those where +# this is not the case +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_SUDO_EMAIL_ALERT = "0" + +# Send an email alert if anyone accesses webmin +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_WEBMIN_EMAIL_ALERT = "1" + +# Send an email alert if anyone logs in successfully to root on the console +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_CONSOLE_EMAIL_ALERT = "1" + +# This option will keep track of the number of "File does not exist" errors in +# HTACCESS_LOG. If the number of hits is more than LF_APACHE_404 in LF_INTERVAL +# seconds then the IP address will be blocked +# +# Care should be used with this option as it could generate many +# false-positives, especially Search Bots (use csf.rignore to ignore such bots) +# so only use this option if you know you are under this type of attack +# +# A sensible setting for this would be quite high, perhaps 200 +# +# To disable set to "0" +LF_APACHE_404 = "0" + +# If this option is set to 1 the blocks will be permanent +# If this option is > 1, the blocks will be temporary for the specified number +# of seconds +LF_APACHE_404_PERM = "3600" + +# This option will keep track of the number of "client denied by server +# configuration" errors in HTACCESS_LOG. If the number of hits is more than +# LF_APACHE_403 in LF_INTERVAL seconds then the IP address will be blocked +# +# Care should be used with this option as it could generate many +# false-positives, especially Search Bots (use csf.rignore to ignore such bots) +# so only use this option if you know you are under this type of attack +# +# A sensible setting for this would be quite high, perhaps 200 +# +# To disable set to "0" +LF_APACHE_403 = "0" + +# If this option is set to 1 the blocks will be permanent +# If this option is > 1, the blocks will be temporary for the specified number +# of seconds +LF_APACHE_403_PERM = "3600" + +# This option will keep track of the number of 401 failures in HTACCESS_LOG. +# If the number of hits is more than LF_APACHE_401 in LF_INTERVAL seconds then +# the IP address will be blocked +# +# To disable set to "0" +LF_APACHE_401 = "0" + +# If this option is set to 1 the blocks will be permanent +# If this option is > 1, the blocks will be temporary for the specified number +# of seconds +LF_APACHE_401_PERM = "3600" + +# This option is used to determine if the Apache error_log format contains the +# client port after the client IP. In Apache prior to v2.4, this was not the +# case. In Apache v2.4+ the error_log format can be configured using +# ErrorLogFormat, making the port directive optional +# +# Unfortunately v2.4 ErrorLogFormat places the port number after a colon next +# to the client IP by default. This makes determining client IPv6 addresses +# difficult unless we know whether the port is being appended or not +# +# lfd will attempt to autodetect the correct value if this option is set to "0" +# from the httpd binary found in common locations. If it fails to find a binary +# it will be set to "2", unless specified here +# +# The value can be set here explicitly if the autodetection does not work: +# 0 - autodetect +# 1 - no port directive after client IP +# 2 - port directive after client IP +LF_APACHE_ERRPORT = "0" + +# This option will send an alert if the ModSecurity IP persistent storage grows +# excessively large: https://goo.gl/rGh5sF +# +# More information on cPanel servers here: https://goo.gl/vo6xTE +# +# LF_MODSECIPDB_FILE must be set to the correct location of the database file +# +# The check is performed at lfd startup and then once per hour, the template +# used is modsecipdbalert.txt +# +# Set to "0" to disable this option, otherwise it is the threshold size of the +# file to report in gigabytes, e.g. set to 5 for 5GB +LF_MODSECIPDB_ALERT = "0" + +# This is the location of the persistent IP storage file on the server, e.g.: +# /var/run/modsecurity/data/ip.pag +# /var/cpanel/secdatadir/ip.pag +# /var/cache/modsecurity/ip.pag +# /usr/local/apache/conf/modsec/data/msa/ip.pag +# /var/tmp/ip.pag +# /tmp/ip.pag +LF_MODSECIPDB_FILE = "/tmp/ip.pag" + +# System Exploit Checking. This option is designed to perform a series of tests +# to send an alert in case a possible server compromise is detected +# +# To enable this feature set the following to the checking interval in seconds +# (a value of 300 would seem sensible). +# +# To disable set to "0" +LF_EXPLOIT = "300" + +# This comma separated list allows you to ignore tests LF_EXPLOIT performs +# +# For the SUPERUSER check, you can list usernames in csf.suignore to have them +# ignored for that test +# +# Valid tests are: +# SUPERUSER +# +# If you want to ignore a test add it to this as a comma separated list, e.g. +# "SUPERUSER" +LF_EXPLOIT_IGNORE = "" + +# Set the time interval to track login and other LF_ failures within (seconds), +# i.e. LF_TRIGGER failures within the last LF_INTERVAL seconds +LF_INTERVAL = "3600" + +# This is how long the lfd process sleeps (in seconds) before processing the +# log file entries and checking whether other events need to be triggered +LF_PARSE = "5" + +# This is the interval that is used to flush reports of usernames, files and +# pids so that persistent problems continue to be reported, in seconds. +# A value of 3600 seems sensible +LF_FLUSH = "3600" + +# Under some circumstances iptables can fail to include a rule instruction, +# especially if more than one request is made concurrently. In this event, a +# permanent block entry may exist in csf.deny, but not in iptables. +# +# This option instructs csf to deny an already blocked IP address the number +# of times set. The downside, is that there will be multiple entries for an IP +# address in csf.deny and possibly multiple rules for the same IP address in +# iptables. This needs to be taken into consideration when unblocking such IP +# addresses. +# +# Set to "0" to disable this feature. Do not set this too high for the reasons +# detailed above (e.g. "5" should be more than enough) +LF_REPEATBLOCK = "0" + +# By default csf will create both an inbound and outbound blocks from/to an IP +# unless otherwise specified in csf.deny and GLOBAL_DENY. This is the most +# effective way to block IP traffic. This option instructs csf to only block +# inbound traffic from those IP's and so reduces the number of iptables rules, +# but at the expense of less effectiveness. For this reason we recommend +# leaving this option disabled +# +# Set to "0" to disable this feature - the default +LF_BLOCKINONLY = "0" + +############################################################################### +# SECTION:CloudFlare +############################################################################### +# This features provides interaction with the CloudFlare Firewall +# +# As CloudFlare is a reverse proxy, any attacking IP addresses (so far as +# iptables is concerned) come from the CloudFlare IP's. To counter this, an +# Apache module (mod_cloudflare) is available that obtains the true attackers +# IP from a custom HTTP header record (similar functionality is available +# for other HTTP daemons +# +# However, despite now knowing the true attacking IP address, iptables cannot +# be used to block that IP as the traffic is still coming from the CloudFlare +# servers +# +# CloudFlare have provided a Firewall feature within the user account where +# rules can be added to block, challenge or whitelist IP addresses +# +# Using the CloudFlare API, this feature adds and removes attacking IPs from +# that firewall and provides CLI (and via the UI) additional commands +# +# See /etc/csf/readme.txt for more information about this feature and the +# restrictions for its use BEFORE enabling this feature +CF_ENABLE = "0" + +# This can be set to either "block" or "challenge" (see CloudFlare docs) +CF_BLOCK = "block" + +# This setting determines how long the temporary block will apply within csf +# and CloudFlare, keeping them in sync +# +# Block duration in seconds - overrides perm block or time of individual blocks +# in lfd for block triggers +CF_TEMP = "3600" + +############################################################################### +# SECTION:Directory Watching & Integrity +############################################################################### +# Enable Directory Watching. This enables lfd to check /tmp and /dev/shm +# directories for suspicious files, i.e. script exploits. If a suspicious +# file is found an email alert is sent. One alert per file per LF_FLUSH +# interval is sent +# +# To enable this feature set the following to the checking interval in seconds. +# To disable set to "0" +LF_DIRWATCH = "300" + +# To remove any suspicious files found during directory watching, enable the +# following. These files will be appended to a tarball in +# /var/lib/csf/suspicious.tar +LF_DIRWATCH_DISABLE = "0" + +# This option allows you to have lfd watch a particular file or directory for +# changes and should they change and email alert using watchalert.txt is sent +# +# To enable this feature set the following to the checking interval in seconds +# (a value of 60 would seem sensible) and add your entries to csf.dirwatch +# +# Set to disable set to "0" +LF_DIRWATCH_FILE = "0" + +# System Integrity Checking. This enables lfd to compare md5sums of the +# servers OS binary application files from the time when lfd starts. If the +# md5sum of a monitored file changes an alert is sent. This option is intended +# as an IDS (Intrusion Detection System) and is the last line of detection for +# a possible root compromise. +# +# There will be constant false-positives as the servers OS is updated or +# monitored application binaries are updated. However, unexpected changes +# should be carefully inspected. +# +# Modified files will only be reported via email once. +# +# To enable this feature set the following to the checking interval in seconds +# (a value of 3600 would seem sensible). This option may increase server I/O +# load onto the server as it checks system binaries. +# +# To disable set to "0" +LF_INTEGRITY = "3600" + +############################################################################### +# SECTION:Distributed Attacks +############################################################################### +# Distributed Account Attack. This option will keep track of login failures +# from distributed IP addresses to a specific application account. If the +# number of failures matches the trigger value above, ALL of the IP addresses +# involved in the attack will be blocked according to the temp/perm rules above +# +# Tracking applies to LF_SSHD, LF_FTPD, LF_SMTPAUTH, LF_POP3D, LF_IMAPD, +# LF_HTACCESS +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_DISTATTACK = "0" + +# Set the following to the minimum number of unique IP addresses that trigger +# LF_DISTATTACK +LF_DISTATTACK_UNIQ = "2" + +# Distributed FTP Logins. This option will keep track of successful FTP logins. +# If the number of successful logins to an individual account is at least +# LF_DISTFTP in LF_DIST_INTERVAL from at least LF_DISTFTP_UNIQ IP addresses, +# then all of the IP addresses will be blocked +# +# This option can help mitigate the common FTP account compromise attacks that +# use a distributed network of zombies to deface websites +# +# A sensible setting for this might be 5, depending on how many different +# IP addresses you expect to an individual FTP account within LF_DIST_INTERVAL +# +# To disable set to "0" +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_DISTFTP = "0" + +# Set the following to the minimum number of unique IP addresses that trigger +# LF_DISTFTP. LF_DISTFTP_UNIQ must be <= LF_DISTFTP for this to work +LF_DISTFTP_UNIQ = "3" + +# If this option is set to 1 the blocks will be permanent +# If this option is > 1, the blocks will be temporary for the specified number +# of seconds +LF_DISTFTP_PERM = "1" + +# Send an email alert if LF_DISTFTP is triggered +LF_DISTFTP_ALERT = "1" + +# Distributed SMTP Logins. This option will keep track of successful SMTP +# logins. If the number of successful logins to an individual account is at +# least LF_DISTSMTP in LF_DIST_INTERVAL from at least LF_DISTSMTP_UNIQ IP +# addresses, then all of the IP addresses will be blocked. These options only +# apply to the exim MTA +# +# This option can help mitigate the common SMTP account compromise attacks that +# use a distributed network of zombies to send spam +# +# A sensible setting for this might be 5, depending on how many different +# IP addresses you expect to an individual SMTP account within LF_DIST_INTERVAL +# +# To disable set to "0" +LF_DISTSMTP = "0" + +# Set the following to the minimum number of unique IP addresses that trigger +# LF_DISTSMTP. LF_DISTSMTP_UNIQ must be <= LF_DISTSMTP for this to work +LF_DISTSMTP_UNIQ = "3" + +# If this option is set to 1 the blocks will be permanent +# If this option is > 1, the blocks will be temporary for the specified number +# of seconds +LF_DISTSMTP_PERM = "1" + +# Send an email alert if LF_DISTSMTP is triggered +LF_DISTSMTP_ALERT = "1" + +# This is the interval during which a distributed FTP or SMTP attack is +# measured +LF_DIST_INTERVAL = "300" + +# If LF_DISTFTP or LF_DISTSMTP is triggered, then if the following contains the +# path to a script, it will run the script and pass the following as arguments: +# +# LF_DISTFTP/LF_DISTSMTP +# account name +# log file text +# +# The action script must have the execute bit and interpreter (shebang) set +LF_DIST_ACTION = "" + +############################################################################### +# SECTION:Login Tracking +############################################################################### +# Block POP3 logins if greater than LT_POP3D times per hour per account per IP +# address (0=disabled) +# +# This is a temporary block for the rest of the hour, afterwhich the IP is +# unblocked +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LT_POP3D = "0" + +# Block IMAP logins if greater than LT_IMAPD times per hour per account per IP +# address (0=disabled) - not recommended for IMAP logins due to the ethos +# within which IMAP works. If you want to use this, setting it quite high is +# probably a good idea +# +# This is a temporary block for the rest of the hour, afterwhich the IP is +# unblocked +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LT_IMAPD = "0" + +# Send an email alert if an account exceeds LT_POP3D/LT_IMAPD logins per hour +# per IP +LT_EMAIL_ALERT = "1" + +# If LF_PERMBLOCK is enabled but you do not want this to apply to +# LT_POP3D/LT_IMAPD, then enable this option +LT_SKIPPERMBLOCK = "0" + +############################################################################### +# SECTION:Relay Tracking +############################################################################### +# Relay Tracking. This allows you to track email that is relayed through the +# server. There are also options to send alerts and block external IP addresses +# if the number of emails relayed per hour exceeds configured limits. The +# blocks can be either permanent or temporary. +# +# The following information applies to each of the following types of relay +# check: +# RT_[relay type]_ALERT: 0 = disable, 1 = enable +# RT_[relay type]_LIMIT: the limit/hour afterwhich an email alert will be sent +# RT_[relay type]_BLOCK: 0 = no block;1 = perm block;nn=temp block for nn secs + +# This option triggers for external email +RT_RELAY_ALERT = "1" +RT_RELAY_LIMIT = "100" +RT_RELAY_BLOCK = "0" + +# This option triggers for email authenticated by SMTP AUTH +RT_AUTHRELAY_ALERT = "1" +RT_AUTHRELAY_LIMIT = "100" +RT_AUTHRELAY_BLOCK = "0" + +# This option triggers for email sent via /usr/sbin/sendmail or /usr/sbin/exim +RT_LOCALRELAY_ALERT = "1" +RT_LOCALRELAY_LIMIT = "100" + +# This option triggers for email sent via a local IP addresses +RT_LOCALHOSTRELAY_ALERT = "1" +RT_LOCALHOSTRELAY_LIMIT = "100" + +# If an RT_* event is triggered, then if the following contains the path to +# a script, it will be run in a child process and passed the following: +# information as parameters which also appears in the email alert: +# IP Address +# Relay Type (RELAY/AUTHRELAY/POPRELAY/LOCALRELAY/LOCALHOSTRELAY) +# Block Message (Temporary/Permanent Block) +# Count of emails relayed +# Sample of the first 10 emails +# +# The action script must have the execute bit and interpreter (shebang) set +RT_ACTION = "" + +############################################################################### +# SECTION:Connection Tracking +############################################################################### +# Connection Tracking. This option enables tracking of all connections from IP +# addresses to the server. If the total number of connections is greater than +# this value then the offending IP address is blocked. This can be used to help +# prevent some types of DOS attack. +# +# Care should be taken with this option. It's entirely possible that you will +# see false-positives. Some protocols can be connection hungry, e.g. FTP, IMAPD +# and HTTP so it could be quite easy to trigger, especially with a lot of +# closed connections in TIME_WAIT. However, for a server that is prone to DOS +# attacks this may be very useful. A reasonable setting for this option might +# be around 300. +# +# To disable this feature, set this to 0 +CT_LIMIT = "0" + +# Connection Tracking interval. Set this to the the number of seconds between +# connection tracking scans +CT_INTERVAL = "30" + +# Send an email alert if an IP address is blocked due to connection tracking +CT_EMAIL_ALERT = "1" + +# If you want to make IP blocks permanent then set this to 1, otherwise blocks +# will be temporary and will be cleared after CT_BLOCK_TIME seconds +CT_PERMANENT = "0" + +# If you opt for temporary IP blocks for CT, then the following is the interval +# in seconds that the IP will remained blocked for (e.g. 1800 = 30 mins) +CT_BLOCK_TIME = "1800" + +# If you don't want to count the TIME_WAIT state against the connection count +# then set the following to "1" +CT_SKIP_TIME_WAIT = "0" + +# If you only want to count specific states (e.g. SYN_RECV) then add the states +# to the following as a comma separated list. E.g. "SYN_RECV,TIME_WAIT" +# +# Leave this option empty to count all states against CT_LIMIT +CT_STATES = "" + +# If you only want to count specific ports (e.g. 80,443) then add the ports +# to the following as a comma separated list. E.g. "80,443" +# +# Leave this option empty to count all ports against CT_LIMIT +CT_PORTS = "" + +# If the total number of connections from a class C subnet is greater than this +# value then the offending subnet is blocked according to the other CT_* +# settings +# +# This option can be used to help prevent some types of DOS attack where a +# range of IP's between x.y.z.1-255 has connected to the server +# +# If you use a reverse proxy service such as Cloudflare you should not enable +# this option, or should exclude the ports that you have proxied in CT_PORTS +# +# To disable this feature, set this to 0 +CT_SUBNET_LIMIT = "0" + +############################################################################### +# SECTION:Process Tracking +############################################################################### +# Process Tracking. This option enables tracking of user and nobody processes +# and examines them for suspicious executables or open network ports. Its +# purpose is to identify potential exploit processes that are running on the +# server, even if they are obfuscated to appear as system services. If a +# suspicious process is found an alert email is sent with relevant information. +# It is then the responsibility of the recipient to investigate the process +# further as the script takes no further action +# +# The following is the number of seconds a process has to be active before it +# is inspected. If you set this time too low, then you will likely trigger +# false-positives with CGI or PHP scripts. +# Set the value to 0 to disable this feature +PT_LIMIT = "60" + +# How frequently processes are checked in seconds +PT_INTERVAL = "60" + +# If you want process tracking to highlight php or perl scripts that are run +# through apache then disable the following, +# i.e. set it to 0 +# +# While enabling this setting will reduce false-positives, having it set to 0 +# does provide better checking for exploits running on the server +PT_SKIP_HTTP = "0" + +# lfd will report processes, even if they're listed in csf.pignore, if they're +# tagged as (deleted) by Linux. This information is provided in Linux under +# /proc/PID/exe. A (deleted) process is one that is running a binary that has +# the inode for the file removed from the file system directory. This usually +# happens when the binary has been replaced due to an upgrade for it by the OS +# vendor or another third party (e.g. cPanel). You need to investigate whether +# this is indeed the case to be sure that the original binary has not been +# replaced by a rootkit or is running an exploit. +# +# Note: If a deleted executable process is detected and reported then lfd will +# not report children of the parent (or the parent itself if a child triggered +# the report) if the parent is also a deleted executable process +# +# To stop lfd reporting such process you need to restart the daemon to which it +# belongs and therefore run the process using the replacement binary (presuming +# one exists). This will normally mean running the associated startup script in +# /etc/init.d/ +# +# If you do want lfd to report deleted binary processes, set to 1 +PT_DELETED = "0" + +# If a PT_DELETED event is triggered, then if the following contains the path to +# a script, it will be run in a child process and passed the executable, pid, +# account for the process, and parent pid +# +# The action script must have the execute bit and interpreter (shebang) set. An +# example is provided in /usr/local/csf/bin/pt_deleted_action.pl +# +# WARNING: Make sure you read and understand the potential security +# implications of such processes in PT_DELETED above before simply restarting +# such processes with a script +PT_DELETED_ACTION = "" + +# User Process Tracking. This option enables the tracking of the number of +# process any given account is running at one time. If the number of processes +# exceeds the value of the following setting an email alert is sent with +# details of those processes. If you specify a user in csf.pignore it will be +# ignored +# +# Set to 0 to disable this feature +PT_USERPROC = "10" + +# This User Process Tracking option sends an alert if any user process exceeds +# the virtual memory usage set (MB). To ignore specific processes or users use +# csf.pignore +# +# Set to 0 to disable this feature +PT_USERMEM = "512" + +# This User Process Tracking option sends an alert if any user process exceeds +# the RSS memory usage set (MB) - RAM used, not virtual. To ignore specific +# processes or users use csf.pignore +# +# Set to 0 to disable this feature +PT_USERRSS = "256" + +# This User Process Tracking option sends an alert if any linux user process +# exceeds the time usage set (seconds). To ignore specific processes or users +# use csf.pignore +# +# Set to 0 to disable this feature +PT_USERTIME = "1800" + +# If this option is set then processes detected by PT_USERMEM, PT_USERTIME or +# PT_USERPROC are killed +# +# Warning: We don't recommend enabling this option unless absolutely necessary +# as it can cause unexpected problems when processes are suddenly terminated. +# It can also lead to system processes being terminated which could cause +# stability issues. It is much better to leave this option disabled and to +# investigate each case as it is reported when the triggers above are breached +# +# Note: Processes that are running deleted excecutables (see PT_DELETED) will +# not be killed by lfd +PT_USERKILL = "0" + +# If you want to disable email alerts if PT_USERKILL is triggered, then set +# this option to 0 +PT_USERKILL_ALERT = "1" + +# If a PT_* event is triggered, then if the following contains the path to +# a script, it will be run in a child process and passed the PID(s) of the +# process(es) in a comma separated list. +# +# The action script must have the execute bit and interpreter (shebang) set +PT_USER_ACTION = "" + +# Check the PT_LOAD_AVG minute Load Average (can be set to 1 5 or 15 and +# defaults to 5 if set otherwise) on the server every PT_LOAD seconds. If the +# load average is greater than or equal to PT_LOAD_LEVEL then an email alert is +# sent. lfd then does not report subsequent high load until PT_LOAD_SKIP +# seconds has passed to prevent email floods. +# +# Set PT_LOAD to "0" to disable this feature +PT_LOAD = "30" +PT_LOAD_AVG = "5" +PT_LOAD_LEVEL = "6" +PT_LOAD_SKIP = "3600" + +# This is the Apache Server Status URL used in the email alert. Requires the +# Apache mod_status module to be installed and configured correctly +PT_APACHESTATUS = "http://127.0.0.1/server-status" + +# If a PT_LOAD event is triggered, then if the following contains the path to +# a script, it will be run in a child process. For example, the script could +# contain commands to terminate and restart httpd, php, exim, etc incase of +# looping processes. The action script must have the execute bit an +# interpreter (shebang) set +PT_LOAD_ACTION = "" + +# Fork Bomb Protection. This option checks the number of processes with the +# same session id and if greater than the value set, the whole session tree is +# terminated and an alert sent +# +# You can see an example of common session id processes on most Linux systems +# using: "ps axf -O sid" +# +# On cPanel servers, PT_ALL_USERS should be enabled to use this option +# effectively +# +# This option will check root owned processes. Session id 0 and 1 will always +# be ignored as they represent kernel and init processes. csf.pignore will be +# honoured, but bear in mind that a session tree can contain a variety of users +# and executables +# +# Care needs to be taken to ensure that this option only detects runaway fork +# bombs, so should be set higher than any session tree is likely to get (e.g. +# httpd could have 100s of legitimate children on very busy systems). A +# sensible starting point on most servers might be 250 +PT_FORKBOMB = "0" + +# Terminate hung SSHD sessions. When under an SSHD login attack, SSHD processes +# are often left hanging after their connecting IP addresses have been blocked +# +# This option will terminate the SSH processes created by the blocked IP. This +# option is preferred over PT_SSHDHUNG +PT_SSHDKILL = "0" + +# This option will terminate all processes with the cmdline of "sshd: unknown +# [net]" or "sshd: unknown [priv]" if they have been running for more than 60 +# seconds +PT_SSHDHUNG = "0" + +############################################################################### +# SECTION:Port Scan Tracking +############################################################################### +# Port Scan Tracking. This feature tracks port blocks logged by iptables to +# syslog. If an IP address generates a port block that is logged more than +# PS_LIMIT within PS_INTERVAL seconds, the IP address will be blocked. +# +# This feature could, for example, be useful for blocking hackers attempting +# to access the standard SSH port if you have moved it to a port other than 22 +# and have removed 22 from the TCP_IN list so that connection attempts to the +# old port are being logged +# +# This feature blocks all iptables blocks from the iptables logs, including +# repeated attempts to one port or SYN flood blocks, etc +# +# Note: This feature will only track iptables blocks from the log file set in +# IPTABLES_LOG below and if you have DROP_LOGGING enabled. However, it will +# cause redundant blocking with DROP_IP_LOGGING enabled +# +# Warning: It's possible that an elaborate DDOS (i.e. from multiple IP's) +# could very quickly fill the iptables rule chains and cause a DOS in itself. +# The DENY_IP_LIMIT should help to mitigate such problems with permanent blocks +# and the DENY_TEMP_IP_LIMIT with temporary blocks +# +# Set PS_INTERVAL to "0" to disable this feature. A value of between 60 and 300 +# would be sensible to enable this feature +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +PS_INTERVAL = "0" +PS_LIMIT = "10" + +# You can specify the ports and/or port ranges that should be tracked by the +# Port Scan Tracking feature. The following setting is a comma separated list +# of those ports and uses the same format as TCP_IN. The setting of +# 0:65535,ICMP,INVALID,OPEN,BRD covers all ports +# +# Special values are: +# ICMP - include ICMP blocks (see ICMP_*) +# INVALID - include INVALID blocks (see PACKET_FILTER) +# OPEN - include TCP_IN and UDP_IN open port blocks - *[proto]_IN Blocked* +# BRD - include UDP Broadcast IPs, otherwise they are ignored +PS_PORTS = "0:65535,ICMP" + +# To specify how many different ports qualifies as a Port Scan you can increase +# the following from the default value of 1. The risk in doing so will mean +# that persistent attempts to attack a specific closed port will not be +# detected and blocked +PS_DIVERSITY = "1" + +# You can select whether IP blocks for Port Scan Tracking should be temporary +# or permanent. Set PS_PERMANENT to "0" for temporary and "1" for permanent +# blocking. If set to "0" PS_BLOCK_TIME is the amount of time in seconds to +# temporarily block the IP address for +PS_PERMANENT = "0" +PS_BLOCK_TIME = "3600" + +# Set the following to "1" to enable Port Scan Tracking email alerts, set to +# "0" to disable them +PS_EMAIL_ALERT = "1" + +############################################################################### +# SECTION:User ID Tracking +############################################################################### +# User ID Tracking. This feature tracks UID blocks logged by iptables to +# syslog. If a UID generates a port block that is logged more than UID_LIMIT +# times within UID_INTERVAL seconds, an alert will be sent +# +# Note: This feature will only track iptables blocks from the log file set in +# IPTABLES_LOG and if DROP_OUT_LOGGING and DROP_UID_LOGGING are enabled. +# +# To ignore specific UIDs list them in csf.uidignore and then restart lfd +# +# Set UID_INTERVAL to "0" to disable this feature. A value of between 60 and 300 +# would be sensible to enable this feature +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +UID_INTERVAL = "0" +UID_LIMIT = "10" + +# You can specify the ports and/or port ranges that should be tracked by the +# User ID Tracking feature. The following setting is a comma separated list +# of those ports and uses the same format as TCP_OUT. The default setting of +# 0:65535,ICMP covers all ports +UID_PORTS = "0:65535,ICMP" + +############################################################################### +# SECTION:Account Tracking +############################################################################### +# Account Tracking. The following options enable the tracking of modifications +# to the accounts on a server. If any of the enabled options are triggered by +# a modifications to an account, an alert email is sent. Only the modification +# is reported. The cause of the modification will have to be investigated +# manually +# +# You can set AT_ALERT to the following: +# 0 = disable this feature +# 1 = enable this feature for all accounts +# 2 = enable this feature only for superuser accounts (UID = 0, e.g. root, etc) +# 3 = enable this feature only for the root account +AT_ALERT = "2" + +# This options is the interval between checks in seconds +AT_INTERVAL = "60" + +# Send alert if a new account is created +AT_NEW = "1" + +# Send alert if an existing account is deleted +AT_OLD = "1" + +# Send alert if an account password has changed +AT_PASSWD = "1" + +# Send alert if an account uid has changed +AT_UID = "1" + +# Send alert if an account gid has changed +AT_GID = "1" + +# Send alert if an account login directory has changed +AT_DIR = "1" + +# Send alert if an account login shell has changed +AT_SHELL = "1" + +############################################################################### +# SECTION:Integrated User Interface +############################################################################### +# Integrated User Interface. This feature provides a HTML UI to csf and lfd, +# without requiring a control panel or web server. The UI runs as a sub process +# to the lfd daemon +# +# As it runs under the root account and successful login provides root access +# to the server, great care should be taken when configuring and using this +# feature. There are additional restrictions to enhance secure access to the UI +# +# See readme.txt for more information about using this feature BEFORE enabling +# it for security and access reasons +# +# 1 to enable, 0 to disable +UI = "0" + +# Set this to the port that want to bind this service to. You should configure +# this port to be >1023 and different from any other port already being used +# +# Do NOT enable access to this port in TCP_IN, instead only allow trusted IP's +# to the port using Advanced Allow Filters (see readme.txt) +UI_PORT = "6666" + +# Optionally set the IP address to bind to. Normally this should be left blank +# to bind to all IP addresses on the server. +# +# If the server is configured for IPv6 but the IP to bind to is IPv4, then the +# IP address MUST use the IPv6 representation. For example 1.2.3.4 must use +# ::ffff:1.2.3.4 +# +# Leave blank to bind to all IP addresses on the server +UI_IP = "" + +# This should be a secure, hard to guess username +# +# This must be changed from the default +UI_USER = "username" + +# This should be a secure, hard to guess password. That is, at least 8 +# characters long with a mixture of upper and lowercase characters plus +# numbers and non-alphanumeric characters +# +# This must be changed from the default +UI_PASS = "password" + +# This is the login session timeout. If there is no activity for a logged in +# session within this number of seconds, the session will timeout and a new +# login will be required +# +# For security reasons, you should always keep this option low (i.e 60-300) +UI_TIMEOUT = "300" + +# This is the maximum concurrent connections allowed to the server. The default +# value should be sufficient +UI_CHILDREN = "5" + +# The number of login retries allowed within a 24 hour period. A successful +# login from the IP address will clear the failures +# +# For security reasons, you should always keep this option low (i.e 0-10) +UI_RETRY = "5" + +# If enabled, this option will add the connecting IP address to the file +# /etc/csf/ui/ui.ban after UI_RETRY login failures. The IP address will not be +# able to login to the UI while it is listed in this file. The UI_BAN setting +# does not refer to any of the csf/lfd allow or ignore files, e.g. csf.allow, +# csf.ignore, etc. +# +# For security reasons, you should always enable this option +UI_BAN = "1" + +# If enabled, only IPs (or CIDR's) listed in the file /etc/csf/ui/ui.allow will +# be allowed to login to the UI. The UI_ALLOW setting does not refer to any of +# the csf/lfd allow or ignore files, e.g. csf.allow, csf.ignore, etc. +# +# For security reasons, you should always enable this option and use ui.allow +UI_ALLOW = "1" + +# If enabled, this option will trigger an iptables block through csf after +# UI_RETRY login failures +# +# 0 = no block;1 = perm block;nn=temp block for nn secs +UI_BLOCK = "1" + +# This controls what email alerts are sent with regards to logins to the UI. It +# uses the uialert.txt template +# +# 4 = login success + login failure/ban/block + login attempts +# 3 = login success + login failure/ban/block +# 2 = login failure/ban/block +# 1 = login ban/block +# 0 = disabled +UI_ALERT = "4" + +# This is the SSL cipher list that the Integrated UI will negotiate from +UI_CIPHER = "ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:-LOW:-SSLv2:-EXP:!kEDH" + +# This is the SSL protocol version used. See IO::Socket::SSL if you wish to +# change this and to understand the implications of changing it +UI_SSL_VERSION = "SSLv23:!SSLv3:!SSLv2" + +# If cxs is installed then enabling this option will provide a dropdown box to +# switch between applications +UI_CXS = "0" + +# There is a modified installation of ConfigServer Explorer (cse) provided with +# the csf distribution. If this option is enabled it will provide a dropdown +# box to switch between applications +UI_CSE = "0" + +############################################################################### +# SECTION:Messenger service +############################################################################### +# Messenger service. This feature allows the display of a message to a blocked +# connecting IP address to inform the user that they are blocked in the +# firewall. This can help when users get themselves blocked, e.g. due to +# multiple login failures. The service is provided by two daemons running on +# ports providing either an HTML or TEXT message +# +# This feature does not work on servers that do not have the iptables module +# ipt_REDIRECT loaded. Typically, this will be with MONOLITHIC kernels. VPS +# server admins should check with their VPS host provider that the iptables +# module is included +# +# IPv6 will need the IO::Socket::INET6 perl module +# +# For further information on features and limitations refer to the csf +# readme.txt +# +# Note: Run /etc/csf/csftest.pl to check whether this option will function on +# this server +# +# 1 to enable, 0 to disable +MESSENGER = "0" + +# Provide this service to temporary IP address blocks +MESSENGER_TEMP = "1" + +# Provide this service to permanent IP address blocks +MESSENGER_PERM = "1" + +# User account to run the service servers under. We recommend creating a +# specific non-priv, non-shell account for this purpose +# +# Note: When using MESSENGERV2, this account must NOT be a valid control panel +# account, it must be created manually as explained in the csf readme.txt +MESSENGER_USER = "csf" + +# This option points to the file(s) containing the Apache VirtualHost SSL +# definitions. This can be a file glob if there are multiple files to search. +# Only Apache v2 SSL VirtualHost definitions are supported +# +# This is used by MESSENGERV1 and MESSENGERV2 only +MESSENGER_HTTPS_CONF = "/etc/httpd/conf/httpd.conf" + +# The following options can be specified to provide a default fallback +# certificate to be used if either SNI is not supported or a hosted domain does +# not have an SSL certificate. If a fallback is not provided, one of the certs +# obtained from MESSENGER_HTTPS_CONF will be used +# +# This is used by MESSENGERV1 and MESSENGERV2 only +MESSENGER_HTTPS_KEY = "/etc/httpd/conf/ssl.key/server.key" +MESSENGER_HTTPS_CRT = "/etc/httpd/conf/ssl.crt/server.crt" + +# Set this to the port that will receive the HTTPS HTML message. You should +# configure this port to be >1023 and different from the TEXT and HTML port. Do +# NOT enable access to this port in TCP_IN. This option requires the perl +# module IO::Socket::SSL at a version level that supports SNI (1.83+). +# Additionally the version of openssl on the server must also support SNI +# +# The option uses existing SSL certificates on the server for each domain to +# maintain a secure connection without browser warnings. It uses SNI to choose +# the correct certificate to use for each client connection +# +# Warning: On some servers the amount of memory used by the HTTPS MESSENGER +# service can become significant depending on various factors associated with +# the use of IO::Socket::SSL including the number of domains and certificates +# served. This is normally only an issue if using MESSENGERV1 +MESSENGER_HTTPS = "8887" + +# This comma separated list are the HTTPS HTML ports that will be redirected +# for the blocked IP address. If you are using per application blocking +# (LF_TRIGGER) then only the relevant block port will be redirected to the +# messenger port +# +# Recommended setting "443" plus any end-user control panel SSL ports. So, for +# cPanel: "443,2083,2096" +MESSENGER_HTTPS_IN = "443,2222" + +# Set this to the port that will receive the HTML message. You should configure +# this port to be >1023 and different from the TEXT port. Do NOT enable access +# to this port in TCP_IN +MESSENGER_HTML = "8888" + +# This comma separated list are the HTML ports that will be redirected for the +# blocked IP address. If you are using per application blocking (LF_TRIGGER) +# then only the relevant block port will be redirected to the messenger port +MESSENGER_HTML_IN = "80" + +# Set this to the port that will receive the TEXT message. You should configure +# this port to be >1023 and different from the HTML port. Do NOT enable access +# to this port in TCP_IN +MESSENGER_TEXT = "8889" + +# This comma separated list are the TEXT ports that will be redirected for the +# blocked IP address. If you are using per application blocking (LF_TRIGGER) +# then only the relevant block port will be redirected to the messenger port +MESSENGER_TEXT_IN = "21" + +# These settings limit the rate at which connections can be made to the +# messenger service servers. Its intention is to provide protection from +# attacks or excessive connections to the servers. If the rate is exceeded then +# iptables will revert for the duration to the normal blocking activity +# +# See the iptables man page for the correct --limit rate syntax +MESSENGER_RATE = "100/s" +MESSENGER_BURST = "150" + +# MESSENGERV1 only: +#------------------------------------------------------------------------------ +# This is the maximum concurrent connections allowed to each service server +# +# Note: This number should be increased to cater for the number of local images +# served by this page, including one for favicon.ico. This is because each +# image displayed counts as an additional connection +MESSENGER_CHILDREN = "20" + +# This options ignores ServerAlias definitions that begin with "mail.". This +# can help reduce memory usage on systems that do not require the use of +# MESSENGER_HTTPS on those subdomains +# +# Set to 0 to include these ServerAlias definitions +MESSENGER_HTTPS_SKIPMAIL = "1" + +# MESSENGERV2 only: +#------------------------------------------------------------------------------ +# MESSENGERV2. This option is available on cPanel servers running Apache v2.4+ +# under EA4. +# +# This uses the Apache http daemon to provide the web server functionality for +# the MESSENGER HTML and HTTPS services. It uses a fraction of the resources +# that the lfd inbuilt service uses and overcomes the memory overhead of using +# the MESSENGER HTTPS service +# +# For more information consult readme.txt before enabling this option +#MESSENGERV2 = "0" + +# MESSENGERV3 only: +#------------------------------------------------------------------------------ +# MESSENGERV3. This option is available on any server running Apache v2.4+, +# Litespeed or Openlitespeed +# +# This uses the web server http daemon to provide the web server functionality +# for the MESSENGER HTML and HTTPS services. It uses a fraction of the +# resources that the lfd inbuilt service uses and overcomes the memory overhead +# of using the MESSENGER HTTPS service +# +# For more information consult readme.txt before enabling this option +MESSENGERV3 = "0" + +# This is the file or directory where the additional web server configuration +# file should be included +MESSENGERV3LOCATION = "/etc/httpd/conf/extra/httpd-includes.conf" + +# This is the command to restart the web server +MESSENGERV3RESTART = "service httpd restart" + +# This is the command to test the validity of the web server configuration. If +# using Litespeed, set to "" +MESSENGERV3TEST = "/usr/sbin/apachectl -t" + +# This must be set to the main httpd.conf file for either Apache or Litespeed +MESSENGERV3HTTPS_CONF = "/etc/httpd/conf/httpd.conf" + +# This can be set to either: +# "apache" - for servers running Apache v2.4+ or Litespeed using Apache +# configuration +# "litespeed" - for Litespeed or Openlitespeed +MESSENGERV3WEBSERVER = "apache" + +# On creation, set the MESSENGER_USER public_html directory permissions to +# Note: If you precreate this directory the following setting will be ignored +MESSENGERV3PERMS = "711" + +# On creation, set the MESSENGER_USER public_html directory group user to +# Note: If you precreate this directory the following setting will be ignored +MESSENGERV3GROUP = "apache" + +# This is the web server configuration to allow PHP scripts to run. If left +# empty, the MESSENGER service will try to configure this. If this does not +# work, this should be set as an "Include /path/to/csf_php.conf" or similar +# file which must contain appropriate web server configuration to allow PHP +# scripts to run. This line will be included within each MESSENGER VirtualHost +# container. This will replace the [MESSENGERV3PHPHANDLER] line from the csf +# webserver template files +MESSENGERV3PHPHANDLER = "" + +# RECAPTCHA: +#------------------------------------------------------------------------------ +# The RECAPTCHA options provide a way for end-users that have blocked +# themselves in the firewall to unblock themselves. +# +# A valid Google ReCAPTCHA (v2) key set is required for this feature from: +# https://www.google.com/recaptcha/intro/index.html +# +# When configuring a new reCAPTCHA API key set you must ensure that the option +# for "Domain Name Validation" is unticked so that the same reCAPTCHA can be +# used for all domains hosted on the server. lfd then checks that the hostname +# of the request resolves to an IP on this server +# +# This feature requires the installation of the LWP::UserAgent perl module (see +# option URLGET for more details) +# +# The template used for this feature is /etc/csf/messenger/index.recaptcha.html +# +# Note: An unblock will fail if the end-users IP is located in a netblock, +# blocklist or CC_* deny entry +RECAPTCHA_SITEKEY = "" +RECAPTCHA_SECRET = "" + +# Send an email when an IP address successfully attempts to unblock themselves. +# This does not necessarily mean the IP was unblocked, only that the +# post-recaptcha unblock request was attempted +# +# Set to "0" to disable +RECAPTCHA_ALERT = "1" + +# If the server uses NAT then resolving the hostname to hosted IPs will likely +# not succeed. In that case, the external IP addresses must be listed as comma +# separated list here +RECAPTCHA_NAT = "" + +############################################################################### +# SECTION:lfd Clustering +############################################################################### +# lfd Clustering. This allows the configuration of an lfd cluster environment +# where a group of servers can share blocks and configuration option changes. +# Included are CLI and UI options to send requests to the cluster. +# +# See the readme.txt file for more information and details on setup and +# security risks. +# +# Set this to a comma separated list of cluster member IP addresses to send +# requests to. Alternatively, it can be set to the full path of a file that +# will read in one IP per line, e.g.: +# "/etc/csf/cluster_sendto.txt" +CLUSTER_SENDTO = "" + +# Set this to a comma separated list of cluster member IP addresses to receive +# requests from. Alternatively, it can be set to the full path of a file that +# will read in one IP per line, e.g.: +# "/etc/csf/cluster_recvfrom.txt" +CLUSTER_RECVFROM = "" + +# IP address of the master node in the cluster allowed to send CLUSTER_CONFIG +# changes +CLUSTER_MASTER = "" + +# If this is a NAT server, set this to the public IP address of this server +CLUSTER_NAT = "" + +# If a cluster member should send requests on an IP other than the default IP, +# set it here +CLUSTER_LOCALADDR = "" + +# Cluster communication port (must be the same on all member servers). There +# is no need to open this port in the firewall as csf will automatically add +# in and out bound rules to allow communication between cluster members +CLUSTER_PORT = "7777" + +# This is a secret key used to encrypt cluster communications using the +# Blowfish algorithm. It should be between 8 and 56 characters long, +# preferably > 20 random characters +# 56 chars: 01234567890123456789012345678901234567890123456789012345 +CLUSTER_KEY = "" + +# Automatically send lfd blocks to all members of CLUSTER_SENDTO. Those +# servers must have this servers IP address listed in their CLUSTER_RECVFROM +# +# Set to 0 to disable this feature +CLUSTER_BLOCK = "1" + +# This option allows the enabling and disabling of the Cluster configuration +# changing options --cconfig, --cconfigr, --cfile, --ccfile sent from the +# CLUSTER_MASTER server +# +# Set this option to 1 to allow Cluster configurations to be received +CLUSTER_CONFIG = "0" + +# Maximum number of child processes to listen on. High blocking rates or large +# clusters may need to increase this +CLUSTER_CHILDREN = "10" + +############################################################################### +# SECTION:Port Knocking +############################################################################### +# Port Knocking. This feature allows port knocking to be enabled on multiple +# ports with a variable number of knocked ports and a timeout. There must be a +# minimum of 3 ports to knock for an entry to be valid +# +# See the following for information regarding Port Knocking: +# http://www.portknocking.org/ +# +# This feature does not work on servers that do not have the iptables module +# ipt_recent loaded. Typically, this will be with MONOLITHIC kernels. VPS +# server admins should check with their VPS host provider that the iptables +# module is included +# +# For further information and syntax refer to the Port Knocking section of the +# csf readme.txt +# +# Note: Run /etc/csf/csftest.pl to check whether this option will function on +# this server +# +# openport;protocol;timeout;kport1;kport2;kport3[...;kportN],... +# e.g.: 22;TCP;20;100;200;300;400 +PORTKNOCKING = "" + +# Enable PORTKNOCKING logging by iptables +PORTKNOCKING_LOG = "1" + +# Send an email alert if the PORTKNOCKING port is opened. PORTKNOCKING_LOG must +# also be enabled to use this option +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +PORTKNOCKING_ALERT = "0" + +############################################################################### +# SECTION:Log Scanner +############################################################################### +# Log Scanner. This feature will send out an email summary of the log lines of +# each log listed in /etc/csf/csf.logfiles. All lines will be reported unless +# they match a regular expression in /etc/csf/csf.logignore +# +# File globbing is supported for logs listed in /etc/csf/csf.logfiles. However, +# be aware that the more files lfd has to track, the greater the performance +# hit. Note: File globs are only evaluated when lfd is started +# +# Note: lfd builds the report continuously from lines logged after lfd has +# started, so any lines logged when lfd is not running will not be reported +# (e.g. during reboot). If lfd is restarted, then the report will include any +# lines logged during the previous lfd logging period that weren't reported +# +# 1 to enable, 0 to disable +LOGSCANNER = "0" + +# This is the interval each report will be sent based on the logalert.txt +# template +# +# The interval can be set to: +# "hourly" - sent on the hour +# "daily" - sent at midnight (00:00) +# "manual" - sent whenever "csf --logrun" is run. This allows for scheduling +# via cron job +LOGSCANNER_INTERVAL = "hourly" + +# Report Style +# 1 = Separate chronological log lines per log file +# 2 = Simply chronological log of all lines +LOGSCANNER_STYLE = "1" + +# Send the report email even if no log lines reported +# 1 to enable, 0 to disable +LOGSCANNER_EMPTY = "1" + +# Maximum number of lines in the report before it is truncated. This is to +# prevent log lines flooding resulting in an excessively large report. This +# might need to be increased if you choose a daily report +LOGSCANNER_LINES = "5000" + +############################################################################### +# SECTION:Statistics Settings +############################################################################### +# Statistics +# +# Some of the Statistics output requires the gd graphics library and the +# GD::Graph perl module with all dependent modules to be installed for the UI +# for them to be displayed +# +# This option enabled statistical data gathering +ST_ENABLE = "1" + +# This option determines how many iptables log lines to store for reports +ST_IPTABLES = "100" + +# This option indicates whether rDNS and CC lookups are performed at the time +# the log line is recorded (this is not performed when viewing the reports) +# +# Warning: If DROP_IP_LOGGING is enabled and there are frequent iptables hits, +# then enabling this setting could cause serious performance problems +ST_LOOKUP = "0" + +# This option will gather basic system statstics. Through the UI it displays +# various graphs for disk, cpu, memory, network, etc usage over 4 intervals: +# . Hourly (per minute) +# . 24 hours (per minute) +# . 7 days (per minute averaged over an hour) +# . 30 days (per minute averaged over an hour) - user definable +# The data is stored in /var/lib/csf/stats/system and the option requires the +# perl GD::Graph module +# +# Note: Disk graphs do not show on Virtuozzo/OpenVZ servers as the kernel on +# those systems do not store the required information in /proc/diskstats +# On new installations or when enabling this option it will take time for these +# graphs to be populated +ST_SYSTEM = "0" + +# Set the maximum days to collect statistics for. The default is 30 days, the +# more data that is collected the longer it will take for each of the graphs to +# be generated +ST_SYSTEM_MAXDAYS = "30" + +# If ST_SYSTEM is enabled, then these options can collect MySQL statistical +# data. To use this option the server must have the perl modules DBI and +# DBD::mysql installed. +# +# Set this option to "0" to disable MySQL data collection +ST_MYSQL = "0" + +# The following options are for authentication for MySQL data collection. If +# the password is left blank and the user set to "root" then the procedure will +# look for authentication data in /root/.my.cnf. Otherwise, you will need to +# provide a MySQL username and password to collect the data. Any MySQL user +# account can be used +ST_MYSQL_USER = "root" +ST_MYSQL_PASS = "" +ST_MYSQL_HOST = "localhost" + +# If ST_SYSTEM is enabled, then this option can collect Apache statistical data +# The value for PT_APACHESTATUS must be correctly set +ST_APACHE = "0" + +# The following options measure disk write performance using dd (location set +# via the DD setting). It creates a 64MB file called /var/lib/dd_write_test and +# the statistics will plot the MB/s response time of the disk. As this is an IO +# intensive operation, it may not be prudent to run this test too often, so by +# default it is only run every 5 minutes and the result duplicated for each +# intervening minute for the statistics +# +# This is not necessrily a good measure of disk performance, primarily because +# the measurements are for relatively small amounts of data over a small amount +# of time. To properly test disk performance there are a variety of tools +# available that should be run for extended periods of time to obtain an +# accurate measurement. This metric is provided to give an idea of how the disk +# is performing over time +# +# Note: There is a 15 second timeout performing the check +# +# Set to 0 to disable, 1 to enable +ST_DISKW = "0" + +# The number of minutes that elapse between tests. Default is 5, minimum is 1. +ST_DISKW_FREQ = "5" + +# This is the command line passed to dd. If you are familiar with dd, or wish +# to move the output file (of) to a different disk, then you can alter this +# command. Take great care when making any changes to this command as it is +# very easy to overwrite a disk using dd if you make a mistake +ST_DISKW_DD = "if=/dev/zero of=/var/lib/csf/dd_test bs=1MB count=64 conv=fdatasync" + +############################################################################### +# SECTION:Docker Settings +############################################################################### +# This section provides the configuration of iptables rules to allow Docker +# containers to communicate through the host. If the generated rules do not +# work with your setup you will have to use a /etc/csf/csfpost.sh file and add +# your own iptables configuration instead +# +# 1 to enable, 0 to disable +DOCKER = "0" + +# The network device on the host +DOCKER_DEVICE = "docker0" + +# Docker container IPv4 range +DOCKER_NETWORK4 = "172.17.0.0/16" + +# Docker container IPv6 range. IPV6 must be enabled and the IPv6 nat table +# available (see IPv6 section). Leave blank to disable +DOCKER_NETWORK6 = "2001:db8:1::/64" + +############################################################################### +# SECTION:OS Specific Settings +############################################################################### +# Binary locations +IPTABLES = "/sbin/iptables" +IPTABLES_SAVE = "/sbin/iptables-save" +IPTABLES_RESTORE = "/sbin/iptables-restore" +IP6TABLES = "/sbin/ip6tables" +IP6TABLES_SAVE = "/sbin/ip6tables-save" +IP6TABLES_RESTORE = "/sbin/ip6tables-restore" +MODPROBE = "/sbin/modprobe" +IFCONFIG = "/sbin/ifconfig" +SENDMAIL = "/usr/sbin/sendmail" +PS = "/bin/ps" +VMSTAT = "/usr/bin/vmstat" +NETSTAT = "/bin/netstat" +LS = "/bin/ls" +MD5SUM = "/usr/bin/md5sum" +TAR = "/bin/tar" +CHATTR = "/usr/bin/chattr" +UNZIP = "/usr/bin/unzip" +GUNZIP = "/bin/gunzip" +DD = "/bin/dd" +TAIL = "/usr/bin/tail" +GREP = "/bin/grep" +ZGREP = "/usr/bin/zgrep" +IPSET = "/usr/sbin/ipset" +SYSTEMCTL = "/usr/bin/systemctl" +HOST = "/usr/bin/host" +IP = "/sbin/ip" +CURL = "/usr/bin/curl" +WGET = "/usr/bin/wget" + +# Log file locations +# +# File globbing is allowed for the following logs. However, be aware that the +# more files lfd has to track, the greater the performance hit +# +# Note: File globs are only evaluated when lfd is started +# +HTACCESS_LOG = "/var/log/httpd/error_log" +MODSEC_LOG = "/var/log/httpd/error_log" +SSHD_LOG = "/var/log/secure" +SU_LOG = "/var/log/secure" +SUDO_LOG = "/var/log/secure" +FTPD_LOG = "/var/log/messages" +SMTPAUTH_LOG = "/var/log/exim/mainlog" +POP3D_LOG = "/var/log/maillog" +IMAPD_LOG = "/var/log/maillog" +IPTABLES_LOG = "/var/log/messages" +SUHOSIN_LOG = "/var/log/messages" +SMTPRELAY_LOG = "/var/log/exim/mainlog" +BIND_LOG = "/var/log/messages" +SYSLOG_LOG = "/var/log/messages" +WEBMIN_LOG = "/var/log/secure" +DIRECTADMIN_LOG = "/var/log/directadmin/login.log" +DIRECTADMIN_LOG_R = "/var/www/html/roundcube/logs/errors.log" +DIRECTADMIN_LOG_S = "/var/www/html/squirrelmail/data/squirrelmail_access_log" +DIRECTADMIN_LOG_P = "/var/www/html/phpMyAdmin/log/auth.log" + +CUSTOM1_LOG = "/var/log/customlog" +CUSTOM2_LOG = "/var/log/customlog" +CUSTOM3_LOG = "/var/log/customlog" +CUSTOM4_LOG = "/var/log/customlog" +CUSTOM5_LOG = "/var/log/customlog" +CUSTOM6_LOG = "/var/log/customlog" +CUSTOM7_LOG = "/var/log/customlog" +CUSTOM8_LOG = "/var/log/customlog" +CUSTOM9_LOG = "/var/log/customlog" + +# The following are comma separated lists used if LF_SELECT is enabled, +# otherwise they are not used. They are derived from the application returned +# from a regex match in /usr/local/csf/bin/regex.pm +# +# All ports default to tcp blocks. To specify udp or tcp use the format: +# port;protocol,port;protocol,... For example, "53;udp,53;tcp" +PORTS_pop3d = "110,995" +PORTS_imapd = "143,993" +PORTS_htpasswd = "80,443" +PORTS_mod_security = "80,443" +PORTS_mod_qos = "80,443" +PORTS_symlink = "80,443" +PORTS_suhosin = "80,443" +PORTS_cxs = "80,443" +PORTS_bind = "53;udp,53;tcp" +PORTS_ftpd = "20,21" +PORTS_webmin = "10000" +PORTS_smtpauth = "25,465,587" +PORTS_eximsyntax = "25,465,587" +PORTS_directadmin = "2222" +# This list is replaced, if present, by "Port" definitions in +# /etc/ssh/sshd_config +PORTS_sshd = "22" + +# This configuration is for use with generic Linux servers, do not change the +# following settings: +GENERIC = "1" +DIRECTADMIN = "1" + +# For internal use only. You should not enable this option as it could cause +# instability in csf and lfd +DEBUG = "0" +############################################################################### diff --git a/csf/csf.directadmin.ignore b/csf/csf.directadmin.ignore new file mode 100644 index 0000000..bf3fb2a --- /dev/null +++ b/csf/csf.directadmin.ignore @@ -0,0 +1,25 @@ +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +# The following IP addresses will be ignored by all lfd checks +# One IP address per line +# CIDR addressing allowed with a quaded IP (e.g. 192.168.254.0/24) +# Only list IP addresses, not domain names (they will be ignored) +# + +127.0.0.1 diff --git a/csf/csf.directadmin.pignore b/csf/csf.directadmin.pignore new file mode 100644 index 0000000..6d84794 --- /dev/null +++ b/csf/csf.directadmin.pignore @@ -0,0 +1,95 @@ +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +# The following is a list of executables (exe) command lines (cmd) and +# usernames (user) that lfd process tracking will ignore. +# +# You must use the following format: +# +# exe:/full/path/to/file +# user:username +# cmd:command line +# +# Or, perl regular expression matching (regex): +# +# pexe:/full/path/to/file as a perl regex[*] +# puser:username as a perl regex[*] +# pcmd:command line as a perl regex[*] +# +# [*]You must remember to escape characters correctly when using regex's, e.g.: +# pexe:/home/.*/public_html/cgi-bin/script\.cgi +# puser:bob\d.* +# pcmd:/home/.*/command\s\to\smatch\s\.pl\s.* +# +# It is strongly recommended that you use command line ignores very carefully +# as any process can change what is reported to the OS. +# +# For more information see readme.txt + +exe:/bin/dbus-daemon +exe:/sbin/ntpd +exe:/usr/bin/dbus-daemon +exe:/usr/bin/dbus-daemon +exe:/usr/bin/dbus-daemon-1 +exe:/usr/bin/lsmd +exe:/usr/lib/polkit-1/polkitd +exe:/usr/libexec/dovecot/anvil +exe:/usr/libexec/dovecot/imap +exe:/usr/libexec/dovecot/imap-login +exe:/usr/libexec/dovecot/pop3 +exe:/usr/libexec/dovecot/pop3-login +exe:/usr/libexec/dovecot/stats +exe:/usr/libexec/gam_server +exe:/usr/libexec/hald-addon-acpi +exe:/usr/libexec/hald-addon-keyboard +exe:/usr/local/directadmin/dataskq +exe:/usr/local/directadmin/directadmin +exe:/usr/local/libexec/dovecot/imap +exe:/usr/local/libexec/dovecot/imap-login +exe:/usr/local/libexec/dovecot/pop3 +exe:/usr/local/libexec/dovecot/pop3-login +exe:/usr/local/mysql-5.1.54-linux-x86_64/bin/mysqld +exe:/usr/sbin/chronyd +exe:/usr/sbin/exim +exe:/usr/sbin/exim +exe:/usr/sbin/hald +exe:/usr/sbin/httpd +exe:/usr/sbin/mysqld +exe:/usr/sbin/mysqld_safe +exe:/usr/sbin/named +exe:/usr/sbin/nscd +exe:/usr/sbin/ntpd +exe:/usr/sbin/proftpd +exe:/usr/sbin/sshd +exe:/usr/sbin/apache2 +exe:/usr/sbin/mysqld +exe:/lib/systemd/systemd-timesyncd +exe:/usr/local/bin/freshclam +exe:/sbin/rngd +exe:/usr/sbin/mariadbd +exe:/usr/bin/dbus-broker-launch +exe:/usr/bin/dbus-broker + +# Some additional entries that you might want to ignore on DirectAdmin +# servers. +# However, be aware of the security implications under "Process Tracking" in +# the csf readme.txt when using these: +# +#cmd:/bin/sh /usr/bin/mysqld_safe +#cmd:/bin/sh /usr/bin/mysqld_safe --basedir=/usr +#pcmd:MailScanner:.* diff --git a/csf/csf.dirwatch b/csf/csf.dirwatch new file mode 100644 index 0000000..5ab0ba4 --- /dev/null +++ b/csf/csf.dirwatch @@ -0,0 +1,27 @@ +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +# The following should be a list of directories and files that you want to be +# alerted when they change. You must specify full paths for each entry. +# +# lfd uses a simple md5sum match from the output of: +# ls --full-time -lARt [dir] +# on the entry and so will traverse directories if specified. +# +# An example where you might want to use this is /var/spool/cron +# \ No newline at end of file diff --git a/csf/csf.div b/csf/csf.div new file mode 100644 index 0000000..1492dc7 --- /dev/null +++ b/csf/csf.div @@ -0,0 +1,230 @@ + diff --git a/csf/csf.dyndns b/csf/csf.dyndns new file mode 100644 index 0000000..7abf77f --- /dev/null +++ b/csf/csf.dyndns @@ -0,0 +1,31 @@ +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +# The following FQDN's will be allowed through the firewall. This is controlled +# by lfd which checks the DNS resolution of the FQDN and adds the ip address +# into the ALLOWDYNIN and ALLOWDYNOUT iptables chains. lfd will check for IP +# updates every DYNDNS seconds if set. +# +# If the FQDN has multiple A records then all of the IP addresses will be +# processed. If IPV6 is enabled and the perl module Socket6 from cpan.org is +# installed, then all IPv6 AAAA IP address records will also be allowed. +# +# Only list fully qualified domain names (FQDN's) in this file, either on their +# own to allow full access, or using Advanced Allow/Deny Filters (see +# readme.txt) +# diff --git a/csf/csf.fignore b/csf/csf.fignore new file mode 100644 index 0000000..535f543 --- /dev/null +++ b/csf/csf.fignore @@ -0,0 +1,41 @@ +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +# The following is a list of files that lfd directory watching will ignore. You +# must specify the full path to the file +# +# You can also use perl regular expression pattern matching, for example: +# /tmp/clamav.* +# /tmp/.*\.wrk +# +# Remember that you will need to escape special characters (precede them with a +# backslash) such as \. \? +# +# Pattern matching will only occur with strings containing an asterix (*), +# otherwise full file path matching will be applied +# +# You can also add entries to ignore files owner by a particular user by +# preceding it with user:, for example: +# user:bob +# +# Note: files owned by root are ignored + +#/tmp/\.horde +#/tmp/\.horde/.* +#/tmp/yarn--[\d\-\.]+/(node|yarn) +#/tmp/\.spamassassin.* diff --git a/csf/csf.generic.allow b/csf/csf.generic.allow new file mode 100644 index 0000000..19ec008 --- /dev/null +++ b/csf/csf.generic.allow @@ -0,0 +1,30 @@ +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +# The following IP addresses will be allowed through iptables. +# One IP address per line. +# CIDR addressing allowed with a quaded IP (e.g. 192.168.254.0/24). +# Only list IP addresses, not domain names (they will be ignored) +# +# Advanced port+ip filtering allowed with the following format +# tcp/udp|in/out|s/d=port|s/d=ip +# See readme.txt for more information +# +# Note: IP addressess listed in this file will NOT be ignored by lfd, so they +# can still be blocked. If you do not want lfd to block an IP address you must +# add it to csf.ignore diff --git a/csf/csf.generic.conf b/csf/csf.generic.conf new file mode 100644 index 0000000..7df13a4 --- /dev/null +++ b/csf/csf.generic.conf @@ -0,0 +1,2678 @@ +############################################################################### +# SECTION:Initial Settings +############################################################################### +# Testing flag - enables a CRON job that clears iptables incase of +# configuration problems when you start csf. This should be enabled until you +# are sure that the firewall works - i.e. incase you get locked out of your +# server! Then do remember to set it to 0 and restart csf when you're sure +# everything is OK. Stopping csf will remove the line from /etc/crontab +# +# lfd will not start while this is enabled +TESTING = "1" + +# The interval for the crontab in minutes. Since this uses the system clock the +# CRON job will run at the interval past the hour and not from when you issue +# the start command. Therefore an interval of 5 minutes means the firewall +# will be cleared in 0-5 minutes from the firewall start +TESTING_INTERVAL = "5" + +# SECURITY WARNING +# ================ +# +# Unfortunately, syslog and rsyslog allow end-users to log messages to some +# system logs via the same unix socket that other local services use. This +# means that any log line shown in these system logs that syslog or rsyslog +# maintain can be spoofed (they are exactly the same as real log lines). +# +# Since some of the features of lfd rely on such log lines, spoofed messages +# can cause false-positive matches which can lead to confusion at best, or +# blocking of any innocent IP address or making the server inaccessible at +# worst. +# +# Any option that relies on the log entries in the files listed in +# /etc/syslog.conf and /etc/rsyslog.conf should therefore be considered +# vulnerable to exploitation by end-users and scripts run by end-users. +# +# NOTE: Not all log files are affected as they may not use syslog/rsyslog +# +# The option RESTRICT_SYSLOG disables all these features that rely on affected +# logs. These options are: +# LF_SSHD LF_FTPD LF_IMAPD LF_POP3D LF_BIND LF_SUHOSIN LF_SSH_EMAIL_ALERT +# LF_SU_EMAIL_ALERT LF_CONSOLE_EMAIL_ALERT LF_DISTATTACK LF_DISTFTP +# LT_POP3D LT_IMAPD PS_INTERVAL UID_INTERVAL WEBMIN_LOG LF_WEBMIN_EMAIL_ALERT +# PORTKNOCKING_ALERT LF_SUDO_EMAIL_ALERT +# +# This list of options use the logs but are not disabled by RESTRICT_SYSLOG: +# ST_ENABLE SYSLOG_CHECK LOGSCANNER CUSTOM*_LOG +# +# The following options are still enabled by default on new installations so +# that, on balance, csf/lfd still provides expected levels of security: +# LF_SSHD LF_FTPD LF_POP3D LF_IMAPD LF_SSH_EMAIL_ALERT LF_SU_EMAIL_ALERT +# +# If you set RESTRICT_SYSLOG to "0" or "2" and enable any of the options listed +# above, it should be done with the knowledge that any of the those options +# that are enabled could be triggered by spoofed log lines and lead to the +# server being inaccessible in the worst case. If you do not want to take that +# risk you should set RESTRICT_SYSLOG to "1" and those features will not work +# but you will not be protected from the exploits that they normally help block +# +# The recommended setting for RESTRICT_SYSLOG is "3" to restrict who can access +# the syslog/rsyslog unix socket. +# +# For further advice on how to help mitigate these issues, see +# /etc/csf/readme.txt +# +# 0 = Allow those options listed above to be used and configured +# 1 = Disable all the options listed above and prevent them from being used +# 2 = Disable only alerts about this feature and do nothing else +# 3 = Restrict syslog/rsyslog access to RESTRICT_SYSLOG_GROUP ** RECOMMENDED ** +RESTRICT_SYSLOG = "0" + +# The following setting is used if RESTRICT_SYSLOG is set to 3. It restricts +# write access to the syslog/rsyslog unix socket(s). The group must not already +# exists in /etc/group before setting RESTRICT_SYSLOG to 3, so set the option +# to a unique name for the server +# +# You can add users to this group by changing /etc/csf/csf.syslogusers and then +# restarting lfd afterwards. This will create the system group and add the +# users from csf.syslogusers if they exist to that group and will change the +# permissions on the syslog/rsyslog unix socket(s). The socket(s) will be +# monitored and the permissions re-applied should syslog/rsyslog be restarted +# +# Using this option will prevent some legitimate logging, e.g. end-user cron +# job logs +# +# If you want to revert RESTRICT_SYSLOG to another option and disable this +# feature, change the setting of RESTRICT_SYSLOG and then restart lfd and then +# syslog/rsyslog and the unix sockets will be reset +RESTRICT_SYSLOG_GROUP = "mysyslog" + +# This options restricts the ability to modify settings within this file from +# the csf UI. Should the parent control panel be compromised, these restricted +# options could be used to further compromise the server. For this reason we +# recommend leaving this option set to at least "1" and if any of the +# restricted items need to be changed, they are done so from the root shell +# +# 0 = Unrestricted UI +# 1 = Restricted UI +# 2 = Disabled UI +RESTRICT_UI = "1" + +# Enabling auto updates creates a cron job called /etc/cron.d/csf_update which +# runs once per day to see if there is an update to csf+lfd and upgrades if +# available and restarts csf and lfd +# +# You should check for new version announcements at http://blog.configserver.com +AUTO_UPDATES = "1" + +############################################################################### +# SECTION:IPv4 Port Settings +############################################################################### +# Lists of ports in the following comma separated lists can be added using a +# colon (e.g. 30000:35000). + +# Some kernel/iptables setups do not perform stateful connection tracking +# correctly (typically some virtual servers or custom compiled kernels), so a +# SPI firewall will not function correctly. If this happens, LF_SPI can be set +# to 0 to reconfigure csf as a static firewall. +# +# As connection tracking will not be configured, applications that rely on it +# will not function unless all outgoing ports are opened. Therefore, all +# outgoing connections will be allowed once all other tests have completed. So +# TCP_OUT, UDP_OUT and ICMP_OUT will not have any affect. +# +# If you allow incoming DNS lookups you may need to use the following +# directive in the options{} section of your named.conf: +# +# query-source port 53; +# +# This will force incoming DNS traffic only through port 53 +# +# Disabling this option will break firewall functionality that relies on +# stateful packet inspection (e.g. DNAT, PACKET_FILTER) and makes the firewall +# less secure +# +# This option should be set to "1" in all other circumstances +LF_SPI = "1" + +# Allow incoming TCP ports +TCP_IN = "20,21,22,25,53,853,80,110,143,443,465,587,993,995" + +# Allow outgoing TCP ports +TCP_OUT = "20,21,22,25,53,853,80,110,113,443,587,993,995" + +# Allow incoming UDP ports +UDP_IN = "20,21,53,853,80,443" + +# Allow outgoing UDP ports +# To allow outgoing traceroute add 33434:33523 to this list +UDP_OUT = "20,21,53,853,113,123" + +# Allow incoming PING. Disabling PING will likely break external uptime +# monitoring +ICMP_IN = "1" + +# Set the per IP address incoming ICMP packet rate for PING requests. This +# ratelimits PING requests which if exceeded results in silently rejected +# packets. Disable or increase this value if you are seeing PING drops that you +# do not want +# +# To disable rate limiting set to "0", otherwise set according to the iptables +# documentation for the limit module. For example, "1/s" will limit to one +# packet per second +ICMP_IN_RATE = "1/s" + +# Allow outgoing PING +# +# Unless there is a specific reason, this option should NOT be disabled as it +# could break OS functionality +ICMP_OUT = "1" + +# Set the per IP address outgoing ICMP packet rate for PING requests. This +# ratelimits PING requests which if exceeded results in silently rejected +# packets. Disable or increase this value if you are seeing PING drops that you +# do not want +# +# Unless there is a specific reason, this option should NOT be enabled as it +# could break OS functionality +# +# To disable rate limiting set to "0", otherwise set according to the iptables +# documentation for the limit module. For example, "1/s" will limit to one +# packet per second +ICMP_OUT_RATE = "0" + +# For those with PCI Compliance tools that state that ICMP timestamps (type 13) +# should be dropped, you can enable the following option. Otherwise, there +# appears to be little evidence that it has anything to do with a security risk +# and can impact network performance, so should be left disabled by everyone +# else +ICMP_TIMESTAMPDROP = "0" + +############################################################################### +# SECTION:IPv6 Port Settings +############################################################################### +# IPv6: (Requires ip6tables) +# +# Pre v2.6.20 kernels do not perform stateful connection tracking, so a static +# firewall is configured as a fallback instead if IPV6_SPI is set to 0 below +# +# Supported: +# Temporary ACCEPT/DENY, GLOBAL_DENY, GLOBAL_ALLOW, SMTP_BLOCK, LF_PERMBLOCK, +# PACKET_FILTER, Advanced Allow/Deny Filters, RELAY_*, CLUSTER_*, CC6_LOOKUPS, +# SYNFLOOD, LF_NETBLOCK +# +# Supported if CC6_LOOKUPS and CC_LOOKUPS are enabled +# CC_DENY, CC_ALLOW, CC_ALLOW_FILTER, CC_IGNORE, CC_ALLOW_PORTS, CC_DENY_PORTS, +# CC_ALLOW_SMTPAUTH +# +# Supported if ip6tables >= 1.4.3: +# PORTFLOOD, CONNLIMIT +# +# Supported if ip6tables >= 1.4.17 and perl module IO::Socket::INET6 is +# installed: +# MESSENGER DOCKER SMTP_REDIRECT +# +# Not supported: +# ICMP_IN, ICMP_OUT +# +IPV6 = "0" + +# IPv6 uses icmpv6 packets very heavily. By default, csf will allow all icmpv6 +# traffic in the INPUT and OUTPUT chains. However, this could increase the risk +# of icmpv6 attacks. To restrict incoming icmpv6, set to "1" but may break some +# connection types +IPV6_ICMP_STRICT = "0" + +# Pre v2.6.20 kernel must set this option to "0" as no working state module is +# present, so a static firewall is configured as a fallback +# +# A workaround has been added for CentOS/RedHat v5 and custom kernels that do +# not support IPv6 connection tracking by opening ephemeral port range +# 32768:61000. This is only applied if IPV6_SPI is not enabled. This is the +# same workaround implemented by RedHat in the sample default IPv6 rules +# +# As connection tracking will not be configured, applications that rely on it +# will not function unless all outgoing ports are opened. Therefore, all +# outgoing connections will be allowed once all other tests have completed. So +# TCP6_OUT, UDP6_OUT and ICMP6_OUT will not have any affect. +# +# If you allow incoming ipv6 DNS lookups you may need to use the following +# directive in the options{} section of your named.conf: +# +# query-source-v6 port 53; +# +# This will force ipv6 incoming DNS traffic only through port 53 +# +# These changes are not necessary if the SPI firewall is used +IPV6_SPI = "1" + +# Allow incoming IPv6 TCP ports +TCP6_IN = "20,21,22,25,53,853,80,110,143,443,465,587,993,995" + +# Allow outgoing IPv6 TCP ports +TCP6_OUT = "20,21,22,25,53,853,80,110,113,443,587,993,995" + +# Allow incoming IPv6 UDP ports +UDP6_IN = "20,21,53,853,80,443" + +# Allow outgoing IPv6 UDP ports +# To allow outgoing traceroute add 33434:33523 to this list +UDP6_OUT = "20,21,53,853,113,123" + +############################################################################### +# SECTION:General Settings +############################################################################### +# By default, csf will auto-configure iptables to filter all traffic except on +# the loopback device. If you only want iptables rules applied to a specific +# NIC, then list it here (e.g. eth1, or eth+) +ETH_DEVICE = "" + +# By adding a device to this option, ip6tables can be configured only on the +# specified device. Otherwise, ETH_DEVICE and then the default setting will be +# used +ETH6_DEVICE = "" + +# If you don't want iptables rules applied to specific NICs, then list them in +# a comma separated list (e.g "eth1,eth2") +ETH_DEVICE_SKIP = "" + +# This option should be enabled unless the kernel does not support the +# "conntrack" module +# +# To use the deprecated iptables "state" module, change this to 0 +USE_CONNTRACK = "1" + +# Enable ftp helper via the iptables CT target on supporting kernels (v2.6.34+) +# instead of the current method via /proc/sys/net/netfilter/nf_conntrack_helper +# This will also remove the RELATED target from the global state iptables rule +# +# This is not needed (and will be ignored) if LF_SPI/IPV6_SPI is disabled or +# the raw tables do not exist. The USE_CONNTRACK option should be enabled +# +# To enable this option, set it to your FTP server listening port number +# (normally 21), do NOT set it to "1" +USE_FTPHELPER = "0" + +# Check whether syslog is running. Many of the lfd checks require syslog to be +# running correctly. This test will send a coded message to syslog every +# SYSLOG_CHECK seconds. lfd will check SYSLOG_LOG log lines for the coded +# message. If it fails to do so within SYSLOG_CHECK seconds an alert using +# syslogalert.txt is sent +# +# A value of between 300 and 3600 seconds is suggested. Set to 0 to disable +SYSLOG_CHECK = "0" + +# Enable this option if you want lfd to ignore (i.e. don't block) IP addresses +# listed in csf.allow in addition to csf.ignore (the default). This option +# should be used with caution as it would mean that IP's allowed through the +# firewall from infected PC's could launch attacks on the server that lfd +# would ignore +IGNORE_ALLOW = "0" + +# Enable the following option if you want to apply strict iptables rules to DNS +# traffic (i.e. relying on iptables connection tracking). Enabling this option +# could cause DNS resolution issues both to and from the server but could help +# prevent abuse of the local DNS server +DNS_STRICT = "0" + +# Enable the following option if you want to apply strict iptables rules to DNS +# traffic between the server and the nameservers listed in /etc/resolv.conf +# Enabling this option could cause DNS resolution issues both to and from the +# server but could help prevent abuse of the local DNS server +DNS_STRICT_NS = "0" + +# Limit the number of IP's kept in the /etc/csf/csf.deny file +# +# Care should be taken when increasing this value on servers with low memory +# resources or hard limits (such as Virtuozzo/OpenVZ) as too many rules (in the +# thousands) can sometimes cause network slowdown +# +# The value set here is the maximum number of IPs/CIDRs allowed +# if the limit is reached, the entries will be rotated so that the oldest +# entries (i.e. the ones at the top) will be removed and the latest is added. +# The limit is only checked when using csf -d (which is what lfd also uses) +# Set to 0 to disable limiting +# +# For implementations wishing to set this value significantly higher, we +# recommend using the IPSET option +DENY_IP_LIMIT = "200" + +# Limit the number of IP's kept in the temprary IP ban list. If the limit is +# reached the oldest IP's in the ban list will be removed and allowed +# regardless of the amount of time remaining for the block +# Set to 0 to disable limiting +DENY_TEMP_IP_LIMIT = "100" + +# Enable login failure detection daemon (lfd). If set to 0 none of the +# following settings will have any effect as the daemon won't start. +LF_DAEMON = "1" + +# Check whether csf appears to have been stopped and restart if necessary, +# unless TESTING is enabled above. The check is done every 300 seconds +LF_CSF = "1" + +# This option uses IPTABLES_SAVE, IPTABLES_RESTORE and IP6TABLES_SAVE, +# IP6TABLES_RESTORE in two ways: +# +# 1. On a clean server reboot the entire csf iptables configuration is saved +# and then restored where possible to provide a near instant firewall +# startup[*] +# +# 2. On csf restart or lfd reloading tables, CC_* as well as SPAMHAUS, DSHIELD, +# BOGON, TOR are loaded using this method in a fraction of the time than if +# this setting is disabled +# +# [*]Not supported on all OS platforms +# +# Set to "0" to disable this functionality +FASTSTART = "1" + +# This option allows you to use ipset v6+ for the following csf options: +# CC_* and /etc/csf/csf.blocklist, /etc/csf/csf.allow, /etc/csf/csf.deny, +# GLOBAL_DENY, GLOBAL_ALLOW, DYNDNS, GLOBAL_DYNDNS, MESSENGER +# +# ipset will only be used with the above options when listing IPs and CIDRs. +# Advanced Allow Filters and temporary blocks use traditional iptables +# +# Using ipset moves the onus of ip matching against large lists away from +# iptables rules and to a purpose built and optimised database matching +# utility. It also simplifies the switching in of updated lists +# +# To use this option you must have a fully functioning installation of ipset +# installed either via rpm or source from http://ipset.netfilter.org/ +# +# Note: Using ipset has many advantages, some disadvantages are that you will +# no longer see packet and byte counts against IPs and it makes identifying +# blocked/allowed IPs that little bit harder +# +# Note: If you mainly use IP address only entries in csf.deny, you can increase +# the value of DENY_IP_LIMIT significantly if you wish +# +# Note: It's highly unlikely that ipset will function on Virtuozzo/OpenVZ +# containers even if it has been installed +# +# If you find any problems, please post on forums.configserver.com with full +# details of the issue +LF_IPSET = "0" + +# Versions of iptables greater or equal to v1.4.20 should support the --wait +# option. This forces iptables commands that use the option to wait until a +# lock by any other process using iptables completes, rather than simply +# failing +# +# Enabling this feature will add the --wait option to iptables commands +# +# NOTE: The disadvantage of using this option is that any iptables command that +# uses it will hang until the lock is released. This could cause a cascade of +# hung processes trying to issue iptables commands. To try and avoid this issue +# csf uses a last ditch timeout, WAITLOCK_TIMEOUT in seconds, that will trigger +# a failure if reached +WAITLOCK = "0" +WAITLOCK_TIMEOUT = "300" + +# The following sets the hashsize for ipset sets, which must be a power of 2. +# +# Note: Increasing this value will consume more memory for all sets +# Default: "1024" +LF_IPSET_HASHSIZE = "1024" + +# The following sets the maxelem for ipset sets. +# +# Note: Increasing this value will consume more memory for all sets +# Default: "65536" +LF_IPSET_MAXELEM = "65536" + +# If you enable this option then whenever a CLI request to restart csf is used +# lfd will restart csf instead within LF_PARSE seconds +# +# This feature can be helpful for restarting configurations that cannot use +# FASTSTART +LFDSTART = "0" + +# Enable verbose output of iptables commands +VERBOSE = "1" + +# Drop out of order packets and packets in an INVALID state in iptables +# connection tracking +PACKET_FILTER = "1" + +# Perform reverse DNS lookups on IP addresses. (See also CC_LOOKUPS) +LF_LOOKUPS = "1" + +# Custom styling is possible in the csf UI. See the readme.txt for more +# information under "UI skinning and Mobile View" +# +# This option enables the use of custom styling. If the styling fails to work +# correctly, e.g. custom styling does not take into account a change in the +# standard csf UI, then disabling this option will return the standard UI +STYLE_CUSTOM = "0" + +# This option disables the presence of the Mobile View in the csf UI +STYLE_MOBILE = "1" + +############################################################################### +# SECTION:SMTP Settings +############################################################################### +# Block outgoing SMTP except for root, exim and mailman (forces scripts/users +# to use the exim/sendmail binary instead of sockets access). This replaces the +# protection as WHM > Tweak Settings > SMTP Tweaks +# +# This option uses the iptables ipt_owner/xt_owner module and must be loaded +# for it to work. It may not be available on some VPS platforms +# +# Note: Run /etc/csf/csftest.pl to check whether this option will function on +# this server +SMTP_BLOCK = "0" + +# If SMTP_BLOCK is enabled but you want to allow local connections to port 25 +# on the server (e.g. for webmail or web scripts) then enable this option to +# allow outgoing SMTP connections to the loopback device +SMTP_ALLOWLOCAL = "1" + +# This option redirects outgoing SMTP connections destined for remote servers +# for non-bypass users to the local SMTP server to force local relaying of +# email. Such email may require authentication (SMTP AUTH) +SMTP_REDIRECT = "0" + +# This is a comma separated list of the ports to block. You should list all +# ports that exim is configured to listen on +SMTP_PORTS = "25,465,587" + +# Always allow the following comma separated users and groups to bypass +# SMTP_BLOCK +# +# Note: root (UID:0) is always allowed +SMTP_ALLOWUSER = "" +SMTP_ALLOWGROUP = "mail,mailman" + +# This option will only allow SMTP AUTH to be advertised to the IP addresses +# listed in /etc/csf/csf.smtpauth on EXIM mail servers +# +# The additional option CC_ALLOW_SMTPAUTH can be used with this option to +# additionally restrict access to specific countries +# +# This is to help limit attempts at distributed attacks against SMTP AUTH which +# are difficult to achive since port 25 needs to be open to relay email +# +# The reason why this works is that if EXIM does not advertise SMTP AUTH on a +# connection, then SMTP AUTH will not accept logins, defeating the attacks +# without restricting mail relaying +# +# Note: csf and lfd must be restarted if /etc/csf/csf.smtpauth is modified so +# that the lookup file in /etc/exim.smtpauth is regenerated from the +# information from /etc/csf/csf.smtpauth plus any countries listed in +# CC_ALLOW_SMTPAUTH +# +# NOTE: To make this option work you MUST make the modifications to exim.conf +# as explained in "Exim SMTP AUTH Restriction" section in /etc/csf/readme.txt +# after enabling the option here, otherwise this option will not work +# +# To enable this option, set to 1 and make the exim configuration changes +# To disable this option, set to 0 and undo the exim configuration changes +SMTPAUTH_RESTRICT = "0" + +############################################################################### +# SECTION:Port Flood Settings +############################################################################### +# Enable SYN Flood Protection. This option configures iptables to offer some +# protection from tcp SYN packet DOS attempts. You should set the RATE so that +# false-positives are kept to a minimum otherwise visitors may see connection +# issues (check /var/log/messages for *SYNFLOOD Blocked*). See the iptables +# man page for the correct --limit rate syntax +# +# Note: This option should ONLY be enabled if you know you are under a SYN +# flood attack as it will slow down all new connections from any IP address to +# the server if triggered +SYNFLOOD = "0" +SYNFLOOD_RATE = "100/s" +SYNFLOOD_BURST = "150" + +# Connection Limit Protection. This option configures iptables to offer more +# protection from DOS attacks against specific ports. It can also be used as a +# way to simply limit resource usage by IP address to specific server services. +# This option limits the number of concurrent new connections per IP address +# that can be made to specific ports +# +# This feature does not work on servers that do not have the iptables module +# xt_connlimit loaded. Typically, this will be with MONOLITHIC kernels. VPS +# server admins should check with their VPS host provider that the iptables +# module is included +# +# For further information and syntax refer to the Connection Limit Protection +# section of the csf readme.txt +# +# Note: Run /etc/csf/csftest.pl to check whether this option will function on +# this server +CONNLIMIT = "" + +# Port Flood Protection. This option configures iptables to offer protection +# from DOS attacks against specific ports. This option limits the number of +# new connections per time interval that can be made to specific ports +# +# This feature does not work on servers that do not have the iptables module +# ipt_recent loaded. Typically, this will be with MONOLITHIC kernels. VPS +# server admins should check with their VPS host provider that the iptables +# module is included +# +# For further information and syntax refer to the Port Flood Protection +# section of the csf readme.txt +# +# Note: Run /etc/csf/csftest.pl to check whether this option will function on +# this server +PORTFLOOD = "" + +# Outgoing UDP Flood Protection. This option limits outbound UDP packet floods. +# These typically originate from exploit scripts uploaded through vulnerable +# web scripts. Care should be taken on servers that use services that utilise +# high levels of UDP outbound traffic, such as SNMP, so you may need to alter +# the UDPFLOOD_LIMIT and UDPFLOOD_BURST options to suit your environment +# +# We recommend enabling User ID Tracking (UID_INTERVAL) with this feature +UDPFLOOD = "0" +UDPFLOOD_LIMIT = "100/s" +UDPFLOOD_BURST = "500" + +# This is a list of usernames that should not be rate limited, such as "named" +# to prevent bind traffic from being limited. +# +# Note: root (UID:0) is always allowed +UDPFLOOD_ALLOWUSER = "named" + +############################################################################### +# SECTION:Logging Settings +############################################################################### +# Log lfd messages to SYSLOG in addition to /var/log/lfd.log. You must have the +# perl module Sys::Syslog installed to use this feature +SYSLOG = "0" + +# Drop target for incoming iptables rules. This can be set to either DROP or +# REJECT. REJECT will send back an error packet, DROP will not respond at all. +# REJECT is more polite, however it does provide extra information to a hacker +# and lets them know that a firewall is blocking their attempts. DROP hangs +# their connection, thereby frustrating attempts to port scan the server +DROP = "DROP" + +# Drop target for outgoing iptables rules. This can be set to either DROP or +# REJECT as with DROP, however as such connections are from this server it is +# better to REJECT connections to closed ports rather than to DROP them. This +# helps to immediately free up server resources rather than tying them up until +# a connection times out. It also tells the process making the connection that +# it has immediately failed +# +# It is possible that some monolithic kernels may not support the REJECT +# target. If this is the case, csf checks before using REJECT and falls back to +# using DROP, issuing a warning to set this to DROP instead +DROP_OUT = "REJECT" + +# Enable logging of dropped connections to blocked ports to syslog, usually +# /var/log/messages. This option needs to be enabled to use Port Scan Tracking +DROP_LOGGING = "1" + +# Enable logging of dropped incoming connections from blocked IP addresses +# +# This option will be disabled if you enable Port Scan Tracking (PS_INTERVAL) +DROP_IP_LOGGING = "0" + +# Enable logging of dropped outgoing connections +# +# Note: Only outgoing SYN packets for TCP connections are logged, other +# protocols log all packets +# +# We recommend that you enable this option +DROP_OUT_LOGGING = "1" + +# Together with DROP_OUT_LOGGING enabled, this option logs the UID connecting +# out (where available) which can help track abuse +DROP_UID_LOGGING = "1" + +# Only log incoming reserved port dropped connections (0:1023). This can reduce +# the amount of log noise from dropped connections, but will affect options +# such as Port Scan Tracking (PS_INTERVAL) +DROP_ONLYRES = "0" + +# Commonly blocked ports that you do not want logging as they tend to just fill +# up the log file. These ports are specifically blocked (applied to TCP and UDP +# protocols) for incoming connections +DROP_NOLOG = "23,67,68,111,113,135:139,445,500,513,520" + +# Log packets dropped by the packet filtering option PACKET_FILTER +DROP_PF_LOGGING = "0" + +# Log packets dropped by the Connection Limit Protection option CONNLIMIT. If +# this is enabled and Port Scan Tracking (PS_INTERVAL) is also enabled, IP +# addresses breaking the Connection Limit Protection will be blocked +CONNLIMIT_LOGGING = "0" + +# Enable logging of UDP floods. This should be enabled, especially with User ID +# Tracking enabled +UDPFLOOD_LOGGING = "1" + +# Send an alert if log file flooding is detected which causes lfd to skip log +# lines to prevent lfd from looping. If this alert is sent you should check the +# reported log file for the reason for the flooding +LOGFLOOD_ALERT = "0" + +############################################################################### +# SECTION:Reporting Settings +############################################################################### +# By default, lfd will send alert emails using the relevant alert template to +# the To: address configured within that template. Setting the following +# option will override the configured To: field in all lfd alert emails +# +# Leave this option empty to use the To: field setting in each alert template +LF_ALERT_TO = "" + +# By default, lfd will send alert emails using the relevant alert template from +# the From: address configured within that template. Setting the following +# option will override the configured From: field in all lfd alert emails +# +# Leave this option empty to use the From: field setting in each alert template +LF_ALERT_FROM = "" + +# By default, lfd will send all alerts using the SENDMAIL binary. To send using +# SMTP directly, you can set the following to a relaying SMTP server, e.g. +# "127.0.0.1". Leave this setting blank to use SENDMAIL +LF_ALERT_SMTP = "" + +# Block Reporting. lfd can run an external script when it performs and IP +# address block following for example a login failure. The following setting +# is to the full path of the external script which must be executable. See +# readme.txt for format details +# +# Leave this setting blank to disable +BLOCK_REPORT = "" + +# To also run an external script when a temporary block is unblocked. The +# following setting can be the full path of the external script which must be +# executable. See readme.txt for format details +# +# Leave this setting blank to disable +UNBLOCK_REPORT = "" + +# In addition to the standard lfd email alerts, you can additionally enable the +# sending of X-ARF reports (see http://www.xarf.org/specification.html). Only +# block alert messages will be sent. The reports use our schema at: +# https://download.configserver.com/abuse_login-attack_0.2.json +# +# These reports are in a format accepted by many Netblock owners and should +# help them investigate abuse. This option is not designed to automatically +# forward these reports to the Netblock owners and should be checked for +# false-positive blocks before reporting +# +# If available, the report will also include the abuse contact for the IP from +# the Abusix Contact DB: https://abusix.com/contactdb.html +# +# Note: The following block types are not reported through this feature: +# LF_PERMBLOCK, LF_NETBLOCK, LF_DISTATTACK, LF_DISTFTP, RT_*_ALERT +X_ARF = "0" + +# By default, lfd will send emails from the root forwarder. Setting the +# following option will override this +X_ARF_FROM = "" + +# By default, lfd will send emails to the root forwarder. Setting the following +# option will override this +X_ARF_TO = "" + +# If you want to automatically send reports to the abuse contact where found, +# you can enable the following option +# +# Note: You MUST set X_ARF_FROM to a valid email address for this option to +# work. This is so that the abuse contact can reply to the report +# +# However, you should be aware that without manual checking you could be +# reporting innocent IP addresses, including your own clients, yourself and +# your own servers +# +# Additionally, just because a contact address is found, does not mean that +# there is anyone on the end of it reading, processing or acting on such +# reports and you could conceivably reported for sending spam +# +# We do not recommend enabling this option. Abuse reports should be checked and +# verified before being forwarded to the abuse contact +X_ARF_ABUSE = "0" + +############################################################################### +# SECTION:Temp to Perm/Netblock Settings +############################################################################### +# Temporary to Permanent IP blocking. The following enables this feature to +# permanently block IP addresses that have been temporarily blocked more than +# LF_PERMBLOCK_COUNT times in the last LF_PERMBLOCK_INTERVAL seconds. Set +# LF_PERMBLOCK to "1" to enable this feature +# +# Care needs to be taken when setting LF_PERMBLOCK_INTERVAL as it needs to be +# at least LF_PERMBLOCK_COUNT multiplied by the longest temporary time setting +# (TTL) for blocked IPs, to be effective +# +# Set LF_PERMBLOCK to "0" to disable this feature +LF_PERMBLOCK = "1" +LF_PERMBLOCK_INTERVAL = "86400" +LF_PERMBLOCK_COUNT = "4" +LF_PERMBLOCK_ALERT = "1" + +# Permanently block IPs by network class. The following enables this feature +# to permanently block classes of IP address where individual IP addresses +# within the same class LF_NETBLOCK_CLASS have already been blocked more than +# LF_NETBLOCK_COUNT times in the last LF_NETBLOCK_INTERVAL seconds. Set +# LF_NETBLOCK to "1" to enable this feature +# +# This can be an affective way of blocking DDOS attacks launched from within +# the same network class +# +# Valid settings for LF_NETBLOCK_CLASS are "A", "B" and "C", care and +# consideration is required when blocking network classes A or B +# +# Set LF_NETBLOCK to "0" to disable this feature +LF_NETBLOCK = "0" +LF_NETBLOCK_INTERVAL = "86400" +LF_NETBLOCK_COUNT = "4" +LF_NETBLOCK_CLASS = "C" +LF_NETBLOCK_ALERT = "1" + +# Valid settings for LF_NETBLOCK_IPV6 are "/64", "/56", "/48", "/32" and "/24" +# Great care should be taken with IPV6 netblock ranges due to the large number +# of addresses involved +# +# To disable IPv6 netblocks set to "" +LF_NETBLOCK_IPV6 = "" + +############################################################################### +# SECTION:Global Lists/DYNDNS/Blocklists +############################################################################### +# Safe Chain Update. If enabled, all dynamic update chains (GALLOW*, GDENY*, +# SPAMHAUS, DSHIELD, BOGON, CC_ALLOW, CC_DENY, ALLOWDYN*) will create a new +# chain when updating, and insert it into the relevant LOCALINPUT/LOCALOUTPUT +# chain, then flush and delete the old dynamic chain and rename the new chain. +# +# This prevents a small window of opportunity opening when an update occurs and +# the dynamic chain is flushed for the new rules. +# +# This option should not be enabled on servers with long dynamic chains (e.g. +# CC_DENY/CC_ALLOW lists) and low memory. It should also not be enabled on +# Virtuozzo VPS servers with a restricted numiptent value. This is because each +# chain will effectively be duplicated while the update occurs, doubling the +# number of iptables rules +SAFECHAINUPDATE = "0" + +# If you wish to allow access from dynamic DNS records (for example if your IP +# address changes whenever you connect to the internet but you have a dedicated +# dynamic DNS record from the likes of dyndns.org) then you can list the FQDN +# records in csf.dyndns and then set the following to the number of seconds to +# poll for a change in the IP address. If the IP address has changed iptables +# will be updated. +# +# If the FQDN has multiple A records then all of the IP addresses will be +# processed. If IPV6 is enabled, then all IPv6 AAAA IP address records will +# also be allowed. +# +# A setting of 600 would check for IP updates every 10 minutes. Set the value +# to 0 to disable the feature +DYNDNS = "0" + +# To always ignore DYNDNS IP addresses in lfd blocking, set the following +# option to 1 +DYNDNS_IGNORE = "0" + +# The follow Global options allow you to specify a URL where csf can grab a +# centralised copy of an IP allow or deny block list of your own. You need to +# specify the full URL in the following options, i.e.: +# http://www.somelocation.com/allow.txt +# +# The actual retrieval of these IP's is controlled by lfd, so you need to set +# LF_GLOBAL to the interval (in seconds) when you want lfd to retrieve. lfd +# will perform the retrieval when it runs and then again at the specified +# interval. A sensible interval would probably be every 3600 seconds (1 hour). +# A minimum value of 300 is enforced for LF_GLOBAL if enabled +# +# You do not have to specify both an allow and a deny file +# +# You can also configure a global ignore file for IP's that lfd should ignore +LF_GLOBAL = "0" + +GLOBAL_ALLOW = "" +GLOBAL_DENY = "" +GLOBAL_IGNORE = "" + +# Provides the same functionality as DYNDNS but with a GLOBAL URL file. Set +# this to the URL of the file containing DYNDNS entries +GLOBAL_DYNDNS = "" + +# Set the following to the number of seconds to poll for a change in the IP +# address resoved from GLOBAL_DYNDNS +GLOBAL_DYNDNS_INTERVAL = "600" + +# To always ignore GLOBAL_DYNDNS IP addresses in lfd blocking, set the following +# option to 1 +GLOBAL_DYNDNS_IGNORE = "0" + +# Blocklists are controlled by modifying /etc/csf/csf.blocklists +# +# If you don't want BOGON rules applied to specific NICs, then list them in +# a comma separated list (e.g "eth1,eth2") +LF_BOGON_SKIP = "" + +# The following option can be used to select the method csf will use to +# retrieve URL data and files +# +# This can be set to use: +# +# 1. Perl module HTTP::Tiny +# 2. Perl module LWP::UserAgent +# 3. CURL/WGET (set location at the bottom of csf.conf if installed) +# +# HTTP::Tiny is much faster than LWP::UserAgent and is included in the csf +# distribution. LWP::UserAgent may have to be installed manually, but it can +# better support https:// URL's which also needs the LWP::Protocol::https perl +# module +# +# CURL/WGET uses the system binaries if installed but does not always provide +# good feedback when it fails. The script will first look for CURL, if that +# does not exist at the configured location it will then look for WGET +# +# Additionally, 1 or 2 are used and the retrieval fails, then if either CURL or +# WGET are available, an additional attempt will be using CURL/WGET. This is +# useful if the perl distribution has outdated modules that do not support +# modern SSL/TLS implementations +# +# To install the LWP perl modules required: +# +# On rpm based systems: +# +# yum install perl-libwww-perl.noarch perl-LWP-Protocol-https.noarch +# +# On APT based systems: +# +# apt-get install libwww-perl liblwp-protocol-https-perl +# +# Via cpan: +# +# perl -MCPAN -eshell +# cpan> install LWP LWP::Protocol::https +# +# We recommend setting this set to "2" or "3" as upgrades to csf will be +# performed over SSL as well as other URLs used when retrieving external data +# +# "1" = HTTP::Tiny +# "2" = LWP::UserAgent +# "3" = CURL/WGET (set location at the bottom of csf.conf) +URLGET = "2" + +# If you need csf/lfd to use a proxy, then you can set this option to the URL +# of the proxy. The proxy provided will be used for both HTTP and HTTPS +# connections +URLPROXY = "" + +############################################################################### +# SECTION:Country Code Lists and Settings +############################################################################### +# Country Code to CIDR allow/deny. In the following options you can allow or +# deny whole country CIDR ranges. The CIDR blocks are obtained from a selected +# source below. They also display Country Code Country and City for reported IP +# addresses and lookups +# +# There are a number of sources for these databases, before utilising them you +# need to visit each site and ensure you abide by their license provisions +# where stated: + +# 1. MaxMind +# +# MaxMind GeoLite2 Country/City and ASN databases at: +# https://dev.MaxMind.com/geoip/geoip2/geolite2/ +# This feature relies entirely on that service being available +# +# Advantages: This is a one stop shop for all of the databases required for +# these features. They provide a consistent dataset for blocking and reporting +# purposes +# +# Disadvantages: MaxMind require a license key to download their databases. +# This is free of charge, but requires the user to create an account on their +# website to generate the required key: +# +# WARNING: As of 2019-12-29, MaxMind REQUIRES you to create an account on their +# site and to generate a license key to use their databases. See: +# https://www.maxmind.com/en/geolite2/signup +# https://blog.maxmind.com/2019/12/18/significant-changes-to-accessing-and-using-geolite2-databases/ +# +# You MUST set the following to continue using the IP lookup features of csf, +# otherwise an error will be generated and the features will not work. +# Alternatively set CC_SRC below to a different provider +# +# MaxMind License Key: +MM_LICENSE_KEY = "" + +# 2. DB-IP, ipdeny.com, iptoasn.com +# +# Advantages: The ipdeny.com databases form CC blocking are better optimised +# and so are quicker to process and create fewer iptables entries. All of these +# databases are free to download without requiring login or key +# +# Disadvantages: Multiple sources mean that any one of the three could +# interrupt the provision of these features. It may also mean that there are +# inconsistences between them +# +# https://db-ip.com/db/lite.php +# http://ipdeny.com/ +# https://iptoasn.com/ +# http://download.geonames.org/export/dump/readme.txt + +# Set the following to your preferred source: +# +# "1" - MaxMind +# "2" - db-ip, ipdeny, iptoasn +# +# The default is "2" on new installations of csf, or set to "1" to use the +# MaxMind databases after obtaining a license key +CC_SRC = "2" + +# In the following options, specify the the two-letter ISO Country Code(s). +# The iptables rules are for incoming connections only +# +# Additionally, ASN numbers can also be added to the comma separated lists +# below that also list Country Codes. The same WARNINGS for Country Codes apply +# to the use of ASNs. More about Autonomous System Numbers (ASN): +# http://www.iana.org/assignments/as-numbers/as-numbers.xhtml +# ASNs must be listed as ASnnnn (where nnnn is the ASN number) +# +# You should consider using LF_IPSET when using any of the following options +# +# WARNING: These lists are never 100% accurate and some ISP's (e.g. AOL) use +# non-geographic IP address designations for their clients +# +# WARNING: Some of the CIDR lists are huge and each one requires a rule within +# the incoming iptables chain. This can result in significant performance +# overheads and could render the server inaccessible in some circumstances. For +# this reason (amongst others) we do not recommend using these options +# +# WARNING: Due to the resource constraints on VPS servers this feature should +# not be used on such systems unless you choose very small CC zones +# +# WARNING: CC_ALLOW allows access through all ports in the firewall. For this +# reason CC_ALLOW probably has very limited use and CC_ALLOW_FILTER is +# preferred +# +# Each option is a comma separated list of CC's, e.g. "US,GB,DE" +CC_DENY = "" +CC_ALLOW = "" + +# An alternative to CC_ALLOW is to only allow access from the following +# countries but still filter based on the port and packets rules. All other +# connections are dropped +CC_ALLOW_FILTER = "" + +# This option allows access from the following countries to specific ports +# listed in CC_ALLOW_PORTS_TCP and CC_ALLOW_PORTS_UDP +# +# Note: The rules for this feature are inserted after the allow and deny +# rules to still allow blocking of IP addresses +# +# Each option is a comma separated list of CC's, e.g. "US,GB,DE" +CC_ALLOW_PORTS = "" + +# All listed ports should be removed from TCP_IN/UDP_IN to block access from +# elsewhere. This option uses the same format as TCP_IN/UDP_IN +# +# An example would be to list port 21 here and remove it from TCP_IN/UDP_IN +# then only countries listed in CC_ALLOW_PORTS can access FTP +CC_ALLOW_PORTS_TCP = "" +CC_ALLOW_PORTS_UDP = "" + +# This option denies access from the following countries to specific ports +# listed in CC_DENY_PORTS_TCP and CC_DENY_PORTS_UDP +# +# Note: The rules for this feature are inserted after the allow and deny +# rules to still allow allowing of IP addresses +# +# Each option is a comma separated list of CC's, e.g. "US,GB,DE" +CC_DENY_PORTS = "" + +# This option uses the same format as TCP_IN/UDP_IN. The ports listed should +# NOT be removed from TCP_IN/UDP_IN +# +# An example would be to list port 21 here then countries listed in +# CC_DENY_PORTS cannot access FTP +CC_DENY_PORTS_TCP = "" +CC_DENY_PORTS_UDP = "" + +# This Country Code list will prevent lfd from blocking IP address hits for the +# listed CC's +# +# CC_LOOKUPS must be enabled to use this option +CC_IGNORE = "" + +# This Country Code list will only allow SMTP AUTH to be advertised to the +# listed countries in EXIM. This is to help limit attempts at distributed +# attacks against SMTP AUTH which are difficult to achive since port 25 needs +# to be open to relay email +# +# The reason why this works is that if EXIM does not advertise SMTP AUTH on a +# connection, then SMTP AUTH will not accept logins, defeating the attacks +# without restricting mail relaying +# +# This option can generate a very large list of IP addresses that could easily +# severely impact on SMTP (mail) performance, so care must be taken when +# selecting countries and if performance issues ensue +# +# The option SMTPAUTH_RESTRICT must be enabled to use this option +CC_ALLOW_SMTPAUTH = "" + +# These options can control which IP blocks are redirected to the MESSENGER +# service, if it is enabled +# +# If Country Codes are listed in CC_MESSENGER_ALLOW, then only a blocked IP +# that resolves to one of those Country Codes will be redirected to the +# MESSENGER service +# +# If Country Codes are listed in CC_MESSENGER_DENY, then a blocked IP that +# resolves to one of those Country Codes will NOT be redirected to the +# MESSENGER service +# +CC_MESSENGER_ALLOW = "" +CC_MESSENGER_DENY = "" + +# Set this option to a valid CIDR (i.e. 1 to 32) to ignore CIDR blocks smaller +# than this value when implementing CC_DENY/CC_ALLOW/CC_ALLOW_FILTER. This can +# help reduce the number of CC entries and may improve iptables throughput. +# Obviously, this will deny/allow fewer IP addresses depending on how small you +# configure the option +# +# For example, to ignore all CIDR (and single IP) entries small than a /16, set +# this option to "16". Set to "" to block all CC IP addresses +CC_DROP_CIDR = "" + +# Display Country Code and Country for reported IP addresses. This option can +# be configured to use the databases enabled at the top of this section. An +# additional option is also available if you cannot use those databases: +# +# "0" - disable +# "1" - Reports: Country Code and Country +# "2" - Reports: Country Code and Country and Region and City +# "3" - Reports: Country Code and Country and Region and City and ASN +# "4" - Reports: Country Code and Country and Region and City (db-ip.com) +# +# Note: "4" does not use the databases enabled at the top of this section +# directly for lookups. Instead it uses a URL-based lookup from +# https://db-ip.com and so avoids having to download and process the large +# databases. Please visit the https://db-ip.com and read their limitations and +# understand that this option will either cease to function or be removed by us +# if that site is abused or overloaded. ONLY use this option if you have +# difficulties using the databases enabled at the top of this section. This +# option is ONLY for IP lookups, NOT when using the CC_* options above, which +# will continue to use the databases enabled at the top of this section +# +CC_LOOKUPS = "1" + +# Display Country Code and Country for reported IPv6 addresses using the +# databases enabled at the top of this section +# +# "0" - disable +# "1" - enable and report the detail level as specified in CC_LOOKUPS +# +# This option must also be enabled to allow IPv6 support to CC_*, MESSENGER and +# PORTFLOOD +CC6_LOOKUPS = "0" + +# This option tells lfd how often to retrieve the databases for CC_ALLOW, +# CC_ALLOW_FILTER, CC_DENY, CC_IGNORE and CC_LOOKUPS (in days) +CC_INTERVAL = "14" + +############################################################################### +# SECTION:Login Failure Blocking and Alerts +############################################################################### +# The following[*] triggers are application specific. If you set LF_TRIGGER to +# "0" the value of each trigger is the number of failures against that +# application that will trigger lfd to block the IP address +# +# If you set LF_TRIGGER to a value greater than "0" then the following[*] +# application triggers are simply on or off ("0" or "1") and the value of +# LF_TRIGGER is the total cumulative number of failures that will trigger lfd +# to block the IP address +# +# Setting the application trigger to "0" disables it +LF_TRIGGER = "0" + +# If LF_TRIGGER is > "0" then LF_TRIGGER_PERM can be set to "1" to permanently +# block the IP address, or LF_TRIGGER_PERM can be set to a value greater than +# "1" and the IP address will be blocked temporarily for that value in seconds. +# For example: +# LF_TRIGGER_PERM = "1" => the IP is blocked permanently +# LF_TRIGGER_PERM = "3600" => the IP is blocked temporarily for 1 hour +# +# If LF_TRIGGER is "0", then the application LF_[application]_PERM value works +# in the same way as above and LF_TRIGGER_PERM serves no function +LF_TRIGGER_PERM = "1" + +# To only block access to the failed application instead of a complete block +# for an ip address, you can set the following to "1", but LF_TRIGGER must be +# set to "0" with specific application[*] trigger levels also set appropriately +# +# The ports that are blocked can be configured by changing the PORTS_* options +LF_SELECT = "0" + +# Send an email alert if an IP address is blocked by one of the [*] triggers +LF_EMAIL_ALERT = "1" + +# Send an email alert if an IP address is only temporarily blocked by one of +# the [*] triggers +# +# Note: LF_EMAIL_ALERT must still be enabled to get permanent block emails +LF_TEMP_EMAIL_ALERT = "1" + +# [*]Enable login failure detection of sshd connections +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_SSHD = "5" +LF_SSHD_PERM = "1" + +# [*]Enable login failure detection of ftp connections +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_FTPD = "10" +LF_FTPD_PERM = "1" + +# [*]Enable login failure detection of SMTP AUTH connections +LF_SMTPAUTH = "5" +LF_SMTPAUTH_PERM = "1" + +# [*]Enable syntax failure detection of Exim connections +LF_EXIMSYNTAX = "10" +LF_EXIMSYNTAX_PERM = "1" + +# [*]Enable login failure detection of pop3 connections +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_POP3D = "0" +LF_POP3D_PERM = "1" + +# [*]Enable login failure detection of imap connections +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_IMAPD = "0" +LF_IMAPD_PERM = "1" + +# [*]Enable login failure detection of Apache .htpasswd connections +# Due to the often high logging rate in the Apache error log, you might want to +# enable this option only if you know you are suffering from attacks against +# password protected directories +LF_HTACCESS = "5" +LF_HTACCESS_PERM = "1" + +# [*]Enable failure detection of repeated Apache mod_security rule triggers +LF_MODSEC = "5" +LF_MODSEC_PERM = "1" + +# [*]Enable detection of repeated BIND denied requests +# This option should be enabled with care as it will prevent blocked IPs from +# resolving any domains on the server. You might want to set the trigger value +# reasonably high to avoid this +# Example: LF_BIND = "100" +LF_BIND = "0" +LF_BIND_PERM = "1" + +# [*]Enable detection of repeated suhosin ALERTs +# Example: LF_SUHOSIN = "5" +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_SUHOSIN = "0" +LF_SUHOSIN_PERM = "1" + +# [*]Enable detection of repeated cxs ModSecurity mod_security rule triggers +# This option will block IP addresses if cxs detects a hits from the +# ModSecurity rule associated with it +# +# Note: This option takes precedence over LF_MODSEC and removes any hits +# counted towards LF_MODSEC for the cxs rule +# +# This setting should probably set very low, perhaps to 1, if you want to +# effectively block IP addresses for this trigger option +LF_CXS = "0" +LF_CXS_PERM = "1" + +# [*]Enable detection of repeated Apache mod_qos rule triggers +LF_QOS = "0" +LF_QOS_PERM = "1" + +# [*]Enable detection of repeated Apache symlink race condition triggers from +# the Apache patch provided by: +# http://www.mail-archive.com/dev@httpd.apache.org/msg55666.html +# This patch has also been included by cPanel via the easyapache option: +# "Symlink Race Condition Protection" +LF_SYMLINK = "0" +LF_SYMLINK_PERM = "1" + +# [*]Enable login failure detection of webmin connections +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_WEBMIN = "0" +LF_WEBMIN_PERM = "1" + +# Send an email alert if anyone logs in successfully using SSH +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_SSH_EMAIL_ALERT = "1" + +# Send an email alert if anyone uses su to access another account. This will +# send an email alert whether the attempt to use su was successful or not +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_SU_EMAIL_ALERT = "1" + +# Send an email alert if anyone uses sudo to access another account. This will +# send an email alert whether the attempt to use sudo was successful or not +# +# NOTE: This option could become onerous if sudo is used extensively for root +# access by administrators or control panels. It is provided for those where +# this is not the case +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_SUDO_EMAIL_ALERT = "0" + +# Send an email alert if anyone accesses webmin +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_WEBMIN_EMAIL_ALERT = "1" + +# Send an email alert if anyone logs in successfully to root on the console +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_CONSOLE_EMAIL_ALERT = "1" + +# This option will keep track of the number of "File does not exist" errors in +# HTACCESS_LOG. If the number of hits is more than LF_APACHE_404 in LF_INTERVAL +# seconds then the IP address will be blocked +# +# Care should be used with this option as it could generate many +# false-positives, especially Search Bots (use csf.rignore to ignore such bots) +# so only use this option if you know you are under this type of attack +# +# A sensible setting for this would be quite high, perhaps 200 +# +# To disable set to "0" +LF_APACHE_404 = "0" + +# If this option is set to 1 the blocks will be permanent +# If this option is > 1, the blocks will be temporary for the specified number +# of seconds +LF_APACHE_404_PERM = "3600" + +# This option will keep track of the number of "client denied by server +# configuration" errors in HTACCESS_LOG. If the number of hits is more than +# LF_APACHE_403 in LF_INTERVAL seconds then the IP address will be blocked +# +# Care should be used with this option as it could generate many +# false-positives, especially Search Bots (use csf.rignore to ignore such bots) +# so only use this option if you know you are under this type of attack +# +# A sensible setting for this would be quite high, perhaps 200 +# +# To disable set to "0" +LF_APACHE_403 = "0" + +# If this option is set to 1 the blocks will be permanent +# If this option is > 1, the blocks will be temporary for the specified number +# of seconds +LF_APACHE_403_PERM = "3600" + +# This option will keep track of the number of 401 failures in HTACCESS_LOG. +# If the number of hits is more than LF_APACHE_401 in LF_INTERVAL seconds then +# the IP address will be blocked +# +# To disable set to "0" +LF_APACHE_401 = "0" + +# This option is used to determine if the Apache error_log format contains the +# client port after the client IP. In Apache prior to v2.4, this was not the +# case. In Apache v2.4+ the error_log format can be configured using +# ErrorLogFormat, making the port directive optional +# +# Unfortunately v2.4 ErrorLogFormat places the port number after a colon next +# to the client IP by default. This makes determining client IPv6 addresses +# difficult unless we know whether the port is being appended or not +# +# lfd will attempt to autodetect the correct value if this option is set to "0" +# from the httpd binary found in common locations. If it fails to find a binary +# it will be set to "2", unless specified here +# +# The value can be set here explicitly if the autodetection does not work: +# 0 - autodetect +# 1 - no port directive after client IP +# 2 - port directive after client IP +LF_APACHE_ERRPORT = "0" + +# If this option is set to 1 the blocks will be permanent +# If this option is > 1, the blocks will be temporary for the specified number +# of seconds +LF_APACHE_401_PERM = "3600" + +# This option will send an alert if the ModSecurity IP persistent storage grows +# excessively large: https://goo.gl/rGh5sF +# +# More information on cPanel servers here: https://goo.gl/vo6xTE +# +# LF_MODSECIPDB_FILE must be set to the correct location of the database file +# +# The check is performed at lfd startup and then once per hour, the template +# used is modsecipdbalert.txt +# +# Set to "0" to disable this option, otherwise it is the threshold size of the +# file to report in gigabytes, e.g. set to 5 for 5GB +LF_MODSECIPDB_ALERT = "0" + +# This is the location of the persistent IP storage file on the server, e.g.: +# /var/run/modsecurity/data/ip.pag +# /var/cpanel/secdatadir/ip.pag +# /var/cache/modsecurity/ip.pag +# /usr/local/apache/conf/modsec/data/msa/ip.pag +# /var/tmp/ip.pag +# /tmp/ip.pag +LF_MODSECIPDB_FILE = "/var/run/modsecurity/data/ip.pag" + +# System Exploit Checking. This option is designed to perform a series of tests +# to send an alert in case a possible server compromise is detected +# +# To enable this feature set the following to the checking interval in seconds +# (a value of 300 would seem sensible). +# +# To disable set to "0" +LF_EXPLOIT = "300" + +# This comma separated list allows you to ignore tests LF_EXPLOIT performs +# +# For the SUPERUSER check, you can list usernames in csf.suignore to have them +# ignored for that test +# +# Valid tests are: +# SUPERUSER +# +# If you want to ignore a test add it to this as a comma separated list, e.g. +# "SUPERUSER" +LF_EXPLOIT_IGNORE = "" + +# Set the time interval to track login and other LF_ failures within (seconds), +# i.e. LF_TRIGGER failures within the last LF_INTERVAL seconds +LF_INTERVAL = "3600" + +# This is how long the lfd process sleeps (in seconds) before processing the +# log file entries and checking whether other events need to be triggered +LF_PARSE = "5" + +# This is the interval that is used to flush reports of usernames, files and +# pids so that persistent problems continue to be reported, in seconds. +# A value of 3600 seems sensible +LF_FLUSH = "3600" + +# Under some circumstances iptables can fail to include a rule instruction, +# especially if more than one request is made concurrently. In this event, a +# permanent block entry may exist in csf.deny, but not in iptables. +# +# This option instructs csf to deny an already blocked IP address the number +# of times set. The downside, is that there will be multiple entries for an IP +# address in csf.deny and possibly multiple rules for the same IP address in +# iptables. This needs to be taken into consideration when unblocking such IP +# addresses. +# +# Set to "0" to disable this feature. Do not set this too high for the reasons +# detailed above (e.g. "5" should be more than enough) +LF_REPEATBLOCK = "0" + +# By default csf will create both an inbound and outbound blocks from/to an IP +# unless otherwise specified in csf.deny and GLOBAL_DENY. This is the most +# effective way to block IP traffic. This option instructs csf to only block +# inbound traffic from those IP's and so reduces the number of iptables rules, +# but at the expense of less effectiveness. For this reason we recommend +# leaving this option disabled +# +# Set to "0" to disable this feature - the default +LF_BLOCKINONLY = "0" + +############################################################################### +# SECTION:CloudFlare +############################################################################### +# This features provides interaction with the CloudFlare Firewall +# +# As CloudFlare is a reverse proxy, any attacking IP addresses (so far as +# iptables is concerned) come from the CloudFlare IP's. To counter this, an +# Apache module (mod_cloudflare) is available that obtains the true attackers +# IP from a custom HTTP header record (similar functionality is available +# for other HTTP daemons +# +# However, despite now knowing the true attacking IP address, iptables cannot +# be used to block that IP as the traffic is still coming from the CloudFlare +# servers +# +# CloudFlare have provided a Firewall feature within the user account where +# rules can be added to block, challenge or whitelist IP addresses +# +# Using the CloudFlare API, this feature adds and removes attacking IPs from +# that firewall and provides CLI (and via the UI) additional commands +# +# See /etc/csf/readme.txt for more information about this feature and the +# restrictions for its use BEFORE enabling this feature +CF_ENABLE = "0" + +# This can be set to either "block" or "challenge" (see CloudFlare docs) +CF_BLOCK = "block" + +# This setting determines how long the temporary block will apply within csf +# and CloudFlare, keeping them in sync +# +# Block duration in seconds - overrides perm block or time of individual blocks +# in lfd for block triggers +CF_TEMP = "3600" + +############################################################################### +# SECTION:Directory Watching & Integrity +############################################################################### +# Enable Directory Watching. This enables lfd to check /tmp and /dev/shm +# directories for suspicious files, i.e. script exploits. If a suspicious +# file is found an email alert is sent. One alert per file per LF_FLUSH +# interval is sent +# +# To enable this feature set the following to the checking interval in seconds. +# To disable set to "0" +LF_DIRWATCH = "300" + +# To remove any suspicious files found during directory watching, enable the +# following. These files will be appended to a tarball in +# /var/lib/csf/suspicious.tar +LF_DIRWATCH_DISABLE = "0" + +# This option allows you to have lfd watch a particular file or directory for +# changes and should they change and email alert using watchalert.txt is sent +# +# To enable this feature set the following to the checking interval in seconds +# (a value of 60 would seem sensible) and add your entries to csf.dirwatch +# +# Set to disable set to "0" +LF_DIRWATCH_FILE = "0" + +# System Integrity Checking. This enables lfd to compare md5sums of the +# servers OS binary application files from the time when lfd starts. If the +# md5sum of a monitored file changes an alert is sent. This option is intended +# as an IDS (Intrusion Detection System) and is the last line of detection for +# a possible root compromise. +# +# There will be constant false-positives as the servers OS is updated or +# monitored application binaries are updated. However, unexpected changes +# should be carefully inspected. +# +# Modified files will only be reported via email once. +# +# To enable this feature set the following to the checking interval in seconds +# (a value of 3600 would seem sensible). This option may increase server I/O +# load onto the server as it checks system binaries. +# +# To disable set to "0" +LF_INTEGRITY = "3600" + +############################################################################### +# SECTION:Distributed Attacks +############################################################################### +# Distributed Account Attack. This option will keep track of login failures +# from distributed IP addresses to a specific application account. If the +# number of failures matches the trigger value above, ALL of the IP addresses +# involved in the attack will be blocked according to the temp/perm rules above +# +# Tracking applies to LF_SSHD, LF_FTPD, LF_SMTPAUTH, LF_POP3D, LF_IMAPD, +# LF_HTACCESS +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_DISTATTACK = "0" + +# Set the following to the minimum number of unique IP addresses that trigger +# LF_DISTATTACK +LF_DISTATTACK_UNIQ = "2" + +# Distributed FTP Logins. This option will keep track of successful FTP logins. +# If the number of successful logins to an individual account is at least +# LF_DISTFTP in LF_DIST_INTERVAL from at least LF_DISTFTP_UNIQ IP addresses, +# then all of the IP addresses will be blocked +# +# This option can help mitigate the common FTP account compromise attacks that +# use a distributed network of zombies to deface websites +# +# A sensible setting for this might be 5, depending on how many different +# IP addresses you expect to an individual FTP account within LF_DIST_INTERVAL +# +# To disable set to "0" +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_DISTFTP = "0" + +# Set the following to the minimum number of unique IP addresses that trigger +# LF_DISTFTP. LF_DISTFTP_UNIQ must be <= LF_DISTFTP for this to work +LF_DISTFTP_UNIQ = "3" + +# If this option is set to 1 the blocks will be permanent +# If this option is > 1, the blocks will be temporary for the specified number +# of seconds +LF_DISTFTP_PERM = "1" + +# Send an email alert if LF_DISTFTP is triggered +LF_DISTFTP_ALERT = "1" + +# Distributed SMTP Logins. This option will keep track of successful SMTP +# logins. If the number of successful logins to an individual account is at +# least LF_DISTSMTP in LF_DIST_INTERVAL from at least LF_DISTSMTP_UNIQ IP +# addresses, then all of the IP addresses will be blocked. These options only +# apply to the exim MTA +# +# This option can help mitigate the common SMTP account compromise attacks that +# use a distributed network of zombies to send spam +# +# A sensible setting for this might be 5, depending on how many different +# IP addresses you expect to an individual SMTP account within LF_DIST_INTERVAL +# +# To disable set to "0" +LF_DISTSMTP = "0" + +# Set the following to the minimum number of unique IP addresses that trigger +# LF_DISTSMTP. LF_DISTSMTP_UNIQ must be <= LF_DISTSMTP for this to work +LF_DISTSMTP_UNIQ = "3" + +# If this option is set to 1 the blocks will be permanent +# If this option is > 1, the blocks will be temporary for the specified number +# of seconds +LF_DISTSMTP_PERM = "1" + +# Send an email alert if LF_DISTSMTP is triggered +LF_DISTSMTP_ALERT = "1" + +# This is the interval during which a distributed FTP or SMTP attack is +# measured +LF_DIST_INTERVAL = "300" + +# If LF_DISTFTP or LF_DISTSMTP is triggered, then if the following contains the +# path to a script, it will run the script and pass the following as arguments: +# +# LF_DISTFTP/LF_DISTSMTP +# account name +# log file text +# +# The action script must have the execute bit and interpreter (shebang) set +LF_DIST_ACTION = "" + +############################################################################### +# SECTION:Login Tracking +############################################################################### +# Block POP3 logins if greater than LT_POP3D times per hour per account per IP +# address (0=disabled) +# +# This is a temporary block for the rest of the hour, afterwhich the IP is +# unblocked +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LT_POP3D = "0" + +# Block IMAP logins if greater than LT_IMAPD times per hour per account per IP +# address (0=disabled) - not recommended for IMAP logins due to the ethos +# within which IMAP works. If you want to use this, setting it quite high is +# probably a good idea +# +# This is a temporary block for the rest of the hour, afterwhich the IP is +# unblocked +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LT_IMAPD = "0" + +# Send an email alert if an account exceeds LT_POP3D/LT_IMAPD logins per hour +# per IP +LT_EMAIL_ALERT = "1" + +# If LF_PERMBLOCK is enabled but you do not want this to apply to +# LT_POP3D/LT_IMAPD, then enable this option +LT_SKIPPERMBLOCK = "0" + +############################################################################### +# SECTION:Connection Tracking +############################################################################### +# Connection Tracking. This option enables tracking of all connections from IP +# addresses to the server. If the total number of connections is greater than +# this value then the offending IP address is blocked. This can be used to help +# prevent some types of DOS attack. +# +# Care should be taken with this option. It's entirely possible that you will +# see false-positives. Some protocols can be connection hungry, e.g. FTP, IMAPD +# and HTTP so it could be quite easy to trigger, especially with a lot of +# closed connections in TIME_WAIT. However, for a server that is prone to DOS +# attacks this may be very useful. A reasonable setting for this option might +# be around 300. +# +# To disable this feature, set this to 0 +CT_LIMIT = "0" + +# Connection Tracking interval. Set this to the the number of seconds between +# connection tracking scans +CT_INTERVAL = "30" + +# Send an email alert if an IP address is blocked due to connection tracking +CT_EMAIL_ALERT = "1" + +# If you want to make IP blocks permanent then set this to 1, otherwise blocks +# will be temporary and will be cleared after CT_BLOCK_TIME seconds +CT_PERMANENT = "0" + +# If you opt for temporary IP blocks for CT, then the following is the interval +# in seconds that the IP will remained blocked for (e.g. 1800 = 30 mins) +CT_BLOCK_TIME = "1800" + +# If you don't want to count the TIME_WAIT state against the connection count +# then set the following to "1" +CT_SKIP_TIME_WAIT = "0" + +# If you only want to count specific states (e.g. SYN_RECV) then add the states +# to the following as a comma separated list. E.g. "SYN_RECV,TIME_WAIT" +# +# Leave this option empty to count all states against CT_LIMIT +CT_STATES = "" + +# If you only want to count specific ports (e.g. 80,443) then add the ports +# to the following as a comma separated list. E.g. "80,443" +# +# Leave this option empty to count all ports against CT_LIMIT +CT_PORTS = "" + +# If the total number of connections from a class C subnet is greater than this +# value then the offending subnet is blocked according to the other CT_* +# settings +# +# This option can be used to help prevent some types of DOS attack where a +# range of IP's between x.y.z.1-255 has connected to the server +# +# If you use a reverse proxy service such as Cloudflare you should not enable +# this option, or should exclude the ports that you have proxied in CT_PORTS +# +# To disable this feature, set this to 0 +CT_SUBNET_LIMIT = "0" + +############################################################################### +# SECTION:Process Tracking +############################################################################### +# Process Tracking. This option enables tracking of user and nobody processes +# and examines them for suspicious executables or open network ports. Its +# purpose is to identify potential exploit processes that are running on the +# server, even if they are obfuscated to appear as system services. If a +# suspicious process is found an alert email is sent with relevant information. +# It is then the responsibility of the recipient to investigate the process +# further as the script takes no further action +# +# The following is the number of seconds a process has to be active before it +# is inspected. If you set this time too low, then you will likely trigger +# false-positives with CGI or PHP scripts. +# Set the value to 0 to disable this feature +PT_LIMIT = "60" + +# How frequently processes are checked in seconds +PT_INTERVAL = "60" + +# If you want process tracking to highlight php or perl scripts that are run +# through apache then disable the following, +# i.e. set it to 0 +# +# While enabling this setting will reduce false-positives, having it set to 0 +# does provide better checking for exploits running on the server +PT_SKIP_HTTP = "0" + +# lfd will report processes, even if they're listed in csf.pignore, if they're +# tagged as (deleted) by Linux. This information is provided in Linux under +# /proc/PID/exe. A (deleted) process is one that is running a binary that has +# the inode for the file removed from the file system directory. This usually +# happens when the binary has been replaced due to an upgrade for it by the OS +# vendor or another third party (e.g. cPanel). You need to investigate whether +# this is indeed the case to be sure that the original binary has not been +# replaced by a rootkit or is running an exploit. +# +# Note: If a deleted executable process is detected and reported then lfd will +# not report children of the parent (or the parent itself if a child triggered +# the report) if the parent is also a deleted executable process +# +# To stop lfd reporting such process you need to restart the daemon to which it +# belongs and therefore run the process using the replacement binary (presuming +# one exists). This will normally mean running the associated startup script in +# /etc/init.d/ +# +# If you do want lfd to report deleted binary processes, set to 1 +PT_DELETED = "0" + +# If a PT_DELETED event is triggered, then if the following contains the path to +# a script, it will be run in a child process and passed the executable, pid, +# account for the process, and parent pid +# +# The action script must have the execute bit and interpreter (shebang) set. An +# example is provided in /usr/local/csf/bin/pt_deleted_action.pl +# +# WARNING: Make sure you read and understand the potential security +# implications of such processes in PT_DELETED above before simply restarting +# such processes with a script +PT_DELETED_ACTION = "" + +# User Process Tracking. This option enables the tracking of the number of +# process any given account is running at one time. If the number of processes +# exceeds the value of the following setting an email alert is sent with +# details of those processes. If you specify a user in csf.pignore it will be +# ignored +# +# Set to 0 to disable this feature +PT_USERPROC = "10" + +# This User Process Tracking option sends an alert if any user process exceeds +# the virtual memory usage set (MB). To ignore specific processes or users use +# csf.pignore +# +# Set to 0 to disable this feature +PT_USERMEM = "512" + +# This User Process Tracking option sends an alert if any user process exceeds +# the RSS memory usage set (MB) - RAM used, not virtual. To ignore specific +# processes or users use csf.pignore +# +# Set to 0 to disable this feature +PT_USERRSS = "256" + +# This User Process Tracking option sends an alert if any linux user process +# exceeds the time usage set (seconds). To ignore specific processes or users +# use csf.pignore +# +# Set to 0 to disable this feature +PT_USERTIME = "1800" + +# If this option is set then processes detected by PT_USERMEM, PT_USERTIME or +# PT_USERPROC are killed +# +# Warning: We don't recommend enabling this option unless absolutely necessary +# as it can cause unexpected problems when processes are suddenly terminated. +# It can also lead to system processes being terminated which could cause +# stability issues. It is much better to leave this option disabled and to +# investigate each case as it is reported when the triggers above are breached +# +# Note: Processes that are running deleted excecutables (see PT_DELETED) will +# not be killed by lfd +PT_USERKILL = "0" + +# If you want to disable email alerts if PT_USERKILL is triggered, then set +# this option to 0 +PT_USERKILL_ALERT = "1" + +# If a PT_* event is triggered, then if the following contains the path to +# a script, it will be run in a child process and passed the PID(s) of the +# process(es) in a comma separated list. +# +# The action script must have the execute bit and interpreter (shebang) set +PT_USER_ACTION = "" + +# Check the PT_LOAD_AVG minute Load Average (can be set to 1 5 or 15 and +# defaults to 5 if set otherwise) on the server every PT_LOAD seconds. If the +# load average is greater than or equal to PT_LOAD_LEVEL then an email alert is +# sent. lfd then does not report subsequent high load until PT_LOAD_SKIP +# seconds has passed to prevent email floods. +# +# Set PT_LOAD to "0" to disable this feature +PT_LOAD = "30" +PT_LOAD_AVG = "5" +PT_LOAD_LEVEL = "6" +PT_LOAD_SKIP = "3600" + +# This is the Apache Server Status URL used in the email alert. Requires the +# Apache mod_status module to be installed and configured correctly +PT_APACHESTATUS = "http://127.0.0.1/server-status" + +# If a PT_LOAD event is triggered, then if the following contains the path to +# a script, it will be run in a child process. For example, the script could +# contain commands to terminate and restart httpd, php, exim, etc incase of +# looping processes. The action script must have the execute bit an +# interpreter (shebang) set +PT_LOAD_ACTION = "" + +# Fork Bomb Protection. This option checks the number of processes with the +# same session id and if greater than the value set, the whole session tree is +# terminated and an alert sent +# +# You can see an example of common session id processes on most Linux systems +# using: "ps axf -O sid" +# +# On cPanel servers, PT_ALL_USERS should be enabled to use this option +# effectively +# +# This option will check root owned processes. Session id 0 and 1 will always +# be ignored as they represent kernel and init processes. csf.pignore will be +# honoured, but bear in mind that a session tree can contain a variety of users +# and executables +# +# Care needs to be taken to ensure that this option only detects runaway fork +# bombs, so should be set higher than any session tree is likely to get (e.g. +# httpd could have 100s of legitimate children on very busy systems). A +# sensible starting point on most servers might be 250 +PT_FORKBOMB = "0" + +# Terminate hung SSHD sessions. When under an SSHD login attack, SSHD processes +# are often left hanging after their connecting IP addresses have been blocked +# +# This option will terminate the SSH processes created by the blocked IP. This +# option is preferred over PT_SSHDHUNG +PT_SSHDKILL = "0" + +# This option will terminate all processes with the cmdline of "sshd: unknown +# [net]" or "sshd: unknown [priv]" if they have been running for more than 60 +# seconds +PT_SSHDHUNG = "0" + +############################################################################### +# SECTION:Port Scan Tracking +############################################################################### +# Port Scan Tracking. This feature tracks port blocks logged by iptables to +# syslog. If an IP address generates a port block that is logged more than +# PS_LIMIT within PS_INTERVAL seconds, the IP address will be blocked. +# +# This feature could, for example, be useful for blocking hackers attempting +# to access the standard SSH port if you have moved it to a port other than 22 +# and have removed 22 from the TCP_IN list so that connection attempts to the +# old port are being logged +# +# This feature blocks all iptables blocks from the iptables logs, including +# repeated attempts to one port or SYN flood blocks, etc +# +# Note: This feature will only track iptables blocks from the log file set in +# IPTABLES_LOG below and if you have DROP_LOGGING enabled. However, it will +# cause redundant blocking with DROP_IP_LOGGING enabled +# +# Warning: It's possible that an elaborate DDOS (i.e. from multiple IP's) +# could very quickly fill the iptables rule chains and cause a DOS in itself. +# The DENY_IP_LIMIT should help to mitigate such problems with permanent blocks +# and the DENY_TEMP_IP_LIMIT with temporary blocks +# +# Set PS_INTERVAL to "0" to disable this feature. A value of between 60 and 300 +# would be sensible to enable this feature +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +PS_INTERVAL = "0" +PS_LIMIT = "10" + +# You can specify the ports and/or port ranges that should be tracked by the +# Port Scan Tracking feature. The following setting is a comma separated list +# of those ports and uses the same format as TCP_IN. The setting of +# 0:65535,ICMP,INVALID,OPEN,BRD covers all ports +# +# Special values are: +# ICMP - include ICMP blocks (see ICMP_*) +# INVALID - include INVALID blocks (see PACKET_FILTER) +# OPEN - include TCP_IN and UDP_IN open port blocks - *[proto]_IN Blocked* +# BRD - include UDP Broadcast IPs, otherwise they are ignored +PS_PORTS = "0:65535,ICMP" + +# To specify how many different ports qualifies as a Port Scan you can increase +# the following from the default value of 1. The risk in doing so will mean +# that persistent attempts to attack a specific closed port will not be +# detected and blocked +PS_DIVERSITY = "1" + +# You can select whether IP blocks for Port Scan Tracking should be temporary +# or permanent. Set PS_PERMANENT to "0" for temporary and "1" for permanent +# blocking. If set to "0" PS_BLOCK_TIME is the amount of time in seconds to +# temporarily block the IP address for +PS_PERMANENT = "0" +PS_BLOCK_TIME = "3600" + +# Set the following to "1" to enable Port Scan Tracking email alerts, set to +# "0" to disable them +PS_EMAIL_ALERT = "1" + +############################################################################### +# SECTION:User ID Tracking +############################################################################### +# User ID Tracking. This feature tracks UID blocks logged by iptables to +# syslog. If a UID generates a port block that is logged more than UID_LIMIT +# times within UID_INTERVAL seconds, an alert will be sent +# +# Note: This feature will only track iptables blocks from the log file set in +# IPTABLES_LOG and if DROP_OUT_LOGGING and DROP_UID_LOGGING are enabled. +# +# To ignore specific UIDs list them in csf.uidignore and then restart lfd +# +# Set UID_INTERVAL to "0" to disable this feature. A value of between 60 and 300 +# would be sensible to enable this feature +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +UID_INTERVAL = "0" +UID_LIMIT = "10" + +# You can specify the ports and/or port ranges that should be tracked by the +# User ID Tracking feature. The following setting is a comma separated list +# of those ports and uses the same format as TCP_OUT. The default setting of +# 0:65535,ICMP covers all ports +UID_PORTS = "0:65535,ICMP" + +############################################################################### +# SECTION:Account Tracking +############################################################################### +# Account Tracking. The following options enable the tracking of modifications +# to the accounts on a server. If any of the enabled options are triggered by +# a modifications to an account, an alert email is sent. Only the modification +# is reported. The cause of the modification will have to be investigated +# manually +# +# You can set AT_ALERT to the following: +# 0 = disable this feature +# 1 = enable this feature for all accounts +# 2 = enable this feature only for superuser accounts (UID = 0, e.g. root, etc) +# 3 = enable this feature only for the root account +AT_ALERT = "2" + +# This options is the interval between checks in seconds +AT_INTERVAL = "60" + +# Send alert if a new account is created +AT_NEW = "1" + +# Send alert if an existing account is deleted +AT_OLD = "1" + +# Send alert if an account password has changed +AT_PASSWD = "1" + +# Send alert if an account uid has changed +AT_UID = "1" + +# Send alert if an account gid has changed +AT_GID = "1" + +# Send alert if an account login directory has changed +AT_DIR = "1" + +# Send alert if an account login shell has changed +AT_SHELL = "1" + +############################################################################### +# SECTION:Integrated User Interface +############################################################################### +# Integrated User Interface. This feature provides a HTML UI to csf and lfd, +# without requiring a control panel or web server. The UI runs as a sub process +# to the lfd daemon +# +# As it runs under the root account and successful login provides root access +# to the server, great care should be taken when configuring and using this +# feature. There are additional restrictions to enhance secure access to the UI +# +# See readme.txt for more information about using this feature BEFORE enabling +# it for security and access reasons +# +# 1 to enable, 0 to disable +UI = "0" + +# Set this to the port that want to bind this service to. You should configure +# this port to be >1023 and different from any other port already being used +# +# Do NOT enable access to this port in TCP_IN, instead only allow trusted IP's +# to the port using Advanced Allow Filters (see readme.txt) +UI_PORT = "6666" + +# Optionally set the IP address to bind to. Normally this should be left blank +# to bind to all IP addresses on the server. +# +# If the server is configured for IPv6 but the IP to bind to is IPv4, then the +# IP address MUST use the IPv6 representation. For example 1.2.3.4 must use +# ::ffff:1.2.3.4 +# +# Leave blank to bind to all IP addresses on the server +UI_IP = "" + +# This should be a secure, hard to guess username +# +# This must be changed from the default +UI_USER = "username" + +# This should be a secure, hard to guess password. That is, at least 8 +# characters long with a mixture of upper and lowercase characters plus +# numbers and non-alphanumeric characters +# +# This must be changed from the default +UI_PASS = "password" + +# This is the login session timeout. If there is no activity for a logged in +# session within this number of seconds, the session will timeout and a new +# login will be required +# +# For security reasons, you should always keep this option low (i.e 60-300) +UI_TIMEOUT = "300" + +# This is the maximum concurrent connections allowed to the server. The default +# value should be sufficient +UI_CHILDREN = "5" + +# The number of login retries allowed within a 24 hour period. A successful +# login from the IP address will clear the failures +# +# For security reasons, you should always keep this option low (i.e 0-10) +UI_RETRY = "5" + +# If enabled, this option will add the connecting IP address to the file +# /etc/csf/ui/ui.ban after UI_RETRY login failures. The IP address will not be +# able to login to the UI while it is listed in this file. The UI_BAN setting +# does not refer to any of the csf/lfd allow or ignore files, e.g. csf.allow, +# csf.ignore, etc. +# +# For security reasons, you should always enable this option +UI_BAN = "1" + +# If enabled, only IPs (or CIDR's) listed in the file /etc/csf/ui/ui.allow will +# be allowed to login to the UI. The UI_ALLOW setting does not refer to any of +# the csf/lfd allow or ignore files, e.g. csf.allow, csf.ignore, etc. +# +# For security reasons, you should always enable this option and use ui.allow +UI_ALLOW = "1" + +# If enabled, this option will trigger an iptables block through csf after +# UI_RETRY login failures +# +# 0 = no block;1 = perm block;nn=temp block for nn secs +UI_BLOCK = "1" + +# This controls what email alerts are sent with regards to logins to the UI. It +# uses the uialert.txt template +# +# 4 = login success + login failure/ban/block + login attempts +# 3 = login success + login failure/ban/block +# 2 = login failure/ban/block +# 1 = login ban/block +# 0 = disabled +UI_ALERT = "4" + +# This is the SSL cipher list that the Integrated UI will negotiate from +UI_CIPHER = "ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:-LOW:-SSLv2:-EXP:!kEDH" + +# This is the SSL protocol version used. See IO::Socket::SSL if you wish to +# change this and to understand the implications of changing it +UI_SSL_VERSION = "SSLv23:!SSLv3:!SSLv2" + +# If cxs is installed then enabling this option will provide a dropdown box to +# switch between applications +UI_CXS = "0" + +# There is a modified installation of ConfigServer Explorer (cse) provided with +# the csf distribution. If this option is enabled it will provide a dropdown +# box to switch between applications +UI_CSE = "0" + +############################################################################### +# SECTION:Messenger service +############################################################################### +# Messenger service. This feature allows the display of a message to a blocked +# connecting IP address to inform the user that they are blocked in the +# firewall. This can help when users get themselves blocked, e.g. due to +# multiple login failures. The service is provided by two daemons running on +# ports providing either an HTML or TEXT message +# +# This feature does not work on servers that do not have the iptables module +# ipt_REDIRECT loaded. Typically, this will be with MONOLITHIC kernels. VPS +# server admins should check with their VPS host provider that the iptables +# module is included +# +# IPv6 will need the IO::Socket::INET6 perl module +# +# For further information on features and limitations refer to the csf +# readme.txt +# +# Note: Run /etc/csf/csftest.pl to check whether this option will function on +# this server +# +# 1 to enable, 0 to disable +MESSENGER = "0" + +# Provide this service to temporary IP address blocks +MESSENGER_TEMP = "1" + +# Provide this service to permanent IP address blocks +MESSENGER_PERM = "1" + +# User account to run the service servers under. We recommend creating a +# specific non-priv, non-shell account for this purpose +# +# Note: When using MESSENGERV2, this account must NOT be a valid control panel +# account, it must be created manually as explained in the csf readme.txt +MESSENGER_USER = "csf" + +# This option points to the file(s) containing the Apache VirtualHost SSL +# definitions. This can be a file glob if there are multiple files to search. +# Only Apache v2 SSL VirtualHost definitions are supported +# +# This is used by MESSENGERV1 and MESSENGERV2 only +MESSENGER_HTTPS_CONF = "/etc/httpd/conf.d/ssl.conf" + +# The following options can be specified to provide a default fallback +# certificate to be used if either SNI is not supported or a hosted domain does +# not have an SSL certificate. If a fallback is not provided, one of the certs +# obtained from MESSENGER_HTTPS_CONF will be used +# +# This is used by MESSENGERV1 and MESSENGERV2 only +MESSENGER_HTTPS_KEY = "/etc/pki/tls/private/localhost.key" +MESSENGER_HTTPS_CRT = "/etc/pki/tls/certs/localhost.crt" + +# Set this to the port that will receive the HTTPS HTML message. You should +# configure this port to be >1023 and different from the TEXT and HTML port. Do +# NOT enable access to this port in TCP_IN. This option requires the perl +# module IO::Socket::SSL at a version level that supports SNI (1.83+). +# Additionally the version of openssl on the server must also support SNI +# +# The option uses existing SSL certificates on the server for each domain to +# maintain a secure connection without browser warnings. It uses SNI to choose +# the correct certificate to use for each client connection +# +# Warning: On some servers the amount of memory used by the HTTPS MESSENGER +# service can become significant depending on various factors associated with +# the use of IO::Socket::SSL including the number of domains and certificates +# served. This is normally only an issue if using MESSENGERV1 +MESSENGER_HTTPS = "8887" + +# This comma separated list are the HTTPS HTML ports that will be redirected +# for the blocked IP address. If you are using per application blocking +# (LF_TRIGGER) then only the relevant block port will be redirected to the +# messenger port +# +# Recommended setting "443" plus any end-user control panel SSL ports. So, for +# cPanel: "443,2083,2096" +MESSENGER_HTTPS_IN = "443" + +# Set this to the port that will receive the HTML message. You should configure +# this port to be >1023 and different from the TEXT port. Do NOT enable access +# to this port in TCP_IN +MESSENGER_HTML = "8888" + +# This comma separated list are the HTML ports that will be redirected for the +# blocked IP address. If you are using per application blocking (LF_TRIGGER) +# then only the relevant block port will be redirected to the messenger port +MESSENGER_HTML_IN = "80" + +# Set this to the port that will receive the TEXT message. You should configure +# this port to be >1023 and different from the HTML port. Do NOT enable access +# to this port in TCP_IN +MESSENGER_TEXT = "8889" + +# This comma separated list are the TEXT ports that will be redirected for the +# blocked IP address. If you are using per application blocking (LF_TRIGGER) +# then only the relevant block port will be redirected to the messenger port +MESSENGER_TEXT_IN = "21" + +# These settings limit the rate at which connections can be made to the +# messenger service servers. Its intention is to provide protection from +# attacks or excessive connections to the servers. If the rate is exceeded then +# iptables will revert for the duration to the normal blocking activity +# +# See the iptables man page for the correct --limit rate syntax +MESSENGER_RATE = "100/s" +MESSENGER_BURST = "150" + +# MESSENGERV1 only: +#------------------------------------------------------------------------------ +# This is the maximum concurrent connections allowed to each service server +# +# Note: This number should be increased to cater for the number of local images +# served by this page, including one for favicon.ico. This is because each +# image displayed counts as an additional connection +MESSENGER_CHILDREN = "20" + +# This options ignores ServerAlias definitions that begin with "mail.". This +# can help reduce memory usage on systems that do not require the use of +# MESSENGER_HTTPS on those subdomains +# +# Set to 0 to include these ServerAlias definitions +MESSENGER_HTTPS_SKIPMAIL = "1" + +# MESSENGERV2 only: +#------------------------------------------------------------------------------ +# MESSENGERV2. This option is available on cPanel servers running Apache v2.4+ +# under EA4. +# +# This uses the Apache http daemon to provide the web server functionality for +# the MESSENGER HTML and HTTPS services. It uses a fraction of the resources +# that the lfd inbuilt service uses and overcomes the memory overhead of using +# the MESSENGER HTTPS service +# +# For more information consult readme.txt before enabling this option +#MESSENGERV2 = "0" + +# MESSENGERV3 only: +#------------------------------------------------------------------------------ +# MESSENGERV3. This option is available on any server running Apache v2.4+, +# Litespeed or Openlitespeed +# +# This uses the web server http daemon to provide the web server functionality +# for the MESSENGER HTML and HTTPS services. It uses a fraction of the +# resources that the lfd inbuilt service uses and overcomes the memory overhead +# of using the MESSENGER HTTPS service +# +# For more information consult readme.txt before enabling this option +MESSENGERV3 = "0" + +# This is the file or directory where the additional web server configuration +# file should be included +MESSENGERV3LOCATION = "/etc/httpd/conf.d/" + +# This is the command to restart the web server +MESSENGERV3RESTART = "service httpd restart" + +# This is the command to test the validity of the web server configuration. If +# using Litespeed, set to "" +MESSENGERV3TEST = "/usr/sbin/apachectl -t" + +# This must be set to the main httpd.conf file for either Apache or Litespeed +MESSENGERV3HTTPS_CONF = "/etc/httpd/conf/httpd.conf" + +# This can be set to either: +# "apache" - for servers running Apache v2.4+ or Litespeed using Apache +# configuration +# "litespeed" - for Litespeed or Openlitespeed +MESSENGERV3WEBSERVER = "apache" + +# On creation, set the MESSENGER_USER public_html directory permissions to +# Note: If you precreate this directory the following setting will be ignored +MESSENGERV3PERMS = "711" + +# On creation, set the MESSENGER_USER public_html directory group user to +# Note: If you precreate this directory the following setting will be ignored +MESSENGERV3GROUP = "apache" + +# This is the web server configuration to allow PHP scripts to run. If left +# empty, the MESSENGER service will try to configure this. If this does not +# work, this should be set as an "Include /path/to/csf_php.conf" or similar +# file which must contain appropriate web server configuration to allow PHP +# scripts to run. This line will be included within each MESSENGER VirtualHost +# container. This will replace the [MESSENGERV3PHPHANDLER] line from the csf +# webserver template files +MESSENGERV3PHPHANDLER = "" + +# RECAPTCHA: +#------------------------------------------------------------------------------ +# The RECAPTCHA options provide a way for end-users that have blocked +# themselves in the firewall to unblock themselves. +# +# A valid Google ReCAPTCHA (v2) key set is required for this feature from: +# https://www.google.com/recaptcha/intro/index.html +# +# When configuring a new reCAPTCHA API key set you must ensure that the option +# for "Domain Name Validation" is unticked so that the same reCAPTCHA can be +# used for all domains hosted on the server. lfd then checks that the hostname +# of the request resolves to an IP on this server +# +# This feature requires the installation of the LWP::UserAgent perl module (see +# option URLGET for more details) +# +# The template used for this feature is /etc/csf/messenger/index.recaptcha.html +# +# Note: An unblock will fail if the end-users IP is located in a netblock, +# blocklist or CC_* deny entry +RECAPTCHA_SITEKEY = "" +RECAPTCHA_SECRET = "" + +# Send an email when an IP address successfully attempts to unblock themselves. +# This does not necessarily mean the IP was unblocked, only that the +# post-recaptcha unblock request was attempted +# +# Set to "0" to disable +RECAPTCHA_ALERT = "1" + +# If the server uses NAT then resolving the hostname to hosted IPs will likely +# not succeed. In that case, the external IP addresses must be listed as comma +# separated list here +RECAPTCHA_NAT = "" + +############################################################################### +# SECTION:lfd Clustering +############################################################################### +# lfd Clustering. This allows the configuration of an lfd cluster environment +# where a group of servers can share blocks and configuration option changes. +# Included are CLI and UI options to send requests to the cluster. +# +# See the readme.txt file for more information and details on setup and +# security risks. +# +# Set this to a comma separated list of cluster member IP addresses to send +# requests to. Alternatively, it can be set to the full path of a file that +# will read in one IP per line, e.g.: +# "/etc/csf/cluster_sendto.txt" +CLUSTER_SENDTO = "" + +# Set this to a comma separated list of cluster member IP addresses to receive +# requests from. Alternatively, it can be set to the full path of a file that +# will read in one IP per line, e.g.: +# "/etc/csf/cluster_recvfrom.txt" +CLUSTER_RECVFROM = "" + +# IP address of the master node in the cluster allowed to send CLUSTER_CONFIG +# changes +CLUSTER_MASTER = "" + +# If this is a NAT server, set this to the public IP address of this server +CLUSTER_NAT = "" + +# If a cluster member should send requests on an IP other than the default IP, +# set it here +CLUSTER_LOCALADDR = "" + +# Cluster communication port (must be the same on all member servers). There +# is no need to open this port in the firewall as csf will automatically add +# in and out bound rules to allow communication between cluster members +CLUSTER_PORT = "7777" + +# This is a secret key used to encrypt cluster communications using the +# Blowfish algorithm. It should be between 8 and 56 characters long, +# preferably > 20 random characters +# 56 chars: 01234567890123456789012345678901234567890123456789012345 +CLUSTER_KEY = "" + +# Automatically send lfd blocks to all members of CLUSTER_SENDTO. Those +# servers must have this servers IP address listed in their CLUSTER_RECVFROM +# +# Set to 0 to disable this feature +CLUSTER_BLOCK = "1" + +# This option allows the enabling and disabling of the Cluster configuration +# changing options --cconfig, --cconfigr, --cfile, --ccfile sent from the +# CLUSTER_MASTER server +# +# Set this option to 1 to allow Cluster configurations to be received +CLUSTER_CONFIG = "0" + +# Maximum number of child processes to listen on. High blocking rates or large +# clusters may need to increase this +CLUSTER_CHILDREN = "10" + +############################################################################### +# SECTION:Port Knocking +############################################################################### +# Port Knocking. This feature allows port knocking to be enabled on multiple +# ports with a variable number of knocked ports and a timeout. There must be a +# minimum of 3 ports to knock for an entry to be valid +# +# See the following for information regarding Port Knocking: +# http://www.portknocking.org/ +# +# This feature does not work on servers that do not have the iptables module +# ipt_recent loaded. Typically, this will be with MONOLITHIC kernels. VPS +# server admins should check with their VPS host provider that the iptables +# module is included +# +# For further information and syntax refer to the Port Knocking section of the +# csf readme.txt +# +# Note: Run /etc/csf/csftest.pl to check whether this option will function on +# this server +# +# openport;protocol;timeout;kport1;kport2;kport3[...;kportN],... +# e.g.: 22;TCP;20;100;200;300;400 +PORTKNOCKING = "" + +# Enable PORTKNOCKING logging by iptables +PORTKNOCKING_LOG = "1" + +# Send an email alert if the PORTKNOCKING port is opened. PORTKNOCKING_LOG must +# also be enabled to use this option +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +PORTKNOCKING_ALERT = "0" + +############################################################################### +# SECTION:Log Scanner +############################################################################### +# Log Scanner. This feature will send out an email summary of the log lines of +# each log listed in /etc/csf/csf.logfiles. All lines will be reported unless +# they match a regular expression in /etc/csf/csf.logignore +# +# File globbing is supported for logs listed in /etc/csf/csf.logfiles. However, +# be aware that the more files lfd has to track, the greater the performance +# hit. Note: File globs are only evaluated when lfd is started +# +# Note: lfd builds the report continuously from lines logged after lfd has +# started, so any lines logged when lfd is not running will not be reported +# (e.g. during reboot). If lfd is restarted, then the report will include any +# lines logged during the previous lfd logging period that weren't reported +# +# 1 to enable, 0 to disable +LOGSCANNER = "0" + +# This is the interval each report will be sent based on the logalert.txt +# template +# +# The interval can be set to: +# "hourly" - sent on the hour +# "daily" - sent at midnight (00:00) +# "manual" - sent whenever "csf --logrun" is run. This allows for scheduling +# via cron job +LOGSCANNER_INTERVAL = "hourly" + +# Report Style +# 1 = Separate chronological log lines per log file +# 2 = Simply chronological log of all lines +LOGSCANNER_STYLE = "1" + +# Send the report email even if no log lines reported +# 1 to enable, 0 to disable +LOGSCANNER_EMPTY = "1" + +# Maximum number of lines in the report before it is truncated. This is to +# prevent log lines flooding resulting in an excessively large report. This +# might need to be increased if you choose a daily report +LOGSCANNER_LINES = "5000" + +############################################################################### +# SECTION:Statistics Settings +############################################################################### +# Statistics +# +# Some of the Statistics output requires the gd graphics library and the +# GD::Graph perl module with all dependent modules to be installed for the UI +# for them to be displayed +# +# This option enabled statistical data gathering +ST_ENABLE = "1" + +# This option determines how many iptables log lines to store for reports +ST_IPTABLES = "100" + +# This option indicates whether rDNS and CC lookups are performed at the time +# the log line is recorded (this is not performed when viewing the reports) +# +# Warning: If DROP_IP_LOGGING is enabled and there are frequent iptables hits, +# then enabling this setting could cause serious performance problems +ST_LOOKUP = "0" + +# This option will gather basic system statstics. Through the UI it displays +# various graphs for disk, cpu, memory, network, etc usage over 4 intervals: +# . Hourly (per minute) +# . 24 hours (per minute) +# . 7 days (per minute averaged over an hour) +# . 30 days (per minute averaged over an hour) - user definable +# The data is stored in /var/lib/csf/stats/system and the option requires the +# perl GD::Graph module +# +# Note: Disk graphs do not show on Virtuozzo/OpenVZ servers as the kernel on +# those systems do not store the required information in /proc/diskstats +# On new installations or when enabling this option it will take time for these +# graphs to be populated +ST_SYSTEM = "0" + +# Set the maximum days to collect statistics for. The default is 30 days, the +# more data that is collected the longer it will take for each of the graphs to +# be generated +ST_SYSTEM_MAXDAYS = "30" + +# If ST_SYSTEM is enabled, then these options can collect MySQL statistical +# data. To use this option the server must have the perl modules DBI and +# DBD::mysql installed. +# +# Set this option to "0" to disable MySQL data collection +ST_MYSQL = "0" + +# The following options are for authentication for MySQL data collection. If +# the password is left blank and the user set to "root" then the procedure will +# look for authentication data in /root/.my.cnf. Otherwise, you will need to +# provide a MySQL username and password to collect the data. Any MySQL user +# account can be used +ST_MYSQL_USER = "root" +ST_MYSQL_PASS = "" +ST_MYSQL_HOST = "localhost" + +# If ST_SYSTEM is enabled, then this option can collect Apache statistical data +# The value for PT_APACHESTATUS must be correctly set +ST_APACHE = "0" + +# The following options measure disk write performance using dd (location set +# via the DD setting). It creates a 64MB file called /var/lib/dd_write_test and +# the statistics will plot the MB/s response time of the disk. As this is an IO +# intensive operation, it may not be prudent to run this test too often, so by +# default it is only run every 5 minutes and the result duplicated for each +# intervening minute for the statistics +# +# This is not necessrily a good measure of disk performance, primarily because +# the measurements are for relatively small amounts of data over a small amount +# of time. To properly test disk performance there are a variety of tools +# available that should be run for extended periods of time to obtain an +# accurate measurement. This metric is provided to give an idea of how the disk +# is performing over time +# +# Note: There is a 15 second timeout performing the check +# +# Set to 0 to disable, 1 to enable +ST_DISKW = "0" + +# The number of minutes that elapse between tests. Default is 5, minimum is 1. +ST_DISKW_FREQ = "5" + +# This is the command line passed to dd. If you are familiar with dd, or wish +# to move the output file (of) to a different disk, then you can alter this +# command. Take great care when making any changes to this command as it is +# very easy to overwrite a disk using dd if you make a mistake +ST_DISKW_DD = "if=/dev/zero of=/var/lib/csf/dd_test bs=1MB count=64 conv=fdatasync" + +############################################################################### +# SECTION:Docker Settings +############################################################################### +# This section provides the configuration of iptables rules to allow Docker +# containers to communicate through the host. If the generated rules do not +# work with your setup you will have to use a /etc/csf/csfpost.sh file and add +# your own iptables configuration instead +# +# 1 to enable, 0 to disable +DOCKER = "0" + +# The network device on the host +DOCKER_DEVICE = "docker0" + +# Docker container IPv4 range +DOCKER_NETWORK4 = "172.17.0.0/16" + +# Docker container IPv6 range. IPV6 must be enabled and the IPv6 nat table +# available (see IPv6 section). Leave blank to disable +DOCKER_NETWORK6 = "2001:db8:1::/64" + +############################################################################### +# SECTION:OS Specific Settings +############################################################################### +# Binary locations +IPTABLES = "/sbin/iptables" +IPTABLES_SAVE = "/sbin/iptables-save" +IPTABLES_RESTORE = "/sbin/iptables-restore" +IP6TABLES = "/sbin/ip6tables" +IP6TABLES_SAVE = "/sbin/ip6tables-save" +IP6TABLES_RESTORE = "/sbin/ip6tables-restore" +MODPROBE = "/sbin/modprobe" +IFCONFIG = "/sbin/ifconfig" +SENDMAIL = "/usr/sbin/sendmail" +PS = "/bin/ps" +VMSTAT = "/usr/bin/vmstat" +NETSTAT = "/bin/netstat" +LS = "/bin/ls" +MD5SUM = "/usr/bin/md5sum" +TAR = "/bin/tar" +CHATTR = "/usr/bin/chattr" +UNZIP = "/usr/bin/unzip" +GUNZIP = "/bin/gunzip" +DD = "/bin/dd" +TAIL = "/usr/bin/tail" +GREP = "/bin/grep" +ZGREP = "/usr/bin/zgrep" +IPSET = "/usr/sbin/ipset" +SYSTEMCTL = "/usr/bin/systemctl" +HOST = "/usr/bin/host" +IP = "/sbin/ip" +CURL = "/usr/bin/curl" +WGET = "/usr/bin/wget" + +# Log file locations +# +# File globbing is allowed for the following logs. However, be aware that the +# more files lfd has to track, the greater the performance hit +# +# Note: File globs are only evaluated when lfd is started +# +HTACCESS_LOG = "/var/log/httpd/error_log" +MODSEC_LOG = "/var/log/httpd/error_log" +SSHD_LOG = "/var/log/secure" +SU_LOG = "/var/log/secure" +SUDO_LOG = "/var/log/secure" +FTPD_LOG = "/var/log/messages" +SMTPAUTH_LOG = "/var/log/secure" +POP3D_LOG = "/var/log/maillog" +IMAPD_LOG = "/var/log/maillog" +IPTABLES_LOG = "/var/log/messages" +SUHOSIN_LOG = "/var/log/messages" +BIND_LOG = "/var/log/messages" +SYSLOG_LOG = "/var/log/messages" +WEBMIN_LOG = "/var/log/secure" + +CUSTOM1_LOG = "/var/log/customlog" +CUSTOM2_LOG = "/var/log/customlog" +CUSTOM3_LOG = "/var/log/customlog" +CUSTOM4_LOG = "/var/log/customlog" +CUSTOM5_LOG = "/var/log/customlog" +CUSTOM6_LOG = "/var/log/customlog" +CUSTOM7_LOG = "/var/log/customlog" +CUSTOM8_LOG = "/var/log/customlog" +CUSTOM9_LOG = "/var/log/customlog" + +# The following are comma separated lists used if LF_SELECT is enabled, +# otherwise they are not used. They are derived from the application returned +# from a regex match in /usr/local/csf/bin/regex.pm +# +# All ports default to tcp blocks. To specify udp or tcp use the format: +# port;protocol,port;protocol,... For example, "53;udp,53;tcp" +PORTS_pop3d = "110,995" +PORTS_imapd = "143,993" +PORTS_htpasswd = "80,443" +PORTS_mod_security = "80,443" +PORTS_mod_qos = "80,443" +PORTS_symlink = "80,443" +PORTS_suhosin = "80,443" +PORTS_cxs = "80,443" +PORTS_bind = "53;udp,53;tcp" +PORTS_ftpd = "20,21" +PORTS_webmin = "10000" +PORTS_smtpauth = "25,465,587" +PORTS_eximsyntax = "25,465,587" +# This list is replaced, if present, by "Port" definitions in +# /etc/ssh/sshd_config +PORTS_sshd = "22" + +# This configuration is for use with generic Linux servers, do not change the +# following setting: +GENERIC = "1" + +# For internal use only. You should not enable this option as it could cause +# instability in csf and lfd +DEBUG = "0" +############################################################################### diff --git a/csf/csf.generic.ignore b/csf/csf.generic.ignore new file mode 100644 index 0000000..bf3fb2a --- /dev/null +++ b/csf/csf.generic.ignore @@ -0,0 +1,25 @@ +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +# The following IP addresses will be ignored by all lfd checks +# One IP address per line +# CIDR addressing allowed with a quaded IP (e.g. 192.168.254.0/24) +# Only list IP addresses, not domain names (they will be ignored) +# + +127.0.0.1 diff --git a/csf/csf.generic.pignore b/csf/csf.generic.pignore new file mode 100644 index 0000000..475fd33 --- /dev/null +++ b/csf/csf.generic.pignore @@ -0,0 +1,81 @@ +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +# The following is a list of executables (exe) command lines (cmd) and +# usernames (user) that lfd process tracking will ignore. +# +# You must use the following format: +# +# exe:/full/path/to/file +# user:username +# cmd:command line +# +# Or, perl regular expression matching (regex): +# +# pexe:/full/path/to/file as a perl regex[*] +# puser:username as a perl regex[*] +# pcmd:command line as a perl regex[*] +# +# [*]You must remember to escape characters correctly when using regex's, e.g.: +# pexe:/home/.*/public_html/cgi-bin/script\.cgi +# puser:bob\d.* +# pcmd:/home/.*/command\s\to\smatch\s\.pl\s.* +# +# It is strongly recommended that you use command line ignores very carefully +# as any process can change what is reported to the OS. +# +# For more information see readme.txt + +exe:/bin/dbus-daemon +exe:/sbin/ntpd +exe:/usr/bin/dbus-daemon +exe:/usr/bin/lsmd +exe:/usr/lib/courier-imap/bin/imapd +exe:/usr/lib/courier-imap/bin/pop3d +exe:/usr/lib/polkit-1/polkitd +exe:/usr/libexec/dovecot/imap +exe:/usr/libexec/dovecot/imap +exe:/usr/libexec/dovecot/pop3 +exe:/usr/libexec/dovecot/pop3 +exe:/usr/libexec/mysqld +exe:/usr/local/apache/bin/httpd +exe:/usr/local/libexec/dovecot/imap +exe:/usr/local/libexec/dovecot/imap-login +exe:/usr/local/libexec/dovecot/pop3 +exe:/usr/local/libexec/dovecot/pop3-login +exe:/usr/sbin/chronyd +exe:/usr/sbin/exim +exe:/usr/sbin/exim4 +exe:/usr/sbin/named +exe:/usr/sbin/nscd +exe:/usr/sbin/ntpd +exe:/usr/sbin/ntpd +exe:/usr/sbin/proftpd +exe:/usr/sbin/pure-ftpd +exe:/usr/sbin/sshd +exe:/usr/sbin/apache2 +exe:/usr/sbin/mysqld +exe:/lib/systemd/systemd-timesyncd +exe:/usr/lib/systemd/systemd-resolved +exe:/usr/libexec/postfix/pickup +exe:/usr/libexec/postfix/qmgr +exe:/usr/libexec/postfix/tlsmgr +exe:/sbin/rngd +exe:/usr/sbin/mariadbd +exe:/usr/bin/dbus-broker-launch +exe:/usr/bin/dbus-broker diff --git a/csf/csf.help b/csf/csf.help new file mode 100644 index 0000000..3eb0d8d --- /dev/null +++ b/csf/csf.help @@ -0,0 +1,222 @@ +csf(1) General Commands Manual csf(1) + +NAME + csf - ConfigServer & Security Firewall + +SYNOPSIS + csf [OPTIONS] + +DESCRIPTION + This manual documents the csf command line options for the ConfigServer & Security Firewall. See /etc/csf/csf.conf and + /etc/csf/readme.txt for more detailed information on how to use and configure this application. + +OPTIONS + -h, --help + Show this message + + -l, --status + List/Show the IPv4 iptables configuration + + -l6, --status6 + List/Show the IPv6 ip6tables configuration + + -s, --start + Start the firewall rules + + -f, --stop + Flush/Stop firewall rules (Note: lfd may restart csf) + + -r, --restart + Restart firewall rules (csf) + + -q, --startq + Quick restart (csf restarted by lfd) + + -sf, --startf + Force CLI restart regardless of LFDSTART setting + + -ra, --restartall + Restart firewall rules (csf) and then restart lfd daemon. Both csf and then lfd should be restarted after making any changes to + the configuration files + + --lfd [stop|start|restart|status] + Actions to take with the lfd daemon + + -a, --add ip [comment] + Allow an IP and add to /etc/csf/csf.allow + + -ar, --addrm ip + Remove an IP from /etc/csf/csf.allow and delete rule + + -d, --deny ip [comment] + Deny an IP and add to /etc/csf/csf.deny + + -dr, --denyrm ip + Unblock an IP and remove from /etc/csf/csf.deny + + -df, --denyf + Remove and unblock all entries in /etc/csf/csf.deny + + -g, --grep ip + Search the iptables and ip6tables rules for a match (e.g. IP, CIDR, Port Number) + + -i, --iplookup ip + Lookup IP address geographical information using CC_LOOKUPS setting in /etc/csf/csf.conf + + -t, --temp + Displays the current list of temporary allow and deny IP entries with their TTL and comment + + -tr, --temprm ip + Remove an IP from the temporary IP ban or allow list + + -trd, --temprmd ip + Remove an IP from the temporary IP ban list only + + -tra, --temprma ip + Remove an IP from the temporary IP allow list only + + -td, --tempdeny ip ttl [-p port] [-d direction] [comment] + Add an IP to the temp IP ban list. ttl is how long to blocks for (default:seconds, can use one suffix of h/m/d). Optional port. + Optional direction of block can be one of: in, out or inout (default:in) + + -ta, --tempallow ip ttl [-p port] [-d direction] [comment] + Add an IP to the temp IP allow list (default:inout) + + -tf, --tempf + Flush all IPs from the temporary IP entries + + -cp, --cping + PING all members in an lfd Cluster + + -cg, --cgrep ip + Requests the --grep output for IP from each member in an lfd Cluster + + -cd, --cdeny ip [comment] + Deny an IP in a Cluster and add to each remote /etc/csf/csf.deny + + -ctd, --ctempdeny ip ttl [-p port] [-d direction] [comment] + Add an IP in a Cluster to the temp IP ban list (default:in) + + -cr, --crm ip + Unblock an IP in a Cluster and remove from each remote /etc/csf/csf.deny and temporary list + + -ca, --callow ip [comment] + Allow an IP in a Cluster and add to each remote /etc/csf/csf.allow + + -cta, --ctempallow ip ttl [-p port] [-d direction] [comment] + Add an IP in a Cluster to the temp IP allow list (default:in) + + -car, --carm ip + Remove allowed IP in a Cluster and remove from each remote /etc/csf/csf.allow and temporary list + + -ci, --cignore ip [comment] + Ignore an IP in a Cluster and add to each remote /etc/csf/csf.ignore. Note: This will result in lfd being restarted + + -cir, --cirm ip + Remove ignored IP in a Cluster and remove from each remote /etc/csf/csf.ignore. Note: This will result in lfd being restarted + + -cc, --cconfig [name] [value] + Change configuration option [name] to [value] in a Cluster + + -cf, --cfile [file] + Send [file] in a Cluster to /etc/csf/ + + -crs, --crestart + Cluster restart csf and lfd + + --trace [add|remove] ip + Log SYN packets for an IP across iptables chains. Note, this can create a LOT of logging information in /var/log/messages so + should only be used for a short period of time. This option requires the iptables TRACE module and access to the raw PREROUTING + chain to function + + -m, --mail [email] + Display Server Check in HTML or email to [email] if present + + --rbl [email] + Process and display RBL Check in HTML or email to [email] if present + + -lr, --logrun + Initiate Log Scanner report via lfd + + -p, --ports + View ports on the server that have a running process behind them listening for external connections + + --graphs [graph type] [directory] + Generate System Statistics html pages and images for a given graph type into a given directory. See ST_SYSTEM for requirements + + --profile [command] [profile|backup] [profile|backup] + Configuration profile functions for /etc/csf/csf.conf + You can create your own profiles using the examples provided in /usr/local/csf/profiles/ + The profile reset_to_defaults.conf is a special case and will always be the latest default csf.conf + + list + Lists available profiles and backups + + apply [profile] + Modify csf.conf with Configuration Profile + + backup "name" + Create Configuration Backup with optional "name" stored in /var/lib/csf/backup/ + + restore [backup] + Restore a Configuration Backup + + keep [num] + Remove old Configuration Backups and keep the latest [num] + + diff [profile|backup] [profile|backup] + Report differences between Configuration Profiles or Configuration Backups, only specify one [profile|backup] to compare to the + current Configuration + + --mregen + MESSENGERV2 /etc/apache2/conf.d/csf_messenger.conf regeneration. This will also gracefully restart httpd + + --cloudflare [command] + Commands for interacting with the CloudFlare firewall. See /etc/csf/readme.txt and CF_ENABLE for more detailed information + + Note: target can be one of: An IP address; 2 letter Country Code; IP range CIDR. Only Enterprise customers can block a Country + Code, but all can allow and challenge. IP range CIDR is limited to /16 and /24 + + list [all|block|challenge|whitelist] [user1,user2,domain1...] + List specified type of CloudFlare Firewall rules for comma separated list of users/domains + + add [block|challenge|whitelist] target [user1,user2,domain1...] + Add CloudFlare Firewall rule action for target for comma separated list of users/domains only + + del target [user1,user2,domain1...] + Delete CloudFlare Firewall rule for target for comma separated list of users/domains only + + tempadd [allow|deny] ip [user1,user2,domain1...] + Add a temporary block for CF_TEMP seconds to both csf and the CloudFlare Firewall rule for ip for comma separated list of + users/domains as well as any user set to "any" + + -c, --check + Check for updates to csf but do not upgrade + + -u, --update + Check for updates to csf and upgrade if available + + -uf Force an update of csf whether and upgrade is required or not + + -x, --disable + Disable csf and lfd completely + + -e, --enable + Enable csf and lfd if previously disabled + + -v, --version + Show csf version + +FILES + /etc/csf/csf.conf + The system wide configuration file + /etc/csf/readme.txt + Detailed information about csf and lfd + +BUGS + Report bugs on the forums at http://forum.configserver.com + +AUTHOR + (c)2006-2023, Jonathan Michaelson (http://www.configserver.com) + + csf(1) diff --git a/csf/csf.ignore b/csf/csf.ignore new file mode 100644 index 0000000..4d407ae --- /dev/null +++ b/csf/csf.ignore @@ -0,0 +1,28 @@ +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +# The following IP addresses will be ignored by all lfd checks +# One IP address per line +# CIDR addressing allowed with a quaded IP (e.g. 192.168.254.0/24) +# Only list IP addresses, not domain names (they will be ignored) +# + +127.0.0.1 + +Include /etc/csf/cpanel.comodo.ignore +Include /etc/csf/cpanel.ignore diff --git a/csf/csf.interworx.allow b/csf/csf.interworx.allow new file mode 100644 index 0000000..19ec008 --- /dev/null +++ b/csf/csf.interworx.allow @@ -0,0 +1,30 @@ +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +# The following IP addresses will be allowed through iptables. +# One IP address per line. +# CIDR addressing allowed with a quaded IP (e.g. 192.168.254.0/24). +# Only list IP addresses, not domain names (they will be ignored) +# +# Advanced port+ip filtering allowed with the following format +# tcp/udp|in/out|s/d=port|s/d=ip +# See readme.txt for more information +# +# Note: IP addressess listed in this file will NOT be ignored by lfd, so they +# can still be blocked. If you do not want lfd to block an IP address you must +# add it to csf.ignore diff --git a/csf/csf.interworx.conf b/csf/csf.interworx.conf new file mode 100644 index 0000000..60d4cec --- /dev/null +++ b/csf/csf.interworx.conf @@ -0,0 +1,2686 @@ +############################################################################### +# SECTION:Initial Settings +############################################################################### +# Testing flag - enables a CRON job that clears iptables incase of +# configuration problems when you start csf. This should be enabled until you +# are sure that the firewall works - i.e. incase you get locked out of your +# server! Then do remember to set it to 0 and restart csf when you're sure +# everything is OK. Stopping csf will remove the line from /etc/crontab +# +# lfd will not start while this is enabled +TESTING = "1" + +# The interval for the crontab in minutes. Since this uses the system clock the +# CRON job will run at the interval past the hour and not from when you issue +# the start command. Therefore an interval of 5 minutes means the firewall +# will be cleared in 0-5 minutes from the firewall start +TESTING_INTERVAL = "5" + +# SECURITY WARNING +# ================ +# +# Unfortunately, syslog and rsyslog allow end-users to log messages to some +# system logs via the same unix socket that other local services use. This +# means that any log line shown in these system logs that syslog or rsyslog +# maintain can be spoofed (they are exactly the same as real log lines). +# +# Since some of the features of lfd rely on such log lines, spoofed messages +# can cause false-positive matches which can lead to confusion at best, or +# blocking of any innocent IP address or making the server inaccessible at +# worst. +# +# Any option that relies on the log entries in the files listed in +# /etc/syslog.conf and /etc/rsyslog.conf should therefore be considered +# vulnerable to exploitation by end-users and scripts run by end-users. +# +# NOTE: Not all log files are affected as they may not use syslog/rsyslog +# +# The option RESTRICT_SYSLOG disables all these features that rely on affected +# logs. These options are: +# LF_SSHD LF_FTPD LF_IMAPD LF_POP3D LF_BIND LF_SUHOSIN LF_SSH_EMAIL_ALERT +# LF_SU_EMAIL_ALERT LF_CONSOLE_EMAIL_ALERT LF_DISTATTACK LF_DISTFTP +# LT_POP3D LT_IMAPD PS_INTERVAL UID_INTERVAL WEBMIN_LOG LF_WEBMIN_EMAIL_ALERT +# PORTKNOCKING_ALERT LF_SUDO_EMAIL_ALERT +# +# This list of options use the logs but are not disabled by RESTRICT_SYSLOG: +# ST_ENABLE SYSLOG_CHECK LOGSCANNER CUSTOM*_LOG +# +# The following options are still enabled by default on new installations so +# that, on balance, csf/lfd still provides expected levels of security: +# LF_SSHD LF_FTPD LF_POP3D LF_IMAPD LF_SSH_EMAIL_ALERT LF_SU_EMAIL_ALERT +# +# If you set RESTRICT_SYSLOG to "0" or "2" and enable any of the options listed +# above, it should be done with the knowledge that any of the those options +# that are enabled could be triggered by spoofed log lines and lead to the +# server being inaccessible in the worst case. If you do not want to take that +# risk you should set RESTRICT_SYSLOG to "1" and those features will not work +# but you will not be protected from the exploits that they normally help block +# +# The recommended setting for RESTRICT_SYSLOG is "3" to restrict who can access +# the syslog/rsyslog unix socket. +# +# For further advice on how to help mitigate these issues, see +# /etc/csf/readme.txt +# +# 0 = Allow those options listed above to be used and configured +# 1 = Disable all the options listed above and prevent them from being used +# 2 = Disable only alerts about this feature and do nothing else +# 3 = Restrict syslog/rsyslog access to RESTRICT_SYSLOG_GROUP ** RECOMMENDED ** +RESTRICT_SYSLOG = "0" + +# The following setting is used if RESTRICT_SYSLOG is set to 3. It restricts +# write access to the syslog/rsyslog unix socket(s). The group must not already +# exists in /etc/group before setting RESTRICT_SYSLOG to 3, so set the option +# to a unique name for the server +# +# You can add users to this group by changing /etc/csf/csf.syslogusers and then +# restarting lfd afterwards. This will create the system group and add the +# users from csf.syslogusers if they exist to that group and will change the +# permissions on the syslog/rsyslog unix socket(s). The socket(s) will be +# monitored and the permissions re-applied should syslog/rsyslog be restarted +# +# Using this option will prevent some legitimate logging, e.g. end-user cron +# job logs +# +# If you want to revert RESTRICT_SYSLOG to another option and disable this +# feature, change the setting of RESTRICT_SYSLOG and then restart lfd and then +# syslog/rsyslog and the unix sockets will be reset +RESTRICT_SYSLOG_GROUP = "mysyslog" + +# This options restricts the ability to modify settings within this file from +# the csf UI. Should the parent control panel be compromised, these restricted +# options could be used to further compromise the server. For this reason we +# recommend leaving this option set to at least "1" and if any of the +# restricted items need to be changed, they are done so from the root shell +# +# 0 = Unrestricted UI +# 1 = Restricted UI +# 2 = Disabled UI +RESTRICT_UI = "1" + +# Enabling auto updates creates a cron job called /etc/cron.d/csf_update which +# runs once per day to see if there is an update to csf+lfd and upgrades if +# available and restarts csf and lfd +# +# You should check for new version announcements at http://blog.configserver.com +AUTO_UPDATES = "1" + +############################################################################### +# SECTION:IPv4 Port Settings +############################################################################### +# Lists of ports in the following comma separated lists can be added using a +# colon (e.g. 30000:35000). + +# Some kernel/iptables setups do not perform stateful connection tracking +# correctly (typically some virtual servers or custom compiled kernels), so a +# SPI firewall will not function correctly. If this happens, LF_SPI can be set +# to 0 to reconfigure csf as a static firewall. +# +# As connection tracking will not be configured, applications that rely on it +# will not function unless all outgoing ports are opened. Therefore, all +# outgoing connections will be allowed once all other tests have completed. So +# TCP_OUT, UDP_OUT and ICMP_OUT will not have any affect. +# +# If you allow incoming DNS lookups you may need to use the following +# directive in the options{} section of your named.conf: +# +# query-source port 53; +# +# This will force incoming DNS traffic only through port 53 +# +# Disabling this option will break firewall functionality that relies on +# stateful packet inspection (e.g. DNAT, PACKET_FILTER) and makes the firewall +# less secure +# +# This option should be set to "1" in all other circumstances +LF_SPI = "1" + +# Allow incoming TCP ports +TCP_IN = "20,21,22,24,25,53,853,80,110,143,443,465,587,993,995,2080,2443" + +# Allow outgoing TCP ports +TCP_OUT = "20,21,22,25,53,853,80,110,113,443,587,993,995,2080,2443" + +# Allow incoming UDP ports +UDP_IN = "20,21,53,853,80,443" + +# Allow outgoing UDP ports +# To allow outgoing traceroute add 33434:33523 to this list +UDP_OUT = "20,21,53,853,113,123" + +# Allow incoming PING. Disabling PING will likely break external uptime +# monitoring +ICMP_IN = "1" + +# Set the per IP address incoming ICMP packet rate for PING requests. This +# ratelimits PING requests which if exceeded results in silently rejected +# packets. Disable or increase this value if you are seeing PING drops that you +# do not want +# +# To disable rate limiting set to "0", otherwise set according to the iptables +# documentation for the limit module. For example, "1/s" will limit to one +# packet per second +ICMP_IN_RATE = "1/s" + +# Allow outgoing PING +# +# Unless there is a specific reason, this option should NOT be disabled as it +# could break OS functionality +ICMP_OUT = "1" + +# Set the per IP address outgoing ICMP packet rate for PING requests. This +# ratelimits PING requests which if exceeded results in silently rejected +# packets. Disable or increase this value if you are seeing PING drops that you +# do not want +# +# Unless there is a specific reason, this option should NOT be enabled as it +# could break OS functionality +# +# To disable rate limiting set to "0", otherwise set according to the iptables +# documentation for the limit module. For example, "1/s" will limit to one +# packet per second +ICMP_OUT_RATE = "0" + +# For those with PCI Compliance tools that state that ICMP timestamps (type 13) +# should be dropped, you can enable the following option. Otherwise, there +# appears to be little evidence that it has anything to do with a security risk +# and can impact network performance, so should be left disabled by everyone +# else +ICMP_TIMESTAMPDROP = "0" + +############################################################################### +# SECTION:IPv6 Port Settings +############################################################################### +# IPv6: (Requires ip6tables) +# +# Pre v2.6.20 kernels do not perform stateful connection tracking, so a static +# firewall is configured as a fallback instead if IPV6_SPI is set to 0 below +# +# Supported: +# Temporary ACCEPT/DENY, GLOBAL_DENY, GLOBAL_ALLOW, SMTP_BLOCK, LF_PERMBLOCK, +# PACKET_FILTER, Advanced Allow/Deny Filters, RELAY_*, CLUSTER_*, CC6_LOOKUPS, +# SYNFLOOD, LF_NETBLOCK +# +# Supported if CC6_LOOKUPS and CC_LOOKUPS are enabled +# CC_DENY, CC_ALLOW, CC_ALLOW_FILTER, CC_IGNORE, CC_ALLOW_PORTS, CC_DENY_PORTS, +# CC_ALLOW_SMTPAUTH +# +# Supported if ip6tables >= 1.4.3: +# PORTFLOOD, CONNLIMIT +# +# Supported if ip6tables >= 1.4.17 and perl module IO::Socket::INET6 is +# installed: +# MESSENGER DOCKER SMTP_REDIRECT +# +# Not supported: +# ICMP_IN, ICMP_OUT +# +IPV6 = "0" + +# IPv6 uses icmpv6 packets very heavily. By default, csf will allow all icmpv6 +# traffic in the INPUT and OUTPUT chains. However, this could increase the risk +# of icmpv6 attacks. To restrict incoming icmpv6, set to "1" but may break some +# connection types +IPV6_ICMP_STRICT = "0" + +# Pre v2.6.20 kernel must set this option to "0" as no working state module is +# present, so a static firewall is configured as a fallback +# +# A workaround has been added for CentOS/RedHat v5 and custom kernels that do +# not support IPv6 connection tracking by opening ephemeral port range +# 32768:61000. This is only applied if IPV6_SPI is not enabled. This is the +# same workaround implemented by RedHat in the sample default IPv6 rules +# +# As connection tracking will not be configured, applications that rely on it +# will not function unless all outgoing ports are opened. Therefore, all +# outgoing connections will be allowed once all other tests have completed. So +# TCP6_OUT, UDP6_OUT and ICMP6_OUT will not have any affect. +# +# If you allow incoming ipv6 DNS lookups you may need to use the following +# directive in the options{} section of your named.conf: +# +# query-source-v6 port 53; +# +# This will force ipv6 incoming DNS traffic only through port 53 +# +# These changes are not necessary if the SPI firewall is used +IPV6_SPI = "1" + +# Allow incoming IPv6 TCP ports +TCP6_IN = "20,21,22,24,25,53,853,80,110,143,443,465,587,993,995,2080,2443" + +# Allow outgoing IPv6 TCP ports +TCP6_OUT = "20,21,22,25,53,853,80,110,113,443,587,993,995,2080,2443" + +# Allow incoming IPv6 UDP ports +UDP6_IN = "20,21,53,853,80,443" + +# Allow outgoing IPv6 UDP ports +# To allow outgoing traceroute add 33434:33523 to this list +UDP6_OUT = "20,21,53,853,113,123" + +############################################################################### +# SECTION:General Settings +############################################################################### +# By default, csf will auto-configure iptables to filter all traffic except on +# the loopback device. If you only want iptables rules applied to a specific +# NIC, then list it here (e.g. eth1, or eth+) +ETH_DEVICE = "" + +# By adding a device to this option, ip6tables can be configured only on the +# specified device. Otherwise, ETH_DEVICE and then the default setting will be +# used +ETH6_DEVICE = "" + +# If you don't want iptables rules applied to specific NICs, then list them in +# a comma separated list (e.g "eth1,eth2") +ETH_DEVICE_SKIP = "" + +# This option should be enabled unless the kernel does not support the +# "conntrack" module +# +# To use the deprecated iptables "state" module, change this to 0 +USE_CONNTRACK = "1" + +# Enable ftp helper via the iptables CT target on supporting kernels (v2.6.34+) +# instead of the current method via /proc/sys/net/netfilter/nf_conntrack_helper +# This will also remove the RELATED target from the global state iptables rule +# +# This is not needed (and will be ignored) if LF_SPI/IPV6_SPI is disabled or +# the raw tables do not exist. The USE_CONNTRACK option should be enabled +# +# To enable this option, set it to your FTP server listening port number +# (normally 21), do NOT set it to "1" +USE_FTPHELPER = "0" + +# Check whether syslog is running. Many of the lfd checks require syslog to be +# running correctly. This test will send a coded message to syslog every +# SYSLOG_CHECK seconds. lfd will check SYSLOG_LOG log lines for the coded +# message. If it fails to do so within SYSLOG_CHECK seconds an alert using +# syslogalert.txt is sent +# +# A value of between 300 and 3600 seconds is suggested. Set to 0 to disable +SYSLOG_CHECK = "0" + +# Enable this option if you want lfd to ignore (i.e. don't block) IP addresses +# listed in csf.allow in addition to csf.ignore (the default). This option +# should be used with caution as it would mean that IP's allowed through the +# firewall from infected PC's could launch attacks on the server that lfd +# would ignore +IGNORE_ALLOW = "0" + +# Enable the following option if you want to apply strict iptables rules to DNS +# traffic (i.e. relying on iptables connection tracking). Enabling this option +# could cause DNS resolution issues both to and from the server but could help +# prevent abuse of the local DNS server +DNS_STRICT = "0" + +# Enable the following option if you want to apply strict iptables rules to DNS +# traffic between the server and the nameservers listed in /etc/resolv.conf +# Enabling this option could cause DNS resolution issues both to and from the +# server but could help prevent abuse of the local DNS server +DNS_STRICT_NS = "0" + +# Limit the number of IP's kept in the /etc/csf/csf.deny file +# +# Care should be taken when increasing this value on servers with low memory +# resources or hard limits (such as Virtuozzo/OpenVZ) as too many rules (in the +# thousands) can sometimes cause network slowdown +# +# The value set here is the maximum number of IPs/CIDRs allowed +# if the limit is reached, the entries will be rotated so that the oldest +# entries (i.e. the ones at the top) will be removed and the latest is added. +# The limit is only checked when using csf -d (which is what lfd also uses) +# Set to 0 to disable limiting +# +# For implementations wishing to set this value significantly higher, we +# recommend using the IPSET option +DENY_IP_LIMIT = "200" + +# Limit the number of IP's kept in the temprary IP ban list. If the limit is +# reached the oldest IP's in the ban list will be removed and allowed +# regardless of the amount of time remaining for the block +# Set to 0 to disable limiting +DENY_TEMP_IP_LIMIT = "100" + +# Enable login failure detection daemon (lfd). If set to 0 none of the +# following settings will have any effect as the daemon won't start. +LF_DAEMON = "1" + +# Check whether csf appears to have been stopped and restart if necessary, +# unless TESTING is enabled above. The check is done every 300 seconds +LF_CSF = "1" + +# This option uses IPTABLES_SAVE, IPTABLES_RESTORE and IP6TABLES_SAVE, +# IP6TABLES_RESTORE in two ways: +# +# 1. On a clean server reboot the entire csf iptables configuration is saved +# and then restored where possible to provide a near instant firewall +# startup[*] +# +# 2. On csf restart or lfd reloading tables, CC_* as well as SPAMHAUS, DSHIELD, +# BOGON, TOR are loaded using this method in a fraction of the time than if +# this setting is disabled +# +# [*]Not supported on all OS platforms +# +# Set to "0" to disable this functionality +FASTSTART = "1" + +# This option allows you to use ipset v6+ for the following csf options: +# CC_* and /etc/csf/csf.blocklist, /etc/csf/csf.allow, /etc/csf/csf.deny, +# GLOBAL_DENY, GLOBAL_ALLOW, DYNDNS, GLOBAL_DYNDNS, MESSENGER +# +# ipset will only be used with the above options when listing IPs and CIDRs. +# Advanced Allow Filters and temporary blocks use traditional iptables +# +# Using ipset moves the onus of ip matching against large lists away from +# iptables rules and to a purpose built and optimised database matching +# utility. It also simplifies the switching in of updated lists +# +# To use this option you must have a fully functioning installation of ipset +# installed either via rpm or source from http://ipset.netfilter.org/ +# +# Note: Using ipset has many advantages, some disadvantages are that you will +# no longer see packet and byte counts against IPs and it makes identifying +# blocked/allowed IPs that little bit harder +# +# Note: If you mainly use IP address only entries in csf.deny, you can increase +# the value of DENY_IP_LIMIT significantly if you wish +# +# Note: It's highly unlikely that ipset will function on Virtuozzo/OpenVZ +# containers even if it has been installed +# +# If you find any problems, please post on forums.configserver.com with full +# details of the issue +LF_IPSET = "0" + +# Versions of iptables greater or equal to v1.4.20 should support the --wait +# option. This forces iptables commands that use the option to wait until a +# lock by any other process using iptables completes, rather than simply +# failing +# +# Enabling this feature will add the --wait option to iptables commands +# +# NOTE: The disadvantage of using this option is that any iptables command that +# uses it will hang until the lock is released. This could cause a cascade of +# hung processes trying to issue iptables commands. To try and avoid this issue +# csf uses a last ditch timeout, WAITLOCK_TIMEOUT in seconds, that will trigger +# a failure if reached +WAITLOCK = "0" +WAITLOCK_TIMEOUT = "300" + +# The following sets the hashsize for ipset sets, which must be a power of 2. +# +# Note: Increasing this value will consume more memory for all sets +# Default: "1024" +LF_IPSET_HASHSIZE = "1024" + +# The following sets the maxelem for ipset sets. +# +# Note: Increasing this value will consume more memory for all sets +# Default: "65536" +LF_IPSET_MAXELEM = "65536" + +# If you enable this option then whenever a CLI request to restart csf is used +# lfd will restart csf instead within LF_PARSE seconds +# +# This feature can be helpful for restarting configurations that cannot use +# FASTSTART +LFDSTART = "0" + +# Enable verbose output of iptables commands +VERBOSE = "1" + +# Drop out of order packets and packets in an INVALID state in iptables +# connection tracking +PACKET_FILTER = "1" + +# Perform reverse DNS lookups on IP addresses. (See also CC_LOOKUPS) +LF_LOOKUPS = "1" + +# Custom styling is possible in the csf UI. See the readme.txt for more +# information under "UI skinning and Mobile View" +# +# This option enables the use of custom styling. If the styling fails to work +# correctly, e.g. custom styling does not take into account a change in the +# standard csf UI, then disabling this option will return the standard UI +STYLE_CUSTOM = "0" + +# This option disables the presence of the Mobile View in the csf UI +STYLE_MOBILE = "1" + +############################################################################### +# SECTION:SMTP Settings +############################################################################### +# Block outgoing SMTP except for root, exim and mailman (forces scripts/users +# to use the exim/sendmail binary instead of sockets access). This replaces the +# protection as WHM > Tweak Settings > SMTP Tweaks +# +# This option uses the iptables ipt_owner/xt_owner module and must be loaded +# for it to work. It may not be available on some VPS platforms +# +# Note: Run /etc/csf/csftest.pl to check whether this option will function on +# this server +SMTP_BLOCK = "0" + +# If SMTP_BLOCK is enabled but you want to allow local connections to port 25 +# on the server (e.g. for webmail or web scripts) then enable this option to +# allow outgoing SMTP connections to the loopback device +SMTP_ALLOWLOCAL = "1" + +# This option redirects outgoing SMTP connections destined for remote servers +# for non-bypass users to the local SMTP server to force local relaying of +# email. Such email may require authentication (SMTP AUTH) +SMTP_REDIRECT = "0" + +# This is a comma separated list of the ports to block. You should list all +# ports that exim is configured to listen on +SMTP_PORTS = "25,465,587" + +# Always allow the following comma separated users and groups to bypass +# SMTP_BLOCK +# +# Note: root (UID:0) is always allowed +SMTP_ALLOWUSER = "" +SMTP_ALLOWGROUP = "vpopmail,qmail" + +# This option will only allow SMTP AUTH to be advertised to the IP addresses +# listed in /etc/csf/csf.smtpauth on EXIM mail servers +# +# The additional option CC_ALLOW_SMTPAUTH can be used with this option to +# additionally restrict access to specific countries +# +# This is to help limit attempts at distributed attacks against SMTP AUTH which +# are difficult to achive since port 25 needs to be open to relay email +# +# The reason why this works is that if EXIM does not advertise SMTP AUTH on a +# connection, then SMTP AUTH will not accept logins, defeating the attacks +# without restricting mail relaying +# +# Note: csf and lfd must be restarted if /etc/csf/csf.smtpauth is modified so +# that the lookup file in /etc/exim.smtpauth is regenerated from the +# information from /etc/csf/csf.smtpauth plus any countries listed in +# CC_ALLOW_SMTPAUTH +# +# NOTE: To make this option work you MUST make the modifications to exim.conf +# as explained in "Exim SMTP AUTH Restriction" section in /etc/csf/readme.txt +# after enabling the option here, otherwise this option will not work +# +# To enable this option, set to 1 and make the exim configuration changes +# To disable this option, set to 0 and undo the exim configuration changes +SMTPAUTH_RESTRICT = "0" + +############################################################################### +# SECTION:Port Flood Settings +############################################################################### +# Enable SYN Flood Protection. This option configures iptables to offer some +# protection from tcp SYN packet DOS attempts. You should set the RATE so that +# false-positives are kept to a minimum otherwise visitors may see connection +# issues (check /var/log/messages for *SYNFLOOD Blocked*). See the iptables +# man page for the correct --limit rate syntax +# +# Note: This option should ONLY be enabled if you know you are under a SYN +# flood attack as it will slow down all new connections from any IP address to +# the server if triggered +SYNFLOOD = "0" +SYNFLOOD_RATE = "100/s" +SYNFLOOD_BURST = "150" + +# Connection Limit Protection. This option configures iptables to offer more +# protection from DOS attacks against specific ports. It can also be used as a +# way to simply limit resource usage by IP address to specific server services. +# This option limits the number of concurrent new connections per IP address +# that can be made to specific ports +# +# This feature does not work on servers that do not have the iptables module +# xt_connlimit loaded. Typically, this will be with MONOLITHIC kernels. VPS +# server admins should check with their VPS host provider that the iptables +# module is included +# +# For further information and syntax refer to the Connection Limit Protection +# section of the csf readme.txt +# +# Note: Run /etc/csf/csftest.pl to check whether this option will function on +# this server +CONNLIMIT = "" + +# Port Flood Protection. This option configures iptables to offer protection +# from DOS attacks against specific ports. This option limits the number of +# new connections per time interval that can be made to specific ports +# +# This feature does not work on servers that do not have the iptables module +# ipt_recent loaded. Typically, this will be with MONOLITHIC kernels. VPS +# server admins should check with their VPS host provider that the iptables +# module is included +# +# For further information and syntax refer to the Port Flood Protection +# section of the csf readme.txt +# +# Note: Run /etc/csf/csftest.pl to check whether this option will function on +# this server +PORTFLOOD = "" + +# Outgoing UDP Flood Protection. This option limits outbound UDP packet floods. +# These typically originate from exploit scripts uploaded through vulnerable +# web scripts. Care should be taken on servers that use services that utilise +# high levels of UDP outbound traffic, such as SNMP, so you may need to alter +# the UDPFLOOD_LIMIT and UDPFLOOD_BURST options to suit your environment +# +# We recommend enabling User ID Tracking (UID_INTERVAL) with this feature +UDPFLOOD = "0" +UDPFLOOD_LIMIT = "100/s" +UDPFLOOD_BURST = "500" + +# This is a list of usernames that should not be rate limited, such as "named" +# to prevent bind traffic from being limited. +# +# Note: root (UID:0) is always allowed +UDPFLOOD_ALLOWUSER = "named" + +############################################################################### +# SECTION:Logging Settings +############################################################################### +# Log lfd messages to SYSLOG in addition to /var/log/lfd.log. You must have the +# perl module Sys::Syslog installed to use this feature +SYSLOG = "0" + +# Drop target for incoming iptables rules. This can be set to either DROP or +# REJECT. REJECT will send back an error packet, DROP will not respond at all. +# REJECT is more polite, however it does provide extra information to a hacker +# and lets them know that a firewall is blocking their attempts. DROP hangs +# their connection, thereby frustrating attempts to port scan the server +DROP = "DROP" + +# Drop target for outgoing iptables rules. This can be set to either DROP or +# REJECT as with DROP, however as such connections are from this server it is +# better to REJECT connections to closed ports rather than to DROP them. This +# helps to immediately free up server resources rather than tying them up until +# a connection times out. It also tells the process making the connection that +# it has immediately failed +# +# It is possible that some monolithic kernels may not support the REJECT +# target. If this is the case, csf checks before using REJECT and falls back to +# using DROP, issuing a warning to set this to DROP instead +DROP_OUT = "REJECT" + +# Enable logging of dropped connections to blocked ports to syslog, usually +# /var/log/messages. This option needs to be enabled to use Port Scan Tracking +DROP_LOGGING = "1" + +# Enable logging of dropped incoming connections from blocked IP addresses +# +# This option will be disabled if you enable Port Scan Tracking (PS_INTERVAL) +DROP_IP_LOGGING = "0" + +# Enable logging of dropped outgoing connections +# +# Note: Only outgoing SYN packets for TCP connections are logged, other +# protocols log all packets +# +# We recommend that you enable this option +DROP_OUT_LOGGING = "1" + +# Together with DROP_OUT_LOGGING enabled, this option logs the UID connecting +# out (where available) which can help track abuse +DROP_UID_LOGGING = "1" + +# Only log incoming reserved port dropped connections (0:1023). This can reduce +# the amount of log noise from dropped connections, but will affect options +# such as Port Scan Tracking (PS_INTERVAL) +DROP_ONLYRES = "0" + +# Commonly blocked ports that you do not want logging as they tend to just fill +# up the log file. These ports are specifically blocked (applied to TCP and UDP +# protocols) for incoming connections +DROP_NOLOG = "23,67,68,111,113,135:139,445,500,513,520" + +# Log packets dropped by the packet filtering option PACKET_FILTER +DROP_PF_LOGGING = "0" + +# Log packets dropped by the Connection Limit Protection option CONNLIMIT. If +# this is enabled and Port Scan Tracking (PS_INTERVAL) is also enabled, IP +# addresses breaking the Connection Limit Protection will be blocked +CONNLIMIT_LOGGING = "0" + +# Enable logging of UDP floods. This should be enabled, especially with User ID +# Tracking enabled +UDPFLOOD_LOGGING = "1" + +# Send an alert if log file flooding is detected which causes lfd to skip log +# lines to prevent lfd from looping. If this alert is sent you should check the +# reported log file for the reason for the flooding +LOGFLOOD_ALERT = "0" + +############################################################################### +# SECTION:Reporting Settings +############################################################################### +# By default, lfd will send alert emails using the relevant alert template to +# the To: address configured within that template. Setting the following +# option will override the configured To: field in all lfd alert emails +# +# Leave this option empty to use the To: field setting in each alert template +LF_ALERT_TO = "" + +# By default, lfd will send alert emails using the relevant alert template from +# the From: address configured within that template. Setting the following +# option will override the configured From: field in all lfd alert emails +# +# Leave this option empty to use the From: field setting in each alert template +LF_ALERT_FROM = "" + +# By default, lfd will send all alerts using the SENDMAIL binary. To send using +# SMTP directly, you can set the following to a relaying SMTP server, e.g. +# "127.0.0.1". Leave this setting blank to use SENDMAIL +LF_ALERT_SMTP = "" + +# Block Reporting. lfd can run an external script when it performs and IP +# address block following for example a login failure. The following setting +# is to the full path of the external script which must be executable. See +# readme.txt for format details +# +# Leave this setting blank to disable +BLOCK_REPORT = "" + +# To also run an external script when a temporary block is unblocked. The +# following setting can be the full path of the external script which must be +# executable. See readme.txt for format details +# +# Leave this setting blank to disable +UNBLOCK_REPORT = "" + +# In addition to the standard lfd email alerts, you can additionally enable the +# sending of X-ARF reports (see http://www.xarf.org/specification.html). Only +# block alert messages will be sent. The reports use our schema at: +# https://download.configserver.com/abuse_login-attack_0.2.json +# +# These reports are in a format accepted by many Netblock owners and should +# help them investigate abuse. This option is not designed to automatically +# forward these reports to the Netblock owners and should be checked for +# false-positive blocks before reporting +# +# If available, the report will also include the abuse contact for the IP from +# the Abusix Contact DB: https://abusix.com/contactdb.html +# +# Note: The following block types are not reported through this feature: +# LF_PERMBLOCK, LF_NETBLOCK, LF_DISTATTACK, LF_DISTFTP, RT_*_ALERT +X_ARF = "0" + +# By default, lfd will send emails from the root forwarder. Setting the +# following option will override this +X_ARF_FROM = "" + +# By default, lfd will send emails to the root forwarder. Setting the following +# option will override this +X_ARF_TO = "" + +# If you want to automatically send reports to the abuse contact where found, +# you can enable the following option +# +# Note: You MUST set X_ARF_FROM to a valid email address for this option to +# work. This is so that the abuse contact can reply to the report +# +# However, you should be aware that without manual checking you could be +# reporting innocent IP addresses, including your own clients, yourself and +# your own servers +# +# Additionally, just because a contact address is found, does not mean that +# there is anyone on the end of it reading, processing or acting on such +# reports and you could conceivably reported for sending spam +# +# We do not recommend enabling this option. Abuse reports should be checked and +# verified before being forwarded to the abuse contact +X_ARF_ABUSE = "0" + +############################################################################### +# SECTION:Temp to Perm/Netblock Settings +############################################################################### +# Temporary to Permanent IP blocking. The following enables this feature to +# permanently block IP addresses that have been temporarily blocked more than +# LF_PERMBLOCK_COUNT times in the last LF_PERMBLOCK_INTERVAL seconds. Set +# LF_PERMBLOCK to "1" to enable this feature +# +# Care needs to be taken when setting LF_PERMBLOCK_INTERVAL as it needs to be +# at least LF_PERMBLOCK_COUNT multiplied by the longest temporary time setting +# (TTL) for blocked IPs, to be effective +# +# Set LF_PERMBLOCK to "0" to disable this feature +LF_PERMBLOCK = "1" +LF_PERMBLOCK_INTERVAL = "86400" +LF_PERMBLOCK_COUNT = "4" +LF_PERMBLOCK_ALERT = "1" + +# Permanently block IPs by network class. The following enables this feature +# to permanently block classes of IP address where individual IP addresses +# within the same class LF_NETBLOCK_CLASS have already been blocked more than +# LF_NETBLOCK_COUNT times in the last LF_NETBLOCK_INTERVAL seconds. Set +# LF_NETBLOCK to "1" to enable this feature +# +# This can be an affective way of blocking DDOS attacks launched from within +# the same network class +# +# Valid settings for LF_NETBLOCK_CLASS are "A", "B" and "C", care and +# consideration is required when blocking network classes A or B +# +# Set LF_NETBLOCK to "0" to disable this feature +LF_NETBLOCK = "0" +LF_NETBLOCK_INTERVAL = "86400" +LF_NETBLOCK_COUNT = "4" +LF_NETBLOCK_CLASS = "C" +LF_NETBLOCK_ALERT = "1" + +# Valid settings for LF_NETBLOCK_IPV6 are "/64", "/56", "/48", "/32" and "/24" +# Great care should be taken with IPV6 netblock ranges due to the large number +# of addresses involved +# +# To disable IPv6 netblocks set to "" +LF_NETBLOCK_IPV6 = "" + +############################################################################### +# SECTION:Global Lists/DYNDNS/Blocklists +############################################################################### +# Safe Chain Update. If enabled, all dynamic update chains (GALLOW*, GDENY*, +# SPAMHAUS, DSHIELD, BOGON, CC_ALLOW, CC_DENY, ALLOWDYN*) will create a new +# chain when updating, and insert it into the relevant LOCALINPUT/LOCALOUTPUT +# chain, then flush and delete the old dynamic chain and rename the new chain. +# +# This prevents a small window of opportunity opening when an update occurs and +# the dynamic chain is flushed for the new rules. +# +# This option should not be enabled on servers with long dynamic chains (e.g. +# CC_DENY/CC_ALLOW lists) and low memory. It should also not be enabled on +# Virtuozzo VPS servers with a restricted numiptent value. This is because each +# chain will effectively be duplicated while the update occurs, doubling the +# number of iptables rules +SAFECHAINUPDATE = "0" + +# If you wish to allow access from dynamic DNS records (for example if your IP +# address changes whenever you connect to the internet but you have a dedicated +# dynamic DNS record from the likes of dyndns.org) then you can list the FQDN +# records in csf.dyndns and then set the following to the number of seconds to +# poll for a change in the IP address. If the IP address has changed iptables +# will be updated. +# +# If the FQDN has multiple A records then all of the IP addresses will be +# processed. If IPV6 is enabled, then all IPv6 AAAA IP address records will +# also be allowed. +# +# A setting of 600 would check for IP updates every 10 minutes. Set the value +# to 0 to disable the feature +DYNDNS = "0" + +# To always ignore DYNDNS IP addresses in lfd blocking, set the following +# option to 1 +DYNDNS_IGNORE = "0" + +# The follow Global options allow you to specify a URL where csf can grab a +# centralised copy of an IP allow or deny block list of your own. You need to +# specify the full URL in the following options, i.e.: +# http://www.somelocation.com/allow.txt +# +# The actual retrieval of these IP's is controlled by lfd, so you need to set +# LF_GLOBAL to the interval (in seconds) when you want lfd to retrieve. lfd +# will perform the retrieval when it runs and then again at the specified +# interval. A sensible interval would probably be every 3600 seconds (1 hour). +# A minimum value of 300 is enforced for LF_GLOBAL if enabled +# +# You do not have to specify both an allow and a deny file +# +# You can also configure a global ignore file for IP's that lfd should ignore +LF_GLOBAL = "0" + +GLOBAL_ALLOW = "" +GLOBAL_DENY = "" +GLOBAL_IGNORE = "" + +# Provides the same functionality as DYNDNS but with a GLOBAL URL file. Set +# this to the URL of the file containing DYNDNS entries +GLOBAL_DYNDNS = "" + +# Set the following to the number of seconds to poll for a change in the IP +# address resoved from GLOBAL_DYNDNS +GLOBAL_DYNDNS_INTERVAL = "600" + +# To always ignore GLOBAL_DYNDNS IP addresses in lfd blocking, set the following +# option to 1 +GLOBAL_DYNDNS_IGNORE = "0" + +# Blocklists are controlled by modifying /etc/csf/csf.blocklists +# +# If you don't want BOGON rules applied to specific NICs, then list them in +# a comma separated list (e.g "eth1,eth2") +LF_BOGON_SKIP = "" + +# The following option can be used to select the method csf will use to +# retrieve URL data and files +# +# This can be set to use: +# +# 1. Perl module HTTP::Tiny +# 2. Perl module LWP::UserAgent +# 3. CURL/WGET (set location at the bottom of csf.conf if installed) +# +# HTTP::Tiny is much faster than LWP::UserAgent and is included in the csf +# distribution. LWP::UserAgent may have to be installed manually, but it can +# better support https:// URL's which also needs the LWP::Protocol::https perl +# module +# +# CURL/WGET uses the system binaries if installed but does not always provide +# good feedback when it fails. The script will first look for CURL, if that +# does not exist at the configured location it will then look for WGET +# +# Additionally, 1 or 2 are used and the retrieval fails, then if either CURL or +# WGET are available, an additional attempt will be using CURL/WGET. This is +# useful if the perl distribution has outdated modules that do not support +# modern SSL/TLS implementations +# +# To install the LWP perl modules required: +# +# On rpm based systems: +# +# yum install perl-libwww-perl.noarch perl-LWP-Protocol-https.noarch +# +# On APT based systems: +# +# apt-get install libwww-perl liblwp-protocol-https-perl +# +# Via cpan: +# +# perl -MCPAN -eshell +# cpan> install LWP LWP::Protocol::https +# +# We recommend setting this set to "2" or "3" as upgrades to csf will be +# performed over SSL as well as other URLs used when retrieving external data +# +# "1" = HTTP::Tiny +# "2" = LWP::UserAgent +# "3" = CURL/WGET (set location at the bottom of csf.conf) +URLGET = "2" + +# If you need csf/lfd to use a proxy, then you can set this option to the URL +# of the proxy. The proxy provided will be used for both HTTP and HTTPS +# connections +URLPROXY = "" + +############################################################################### +# SECTION:Country Code Lists and Settings +############################################################################### +# Country Code to CIDR allow/deny. In the following options you can allow or +# deny whole country CIDR ranges. The CIDR blocks are obtained from a selected +# source below. They also display Country Code Country and City for reported IP +# addresses and lookups +# +# There are a number of sources for these databases, before utilising them you +# need to visit each site and ensure you abide by their license provisions +# where stated: + +# 1. MaxMind +# +# MaxMind GeoLite2 Country/City and ASN databases at: +# https://dev.MaxMind.com/geoip/geoip2/geolite2/ +# This feature relies entirely on that service being available +# +# Advantages: This is a one stop shop for all of the databases required for +# these features. They provide a consistent dataset for blocking and reporting +# purposes +# +# Disadvantages: MaxMind require a license key to download their databases. +# This is free of charge, but requires the user to create an account on their +# website to generate the required key: +# +# WARNING: As of 2019-12-29, MaxMind REQUIRES you to create an account on their +# site and to generate a license key to use their databases. See: +# https://www.maxmind.com/en/geolite2/signup +# https://blog.maxmind.com/2019/12/18/significant-changes-to-accessing-and-using-geolite2-databases/ +# +# You MUST set the following to continue using the IP lookup features of csf, +# otherwise an error will be generated and the features will not work. +# Alternatively set CC_SRC below to a different provider +# +# MaxMind License Key: +MM_LICENSE_KEY = "" + +# 2. DB-IP, ipdeny.com, iptoasn.com +# +# Advantages: The ipdeny.com databases form CC blocking are better optimised +# and so are quicker to process and create fewer iptables entries. All of these +# databases are free to download without requiring login or key +# +# Disadvantages: Multiple sources mean that any one of the three could +# interrupt the provision of these features. It may also mean that there are +# inconsistences between them +# +# https://db-ip.com/db/lite.php +# http://ipdeny.com/ +# https://iptoasn.com/ +# http://download.geonames.org/export/dump/readme.txt + +# Set the following to your preferred source: +# +# "1" - MaxMind +# "2" - db-ip, ipdeny, iptoasn +# +# The default is "2" on new installations of csf, or set to "1" to use the +# MaxMind databases after obtaining a license key +CC_SRC = "2" + +# In the following options, specify the the two-letter ISO Country Code(s). +# The iptables rules are for incoming connections only +# +# Additionally, ASN numbers can also be added to the comma separated lists +# below that also list Country Codes. The same WARNINGS for Country Codes apply +# to the use of ASNs. More about Autonomous System Numbers (ASN): +# http://www.iana.org/assignments/as-numbers/as-numbers.xhtml +# ASNs must be listed as ASnnnn (where nnnn is the ASN number) +# +# You should consider using LF_IPSET when using any of the following options +# +# WARNING: These lists are never 100% accurate and some ISP's (e.g. AOL) use +# non-geographic IP address designations for their clients +# +# WARNING: Some of the CIDR lists are huge and each one requires a rule within +# the incoming iptables chain. This can result in significant performance +# overheads and could render the server inaccessible in some circumstances. For +# this reason (amongst others) we do not recommend using these options +# +# WARNING: Due to the resource constraints on VPS servers this feature should +# not be used on such systems unless you choose very small CC zones +# +# WARNING: CC_ALLOW allows access through all ports in the firewall. For this +# reason CC_ALLOW probably has very limited use and CC_ALLOW_FILTER is +# preferred +# +# Each option is a comma separated list of CC's, e.g. "US,GB,DE" +CC_DENY = "" +CC_ALLOW = "" + +# An alternative to CC_ALLOW is to only allow access from the following +# countries but still filter based on the port and packets rules. All other +# connections are dropped +CC_ALLOW_FILTER = "" + +# This option allows access from the following countries to specific ports +# listed in CC_ALLOW_PORTS_TCP and CC_ALLOW_PORTS_UDP +# +# Note: The rules for this feature are inserted after the allow and deny +# rules to still allow blocking of IP addresses +# +# Each option is a comma separated list of CC's, e.g. "US,GB,DE" +CC_ALLOW_PORTS = "" + +# All listed ports should be removed from TCP_IN/UDP_IN to block access from +# elsewhere. This option uses the same format as TCP_IN/UDP_IN +# +# An example would be to list port 21 here and remove it from TCP_IN/UDP_IN +# then only countries listed in CC_ALLOW_PORTS can access FTP +CC_ALLOW_PORTS_TCP = "" +CC_ALLOW_PORTS_UDP = "" + +# This option denies access from the following countries to specific ports +# listed in CC_DENY_PORTS_TCP and CC_DENY_PORTS_UDP +# +# Note: The rules for this feature are inserted after the allow and deny +# rules to still allow allowing of IP addresses +# +# Each option is a comma separated list of CC's, e.g. "US,GB,DE" +CC_DENY_PORTS = "" + +# This option uses the same format as TCP_IN/UDP_IN. The ports listed should +# NOT be removed from TCP_IN/UDP_IN +# +# An example would be to list port 21 here then countries listed in +# CC_DENY_PORTS cannot access FTP +CC_DENY_PORTS_TCP = "" +CC_DENY_PORTS_UDP = "" + +# This Country Code list will prevent lfd from blocking IP address hits for the +# listed CC's +# +# CC_LOOKUPS must be enabled to use this option +CC_IGNORE = "" + +# This Country Code list will only allow SMTP AUTH to be advertised to the +# listed countries in EXIM. This is to help limit attempts at distributed +# attacks against SMTP AUTH which are difficult to achive since port 25 needs +# to be open to relay email +# +# The reason why this works is that if EXIM does not advertise SMTP AUTH on a +# connection, then SMTP AUTH will not accept logins, defeating the attacks +# without restricting mail relaying +# +# This option can generate a very large list of IP addresses that could easily +# severely impact on SMTP (mail) performance, so care must be taken when +# selecting countries and if performance issues ensue +# +# The option SMTPAUTH_RESTRICT must be enabled to use this option +CC_ALLOW_SMTPAUTH = "" + +# These options can control which IP blocks are redirected to the MESSENGER +# service, if it is enabled +# +# If Country Codes are listed in CC_MESSENGER_ALLOW, then only a blocked IP +# that resolves to one of those Country Codes will be redirected to the +# MESSENGER service +# +# If Country Codes are listed in CC_MESSENGER_DENY, then a blocked IP that +# resolves to one of those Country Codes will NOT be redirected to the +# MESSENGER service +# +CC_MESSENGER_ALLOW = "" +CC_MESSENGER_DENY = "" + +# Set this option to a valid CIDR (i.e. 1 to 32) to ignore CIDR blocks smaller +# than this value when implementing CC_DENY/CC_ALLOW/CC_ALLOW_FILTER. This can +# help reduce the number of CC entries and may improve iptables throughput. +# Obviously, this will deny/allow fewer IP addresses depending on how small you +# configure the option +# +# For example, to ignore all CIDR (and single IP) entries small than a /16, set +# this option to "16". Set to "" to block all CC IP addresses +CC_DROP_CIDR = "" + +# Display Country Code and Country for reported IP addresses. This option can +# be configured to use the databases enabled at the top of this section. An +# additional option is also available if you cannot use those databases: +# +# "0" - disable +# "1" - Reports: Country Code and Country +# "2" - Reports: Country Code and Country and Region and City +# "3" - Reports: Country Code and Country and Region and City and ASN +# "4" - Reports: Country Code and Country and Region and City (db-ip.com) +# +# Note: "4" does not use the databases enabled at the top of this section +# directly for lookups. Instead it uses a URL-based lookup from +# https://db-ip.com and so avoids having to download and process the large +# databases. Please visit the https://db-ip.com and read their limitations and +# understand that this option will either cease to function or be removed by us +# if that site is abused or overloaded. ONLY use this option if you have +# difficulties using the databases enabled at the top of this section. This +# option is ONLY for IP lookups, NOT when using the CC_* options above, which +# will continue to use the databases enabled at the top of this section +# +CC_LOOKUPS = "1" + +# Display Country Code and Country for reported IPv6 addresses using the +# databases enabled at the top of this section +# +# "0" - disable +# "1" - enable and report the detail level as specified in CC_LOOKUPS +# +# This option must also be enabled to allow IPv6 support to CC_*, MESSENGER and +# PORTFLOOD +CC6_LOOKUPS = "0" + +# This option tells lfd how often to retrieve the databases for CC_ALLOW, +# CC_ALLOW_FILTER, CC_DENY, CC_IGNORE and CC_LOOKUPS (in days) +CC_INTERVAL = "14" + +############################################################################### +# SECTION:Login Failure Blocking and Alerts +############################################################################### +# The following[*] triggers are application specific. If you set LF_TRIGGER to +# "0" the value of each trigger is the number of failures against that +# application that will trigger lfd to block the IP address +# +# If you set LF_TRIGGER to a value greater than "0" then the following[*] +# application triggers are simply on or off ("0" or "1") and the value of +# LF_TRIGGER is the total cumulative number of failures that will trigger lfd +# to block the IP address +# +# Setting the application trigger to "0" disables it +LF_TRIGGER = "0" + +# If LF_TRIGGER is > "0" then LF_TRIGGER_PERM can be set to "1" to permanently +# block the IP address, or LF_TRIGGER_PERM can be set to a value greater than +# "1" and the IP address will be blocked temporarily for that value in seconds. +# For example: +# LF_TRIGGER_PERM = "1" => the IP is blocked permanently +# LF_TRIGGER_PERM = "3600" => the IP is blocked temporarily for 1 hour +# +# If LF_TRIGGER is "0", then the application LF_[application]_PERM value works +# in the same way as above and LF_TRIGGER_PERM serves no function +LF_TRIGGER_PERM = "1" + +# To only block access to the failed application instead of a complete block +# for an ip address, you can set the following to "1", but LF_TRIGGER must be +# set to "0" with specific application[*] trigger levels also set appropriately +# +# The ports that are blocked can be configured by changing the PORTS_* options +LF_SELECT = "0" + +# Send an email alert if an IP address is blocked by one of the [*] triggers +LF_EMAIL_ALERT = "1" + +# Send an email alert if an IP address is only temporarily blocked by one of +# the [*] triggers +# +# Note: LF_EMAIL_ALERT must still be enabled to get permanent block emails +LF_TEMP_EMAIL_ALERT = "1" + +# [*]Enable login failure detection of sshd connections +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_SSHD = "5" +LF_SSHD_PERM = "1" + +# [*]Enable login failure detection of ftp connections +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_FTPD = "10" +LF_FTPD_PERM = "1" + +# [*]Enable login failure detection of SMTP AUTH connections +LF_SMTPAUTH = "5" +LF_SMTPAUTH_PERM = "1" + +# [*]Enable syntax failure detection of Exim connections +LF_EXIMSYNTAX = "10" +LF_EXIMSYNTAX_PERM = "1" + +# [*]Enable login failure detection of pop3 connections +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_POP3D = "0" +LF_POP3D_PERM = "1" + +# [*]Enable login failure detection of imap connections +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_IMAPD = "0" +LF_IMAPD_PERM = "1" + +# [*]Enable login failure detection of Apache .htpasswd connections +# Due to the often high logging rate in the Apache error log, you might want to +# enable this option only if you know you are suffering from attacks against +# password protected directories +LF_HTACCESS = "5" +LF_HTACCESS_PERM = "1" + +# [*]Enable failure detection of repeated Apache mod_security rule triggers +LF_MODSEC = "5" +LF_MODSEC_PERM = "1" + +# [*]Enable login failure detection of InterWorx connections to NodeWorx and +# SiteWorx +LF_INTERWORX = "5" +LF_INTERWORX_PERM = "1" + +# [*]Enable detection of repeated BIND denied requests +# This option should be enabled with care as it will prevent blocked IPs from +# resolving any domains on the server. You might want to set the trigger value +# reasonably high to avoid this +# Example: LF_BIND = "100" +LF_BIND = "0" +LF_BIND_PERM = "1" + +# [*]Enable detection of repeated suhosin ALERTs +# Example: LF_SUHOSIN = "5" +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_SUHOSIN = "0" +LF_SUHOSIN_PERM = "1" + +# [*]Enable detection of repeated cxs ModSecurity mod_security rule triggers +# This option will block IP addresses if cxs detects a hits from the +# ModSecurity rule associated with it +# +# Note: This option takes precedence over LF_MODSEC and removes any hits +# counted towards LF_MODSEC for the cxs rule +# +# This setting should probably set very low, perhaps to 1, if you want to +# effectively block IP addresses for this trigger option +LF_CXS = "0" +LF_CXS_PERM = "1" + +# [*]Enable detection of repeated Apache mod_qos rule triggers +LF_QOS = "0" +LF_QOS_PERM = "1" + +# [*]Enable detection of repeated Apache symlink race condition triggers from +# the Apache patch provided by: +# http://www.mail-archive.com/dev@httpd.apache.org/msg55666.html +# This patch has also been included by cPanel via the easyapache option: +# "Symlink Race Condition Protection" +LF_SYMLINK = "0" +LF_SYMLINK_PERM = "1" + +# [*]Enable login failure detection of webmin connections +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_WEBMIN = "0" +LF_WEBMIN_PERM = "1" + +# Send an email alert if anyone logs in successfully using SSH +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_SSH_EMAIL_ALERT = "1" + +# Send an email alert if anyone uses su to access another account. This will +# send an email alert whether the attempt to use su was successful or not +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_SU_EMAIL_ALERT = "1" + +# Send an email alert if anyone uses sudo to access another account. This will +# send an email alert whether the attempt to use sudo was successful or not +# +# NOTE: This option could become onerous if sudo is used extensively for root +# access by administrators or control panels. It is provided for those where +# this is not the case +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_SUDO_EMAIL_ALERT = "0" + +# Send an email alert if anyone accesses webmin +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_WEBMIN_EMAIL_ALERT = "1" + +# Send an email alert if anyone logs in successfully to root on the console +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_CONSOLE_EMAIL_ALERT = "1" + +# This option will keep track of the number of "File does not exist" errors in +# HTACCESS_LOG. If the number of hits is more than LF_APACHE_404 in LF_INTERVAL +# seconds then the IP address will be blocked +# +# Care should be used with this option as it could generate many +# false-positives, especially Search Bots (use csf.rignore to ignore such bots) +# so only use this option if you know you are under this type of attack +# +# A sensible setting for this would be quite high, perhaps 200 +# +# To disable set to "0" +LF_APACHE_404 = "0" + +# If this option is set to 1 the blocks will be permanent +# If this option is > 1, the blocks will be temporary for the specified number +# of seconds +LF_APACHE_404_PERM = "3600" + +# This option will keep track of the number of "client denied by server +# configuration" errors in HTACCESS_LOG. If the number of hits is more than +# LF_APACHE_403 in LF_INTERVAL seconds then the IP address will be blocked +# +# Care should be used with this option as it could generate many +# false-positives, especially Search Bots (use csf.rignore to ignore such bots) +# so only use this option if you know you are under this type of attack +# +# A sensible setting for this would be quite high, perhaps 200 +# +# To disable set to "0" +LF_APACHE_403 = "0" + +# If this option is set to 1 the blocks will be permanent +# If this option is > 1, the blocks will be temporary for the specified number +# of seconds +LF_APACHE_403_PERM = "3600" + +# This option will keep track of the number of 401 failures in HTACCESS_LOG. +# If the number of hits is more than LF_APACHE_401 in LF_INTERVAL seconds then +# the IP address will be blocked +# +# To disable set to "0" +LF_APACHE_401 = "0" + +# This option is used to determine if the Apache error_log format contains the +# client port after the client IP. In Apache prior to v2.4, this was not the +# case. In Apache v2.4+ the error_log format can be configured using +# ErrorLogFormat, making the port directive optional +# +# Unfortunately v2.4 ErrorLogFormat places the port number after a colon next +# to the client IP by default. This makes determining client IPv6 addresses +# difficult unless we know whether the port is being appended or not +# +# lfd will attempt to autodetect the correct value if this option is set to "0" +# from the httpd binary found in common locations. If it fails to find a binary +# it will be set to "2", unless specified here +# +# The value can be set here explicitly if the autodetection does not work: +# 0 - autodetect +# 1 - no port directive after client IP +# 2 - port directive after client IP +LF_APACHE_ERRPORT = "0" + +# If this option is set to 1 the blocks will be permanent +# If this option is > 1, the blocks will be temporary for the specified number +# of seconds +LF_APACHE_401_PERM = "3600" + +# This option will send an alert if the ModSecurity IP persistent storage grows +# excessively large: https://goo.gl/rGh5sF +# +# More information on cPanel servers here: https://goo.gl/vo6xTE +# +# LF_MODSECIPDB_FILE must be set to the correct location of the database file +# +# The check is performed at lfd startup and then once per hour, the template +# used is modsecipdbalert.txt +# +# Set to "0" to disable this option, otherwise it is the threshold size of the +# file to report in gigabytes, e.g. set to 5 for 5GB +LF_MODSECIPDB_ALERT = "0" + +# This is the location of the persistent IP storage file on the server, e.g.: +# /var/run/modsecurity/data/ip.pag +# /var/cpanel/secdatadir/ip.pag +# /var/cache/modsecurity/ip.pag +# /usr/local/apache/conf/modsec/data/msa/ip.pag +# /var/tmp/ip.pag +# /tmp/ip.pag +LF_MODSECIPDB_FILE = "/var/run/modsecurity/data/ip.pag" + +# System Exploit Checking. This option is designed to perform a series of tests +# to send an alert in case a possible server compromise is detected +# +# To enable this feature set the following to the checking interval in seconds +# (a value of 300 would seem sensible). +# +# To disable set to "0" +LF_EXPLOIT = "300" + +# This comma separated list allows you to ignore tests LF_EXPLOIT performs +# +# For the SUPERUSER check, you can list usernames in csf.suignore to have them +# ignored for that test +# +# Valid tests are: +# SUPERUSER +# +# If you want to ignore a test add it to this as a comma separated list, e.g. +# "SUPERUSER" +LF_EXPLOIT_IGNORE = "" + +# Set the time interval to track login and other LF_ failures within (seconds), +# i.e. LF_TRIGGER failures within the last LF_INTERVAL seconds +LF_INTERVAL = "3600" + +# This is how long the lfd process sleeps (in seconds) before processing the +# log file entries and checking whether other events need to be triggered +LF_PARSE = "5" + +# This is the interval that is used to flush reports of usernames, files and +# pids so that persistent problems continue to be reported, in seconds. +# A value of 3600 seems sensible +LF_FLUSH = "3600" + +# Under some circumstances iptables can fail to include a rule instruction, +# especially if more than one request is made concurrently. In this event, a +# permanent block entry may exist in csf.deny, but not in iptables. +# +# This option instructs csf to deny an already blocked IP address the number +# of times set. The downside, is that there will be multiple entries for an IP +# address in csf.deny and possibly multiple rules for the same IP address in +# iptables. This needs to be taken into consideration when unblocking such IP +# addresses. +# +# Set to "0" to disable this feature. Do not set this too high for the reasons +# detailed above (e.g. "5" should be more than enough) +LF_REPEATBLOCK = "0" + +# By default csf will create both an inbound and outbound blocks from/to an IP +# unless otherwise specified in csf.deny and GLOBAL_DENY. This is the most +# effective way to block IP traffic. This option instructs csf to only block +# inbound traffic from those IP's and so reduces the number of iptables rules, +# but at the expense of less effectiveness. For this reason we recommend +# leaving this option disabled +# +# Set to "0" to disable this feature - the default +LF_BLOCKINONLY = "0" + +############################################################################### +# SECTION:CloudFlare +############################################################################### +# This features provides interaction with the CloudFlare Firewall +# +# As CloudFlare is a reverse proxy, any attacking IP addresses (so far as +# iptables is concerned) come from the CloudFlare IP's. To counter this, an +# Apache module (mod_cloudflare) is available that obtains the true attackers +# IP from a custom HTTP header record (similar functionality is available +# for other HTTP daemons +# +# However, despite now knowing the true attacking IP address, iptables cannot +# be used to block that IP as the traffic is still coming from the CloudFlare +# servers +# +# CloudFlare have provided a Firewall feature within the user account where +# rules can be added to block, challenge or whitelist IP addresses +# +# Using the CloudFlare API, this feature adds and removes attacking IPs from +# that firewall and provides CLI (and via the UI) additional commands +# +# See /etc/csf/readme.txt for more information about this feature and the +# restrictions for its use BEFORE enabling this feature +CF_ENABLE = "0" + +# This can be set to either "block" or "challenge" (see CloudFlare docs) +CF_BLOCK = "block" + +# This setting determines how long the temporary block will apply within csf +# and CloudFlare, keeping them in sync +# +# Block duration in seconds - overrides perm block or time of individual blocks +# in lfd for block triggers +CF_TEMP = "3600" + +############################################################################### +# SECTION:Directory Watching & Integrity +############################################################################### +# Enable Directory Watching. This enables lfd to check /tmp and /dev/shm +# directories for suspicious files, i.e. script exploits. If a suspicious +# file is found an email alert is sent. One alert per file per LF_FLUSH +# interval is sent +# +# To enable this feature set the following to the checking interval in seconds. +# To disable set to "0" +LF_DIRWATCH = "300" + +# To remove any suspicious files found during directory watching, enable the +# following. These files will be appended to a tarball in +# /var/lib/csf/suspicious.tar +LF_DIRWATCH_DISABLE = "0" + +# This option allows you to have lfd watch a particular file or directory for +# changes and should they change and email alert using watchalert.txt is sent +# +# To enable this feature set the following to the checking interval in seconds +# (a value of 60 would seem sensible) and add your entries to csf.dirwatch +# +# Set to disable set to "0" +LF_DIRWATCH_FILE = "0" + +# System Integrity Checking. This enables lfd to compare md5sums of the +# servers OS binary application files from the time when lfd starts. If the +# md5sum of a monitored file changes an alert is sent. This option is intended +# as an IDS (Intrusion Detection System) and is the last line of detection for +# a possible root compromise. +# +# There will be constant false-positives as the servers OS is updated or +# monitored application binaries are updated. However, unexpected changes +# should be carefully inspected. +# +# Modified files will only be reported via email once. +# +# To enable this feature set the following to the checking interval in seconds +# (a value of 3600 would seem sensible). This option may increase server I/O +# load onto the server as it checks system binaries. +# +# To disable set to "0" +LF_INTEGRITY = "3600" + +############################################################################### +# SECTION:Distributed Attacks +############################################################################### +# Distributed Account Attack. This option will keep track of login failures +# from distributed IP addresses to a specific application account. If the +# number of failures matches the trigger value above, ALL of the IP addresses +# involved in the attack will be blocked according to the temp/perm rules above +# +# Tracking applies to LF_SSHD, LF_FTPD, LF_SMTPAUTH, LF_POP3D, LF_IMAPD, +# LF_HTACCESS +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_DISTATTACK = "0" + +# Set the following to the minimum number of unique IP addresses that trigger +# LF_DISTATTACK +LF_DISTATTACK_UNIQ = "2" + +# Distributed FTP Logins. This option will keep track of successful FTP logins. +# If the number of successful logins to an individual account is at least +# LF_DISTFTP in LF_DIST_INTERVAL from at least LF_DISTFTP_UNIQ IP addresses, +# then all of the IP addresses will be blocked +# +# This option can help mitigate the common FTP account compromise attacks that +# use a distributed network of zombies to deface websites +# +# A sensible setting for this might be 5, depending on how many different +# IP addresses you expect to an individual FTP account within LF_DIST_INTERVAL +# +# To disable set to "0" +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_DISTFTP = "0" + +# Set the following to the minimum number of unique IP addresses that trigger +# LF_DISTFTP. LF_DISTFTP_UNIQ must be <= LF_DISTFTP for this to work +LF_DISTFTP_UNIQ = "3" + +# If this option is set to 1 the blocks will be permanent +# If this option is > 1, the blocks will be temporary for the specified number +# of seconds +LF_DISTFTP_PERM = "1" + +# Send an email alert if LF_DISTFTP is triggered +LF_DISTFTP_ALERT = "1" + +# Distributed SMTP Logins. This option will keep track of successful SMTP +# logins. If the number of successful logins to an individual account is at +# least LF_DISTSMTP in LF_DIST_INTERVAL from at least LF_DISTSMTP_UNIQ IP +# addresses, then all of the IP addresses will be blocked. These options only +# apply to the exim MTA +# +# This option can help mitigate the common SMTP account compromise attacks that +# use a distributed network of zombies to send spam +# +# A sensible setting for this might be 5, depending on how many different +# IP addresses you expect to an individual SMTP account within LF_DIST_INTERVAL +# +# To disable set to "0" +LF_DISTSMTP = "0" + +# Set the following to the minimum number of unique IP addresses that trigger +# LF_DISTSMTP. LF_DISTSMTP_UNIQ must be <= LF_DISTSMTP for this to work +LF_DISTSMTP_UNIQ = "3" + +# If this option is set to 1 the blocks will be permanent +# If this option is > 1, the blocks will be temporary for the specified number +# of seconds +LF_DISTSMTP_PERM = "1" + +# Send an email alert if LF_DISTSMTP is triggered +LF_DISTSMTP_ALERT = "1" + +# This is the interval during which a distributed FTP or SMTP attack is +# measured +LF_DIST_INTERVAL = "300" + +# If LF_DISTFTP or LF_DISTSMTP is triggered, then if the following contains the +# path to a script, it will run the script and pass the following as arguments: +# +# LF_DISTFTP/LF_DISTSMTP +# account name +# log file text +# +# The action script must have the execute bit and interpreter (shebang) set +LF_DIST_ACTION = "" + +############################################################################### +# SECTION:Login Tracking +############################################################################### +# Block POP3 logins if greater than LT_POP3D times per hour per account per IP +# address (0=disabled) +# +# This is a temporary block for the rest of the hour, afterwhich the IP is +# unblocked +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LT_POP3D = "0" + +# Block IMAP logins if greater than LT_IMAPD times per hour per account per IP +# address (0=disabled) - not recommended for IMAP logins due to the ethos +# within which IMAP works. If you want to use this, setting it quite high is +# probably a good idea +# +# This is a temporary block for the rest of the hour, afterwhich the IP is +# unblocked +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LT_IMAPD = "0" + +# Send an email alert if an account exceeds LT_POP3D/LT_IMAPD logins per hour +# per IP +LT_EMAIL_ALERT = "1" + +# If LF_PERMBLOCK is enabled but you do not want this to apply to +# LT_POP3D/LT_IMAPD, then enable this option +LT_SKIPPERMBLOCK = "0" + +############################################################################### +# SECTION:Connection Tracking +############################################################################### +# Connection Tracking. This option enables tracking of all connections from IP +# addresses to the server. If the total number of connections is greater than +# this value then the offending IP address is blocked. This can be used to help +# prevent some types of DOS attack. +# +# Care should be taken with this option. It's entirely possible that you will +# see false-positives. Some protocols can be connection hungry, e.g. FTP, IMAPD +# and HTTP so it could be quite easy to trigger, especially with a lot of +# closed connections in TIME_WAIT. However, for a server that is prone to DOS +# attacks this may be very useful. A reasonable setting for this option might +# be around 300. +# +# To disable this feature, set this to 0 +CT_LIMIT = "0" + +# Connection Tracking interval. Set this to the the number of seconds between +# connection tracking scans +CT_INTERVAL = "30" + +# Send an email alert if an IP address is blocked due to connection tracking +CT_EMAIL_ALERT = "1" + +# If you want to make IP blocks permanent then set this to 1, otherwise blocks +# will be temporary and will be cleared after CT_BLOCK_TIME seconds +CT_PERMANENT = "0" + +# If you opt for temporary IP blocks for CT, then the following is the interval +# in seconds that the IP will remained blocked for (e.g. 1800 = 30 mins) +CT_BLOCK_TIME = "1800" + +# If you don't want to count the TIME_WAIT state against the connection count +# then set the following to "1" +CT_SKIP_TIME_WAIT = "0" + +# If you only want to count specific states (e.g. SYN_RECV) then add the states +# to the following as a comma separated list. E.g. "SYN_RECV,TIME_WAIT" +# +# Leave this option empty to count all states against CT_LIMIT +CT_STATES = "" + +# If you only want to count specific ports (e.g. 80,443) then add the ports +# to the following as a comma separated list. E.g. "80,443" +# +# Leave this option empty to count all ports against CT_LIMIT +CT_PORTS = "" + +# If the total number of connections from a class C subnet is greater than this +# value then the offending subnet is blocked according to the other CT_* +# settings +# +# This option can be used to help prevent some types of DOS attack where a +# range of IP's between x.y.z.1-255 has connected to the server +# +# If you use a reverse proxy service such as Cloudflare you should not enable +# this option, or should exclude the ports that you have proxied in CT_PORTS +# +# To disable this feature, set this to 0 +CT_SUBNET_LIMIT = "0" + +############################################################################### +# SECTION:Process Tracking +############################################################################### +# Process Tracking. This option enables tracking of user and nobody processes +# and examines them for suspicious executables or open network ports. Its +# purpose is to identify potential exploit processes that are running on the +# server, even if they are obfuscated to appear as system services. If a +# suspicious process is found an alert email is sent with relevant information. +# It is then the responsibility of the recipient to investigate the process +# further as the script takes no further action +# +# The following is the number of seconds a process has to be active before it +# is inspected. If you set this time too low, then you will likely trigger +# false-positives with CGI or PHP scripts. +# Set the value to 0 to disable this feature +PT_LIMIT = "60" + +# How frequently processes are checked in seconds +PT_INTERVAL = "60" + +# If you want process tracking to highlight php or perl scripts that are run +# through apache then disable the following, +# i.e. set it to 0 +# +# While enabling this setting will reduce false-positives, having it set to 0 +# does provide better checking for exploits running on the server +PT_SKIP_HTTP = "0" + +# lfd will report processes, even if they're listed in csf.pignore, if they're +# tagged as (deleted) by Linux. This information is provided in Linux under +# /proc/PID/exe. A (deleted) process is one that is running a binary that has +# the inode for the file removed from the file system directory. This usually +# happens when the binary has been replaced due to an upgrade for it by the OS +# vendor or another third party (e.g. cPanel). You need to investigate whether +# this is indeed the case to be sure that the original binary has not been +# replaced by a rootkit or is running an exploit. +# +# Note: If a deleted executable process is detected and reported then lfd will +# not report children of the parent (or the parent itself if a child triggered +# the report) if the parent is also a deleted executable process +# +# To stop lfd reporting such process you need to restart the daemon to which it +# belongs and therefore run the process using the replacement binary (presuming +# one exists). This will normally mean running the associated startup script in +# /etc/init.d/ +# +# If you do want lfd to report deleted binary processes, set to 1 +PT_DELETED = "0" + +# If a PT_DELETED event is triggered, then if the following contains the path to +# a script, it will be run in a child process and passed the executable, pid, +# account for the process, and parent pid +# +# The action script must have the execute bit and interpreter (shebang) set. An +# example is provided in /usr/local/csf/bin/pt_deleted_action.pl +# +# WARNING: Make sure you read and understand the potential security +# implications of such processes in PT_DELETED above before simply restarting +# such processes with a script +PT_DELETED_ACTION = "" + +# User Process Tracking. This option enables the tracking of the number of +# process any given account is running at one time. If the number of processes +# exceeds the value of the following setting an email alert is sent with +# details of those processes. If you specify a user in csf.pignore it will be +# ignored +# +# Set to 0 to disable this feature +PT_USERPROC = "10" + +# This User Process Tracking option sends an alert if any user process exceeds +# the virtual memory usage set (MB). To ignore specific processes or users use +# csf.pignore +# +# Set to 0 to disable this feature +PT_USERMEM = "512" + +# This User Process Tracking option sends an alert if any user process exceeds +# the RSS memory usage set (MB) - RAM used, not virtual. To ignore specific +# processes or users use csf.pignore +# +# Set to 0 to disable this feature +PT_USERRSS = "256" + +# This User Process Tracking option sends an alert if any linux user process +# exceeds the time usage set (seconds). To ignore specific processes or users +# use csf.pignore +# +# Set to 0 to disable this feature +PT_USERTIME = "1800" + +# If this option is set then processes detected by PT_USERMEM, PT_USERTIME or +# PT_USERPROC are killed +# +# Warning: We don't recommend enabling this option unless absolutely necessary +# as it can cause unexpected problems when processes are suddenly terminated. +# It can also lead to system processes being terminated which could cause +# stability issues. It is much better to leave this option disabled and to +# investigate each case as it is reported when the triggers above are breached +# +# Note: Processes that are running deleted excecutables (see PT_DELETED) will +# not be killed by lfd +PT_USERKILL = "0" + +# If you want to disable email alerts if PT_USERKILL is triggered, then set +# this option to 0 +PT_USERKILL_ALERT = "1" + +# If a PT_* event is triggered, then if the following contains the path to +# a script, it will be run in a child process and passed the PID(s) of the +# process(es) in a comma separated list. +# +# The action script must have the execute bit and interpreter (shebang) set +PT_USER_ACTION = "" + +# Check the PT_LOAD_AVG minute Load Average (can be set to 1 5 or 15 and +# defaults to 5 if set otherwise) on the server every PT_LOAD seconds. If the +# load average is greater than or equal to PT_LOAD_LEVEL then an email alert is +# sent. lfd then does not report subsequent high load until PT_LOAD_SKIP +# seconds has passed to prevent email floods. +# +# Set PT_LOAD to "0" to disable this feature +PT_LOAD = "30" +PT_LOAD_AVG = "5" +PT_LOAD_LEVEL = "6" +PT_LOAD_SKIP = "3600" + +# This is the Apache Server Status URL used in the email alert. Requires the +# Apache mod_status module to be installed and configured correctly +PT_APACHESTATUS = "http://127.0.0.1/server-status" + +# If a PT_LOAD event is triggered, then if the following contains the path to +# a script, it will be run in a child process. For example, the script could +# contain commands to terminate and restart httpd, php, exim, etc incase of +# looping processes. The action script must have the execute bit an +# interpreter (shebang) set +PT_LOAD_ACTION = "" + +# Fork Bomb Protection. This option checks the number of processes with the +# same session id and if greater than the value set, the whole session tree is +# terminated and an alert sent +# +# You can see an example of common session id processes on most Linux systems +# using: "ps axf -O sid" +# +# On cPanel servers, PT_ALL_USERS should be enabled to use this option +# effectively +# +# This option will check root owned processes. Session id 0 and 1 will always +# be ignored as they represent kernel and init processes. csf.pignore will be +# honoured, but bear in mind that a session tree can contain a variety of users +# and executables +# +# Care needs to be taken to ensure that this option only detects runaway fork +# bombs, so should be set higher than any session tree is likely to get (e.g. +# httpd could have 100s of legitimate children on very busy systems). A +# sensible starting point on most servers might be 250 +PT_FORKBOMB = "0" + +# Terminate hung SSHD sessions. When under an SSHD login attack, SSHD processes +# are often left hanging after their connecting IP addresses have been blocked +# +# This option will terminate the SSH processes created by the blocked IP. This +# option is preferred over PT_SSHDHUNG +PT_SSHDKILL = "0" + +# This option will terminate all processes with the cmdline of "sshd: unknown +# [net]" or "sshd: unknown [priv]" if they have been running for more than 60 +# seconds +PT_SSHDHUNG = "0" + +############################################################################### +# SECTION:Port Scan Tracking +############################################################################### +# Port Scan Tracking. This feature tracks port blocks logged by iptables to +# syslog. If an IP address generates a port block that is logged more than +# PS_LIMIT within PS_INTERVAL seconds, the IP address will be blocked. +# +# This feature could, for example, be useful for blocking hackers attempting +# to access the standard SSH port if you have moved it to a port other than 22 +# and have removed 22 from the TCP_IN list so that connection attempts to the +# old port are being logged +# +# This feature blocks all iptables blocks from the iptables logs, including +# repeated attempts to one port or SYN flood blocks, etc +# +# Note: This feature will only track iptables blocks from the log file set in +# IPTABLES_LOG below and if you have DROP_LOGGING enabled. However, it will +# cause redundant blocking with DROP_IP_LOGGING enabled +# +# Warning: It's possible that an elaborate DDOS (i.e. from multiple IP's) +# could very quickly fill the iptables rule chains and cause a DOS in itself. +# The DENY_IP_LIMIT should help to mitigate such problems with permanent blocks +# and the DENY_TEMP_IP_LIMIT with temporary blocks +# +# Set PS_INTERVAL to "0" to disable this feature. A value of between 60 and 300 +# would be sensible to enable this feature +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +PS_INTERVAL = "0" +PS_LIMIT = "10" + +# You can specify the ports and/or port ranges that should be tracked by the +# Port Scan Tracking feature. The following setting is a comma separated list +# of those ports and uses the same format as TCP_IN. The setting of +# 0:65535,ICMP,INVALID,OPEN,BRD covers all ports +# +# Special values are: +# ICMP - include ICMP blocks (see ICMP_*) +# INVALID - include INVALID blocks (see PACKET_FILTER) +# OPEN - include TCP_IN and UDP_IN open port blocks - *[proto]_IN Blocked* +# BRD - include UDP Broadcast IPs, otherwise they are ignored +PS_PORTS = "0:65535,ICMP" + +# To specify how many different ports qualifies as a Port Scan you can increase +# the following from the default value of 1. The risk in doing so will mean +# that persistent attempts to attack a specific closed port will not be +# detected and blocked +PS_DIVERSITY = "1" + +# You can select whether IP blocks for Port Scan Tracking should be temporary +# or permanent. Set PS_PERMANENT to "0" for temporary and "1" for permanent +# blocking. If set to "0" PS_BLOCK_TIME is the amount of time in seconds to +# temporarily block the IP address for +PS_PERMANENT = "0" +PS_BLOCK_TIME = "3600" + +# Set the following to "1" to enable Port Scan Tracking email alerts, set to +# "0" to disable them +PS_EMAIL_ALERT = "1" + +############################################################################### +# SECTION:User ID Tracking +############################################################################### +# User ID Tracking. This feature tracks UID blocks logged by iptables to +# syslog. If a UID generates a port block that is logged more than UID_LIMIT +# times within UID_INTERVAL seconds, an alert will be sent +# +# Note: This feature will only track iptables blocks from the log file set in +# IPTABLES_LOG and if DROP_OUT_LOGGING and DROP_UID_LOGGING are enabled. +# +# To ignore specific UIDs list them in csf.uidignore and then restart lfd +# +# Set UID_INTERVAL to "0" to disable this feature. A value of between 60 and 300 +# would be sensible to enable this feature +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +UID_INTERVAL = "0" +UID_LIMIT = "10" + +# You can specify the ports and/or port ranges that should be tracked by the +# User ID Tracking feature. The following setting is a comma separated list +# of those ports and uses the same format as TCP_OUT. The default setting of +# 0:65535,ICMP covers all ports +UID_PORTS = "0:65535,ICMP" + +############################################################################### +# SECTION:Account Tracking +############################################################################### +# Account Tracking. The following options enable the tracking of modifications +# to the accounts on a server. If any of the enabled options are triggered by +# a modifications to an account, an alert email is sent. Only the modification +# is reported. The cause of the modification will have to be investigated +# manually +# +# You can set AT_ALERT to the following: +# 0 = disable this feature +# 1 = enable this feature for all accounts +# 2 = enable this feature only for superuser accounts (UID = 0, e.g. root, etc) +# 3 = enable this feature only for the root account +AT_ALERT = "2" + +# This options is the interval between checks in seconds +AT_INTERVAL = "60" + +# Send alert if a new account is created +AT_NEW = "1" + +# Send alert if an existing account is deleted +AT_OLD = "1" + +# Send alert if an account password has changed +AT_PASSWD = "1" + +# Send alert if an account uid has changed +AT_UID = "1" + +# Send alert if an account gid has changed +AT_GID = "1" + +# Send alert if an account login directory has changed +AT_DIR = "1" + +# Send alert if an account login shell has changed +AT_SHELL = "1" + +############################################################################### +# SECTION:Integrated User Interface +############################################################################### +# Integrated User Interface. This feature provides a HTML UI to csf and lfd, +# without requiring a control panel or web server. The UI runs as a sub process +# to the lfd daemon +# +# As it runs under the root account and successful login provides root access +# to the server, great care should be taken when configuring and using this +# feature. There are additional restrictions to enhance secure access to the UI +# +# See readme.txt for more information about using this feature BEFORE enabling +# it for security and access reasons +# +# 1 to enable, 0 to disable +UI = "0" + +# Set this to the port that want to bind this service to. You should configure +# this port to be >1023 and different from any other port already being used +# +# Do NOT enable access to this port in TCP_IN, instead only allow trusted IP's +# to the port using Advanced Allow Filters (see readme.txt) +UI_PORT = "6666" + +# Optionally set the IP address to bind to. Normally this should be left blank +# to bind to all IP addresses on the server. +# +# If the server is configured for IPv6 but the IP to bind to is IPv4, then the +# IP address MUST use the IPv6 representation. For example 1.2.3.4 must use +# ::ffff:1.2.3.4 +# +# Leave blank to bind to all IP addresses on the server +UI_IP = "" + +# This should be a secure, hard to guess username +# +# This must be changed from the default +UI_USER = "username" + +# This should be a secure, hard to guess password. That is, at least 8 +# characters long with a mixture of upper and lowercase characters plus +# numbers and non-alphanumeric characters +# +# This must be changed from the default +UI_PASS = "password" + +# This is the login session timeout. If there is no activity for a logged in +# session within this number of seconds, the session will timeout and a new +# login will be required +# +# For security reasons, you should always keep this option low (i.e 60-300) +UI_TIMEOUT = "300" + +# This is the maximum concurrent connections allowed to the server. The default +# value should be sufficient +UI_CHILDREN = "5" + +# The number of login retries allowed within a 24 hour period. A successful +# login from the IP address will clear the failures +# +# For security reasons, you should always keep this option low (i.e 0-10) +UI_RETRY = "5" + +# If enabled, this option will add the connecting IP address to the file +# /etc/csf/ui/ui.ban after UI_RETRY login failures. The IP address will not be +# able to login to the UI while it is listed in this file. The UI_BAN setting +# does not refer to any of the csf/lfd allow or ignore files, e.g. csf.allow, +# csf.ignore, etc. +# +# For security reasons, you should always enable this option +UI_BAN = "1" + +# If enabled, only IPs (or CIDR's) listed in the file /etc/csf/ui/ui.allow will +# be allowed to login to the UI. The UI_ALLOW setting does not refer to any of +# the csf/lfd allow or ignore files, e.g. csf.allow, csf.ignore, etc. +# +# For security reasons, you should always enable this option and use ui.allow +UI_ALLOW = "1" + +# If enabled, this option will trigger an iptables block through csf after +# UI_RETRY login failures +# +# 0 = no block;1 = perm block;nn=temp block for nn secs +UI_BLOCK = "1" + +# This controls what email alerts are sent with regards to logins to the UI. It +# uses the uialert.txt template +# +# 4 = login success + login failure/ban/block + login attempts +# 3 = login success + login failure/ban/block +# 2 = login failure/ban/block +# 1 = login ban/block +# 0 = disabled +UI_ALERT = "4" + +# This is the SSL cipher list that the Integrated UI will negotiate from +UI_CIPHER = "ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:-LOW:-SSLv2:-EXP:!kEDH" + +# This is the SSL protocol version used. See IO::Socket::SSL if you wish to +# change this and to understand the implications of changing it +UI_SSL_VERSION = "SSLv23:!SSLv3:!SSLv2" + +# If cxs is installed then enabling this option will provide a dropdown box to +# switch between applications +UI_CXS = "0" + +# There is a modified installation of ConfigServer Explorer (cse) provided with +# the csf distribution. If this option is enabled it will provide a dropdown +# box to switch between applications +UI_CSE = "0" + +############################################################################### +# SECTION:Messenger service +############################################################################### +# Messenger service. This feature allows the display of a message to a blocked +# connecting IP address to inform the user that they are blocked in the +# firewall. This can help when users get themselves blocked, e.g. due to +# multiple login failures. The service is provided by two daemons running on +# ports providing either an HTML or TEXT message +# +# This feature does not work on servers that do not have the iptables module +# ipt_REDIRECT loaded. Typically, this will be with MONOLITHIC kernels. VPS +# server admins should check with their VPS host provider that the iptables +# module is included +# +# IPv6 will need the IO::Socket::INET6 perl module +# +# For further information on features and limitations refer to the csf +# readme.txt +# +# Note: Run /etc/csf/csftest.pl to check whether this option will function on +# this server +# +# 1 to enable, 0 to disable +MESSENGER = "0" + +# Provide this service to temporary IP address blocks +MESSENGER_TEMP = "1" + +# Provide this service to permanent IP address blocks +MESSENGER_PERM = "1" + +# User account to run the service servers under. We recommend creating a +# specific non-priv, non-shell account for this purpose +# +# Note: When using MESSENGERV2, this account must NOT be a valid control panel +# account, it must be created manually as explained in the csf readme.txt +MESSENGER_USER = "csf" + +# This option points to the file(s) containing the Apache VirtualHost SSL +# definitions. This can be a file glob if there are multiple files to search. +# Only Apache v2 SSL VirtualHost definitions are supported +# +# This is used by MESSENGERV1 and MESSENGERV2 only +MESSENGER_HTTPS_CONF = "/etc/httpd/conf.d/ssl.conf" + +# The following options can be specified to provide a default fallback +# certificate to be used if either SNI is not supported or a hosted domain does +# not have an SSL certificate. If a fallback is not provided, one of the certs +# obtained from MESSENGER_HTTPS_CONF will be used +# +# This is used by MESSENGERV1 and MESSENGERV2 only +MESSENGER_HTTPS_KEY = "/etc/pki/tls/private/localhost.key" +MESSENGER_HTTPS_CRT = "/etc/pki/tls/certs/localhost.crt" + +# Set this to the port that will receive the HTTPS HTML message. You should +# configure this port to be >1023 and different from the TEXT and HTML port. Do +# NOT enable access to this port in TCP_IN. This option requires the perl +# module IO::Socket::SSL at a version level that supports SNI (1.83+). +# Additionally the version of openssl on the server must also support SNI +# +# The option uses existing SSL certificates on the server for each domain to +# maintain a secure connection without browser warnings. It uses SNI to choose +# the correct certificate to use for each client connection +# +# Warning: On some servers the amount of memory used by the HTTPS MESSENGER +# service can become significant depending on various factors associated with +# the use of IO::Socket::SSL including the number of domains and certificates +# served. This is normally only an issue if using MESSENGERV1 +MESSENGER_HTTPS = "8887" + +# This comma separated list are the HTTPS HTML ports that will be redirected +# for the blocked IP address. If you are using per application blocking +# (LF_TRIGGER) then only the relevant block port will be redirected to the +# messenger port +# +# Recommended setting "443" plus any end-user control panel SSL ports. So, for +# cPanel: "443,2083,2096" +MESSENGER_HTTPS_IN = "443,2443" + +# Set this to the port that will receive the HTML message. You should configure +# this port to be >1023 and different from the TEXT port. Do NOT enable access +# to this port in TCP_IN +MESSENGER_HTML = "8888" + +# This comma separated list are the HTML ports that will be redirected for the +# blocked IP address. If you are using per application blocking (LF_TRIGGER) +# then only the relevant block port will be redirected to the messenger port +MESSENGER_HTML_IN = "80,2080" + +# Set this to the port that will receive the TEXT message. You should configure +# this port to be >1023 and different from the HTML port. Do NOT enable access +# to this port in TCP_IN +MESSENGER_TEXT = "8889" + +# This comma separated list are the TEXT ports that will be redirected for the +# blocked IP address. If you are using per application blocking (LF_TRIGGER) +# then only the relevant block port will be redirected to the messenger port +MESSENGER_TEXT_IN = "21" + +# These settings limit the rate at which connections can be made to the +# messenger service servers. Its intention is to provide protection from +# attacks or excessive connections to the servers. If the rate is exceeded then +# iptables will revert for the duration to the normal blocking activity +# +# See the iptables man page for the correct --limit rate syntax +MESSENGER_RATE = "100/s" +MESSENGER_BURST = "150" + +# MESSENGERV1 only: +#------------------------------------------------------------------------------ +# This is the maximum concurrent connections allowed to each service server +# +# Note: This number should be increased to cater for the number of local images +# served by this page, including one for favicon.ico. This is because each +# image displayed counts as an additional connection +MESSENGER_CHILDREN = "20" + +# This options ignores ServerAlias definitions that begin with "mail.". This +# can help reduce memory usage on systems that do not require the use of +# MESSENGER_HTTPS on those subdomains +# +# Set to 0 to include these ServerAlias definitions +MESSENGER_HTTPS_SKIPMAIL = "1" + +# MESSENGERV2 only: +#------------------------------------------------------------------------------ +# MESSENGERV2. This option is available on cPanel servers running Apache v2.4+ +# under EA4. +# +# This uses the Apache http daemon to provide the web server functionality for +# the MESSENGER HTML and HTTPS services. It uses a fraction of the resources +# that the lfd inbuilt service uses and overcomes the memory overhead of using +# the MESSENGER HTTPS service +# +# For more information consult readme.txt before enabling this option +#MESSENGERV2 = "0" + +# MESSENGERV3 only: +#------------------------------------------------------------------------------ +# MESSENGERV3. This option is available on any server running Apache v2.4+, +# Litespeed or Openlitespeed +# +# This uses the web server http daemon to provide the web server functionality +# for the MESSENGER HTML and HTTPS services. It uses a fraction of the +# resources that the lfd inbuilt service uses and overcomes the memory overhead +# of using the MESSENGER HTTPS service +# +# For more information consult readme.txt before enabling this option +MESSENGERV3 = "0" + +# This is the file or directory where the additional web server configuration +# file should be included +MESSENGERV3LOCATION = "/etc/httpd/conf.d/" + +# This is the command to restart the web server +MESSENGERV3RESTART = "service httpd restart" + +# This is the command to test the validity of the web server configuration. If +# using Litespeed, set to "" +MESSENGERV3TEST = "/usr/sbin/apachectl -t" + +# This must be set to the main httpd.conf file for either Apache or Litespeed +MESSENGERV3HTTPS_CONF = "/etc/httpd/conf/httpd.conf" + +# This can be set to either: +# "apache" - for servers running Apache v2.4+ or Litespeed using Apache +# configuration +# "litespeed" - for Litespeed or Openlitespeed +MESSENGERV3WEBSERVER = "apache" + +# On creation, set the MESSENGER_USER public_html directory permissions to +# Note: If you precreate this directory the following setting will be ignored +MESSENGERV3PERMS = "711" + +# On creation, set the MESSENGER_USER public_html directory group user to +# Note: If you precreate this directory the following setting will be ignored +MESSENGERV3GROUP = "apache" + +# This is the web server configuration to allow PHP scripts to run. If left +# empty, the MESSENGER service will try to configure this. If this does not +# work, this should be set as an "Include /path/to/csf_php.conf" or similar +# file which must contain appropriate web server configuration to allow PHP +# scripts to run. This line will be included within each MESSENGER VirtualHost +# container. This will replace the [MESSENGERV3PHPHANDLER] line from the csf +# webserver template files +MESSENGERV3PHPHANDLER = "" + +# RECAPTCHA: +#------------------------------------------------------------------------------ +# The RECAPTCHA options provide a way for end-users that have blocked +# themselves in the firewall to unblock themselves. +# +# A valid Google ReCAPTCHA (v2) key set is required for this feature from: +# https://www.google.com/recaptcha/intro/index.html +# +# When configuring a new reCAPTCHA API key set you must ensure that the option +# for "Domain Name Validation" is unticked so that the same reCAPTCHA can be +# used for all domains hosted on the server. lfd then checks that the hostname +# of the request resolves to an IP on this server +# +# This feature requires the installation of the LWP::UserAgent perl module (see +# option URLGET for more details) +# +# The template used for this feature is /etc/csf/messenger/index.recaptcha.html +# +# Note: An unblock will fail if the end-users IP is located in a netblock, +# blocklist or CC_* deny entry +RECAPTCHA_SITEKEY = "" +RECAPTCHA_SECRET = "" + +# Send an email when an IP address successfully attempts to unblock themselves. +# This does not necessarily mean the IP was unblocked, only that the +# post-recaptcha unblock request was attempted +# +# Set to "0" to disable +RECAPTCHA_ALERT = "1" + +# If the server uses NAT then resolving the hostname to hosted IPs will likely +# not succeed. In that case, the external IP addresses must be listed as comma +# separated list here +RECAPTCHA_NAT = "" + +############################################################################### +# SECTION:lfd Clustering +############################################################################### +# lfd Clustering. This allows the configuration of an lfd cluster environment +# where a group of servers can share blocks and configuration option changes. +# Included are CLI and UI options to send requests to the cluster. +# +# See the readme.txt file for more information and details on setup and +# security risks. +# +# Set this to a comma separated list of cluster member IP addresses to send +# requests to. Alternatively, it can be set to the full path of a file that +# will read in one IP per line, e.g.: +# "/etc/csf/cluster_sendto.txt" +CLUSTER_SENDTO = "" + +# Set this to a comma separated list of cluster member IP addresses to receive +# requests from. Alternatively, it can be set to the full path of a file that +# will read in one IP per line, e.g.: +# "/etc/csf/cluster_recvfrom.txt" +CLUSTER_RECVFROM = "" + +# IP address of the master node in the cluster allowed to send CLUSTER_CONFIG +# changes +CLUSTER_MASTER = "" + +# If this is a NAT server, set this to the public IP address of this server +CLUSTER_NAT = "" + +# If a cluster member should send requests on an IP other than the default IP, +# set it here +CLUSTER_LOCALADDR = "" + +# Cluster communication port (must be the same on all member servers). There +# is no need to open this port in the firewall as csf will automatically add +# in and out bound rules to allow communication between cluster members +CLUSTER_PORT = "7777" + +# This is a secret key used to encrypt cluster communications using the +# Blowfish algorithm. It should be between 8 and 56 characters long, +# preferably > 20 random characters +# 56 chars: 01234567890123456789012345678901234567890123456789012345 +CLUSTER_KEY = "" + +# Automatically send lfd blocks to all members of CLUSTER_SENDTO. Those +# servers must have this servers IP address listed in their CLUSTER_RECVFROM +# +# Set to 0 to disable this feature +CLUSTER_BLOCK = "1" + +# This option allows the enabling and disabling of the Cluster configuration +# changing options --cconfig, --cconfigr, --cfile, --ccfile sent from the +# CLUSTER_MASTER server +# +# Set this option to 1 to allow Cluster configurations to be received +CLUSTER_CONFIG = "0" + +# Maximum number of child processes to listen on. High blocking rates or large +# clusters may need to increase this +CLUSTER_CHILDREN = "10" + +############################################################################### +# SECTION:Port Knocking +############################################################################### +# Port Knocking. This feature allows port knocking to be enabled on multiple +# ports with a variable number of knocked ports and a timeout. There must be a +# minimum of 3 ports to knock for an entry to be valid +# +# See the following for information regarding Port Knocking: +# http://www.portknocking.org/ +# +# This feature does not work on servers that do not have the iptables module +# ipt_recent loaded. Typically, this will be with MONOLITHIC kernels. VPS +# server admins should check with their VPS host provider that the iptables +# module is included +# +# For further information and syntax refer to the Port Knocking section of the +# csf readme.txt +# +# Note: Run /etc/csf/csftest.pl to check whether this option will function on +# this server +# +# openport;protocol;timeout;kport1;kport2;kport3[...;kportN],... +# e.g.: 22;TCP;20;100;200;300;400 +PORTKNOCKING = "" + +# Enable PORTKNOCKING logging by iptables +PORTKNOCKING_LOG = "1" + +# Send an email alert if the PORTKNOCKING port is opened. PORTKNOCKING_LOG must +# also be enabled to use this option +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +PORTKNOCKING_ALERT = "0" + +############################################################################### +# SECTION:Log Scanner +############################################################################### +# Log Scanner. This feature will send out an email summary of the log lines of +# each log listed in /etc/csf/csf.logfiles. All lines will be reported unless +# they match a regular expression in /etc/csf/csf.logignore +# +# File globbing is supported for logs listed in /etc/csf/csf.logfiles. However, +# be aware that the more files lfd has to track, the greater the performance +# hit. Note: File globs are only evaluated when lfd is started +# +# Note: lfd builds the report continuously from lines logged after lfd has +# started, so any lines logged when lfd is not running will not be reported +# (e.g. during reboot). If lfd is restarted, then the report will include any +# lines logged during the previous lfd logging period that weren't reported +# +# 1 to enable, 0 to disable +LOGSCANNER = "0" + +# This is the interval each report will be sent based on the logalert.txt +# template +# +# The interval can be set to: +# "hourly" - sent on the hour +# "daily" - sent at midnight (00:00) +# "manual" - sent whenever "csf --logrun" is run. This allows for scheduling +# via cron job +LOGSCANNER_INTERVAL = "hourly" + +# Report Style +# 1 = Separate chronological log lines per log file +# 2 = Simply chronological log of all lines +LOGSCANNER_STYLE = "1" + +# Send the report email even if no log lines reported +# 1 to enable, 0 to disable +LOGSCANNER_EMPTY = "1" + +# Maximum number of lines in the report before it is truncated. This is to +# prevent log lines flooding resulting in an excessively large report. This +# might need to be increased if you choose a daily report +LOGSCANNER_LINES = "5000" + +############################################################################### +# SECTION:Statistics Settings +############################################################################### +# Statistics +# +# Some of the Statistics output requires the gd graphics library and the +# GD::Graph perl module with all dependent modules to be installed for the UI +# for them to be displayed +# +# This option enabled statistical data gathering +ST_ENABLE = "1" + +# This option determines how many iptables log lines to store for reports +ST_IPTABLES = "100" + +# This option indicates whether rDNS and CC lookups are performed at the time +# the log line is recorded (this is not performed when viewing the reports) +# +# Warning: If DROP_IP_LOGGING is enabled and there are frequent iptables hits, +# then enabling this setting could cause serious performance problems +ST_LOOKUP = "0" + +# This option will gather basic system statstics. Through the UI it displays +# various graphs for disk, cpu, memory, network, etc usage over 4 intervals: +# . Hourly (per minute) +# . 24 hours (per minute) +# . 7 days (per minute averaged over an hour) +# . 30 days (per minute averaged over an hour) - user definable +# The data is stored in /var/lib/csf/stats/system and the option requires the +# perl GD::Graph module +# +# Note: Disk graphs do not show on Virtuozzo/OpenVZ servers as the kernel on +# those systems do not store the required information in /proc/diskstats +# On new installations or when enabling this option it will take time for these +# graphs to be populated +ST_SYSTEM = "0" + +# Set the maximum days to collect statistics for. The default is 30 days, the +# more data that is collected the longer it will take for each of the graphs to +# be generated +ST_SYSTEM_MAXDAYS = "30" + +# If ST_SYSTEM is enabled, then these options can collect MySQL statistical +# data. To use this option the server must have the perl modules DBI and +# DBD::mysql installed. +# +# Set this option to "0" to disable MySQL data collection +ST_MYSQL = "0" + +# The following options are for authentication for MySQL data collection. If +# the password is left blank and the user set to "root" then the procedure will +# look for authentication data in /root/.my.cnf. Otherwise, you will need to +# provide a MySQL username and password to collect the data. Any MySQL user +# account can be used +ST_MYSQL_USER = "root" +ST_MYSQL_PASS = "" +ST_MYSQL_HOST = "localhost" + +# If ST_SYSTEM is enabled, then this option can collect Apache statistical data +# The value for PT_APACHESTATUS must be correctly set +ST_APACHE = "0" + +# The following options measure disk write performance using dd (location set +# via the DD setting). It creates a 64MB file called /var/lib/dd_write_test and +# the statistics will plot the MB/s response time of the disk. As this is an IO +# intensive operation, it may not be prudent to run this test too often, so by +# default it is only run every 5 minutes and the result duplicated for each +# intervening minute for the statistics +# +# This is not necessrily a good measure of disk performance, primarily because +# the measurements are for relatively small amounts of data over a small amount +# of time. To properly test disk performance there are a variety of tools +# available that should be run for extended periods of time to obtain an +# accurate measurement. This metric is provided to give an idea of how the disk +# is performing over time +# +# Note: There is a 15 second timeout performing the check +# +# Set to 0 to disable, 1 to enable +ST_DISKW = "0" + +# The number of minutes that elapse between tests. Default is 5, minimum is 1. +ST_DISKW_FREQ = "5" + +# This is the command line passed to dd. If you are familiar with dd, or wish +# to move the output file (of) to a different disk, then you can alter this +# command. Take great care when making any changes to this command as it is +# very easy to overwrite a disk using dd if you make a mistake +ST_DISKW_DD = "if=/dev/zero of=/var/lib/csf/dd_test bs=1MB count=64 conv=fdatasync" + +############################################################################### +# SECTION:Docker Settings +############################################################################### +# This section provides the configuration of iptables rules to allow Docker +# containers to communicate through the host. If the generated rules do not +# work with your setup you will have to use a /etc/csf/csfpost.sh file and add +# your own iptables configuration instead +# +# 1 to enable, 0 to disable +DOCKER = "0" + +# The network device on the host +DOCKER_DEVICE = "docker0" + +# Docker container IPv4 range +DOCKER_NETWORK4 = "172.17.0.0/16" + +# Docker container IPv6 range. IPV6 must be enabled and the IPv6 nat table +# available (see IPv6 section). Leave blank to disable +DOCKER_NETWORK6 = "2001:db8:1::/64" + +############################################################################### +# SECTION:OS Specific Settings +############################################################################### +# Binary locations +IPTABLES = "/sbin/iptables" +IPTABLES_SAVE = "/sbin/iptables-save" +IPTABLES_RESTORE = "/sbin/iptables-restore" +IP6TABLES = "/sbin/ip6tables" +IP6TABLES_SAVE = "/sbin/ip6tables-save" +IP6TABLES_RESTORE = "/sbin/ip6tables-restore" +MODPROBE = "/sbin/modprobe" +IFCONFIG = "/sbin/ifconfig" +SENDMAIL = "/usr/sbin/sendmail" +PS = "/bin/ps" +VMSTAT = "/usr/bin/vmstat" +NETSTAT = "/bin/netstat" +LS = "/bin/ls" +MD5SUM = "/usr/bin/md5sum" +TAR = "/bin/tar" +CHATTR = "/usr/bin/chattr" +UNZIP = "/usr/bin/unzip" +GUNZIP = "/bin/gunzip" +DD = "/bin/dd" +TAIL = "/usr/bin/tail" +GREP = "/bin/grep" +ZGREP = "/usr/bin/zgrep" +IPSET = "/usr/sbin/ipset" +SYSTEMCTL = "/usr/bin/systemctl" +HOST = "/usr/bin/host" +IP = "/sbin/ip" +CURL = "/usr/bin/curl" +WGET = "/usr/bin/wget" + +# Log file locations +# +# File globbing is allowed for the following logs. However, be aware that the +# more files lfd has to track, the greater the performance hit +# +# Note: File globs are only evaluated when lfd is started +# +HTACCESS_LOG = "/var/log/httpd/error_log" +MODSEC_LOG = "/var/log/httpd/error_log" +SSHD_LOG = "/var/log/secure" +SU_LOG = "/var/log/secure" +SUDO_LOG = "/var/log/secure" +FTPD_LOG = "/var/log/proftpd/auth.log" +SMTPAUTH_LOG = "/var/log/smtp/current" +POP3D_LOG = "/var/log/dovecot/dovecot.log" +IMAPD_LOG = "/var/log/dovecot/dovecot.log" +IPTABLES_LOG = "/var/log/messages" +SUHOSIN_LOG = "/var/log/messages" +BIND_LOG = "/var/log/messages" +SYSLOG_LOG = "/var/log/messages" +WEBMIN_LOG = "/var/log/secure" +INTERWORX_LOG = "/usr/local/interworx/var/log/login_failures.log" + +CUSTOM1_LOG = "/var/log/customlog" +CUSTOM2_LOG = "/var/log/customlog" +CUSTOM3_LOG = "/var/log/customlog" +CUSTOM4_LOG = "/var/log/customlog" +CUSTOM5_LOG = "/var/log/customlog" +CUSTOM6_LOG = "/var/log/customlog" +CUSTOM7_LOG = "/var/log/customlog" +CUSTOM8_LOG = "/var/log/customlog" +CUSTOM9_LOG = "/var/log/customlog" + +# The following are comma separated lists used if LF_SELECT is enabled, +# otherwise they are not used. They are derived from the application returned +# from a regex match in /usr/local/csf/bin/regex.pm +# +# All ports default to tcp blocks. To specify udp or tcp use the format: +# port;protocol,port;protocol,... For example, "53;udp,53;tcp" +PORTS_pop3d = "110,995" +PORTS_imapd = "143,993" +PORTS_htpasswd = "80,443" +PORTS_mod_security = "80,443" +PORTS_mod_qos = "80,443" +PORTS_symlink = "80,443" +PORTS_suhosin = "80,443" +PORTS_cxs = "80,443" +PORTS_bind = "53;udp,53;tcp" +PORTS_ftpd = "20,21" +PORTS_webmin = "10000" +PORTS_smtpauth = "25,465,587" +PORTS_eximsyntax = "25,465,587" +PORTS_interworx = "2080,2443" +# This list is replaced, if present, by "Port" definitions in +# /etc/ssh/sshd_config +PORTS_sshd = "22" + +# This configuration is for use with generic Linux servers, do not change the +# following settings: +GENERIC = "1" +INTERWORX = "1" + +# For internal use only. You should not enable this option as it could cause +# instability in csf and lfd +DEBUG = "0" +############################################################################### diff --git a/csf/csf.interworx.ignore b/csf/csf.interworx.ignore new file mode 100644 index 0000000..bf3fb2a --- /dev/null +++ b/csf/csf.interworx.ignore @@ -0,0 +1,25 @@ +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +# The following IP addresses will be ignored by all lfd checks +# One IP address per line +# CIDR addressing allowed with a quaded IP (e.g. 192.168.254.0/24) +# Only list IP addresses, not domain names (they will be ignored) +# + +127.0.0.1 diff --git a/csf/csf.interworx.pignore b/csf/csf.interworx.pignore new file mode 100644 index 0000000..29d13cd --- /dev/null +++ b/csf/csf.interworx.pignore @@ -0,0 +1,101 @@ +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +# The following is a list of executables (exe) command lines (cmd) and +# usernames (user) that lfd process tracking will ignore. +# +# You must use the following format: +# +# exe:/full/path/to/file +# user:username +# cmd:command line +# +# Or, perl regular expression matching (regex): +# +# pexe:/full/path/to/file as a perl regex[*] +# puser:username as a perl regex[*] +# pcmd:command line as a perl regex[*] +# +# [*]You must remember to escape characters correctly when using regex's, e.g.: +# pexe:/home/.*/public_html/cgi-bin/script\.cgi +# puser:bob\d.* +# pcmd:/home/.*/command\s\to\smatch\s\.pl\s.* +# +# It is strongly recommended that you use command line ignores very carefully +# as any process can change what is reported to the OS. +# +# For more information see readme.txt + +exe:/bin/dbus-daemon +exe:/sbin/ntpd +exe:/usr/bin/dbus-daemon +exe:/usr/bin/lsmd +exe:/usr/lib/courier-imap/bin/imapd +exe:/usr/lib/courier-imap/bin/pop3d +exe:/usr/lib/polkit-1/polkitd +exe:/usr/libexec/dovecot/imap +exe:/usr/libexec/dovecot/imap +exe:/usr/libexec/dovecot/pop3 +exe:/usr/libexec/dovecot/pop3 +exe:/usr/libexec/dovecot/stats +exe:/usr/libexec/dovecot/auth +exe:/usr/libexec/mysqld +exe:/usr/local/apache/bin/httpd +exe:/usr/local/libexec/dovecot/imap +exe:/usr/local/libexec/dovecot/imap-login +exe:/usr/local/libexec/dovecot/pop3 +exe:/usr/local/libexec/dovecot/pop3-login +exe:/usr/local/libexec/dovecot/stats +exe:/usr/sbin/chronyd +exe:/usr/sbin/exim +exe:/usr/sbin/exim4 +exe:/usr/sbin/named +exe:/usr/sbin/nscd +exe:/usr/sbin/ntpd +exe:/usr/sbin/ntpd +exe:/usr/sbin/proftpd +exe:/usr/sbin/pure-ftpd +exe:/usr/sbin/sshd +exe:/usr/sbin/apache2 +exe:/usr/sbin/mysqld +exe:/lib/systemd/systemd-timesyncd +exe:/sbin/rngd +exe:/usr/bin/dbus-broker-launch +exe:/usr/bin/dbus-broker + +exe:/usr/local/interworx/mysql/usr/sbin/mysqld +exe:/usr/bin/tcpserver +exe:/usr/bin/multilog +exe:/usr/sbin/clamd +exe:/usr/bin/freshclam +exe:/usr/sbin/httpd +exe:/usr/libexec/dovecot/anvil +exe:/var/qmail/bin/qmail-rspawn +exe:/var/qmail/bin/qmail-send +exe:/var/qmail/bin/qmail-clean +exe:/usr/bin/tinydns +exe:/usr/local/interworx/bin/httpd/httpd +exe:/usr/bin/dnscache +exe:/usr/sbin/mariadbd + +# Some additional entries that you might want to ignore on cPanel servers. +# However, be aware of the security implications under "Process Tracking" in +# the csf readme.txt when using these: +# +#cmd:spamd child +#cmd:/bin/sh /usr/bin/mysqld_safe --basedir=/usr diff --git a/csf/csf.logfiles b/csf/csf.logfiles new file mode 100644 index 0000000..55aa4dc --- /dev/null +++ b/csf/csf.logfiles @@ -0,0 +1,49 @@ +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +# The following is a list of log files for the LOGSCANNER feature + +# All: +/var/log/messages +/var/log/lfd.log +/var/log/cxswatch.log + +# RedHat: +/var/log/secure + +# Debian/Ubuntu: +/var/log/auth.log +/var/log/daemon.log +/var/log/syslog + +# cPanel: +/usr/local/cpanel/logs/error_log +/var/log/exim_paniclog + +# DirectAdmin: +/var/log/directadmin/error.log +/var/log/directadmin/security.log +/var/log/exim/paniclog + +# InterWorx +/usr/local/interworx/var/log/error.log + +# CyberPanel +/home/cyberpanel/error-logs.txt +/usr/local/lscp/cyberpanel/logs/error.log +/usr/local/lscp/cyberpanel/logs/stderr.log diff --git a/csf/csf.logignore b/csf/csf.logignore new file mode 100644 index 0000000..8f0f65e --- /dev/null +++ b/csf/csf.logignore @@ -0,0 +1,88 @@ +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +# The following is a list of regular expressions for the LOGSCANNER feature. +# If a log line matches it will be ignored, otherwise it will be reported + + +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ kernel:\s(\[[^\]]+\]\s)?Firewall: + +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ suhosin\[\d+\]: ALERT - script tried to increase memory_limit + +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ named\[\d+\]: client .* view internal +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ named\[\d+\]: client .* view external +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ named\[\d+\]: client .* view localhost_resolver +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ named\[\d+\]: connection refused resolving +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ named\[\d+\]: lame server resolving +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ named\[\d+\]: network unreachable resolving +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ named\[\d+\]: unexpected RCODE +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ named\[\d+\]: zone .* loaded serial +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ named\[\d+\]: zone .* sending notifies +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ named\[\d+\]: FORMERR resolving +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ named\[\d+\]: checkhints: view localhost_resolver: + +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ named\[\d+\]: error \(unexpected RCODE REFUSED\) +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ named\[\d+\]: error \(unexpected RCODE SERVFAIL\) +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ named\[\d+\]: error \(host unreachable\) +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ named\[\d+\]: error \(network unreachable\) +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ named\[\d+\]: error \(connection refused \) resolving +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ named\[\d+\]: error \(FORMERR\) resolving + +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ pure-ftpd: \([\w\?\@\+\%\.]+\@\d+\.\d+\.\d+\.\d+\) \[(INFO|NOTICE)\] + +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ Cp-Wrap\[\d+\]: +^\[\S+\s\S+\s\S+\] info + +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ gconfd + +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ systemd(\[\d+\])?: Started Session +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ systemd(\[\d+\])?: Starting Session +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ systemd(\[\d+\])?: Failed to mark scope +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ systemd-logind(\[\d+\])?: New session +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ systemd-logind(\[\d+\])?: Removed session +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ systemd(\[\d+\])?: Created slice +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ systemd(\[\d+\])?: Removed slice user +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ systemd(\[\d+\])?: Starting user +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ systemd(\[\d+\])?: Stopping user +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ systemd(\[\d+\])?: Reloading +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ systemd(\[\d+\])?: Starting User Slice +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ systemd(\[\d+\])?: Stopping User Slice +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ systemd(\[\d+\])?: Removed slice User +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ systemd(\[\d+\])?: Stopped target +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ systemd(\[\d+\])?: Reached target + +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ nscd(\[\d+\])?: \d+\ monitor + +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ dbus-daemon: dbus\[\d+\]: \[system\] Activating via systemd +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ dbus-daemon: dbus\[\d+\]: \[system\] Successfully activated +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ dbus\[\d+\]: \[system\] Activating via systemd +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ dbus\[\d+\]: \[system\] Successfully activated +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ systemd(\[\d+\])?: Starting Time +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ systemd(\[\d+\])?: Started Time +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ dovecot\[\d+\]: +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ dovecot: +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ CRON\[\d+\]: +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ MailScanner: +^(\S+|\S+\s+\d+\s+\S+) [^\s\.]+ clamd\[\d+\]: SelfCheck: Database status OK + +==> cpsrvd \S+ started +==> cpsrvd: loading security policy....Done +==> cpsrvd: Setting up SSL support ... Done +==> cpsrvd: transferred port bindings +==> cpsrvd: bound to ports + diff --git a/csf/csf.mignore b/csf/csf.mignore new file mode 100644 index 0000000..6ead9c4 --- /dev/null +++ b/csf/csf.mignore @@ -0,0 +1,22 @@ +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +# The following is a list of usernames and local IP addresses that +# RT_LOCALRELAY_ALERT will ignore +# +# Add only one username per line diff --git a/csf/csf.pignore b/csf/csf.pignore new file mode 100644 index 0000000..b28037d --- /dev/null +++ b/csf/csf.pignore @@ -0,0 +1,158 @@ +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +# The following is a list of executables (exe) command lines (cmd) and +# usernames (user) that lfd process tracking will ignore. +# +# You must use the following format: +# +# exe:/full/path/to/file +# user:username +# cmd:command line +# +# Or, perl regular expression matching (regex): +# +# pexe:/full/path/to/file as a perl regex[*] +# puser:username as a perl regex[*] +# pcmd:command line as a perl regex[*] +# +# [*]You must remember to escape characters correctly when using regex's, e.g.: +# pexe:/home/.*/public_html/cgi-bin/script\.cgi +# puser:bob\d.* +# pcmd:/home/.*/command\s\to\smatch\s\.pl\s.* +# +# It is strongly recommended that you use command line ignores very carefully +# as any process can change what is reported to the OS. +# +# For more information see readme.txt + +exe:/bin/dbus-daemon +exe:/sbin/ntpd +exe:/usr/bin/dbus-daemon +exe:/usr/bin/dbus-daemon-1 +exe:/usr/bin/lsmd +exe:/usr/bin/postgres +exe:/usr/bin/spamc +exe:/usr/lib/courier-imap/bin/imapd +exe:/usr/lib/courier-imap/bin/pop3d +exe:/usr/lib/polkit-1/polkitd +exe:/usr/libexec/dovecot/anvil +exe:/usr/libexec/dovecot/auth +exe:/usr/libexec/dovecot/dict +exe:/usr/libexec/dovecot/imap +exe:/usr/libexec/dovecot/imap-login +exe:/usr/libexec/dovecot/lmtp +exe:/usr/libexec/dovecot/pop3 +exe:/usr/libexec/dovecot/pop3-login +exe:/usr/libexec/dovecot/quota-status +exe:/usr/libexec/dovecot/stats +exe:/usr/libexec/dovecot/imap-hibernate +exe:/usr/libexec/gam_server +exe:/usr/libexec/hald-addon-acpi +exe:/usr/libexec/hald-addon-keyboard +exe:/usr/libexec/mysqld +exe:/usr/local/apache/bin/httpd +exe:/usr/local/cpanel/3rdparty/bin/analog +exe:/usr/local/cpanel/3rdparty/bin/english/webalizer +exe:/usr/local/cpanel/3rdparty/bin/imapd +exe:/usr/local/cpanel/3rdparty/bin/php +exe:/usr/local/cpanel/3rdparty/bin/webalizer_lang/english +exe:/usr/local/cpanel/3rdparty/php/54/bin/php-cgi +exe:/usr/local/cpanel/3rdparty/php/56/bin/php-cgi +exe:/usr/local/cpanel/3rdparty/php/56/sbin/php-fpm +exe:/usr/local/cpanel/3rdparty/php/54/sbin/php-fpm +exe:/usr/local/cpanel/3rdparty/sbin/mydns +exe:/usr/local/cpanel/3rdparty/sbin/p0f +exe:/usr/local/cpanel/bin/cppop +exe:/usr/local/cpanel/bin/cppop-ssl +exe:/usr/local/cpanel/bin/cpuwatch +exe:/usr/local/cpanel/bin/cpwrap +exe:/usr/local/cpanel/bin/logrunner +exe:/usr/local/cpanel/bin/pkgacct +exe:/usr/local/cpanel/cpanel +exe:/usr/local/cpanel/cpdavd +exe:/usr/local/cpanel/cpsrvd +exe:/usr/local/cpanel/cpsrvd-ssl +exe:/usr/local/libexec/dovecot/imap +exe:/usr/local/libexec/dovecot/imap-login +exe:/usr/local/libexec/dovecot/pop3 +exe:/usr/local/libexec/dovecot/pop3-login +exe:/usr/local/urchin/bin/urchinwebd +exe:/usr/sbin/chronyd +exe:/usr/sbin/exim +exe:/usr/sbin/exim +exe:/usr/sbin/hald +exe:/usr/sbin/httpd +exe:/usr/sbin/mysqld +exe:/usr/sbin/mysqld_safe +exe:/usr/sbin/named +exe:/usr/sbin/nscd +exe:/usr/sbin/nsd +exe:/usr/sbin/ntpd +exe:/usr/sbin/proftpd +exe:/usr/sbin/pure-ftpd +exe:/usr/sbin/sshd +exe:/var/cpanel/3rdparty/bin/php +exe:/usr/sbin/pdns_server +exe:/usr/local/cpanel/bin/autossl_check +exe:/usr/local/cpanel/bin/whm_xfer_download-ssl +pexe:^/usr/lib/jvm/java-.*/jre/bin/java$ +exe:/usr/libexec/dovecot/indexer-worker +exe:/usr/libexec/dovecot/indexer +pexe:/usr/local/cpanel/3rdparty/bin/git.* +pexe:/usr/local/cpanel/3rdparty/libexec/git-core/git.* +exe:/usr/sbin/imunify-notifier +exe:/usr/bin/sw-engine +exe:/usr/sbin/sw-engine-fpm +exe:/usr/sbin/sw-cp-serverd +exe:/sbin/rngd +exe:/usr/sbin/mariadbd +exe:/usr/sbin/atd +exe:/usr/lib/systemd/systemd-timesyncd +exe:/usr/lib/systemd/systemd-networkd +exe:/usr/sbin/rsyslogd +exe:/usr/lib/apt/methods/http +exe:/usr/sbin/rngd +exe:/usr/lib/systemd/systemd-resolved +exe:/usr/sbin/uuidd +exe:/usr/bin/dbus-broker-launch +exe:/usr/bin/dbus-broker +exe:/usr/local/cpanel/3rdparty/wp-toolkit/bin/wpt-panopticon + +# Some additional entries that you might want to ignore on cPanel servers. +# However, be aware of the security implications under "Process Tracking" in +# the csf readme.txt when using these: +# +#cmd:/bin/sh /usr/bin/mysqld_safe +#cmd:/bin/sh /usr/bin/mysqld_safe --basedir=/usr +#cmd:spamd child +#pcmd:/usr/local/cpanel/3rdparty/bin/python /usr/local/cpanel/3rdparty/mailman/bin/qrunner.* +#pcmd:/usr/local/cpanel/3rdparty/bin/python /usr/local/cpanel/3rdparty/mailman/bin/mailmanctl.* +#pcmd:/usr/bin/python.? /usr/local/cpanel/3rdparty/mailman/bin/qrunner.* +#pcmd:/usr/bin/python.? /usr/local/cpanel/3rdparty/mailman/bin/mailmanctl.* +#pcmd:/usr/bin/perl /usr/local/cpanel/3rdparty/bin/awstats\.pl.* +#pcmd:/usr/bin/perl /usr/local/cpanel/base/awstats\.pl.* +#pcmd:cpanellogd - (http|ftp) logs for .* +#pcmd:ubic-guardian ubic-periodic.* +#pcmd:perl /usr/local/cpanel/3rdparty/perl/\d+/bin/ubic-periodic.* +#pcmd:MailScanner:.* +#pexe:/opt/cpanel/ea-php\d+/root/usr/bin/lsphp +#pexe:/opt/cpanel/ea-php\d+/root/usr/bin/lsphp.cagefs +#pexe:/opt/cpanel/ea-php\d+/root/usr/bin/php +#pexe:/opt/cpanel/ea-php\d+/root/usr/bin/php.cagefs +#pexe:/opt/cpanel/ea-php\d+/root/usr/sbin/php-fpm diff --git a/csf/csf.pl b/csf/csf.pl new file mode 100644 index 0000000..8490184 --- /dev/null +++ b/csf/csf.pl @@ -0,0 +1,6009 @@ +#!/usr/bin/perl +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +## no critic (RequireUseWarnings, ProhibitExplicitReturnUndef, ProhibitMixedBooleanOperators, RequireBriefOpen) +# start main +use strict; +use lib '/usr/local/csf/lib'; +use Fcntl qw(:DEFAULT :flock); +use File::Basename; +use IO::Handle; +use IPC::Open3; +use Net::CIDR::Lite; +use Socket; +use ConfigServer::Config; +use ConfigServer::Slurp qw(slurp); +use ConfigServer::CheckIP qw(checkip cccheckip); +use ConfigServer::Ports; +use ConfigServer::URLGet; +use ConfigServer::Sanity qw(sanity); +use ConfigServer::ServerCheck; +use ConfigServer::ServerStats; +use ConfigServer::Service; +use ConfigServer::Messenger; +use ConfigServer::RBLCheck; +use ConfigServer::GetEthDev; +use ConfigServer::Sendmail; +use ConfigServer::LookUpIP qw(iplookup); + +umask(0177); + +our ($verbose, $version, $logintarget, $noowner, $warning, $accept, $ipscidr, + $ipv6reg, $ipv4reg,$ethdevin, $ethdevout, $ipscidr6, $eth6devin, + $eth6devout, $statemodule, $logouttarget, $cleanreg, $slurpreg, + $faststart, $urlget, $statemodulenew, $statemodule6new, $cxsreputation); + +our ($IPTABLESLOCK, $CSFLOCKFILE); + +our (%input, %config, %ips, %ifaces, %messengerports,%sanitydefault, + %blocklists, %cxsports); + +our (@ipset, @faststart4, @faststart6, @faststart4nat, @faststartipset, + @faststart6nat); + +$version = &version; + +$ipscidr6 = Net::CIDR::Lite->new; +$ipscidr = Net::CIDR::Lite->new; +eval {local $SIG{__DIE__} = undef; $ipscidr6->add("::1/128")}; +eval {local $SIG{__DIE__} = undef; $ipscidr->add("127.0.0.0/8")}; + +$slurpreg = ConfigServer::Slurp->slurpreg; +$cleanreg = ConfigServer::Slurp->cleanreg; +$faststart = 0; + +&process_input; +&load_config; + +$urlget = ConfigServer::URLGet->new($config{URLGET}, "csf/$version", $config{URLPROXY}); +unless (defined $urlget) { + if (-e $config{CURL} or -e $config{WGET}) { + $config{URLGET} = 3; + $urlget = ConfigServer::URLGet->new($config{URLGET}, "csf/$version", $config{URLPROXY}); + print "*WARNING* URLGET set to use LWP but perl module is not installed, fallback to using CURL/WGET\n"; + $warning .= "*WARNING* URLGET set to use LWP but perl module is not installed, fallback to using CURL/WGET\n"; + } else { + $config{URLGET} = 1; + $urlget = ConfigServer::URLGet->new($config{URLGET}, "csf/$version", $config{URLPROXY}); + print "*WARNING* URLGET set to use LWP but perl module is not installed, reverting to HTTP::Tiny\n"; + $warning .= "*WARNING* URLGET set to use LWP but perl module is not installed, reverting to HTTP::Tiny\n"; + } +} + +if ((-e "/etc/csf/csf.disable") and ($input{command} ne "--enable") and ($input{command} ne "-e")) { + print "csf and lfd have been disabled, use 'csf -e' to enable\n"; + my $ok = 0; + foreach my $opt ("--version","-v","--check","-c","--ports","-p","--help","-h","--update","-u","-uf","--flush","-f","--profile","") { + if ($input{command} eq $opt) { + $ok = 1; + last; + } + } + unless ($ok) {exit 1} +} +unless (-e $config{IPTABLES}) {&error(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} (iptables binary location) does not exist!")} +if ($config{IPV6} and !(-e $config{IP6TABLES})) {&error(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} (ip6tables binary location) does not exist!")} + +if ((-e "/etc/csf/csf.error") and ($input{command} ne "--startf") and ($input{command} ne "-sf") and ($input{command} ne "-q") and ($input{command} ne "--startq") and ($input{command} ne "--start") and ($input{command} ne "-s") and ($input{command} ne "--restart") and ($input{command} ne "-r") and ($input{command} ne "--enable") and ($input{command} ne "-e")) { + open (my $IN, "<", "/etc/csf/csf.error"); + flock ($IN, LOCK_SH); + my $error = <$IN>; + close ($IN); + chomp $error; + print "You have an unresolved error when starting csf:\n$error\n\nYou need to restart csf successfully to remove this warning, or delete /etc/csf/csf.error\n"; + exit 1; +} + +unless ($input{command} =~ /^--(stop|initdown|initup)$/) { + if (-e "/var/lib/csf/csf.4.saved") {unlink "/var/lib/csf/csf.4.saved"} + if (-e "/var/lib/csf/csf.4.ipsets") {unlink "/var/lib/csf/csf.4.ipsets"} + if (-e "/var/lib/csf/csf.6.saved") {unlink "/var/lib/csf/csf.6.saved"} +} + +if (($input{command} eq "--status") or ($input{command} eq "-l")) {&dostatus} +elsif (($input{command} eq "--status6") or ($input{command} eq "-l6")) {&dostatus6} +elsif (($input{command} eq "--version") or ($input{command} eq "-v")) {&doversion} +elsif (($input{command} eq "--stop") or ($input{command} eq "-f")) {&csflock("lock");&dostop(0);&csflock("unlock")} +elsif (($input{command} eq "--startf") or ($input{command} eq "-sf")) {&csflock("lock");&dostop(1);&dostart;&csflock("unlock")} +elsif (($input{command} eq "--start") or ($input{command} eq "-s") or ($input{command} eq "--restart") or ($input{command} eq "-r")) {if ($config{LFDSTART}) {&lfdstart} else {&csflock("lock");&dostop(1);&dostart;&csflock("unlock")}} +elsif (($input{command} eq "--startq") or ($input{command} eq "-q")) {&lfdstart} +elsif (($input{command} eq "--restartall") or ($input{command} eq "-ra")) {&dorestartall} +elsif (($input{command} eq "--add") or ($input{command} eq "-a")) {&doadd} +elsif (($input{command} eq "--deny") or ($input{command} eq "-d")) {&dodeny} +elsif (($input{command} eq "--denyrm") or ($input{command} eq "-dr")) {&dokill} +elsif (($input{command} eq "--denyf") or ($input{command} eq "-df")) {&dokillall} +elsif (($input{command} eq "--addrm") or ($input{command} eq "-ar")) {&doakill} +elsif (($input{command} eq "--update") or ($input{command} eq "-u") or ($input{command} eq "-uf")) {&doupdate} +elsif (($input{command} eq "--disable") or ($input{command} eq "-x")) {&csflock("lock");&dodisable;&csflock("unlock")} +elsif (($input{command} eq "--enable") or ($input{command} eq "-e")) {&csflock("lock");&doenable;&csflock("unlock")} +elsif (($input{command} eq "--check") or ($input{command} eq "-c")) {&docheck} +elsif (($input{command} eq "--grep") or ($input{command} eq "-g")) {&dogrep} +elsif (($input{command} eq "--iplookup") or ($input{command} eq "-i")) {&doiplookup} +elsif (($input{command} eq "--temp") or ($input{command} eq "-t")) {&dotempban} +elsif (($input{command} eq "--temprm") or ($input{command} eq "-tr")) {&dotemprm} +elsif (($input{command} eq "--temprma") or ($input{command} eq "-tra")) {&dotemprma} +elsif (($input{command} eq "--temprmd") or ($input{command} eq "-trd")) {&dotemprmd} +elsif (($input{command} eq "--tempdeny") or ($input{command} eq "-td")) {&dotempdeny} +elsif (($input{command} eq "--tempallow") or ($input{command} eq "-ta")) {&dotempallow} +elsif (($input{command} eq "--tempf") or ($input{command} eq "-tf")) {&dotempf} +elsif (($input{command} eq "--mail") or ($input{command} eq "-m")) {&domail} +elsif (($input{command} eq "--cdeny") or ($input{command} eq "-cd")) {&doclusterdeny} +elsif (($input{command} eq "--ctempdeny") or ($input{command} eq "-ctd")) {&doclustertempdeny} +elsif (($input{command} eq "--callow") or ($input{command} eq "-ca")) {&doclusterallow} +elsif (($input{command} eq "--ctempallow") or ($input{command} eq "-cta")) {&doclustertempallow} +elsif (($input{command} eq "--crm") or ($input{command} eq "-cr")) {&doclusterrm} +elsif (($input{command} eq "--carm") or ($input{command} eq "-car")) {&doclusterarm} +elsif (($input{command} eq "--cignore") or ($input{command} eq "-ci")) {&doclusterignore} +elsif (($input{command} eq "--cirm") or ($input{command} eq "-cir")) {&doclusterirm} +elsif (($input{command} eq "--cping") or ($input{command} eq "-cp")) {&clustersend("PING")} +elsif (($input{command} eq "--cgrep") or ($input{command} eq "-cg")) {&doclustergrep} +elsif (($input{command} eq "--cconfig") or ($input{command} eq "-cc")) {&docconfig} +elsif (($input{command} eq "--cfile") or ($input{command} eq "-cf")) {&docfile} +elsif (($input{command} eq "--crestart") or ($input{command} eq "-crs")) {&docrestart} +elsif (($input{command} eq "--watch") or ($input{command} eq "-w")) {&dowatch} +elsif (($input{command} eq "--logrun") or ($input{command} eq "-lr")) {&dologrun} +elsif (($input{command} eq "--ports") or ($input{command} eq "-p")) {&doports} +elsif ($input{command} eq "--cloudflare") {&docloudflare} +elsif ($input{command} eq "--graphs") {&dographs} +elsif ($input{command} eq "--lfd") {&dolfd} +elsif ($input{command} eq "--rbl") {&dorbls} +elsif ($input{command} eq "--initup") {&doinitup} +elsif ($input{command} eq "--initdown") {&doinitdown} +elsif ($input{command} eq "--profile") {&doprofile} +elsif ($input{command} eq "--mregen") {&domessengerv2} +elsif ($input{command} eq "--trace") {&dotrace} +else {&dohelp} + +if ($config{TESTING}) {print "*WARNING* TESTING mode is enabled - do not forget to disable it in the configuration\n"} + +if ($config{AUTO_UPDATES}) { + unless (-e "/etc/cron.d/csf_update") {&autoupdates} +} +elsif (-e "/etc/cron.d/csf_update") {unlink "/etc/cron.d/csf_update"} + +if (($input{command} eq "--start") or ($input{command} eq "-s") or ($input{command} eq "--restart") or ($input{command} eq "-r") or ($input{command} eq "--restartall") or ($input{command} eq "-ra")) { + if ($warning) {print $warning} + foreach my $key (keys %config) { + my ($insane,$range,$default) = sanity($key,$config{$key}); + if ($insane) {print "*WARNING* $key sanity check. $key = $config{$key}. Recommended range: $range (Default: $default)\n"} + } + unless ($config{RESTRICT_SYSLOG}) {print "\n*WARNING* RESTRICT_SYSLOG is disabled. See SECURITY WARNING in /etc/csf/csf.conf.\n"} +} + +exit 0; + +# end main +############################################################################### +# start csflock +sub csflock { + my $lock = shift; + if ($lock eq "lock") { + sysopen ($CSFLOCKFILE, "/var/lib/csf/csf.lock", O_RDWR | O_CREAT) or die ("Error: Unable to open csf lock file: $!"); + flock ($CSFLOCKFILE, LOCK_EX | LOCK_NB) or die "Error: csf is being restarted, try again in a moment: $!"; + } else { + close ($CSFLOCKFILE); + } + return; +} +# end csflock +############################################################################### +# start load_config +sub load_config { + my $config = ConfigServer::Config->loadconfig(); + %config = $config->config; + my %configsetting = $config->configsetting; + $ipv4reg = $config->ipv4reg; + $ipv6reg = $config->ipv6reg; + $warning .= $config->{warning}; + + if ($config{CLUSTER_SENDTO} or $config{CLUSTER_RECVFROM}) { + require Crypt::CBC; + import Crypt::CBC; + require File::Basename; + import File::Basename; + require IO::Socket::INET; + import IO::Socket::INET; + } + + if ($config{CF_ENABLE}) { + require ConfigServer::CloudFlare; + import ConfigServer::CloudFlare; + } + + $verbose = ""; + if ($config{VERBOSE} or $config{DEBUG} >= 1) {$verbose = "-v"} + + $logintarget = "LOG --log-prefix"; + $logouttarget = "LOG --log-uid --log-prefix"; + unless ($config{DROP_UID_LOGGING}) {$logouttarget = "LOG --log-prefix"} + + $accept = "ACCEPT"; + if ($config{WATCH_MODE}) { + $accept = "LOGACCEPT"; + $config{DROP_NOLOG} = ""; + $config{DROP_LOGGING} = "1"; + $config{DROP_IP_LOGGING} = "1"; + $config{DROP_OUT_LOGGING} = "1"; + $config{DROP_PF_LOGGING} = "1"; + $config{PS_INTERVAL} = "0"; + $config{DROP_ONLYRES} = "0"; + } + + if ($config{MESSENGER}) { + foreach my $port (split(/\,/,$config{MESSENGER_HTTPS_IN})) {$messengerports{$port} = 1} + foreach my $port (split(/\,/,$config{MESSENGER_HTML_IN})) {$messengerports{$port} = 1} + foreach my $port (split(/\,/,$config{MESSENGER_TEXT_IN})) {$messengerports{$port} = 1} + } + + $statemodule = "-m state --state"; + if ($config{USE_CONNTRACK}) {$statemodule = "-m conntrack --ctstate"} + if ($config{LF_SPI}) { + $statemodulenew = "$statemodule NEW"; + } else { + $statemodulenew = ""; + } + if ($config{IPV6_SPI}) { + $statemodule6new = "$statemodule NEW"; + } else { + $statemodule6new = ""; + } + + my @entries = slurp("/etc/csf/csf.blocklists"); + foreach my $line (@entries) { + if ($line =~ /^Include\s*(.*)$/) { + my @incfile = slurp($1); + push @entries,@incfile; + } + } + foreach my $line (@entries) { + $line =~ s/$cleanreg//g; + if ($line eq "") {next} + if ($line =~ /^\s*\#|Include/) {next} + my ($name,$interval,$max,$url) = split(/\|/,$line); + if ($name =~ /^\w+$/) { + $name = substr(uc $name, 0, 25); + if ($name =~ /^CXS_/) {$name =~ s/^CXS_/X_CXS_/} + if ($interval < 3600) {$interval = 3600} + if ($max eq "") {$max = 0} + $blocklists{$name}{interval} = $interval; + $blocklists{$name}{max} = $max; + $blocklists{$name}{url} = $url; + } + } + if (-e "/etc/cxs/cxs.reputation" and -e "/usr/local/csf/lib/ConfigServer/cxs.pm") { + require ConfigServer::cxs; + import ConfigServer::cxs; + $cxsreputation = 1; + if (-e "/etc/cxs/cxs.blocklists") { + my $all = 0; + my @lines = slurp("/etc/cxs/cxs.blocklists"); + if (grep {$_ =~ /^CXS_ALL/} @lines) {$all = 1} + foreach my $line (@lines) { + $line =~ s/$cleanreg//g; + if ($line =~ /^(\s|\#|$)/) {next} + my ($name,$interval,$max,$url) = split(/\|/,$line); + if ($all and $name ne "CXS_ALL") {next} + if ($name =~ /^\w+$/) { + $name = substr(uc $name, 0, 25); + if ($max eq "") {$max = 0} + $blocklists{$name}{interval} = $interval; + $blocklists{$name}{max} = $max; + $blocklists{$name}{url} = $url; + } + } + } + %cxsports = ConfigServer::cxs::Rports(); + } + + my @binaries = ("IPTABLES","IPTABLES_SAVE","IPTABLES_RESTORE","MODPROBE","SENDMAIL","PS","VMSTAT","LS","MD5SUM","TAR","CHATTR","UNZIP","GUNZIP","DD","TAIL","GREP","HOST"); + if ($config{IPV6}) {push @binaries, ("IP6TABLES","IP6TABLES_SAVE","IP6TABLES_RESTORE")} + if ($config{LF_IPSET}) {push @binaries, ("IPSET")} + if (ConfigServer::Service::type() eq "systemd") {push @binaries, ("SYSTEMCTL")} + my $hit = 0; + foreach my $bin (@binaries) { + if ($bin eq "SENDMAIL" and $config{LF_ALERT_SMTP}) {next} + unless (-e $config{$bin} and -x $config{$bin}) { + $warning .= "*WARNING* Binary location for [$bin] [$config{$bin}] in /etc/csf/csf.conf is either incorrect, is not installed or is not executable\n"; + $hit = 1; + } + } + my $iphit = 0; + if (-e $config{IP} or -e $config{IFCONFIG}) {$iphit = 1} + unless ($iphit) { + $warning .= "*WARNING* Binary location for either [IP] [$config{IP}] or [IFCONFIG] [$config{IFCONFIG}] in /etc/csf/csf.conf must be set correctly, installed and executable\n"; + $hit = 1; + } + if ($hit) {$warning .= "*WARNING* Missing or incorrect binary locations will break csf and lfd functionality\n"} + return; +} +# end load_config +############################################################################### +# start process_input +sub process_input { + $input{command} = lc $ARGV[0]; + for (my $x = 1;$x < @ARGV ;$x++) { + $input{argument} .= $ARGV[$x] . " "; + } + $input{argument} =~ s/\s$//; + return; +} +# end process_input +############################################################################### +# start dostatus +sub dostatus { + print "iptables filter table\n"; + print "=====================\n"; + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -v -L -n --line-numbers"); + if ($config{MANGLE}) { + print "\n\n"; + print "iptables mangle table\n"; + print "=====================\n"; + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -v -t mangle -L -n --line-numbers"); + } + if ($config{RAW}) { + print "\n\n"; + print "iptables raw table\n"; + print "==================\n"; + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -v -t raw -L -n --line-numbers"); + } + if ($config{NAT}) { + print "\n\n"; + print "iptables nat table\n"; + print "==================\n"; + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -v -t nat -L -n --line-numbers"); + } + return; +} +# end dostatus +############################################################################### +# start dostatus6 +sub dostatus6 { + if ($config{IPV6}) { + print "ip6tables filter table\n"; + print "======================\n"; + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -v -L -n --line-numbers"); + if ($config{MANGLE6}) { + print "\n\n"; + print "ip6tables mangle table\n"; + print "======================\n"; + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -v -t mangle -L -n --line-numbers"); + } + if ($config{RAW6}) { + print "\n\n"; + print "ip6tables raw table\n"; + print "===================\n"; + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -v -t raw -L -n --line-numbers"); + } + if ($config{NAT6}) { + print "\n\n"; + print "ip6tables nat table\n"; + print "===================\n"; + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -v -t nat -L -n --line-numbers"); + } + } else { + print "csf: IPV6 firewall not enabled\n"; + } + return; +} +# end dostatus +############################################################################### +# start doversion +sub doversion { +my $generic = " (cPanel)"; +if ($config{GENERIC}) {$generic = " (generic)"} +if ($config{DIRECTADMIN}) {$generic = " (DirectAdmin)"} +if ($config{INTERWORX}) {$generic = " (InterWorx)"} +if ($config{CYBERPANEL}) {$generic = " (CyberPanel)"} +if ($config{CWP}) {$generic = " (CentOS Web Panel)"} +if ($config{VESTA}) {$generic = " (VestaCP)"} + print "csf: v$version$generic\n"; + return; +} +# end doversion +############################################################################### +# start dolfd +sub dolfd { + my $lfd = $input{argument}; + if ($lfd eq "start") {ConfigServer::Service::startlfd()} + elsif ($lfd eq "stop") {ConfigServer::Service::stoplfd()} + elsif ($lfd eq "restart") {ConfigServer::Service::restartlfd()} + elsif ($lfd eq "status") {ConfigServer::Service::statuslfd()} + else {print "csf: usage: csf --lfd [stop|start|restart|status]\n"} + return; +} +# end dolfd +############################################################################### +# start dorestartall +sub dorestartall { + &csflock("lock"); + &dostop(1); + &dostart; + &csflock("unlock"); + ConfigServer::Service::restartlfd(); + return; +} +# end dorestartall +############################################################################### +# start doinitup +sub doinitup { + &csflock("lock"); + if ($config{FASTSTART}) { + &modprobe; + if (-e "/var/lib/csf/csf.4.saved") { + if ($config{LF_IPSET}) { + if (-x $config{IPSET}) { + print "(restoring ipsets) "; + + open (my $IN, "<", "/var/lib/csf/csf.4.ipsets"); + flock ($IN, LOCK_SH); + my @data = <$IN>; + close ($IN); + chomp @data; + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, $config{IPSET},"restore"); + print $childin join("\n",@data)."\n"; + close $childin; + my @results = <$childout>; + waitpid ($cmdpid, 0); + chomp @results; + + unlink "/var/lib/csf/csf.4.ipsets"; + } + } + print "(restoring iptables) "; + + open (my $IN, "<", "/var/lib/csf/csf.4.saved"); + flock ($IN, LOCK_SH); + my @data = <$IN>; + close ($IN); + chomp @data; + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, $config{IPTABLES_RESTORE}); + print $childin join("\n",@data)."\n"; + close $childin; + my @results = <$childout>; + waitpid ($cmdpid, 0); + chomp @results; + + unlink "/var/lib/csf/csf.4.saved"; + } else { + &dostop(1); + &dostart; + exit 0; + } + if ($config{IPV6}) { + if (-e "/var/lib/csf/csf.6.saved") { + print "(restoring ip6tables) "; + + open (my $IN, "<", "/var/lib/csf/csf.6.saved"); + flock ($IN, LOCK_SH); + my @data = <$IN>; + close ($IN); + chomp @data; + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, $config{IP6TABLES_RESTORE}); + print $childin join("\n",@data)."\n"; + close $childin; + my @results = <$childout>; + waitpid ($cmdpid, 0); + chomp @results; + + unlink "/var/lib/csf/csf.6.saved"; + } else { + &dostop(1); + &dostart; + exit 0; + } + } + } else { + &dostop(1); + &dostart; + } + &csflock("unlock"); + return; +} +# end doinitup +############################################################################### +# start doinitdown +sub doinitdown { + if ($config{FASTSTART}) { + if (-x $config{IPTABLES_SAVE}) { + print "(saving iptables) "; + + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, $config{IPTABLES_SAVE}); + close $childin; + my @results = <$childout>; + waitpid ($cmdpid, 0); + chomp @results; + open (my $OUT, ">", "/var/lib/csf/csf.4.saved"); + flock ($OUT, LOCK_EX); + print $OUT join("\n",@results)."\n"; + close ($OUT); + + if ($config{LF_IPSET}) { + if (-x $config{IPSET}) { + print "(saving ipsets) "; + + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, $config{IPSET}, "save"); + close $childin; + my @results = <$childout>; + waitpid ($cmdpid, 0); + chomp @results; + open (my $OUT, ">", "/var/lib/csf/csf.4.ipsets"); + flock ($OUT, LOCK_EX); + print $OUT join("\n",@results)."\n"; + close ($OUT); + } + } + } + if ($config{IPV6} and -x $config{IP6TABLES_SAVE}) { + print "(saving ip6tables) "; + + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, $config{IP6TABLES_SAVE}); + close $childin; + my @results = <$childout>; + waitpid ($cmdpid, 0); + chomp @results; + open (my $OUT, ">", "/var/lib/csf/csf.6.saved"); + flock ($OUT, LOCK_EX); + print $OUT join("\n",@results)."\n"; + close ($OUT); + } + } + return; +} +# end doinitdown +############################################################################### +# start doclusterdeny +sub doclusterdeny { + my ($ip,$comment) = split (/\s/,$input{argument},2); + + if (!checkip(\$ip)) { + print "[$ip] is not a valid PUBLIC IP/CIDR\n"; + return; + } + + &clustersend("D $ip 1 * inout 3600 $comment"); + return; +} +# end doclusterdeny +############################################################################### +# start doclustertempdeny +sub doclustertempdeny { + my ($ip,$timeout,$portdir) = split(/\s/,$input{argument},3); + my $inout = "in"; + my $ports = ""; + my $perm = 0; + if ($timeout =~ /^(\d*)(m|h|d)/i) { + my $secs = $1; + my $dur = $2; + if ($dur eq "m") {$timeout = $secs * 60} + elsif ($dur eq "h") {$timeout = $secs * 60 * 60} + elsif ($dur eq "d") {$timeout = $secs * 60 * 60 * 24} + else {$timeout = $secs} + } + + my $iptype = checkip(\$ip); + if ($iptype == 6 and !$config{IPV6}) { + print "failed: [$ip] is valid IPv6 but IPV6 is not enabled in csf.conf\n"; + } + + unless ($iptype) { + print "csf: [$ip] is not a valid PUBLIC IP\n"; + return; + } + + if ($timeout =~ /\D/) { + $portdir = join(" ",$timeout,$portdir); + $timeout = 0; + } + + if ($portdir =~ /\-d\s*out/i) {$inout = "out"} + if ($portdir =~ /\-d\s*inout/i) {$inout = "inout"} + if ($portdir =~ /\-p\s*([\w\,\*\;]+)/) {$ports = $1} + my $comment = $portdir; + $comment =~ s/\-d\s*out//ig; + $comment =~ s/\-d\s*inout//ig; + $comment =~ s/\-d\s*in//ig; + $comment =~ s/\-p\s*[\w\,\*\;]+//ig; + $comment =~ s/^\s*|\s*$//g; + if ($comment eq "") {$comment = "Manually added: ".iplookup($ip)} + if ($timeout < 2) {$timeout = 3600} + if ($ports eq "") {$ports = "*"} + + if (!checkip(\$ip)) { + print "[$ip] is not a valid PUBLIC IP/CIDR\n"; + return; + } + + &clustersend("TD $ip $perm $ports $inout $timeout $comment"); + return; +} +# end doclustertempdeny +############################################################################### +# start doclusterrm +sub doclusterrm { + my ($ip,$comment) = split (/\s/,$input{argument},2); + + if (!checkip(\$ip)) { + print "[$ip] is not a valid PUBLIC IP/CIDR\n"; + return; + } + + &clustersend("R $ip"); + return; +} +# end doclusterrm +############################################################################### +# start doclusterarm +sub doclusterarm { + my ($ip,$comment) = split (/\s/,$input{argument},2); + + if (!checkip(\$ip)) { + print "[$ip] is not a valid PUBLIC IP/CIDR\n"; + return; + } + + &clustersend("AR $ip"); + return; +} +# end doclusterarm +############################################################################### +# start doclusterallow +sub doclusterallow { + my ($ip,$comment) = split (/\s/,$input{argument},2); + + if (!checkip(\$ip)) { + print "[$ip] is not a valid PUBLIC IP/CIDR\n"; + return; + } + + &clustersend("A $ip 1 * inout 3600 $comment"); + return; +} +# end doclusterallow +############################################################################### +# start doclustertempallow +sub doclustertempallow { + my ($ip,$timeout,$portdir) = split(/\s/,$input{argument},3); + my $inout = "in"; + my $ports = ""; + my $perm = 0; + if ($timeout =~ /^(\d*)(m|h|d)/i) { + my $secs = $1; + my $dur = $2; + if ($dur eq "m") {$timeout = $secs * 60} + elsif ($dur eq "h") {$timeout = $secs * 60 * 60} + elsif ($dur eq "d") {$timeout = $secs * 60 * 60 * 24} + else {$timeout = $secs} + } + + my $iptype = checkip(\$ip); + if ($iptype == 6 and !$config{IPV6}) { + print "failed: [$ip] is valid IPv6 but IPV6 is not enabled in csf.conf\n"; + } + + unless ($iptype) { + print "csf: [$ip] is not a valid PUBLIC IP\n"; + return; + } + + if ($timeout =~ /\D/) { + $portdir = join(" ",$timeout,$portdir); + $timeout = 0; + } + + if ($portdir =~ /\-d\s*out/i) {$inout = "out"} + if ($portdir =~ /\-d\s*inout/i) {$inout = "inout"} + if ($portdir =~ /\-p\s*([\w\,\*\;]+)/) {$ports = $1} + my $comment = $portdir; + $comment =~ s/\-d\s*out//ig; + $comment =~ s/\-d\s*inout//ig; + $comment =~ s/\-d\s*in//ig; + $comment =~ s/\-p\s*[\w\,\*\;]+//ig; + $comment =~ s/^\s*|\s*$//g; + if ($comment eq "") {$comment = "Manually added: ".iplookup($ip)} + if ($timeout < 2) {$timeout = 3600} + if ($ports eq "") {$ports = "*"} + + if (!checkip(\$ip)) { + print "[$ip] is not a valid PUBLIC IP/CIDR\n"; + return; + } + + &clustersend("TA $ip $perm $ports $inout $timeout $comment"); + return; +} +# end doclustertempallow +############################################################################### +# start doclusterignore +sub doclusterignore { + my ($ip,$comment) = split (/\s/,$input{argument},2); + + if (!checkip(\$ip)) { + print "[$ip] is not a valid PUBLIC IP/CIDR\n"; + return; + } + + &clustersend("I $ip $comment"); + return; +} +# end doclusterignore +############################################################################### +# start doclusterirm +sub doclusterirm { + my ($ip,$comment) = split (/\s/,$input{argument},2); + + if (!checkip(\$ip)) { + print "[$ip] is not a valid PUBLIC IP/CIDR\n"; + return; + } + + &clustersend("IR $ip"); + return; +} +# end doclusterirm +############################################################################### +# start docconfig +sub docconfig { + my ($name,$value) = split (/\s/,$input{argument},2); + unless ($config{CLUSTER_CONFIG}) {print "No configuration setting requests allowed\n"; return} + unless ($name) {print "No configuration setting entered\n"; return} + + &clustersend("C $name $value"); + return; +} +# end docconfig +############################################################################### +# start doclustergrep +sub doclustergrep { + my $ip = $input{argument}; + if (!checkip(\$ip)) { + print "[$ip] is not a valid PUBLIC IP/CIDR\n"; + return; + } + + &clustersend("G $ip"); + return; +} +# end doclustergrep +############################################################################### +# start docfile +sub docfile { + my $name = $input{argument}; + unless ($config{CLUSTER_CONFIG}) {print "No configuration setting requests allowed\n"; return} + unless ($name) {print "No file entered\n"; return} + + if (-e $name) { + open (my $FH, "<", $name); + flock ($FH, LOCK_SH); + my @data = <$FH>; + close @data; + + my ($file, $filedir) = fileparse($name); + my $send = "FILE $file\n"; + foreach my $line (@data) {$send .= $line} + + &clustersend($send); + } else { + print "csf: Error [$name] does not exist\n"; + } + return; +} +# end docfile +############################################################################### +# start docrestart +sub docrestart { + &clustersend("RESTART"); + return; +} +# end docrestart +############################################################################### +# start clustersend +sub clustersend { + my $text = shift; + + my $cipher = Crypt::CBC->new( -key => $config{CLUSTER_KEY}, -cipher => 'Blowfish_PP'); + my $encrypted = $cipher->encrypt($text)."END\n"; + + foreach my $cip (split(/\,/,$config{CLUSTER_SENDTO})) { + my $localaddr = "0.0.0.0"; + if ($config{CLUSTER_LOCALADDR}) {$localaddr = $config{CLUSTER_LOCALADDR}} + my $sock; + eval {$sock = IO::Socket::INET->new(PeerAddr => $cip, PeerPort => $config{CLUSTER_PORT}, LocalAddr => $localaddr, Timeout => '10') or print "Cluster error connecting to $cip: $!\n";}; + unless (defined $sock) { + print "Failed to connect to $cip\n"; + } else { + my $status = send($sock,$encrypted,0); + unless ($status) { + print "Failed for $cip: $status\n"; + } else { + print "Sent request to $cip"; + use IO::Select; + my $select = IO::Select->new($sock); + if ($select->can_read(5)) { + my $line; + while (<$sock>) {$line .= $_} + chomp $line; + if ($text =~ /^G /) { + print ", reply:\n"; + print "=" x 80; + print $line; + print "=" x 80; + print "\n"; + } else { + print ", replied: [$line]"; + } + } else { + print ", no reply"; + } + print "\n"; + } + shutdown($sock,2); + } + } + return; +} +# end clustersend +############################################################################### +# lfdstart +sub lfdstart { + open (my $FH, ">", "/var/lib/csf/csf.restart") or die "Failed to create csf.restart - $!"; + flock ($FH, LOCK_EX); + close ($FH); + print "lfd will restart csf within the next $config{LF_PARSE} seconds\n"; + return; +} +# lfdstart +############################################################################### +# start dostop +sub dostop { + my $restart = shift; + &syscommand(__LINE__,"$config{IPTABLES} $verbose --policy INPUT ACCEPT"); + &syscommand(__LINE__,"$config{IPTABLES} $verbose --policy OUTPUT ACCEPT"); + &syscommand(__LINE__,"$config{IPTABLES} $verbose --policy FORWARD ACCEPT"); + &syscommand(__LINE__,"$config{IPTABLES} $verbose --flush"); + &syscommand(__LINE__,"$config{IPTABLES} $verbose --delete-chain"); + if ($config{NAT}) { + &syscommand(__LINE__,"$config{IPTABLES} $verbose -t nat --flush"); + &syscommand(__LINE__,"$config{IPTABLES} $verbose -t nat --delete-chain"); + } + if ($config{RAW}) { + &syscommand(__LINE__,"$config{IPTABLES} $verbose -t raw --flush"); + &syscommand(__LINE__,"$config{IPTABLES} $verbose -t raw --delete-chain"); + } + if ($config{MANGLE}) { + &syscommand(__LINE__,"$config{IPTABLES} $verbose -t mangle --flush"); + &syscommand(__LINE__,"$config{IPTABLES} $verbose -t mangle --delete-chain"); + } + + if ($config{IPV6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $verbose --policy INPUT ACCEPT"); + &syscommand(__LINE__,"$config{IP6TABLES} $verbose --policy OUTPUT ACCEPT"); + &syscommand(__LINE__,"$config{IP6TABLES} $verbose --policy FORWARD ACCEPT"); + &syscommand(__LINE__,"$config{IP6TABLES} $verbose --flush"); + &syscommand(__LINE__,"$config{IP6TABLES} $verbose --delete-chain"); + if ($config{NAT6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $verbose -t nat --flush"); + &syscommand(__LINE__,"$config{IP6TABLES} $verbose -t nat --delete-chain"); + } + if ($config{RAW6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $verbose -t raw --flush"); + &syscommand(__LINE__,"$config{IP6TABLES} $verbose -t raw --delete-chain"); + } + if ($config{MANGLE6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $verbose -t mangle --flush"); + &syscommand(__LINE__,"$config{IP6TABLES} $verbose -t mangle --delete-chain"); + } + } + if ($config{LF_IPSET}) { + &syscommand(__LINE__,"$config{IPSET} flush"); + &syscommand(__LINE__,"$config{IPSET} destroy"); + } + + if ($config{TESTING}) {&crontab("remove")} + return; +} +# end dostop +############################################################################### +# start dostart +sub dostart { + if (ConfigServer::Service::type() eq "systemd") { + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, $config{SYSTEMCTL},"is-active","firewalld"); + my @reply = <$childout>; + waitpid ($cmdpid, 0); + chomp @reply; + if ($reply[0] eq "active" or $reply[0] eq "activating") { + &error(__LINE__,"*Error* firewalld found to be running. You must stop and disable firewalld when using csf"); + exit 1; + } + } + + if ($config{TESTING}) {&crontab("add")} else {&crontab("remove")} + if (-e "/etc/csf/csf.error") {unlink ("/etc/csf/csf.error")} + + &getethdev; + &modprobe; + + $noowner = 0; + if ($config{VPS} and $config{SMTP_BLOCK}) { + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, "$config{IPTABLES} $config{IPTABLESWAIT} -I OUTPUT -p tcp --dport 9999 -m owner --uid-owner 0 -j $accept"); + my @ipdata = <$childout>; + waitpid ($cmdpid, 0); + chomp @ipdata; + if ($ipdata[0] =~ /# Warning: iptables-legacy tables present/) {shift @ipdata} + if ($ipdata[0] =~ /^iptables/) { + $warning .= "*WARNING* Cannot use SMTP_BLOCK on this VPS as the Monolithic kernel does not support the iptables module ipt_owner/xt_owner - SMTP_BLOCK disabled\n"; + $config{SMTP_BLOCK} = 0; + $noowner = 1; + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -D OUTPUT -p tcp --dport 9999 -m owner --uid-owner 0 -j $accept",0); + } + } + + my $path = "PATH=\$PATH:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin"; + my $csfpre; + my $csfpost; + if (-e "/usr/local/csf/bin/csfpre.sh") {$csfpre = "/usr/local/csf/bin/csfpre.sh"} + elsif (-e "/etc/csf/csfpre.sh") {$csfpre = "/etc/csf/csfpre.sh"} + if (-e "/usr/local/csf/bin/csfpost.sh") {$csfpost = "/usr/local/csf/bin/csfpost.sh"} + elsif (-e "/etc/csf/csfpost.sh") {$csfpost = "/etc/csf/csfpost.sh"} + + if ($csfpre ne "") { + chmod (0700,$csfpre); + my @conf = slurp($csfpre); + if ($conf[0] !~ /^\#\!/) { + open (my $CONF, ">", $csfpre); + flock ($CONF, LOCK_EX); + print $CONF "#!/bin/bash\n"; + foreach my $line (@conf) { + $line =~ s/$cleanreg//g; + print $CONF "$line\n"; + } + close ($CONF); + } + print "Running $csfpre\n"; + &syscommand(__LINE__,"$path ; $csfpre"); + } + + if ($config{WATCH_MODE}) { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N LOGACCEPT"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A LOGACCEPT -j ACCEPT"); + if ($config{IPV6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N LOGACCEPT"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A LOGACCEPT -j ACCEPT"); + } + } + + foreach my $name (keys %blocklists) { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N $name"); + if ($config{IPV6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N $name"); + } + } + if ($config{CC_ALLOW_FILTER}) {&syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N CC_ALLOWF")} + if ($config{CC_ALLOW_PORTS}) { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N CC_ALLOWP"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N CC_ALLOWPORTS"); + } + if ($config{CC_DENY_PORTS}) { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N CC_DENYP"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N CC_DENYPORTS"); + } + if ($config{CC_ALLOW}) {&syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N CC_ALLOW")} + if ($config{CC_DENY}) {&syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N CC_DENY")} + if (scalar(keys %blocklists) > 0 and $config{DROP_IP_LOGGING}) {&syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N BLOCKDROP")} + if (($config{CC_DENY} or $config{CC_ALLOW_FILTER}) and $config{DROP_IP_LOGGING}) {&syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N CCDROP")} + if ($config{IPV6}) { + if ($config{CC_ALLOW_FILTER}) {&syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N CC_ALLOWF")} + if ($config{CC_ALLOW_PORTS}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N CC_ALLOWP"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N CC_ALLOWPORTS"); + } + if ($config{CC_DENY_PORTS}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N CC_DENYP"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N CC_DENYPORTS"); + } + if ($config{CC_ALLOW}) {&syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N CC_ALLOW")} + if ($config{CC_DENY}) {&syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N CC_DENY")} + if (scalar(keys %blocklists) > 0 and $config{DROP_IP_LOGGING}) {&syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N BLOCKDROP")} + if (($config{CC_DENY} or $config{CC_ALLOW_FILTER}) and $config{DROP_IP_LOGGING}) {&syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N CCDROP")} + } + + if ($config{GLOBAL_ALLOW}) {&syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N GALLOWIN")} + if ($config{GLOBAL_ALLOW}) {&syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N GALLOWOUT")} + if ($config{GLOBAL_DENY}) {&syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N GDENYIN")} + if ($config{GLOBAL_DENY}) {&syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N GDENYOUT")} + if ($config{DYNDNS}) {&syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N ALLOWDYNIN")} + if ($config{DYNDNS}) {&syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N ALLOWDYNOUT")} + if ($config{GLOBAL_DYNDNS}) {&syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N GDYNIN")} + if ($config{GLOBAL_DYNDNS}) {&syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N GDYNOUT")} + if ($config{SYNFLOOD}) {&syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N SYNFLOOD")} + if ($config{PORTFLOOD}) {&syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N PORTFLOOD")} + if ($config{CONNLIMIT}) {&syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N CONNLIMIT")} + if ($config{UDPFLOOD}) {&syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N UDPFLOOD")} + if ($config{IPV6}) { + if ($config{GLOBAL_ALLOW}) {&syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N GALLOWIN")} + if ($config{GLOBAL_ALLOW}) {&syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N GALLOWOUT")} + if ($config{GLOBAL_DENY}) {&syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N GDENYIN")} + if ($config{GLOBAL_DENY}) {&syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N GDENYOUT")} + if ($config{DYNDNS}) {&syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N ALLOWDYNIN")} + if ($config{DYNDNS}) {&syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N ALLOWDYNOUT")} + if ($config{GLOBAL_DYNDNS}) {&syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N GDYNIN")} + if ($config{GLOBAL_DYNDNS}) {&syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N GDYNOUT")} + if ($config{SYNFLOOD}) {&syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N SYNFLOOD")} + if ($config{PORTFLOOD6}) {&syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N PORTFLOOD")} + if ($config{CONNLIMIT6}) {&syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N CONNLIMIT")} + if ($config{UDPFLOOD}) {&syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N UDPFLOOD")} + } + + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N LOGDROPIN"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N LOGDROPOUT"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N DENYIN"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N DENYOUT"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N ALLOWIN"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N ALLOWOUT"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N LOCALINPUT"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N LOCALOUTPUT"); + if ($config{IPV6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N LOGDROPIN"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N LOGDROPOUT"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N DENYIN"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N DENYOUT"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N ALLOWIN"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N ALLOWOUT"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N LOCALINPUT"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N LOCALOUTPUT"); + } + + if ($config{DROP_LOGGING}) { + my $dports; + if ($config{DROP_ONLYRES}) {$dports = "--dport 0:1023"} + $config{DROP_NOLOG} =~ s/\s//g; + if ($config{DROP_NOLOG} ne "") { + if ($config{FASTSTART}) {$faststart = 1} + foreach my $port (split(/\,/,$config{DROP_NOLOG})) { + if ($port eq "") {next} + if ($port !~ /^[\d:]*$/) {&error(__LINE__,"Invalid DROP_NOLOG port [$port]")} + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A LOGDROPIN -p tcp --dport $port -j $config{DROP}"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A LOGDROPIN -p udp --dport $port -j $config{DROP}"); + if ($config{IPV6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A LOGDROPIN -p tcp --dport $port -j $config{DROP}"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A LOGDROPIN -p udp --dport $port -j $config{DROP}"); + } + } + if ($config{FASTSTART}) {&faststart("DROP no logging")} + } + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A LOGDROPIN -p tcp $dports -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *TCP_IN Blocked* '"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A LOGDROPOUT -p tcp --syn -m limit --limit 30/m --limit-burst 5 -j $logouttarget 'Firewall: *TCP_OUT Blocked* '"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A LOGDROPIN -p udp $dports -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *UDP_IN Blocked* '"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A LOGDROPOUT -p udp -m limit --limit 30/m --limit-burst 5 -j $logouttarget 'Firewall: *UDP_OUT Blocked* '"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A LOGDROPIN -p icmp -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *ICMP_IN Blocked* '"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A LOGDROPOUT -p icmp -m limit --limit 30/m --limit-burst 5 -j $logouttarget 'Firewall: *ICMP_OUT Blocked* '"); + if ($config{IPV6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A LOGDROPIN -p tcp $dports -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *TCP6IN Blocked* '"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A LOGDROPOUT -p tcp --syn -m limit --limit 30/m --limit-burst 5 -j $logouttarget 'Firewall: *TCP6OUT Blocked* '"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A LOGDROPIN -p udp $dports -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *UDP6IN Blocked* '"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A LOGDROPOUT -p udp -m limit --limit 30/m --limit-burst 5 -j $logouttarget 'Firewall: *UDP6OUT Blocked* '"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A LOGDROPIN -p icmpv6 -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *ICMP6IN Blocked* '"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A LOGDROPOUT -p icmpv6 -m limit --limit 30/m --limit-burst 5 -j $logouttarget 'Firewall: *ICMP6OUT Blocked* '"); + } + if (scalar(keys %blocklists) > 0 and $config{DROP_IP_LOGGING}) {&syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A BLOCKDROP -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *BLOCK_LIST* '");} + if (($config{CC_DENY} or $config{CC_ALLOW_FILTER}) and $config{DROP_IP_LOGGING}) {&syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A CCDROP -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *CC_DENY* '");} + if ($config{PORTFLOOD}) {&syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A PORTFLOOD -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *Port Flood* '");} + if ($config{IPV6}) { + if (scalar(keys %blocklists) > 0 and $config{DROP_IP_LOGGING}) {&syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A BLOCKDROP -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *BLOCK_LIST* '");} + if (($config{CC_DENY} or $config{CC_ALLOW_FILTER}) and $config{DROP_IP_LOGGING}) {&syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A CCDROP -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *CC_DENY* '");} + if ($config{PORTFLOOD6}) {&syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A PORTFLOOD -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *Port Flood* '");} + } + } + + if (scalar(keys %blocklists) > 0 and $config{DROP_IP_LOGGING}) {&syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A BLOCKDROP -j $config{DROP}");} + if (($config{CC_DENY} or $config{CC_ALLOW_FILTER}) and $config{DROP_IP_LOGGING}) {&syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A CCDROP -j $config{DROP}");} + if ($config{IPV6}) { + if (scalar(keys %blocklists) > 0 and $config{DROP_IP_LOGGING}) {&syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A BLOCKDROP -j $config{DROP}");} + if (($config{CC_DENY} or $config{CC_ALLOW_FILTER}) and $config{DROP_IP_LOGGING}) {&syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A CCDROP -j $config{DROP}");} + } + + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A LOGDROPIN -j $config{DROP}"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A LOGDROPOUT -j $config{DROP_OUT}"); + if ($config{IPV6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A LOGDROPIN -j $config{DROP}"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A LOGDROPOUT -j $config{DROP_OUT}"); + } + + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A LOCALOUTPUT $ethdevout -j DENYOUT"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A LOCALINPUT $ethdevin -j DENYIN"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I LOCALOUTPUT $ethdevout -j ALLOWOUT"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I LOCALINPUT $ethdevin -j ALLOWIN"); + if ($config{IPV6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A LOCALOUTPUT $ethdevout -j DENYOUT"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A LOCALINPUT $ethdevin -j DENYIN"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I LOCALOUTPUT $ethdevout -j ALLOWOUT"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I LOCALINPUT $ethdevin -j ALLOWIN"); + } + + if ($config{MESSENGER}) { + if ($config{LF_IPSET}) { + &ipsetcreate("MESSENGER"); + if ($config{MESSENGER6}) {&ipsetcreate("MESSENGER_6")} + &domessenger("-m set --match-set MESSENGER src","A") + } + } + + &dopacketfilters; + &doportfilters; + + my $skipin = 1; + my $skipout = 1; + my $skipin6 = 1; + my $skipout6 = 1; + + my $dropout = $config{DROP_OUT}; + if ($config{DROP_OUT_LOGGING}) {$dropout = "LOGDROPOUT"} + + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I INPUT -i lo -j $accept"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT -o lo -j $accept"); + unless ($config{LF_SPI}) {&syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $ethdevout -j $accept")} + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $ethdevout -j $dropout"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -j LOGDROPIN"); + if ($config{IPV6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I INPUT -i lo -j $accept"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT -o lo -j $accept"); + unless ($config{IPV6_SPI}) {&syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $eth6devout -j $accept")} + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $eth6devout -j $dropout"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INPUT $eth6devin -j LOGDROPIN"); + } + + if ($config{SMTP_BLOCK}) { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N SMTPOUTPUT"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT -j SMTPOUTPUT"); + if ($config{IPV6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N SMTPOUTPUT"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT -j SMTPOUTPUT"); + } + if ($config{FASTSTART}) {$faststart = 1} + my $dropout = $config{DROP_OUT}; + if ($config{DROP_OUT_LOGGING}) {$dropout = "LOGDROPOUT"} + $config{SMTP_PORTS} =~ s/\s//g; + if ($config{SMTP_PORTS} ne "") { + unless ($config{SMTP_REDIRECT}) {&syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I SMTPOUTPUT -p tcp -m multiport --dports $config{SMTP_PORTS} -j $dropout",1)} + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I SMTPOUTPUT -p tcp -m multiport --dports $config{SMTP_PORTS} -m owner --uid-owner 0 -j $accept",1); + if ($config{IPV6}) { + unless ($config{SMTP_REDIRECT}) {&syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I SMTPOUTPUT -p tcp -m multiport --dports $config{SMTP_PORTS} -j $dropout",1)} + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I SMTPOUTPUT -p tcp -m multiport --dports $config{SMTP_PORTS} -m owner --uid-owner 0 -j $accept",1); + } + foreach my $item (split(/\,/,$config{SMTP_ALLOWUSER})) { + $item =~ s/\s//g; + my $uid = (getpwnam($item))[2]; + if ($uid) { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I SMTPOUTPUT -p tcp -m multiport --dports $config{SMTP_PORTS} -m owner --uid-owner $uid -j $accept",1); + if ($config{IPV6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I SMTPOUTPUT -p tcp -m multiport --dports $config{SMTP_PORTS} -m owner --uid-owner $uid -j $accept",1); + } + } + } + foreach my $item (split(/\,/,$config{SMTP_ALLOWGROUP})) { + $item =~ s/\s//g; + my $gid = (getgrnam($item))[2]; + if ($gid) { + syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I SMTPOUTPUT -p tcp -m multiport --dports $config{SMTP_PORTS} -m owner --gid-owner $gid -j $accept",1); + if ($config{IPV6}) { + syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I SMTPOUTPUT -p tcp -m multiport --dports $config{SMTP_PORTS} -m owner --gid-owner $gid -j $accept",1); + } + } + } + if ($config{SMTP_ALLOWLOCAL}) { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I SMTPOUTPUT -o lo -p tcp -m multiport --dports $config{SMTP_PORTS} -j $accept",1); + if ($config{IPV6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I SMTPOUTPUT -o lo -p tcp -m multiport --dports $config{SMTP_PORTS} -j $accept",1); + } + } + if ($config{SMTP_REDIRECT}) { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -t nat -I OUTPUT -p tcp -m multiport --dports $config{SMTP_PORTS} -j REDIRECT",1); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -t nat -I OUTPUT -p tcp -m multiport --dports $config{SMTP_PORTS} -m owner --uid-owner 0 -j RETURN",1); + if ($config{IPV6} and $config{SMTP_REDIRECT6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -t nat -I OUTPUT -p tcp -m multiport --dports $config{SMTP_PORTS} -j REDIRECT",1); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -t nat -I OUTPUT -p tcp -m multiport --dports $config{SMTP_PORTS} -m owner --uid-owner 0 -j RETURN",1); + } + foreach my $item (split(/\,/,$config{SMTP_ALLOWUSER})) { + $item =~ s/\s//g; + my $uid = (getpwnam($item))[2]; + if ($uid) { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -t nat -I OUTPUT -p tcp -m multiport --dports $config{SMTP_PORTS} -m owner --uid-owner $uid -j RETURN",1); + if ($config{IPV6} and $config{SMTP_REDIRECT6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -t nat -I OUTPUT -p tcp -m multiport --dports $config{SMTP_PORTS} -m owner --uid-owner $uid -j RETURN",1); + } + } + } + foreach my $item (split(/\,/,$config{SMTP_ALLOWGROUP})) { + $item =~ s/\s//g; + my $gid = (getgrnam($item))[2]; + if ($gid) { + syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -t nat -I OUTPUT -p tcp -m multiport --dports $config{SMTP_PORTS} -m owner --gid-owner $gid -j RETURN",1); + if ($config{IPV6} and $config{SMTP_REDIRECT6}) { + syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -t nat -I OUTPUT -p tcp -m multiport --dports $config{SMTP_PORTS} -m owner --gid-owner $gid -j RETURN",1); + } + } + } + if ($config{SMTP_ALLOWLOCAL}) { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -t nat -I OUTPUT -o lo -p tcp -m multiport --dports $config{SMTP_PORTS} -j RETURN",1); + if ($config{IPV6} and $config{SMTP_REDIRECT6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -t nat -I OUTPUT -o lo -p tcp -m multiport --dports $config{SMTP_PORTS} -j RETURN",1); + } + } + } + } + if ($config{FASTSTART}) {&faststart("SMTP Block")} + } + + if ($config{FASTSTART}) {$faststart = 1} + unless ($config{DNS_STRICT}) { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $ethdevout -p udp --sport 53 -j $accept"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $ethdevout -p tcp --sport 53 -j $accept"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $ethdevout -p udp --dport 53 -j $accept"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $ethdevout -p tcp --dport 53 -j $accept"); + if ($config{IPV6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $eth6devout -p udp --sport 53 -j $accept"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $eth6devout -p tcp --sport 53 -j $accept"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $eth6devout -p udp --dport 53 -j $accept"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $eth6devout -p tcp --dport 53 -j $accept"); + } + } + + unless ($config{DNS_STRICT_NS}) { + foreach my $line (slurp("/etc/resolv.conf")) { + $line =~ s/$cleanreg//g; + if ($line =~ /^(\s|\#|$)/) {next} + if ($line =~ /^nameserver\s+($ipv4reg)/) { + my $ip = $1; + unless ($ips{$ip} or $ipscidr->find($ip)) { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I INPUT $ethdevin -s $ip -p udp --sport 53 -j $accept"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I INPUT $ethdevin -s $ip -p tcp --sport 53 -j $accept"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I INPUT $ethdevin -s $ip -p udp --dport 53 -j $accept"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I INPUT $ethdevin -s $ip -p tcp --dport 53 -j $accept"); + $skipin += 4; + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $ethdevout -d $ip -p udp --sport 53 -j $accept"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $ethdevout -d $ip -p tcp --sport 53 -j $accept"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $ethdevout -d $ip -p udp --dport 53 -j $accept"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $ethdevout -d $ip -p tcp --dport 53 -j $accept"); + $skipout += 4; + } + } + if ($line =~ /^nameserver\s+($ipv6reg)/) { + my $ip = $1; + unless ($ips{$ip} or $ipscidr6->find($ip)) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I INPUT $ethdevin -s $ip -p udp --sport 53 -j $accept"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I INPUT $ethdevin -s $ip -p tcp --sport 53 -j $accept"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I INPUT $ethdevin -s $ip -p udp --dport 53 -j $accept"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I INPUT $ethdevin -s $ip -p tcp --dport 53 -j $accept"); + $skipin6 += 4; + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $ethdevout -d $ip -p udp --sport 53 -j $accept"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $ethdevout -d $ip -p tcp --sport 53 -j $accept"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $ethdevout -d $ip -p udp --dport 53 -j $accept"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $ethdevout -d $ip -p tcp --dport 53 -j $accept"); + $skipout6 += 4; + } + } + } + } + if ($config{FASTSTART}) {&faststart("DNS")} + + if ($config{MESSENGER}) { + $skipin += 2; + $skipout += 2; + if ($config{MESSENGER_HTTPS_IN}) { + $skipin += 1; + $skipout += 1; + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I INPUT $ethdevin -p tcp --dport $config{MESSENGER_HTTPS} -m limit --limit $config{MESSENGER_RATE} --limit-burst $config{MESSENGER_BURST} -j $accept"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $ethdevout -p tcp --sport $config{MESSENGER_HTTPS} -m limit --limit $config{MESSENGER_RATE} --limit-burst $config{MESSENGER_BURST} -j $accept"); + } + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I INPUT $ethdevin -p tcp --dport $config{MESSENGER_HTML} -m limit --limit $config{MESSENGER_RATE} --limit-burst $config{MESSENGER_BURST} -j $accept"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I INPUT $ethdevin -p tcp --dport $config{MESSENGER_TEXT} -m limit --limit $config{MESSENGER_RATE} --limit-burst $config{MESSENGER_BURST} -j $accept"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $ethdevout -p tcp --sport $config{MESSENGER_HTML} -m limit --limit $config{MESSENGER_RATE} --limit-burst $config{MESSENGER_BURST} -j $accept"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $ethdevout -p tcp --sport $config{MESSENGER_TEXT} -m limit --limit $config{MESSENGER_RATE} --limit-burst $config{MESSENGER_BURST} -j $accept"); + if ($config{MESSENGER6}) { + $skipin6 += 2; + $skipout6 += 2; + if ($config{MESSENGER_HTTPS_IN}) { + $skipin6 += 1; + $skipout6 += 1; + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I INPUT $ethdevin -p tcp --dport $config{MESSENGER_HTTPS} -m limit --limit $config{MESSENGER_RATE} --limit-burst $config{MESSENGER_BURST} -j $accept"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $ethdevout -p tcp --sport $config{MESSENGER_HTTPS} -m limit --limit $config{MESSENGER_RATE} --limit-burst $config{MESSENGER_BURST} -j $accept"); + } + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I INPUT $ethdevin -p tcp --dport $config{MESSENGER_HTML} -m limit --limit $config{MESSENGER_RATE} --limit-burst $config{MESSENGER_BURST} -j $accept"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I INPUT $ethdevin -p tcp --dport $config{MESSENGER_TEXT} -m limit --limit $config{MESSENGER_RATE} --limit-burst $config{MESSENGER_BURST} -j $accept"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $ethdevout -p tcp --sport $config{MESSENGER_HTML} -m limit --limit $config{MESSENGER_RATE} --limit-burst $config{MESSENGER_BURST} -j $accept"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $ethdevout -p tcp --sport $config{MESSENGER_TEXT} -m limit --limit $config{MESSENGER_RATE} --limit-burst $config{MESSENGER_BURST} -j $accept"); + } + } + + if ($config{DOCKER}) { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N DOCKER"); + if ($config{NAT}) { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -t nat -N DOCKER"); + } + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -t nat -A POSTROUTING -s $config{DOCKER_NETWORK4} ! -o $config{DOCKER_DEVICE} -j MASQUERADE"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A FORWARD -o $config{DOCKER_DEVICE} $statemodule RELATED,ESTABLISHED -j ACCEPT"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A FORWARD -i $config{DOCKER_DEVICE} ! -o $config{DOCKER_DEVICE} -j ACCEPT"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A FORWARD -i $config{DOCKER_DEVICE} -o $config{DOCKER_DEVICE} -j ACCEPT"); + if ($config{IPV6} and $config{NAT6} and $config{DOCKER_NETWORK6} ne "") { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N DOCKER"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -t nat -A POSTROUTING -s $config{DOCKER_NETWORK6} ! -o $config{DOCKER_DEVICE} -j MASQUERADE"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A FORWARD -o $config{DOCKER_DEVICE} $statemodule RELATED,ESTABLISHED -j ACCEPT"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A FORWARD -i $config{DOCKER_DEVICE} ! -o $config{DOCKER_DEVICE} -j ACCEPT"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A FORWARD -i $config{DOCKER_DEVICE} -o $config{DOCKER_DEVICE} -j ACCEPT"); + } + } + + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $skipout $ethdevout -j LOCALOUTPUT"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I INPUT $skipin $ethdevin -j LOCALINPUT"); + if ($config{IPV6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $skipout6 $eth6devout -j LOCALOUTPUT"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I INPUT $skipin6 $eth6devin -j LOCALINPUT"); + } + + $config{ETH_DEVICE_SKIP} =~ s/\s//g; + if ($config{ETH_DEVICE_SKIP} ne "") { + foreach my $device (split(/\,/,$config{ETH_DEVICE_SKIP})) { + if ($ifaces{$device}) { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I INPUT -i $device -j $accept"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT -o $device -j $accept"); + if ($config{IPV6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I INPUT -i $device -j $accept"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT -o $device -j $accept"); + } + } else { + $warning .= "*WARNING* ETH_DEVICE_SKIP device [$device] not listed in ip/ifconfig\n"; + } + } + } + + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose --policy INPUT DROP",1); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose --policy OUTPUT DROP",1); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose --policy FORWARD DROP",1); + if ($config{IPV6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose --policy INPUT DROP",1); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose --policy OUTPUT DROP",1); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose --policy FORWARD DROP",1); + } + + if ($csfpost ne "") { + chmod (0700,$csfpost); + my @conf = slurp($csfpost); + + if ($conf[0] !~ /^\#\!/) { + open (my $CONF, ">", $csfpost); + flock ($CONF, LOCK_EX); + print $CONF "#!/bin/bash\n"; + foreach my $line (@conf) { + $line =~ s/$cleanreg//g; + print $CONF "$line\n"; + } + close ($CONF); + } + print "Running $csfpost\n"; + &syscommand(__LINE__,"$path ; $csfpost"); + } + + if ($config{VPS}) { + open (my $FH, "<", "/proc/sys/kernel/osrelease"); + flock ($FH, LOCK_SH); + my @data = <$FH>; + close ($FH); + chomp @data; + if ($data[0] =~ /^(\d+)\.(\d+)\.(\d+)/) { + my $maj = $1; + my $mid = $2; + my $min = $3; + if (($maj > 2) or (($maj > 1) and ($mid > 5) and ($min > 26))) { + } else { + my $status = 0; + if (-e "/etc/pure-ftpd.conf") { + my @conf = slurp("/etc/pure-ftpd.conf"); + if (my @ls = grep {$_ =~ /^PassivePortRange\s+(\d+)\s+(\d+)/} @conf) { + if ($ls[0] =~ /^PassivePortRange\s+(\d+)\s+(\d+)/) { + if ($config{TCP_IN} !~ /\b$1:$2\b/) {$status = 1} + } + } else {$status = 1} + if ($status) {$warning .= "*WARNING* Since the Virtuozzo VPS iptables ip_conntrack_ftp kernel module is currently broken you have to open a PASV port hole in iptables for incoming FTP connections to work correctly. See the csf readme.txt under 'A note about FTP Connection Issues' on how to do this if you have not already done so.\n"} + } + elsif (-e "/etc/proftpd.conf") { + my @conf = slurp("/etc/proftpd.conf"); + if (my @ls = grep {$_ =~ /^PassivePorts\s+(\d+)\s+(\d+)/} @conf) { + if ($ls[0] =~ /^PassivePorts\s+(\d+)\s+(\d+)/) { + if ($config{TCP_IN} !~ /\b$1:$2\b/) {$status = 1} + } + } else {$status = 1} + if ($status) {$warning .= "*WARNING* Since the Virtuozzo VPS iptables ip_conntrack_ftp kernel module is currently broken you have to open a PASV port hole in iptables for incoming FTP connections to work correctly. See the csf readme.txt under 'A note about FTP Connection Issues' on how to do this if you have not already done so.\n"} + } + } + } + } + return; +} +# end dostart +############################################################################### +# start doadd +sub doadd { + my ($ip,$comment) = split (/\s/,$input{argument},2); + my $checkip = checkip(\$ip); + + &getethdev; + + if ($ips{$ip} or $ipscidr->find($ip) or $ipscidr6->find($ip)) { + print "add failed: $ip is one of this servers addresses!\n"; + return; + } + + if ($checkip == 6 and !$config{IPV6}) { + print "add failed: [$ip] is valid IPv6 but IPV6 is not enabled in csf.conf\n"; + return; + } + + if (!$checkip and !(($ip =~ /:|\|/) and ($ip =~ /=/))) { + print "add failed: [$ip] is not a valid PUBLIC IP/CIDR\n"; + return; + } + + my $hit; + my @deny = slurp("/etc/csf/csf.deny"); + foreach my $line (@deny) { + $line =~ s/$cleanreg//g; + if ($line eq "") {next} + if ($line =~ /^\s*\#|Include/) {next} + my ($ipd,$commentd) = split (/\s/,$line,2); + checkip(\$ipd); + if ($ipd eq $ip) { + $hit = 1; + last; + } + } + if ($hit) { + print "Removing $ip from csf.deny...\n"; + $input{argument} = $ip; + &dokill; + } + + my $allowmatches; + my @allow = slurp("/etc/csf/csf.allow"); + foreach my $line (@allow) { + if ($line =~ /^Include\s*(.*)$/) { + my @incfile = slurp($1); + push @allow,@incfile; + } + } + foreach my $line (@allow) { + $line =~ s/$cleanreg//g; + if ($line eq "") {next} + if ($line =~ /^\s*\#|Include/) {next} + my ($ipd,$commentd) = split (/\s/,$line,2); + checkip(\$ipd); + if ($ipd eq $ip) { + $allowmatches = 1; + last; + } + } + + my $ipstring = quotemeta($ip); + sysopen (my $ALLOW, "/etc/csf/csf.allow", O_RDWR | O_CREAT) or &error(__LINE__,"Could not open /etc/csf/csf.allow: $!"); + flock ($ALLOW, LOCK_EX) or &error(__LINE__,"Could not lock /etc/csf/csf.allow: $!"); + my $text = join("", <$ALLOW>); + @allow = split(/$slurpreg/,$text); + chomp @allow; + unless ($allowmatches) { + if ($comment eq "") {$comment = "Manually allowed: ".iplookup($ip)} + print $ALLOW "$ip \# $comment - ".localtime(time)."\n"; + if ($config{TESTING}) { + print "Adding $ip to csf.allow only while in TESTING mode (not iptables ACCEPT)\n"; + } else { + print "Adding $ip to csf.allow and iptables ACCEPT...\n"; + &linefilter($ip, "allow"); + } + } else { + print "add failed: $ip is in already in the allow file /etc/csf/csf.allow\n"; + } + close ($ALLOW) or &error(__LINE__,"Could not close /etc/csf/csf.allow: $!"); + return; +} +# end doadd +############################################################################### +# start dodeny +sub dodeny { + my ($ip,$comment) = split (/\s/,$input{argument},2); + my $checkip = checkip(\$ip); + + &getethdev; + + if ($ips{$ip} or $ipscidr->find($ip) or $ipscidr6->find($ip)) { + print "deny failed: [$ip] is one of this servers addresses!\n"; + return; + } + + if ($checkip == 6 and !$config{IPV6}) { + print "deny failed: [$ip] is valid IPv6 but IPV6 is not enabled in csf.conf\n"; + return; + } + + if (!$checkip and !(($ip =~ /:|\|/) and ($ip =~ /=/))) { + print "deny failed: [$ip] is not a valid PUBLIC IP/CIDR\n"; + return; + } + + my @allow = slurp("/etc/csf/csf.allow"); + foreach my $line (@allow) { + if ($line =~ /^Include\s*(.*)$/) { + my @incfile = slurp($1); + push @allow,@incfile; + } + } + foreach my $line (@allow) { + $line =~ s/$cleanreg//g; + if ($line eq "") {next} + if ($line =~ /^\s*\#|Include/) {next} + my ($ipd,$commentd) = split (/\s/,$line,2); + checkip(\$ipd); + if ($ipd eq $ip) { + print "deny failed: $ip is in the allow file /etc/csf/csf.allow\n"; + return; + } + elsif ($ipd =~ /(.*\/\d+)/) { + my $cidrhit = $1; + if (checkip(\$cidrhit)) { + my $cidr = Net::CIDR::Lite->new; + eval {local $SIG{__DIE__} = undef; $cidr->add($cidrhit)}; + if ($cidr->find($ip)) { + print "deny failed: $ip is in the allow file /etc/csf/csf.allow\n"; + return; + } + } + } + } + + my @ignore = slurp("/etc/csf/csf.ignore"); + foreach my $line (@ignore) { + if ($line =~ /^Include\s*(.*)$/) { + my @incfile = slurp($1); + push @ignore,@incfile; + } + } + foreach my $line (@ignore) { + $line =~ s/$cleanreg//g; + if ($line eq "") {next} + if ($line =~ /^\s*\#|Include/) {next} + my ($ipd,$commentd) = split (/\s/,$line,2); + checkip(\$ipd); + if ($ipd eq $ip) { + print "deny failed: $ip is in the ignore file /etc/csf/csf.ignore\n"; + return; + } + elsif ($ipd =~ /(.*\/\d+)/) { + my $cidrhit = $1; + if (checkip(\$cidrhit)) { + my $cidr = Net::CIDR::Lite->new; + eval {local $SIG{__DIE__} = undef; $cidr->add($cidrhit)}; + if ($cidr->find($ip)) { + print "deny failed: $ip is in the ignore file /etc/csf/csf.ignore\n"; + return; + } + } + } + } + + my $denymatches; + my @deny = slurp("/etc/csf/csf.deny"); + foreach my $line (@deny) { + if ($line =~ /^Include\s*(.*)$/) { + my @incfile = slurp($1); + push @deny,@incfile; + } + } + foreach my $line (@deny) { + $line =~ s/$cleanreg//g; + if ($line eq "") {next} + if ($line =~ /^\s*\#|Include/) {next} + my ($ipd,$commentd) = split (/\s/,$line,2); + checkip(\$ipd); + if ($ipd eq $ip) { + $denymatches = 1; + last; + } + } + + sysopen (my $DENY, "/etc/csf/csf.deny", O_RDWR | O_CREAT) or &error(__LINE__,"Could not open /etc/csf/csf.deny: $!"); + flock ($DENY, LOCK_EX) or &error(__LINE__,"Could not lock /etc/csf/csf.deny: $!"); + my $text = join("", <$DENY>); + @deny = split(/$slurpreg/,$text); + chomp @deny; + if ($config{LF_REPEATBLOCK} and $denymatches < $config{LF_REPEATBLOCK}) {$denymatches = 0} + if ($denymatches == 0) { + my $ipcount; + my @denyips; + foreach my $line (@deny) { + $line =~ s/$cleanreg//g; + if ($line eq "") {next} + if ($line =~ /^\s*\#|Include/) {next} + if ($line =~ /do not delete/i) {next} + my ($ipd,$commentd) = split (/\s/,$line,2); + $ipcount++; + push @denyips,$line; + } + if (($config{DENY_IP_LIMIT} > 0) and ($ipcount >= $config{DENY_IP_LIMIT})) { + seek ($DENY, 0, 0); + truncate ($DENY, 0); + foreach my $line (@deny) { + my $hit = 0; + for (my $x = 0; $x < ($ipcount - $config{DENY_IP_LIMIT})+1;$x++) { + if ($line eq $denyips[$x]) {$hit = 1;} + } + if ($hit) {next} + print $DENY $line."\n"; + } + print "csf: DENY_IP_LIMIT ($config{DENY_IP_LIMIT}), the following IP's were removed from /etc/csf/csf.deny:\n"; + for (my $x = 0; $x < ($ipcount - $config{DENY_IP_LIMIT})+1;$x++) { + print "$denyips[$x]\n"; + my ($kip,undef) = split (/\s/,$denyips[$x],2); + &linefilter($kip, "deny", "", 1); + +# sysopen (my $TEMPIP, "/var/lib/csf/csf.tempip", O_RDWR | O_CREAT); +# flock ($TEMPIP, LOCK_EX); +# my @data = <$TEMPIP>; +# chomp @data; +# seek ($TEMPIP, 0, 0); +# truncate ($TEMPIP, 0); +# foreach my $line (@data) { +# my ($oip,undef,undef,undef) = split(/\|/,$line,4); +# checkip(\$oip); +# if ($oip eq $kip) {next} +# print $TEMPIP "$line\n"; +# } +# close ($TEMPIP); + } + + } + + if ($comment eq "") {$comment = "Manually denied: ".iplookup($ip)} + print $DENY "$ip \# $comment - ".localtime(time)."\n"; + + if ($config{TESTING}) { + print "Adding $ip to csf.deny only while in TESTING mode (not iptables DROP)\n"; + } else { + print "Adding $ip to csf.deny and iptables DROP...\n"; + &linefilter($ip, "deny"); + } + } else { + print "deny failed: $ip is in already in the deny file /etc/csf/csf.deny $denymatches times\n"; + } + close ($DENY) or &error(__LINE__,"Could not close /etc/csf/csf.deny: $!"); + return; +} +# end dodeny +############################################################################### +# start dokill +sub dokill { + my $ip = $input{argument}; + my $is_ip = 0; + if (checkip(\$ip)) {$is_ip = 1} + + if (!$is_ip and !(($ip =~ /:|\|/) and ($ip =~ /=/))) { + print "[$ip] is not a valid PUBLIC IP/CIDR\n"; + return; + } + + &getethdev; + + sysopen (my $DENY, "/etc/csf/csf.deny", O_RDWR | O_CREAT) or &error(__LINE__,"Could not open /etc/csf/csf.deny: $!"); + flock ($DENY, LOCK_EX) or &error(__LINE__,"Could not lock /etc/csf/csf.deny: $!"); + my $text = join("", <$DENY>); + my @deny = split(/$slurpreg/,$text); + chomp @deny; + seek ($DENY, 0, 0); + truncate ($DENY, 0); + my $hit = 0; + foreach my $line (@deny) { + $line =~ s/$cleanreg//g; + my ($ipd,$commentd) = split (/\s/,$line,2); + my $ipmatch = $ipd; + if ($is_ip and $ipd =~ /($ipv4reg|$ipv6reg)/) { + $ipmatch = $1; + if ($ipd =~ /(\/\d+)$/) {$ipmatch .= $1} + } + checkip(\$ipd); + if (uc $ip eq uc $ipmatch) { + if ($commentd =~ /do not delete/i) { + print "csf: $ip set as \"do not delete\" - not removed\n"; + $hit = -1; + } else { + print "Removing rule...\n"; + &linefilter($ipd, "deny", "", 1); + $hit = 1; + next; + } + } + print $DENY $line."\n"; + } + close ($DENY) or &error(__LINE__,"Could not close /etc/csf/csf.deny: $!"); + + if ($hit and ($config{LF_PERMBLOCK} or $config{LF_NETBLOCK})) { + sysopen (my $TEMPIP, "/var/lib/csf/csf.tempip", O_RDWR | O_CREAT); + flock ($TEMPIP, LOCK_EX); + my @data = <$TEMPIP>; + chomp @data; + seek ($TEMPIP, 0, 0); + truncate ($TEMPIP, 0); + foreach my $line (@data) { + my ($oip,undef,undef,undef) = split(/\|/,$line,4); + if ($oip eq $ip) {next} + print $TEMPIP "$line\n"; + } + close ($TEMPIP); + } + elsif ($hit == -1) {} + elsif (!$hit) { + print "csf: $ip not found in csf.deny\n"; + } + return; +} +# end dokill +############################################################################### +# start dokillall +sub dokillall { + + &getethdev; + + sysopen (my $DENY, "/etc/csf/csf.deny", O_RDWR | O_CREAT) or &error(__LINE__,"Could not open /etc/csf/csf.deny: $!"); + flock ($DENY, LOCK_EX) or &error(__LINE__,"Could not lock /etc/csf/csf.deny: $!"); + my $text = join("", <$DENY>); + my @deny = split(/$slurpreg/,$text); + chomp @deny; + seek ($DENY, 0, 0); + truncate ($DENY, 0); + my $hit = 0; + foreach my $line (@deny) { + $line =~ s/$cleanreg//g; + if ($line =~ /^(\#|\n|Include)/) { + print $DENY $line."\n"; + } + elsif ($line =~ /do not delete/i) { + print $DENY $line."\n"; + print "csf: skipped line: $line\n"; + } + else { + my ($ipd,$commentd) = split (/\s/,$line,2); + &linefilter($ipd, "deny", "", 1); + } + } + close ($DENY) or &error(__LINE__,"Could not close /etc/csf/csf.deny: $!"); + print "csf: all entries removed from csf.deny\n"; + return; +} +# end dokillall +############################################################################### +# start doakill +sub doakill { + my $ip = $input{argument}; + + if (!checkip(\$ip) and !(($ip =~ /:|\|/) and ($ip =~ /=/))) { + print "[$ip] is not a valid PUBLIC IP/CIDR\n"; + return; + } + + &getethdev; + + sysopen (my $ALLOW, "/etc/csf/csf.allow", O_RDWR | O_CREAT) or &error(__LINE__,"Could not open /etc/csf/csf.allow: $!"); + flock ($ALLOW, LOCK_EX) or &error(__LINE__,"Could not lock /etc/csf/csf.allow: $!"); + my $text = join("", <$ALLOW>); + my @allow = split(/$slurpreg/,$text); + chomp @allow; + seek ($ALLOW, 0, 0); + truncate ($ALLOW, 0); + my $hit = 0; + foreach my $line (@allow) { + $line =~ s/$cleanreg//g; + my ($ipd,$commentd) = split (/\s/,$line,2); + checkip(\$ipd); + if (uc $ipd eq uc $ip) { + print "Removing rule...\n"; + &linefilter($ipd, "allow", "", 1); + $hit = 1; + next; + } + print $ALLOW $line."\n"; + } + close ($ALLOW) or &error(__LINE__,"Could not close /etc/csf/csf.allow: $!"); + unless ($hit) { + print "csf: $ip not found in csf.allow\n"; + } + return; +} +# end doakill +############################################################################### +# start help +sub dohelp { + my $generic = " (cPanel)"; + if ($config{GENERIC}) {$generic = " (generic)"} + if ($config{DIRECTADMIN}) {$generic = " (DirectAdmin)"} + print "csf: v$version$generic\n"; + open (my $IN, "<", "/usr/local/csf/lib/csf.help"); + flock ($IN, LOCK_SH); + print <$IN>; + close ($IN); + return; +} +# end help +############################################################################### +# start dopacketfilters +sub dopacketfilters { + if ($config{PACKET_FILTER} and $config{LF_SPI}) { + if ($config{FASTSTART}) {$faststart = 1} + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N INVDROP"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N INVALID"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INVALID $statemodule INVALID -j INVDROP"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INVALID -p tcp --tcp-flags ALL NONE -j INVDROP"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INVALID -p tcp --tcp-flags ALL ALL -j INVDROP"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INVALID -p tcp --tcp-flags SYN,FIN SYN,FIN -j INVDROP"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INVALID -p tcp --tcp-flags SYN,RST SYN,RST -j INVDROP"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INVALID -p tcp --tcp-flags FIN,RST FIN,RST -j INVDROP"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INVALID -p tcp --tcp-flags ACK,FIN FIN -j INVDROP"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INVALID -p tcp --tcp-flags ACK,PSH PSH -j INVDROP"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INVALID -p tcp --tcp-flags ACK,URG URG -j INVDROP"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INVALID -p tcp ! --syn $statemodulenew -j INVDROP"); + if ($config{IPV6} and $config{IPV6_SPI}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N INVDROP"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -N INVALID"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INVALID $statemodule INVALID -j INVDROP"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INVALID -p tcp --tcp-flags ALL NONE -j INVDROP"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INVALID -p tcp --tcp-flags ALL ALL -j INVDROP"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INVALID -p tcp --tcp-flags SYN,FIN SYN,FIN -j INVDROP"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INVALID -p tcp --tcp-flags SYN,RST SYN,RST -j INVDROP"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INVALID -p tcp --tcp-flags FIN,RST FIN,RST -j INVDROP"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INVALID -p tcp --tcp-flags ACK,FIN FIN -j INVDROP"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INVALID -p tcp --tcp-flags ACK,PSH PSH -j INVDROP"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INVALID -p tcp --tcp-flags ACK,URG URG -j INVDROP"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INVALID -p tcp ! --syn $statemodule6new -j INVDROP"); + } + if ($config{FASTSTART}) {&faststart("Packet Filter")} + + if ($config{DROP_PF_LOGGING}) { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INVDROP $statemodule INVALID -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *INVALID* '"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INVDROP -p tcp --tcp-flags ALL NONE -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *INV_AN* '"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INVDROP -p tcp --tcp-flags ALL ALL -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *INV_AA* '"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INVDROP -p tcp --tcp-flags SYN,FIN SYN,FIN -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *INV_SFSF* '"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INVDROP -p tcp --tcp-flags SYN,RST SYN,RST -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *INV_SRSR* '"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INVDROP -p tcp --tcp-flags FIN,RST FIN,RST -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *INV_FRFR* '"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INVDROP -p tcp --tcp-flags ACK,FIN FIN -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *INV_AFF* '"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INVDROP -p tcp --tcp-flags ACK,PSH PSH -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *INV_APP* '"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INVDROP -p tcp --tcp-flags ACK,URG URG -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *INV_AUU* '"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INVDROP -p tcp ! --syn $statemodulenew -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *INV_NOSYN* '"); + if ($config{IPV6} and $config{IPV6_SPI}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INVDROP $statemodule INVALID -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *INVALID* '"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INVDROP -p tcp --tcp-flags ALL NONE -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *INV_AN* '"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INVDROP -p tcp --tcp-flags ALL ALL -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *INV_AA* '"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INVDROP -p tcp --tcp-flags SYN,FIN SYN,FIN -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *INV_SFSF* '"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INVDROP -p tcp --tcp-flags SYN,RST SYN,RST -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *INV_SRSR* '"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INVDROP -p tcp --tcp-flags FIN,RST FIN,RST -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *INV_FRFR* '"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INVDROP -p tcp --tcp-flags ACK,FIN FIN -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *INV_AFF* '"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INVDROP -p tcp --tcp-flags ACK,PSH PSH -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *INV_APP* '"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INVDROP -p tcp --tcp-flags ACK,URG URG -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *INV_AUU* '"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INVDROP -p tcp ! --syn $statemodule6new -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *INV_NOSYN* '"); + } + } + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INVDROP -j $config{DROP}"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I INPUT $ethdevin -p tcp -j INVALID"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $ethdevout -p tcp -j INVALID"); + if ($config{IPV6} and $config{IPV6_SPI}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INVDROP -j $config{DROP}"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I INPUT $eth6devin -p tcp -j INVALID"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I OUTPUT $eth6devout -p tcp -j INVALID"); + } + } + return; +} +# end dopacketfilters +############################################################################### +# start doportfilters +sub doportfilters { + my $dropin = $config{DROP}; + my $dropout = $config{DROP_OUT}; + if ($config{DROP_LOGGING}) {$dropin = "LOGDROPIN"} + if ($config{DROP_LOGGING}) {$dropout = "LOGDROPOUT"} + + my @entries = slurp("/etc/csf/csf.sips"); + foreach my $line (@entries) { + if ($line =~ /^Include\s*(.*)$/) { + my @incfile = slurp($1); + push @entries,@incfile; + } + } + foreach my $line (@entries) { + $line =~ s/$cleanreg//g; + if ($line eq "") {next} + if ($line =~ /^\s*\#|Include/) {next} + my ($ip,$comment) = split (/\s/,$line,2); + my $iptype = checkip(\$ip); + if ($iptype == 4) { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A LOCALINPUT $ethdevin -d $ip -j $dropin"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A LOCALOUTPUT $ethdevout -s $ip -j $dropout"); + } + elsif ($iptype == 6) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A LOCALINPUT $eth6devin -d $ip -j $dropin"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A LOCALOUTPUT $eth6devout -s $ip -j $dropout"); + } + } + + if ($config{GLOBAL_DENY}) { + if ($config{LF_IPSET}) { + my $pktin = $config{DROP}; + my $pktout = $config{DROP_OUT}; + if ($config{DROP_IP_LOGGING}) {$pktin = "LOGDROPIN"} + if ($config{DROP_OUT_LOGGING}) {$pktout = "LOGDROPOUT"} + &ipsetcreate("chain_GDENY"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A GDENYIN -m set --match-set chain_GDENY src -j $pktin"); + unless ($config{LF_BLOCKINONLY}) {&syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A GDENYOUT -m set --match-set chain_GDENY dst -j $pktout")} + if ($config{IPV6}) { + &ipsetcreate("chain_6_GDENY"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A GDENYIN -m set --match-set chain_6_GDENY src -j $pktin"); + unless ($config{LF_BLOCKINONLY}) {&syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A GDENYOUT -m set --match-set chain_6_GDENY dst -j $pktout")} + } + } + if (-e "/var/lib/csf/csf.gdeny") { + if ($config{FASTSTART}) {$faststart = 1} + foreach my $line (slurp("/var/lib/csf/csf.gdeny")) { + $line =~ s/$cleanreg//g; + if ($line =~ /^(\s|\#|$)/) {next} + my ($ip,$comment) = split (/\s/,$line,2); + &linefilter($ip, "deny","GDENY"); + } + if ($config{FASTSTART}) {&faststart("Global Deny")} + } + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A LOCALINPUT $ethdevin -j GDENYIN"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A LOCALOUTPUT $ethdevout -j GDENYOUT"); + if ($config{IPV6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A LOCALINPUT $eth6devin -j GDENYIN"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A LOCALOUTPUT $eth6devout -j GDENYOUT"); + } + } + + my @deny = slurp("/etc/csf/csf.deny"); + foreach my $line (@deny) { + if ($line =~ /^Include\s*(.*)$/) { + my @incfile = slurp($1); + push @deny,@incfile; + } + } + if ($config{FASTSTART}) {$faststart = 1} + if ($config{LF_IPSET}) { + my $pktin = $config{DROP}; + my $pktout = $config{DROP_OUT}; + if ($config{DROP_IP_LOGGING}) {$pktin = "LOGDROPIN"} + if ($config{DROP_OUT_LOGGING}) {$pktout = "LOGDROPOUT"} + &ipsetcreate("chain_DENY"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A DENYIN -m set --match-set chain_DENY src -j $pktin"); + unless ($config{LF_BLOCKINONLY}) {&syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A DENYOUT -m set --match-set chain_DENY dst -j $pktout")} + if ($config{IPV6}) { + &ipsetcreate("chain_6_DENY"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A DENYIN -m set --match-set chain_6_DENY src -j $pktin"); + unless ($config{LF_BLOCKINONLY}) {&syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A DENYOUT -m set --match-set chain_6_DENY dst -j $pktout")} + } + } + foreach my $line (@deny) { + $line =~ s/$cleanreg//g; + if ($line eq "") {next} + if ($line =~ /^\s*\#|Include/) {next} + my ($ip,$comment) = split (/\s/,$line,2); + &linefilter($ip, "deny"); + } + if ($config{FASTSTART}) {&faststart("csf.deny")} + + if (! -z "/var/lib/csf/csf.tempban") { + my $dropin = $config{DROP}; + my $dropout = $config{DROP_OUT}; + if ($config{DROP_IP_LOGGING}) {$dropin = "LOGDROPIN"} + if ($config{DROP_OUT_LOGGING}) {$dropout = "LOGDROPOUT"} + + sysopen (my $TEMPBAN, "/var/lib/csf/csf.tempban", O_RDWR | O_CREAT); + flock ($TEMPBAN, LOCK_EX); + my @data = <$TEMPBAN>; + chomp @data; + + my @newdata; + foreach my $line (@data) { + my ($time,$ip,$port,$inout,$timeout,$message) = split(/\|/,$line); + my $iptype = checkip(\$ip); + if ($iptype == 6 and !$config{IPV6}) {next} + if ((((time - $time) < $timeout) and $iptype) or ($message =~ /\(CF:([^\)]+)\)/)) { + if ($inout =~ /in/) { + if ($port) { + foreach my $dport (split(/\,/,$port)) { + my ($tport,$proto) = split(/\;/,$dport); + $dport = $tport; + if ($proto eq "") {$proto = "tcp"} + if ($iptype == 6) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A DENYIN $eth6devin -p $proto --dport $dport -s $ip -j $dropin"); + if ($messengerports{$dport} and $config{MESSENGER6} and $config{MESSENGER_TEMP}) {&domessenger($ip,"A",$dport)} + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A DENYIN $ethdevin -p $proto --dport $dport -s $ip -j $dropin"); + if ($messengerports{$dport} and $config{MESSENGER} and $config{MESSENGER_TEMP}) {&domessenger($ip,"A",$dport)} + } + } + } else { + if ($iptype == 6) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A DENYIN $eth6devin -s $ip -j $dropin"); + if ($config{MESSENGER6} and $config{MESSENGER_TEMP}) {&domessenger($ip,"A")} + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A DENYIN $ethdevin -s $ip -j $dropin"); + if ($config{MESSENGER} and $config{MESSENGER_TEMP}) {&domessenger($ip,"A")} + } + } + } + if ($inout =~ /out/) { + if ($port) { + foreach my $dport (split(/\,/,$port)) { + my ($tport,$proto) = split(/\;/,$dport); + $dport = $tport; + if ($proto eq "") {$proto = "tcp"} + if ($iptype == 6) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A DENYOUT $eth6devout -p $proto --dport $dport -d $ip -j $dropout"); + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A DENYOUT $ethdevout -p $proto --dport $dport -d $ip -j $dropout"); + } + } + } else { + if ($iptype == 6) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A DENYOUT $eth6devout -d $ip -j $dropout"); + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A DENYOUT $ethdevout -d $ip -j $dropout"); + } + } + } + push @newdata, $line; + } + } + seek ($TEMPBAN, 0, 0); + truncate ($TEMPBAN, 0); + foreach my $line (@newdata) {print $TEMPBAN "$line\n"} + close ($TEMPBAN); + } + + if (! -z "/var/lib/csf/csf.tempallow") { + sysopen (my $TEMPALLOW, "/var/lib/csf/csf.tempallow", O_RDWR | O_CREAT); + flock ($TEMPALLOW, LOCK_EX); + my @data = <$TEMPALLOW>; + chomp @data; + + my @newdata; + foreach my $line (@data) { + my ($time,$ip,$port,$inout,$timeout,$message) = split(/\|/,$line); + my $iptype = checkip(\$ip); + if ($iptype == 6 and !$config{IPV6}) {next} + if ((((time - $time) < $timeout) and $iptype) or ($message =~ /\(CF:([^\)]+)\)/)) { + if ($inout =~ /in/) { + if ($port) { + foreach my $dport (split(/\,/,$port)) { + my ($tport,$proto) = split(/\;/,$dport); + $dport = $tport; + if ($proto eq "") {$proto = "tcp"} + if ($iptype == 6) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I ALLOWIN $eth6devin -p $proto --dport $dport -s $ip -j $accept"); + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I ALLOWIN $ethdevin -p $proto --dport $dport -s $ip -j $accept"); + } + } + } else { + if ($iptype == 6) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I ALLOWIN $eth6devin -s $ip -j $accept"); + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I ALLOWIN $ethdevin -s $ip -j $accept"); + } + } + } + if ($inout =~ /out/) { + if ($port) { + foreach my $dport (split(/\,/,$port)) { + my ($tport,$proto) = split(/\;/,$dport); + $dport = $tport; + if ($proto eq "") {$proto = "tcp"} + if ($iptype == 6) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I ALLOWOUT $eth6devout -p $proto --dport $dport -d $ip -j $accept"); + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I ALLOWOUT $ethdevout -p $proto --dport $dport -d $ip -j $accept"); + } + } + } else { + if ($iptype == 6) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I ALLOWOUT $eth6devout -d $ip -j $accept"); + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I ALLOWOUT $ethdevout -d $ip -j $accept"); + } + } + } + push @newdata, $line; + } + } + seek ($TEMPALLOW, 0, 0); + truncate ($TEMPALLOW, 0); + foreach my $line (@newdata) {print $TEMPALLOW "$line\n"} + close ($TEMPALLOW); + } + + if ($config{GLOBAL_ALLOW}) { + if ($config{LF_IPSET}) { + &ipsetcreate("chain_GALLOW"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A GALLOWIN -m set --match-set chain_GALLOW src -j $accept"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A GALLOWOUT -m set --match-set chain_GALLOW dst -j $accept"); + if ($config{IPV6}) { + &ipsetcreate("chain_6_GALLOW"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A GALLOWIN -m set --match-set chain_6_GALLOW src -j $accept"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A GALLOWOUT -m set --match-set chain_6_GALLOW dst -j $accept"); + } + } + if (-e "/var/lib/csf/csf.gallow") { + if ($config{FASTSTART}) {$faststart = 1} + foreach my $line (slurp("/var/lib/csf/csf.gallow")) { + $line =~ s/$cleanreg//g; + if ($line =~ /^(\s|\#|$)/) {next} + my ($ip,$comment) = split (/\s/,$line,2); + &linefilter($ip, "allow","GALLOW"); + } + if ($config{FASTSTART}) {&faststart("Global Allow")} + } + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I LOCALINPUT $ethdevin -j GALLOWIN"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I LOCALOUTPUT $ethdevout -j GALLOWOUT"); + if ($config{IPV6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I LOCALINPUT $eth6devin -j GALLOWIN"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I LOCALOUTPUT $eth6devout -j GALLOWOUT"); + } + } + + $config{CC_ALLOW} =~ s/\s//g; + if ($config{CC_ALLOW}) { + foreach my $cc (split(/\,/,$config{CC_ALLOW})) { + $cc = lc $cc; + if ($config{LF_IPSET}) { + &ipsetcreate("cc_$cc"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A CC_ALLOW -m set --match-set cc_$cc src -j $accept"); + if ($config{CC6_LOOKUPS} and $config{IPV6}) { + &ipsetcreate("cc_6_$cc"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A CC_ALLOW -m set --match-set cc_6_$cc src -j $accept"); + } + } + if (-e "/var/lib/csf/zone/$cc.zone") { + if ($config{LF_IPSET}) { + undef @ipset; + foreach my $line (slurp("/var/lib/csf/zone/$cc.zone")) { + $line =~ s/$cleanreg//g; + if ($line =~ /^(\s|\#|$)/) {next} + my ($ip,undef) = split (/\s/,$line,2); + if ($config{CC_DROP_CIDR} > 0 and $config{CC_DROP_CIDR} < 33) { + my ($drop_ip,$drop_cidr) = split(/\//,$ip); + if ($drop_cidr eq "") {$drop_cidr = "32"} + if ($drop_cidr > $config{CC_DROP_CIDR}) {next} + } + if (cccheckip(\$ip)) {push @ipset,"add -exist cc_$cc $ip"} + } + &ipsetrestore("cc_$cc"); + } else { + if ($config{FASTSTART}) {$faststart = 1} + foreach my $line (slurp("/var/lib/csf/zone/$cc.zone")) { + $line =~ s/$cleanreg//g; + if ($line =~ /^(\s|\#|$)/) {next} + my ($ip,undef) = split (/\s/,$line,2); + if (cccheckip(\$ip)) { + if ($config{CC_DROP_CIDR} > 0 and $config{CC_DROP_CIDR} < 33) { + my ($drop_ip,$drop_cidr) = split(/\//,$ip); + if ($drop_cidr eq "") {$drop_cidr = "32"} + if ($drop_cidr > $config{CC_DROP_CIDR}) {next} + } + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A CC_ALLOW -s $ip -j $accept"); + } + } + if ($config{FASTSTART}) {&faststart("CC_ALLOW [$cc]")} + } + } + if ($config{CC6_LOOKUPS} and -e "/var/lib/csf/zone/$cc.zone6") { + if ($config{LF_IPSET}) { + undef @ipset; + foreach my $line (slurp("/var/lib/csf/zone/$cc.zone6")) { + $line =~ s/$cleanreg//g; + if ($line =~ /^(\s|\#|$)/) {next} + my ($ip,undef) = split (/\s/,$line,2); + if (cccheckip(\$ip)) {push @ipset,"add -exist cc_6_$cc $ip"} + } + &ipsetrestore("cc_6_$cc"); + } else { + if ($config{FASTSTART}) {$faststart = 1} + foreach my $line (slurp("/var/lib/csf/zone/$cc.zone6")) { + $line =~ s/$cleanreg//g; + if ($line =~ /^(\s|\#|$)/) {next} + my ($ip,undef) = split (/\s/,$line,2); + if (cccheckip(\$ip)) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A CC_ALLOW -s $ip -j $accept"); + } + } + if ($config{FASTSTART}) {&faststart("CC_ALLOW [$cc]")} + } + } + } + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I LOCALINPUT $ethdevin -j CC_ALLOW"); + if ($config{IPV6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I LOCALINPUT $ethdevin -j CC_ALLOW"); + } + } + + if ($config{DYNDNS}) { + if ($config{LF_IPSET}) { + &ipsetcreate("chain_ALLOWDYN"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A ALLOWDYNIN -m set --match-set chain_ALLOWDYN src -j $accept"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A ALLOWDYNOUT -m set --match-set chain_ALLOWDYN dst -j $accept"); + if ($config{IPV6}) { + &ipsetcreate("chain_6_ALLOWDYN"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A ALLOWDYNIN -m set --match-set chain_6_ALLOWDYN src -j $accept"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A ALLOWDYNOUT -m set --match-set chain_6_ALLOWDYN dst -j $accept"); + } + } + if (-e "/var/lib/csf/csf.tempdyn") { + foreach my $line (slurp("/var/lib/csf/csf.tempdyn")) { + $line =~ s/$cleanreg//g; + if ($line =~ /^(\s|\#|$)/) {next} + my ($ip,$comment) = split (/\s/,$line,2); + &linefilter($ip, "allow","ALLOWDYN"); + } + } + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I LOCALINPUT $ethdevin -j ALLOWDYNIN"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I LOCALOUTPUT $ethdevout -j ALLOWDYNOUT"); + if ($config{IPV6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I LOCALINPUT $ethdevin -j ALLOWDYNIN"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I LOCALOUTPUT $ethdevout -j ALLOWDYNOUT"); + } + } + if ($config{GLOBAL_DYNDNS}) { + if ($config{LF_IPSET}) { + &ipsetcreate("chain_GDYN"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A GDYNIN -m set --match-set chain_GDYN src -j $accept"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A GDYNOUT -m set --match-set chain_GDYN dst -j $accept"); + if ($config{IPV6}) { + &ipsetcreate("chain_6_GDYN"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A GDYNIN -m set --match-set chain_6_GDYN src -j $accept"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A GDYNOUT -m set --match-set chain_6_GDYN dst -j $accept"); + } + } + if (-e "/var/lib/csf/csf.tempgdyn") { + if ($config{FASTSTART}) {$faststart = 1} + foreach my $line (slurp("/var/lib/csf/csf.tempgdyn")) { + $line =~ s/$cleanreg//g; + if ($line =~ /^(\s|\#|$)/) {next} + my ($ip,$comment) = split (/\s/,$line,2); + &linefilter($ip, "allow","GDYN"); + } + if ($config{FASTSTART}) {&faststart("Global Dynamic DNS")} + } + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I LOCALINPUT $ethdevin -j GDYNIN"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I LOCALOUTPUT $ethdevout -j GDYNOUT"); + if ($config{IPV6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I LOCALINPUT $ethdevin -j GDYNIN"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I LOCALOUTPUT $ethdevout -j GDYNOUT"); + } + } + + my @allow = slurp("/etc/csf/csf.allow"); + foreach my $line (@allow) { + if ($line =~ /^Include\s*(.*)$/) { + my @incfile = slurp($1); + push @allow,@incfile; + } + } + if ($config{FASTSTART}) {$faststart = 1} + if ($config{LF_IPSET}) { + &ipsetcreate("chain_ALLOW"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A ALLOWIN -m set --match-set chain_ALLOW src -j $accept"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A ALLOWOUT -m set --match-set chain_ALLOW dst -j $accept"); + if ($config{IPV6}) { + &ipsetcreate("chain_6_ALLOW"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A ALLOWIN -m set --match-set chain_6_ALLOW src -j $accept"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A ALLOWOUT -m set --match-set chain_6_ALLOW dst -j $accept"); + } + } + foreach my $line (@allow) { + $line =~ s/$cleanreg//g; + if ($line eq "") {next} + if ($line =~ /^\s*\#|Include/) {next} + my ($ip,$comment) = split (/\s/,$line,2); + &linefilter($ip, "allow"); + } + if ($config{FASTSTART}) {&faststart("csf.allow")} + + foreach my $name (keys %blocklists) { + my $drop = $config{DROP}; + if ($config{DROP_IP_LOGGING}) {$drop = "BLOCKDROP"} + if ($config{LF_IPSET}) { + &ipsetcreate("bl_$name"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A $name -m set --match-set bl_$name src -j $drop"); + if ($config{IPV6}) { + &ipsetcreate("bl_6_$name"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A $name -m set --match-set bl_6_$name src -j $drop"); + } + } + if (-e "/var/lib/csf/csf.block.$name") { + if ($config{LF_IPSET}) { + undef @ipset; + my @ipset6; + foreach my $line (slurp("/var/lib/csf/csf.block.$name")) { + $line =~ s/$cleanreg//g; + if ($line =~ /^(\s|\#|$)/) {next} + my ($ip,$comment) = split (/\s/,$line,2); + my $iptype = checkip(\$ip); + if ($iptype == 4) { + push @ipset,"add -exist bl_$name $ip"; + } + elsif ($iptype == 6 and $config{IPV6}) { + push @ipset6,"add -exist bl_6_$name $ip"; + } + } + &ipsetrestore("bl_$name"); + if ($config{IPV6}) { + @ipset = @ipset6; + &ipsetrestore("bl_6_$name"); + } + } else { + if ($config{FASTSTART}) {$faststart = 1} + foreach my $line (slurp("/var/lib/csf/csf.block.$name")) { + $line =~ s/$cleanreg//g; + if ($line =~ /^(\s|\#|$)/) {next} + my ($ip,$comment) = split (/\s/,$line,2); + my $iptype = checkip(\$ip); + if ($iptype == 4) { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A $name -s $ip -j $drop"); + } + elsif ($iptype == 6 and $config{IPV6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A $name -s $ip -j $drop"); + } + } + if ($config{FASTSTART}) {&faststart("Blocklist $name")} + } + } + $config{LF_BOGON_SKIP} =~ s/\s//g; + if ($name eq "BOGON" and $config{LF_BOGON_SKIP} ne "") { + foreach my $device (split(/\,/,$config{LF_BOGON_SKIP})) { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I BOGON -i $device -j RETURN"); + } + } + if ($cxsreputation and $name =~ /^CXS_/ and $name ne "CXS_ALL" and $cxsports{$name} ne "") { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A LOCALINPUT -p tcp -m multiport --dport $cxsports{$name} $ethdevin -j $name"); + if ($config{IPV6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A LOCALINPUT -p tcp -m multiport --dport $cxsports{$name} $ethdevin -j $name"); + } + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A LOCALINPUT $ethdevin -j $name"); + if ($config{IPV6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A LOCALINPUT $ethdevin -j $name"); + } + } + } + + $config{CC_ALLOW_SMTPAUTH} =~ s/\s//g; + if ($config{SMTPAUTH_RESTRICT}) { + if ($verbose) {print "csf: Generating /etc/exim.smtpauth\n"} + sysopen (my $SMTPAUTH, "/etc/exim.smtpauth", O_WRONLY | O_CREAT); + flock ($SMTPAUTH, LOCK_EX); + seek ($SMTPAUTH, 0, 0); + truncate ($SMTPAUTH, 0); + print $SMTPAUTH "# DO NOT EDIT THIS FILE\n#\n"; + print $SMTPAUTH "# Modify /etc/csf/csf.smtpauth and then restart csf and then lfd\n\n"; + print $SMTPAUTH "127.0.0.0/8\n"; + print $SMTPAUTH "\"::1\"\n"; + print $SMTPAUTH "\"::1/128\"\n"; + if (-e "/etc/csf/csf.smtpauth") { + my @entries = slurp("/etc/csf/csf.smtpauth"); + foreach my $line (@entries) { + if ($line =~ /^Include\s*(.*)$/) { + my @incfile = slurp($1); + push @entries,@incfile; + } + } + foreach my $line (@entries) { + $line =~ s/$cleanreg//g; + if ($line eq "") {next} + if ($line =~ /^\s*\#|Include/) {next} + my ($ip,undef) = split (/\s/,$line,2); + my $status = checkip(\$ip); + if ($status == 4) {print $SMTPAUTH "$ip\n"} + elsif ($status == 6) {print $SMTPAUTH "\"$ip\"\n"} + } + } + foreach my $cc (split(/\,/,$config{CC_ALLOW_SMTPAUTH})) { + $cc = lc $cc; + if (-e "/var/lib/csf/zone/$cc.zone") { + print $SMTPAUTH "\n# IPv4 addresses for [".uc($cc)."]:\n"; + foreach my $line (slurp("/var/lib/csf/zone/$cc.zone")) { + $line =~ s/$cleanreg//g; + if ($line =~ /^(\s|\#|$)/) {next} + my ($ip,undef) = split (/\s/,$line,2); + if ($config{CC_DROP_CIDR} > 0 and $config{CC_DROP_CIDR} < 33) { + my ($drop_ip,$drop_cidr) = split(/\//,$ip); + if ($drop_cidr eq "") {$drop_cidr = "32"} + if ($drop_cidr > $config{CC_DROP_CIDR}) {next} + } + my $status = cccheckip(\$ip); + if ($status == 4) {print $SMTPAUTH "$ip\n"} + elsif ($status == 6) {print $SMTPAUTH "\"$ip\"\n"} + } + } + if ($config{CC6_LOOKUPS} and -e "/var/lib/csf/zone/$cc.zone6") { + print $SMTPAUTH "\n# IPv6 addresses for [".uc($cc)."]:\n"; + foreach my $line (slurp("/var/lib/csf/zone/$cc.zone6")) { + $line =~ s/$cleanreg//g; + if ($line =~ /^(\s|\#|$)/) {next} + my ($ip,undef) = split (/\s/,$line,2); + my $status = cccheckip(\$ip); + if ($status == 4) {print $SMTPAUTH "$ip\n"} + elsif ($status == 6) {print $SMTPAUTH "\"$ip\"\n"} + } + } + } + close ($SMTPAUTH); + chmod (0644,"/etc/exim.smtpauth"); + } + + $config{CC_DENY} =~ s/\s//g; + if ($config{CC_DENY}) { + foreach my $cc (split(/\,/,$config{CC_DENY})) { + $cc = lc $cc; + my $drop = $config{DROP}; + if ($config{DROP_IP_LOGGING}) {$drop = "CCDROP"} + if ($config{LF_IPSET}) { + &ipsetcreate("cc_$cc"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I CC_DENY -m set --match-set cc_$cc src -j $drop"); + if ($config{CC6_LOOKUPS} and $config{IPV6}) { + &ipsetcreate("cc_6_$cc"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I CC_DENY -m set --match-set cc_6_$cc src -j $drop"); + } + } + if (-e "/var/lib/csf/zone/$cc.zone") { + if ($config{LF_IPSET}) { + undef @ipset; + foreach my $line (slurp("/var/lib/csf/zone/$cc.zone")) { + $line =~ s/$cleanreg//g; + if ($line =~ /^(\s|\#|$)/) {next} + my ($ip,undef) = split (/\s/,$line,2); + if ($config{CC_DROP_CIDR} > 0 and $config{CC_DROP_CIDR} < 33) { + my ($drop_ip,$drop_cidr) = split(/\//,$ip); + if ($drop_cidr eq "") {$drop_cidr = "32"} + if ($drop_cidr > $config{CC_DROP_CIDR}) {next} + } + if (cccheckip(\$ip)) {push @ipset,"add -exist cc_$cc $ip"} + } + &ipsetrestore("cc_$cc"); + } else { + if ($config{FASTSTART}) {$faststart = 1} + foreach my $line (slurp("/var/lib/csf/zone/$cc.zone")) { + $line =~ s/$cleanreg//g; + if ($line =~ /^(\s|\#|$)/) {next} + my ($ip,undef) = split (/\s/,$line,2); + if ($config{CC_DROP_CIDR} > 0 and $config{CC_DROP_CIDR} < 33) { + my ($drop_ip,$drop_cidr) = split(/\//,$ip); + if ($drop_cidr eq "") {$drop_cidr = "32"} + if ($drop_cidr > $config{CC_DROP_CIDR}) {next} + } + if (cccheckip(\$ip)) { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I CC_DENY -s $ip -j $drop"); + } + } + if ($config{FASTSTART}) {&faststart("CC_DENY [$cc]")} + } + } + if ($config{CC6_LOOKUPS} and -e "/var/lib/csf/zone/$cc.zone6") { + if ($config{LF_IPSET}) { + undef @ipset; + foreach my $line (slurp("/var/lib/csf/zone/$cc.zone6")) { + $line =~ s/$cleanreg//g; + if ($line =~ /^(\s|\#|$)/) {next} + my ($ip,undef) = split (/\s/,$line,2); + if (cccheckip(\$ip)) {push @ipset,"add -exist cc_6_$cc $ip"} + } + &ipsetrestore("cc_6_$cc"); + } else { + if ($config{FASTSTART}) {$faststart = 1} + foreach my $line (slurp("/var/lib/csf/zone/$cc.zone6")) { + $line =~ s/$cleanreg//g; + if ($line =~ /^(\s|\#|$)/) {next} + my ($ip,undef) = split (/\s/,$line,2); + if (cccheckip(\$ip)) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I CC_DENY -s $ip -j $drop"); + } + } + if ($config{FASTSTART}) {&faststart("CC_DENY [$cc]")} + } + } + } + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A LOCALINPUT $ethdevin -j CC_DENY"); + if ($config{IPV6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A LOCALINPUT $ethdevin -j CC_DENY"); + } + } + + + $config{CC_ALLOW_FILTER} =~ s/\s//g; + if ($config{CC_ALLOW_FILTER}) { + my $cnt = 0; + my $cnt6 = 0; + foreach my $cc (split(/\,/,$config{CC_ALLOW_FILTER})) { + $cc = lc $cc; + if ($config{LF_IPSET}) { + &ipsetcreate("cc_$cc"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A CC_ALLOWF -m set --match-set cc_$cc src -j RETURN"); + if ($config{CC6_LOOKUPS} and $config{IPV6}) { + &ipsetcreate("cc_6_$cc"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A CC_ALLOWF -m set --match-set cc_6_$cc src -j RETURN"); + } + } + if (-e "/var/lib/csf/zone/$cc.zone") { + if ($config{LF_IPSET}) { + undef @ipset; + foreach my $line (slurp("/var/lib/csf/zone/$cc.zone")) { + $line =~ s/$cleanreg//g; + if ($line =~ /^(\s|\#|$)/) {next} + my ($ip,undef) = split (/\s/,$line,2); + if ($config{CC_DROP_CIDR} > 0 and $config{CC_DROP_CIDR} < 33) { + my ($drop_ip,$drop_cidr) = split(/\//,$ip); + if ($drop_cidr eq "") {$drop_cidr = "32"} + if ($drop_cidr > $config{CC_DROP_CIDR}) {next} + } + if (cccheckip(\$ip)) { + push @ipset,"add -exist cc_$cc $ip"; + $cnt++; + } + } + &ipsetrestore("cc_$cc"); + } else { + if ($config{FASTSTART}) {$faststart = 1} + foreach my $line (slurp("/var/lib/csf/zone/$cc.zone")) { + $line =~ s/$cleanreg//g; + if ($line =~ /^(\s|\#|$)/) {next} + my ($ip,undef) = split (/\s/,$line,2); + if (cccheckip(\$ip)) { + if ($config{CC_DROP_CIDR} > 0 and $config{CC_DROP_CIDR} < 33) { + my ($drop_ip,$drop_cidr) = split(/\//,$ip); + if ($drop_cidr eq "") {$drop_cidr = "32"} + if ($drop_cidr > $config{CC_DROP_CIDR}) {next} + } + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A CC_ALLOWF -s $ip -j RETURN"); + $cnt++; + } + } + if ($config{FASTSTART}) {&faststart("CC_ALLOW_FILTER [$cc]")} + } + } + if ($config{CC6_LOOKUPS} and -e "/var/lib/csf/zone/$cc.zone6") { + if ($config{LF_IPSET}) { + undef @ipset; + foreach my $line (slurp("/var/lib/csf/zone/$cc.zone6")) { + $line =~ s/$cleanreg//g; + if ($line =~ /^(\s|\#|$)/) {next} + my ($ip,undef) = split (/\s/,$line,2); + if (cccheckip(\$ip)) { + push @ipset,"add -exist cc_6_$cc $ip"; + $cnt6++; + } + } + &ipsetrestore("cc_6_$cc"); + } else { + if ($config{FASTSTART}) {$faststart = 1} + foreach my $line (slurp("/var/lib/csf/zone/$cc.zone6")) { + $line =~ s/$cleanreg//g; + if ($line =~ /^(\s|\#|$)/) {next} + my ($ip,undef) = split (/\s/,$line,2); + if (cccheckip(\$ip)) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A CC_ALLOWF -s $ip -j RETURN"); + $cnt6++; + } + } + if ($config{FASTSTART}) {&faststart("CC_ALLOW_FILTER [$cc]")} + } + } + } + my $drop = $config{DROP}; + if ($config{DROP_IP_LOGGING}) {$drop = "CCDROP"} + if ($cnt > 0) {&syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A CC_ALLOWF -j $drop")}; + if ($config{LF_SPI}) { + if ($config{USE_FTPHELPER}) { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I CC_ALLOWF $ethdevin $statemodule RELATED -m helper --helper ftp -j $accept"); + + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I CC_ALLOWF $ethdevin $statemodule ESTABLISHED -j $accept"); + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I CC_ALLOWF $ethdevin $statemodule ESTABLISHED,RELATED -j $accept"); + } + } + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A LOCALINPUT $ethdevin -j CC_ALLOWF"); + if ($config{IPV6}) { + if ($cnt6 > 0) {&syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A CC_ALLOWF -j $drop")}; + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A LOCALINPUT $ethdevin -j CC_ALLOWF"); + if ($config{IPV6_SPI}) { + if ($config{USE_FTPHELPER}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I CC_ALLOWF $ethdevin $statemodule RELATED -m helper --helper ftp -j $accept"); + + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I CC_ALLOWF $ethdevin $statemodule ESTABLISHED -j $accept"); + } else { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I CC_ALLOWF $ethdevin $statemodule ESTABLISHED,RELATED -j $accept"); + } + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I CC_ALLOWF $eth6devin -p icmpv6 -j $accept"); + } + } + } + + $config{CC_ALLOW_PORTS} =~ s/\s//g; + if ($config{CC_ALLOW_PORTS}) { + $config{CC_ALLOW_PORTS_TCP} =~ s/\s//g; + $config{CC_ALLOW_PORTS_UDP} =~ s/\s//g; + if ($config{CC_ALLOW_PORTS_TCP} ne "") { + foreach my $port (split(/\,/,$config{CC_ALLOW_PORTS_TCP})) { + if ($port eq "") {next} + if ($port !~ /^[\d:]*$/) {&error(__LINE__,"Invalid CC_ALLOW_PORTS_TCP port [$port]")} + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A CC_ALLOWPORTS $ethdevin -p tcp $statemodulenew --dport $port -j $accept"); + if ($config{CC6_LOOKUPS} and $config{IPV6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A CC_ALLOWPORTS $ethdevin -p tcp $statemodulenew --dport $port -j $accept"); + } + } + } + if ($config{CC_ALLOW_PORTS_UDP} ne "") { + foreach my $port (split(/\,/,$config{CC_ALLOW_PORTS_UDP})) { + if ($port eq "") {next} + if ($port !~ /^[\d:]*$/) {&error(__LINE__,"Invalid CC_ALLOW_PORTS_UDP port [$port]")} + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A CC_ALLOWPORTS $ethdevin -p udp $statemodulenew --dport $port -j $accept"); + if ($config{CC6_LOOKUPS} and $config{IPV6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A CC_ALLOWPORTS $ethdevin -p udp $statemodulenew --dport $port -j $accept"); + } + } + } + my $cnt = 0; + foreach my $cc (split(/\,/,$config{CC_ALLOW_PORTS})) { + $cc = lc $cc; + if ($config{LF_IPSET}) { + &ipsetcreate("cc_$cc"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A CC_ALLOWP -m set --match-set cc_$cc src -j CC_ALLOWPORTS"); + if ($config{CC6_LOOKUPS} and $config{IPV6}) { + &ipsetcreate("cc_6_$cc"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A CC_ALLOWP -m set --match-set cc_6_$cc src -j CC_ALLOWPORTS"); + } + } + if (-e "/var/lib/csf/zone/$cc.zone") { + if ($config{LF_IPSET}) { + undef @ipset; + foreach my $line (slurp("/var/lib/csf/zone/$cc.zone")) { + $line =~ s/$cleanreg//g; + if ($line =~ /^(\s|\#|$)/) {next} + my ($ip,undef) = split (/\s/,$line,2); + if ($config{CC_DROP_CIDR} > 0 and $config{CC_DROP_CIDR} < 33) { + my ($drop_ip,$drop_cidr) = split(/\//,$ip); + if ($drop_cidr eq "") {$drop_cidr = "32"} + if ($drop_cidr > $config{CC_DROP_CIDR}) {next} + } + if (cccheckip(\$ip)) {push @ipset,"add -exist cc_$cc $ip"} + } + &ipsetrestore("cc_$cc"); + } else { + if ($config{FASTSTART}) {$faststart = 1} + foreach my $line (slurp("/var/lib/csf/zone/$cc.zone")) { + $line =~ s/$cleanreg//g; + if ($line =~ /^(\s|\#|$)/) {next} + my ($ip,undef) = split (/\s/,$line,2); + if (cccheckip(\$ip)) { + if ($config{CC_DROP_CIDR} > 0 and $config{CC_DROP_CIDR} < 33) { + my ($drop_ip,$drop_cidr) = split(/\//,$ip); + if ($drop_cidr eq "") {$drop_cidr = "32"} + if ($drop_cidr > $config{CC_DROP_CIDR}) {next} + } + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A CC_ALLOWP -s $ip -j CC_ALLOWPORTS"); + $cnt++; + } + } + if ($config{FASTSTART}) {&faststart("CC_ALLOW_PORTS [$cc]")} + } + } + if ($config{CC6_LOOKUPS} and -e "/var/lib/csf/zone/$cc.zone6") { + if ($config{LF_IPSET}) { + undef @ipset; + foreach my $line (slurp("/var/lib/csf/zone/$cc.zone6")) { + $line =~ s/$cleanreg//g; + if ($line =~ /^(\s|\#|$)/) {next} + my ($ip,undef) = split (/\s/,$line,2); + if (cccheckip(\$ip)) {push @ipset,"add -exist cc_6_$cc $ip"} + } + &ipsetrestore("cc_6_$cc"); + } else { + if ($config{FASTSTART}) {$faststart = 1} + foreach my $line (slurp("/var/lib/csf/zone/$cc.zone6")) { + $line =~ s/$cleanreg//g; + if ($line =~ /^(\s|\#|$)/) {next} + my ($ip,undef) = split (/\s/,$line,2); + if (cccheckip(\$ip)) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A CC_ALLOWP -s $ip -j CC_ALLOWPORTS"); + $cnt++; + } + } + if ($config{FASTSTART}) {&faststart("CC_ALLOW_PORTS [$cc]")} + } + } + } + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A LOCALINPUT $ethdevin -j CC_ALLOWP"); + if ($config{IPV6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A LOCALINPUT $ethdevin -j CC_ALLOWP"); + } + } + + $config{CC_DENY_PORTS} =~ s/\s//g; + if ($config{CC_DENY_PORTS}) { + $config{CC_DENY_PORTS_TCP} =~ s/\s//g; + $config{CC_DENY_PORTS_UDP} =~ s/\s//g; + if ($config{CC_DENY_PORTS_TCP} ne "") { + foreach my $port (split(/\,/,$config{CC_DENY_PORTS_TCP})) { + if ($port eq "") {next} + if ($port !~ /^[\d:]*$/) {&error(__LINE__,"Invalid CC_DENY_PORTS_TCP port [$port]")} + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A CC_DENYPORTS $ethdevin -p tcp --dport $port -j $config{DROP}"); + if ($config{CC6_LOOKUPS} and $config{IPV6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A CC_DENYPORTS $ethdevin -p tcp --dport $port -j $config{DROP}"); + } + } + } + if ($config{CC_DENY_PORTS_UDP} ne "") { + foreach my $port (split(/\,/,$config{CC_DENY_PORTS_UDP})) { + if ($port eq "") {next} + if ($port !~ /^[\d:]*$/) {&error(__LINE__,"Invalid CC_DENY_PORTS_UDP port [$port]")} + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A CC_DENYPORTS $ethdevin -p udp --dport $port -j $config{DROP}"); + if ($config{CC6_LOOKUPS} and $config{IPV6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A CC_DENYPORTS $ethdevin -p udp --dport $port -j $config{DROP}"); + + } + } + } + my $cnt = 0; + foreach my $cc (split(/\,/,$config{CC_DENY_PORTS})) { + $cc = lc $cc; + if ($config{LF_IPSET}) { + &ipsetcreate("cc_$cc"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I CC_DENYP -m set --match-set cc_$cc src -j CC_DENYPORTS"); + if ($config{CC6_LOOKUPS} and $config{IPV6}) { + &ipsetcreate("cc_6_$cc"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I CC_DENYP -m set --match-set cc_6_$cc src -j CC_DENYPORTS"); + } + } + if (-e "/var/lib/csf/zone/$cc.zone") { + if ($config{LF_IPSET}) { + undef @ipset; + foreach my $line (slurp("/var/lib/csf/zone/$cc.zone")) { + $line =~ s/$cleanreg//g; + if ($line =~ /^(\s|\#|$)/) {next} + my ($ip,undef) = split (/\s/,$line,2); + if ($config{CC_DROP_CIDR} > 0 and $config{CC_DROP_CIDR} < 33) { + my ($drop_ip,$drop_cidr) = split(/\//,$ip); + if ($drop_cidr eq "") {$drop_cidr = "32"} + if ($drop_cidr > $config{CC_DROP_CIDR}) {next} + } + if (cccheckip(\$ip)) {push @ipset,"add -exist cc_$cc $ip"} + } + &ipsetrestore("cc_$cc"); + } else { + if ($config{FASTSTART}) {$faststart = 1} + foreach my $line (slurp("/var/lib/csf/zone/$cc.zone")) { + $line =~ s/$cleanreg//g; + if ($line =~ /^(\s|\#|$)/) {next} + my ($ip,undef) = split (/\s/,$line,2); + if (cccheckip(\$ip)) { + if ($config{CC_DROP_CIDR} > 0 and $config{CC_DROP_CIDR} < 33) { + my ($drop_ip,$drop_cidr) = split(/\//,$ip); + if ($drop_cidr eq "") {$drop_cidr = "32"} + if ($drop_cidr > $config{CC_DROP_CIDR}) {next} + } + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A CC_DENYP -s $ip -j CC_DENYPORTS"); + $cnt++; + } + } + if ($config{FASTSTART}) {&faststart("CC_DENY_PORTS [$cc]")} + } + } + if ($config{CC6_LOOKUPS} and -e "/var/lib/csf/zone/$cc.zone6") { + if ($config{LF_IPSET}) { + undef @ipset; + foreach my $line (slurp("/var/lib/csf/zone/$cc.zone6")) { + $line =~ s/$cleanreg//g; + if ($line =~ /^(\s|\#|$)/) {next} + my ($ip,undef) = split (/\s/,$line,2); + if (cccheckip(\$ip)) {push @ipset,"add -exist cc_6_$cc $ip"} + } + &ipsetrestore("cc_6_$cc"); + } else { + if ($config{FASTSTART}) {$faststart = 1} + foreach my $line (slurp("/var/lib/csf/zone/$cc.zone6")) { + $line =~ s/$cleanreg//g; + if ($line =~ /^(\s|\#|$)/) {next} + my ($ip,undef) = split (/\s/,$line,2); + if (cccheckip(\$ip)) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A CC_DENYP -s $ip -j CC_DENYPORTS"); + $cnt++; + } + } + if ($config{FASTSTART}) {&faststart("CC_DENY_PORTS [$cc]")} + } + } + } + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A LOCALINPUT $ethdevin -j CC_DENYP"); + if ($config{IPV6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A LOCALINPUT $ethdevin -j CC_DENYP"); + } + } + + if ($config{CLUSTER_SENDTO}) { + foreach my $ip (split(/\,/,$config{CLUSTER_SENDTO})) { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I LOCALOUTPUT $ethdevout -p tcp -d $ip --dport $config{CLUSTER_PORT} -j $accept"); + } + } + if ($config{CLUSTER_RECVFROM}) { + foreach my $ip (split(/\,/,$config{CLUSTER_RECVFROM})) { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I LOCALINPUT $ethdevin -p tcp -s $ip --dport $config{CLUSTER_PORT} -j $accept"); + } + } + + if ($config{SYNFLOOD}) { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A SYNFLOOD -m limit --limit $config{SYNFLOOD_RATE} --limit-burst $config{SYNFLOOD_BURST} -j RETURN"); + if ($config{DROP_LOGGING}) {&syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A SYNFLOOD -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *SYNFLOOD Blocked* '")} + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A SYNFLOOD -j DROP"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I INPUT $ethdevin -p tcp --syn -j SYNFLOOD"); + if ($config{IPV6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A SYNFLOOD -m limit --limit $config{SYNFLOOD_RATE} --limit-burst $config{SYNFLOOD_BURST} -j RETURN"); + if ($config{DROP_LOGGING}) {&syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A SYNFLOOD -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *SYNFLOOD Blocked* '")} + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A SYNFLOOD -j DROP"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I INPUT $ethdevin -p tcp --syn -j SYNFLOOD"); + } + } + + $config{PORTFLOOD} =~ s/\s//g; + if ($config{PORTFLOOD}) { + my $maxrecent = 20; + if (-e "/sys/module/ipt_recent/parameters/ip_pkt_list_tot") { + my @new = slurp("/sys/module/ipt_recent/parameters/ip_pkt_list_tot"); + if ($new[0] > 1) {$maxrecent = $new[0]} + } + if (-e "/sys/module/xt_recent/parameters/ip_pkt_list_tot") { + my @new = slurp("/sys/module/xt_recent/parameters/ip_pkt_list_tot"); + if ($new[0] > 1) {$maxrecent = $new[0]} + } + foreach my $portflood (split(/\,/,$config{PORTFLOOD})) { + my ($port,$proto,$count,$seconds) = split(/\;/,$portflood); + if ((($port < 0) or ($port > 65535)) or ($proto !~ /icmp|tcp|udp/) or ($seconds !~ /\d+/)) {&error(__LINE__,"csf: Incorrect PORTFLOOD setting: [$portflood]")} + if (($count < 1) or ($count > $maxrecent)) { + print "WARNING: count in PORTFLOOD setting must be between 1 and $maxrecent: [$portflood]\n"; + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p $proto --dport $port $statemodulenew -m recent --set --name $port"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p $proto --dport $port $statemodulenew -m recent --update --seconds $seconds --hitcount $count --name $port -j PORTFLOOD"); + if ($config{PORTFLOOD6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p $proto --dport $port $statemodulenew -m recent --set --name $port"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p $proto --dport $port $statemodulenew -m recent --update --seconds $seconds --hitcount $count --name $port -j PORTFLOOD"); + } + } + } + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A PORTFLOOD -j $config{DROP}"); + if ($config{PORTFLOOD6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A PORTFLOOD -j $config{DROP}"); + } + } + + $config{CONNLIMIT} =~ s/\s//g; + if ($config{CONNLIMIT}) { + foreach my $connlimit (split(/\,/,$config{CONNLIMIT})) { + my ($port,$limit) = split(/\;/,$connlimit); + if (($port < 0) or ($port > 65535) or ($limit < 1) or ($limit !~ /\d+/)) {&error(__LINE__,"csf: Incorrect CONNLIMIT setting: [$connlimit]")} + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p tcp --syn --dport $port -m connlimit --connlimit-above $limit -j CONNLIMIT"); + if ($config{CONNLIMIT6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p tcp --syn --dport $port -m connlimit --connlimit-above $limit -j CONNLIMIT"); + } + } + if ($config{CONNLIMIT_LOGGING}) {&syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A CONNLIMIT -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *ConnLimit* '");} + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A CONNLIMIT -p tcp -j REJECT --reject-with tcp-reset"); + if ($config{CONNLIMIT6}) { + if ($config{CONNLIMIT_LOGGING}) {&syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A CONNLIMIT -m limit --limit 30/m --limit-burst 5 -j $logintarget 'Firewall: *ConnLimit* '");} + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A CONNLIMIT -p tcp -j REJECT --reject-with tcp-reset"); + } + } + + if ($config{UDPFLOOD}) { + foreach my $item (split(/\,/,$config{UDPFLOOD_ALLOWUSER})) { + $item =~ s/\s//g; + my $uid = (getpwnam($item))[2]; + if ($uid) { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A UDPFLOOD -p udp -m owner --uid-owner $uid -j RETURN",1); + if ($config{IPV6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A UDPFLOOD -p udp -m owner --uid-owner $uid -j RETURN",1); + } + } + } + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A UDPFLOOD -p udp -m owner --uid-owner 0 -j RETURN",1); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A UDPFLOOD $ethdevout -p udp -m limit --limit $config{UDPFLOOD_LIMIT} --limit-burst $config{UDPFLOOD_BURST} -j RETURN"); + if ($config{UDPFLOOD_LOGGING}) {&syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A UDPFLOOD -m limit --limit 30/m --limit-burst 5 -j $logouttarget 'Firewall: *UDPFLOOD* '");} + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A UDPFLOOD $ethdevout -p udp -j $config{DROP_OUT}"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A LOCALOUTPUT $ethdevout -p udp -j UDPFLOOD"); + if ($config{IPV6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A UDPFLOOD -p udp -m owner --uid-owner 0 -j RETURN",1); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A UDPFLOOD $ethdevout -p udp -m limit --limit $config{UDPFLOOD_LIMIT} --limit-burst $config{UDPFLOOD_BURST} -j RETURN"); + if ($config{UDPFLOOD_LOGGING}) {&syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A UDPFLOOD -m limit --limit 30/m --limit-burst 5 -j $logouttarget 'Firewall: *UDPFLOOD* '");} + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A UDPFLOOD $ethdevout -p udp -j $config{DROP_OUT}"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A LOCALOUTPUT $ethdevout -p udp -j UDPFLOOD"); + } + } + my $icmp_in_rate = ""; + my $icmp_out_rate = ""; + if ($config{ICMP_IN_RATE}) {$icmp_in_rate = "-m limit --limit $config{ICMP_IN_RATE}"} + if ($config{ICMP_OUT_RATE}) {$icmp_out_rate = "-m limit --limit $config{ICMP_OUT_RATE}"} + + if ($config{ICMP_IN}) { + if ($config{ICMP_IN_RATE}) { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p icmp --icmp-type echo-request $icmp_in_rate -j $accept"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p icmp --icmp-type echo-request -j $dropin"); + } + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p icmp --icmp-type echo-request -j $dropin"); + } + if ($config{ICMP_TIMESTAMPDROP}) { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p icmp --icmp-type timestamp-request -j $dropin"); + } + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p icmp -j $accept"); + + if ($config{ICMP_OUT}) { + if ($config{ICMP_OUT_RATE}) { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $ethdevout -p icmp --icmp-type echo-request $icmp_out_rate -j $accept"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $ethdevout -p icmp --icmp-type echo-request -j $dropout"); + } + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $ethdevout -p icmp --icmp-type echo-request -j $dropout"); + } + if ($config{ICMP_TIMESTAMPDROP}) { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $ethdevout -p icmp --icmp-type timestamp-reply -j $dropout"); + } + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $ethdevout -p icmp -j $accept"); + + if ($config{IPV6}) { + if ($config{IPV6_ICMP_STRICT}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INPUT $eth6devin -p icmpv6 --icmpv6-type destination-unreachable -j $accept"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INPUT $eth6devin -p icmpv6 --icmpv6-type packet-too-big -j $accept"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INPUT $eth6devin -p icmpv6 --icmpv6-type time-exceeded -j $accept"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INPUT $eth6devin -p icmpv6 --icmpv6-type parameter-problem -j $accept"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INPUT $eth6devin -p icmpv6 --icmpv6-type echo-request -j $accept"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INPUT $eth6devin -p icmpv6 --icmpv6-type echo-reply -j $accept"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INPUT $eth6devin -p icmpv6 --icmpv6-type router-advertisement -m hl --hl-eq 255 -j $accept"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INPUT $eth6devin -p icmpv6 --icmpv6-type neighbor-solicitation -m hl --hl-eq 255 -j $accept"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INPUT $eth6devin -p icmpv6 --icmpv6-type neighbor-advertisement -m hl --hl-eq 255 -j $accept"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INPUT $eth6devin -p icmpv6 --icmpv6-type redirect -m hl --hl-eq 255 -j $accept"); + } else { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INPUT $eth6devin -p icmpv6 -j $accept"); + } + + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $eth6devout -p icmpv6 -j $accept"); +# &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $eth6devout -p icmpv6 --icmpv6-type destination-unreachable -j $accept"); +# &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $eth6devout -p icmpv6 --icmpv6-type packet-too-big -j $accept"); +# &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $eth6devout -p icmpv6 --icmpv6-type time-exceeded -j $accept"); +# &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $eth6devout -p icmpv6 --icmpv6-type parameter-problem -j $accept"); +# &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $eth6devout -p icmpv6 --icmpv6-type echo-request -j $accept"); +# &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $eth6devout -p icmpv6 --icmpv6-type echo-reply -j $accept"); +# &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $eth6devout -p icmpv6 --icmpv6-type router-advertisement -m hl --hl-eq 255 -j $accept"); +# &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $eth6devout -p icmpv6 --icmpv6-type neighbor-solicitation -m hl --hl-eq 255 -j $accept"); +# &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $eth6devout -p icmpv6 --icmpv6-type neighbor-advertisement -m hl --hl-eq 255 -j $accept"); +# &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $eth6devout -p icmpv6 --icmpv6-type redirect -m hl --hl-eq 255 -j $accept"); + } + + if ($config{LF_SPI}) { + if ($config{USE_FTPHELPER}) { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -t raw -A PREROUTING -p tcp --dport $config{USE_FTPHELPER} -j CT --helper ftp"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -t raw -A OUTPUT -p tcp --dport $config{USE_FTPHELPER} -j CT --helper ftp"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin $statemodule RELATED -m helper --helper ftp -j $accept"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $ethdevout $statemodule RELATED -m helper --helper ftp -j $accept"); + + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin $statemodule ESTABLISHED -j $accept"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $ethdevout $statemodule ESTABLISHED -j $accept"); + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin $statemodule ESTABLISHED,RELATED -j $accept"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $ethdevout $statemodule ESTABLISHED,RELATED -j $accept"); + } + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p udp -m udp --dport 32768:61000 -j $accept"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p tcp -m tcp --dport 32768:61000 ! --syn -j $accept"); + } + if ($config{IPV6}) { + if ($config{IPV6_SPI}) { + if ($config{USE_FTPHELPER}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -t raw -A PREROUTING -p tcp --dport $config{USE_FTPHELPER} -j CT --helper ftp"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -t raw -A OUTPUT -p tcp --dport $config{USE_FTPHELPER} -j CT --helper ftp"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin $statemodule RELATED -m helper --helper ftp -j $accept"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $ethdevout $statemodule RELATED -m helper --helper ftp -j $accept"); + + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INPUT $eth6devin $statemodule ESTABLISHED -j $accept"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $eth6devout $statemodule ESTABLISHED -j $accept"); + } else { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INPUT $eth6devin $statemodule ESTABLISHED,RELATED -j $accept"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $eth6devout $statemodule ESTABLISHED,RELATED -j $accept"); + } + } else { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INPUT $eth6devin -p udp -m udp --dport 32768:61000 -j $accept"); + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INPUT $eth6devin -p tcp -m tcp --dport 32768:61000 ! --syn -j $accept"); + } + } + + $config{PORTKNOCKING} =~ s/\s//g; + if ($config{PORTKNOCKING}) { + foreach my $portknock (split(/\,/,$config{PORTKNOCKING})) { + my ($port,$proto,$timeout,$knocks) = split(/\;/,$portknock,4); + my @steps = split(/\;/,$knocks); + my $nsteps = @steps; + if ($nsteps < 3) { + print "csf: Error - not enough Port Knocks for port $port [$knocks]\n"; + next; + } + for (my $step = 1; $step < $nsteps+1; $step++) { + my $ar = $step - 1; + if ($step == 1) { + if ($config{PORTKNOCKING_LOG}) {&syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p $proto --dport $steps[$ar] $statemodulenew -m limit --limit 30/m --limit-burst 5 -j LOG --log-prefix 'Knock: *$port\_S$step* '")} + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p $proto --dport $steps[$ar] $statemodulenew -m recent --set --name PK\_$port\_S$step"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p $proto --dport $steps[$ar] $statemodulenew -j DROP"); + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -N PK\_$port\_S$step\_IN"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A PK\_$port\_S$step\_IN -m recent --name PK\_$port\_S".($step - 1)." --remove"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A PK\_$port\_S$step\_IN -m recent --name PK\_$port\_S$step --set"); + if ($config{PORTKNOCKING_LOG}) {&syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A PK\_$port\_S$step\_IN -m limit --limit 30/m --limit-burst 5 -j LOG --log-prefix 'Knock: *$port\_S$step* '")} + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A PK\_$port\_S$step\_IN -j DROP"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p $proto --dport $steps[$ar] $statemodulenew -m recent --rcheck --seconds $timeout --name PK\_$port\_S".($step - 1)." -j PK\_$port\_S$step\_IN"); + } + } + if ($config{PORTKNOCKING_LOG}) {&syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p $proto --dport $port $statemodulenew -m recent --rcheck --seconds $timeout --name PK\_$port\_S$nsteps -m limit --limit 30/m --limit-burst 5 -j LOG --log-prefix 'Knock: *$port\_IN* '")} + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p $proto --dport $port $statemodulenew -m recent --rcheck --seconds $timeout --name PK\_$port\_S$nsteps -j ACCEPT"); + } + } + + if ($config{FASTSTART}) {$faststart = 1} + $config{TCP_IN} =~ s/\s//g; + if ($config{TCP_IN} ne "") { + foreach my $port (split(/\,/,$config{TCP_IN})) { + if ($port eq "") {next} + if ($port !~ /^[\d:]*$/) {&error(__LINE__,"Invalid TCP_IN port [$port]")} + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p tcp $statemodulenew --dport $port -j $accept"); + } + } + if ($config{FASTSTART}) {&faststart("TCP_IN")} + + if ($config{FASTSTART}) {$faststart = 1} + $config{TCP6_IN} =~ s/\s//g; + if ($config{IPV6} and $config{TCP6_IN} ne "") { + foreach my $port (split(/\,/,$config{TCP6_IN})) { + if ($port eq "") {next} + if ($port !~ /^[\d:]*$/) {&error(__LINE__,"Invalid TCP6_IN port [$port]")} + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INPUT $eth6devin -p tcp $statemodule6new --dport $port -j $accept"); + } + } + if ($config{FASTSTART}) {&faststart("TCP6_IN")} + + if ($config{FASTSTART}) {$faststart = 1} + $config{TCP_OUT} =~ s/\s//g; + if ($config{TCP_OUT} ne "") { + foreach my $port (split(/\,/,$config{TCP_OUT})) { + if ($port eq "") {next} + if ($port !~ /^[\d:]*$/) {&error(__LINE__,"Invalid TCP_OUT port [$port]")} + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $ethdevout -p tcp $statemodulenew --dport $port -j $accept"); + } + } + if ($config{FASTSTART}) {&faststart("TCP_OUT")} + + if ($config{FASTSTART}) {$faststart = 1} + $config{TCP6_OUT} =~ s/\s//g; + if ($config{IPV6} and $config{TCP6_OUT} ne "") { + foreach my $port (split(/\,/,$config{TCP6_OUT})) { + if ($port eq "") {next} + if ($port !~ /^[\d:]*$/) {&error(__LINE__,"Invalid TCP6_OUT port [$port]")} + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $eth6devout -p tcp $statemodule6new --dport $port -j $accept"); + } + } + if ($config{FASTSTART}) {&faststart("TCP6_OUT")} + + if ($config{FASTSTART}) {$faststart = 1} + $config{UDP_IN} =~ s/\s//g; + if ($config{UDP_IN} ne "") { + foreach my $port (split(/\,/,$config{UDP_IN})) { + if ($port eq "") {next} + if ($port !~ /^[\d:]*$/) {&error(__LINE__,"Invalid UDP_IN port [$port]")} + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p udp $statemodulenew --dport $port -j $accept"); + } + } + if ($config{FASTSTART}) {&faststart("UDP_IN")} + + if ($config{FASTSTART}) {$faststart = 1} + $config{UDP6_IN} =~ s/\s//g; + if ($config{IPV6} and $config{UDP6_IN} ne "") { + foreach my $port (split(/\,/,$config{UDP6_IN})) { + if ($port eq "") {next} + if ($port !~ /^[\d:]*$/) {&error(__LINE__,"Invalid UDP6_IN port [$port]")} + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INPUT $eth6devin -p udp $statemodule6new --dport $port -j $accept"); + } + } + if ($config{FASTSTART}) {&faststart("UDP6_IN")} + + if ($config{FASTSTART}) {$faststart = 1} + $config{UDP_OUT} =~ s/\s//g; + if ($config{UDP_OUT} ne "") { + foreach my $port (split(/\,/,$config{UDP_OUT})) { + if ($port eq "") {next} + if ($port !~ /^[\d:]*$/) {&error(__LINE__,"Invalid UDP_OUT port [$port]")} + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $ethdevout -p udp $statemodulenew --dport $port -j $accept"); + } + } + if ($config{FASTSTART}) {&faststart("UDP_OUT")} + + if ($config{FASTSTART}) {$faststart = 1} + $config{UDP6_OUT} =~ s/\s//g; + if ($config{IPV6} and $config{UDP6_OUT} ne "") { + foreach my $port (split(/\,/,$config{UDP6_OUT})) { + if ($port eq "") {next} + if ($port !~ /^[\d:]*$/) {&error(__LINE__,"Invalid UDP6_OUT port [$port]")} + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $eth6devout -p udp $statemodule6new --dport $port -j $accept"); + } + } + if ($config{FASTSTART}) {&faststart("UDP6_OUT")} + +# if ($config{IPV6}) { +# &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INPUT $eth6devin -p udp -m frag --fraglast -j $accept"); +# } + +# my $icmp_in_rate = ""; +# my $icmp_out_rate = ""; +# if ($config{ICMP_IN_RATE}) {$icmp_in_rate = "-m limit --limit $config{ICMP_IN_RATE}"} +# if ($config{ICMP_OUT_RATE}) {$icmp_out_rate = "-m limit --limit $config{ICMP_OUT_RATE}"} +# +# if ($config{ICMP_IN}) { +# &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p icmp --icmp-type echo-request $icmp_in_rate -j $accept"); +# &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $ethdevout -p icmp --icmp-type echo-reply $icmp_out_rate -j $accept"); +# } +# +# if ($config{ICMP_OUT}) { +# &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $ethdevout -p icmp --icmp-type echo-request $icmp_out_rate -j $accept"); +# &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p icmp --icmp-type echo-reply $icmp_in_rate -j $accept"); +# } +# +# &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p icmp --icmp-type time-exceeded -j $accept"); +# &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A INPUT $ethdevin -p icmp --icmp-type destination-unreachable -j $accept"); +# +# &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $ethdevout -p icmp --icmp-type time-exceeded -j $accept"); +# &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $ethdevout -p icmp --icmp-type destination-unreachable -j $accept"); +# +# if ($config{IPV6}) { +# if ($config{IPV6_ICMP_STRICT}) { +# &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INPUT $eth6devin -p icmpv6 --icmpv6-type destination-unreachable -j $accept"); +# &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INPUT $eth6devin -p icmpv6 --icmpv6-type packet-too-big -j $accept"); +# &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INPUT $eth6devin -p icmpv6 --icmpv6-type time-exceeded -j $accept"); +# &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INPUT $eth6devin -p icmpv6 --icmpv6-type parameter-problem -j $accept"); +# &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INPUT $eth6devin -p icmpv6 --icmpv6-type echo-request -j $accept"); +# &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INPUT $eth6devin -p icmpv6 --icmpv6-type echo-reply -j $accept"); +# &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INPUT $eth6devin -p icmpv6 --icmpv6-type router-advertisement -m hl --hl-eq 255 -j $accept"); +# &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INPUT $eth6devin -p icmpv6 --icmpv6-type neighbor-solicitation -m hl --hl-eq 255 -j $accept"); +# &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INPUT $eth6devin -p icmpv6 --icmpv6-type neighbor-advertisement -m hl --hl-eq 255 -j $accept"); +# &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INPUT $eth6devin -p icmpv6 --icmpv6-type redirect -m hl --hl-eq 255 -j $accept"); +# } else { +# &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A INPUT $eth6devin -p icmpv6 -j $accept"); +# } +# +# &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $eth6devout -p icmpv6 -j $accept"); +## &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $eth6devout -p icmpv6 --icmpv6-type destination-unreachable -j $accept"); +## &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $eth6devout -p icmpv6 --icmpv6-type packet-too-big -j $accept"); +## &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $eth6devout -p icmpv6 --icmpv6-type time-exceeded -j $accept"); +## &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $eth6devout -p icmpv6 --icmpv6-type parameter-problem -j $accept"); +## &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $eth6devout -p icmpv6 --icmpv6-type echo-request -j $accept"); +## &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $eth6devout -p icmpv6 --icmpv6-type echo-reply -j $accept"); +## &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $eth6devout -p icmpv6 --icmpv6-type router-advertisement -m hl --hl-eq 255 -j $accept"); +## &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $eth6devout -p icmpv6 --icmpv6-type neighbor-solicitation -m hl --hl-eq 255 -j $accept"); +## &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $eth6devout -p icmpv6 --icmpv6-type neighbor-advertisement -m hl --hl-eq 255 -j $accept"); +## &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A OUTPUT $eth6devout -p icmpv6 --icmpv6-type redirect -m hl --hl-eq 255 -j $accept"); +# } + + if (-e "/etc/csf/csf.redirect") { + my $dnat = 0; + my @entries = slurp("/etc/csf/csf.redirect"); + foreach my $line (@entries) { + if ($line =~ /^Include\s*(.*)$/) { + my @incfile = slurp($1); + push @entries,@incfile; + } + } + foreach my $line (@entries) { + $line =~ s/$cleanreg//g; + if ($line eq "") {next} + if ($line =~ /^\s*\#|Include/) {next} + my ($redirect,$comment) = split (/\s/,$line,2); + my ($ipx,$porta,$ipy,$portb,$proto) = split (/\|/,$redirect); + unless ($proto eq "tcp" or $proto eq "udp") {&error(__LINE__,"csf: Incorrect csf.redirect setting ([$proto]): [$line]")} + unless ($ipx eq "*" or checkip(\$ipx)) {&error(__LINE__,"csf: Incorrect csf.redirect setting ([$ipx]): [$line]")} + unless ($porta eq "*" or $porta > 0 or $porta < 65536) {&error(__LINE__,"csf: Incorrect csf.redirect setting ([$porta]): [$line]")} + unless ($ipy eq "*" or checkip(\$ipy)) {&error(__LINE__,"csf: Incorrect csf.redirect setting ([$ipy]): [$line]")} + unless ($portb eq "*" or $portb > 0 or $portb < 65536) {&error(__LINE__,"csf: Incorrect csf.redirect setting ([$portb]): [$line]")} + if ($ipy eq "*") { + if ($ipx eq "*") {&syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -t nat -A PREROUTING $ethdevin -p $proto --dport $porta -j REDIRECT --to-ports $portb")} + else {&syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -t nat -A PREROUTING $ethdevin -p $proto -d $ipx --dport $porta -j REDIRECT --to-ports $portb")} + } else { + unless ($dnat) { + open (my $OUT,">","/proc/sys/net/ipv4/ip_forward"); + flock ($OUT, LOCK_EX); + print $OUT "1"; + close ($OUT); + $dnat = 1; + } + if ($ipx ne "*" and $porta eq "*") { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -t nat -A PREROUTING $ethdevin -p $proto -d $ipx -j DNAT --to-destination $ipy"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -t nat -A POSTROUTING $ethdevout -p $proto -d $ipy -j SNAT --to-source $ipx"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A FORWARD $ethdevin -p $proto -d $ipy $statemodulenew -j ACCEPT"); + } + elsif ($ipx ne "*" and $porta ne "*" and $portb ne "*") { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -t nat -A PREROUTING $ethdevin -p $proto -d $ipx --dport $porta -j DNAT --to-destination $ipy:$portb"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -t nat -A POSTROUTING $ethdevout -p $proto -d $ipy -j SNAT --to-source $ipx"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A FORWARD $ethdevin -p $proto -d $ipy --dport $portb $statemodulenew -j ACCEPT"); + } + else {&error(__LINE__,"csf: Invalid csf.redirect format [$line]")} + } + } + if ($dnat and $config{LF_SPI}) { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A FORWARD $ethdevin $statemodule ESTABLISHED,RELATED -j ACCEPT"); + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A FORWARD $ethdevin -j LOGDROPIN"); + } + } + return; +} +# end doportfilters +############################################################################### +# start dodisable +sub dodisable { + open (my $OUT, ">", "/etc/csf/csf.disable"); + flock ($OUT, LOCK_EX); + close ($OUT); + unless ($config{GENERIC}) { + sysopen (my $CONF, "/etc/chkserv.d/chkservd.conf", O_RDWR | O_CREAT) or &error(__LINE__,"Could not open /etc/chkserv.d/chkservd.conf: $!"); + flock ($CONF, LOCK_EX) or &error(__LINE__,"Could not lock /etc/chkserv.d/chkservd.conf: $!"); + my $text = join("", <$CONF>); + my @conf = split(/$slurpreg/,$text); + chomp @conf; + seek ($CONF, 0, 0); + truncate ($CONF, 0); + foreach my $line (@conf) { + if ($line =~ /^lfd:/) {$line = "lfd:0"} + print $CONF $line."\n"; + } + close ($CONF) or &error(__LINE__,"Could not close /etc/conf: $!"); + } + if ($config{DIRECTADMIN}) { + sysopen (my $CONF, "/usr/local/directadmin/data/admin/services.status", O_RDWR | O_CREAT) or &error(__LINE__,"Could not open /usr/local/directadmin/data/admin/services.status: $!"); + flock ($CONF, LOCK_EX) or &error(__LINE__,"Could not lock /usr/local/directadmin/data/admin/services.status: $!"); + my $text = join("", <$CONF>); + my @conf = split(/$slurpreg/,$text); + chomp @conf; + seek ($CONF, 0, 0); + truncate ($CONF, 0); + foreach my $line (@conf) { + if ($line =~ /^lfd=/) {$line = "lfd=OFF"} + print $CONF $line."\n"; + } + close ($CONF) or &error(__LINE__,"Could not close /usr/local/directadmin/data/admin/services.status: $!"); + } + ConfigServer::Service::stoplfd(); + &dostop(0); + + print "csf and lfd have been disabled\n"; + return; +} +# end dodisable +############################################################################### +# start doenable +sub doenable { + unless (-e "/etc/csf/csf.disable") { + print "csf and lfd are not disabled!\n"; + exit 0; + } + unlink ("/etc/csf/csf.disable"); + &dostart; + ConfigServer::Service::startlfd(); + unless ($config{GENERIC}) { + sysopen (my $CONF, "/etc/chkserv.d/chkservd.conf", O_RDWR | O_CREAT) or &error(__LINE__,"Could not open /etc/chkserv.d/chkservd.conf: $!"); + flock ($CONF, LOCK_EX) or &error(__LINE__,"Could not lock /etc/chkserv.d/chkservd.conf: $!"); + my $text = join("", <$CONF>); + my @conf = split(/$slurpreg/,$text); + chomp @conf; + seek ($CONF, 0, 0); + truncate ($CONF, 0); + foreach my $line (@conf) { + if ($line =~ /^lfd:/) {$line = "lfd:1"} + print $CONF $line."\n"; + } + close ($CONF) or &error(__LINE__,"Could not close /etc/conf: $!"); + open (my $OUT, ">", "/etc/chkserv.d/lfd"); + flock ($OUT, LOCK_EX); + print $OUT "service[lfd]=x,x,x,service lfd restart,lfd,root\n"; + close ($OUT); + } + if ($config{DIRECTADMIN}) { + sysopen (my $CONF, "/usr/local/directadmin/data/admin/services.status", O_RDWR | O_CREAT) or &error(__LINE__,"Could not open /usr/local/directadmin/data/admin/services.status: $!"); + flock ($CONF, LOCK_EX) or &error(__LINE__,"Could not lock /usr/local/directadmin/data/admin/services.status: $!"); + my $text = join("", <$CONF>); + my @conf = split(/$slurpreg/,$text); + chomp @conf; + seek ($CONF, 0, 0); + truncate ($CONF, 0); + foreach my $line (@conf) { + if ($line =~ /^lfd=/) {$line = "lfd=ON"} + print $CONF $line."\n"; + } + close ($CONF) or &error(__LINE__,"Could not close /usr/local/directadmin/data/admin/services.status: $!"); + } + + print "csf and lfd have been enabled\n"; + return; +} +# end doenable +############################################################################### +# start crontab +sub crontab { + my $act = shift; + my @crontab = slurp("/etc/crontab"); + my $hit = 0; + my @newcrontab; + foreach my $line (@crontab) { + if ($line =~ /csf(\.pl)? -f/) { + $hit = 1; + if ($act eq "add") { + push @newcrontab, $line; + } + } else { + push @newcrontab, $line; + } + } + if (($act eq "add") and !($hit)) { + push @newcrontab, "*/$config{TESTING_INTERVAL} * * * * root /usr/sbin/csf -f > /dev/null 2>&1"; + } + + if (($act eq "remove") and !($hit)) { + # don't do anything + } else { + sysopen (my $CRONTAB, "/etc/crontab", O_RDWR | O_CREAT) or die "Could not open /etc/crontab: $!"; + flock ($CRONTAB, LOCK_EX) or die "Could not lock /etc/crontab: $!"; + seek ($CRONTAB, 0, 0); + truncate ($CRONTAB, 0); + foreach my $line (@newcrontab) { + print $CRONTAB $line."\n"; + } + close ($CRONTAB) or die "Could not close /etc/crontab: $!"; + } + return; +} +# end crontab +############################################################################### +# start error +sub error { + my $line = shift; + my $error = shift; + my $verbose; + if ($config{DEBUG} >= 1) {$verbose = "--verbose"} + system ("$config{IPTABLES} $verbose --policy INPUT ACCEPT"); + system ("$config{IPTABLES} $verbose --policy OUTPUT ACCEPT"); + system ("$config{IPTABLES} $verbose --policy FORWARD ACCEPT"); + system ("$config{IPTABLES} $verbose --flush"); + system ("$config{IPTABLES} $verbose --delete-chain"); + if ($config{NAT}) { + &syscommand(__LINE__,"$config{IPTABLES} $verbose -t nat --flush"); + &syscommand(__LINE__,"$config{IPTABLES} $verbose -t nat --delete-chain"); + } + if ($config{RAW}) { + &syscommand(__LINE__,"$config{IPTABLES} $verbose -t raw --flush"); + &syscommand(__LINE__,"$config{IPTABLES} $verbose -t raw --delete-chain"); + } + if ($config{MANGLE}) { + &syscommand(__LINE__,"$config{IPTABLES} $verbose -t mangle --flush"); + &syscommand(__LINE__,"$config{IPTABLES} $verbose -t mangle --delete-chain"); + } + + if ($config{IPV6}) { + system ("$config{IP6TABLES} $verbose --policy INPUT ACCEPT"); + system ("$config{IP6TABLES} $verbose --policy OUTPUT ACCEPT"); + system ("$config{IP6TABLES} $verbose --policy FORWARD ACCEPT"); + system ("$config{IP6TABLES} $verbose --flush"); + system ("$config{IP6TABLES} $verbose --delete-chain"); + if ($config{NAT6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $verbose -t nat --flush"); + &syscommand(__LINE__,"$config{IP6TABLES} $verbose -t nat --delete-chain"); + } + if ($config{RAW6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $verbose -t raw --flush"); + &syscommand(__LINE__,"$config{IP6TABLES} $verbose -t raw --delete-chain"); + } + if ($config{MANGLE6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $verbose -t mangle --flush"); + &syscommand(__LINE__,"$config{IP6TABLES} $verbose -t mangle --delete-chain"); + } + } + + if ($config{LF_IPSET}) { + system ("$config{IPSET} flush"); + system ("$config{IPSET} destroy"); + } + + print "Error: $error, at line $line\n"; + open (my $OUT,">", "/etc/csf/csf.error"); + flock ($OUT, LOCK_EX); + print $OUT "Error: $error, at line $line in /usr/sbin/csf\n"; + close ($OUT); + if ($config{TESTING}) {&crontab("remove")} + exit 1; +} +# end error +############################################################################### +# start version +sub version { + open (my $IN, "<", "/etc/csf/version.txt") or die "Unable to open version.txt: $!"; + flock ($IN, LOCK_SH); + my $myv = <$IN>; + close ($IN); + chomp $myv; + return $myv; +} +# end version +############################################################################### +# start getethdev +sub getethdev { + my $ethdev = ConfigServer::GetEthDev->new(); + my %g_ifaces = $ethdev->ifaces; + my %g_ipv4 = $ethdev->ipv4; + my %g_ipv6 = $ethdev->ipv6; + foreach my $key (keys %g_ifaces) { + $ifaces{$key} = 1; + } + foreach my $key (keys %g_ipv4) { + $ips{$key} = 1; + } + if ($config{IPV6}) { + foreach my $key (keys %g_ipv6) { + eval { + local $SIG{__DIE__} = undef; + $ipscidr6->add($key); + }; + } + } + + ($config{ETH_DEVICE},undef) = split (/:/,$config{ETH_DEVICE},2); + if ($config{ETH_DEVICE} eq "") { + $ethdevin = "! -i lo"; + $ethdevout = "! -o lo"; + } else { + $ethdevin = "-i $config{ETH_DEVICE}"; + $ethdevout = "-o $config{ETH_DEVICE}"; + } + if ($config{ETH6_DEVICE} eq "") { + $eth6devin = $ethdevin; + $eth6devout = $ethdevout; + } else { + $eth6devin = "-i $config{ETH6_DEVICE}"; + $eth6devout = "-o $config{ETH6_DEVICE}"; + } + return; +} +# end getethdev +############################################################################### +# start linefilter +sub linefilter { + my $line = shift; + my $ad = shift; + my $chain = shift; + my $delete = shift; + my $pktin = "$accept"; + my $pktout = "$accept"; + my $localin = "ALLOWIN"; + my $localout = "ALLOWOUT"; + my $inadd = "-I"; + if ($ad eq "deny") { + $inadd = "-A"; + $pktin = $config{DROP}; + $pktout = $config{DROP_OUT}; + if ($config{DROP_IP_LOGGING}) {$pktin = "LOGDROPIN"} + if ($config{DROP_OUT_LOGGING}) {$pktout = "LOGDROPOUT"} + $localin = "DENYIN"; + $localout = "DENYOUT"; + } + my $chainin = $chain."IN"; + my $chainout = $chain."OUT"; + + $line =~ s/\n|\r//g; + $line = lc $line; + if ($line =~ /^\#/) {return} + if ($line =~ /^Include/) {return} + if ($line eq "") {return} + + my $checkip = checkip(\$line); + my $iptables = $config{IPTABLES}; + my $ipv4 = 1; + my $ipv6 = 0; + my $linein = $ethdevin; + my $lineout = $ethdevout; + if ($checkip == 6) { + if ($config{IPV6}) { + $iptables = $config{IP6TABLES}; + $linein = $eth6devin; + $lineout = $eth6devout; + $ipv4 = 0; + $ipv6 = 1; + } else {return} + } + + if ($checkip) { + if ($chain) { + if ($config{LF_IPSET}) { + if ($ipv4) {&ipsetadd("chain_$chainin",$line)} + else {&ipsetadd("chain_6_${chainin}",$line)} + } else { + &syscommand(__LINE__,"$iptables $config{IPTABLESWAIT} $verbose -A $chainin $linein -s $line -j $pktin"); + if (($ad eq "deny" and !$config{LF_BLOCKINONLY}) or ($ad ne "deny")) {&syscommand(__LINE__,"$iptables $config{IPTABLESWAIT} $verbose -A $chainout $lineout -d $line -j $pktout")} + } + } else { + if ($delete) { + if ($config{LF_IPSET}) { + if ($ipv4) {&ipsetdel("chain_$localin",$line)} + else {&ipsetdel("chain_6_${localin}",$line)} + } else { + &syscommand(__LINE__,"$iptables $config{IPTABLESWAIT} $verbose -D $localin $linein -s $line -j $pktin"); + if (($ad eq "deny" and !$config{LF_BLOCKINONLY}) or ($ad ne "deny")) {&syscommand(__LINE__,"$iptables $config{IPTABLESWAIT} $verbose -D $localout $lineout -d $line -j $pktout")} + } + if (($ad eq "deny") and ($ipv4 and $config{MESSENGER} and $config{MESSENGER_PERM})) {&domessenger($line,"D")} + if (($ad eq "deny") and ($ipv6 and $config{MESSENGER6} and $config{MESSENGER_PERM})) {&domessenger($line,"D")} + } else { + if ($config{LF_IPSET}) { + if ($ipv4) {&ipsetadd("chain_$localin",$line)} + else {&ipsetadd("chain_6_${localin}",$line)} + } else { + &syscommand(__LINE__,"$iptables $config{IPTABLESWAIT} $verbose $inadd $localin $linein -s $line -j $pktin"); + if (($ad eq "deny" and !$config{LF_BLOCKINONLY}) or ($ad ne "deny")) {&syscommand(__LINE__,"$iptables $config{IPTABLESWAIT} $verbose $inadd $localout $lineout -d $line -j $pktout")} + } + if (($ad eq "deny") and ($ipv4 and $config{MESSENGER} and $config{MESSENGER_PERM})) {&domessenger($line,"A")} + if (($ad eq "deny") and ($ipv6 and $config{MESSENGER6} and $config{MESSENGER_PERM})) {&domessenger($line,"A")} + } + } + } + elsif ($line =~ /\:|\|/) { + if ($line !~ /\|/) {$line =~ s/\:/\|/g} + my $sip; + my $dip; + my $sport; + my $dport; + my $protocol = "-p tcp"; + my $inout; + my $from = 0; + my $uid; + my $gid; + my $iptype; + + my @ll = split(/\|/,$line); + if ($ll[0] eq "tcp") { + $protocol = "-p tcp"; + $from = 1; + } + elsif ($ll[0] eq "udp") { + $protocol = "-p udp"; + $from = 1; + } + elsif ($ll[0] eq "icmp") { + $protocol = "-p icmp"; + $from = 1; + } + for (my $x = $from;$x < 2;$x++) { + if (($ll[$x] eq "out")) { + $inout = "out"; + $from = $x + 1; + last; + } + elsif (($ll[$x] eq "in")) { + $inout = "in"; + $from = $x + 1; + last; + } + } + for (my $x = $from;$x < 3;$x++) { + if (($ll[$x] =~ /d=(.*)/)) { + $dport = "--dport $1"; + $dport =~ s/_/:/g; + if ($protocol eq "-p icmp") {$dport = "--icmp-type $1"} + if ($dport =~ /,/) {$dport = "-m multiport ".$dport} + $from = $x + 1; + last; + } + elsif (($ll[$x] =~ /s=(.*)/)) { + $sport = "--sport $1"; + $sport =~ s/_/:/g; + if ($protocol eq "-p icmp") {$sport = "--icmp-type $1"} + if ($sport =~ /,/) {$sport = "-m multiport ".$sport} + $from = $x + 1; + last; + } + } + for (my $x = $from;$x < 4;$x++) { + if (($ll[$x] =~ /d=(.*)/)) { + my $ip = $1; + my $status = checkip(\$ip); + if ($status) { + $iptype = $status; + $dip = "-d $1"; + } + last; + } + elsif (($ll[$x] =~ /s=(.*)/)) { + my $ip = $1; + my $status = checkip(\$ip); + if ($status) { + $iptype = $status; + $sip = "-s $1"; + } + last; + } + } + for (my $x = $from;$x < 5;$x++) { + if (($ll[$x] =~ /u=(.*)/)) { + $uid = "--uid-owner $1"; + last; + } + elsif (($ll[$x] =~ /g=(.*)/)) { + $gid = "--gid-owner $1"; + last; + } + } + + if ($uid or $gid) { + if ($config{VPS} and $noowner) { + print "Cannot use UID or GID rules [$ad: $line] on this VPS as the Monolithic kernel does not support the iptables module ipt_owner/xt_owner - rule skipped\n"; + } else { + if ($chain) { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A $chainout $lineout $protocol $dport -m owner $uid $gid -j $pktout"); + if ($config{IPV6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A $chainout $lineout $protocol $dport -m owner $uid $gid -j $pktout"); + } + } else { + if ($delete) { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D $localout $lineout $protocol $dport -m owner $uid $gid -j $pktout"); + if ($config{IPV6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D $localout $lineout $protocol $dport -m owner $uid $gid -j $pktout"); + } + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose $inadd $localout $lineout $protocol $dport -m owner $uid $gid -j $pktout"); + if ($config{IPV6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose $inadd $localout $lineout $protocol $dport -m owner $uid $gid -j $pktout"); + } + } + } + } + } + elsif (($sip or $dip) and ($dport or $sport)) { + my $iptables = $config{IPTABLES}; + if ($iptype == 6) { + if ($config{IPV6}) { + $iptables = $config{IP6TABLES}; + } else { + return; + } + } + if (($inout eq "") or ($inout eq "in")) { + my $bport = $dport; + $bport =~ s/--dport //o; + my $bip = $sip; + $bip =~ s/-s //o; + if ($chain) { + &syscommand(__LINE__,"$iptables $config{IPTABLESWAIT} $verbose -A $chainin $linein $protocol $dip $sip $dport $sport -j $pktin"); + } else { + if ($delete) { + &syscommand(__LINE__,"$iptables $config{IPTABLESWAIT} $verbose -D $localin $linein $protocol $dip $sip $dport $sport -j $pktin"); + if ($messengerports{$bport} and ($ad eq "deny") and ($ipv4 and $config{MESSENGER} and $config{MESSENGER_PERM})) {&domessenger($bip,"D","$bport")} + if ($messengerports{$bport} and ($ad eq "deny") and ($ipv6 and $config{MESSENGER6} and $config{MESSENGER_PERM})) {&domessenger($bip,"D","$bport")} + } else { + &syscommand(__LINE__,"$iptables $config{IPTABLESWAIT} $verbose $inadd $localin $linein $protocol $dip $sip $dport $sport -j $pktin"); + if ($messengerports{$bport} and ($ad eq "deny") and ($ipv4 and $config{MESSENGER} and $config{MESSENGER_PERM})) {&domessenger($bip,"A","$bport")} + if ($messengerports{$bport} and ($ad eq "deny") and ($ipv6 and $config{MESSENGER6} and $config{MESSENGER_PERM})) {&domessenger($bip,"A","$bport")} + } + } + } + if ($inout eq "out") { + if ($chain) { + &syscommand(__LINE__,"$iptables $config{IPTABLESWAIT} $verbose -A $chainout $lineout $protocol $dip $sip $dport $sport -j $pktout"); + } else { + if ($delete) { + &syscommand(__LINE__,"$iptables $config{IPTABLESWAIT} $verbose -D $localout $lineout $protocol $dip $sip $dport $sport -j $pktout"); + } else { + &syscommand(__LINE__,"$iptables $config{IPTABLESWAIT} $verbose $inadd $localout $lineout $protocol $dip $sip $dport $sport -j $pktout"); + } + } + } + } + } + return; +} +# end linefilter +############################################################################### +# start autoupdates +sub autoupdates { + my $hour = int (rand(24)); + my $minutes = int (rand(60)); + + unless (-d "/etc/cron.d") {mkdir "/etc/cron.d"} + open (my $OUT,">", "/etc/cron.d/csf_update") or &error(__LINE__,"Could not create /etc/cron.d/csf_update: $!"); + flock ($OUT, LOCK_EX) or &error(__LINE__,"Could not lock /etc/cron.d/csf_update: $!"); + print $OUT <urlget($url); + if ($status) {print "Oops: $text\n"; exit 1} + $actv = $text; + } + + if ((($actv ne "") and ($actv =~ /^[\d\.]*$/)) or $force) { + if (($actv > $version) or $force) { + local $| = 1; + + unless ($force) {print "Upgrading csf from v$version to $actv...\n"} + if (-e "/usr/src/csf.tgz") {unlink ("/usr/src/csf.tgz") or die $!} + print "Retrieving new csf package...\n"; + + my $url = "https://$config{DOWNLOADSERVER}/csf.tgz"; + if ($config{URLGET} == 1) {$url = "http://$config{DOWNLOADSERVER}/csf.tgz";} + my ($status, $text) = $urlget->urlget($url,"/usr/src/csf.tgz"); + + if (! -z "/usr/src/csf/csf.tgz") { + print "\nUnpacking new csf package...\n"; + system ("cd /usr/src ; tar -xzf csf.tgz ; cd csf ; sh install.sh"); + print "\nTidying up...\n"; + system ("rm -Rfv /usr/src/csf*"); + print "\nRestarting csf and lfd...\n"; + system ("/usr/sbin/csf -r"); + ConfigServer::Service::restartlfd(); + print "\n...All done.\n\nChangelog: https://$config{DOWNLOADSERVER}/csf/changelog.txt\n"; + } + } else { + if (-t STDOUT) {print "csf is already at the latest version: v$version\n"} ##no critic + } + } else { + print "Unable to verify the latest version of csf at this time\n"; + } + return; +} +# end doupdate +############################################################################### +# start docheck +sub docheck { + my $url = "https://$config{DOWNLOADSERVER}/csf/version.txt"; + if ($config{URLGET} == 1) {$url = "http://$config{DOWNLOADSERVER}/csf/version.txt";} + my ($status, $text) = $urlget->urlget($url); + if ($status) {print "Oops: $text\n"; exit 1} + + my $actv = $text; + my $up = 0; + + if (($actv ne "") and ($actv =~ /^[\d\.]*$/)) { + if ($actv > $version) { + print "A newer version of csf is available - Current:v$version New:v$actv\n"; + } else { + print "csf is already at the latest version: v$version\n"; + } + } else { + print "Unable to verify the latest version of csf at this time\n"; + } + return; +} +# end docheck +############################################################################### +# start doiplookup +sub doiplookup { + if (checkip(\$input{argument})) { + print iplookup($input{argument})."\n"; + } else { + print "lookup failed: [$input{argument}] is not a valid PUBLIC IP\n"; + } + return; +} +# end doiplookup +############################################################################### +# start dogrep +sub dogrep { + my $ipmatch = $input{argument}; + checkip(\$ipmatch); + my $ipstring = quotemeta($ipmatch); + my $mhit = 0; + my $head = 0; + my $oldchain = "INPUT"; + my $table = "filter"; + my ($chain,$rest); + format GREP = +@<<<<< @<<<<<<<<<<<<<<< @* +$table, $chain, $rest +. + local $~ = "GREP"; + + my $command = "echo 'filter table:\n' ; $config{IPTABLES} $config{IPTABLESWAIT} -v -L -n --line-numbers"; + if ($config{NAT}) {$command .= " ; echo 'nat table:\n' ; $config{IPTABLES} $config{IPTABLESWAIT} -v -t nat -L -n --line-numbers"} + if ($config{MANGLE}) {$command .= " ;echo 'mangle table:\n' ; $config{IPTABLES} $config{IPTABLESWAIT} -v -t mangle -L -n --line-numbers"} + if ($config{RAW}) {$command .= " ; echo 'raw table:\n' ; $config{IPTABLES} $config{IPTABLESWAIT} -v -t raw -L -n --line-numbers"} + my ($childin, $childout); + my $pid = open3($childin, $childout, $childout, $command); + my @output = <$childout>; + waitpid ($pid, 0); + chomp @output; + if ($output[0] =~ /# Warning: iptables-legacy tables present/) {shift @output} + foreach my $line (@output) { + if ($line =~ /^Chain\s([\w\_]*)\s/) {$chain = $1} + if ($line =~ /^(\S+) table:$/) {$table = $1} + if ($chain eq "acctboth") {next} + if (!$head and ($line =~ /^num/)) {print "\nTable Chain $line\n"; $head = 1} + if ($line !~ /\d+/) {next} + my (undef,undef,undef,$action,undef,undef,undef,undef,$source,$destination,$options) = split(/\s+/,$line,11); + + my $hit = 0; + if ($line =~ /\b$ipstring\b/i) { + $hit = 1; + } else { + if (($source =~ /\//) and ($source ne "0.0.0.0/0")) { + if (checkip(\$source)) { + my $cidr = Net::CIDR::Lite->new; + eval {local $SIG{__DIE__} = undef; $cidr->add($source)}; + if ($cidr->find($ipmatch)) {$hit = 1} + } + } + if (!$hit and ($destination =~ /\//) and ($destination ne "0.0.0.0/0")) { + if (checkip(\$destination)) { + my $cidr = Net::CIDR::Lite->new; + eval {local $SIG{__DIE__} = undef; $cidr->add($destination)}; + if ($cidr->find($ipmatch)) {$hit = 1} + } + } + } + if ($hit) { + $rest = $line; + if ($oldchain ne $chain) {print "\n"} + write; + $oldchain = $chain; + $mhit = 1; + } + } + unless ($mhit) { + print "No matches found for $ipmatch in iptables\n"; + } + + if ($config{LF_IPSET} and checkip(\$ipmatch)) { + print "\n"; + my $mhit = 0; + my $head = 0; + my $oldchain = "INPUT"; + my ($childin, $childout); + my $pid = open3($childin, $childout, $childout, $config{IPSET}, "-n", "list"); + my @output = <$childout>; + waitpid ($pid, 0); + chomp @output; + my %sets; + foreach my $line (@output) {$sets{$line} = 1} + foreach my $chain (keys %sets) { + my $option; + my $cc; + my $country; + + if ($chain =~ /^cc_(\w+)$/) { + $cc = $1; + $country = uc $cc; + if ($config{CC_DENY} =~ /$cc/i) {$option = "CC_DENY"} + if ($config{CC_ALLOW} =~ /$cc/i) {$option = "CC_ALLOW"} + if ($config{CC_ALLOW_FILTER} =~ /$cc/i) {$option = "CC_ALLOW_FILTER"} + if ($config{CC_ALLOW_PORTS} =~ /$cc/i) {$option = "CC_ALLOW_PORTS"} + if ($config{CC_DENY_PORTS} =~ /$cc/i) {$option = "CC_DENY_PORTS"} + } + if ($chain =~ /^cc_6_(\w+)$/) { + $cc = $1; + $country = uc $cc; + if ($config{CC_DENY} =~ /$cc/i) {$option = "CC_DENY"} + if ($config{CC_ALLOW} =~ /$cc/i) {$option = "CC_ALLOW"} + if ($config{CC_ALLOW_FILTER} =~ /$cc/i) {$option = "CC_ALLOW_FILTER"} + if ($config{CC_ALLOW_PORTS} =~ /$cc/i) {$option = "CC_ALLOW_PORTS"} + if ($config{CC_DENY_PORTS} =~ /$cc/i) {$option = "CC_DENY_PORTS"} + } + + if ($chain =~ /^bl_(\w+)$/) { + $cc = $1; + $option = "$cc file:/etc/csf/csf.blocklists"; + } + if ($chain =~ /^bl_6_(\w+)$/) { + $cc = $1; + $option = "$cc file:/etc/csf/csf.blocklists"; + } + + if ($chain =~ /^chain_(\w+)$/) { + $cc = $1; + if ($cc eq "DENY") {$option = " File:/etc/csf/csf.deny"} + if ($cc eq "ALLOW") {$option = " File:/etc/csf/csf.allow"} + if ($cc eq "GDENY") {$option = "GLOBAL_DENY"} + if ($cc eq "GALLOW") {$option = "GLOBAL_ALLOW"} + if ($cc eq "ALLOWDYN") {$option = "DYNDNS"} + if ($cc eq "GDYN") {$option = "GLOBAL_DYNDNS"} + } + if ($chain =~ /^chain_6_(\w+)$/) { + $cc = $1; + if ($cc eq "DENY") {$option = " File:/etc/csf/csf.deny"} + if ($cc eq "ALLOW") {$option = " File:/etc/csf/csf.allow"} + if ($cc eq "GDENY") {$option = "GLOBAL_DENY"} + if ($cc eq "GALLOW") {$option = "GLOBAL_ALLOW"} + if ($cc eq "ALLOWDYN") {$option = "DYNDNS"} + if ($cc eq "GDYN") {$option = "GLOBAL_DYNDNS"} + } + + my $hit = 0; + my ($childin, $childout); + my $pid = open3($childin, $childout, $childout, $config{IPSET}, "test", "$chain", "$ipmatch"); + my @output = <$childout>; + waitpid ($pid, 0); + chomp @output; + my $line = $output[0]; + if ($line =~ /is in set/) {$hit = 1} + + if ($hit) { + $rest = $line; + if ($oldchain ne $chain) {print "\n"} + print "IPSET: Set:$chain Match:$ipmatch"; + if ($option) { + print " Setting:$option"; + if ($country) {print " Country:$country"} + } + print "\n"; + $oldchain = $chain; + $mhit = 1; + } + } + unless ($mhit) { + print "IPSET: No matches found for $ipmatch\n"; + } + } + + if ($config{IPV6}) { + my $mhit = 0; + my $head = 0; + $table = "filter"; + my $oldchain = "INPUT"; + print "\n\nip6tables:\n"; + my $command = "echo 'filter table:\n' ; $config{IP6TABLES} $config{IPTABLESWAIT} -v -L -n --line-numbers"; + if ($config{NAT6}) {$command .= " ; echo 'nat table:\n' ; $config{IP6TABLES} $config{IPTABLESWAIT} -v -t nat -L -n --line-numbers"} + if ($config{MANGLE6}) {$command .= " ; echo 'mangle table:\n' ; $config{IP6TABLES} $config{IPTABLESWAIT} -v -t mangle -L -n --line-numbers"} + if ($config{RAW6}) {$command .= " ; echo 'raw table:\n' ; $config{IP6TABLES} $config{IPTABLESWAIT} -v -t raw -L -n --line-numbers"} + my ($childin, $childout); + my $pid = open3($childin, $childout, $childout, $command); + my @output = <$childout>; + waitpid ($pid, 0); + chomp @output; + if ($output[0] =~ /# Warning: iptables-legacy tables present/) {shift @output} + foreach my $line (@output) { + if ($line =~ /^Chain\s([\w\_]*)\s/) {$chain = $1} + if ($line =~ /^(\S+) table:$/) {$table = $1} + if ($chain eq "acctboth") {next} + if (!$head and ($line =~ /^num/)) {print "\nTable Chain $line\n"; $head = 1} + + if ($line !~ /\d+/) {next} + my (undef,undef,undef,$action,undef,undef,undef,$source,$destination,$options) = split(/\s+/,$line,11); + + my $hit = 0; + if ($line =~ /\b$ipstring\b/i) { + $hit = 1; + } else { + if (($source =~ /\//) and ($source ne "::/0")) { + if (checkip(\$source)) { + my $cidr = Net::CIDR::Lite->new; + eval {local $SIG{__DIE__} = undef; $cidr->add($source)}; + if ($cidr->find($ipmatch)) {$hit = 1} + } + } + if (!$hit and ($destination =~ /\//) and ($destination ne "::/0")) { + if (checkip(\$destination)) { + my $cidr = Net::CIDR::Lite->new; + eval {local $SIG{__DIE__} = undef; $cidr->add($destination)}; + if ($cidr->find($ipmatch)) {$hit = 1} + } + } + } + if ($hit) { + $rest = $line; + if ($oldchain ne $chain) {print "\n"} + write; + $oldchain = $chain; + $mhit = 1; + } + } + unless ($mhit) { + print "No matches found for $ipmatch in ip6tables\n"; + } + } + + open (my $IN, "<", "/var/lib/csf/csf.tempallow"); + flock ($IN, LOCK_SH); + my @tempallow = <$IN>; + close ($IN); + chomp @tempallow; + foreach my $line (@tempallow) { + my ($time,$ipd,$port,$inout,$timeout,$message) = split(/\|/,$line); + checkip(\$ipd); + if ($ipd eq $ipmatch) { + print "\nTemporary Allows: IP:$ipd Port:$port Dir:$inout TTL:$timeout ($message)\n"; + } + elsif ($ipd =~ /(.*\/\d+)/) { + my $cidrhit = $1; + if (checkip(\$cidrhit)) { + my $cidr = Net::CIDR::Lite->new; + eval {local $SIG{__DIE__} = undef; $cidr->add($cidrhit)}; + if ($cidr->find($ipmatch)) { + print "\nTemporary Allows: IP:$ipd Port:$port Dir:$inout TTL:$timeout ($message)\n"; + } + } + } + } + my @allow = slurp("/etc/csf/csf.allow"); + foreach my $line (@allow) { + if ($line =~ /^Include\s*(.*)$/) { + my @incfile = slurp($1); + push @allow,@incfile; + } + } + foreach my $line (@allow) { + $line =~ s/$cleanreg//g; + if ($line eq "") {next} + if ($line =~ /^\s*\#|Include/) {next} + my ($ipd,$commentd) = split (/\s/,$line,2); + checkip(\$ipd); + if ($ipd eq $ipmatch) { + print "\ncsf.allow: $line\n"; + } + elsif ($ipd =~ /(.*\/\d+)/) { + my $cidrhit = $1; + if (checkip(\$cidrhit)) { + my $cidr = Net::CIDR::Lite->new; + eval {local $SIG{__DIE__} = undef; $cidr->add($cidrhit)}; + if ($cidr->find($ipmatch)) { + print "\nPermanent Allows (csf.allow): $line\n" + } + } + } + } + open (my $TEMPBAN, "<", "/var/lib/csf/csf.tempban"); + flock ($TEMPBAN, LOCK_SH); + my @tempdeny = <$TEMPBAN>; + close ($TEMPBAN); + chomp @tempdeny; + foreach my $line (@tempdeny) { + my ($time,$ipd,$port,$inout,$timeout,$message) = split(/\|/,$line); + checkip(\$ipd); + if ($ipd eq $ipmatch) { + print "\nTemporary Blocks: IP:$ipd Port:$port Dir:$inout TTL:$timeout ($message)\n"; + } + elsif ($ipd =~ /(.*\/\d+)/) { + my $cidrhit = $1; + if (checkip(\$cidrhit)) { + my $cidr = Net::CIDR::Lite->new; + eval {local $SIG{__DIE__} = undef; $cidr->add($cidrhit)}; + if ($cidr->find($ipmatch)) { + print "\nTemporary Blocks: IP:$ipd Port:$port Dir:$inout TTL:$timeout ($message)\n"; + } + } + } + } + my @deny = slurp("/etc/csf/csf.deny"); + foreach my $line (@deny) { + if ($line =~ /^Include\s*(.*)$/) { + my @incfile = slurp($1); + push @deny,@incfile; + } + } + foreach my $line (@deny) { + $line =~ s/$cleanreg//g; + if ($line eq "") {next} + if ($line =~ /^\s*\#|Include/) {next} + my ($ipd,$commentd) = split (/\s/,$line,2); + checkip(\$ipd); + if ($ipd eq $ipmatch) { + print "\ncsf.deny: $line\n"; + } + elsif ($ipd =~ /(.*\/\d+)/) { + my $cidrhit = $1; + if (checkip(\$cidrhit)) { + my $cidr = Net::CIDR::Lite->new; + eval {local $SIG{__DIE__} = undef; $cidr->add($cidrhit)}; + if ($cidr->find($ipmatch)) { + print "\nPermanent Blocks (csf.deny): $line\n" + } + } + } + } + return; +} +# end dogrep +############################################################################### +# start dotempban +sub dotempban { + my ($ip,$deny,$ports,$inout,$time,$timeout,$message); + format TEMPBAN = +@<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @|||||| @<<<< @<<<<<<<<<<<<<<< @* +$deny, $ip, $ports, $inout,$time,$message +. + local $~ = "TEMPBAN"; + if ((! -z "/var/lib/csf/csf.tempban") or (! -z "/var/lib/csf/csf.tempallow")) { + print "\nA/D IP address Port Dir Time To Live Comment\n"; + if (! -z "/var/lib/csf/csf.tempban") { + sysopen (my $IN, "/var/lib/csf/csf.tempban", O_RDWR); + flock ($IN, LOCK_SH); + my @data = <$IN>; + chomp @data; + close ($IN); + + foreach my $line (@data) { + if ($line eq "") {next} + ($time,$ip,$ports,$inout,$timeout,$message) = split(/\|/,$line); + $time = $timeout - (time - $time); + if ($ports eq "") {$ports = "*"} + if ($inout eq "") {$inout = " *"} + if ($time < 1) { + $time = "<1"; + } else { + my $days = int($time/(24*60*60)); + my $hours = ($time/(60*60))%24; + my $mins = ($time/60)%60; + my $secs = $time%60; + $days = $days < 1 ? '' : $days .'d '; + $hours = $hours < 1 ? '' : $hours .'h '; + $mins = $mins < 1 ? '' : $mins . 'm '; + $time = $days . $hours . $mins . $secs . 's'; + } + $deny = "DENY"; + foreach (split(/,/,$ports)) {write} + } + } + if (! -z "/var/lib/csf/csf.tempallow") { + sysopen (my $IN, "/var/lib/csf/csf.tempallow", O_RDWR); + flock ($IN, LOCK_SH); + my @data = <$IN>; + chomp @data; + close ($IN); + + foreach my $line (@data) { + if ($line eq "") {next} + ($time,$ip,$ports,$inout,$timeout,$message) = split(/\|/,$line); + $time = $timeout - (time - $time); + if ($ports eq "") {$ports = "*"} + if ($inout eq "") {$inout = " *"} + if ($time < 1) { + $time = "<1"; + } else { + my $days = int($time/(24*60*60)); + my $hours = ($time/(60*60))%24; + my $mins = ($time/60)%60; + my $secs = $time%60; + $days = $days < 1 ? '' : $days .'d '; + $hours = $hours < 1 ? '' : $hours .'h '; + $mins = $mins < 1 ? '' : $mins . 'm '; + $time = $days . $hours . $mins . $secs . 's'; + } + $deny = "ALLOW"; + foreach (split(/,/,$ports)) {write} + } + } + } else { + print "csf: There are no temporary IP entries\n"; + } + return; +} +# end dotempban +############################################################################### +# start dotempdeny +sub dotempdeny { + my $cftemp = shift; + my ($ip,$timeout,$portdir) = split(/\s/,$input{argument},3); + my $inout = "in"; + my $port = ""; + if ($timeout =~ /^(\d*)(m|h|d)/i) { + my $secs = $1; + my $dur = $2; + if ($dur eq "m") {$timeout = $secs * 60} + elsif ($dur eq "h") {$timeout = $secs * 60 * 60} + elsif ($dur eq "d") {$timeout = $secs * 60 * 60 * 24} + else {$timeout = $secs} + } + + my $iptype = checkip(\$ip); + if ($iptype == 6 and !$config{IPV6}) { + print "failed: [$ip] is valid IPv6 but IPV6 is not enabled in csf.conf\n"; + } + + unless ($iptype) { + print "csf: [$ip] is not a valid PUBLIC IP\n"; + return; + } + + &getethdev; + + if ($ips{$ip} or $ipscidr->find($ip) or $ipscidr6->find($ip)) { + print "deny failed: [$ip] is one of this servers addresses!\n"; + return; + } + + if ($timeout =~ /\D/) { + $portdir = join(" ",$timeout,$portdir); + $timeout = 0; + } + + if ($portdir =~ /\-d\s*out/i) {$inout = "out"} + if ($portdir =~ /\-d\s*inout/i) {$inout = "inout"} + if ($portdir =~ /\-p\s*([\w\,\*\;]+)/) {$port = $1} + my $comment = $portdir; + $comment =~ s/\-d\s*out//ig; + $comment =~ s/\-d\s*inout//ig; + $comment =~ s/\-d\s*in//ig; + $comment =~ s/\-p\s*[\w\,\*\;]+//ig; + $comment =~ s/^\s*|\s*$//g; + if ($comment eq "") {$comment = "Manually added: ".iplookup($ip)} + + my @deny = slurp("/etc/csf/csf.deny"); + foreach my $line (@deny) { + if ($line =~ /^Include\s*(.*)$/) { + my @incfile = slurp($1); + push @deny,@incfile; + } + } + my $ipstring = quotemeta($ip); + if (grep {$_ =~ /^$ipstring\b/} @deny) { + print "csf: $ip is already permanently blocked\n"; + exit 0; + } + open (my $IN, "<", "/var/lib/csf/csf.tempban"); + flock ($IN, LOCK_SH); + @deny = <$IN>; + close ($IN); + chomp @deny; + if (grep {$_ =~ /\b$ip\|$port\|\b/} @deny) { + print "csf: $ip is already temporarily blocked\n"; + exit 0; + } + + my $dropin = $config{DROP}; + my $dropout = $config{DROP_OUT}; + if ($config{DROP_IP_LOGGING}) {$dropin = "LOGDROPIN"} + if ($config{DROP_OUT_LOGGING}) {$dropout = "LOGDROPOUT"} + if ($timeout < 2) {$timeout = 3600} + if ($port =~ /\*/) {$port = ""} + + if ($inout =~ /in/) { + if ($port) { + foreach my $dport (split(/\,/,$port)) { + my ($tport,$proto) = split(/\;/,$dport); + $dport = $tport; + if ($proto eq "") {$proto = "tcp"} + if ($iptype == 6) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A DENYIN $eth6devin -p $proto --dport $dport -s $ip -j $dropin"); + if ($messengerports{$dport} and $config{MESSENGER6} and $config{MESSENGER_TEMP}) {&domessenger($ip,"A",$dport)} + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A DENYIN $ethdevin -p $proto --dport $dport -s $ip -j $dropin"); + if ($messengerports{$dport} and $config{MESSENGER} and $config{MESSENGER_TEMP}) {&domessenger($ip,"A",$dport)} + } + } + } else { + if ($iptype == 6) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A DENYIN $eth6devin -s $ip -j $dropin"); + if ($config{MESSENGER6} and $config{MESSENGER_TEMP}) {&domessenger($ip,"A")} + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A DENYIN $ethdevin -s $ip -j $dropin"); + if ($config{MESSENGER} and $config{MESSENGER_TEMP}) {&domessenger($ip,"A")} + } + } + } + if ($inout =~ /out/) { + if ($port) { + foreach my $dport (split(/\,/,$port)) { + my ($tport,$proto) = split(/\;/,$dport); + $dport = $tport; + if ($proto eq "") {$proto = "tcp"} + if ($iptype == 6) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A DENYOUT $eth6devout -p $proto --dport $dport -d $ip -j $dropout"); + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A DENYOUT $ethdevout -p $proto --dport $dport -d $ip -j $dropout"); + } + } + } else { + if ($iptype == 6) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -A DENYOUT $eth6devout -d $ip -j $dropout"); + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -A DENYOUT $ethdevout -d $ip -j $dropout"); + } + } + } + + if ($config{CF_ENABLE} and $cftemp) {$comment .= " (CF_ENABLE)"} + + sysopen (my $OUT, "/var/lib/csf/csf.tempban", O_WRONLY | O_APPEND | O_CREAT) or &error(__LINE__,"Error: Can't append out file: $!"); + flock ($OUT, LOCK_EX); + print $OUT time."|$ip|$port|$inout|$timeout|$comment\n"; + close ($OUT); + + if ($port eq "") {$port = "*"} + if ($inout eq "in") {$inout = "inbound"} + if ($inout eq "out") {$inout = "outbound"} + if ($inout eq "inout") {$inout = "in and outbound"} + print "csf: $ip blocked on port $port for $timeout seconds $inout\n"; + return; +} +# end dotempdeny +############################################################################### +# start dotempallow +sub dotempallow { + my $cftemp = shift; + my ($ip,$timeout,$portdir) = split(/\s/,$input{argument},3); + my $inout = "inout"; + my $port = ""; + if ($timeout =~ /^(\d*)(m|h|d)/i) { + my $secs = $1; + my $dur = $2; + if ($dur eq "m") {$timeout = $secs * 60} + elsif ($dur eq "h") {$timeout = $secs * 60 * 60} + elsif ($dur eq "d") {$timeout = $secs * 60 * 60 * 24} + else {$timeout = $secs} + } + + my $iptype = checkip(\$ip); + if ($iptype == 6 and !$config{IPV6}) { + print "failed: [$ip] is valid IPv6 but IPV6 is not enabled in csf.conf\n"; + } + + unless ($iptype) { + print "csf: [$ip] is not a valid PUBLIC IP\n"; + return; + } + if ($timeout =~ /\D/) { + $portdir = join(" ",$timeout,$portdir); + $timeout = 0; + } + + if ($portdir =~ /\-d\s*in/i) {$inout = "in"} + if ($portdir =~ /\-d\s*out/i) {$inout = "out"} + if ($portdir =~ /\-d\s*inout/i) {$inout = "inout"} + if ($portdir =~ /\-p\s*([\w\,\*\;]+)/) {$port = $1} + my $comment = $portdir; + $comment =~ s/\-d\s*out//ig; + $comment =~ s/\-d\s*inout//ig; + $comment =~ s/\-d\s*in//ig; + $comment =~ s/\-p\s*[\w\,\*\;]+//ig; + $comment =~ s/^\s*|\s*$//g; + if ($comment eq "") {$comment = "Manually added: ".iplookup($ip)} + + my @allow = slurp("/etc/csf/csf.allow"); + foreach my $line (@allow) { + if ($line =~ /^Include\s*(.*)$/) { + my @incfile = slurp($1); + push @allow,@incfile; + } + } + if (grep {$_ =~ /^$ip\b/} @allow) { + print "csf: $ip is already permanently allowed\n"; + exit 0; + } + open (my $IN, "<", "/var/lib/csf/csf.tempallow"); + flock ($IN, LOCK_SH); + @allow = <$IN>; + close ($IN); + chomp @allow; + if (grep {$_ =~ /\b$ip\|$port\|\b/} @allow) { + print "csf: $ip is already temporarily allowed\n"; + exit 0; + } + + if ($timeout < 2) {$timeout = 3600} + if ($port =~ /\*/) {$port = ""} + + &getethdev; + + if ($inout =~ /in/) { + if ($port) { + foreach my $dport (split(/\,/,$port)) { + my ($tport,$proto) = split(/\;/,$dport); + $dport = $tport; + if ($proto eq "") {$proto = "tcp"} + if ($iptype == 6) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I ALLOWIN $eth6devin -p $proto --dport $dport -s $ip -j $accept"); + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I ALLOWIN $ethdevin -p $proto --dport $dport -s $ip -j $accept"); + } + } + } else { + if ($iptype == 6) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I ALLOWIN $eth6devin -s $ip -j $accept"); + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I ALLOWIN $ethdevin -s $ip -j $accept"); + } + } + } + if ($inout =~ /out/) { + if ($port) { + foreach my $dport (split(/\,/,$port)) { + my ($tport,$proto) = split(/\;/,$dport); + $dport = $tport; + if ($proto eq "") {$proto = "tcp"} + if ($iptype == 6) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I ALLOWOUT $eth6devout -p $proto --dport $dport -d $ip -j $accept"); + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I ALLOWOUT $ethdevout -p $proto --dport $dport -d $ip -j $accept"); + } + } + } else { + if ($iptype == 6) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -I ALLOWOUT $eth6devout -d $ip -j $accept"); + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -I ALLOWOUT $ethdevout -d $ip -j $accept"); + } + } + } + + if ($config{CF_ENABLE} and $cftemp) {$comment .= " (CF_ENABLE)"} + + sysopen (my $OUT, "/var/lib/csf/csf.tempallow", O_WRONLY | O_APPEND | O_CREAT) or &error(__LINE__,"Error: Can't append out file: $!"); + flock ($OUT, LOCK_EX); + print $OUT time."|$ip|$port|$inout|$timeout|$comment\n"; + close ($OUT); + + if ($port eq "") {$port = "*"} + if ($inout eq "in") {$inout = "inbound"} + if ($inout eq "out") {$inout = "outbound"} + if ($inout eq "inout") {$inout = "in and outbound"} + print "csf: $ip allowed on port $port for $timeout seconds $inout\n"; + return; +} +# end dotempallow +############################################################################### +# start dotemprm +sub dotemprm { + my $ip = $input{argument}; + + if ($ip eq "") { + print "csf: No IP specified\n"; + return; + } + + my $iptype = checkip(\$ip); + if ($iptype == 6 and !$config{IPV6}) { + print "failed: [$ip] is valid IPv6 but IPV6 is not enabled in csf.conf\n"; + } + + unless ($iptype) { + print "csf: [$ip] is not a valid PUBLIC IP\n"; + return; + } + &getethdev; + if (! -z "/var/lib/csf/csf.tempban") { + my $unblock = 0; + sysopen (my $TEMPBAN, "/var/lib/csf/csf.tempban", O_RDWR | O_CREAT); + flock ($TEMPBAN, LOCK_EX); + my @data = <$TEMPBAN>; + chomp @data; + + my @newdata; + foreach my $line (@data) { + my ($time,$thisip,$port,$inout,$timeout,$message) = split(/\|/,$line); + if ($thisip eq $ip) { + my $dropin = $config{DROP}; + my $dropout = $config{DROP_OUT}; + if ($config{DROP_IP_LOGGING}) {$dropin = "LOGDROPIN"} + if ($config{DROP_OUT_LOGGING}) {$dropout = "LOGDROPOUT"} + + if ($inout =~ /in/) { + if ($port) { + foreach my $dport (split(/\,/,$port)) { + my ($tport,$proto) = split(/\;/,$dport); + $dport = $tport; + if ($proto eq "") {$proto = "tcp"} + if ($iptype == 6) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D DENYIN $eth6devin -p $proto --dport $dport -s $ip -j $dropin"); + if ($messengerports{$dport} and $config{MESSENGER6} and $config{MESSENGER_TEMP}) {&domessenger($ip,"D",$dport)} + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D DENYIN $ethdevin -p $proto --dport $dport -s $ip -j $dropin"); + if ($messengerports{$dport} and $config{MESSENGER} and $config{MESSENGER_TEMP}) {&domessenger($ip,"D",$dport)} + } + } + } else { + if ($iptype == 6) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D DENYIN $eth6devin -s $ip -j $dropin"); + if ($config{MESSENGER6} and $config{MESSENGER_TEMP}) {&domessenger($ip,"D")} + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D DENYIN $ethdevin -s $ip -j $dropin"); + if ($config{MESSENGER} and $config{MESSENGER_TEMP}) {&domessenger($ip,"D")} + } + } + } + if ($inout =~ /out/) { + if ($port) { + foreach my $dport (split(/\,/,$port)) { + my ($tport,$proto) = split(/\;/,$dport); + $dport = $tport; + if ($proto eq "") {$proto = "tcp"} + if ($iptype == 6) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D DENYOUT $eth6devout -p $proto --dport $dport -d $ip -j $dropout"); + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D DENYOUT $ethdevout -p $proto --dport $dport -d $ip -j $dropout"); + } + } + } else { + if ($iptype == 6) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D DENYOUT $eth6devout -d $ip -j $dropout"); + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D DENYOUT $ethdevout -d $ip -j $dropout"); + } + } + } + if ($config{CF_ENABLE} and $message =~ /\(CF_ENABLE\)/) {ConfigServer::CloudFlare::action("remove",$ip,$config{CF_BLOCK})} + print "csf: $ip temporary block removed\n"; + $unblock = 1; + } else { + push @newdata, $line; + } + } + seek ($TEMPBAN, 0, 0); + truncate ($TEMPBAN, 0); + foreach my $line (@newdata) {print $TEMPBAN "$line\n"} + close ($TEMPBAN); + unless ($unblock) { + print "csf: $ip not found in temporary bans\n"; + } + } else { + print "csf: There are no temporary IP bans\n"; + } + if (! -z "/var/lib/csf/csf.tempallow") { + my $unblock = 0; + sysopen (my $TEMPALLOW, "/var/lib/csf/csf.tempallow", O_RDWR | O_CREAT); + flock ($TEMPALLOW, LOCK_EX); + my @data = <$TEMPALLOW>; + chomp @data; + + my @newdata; + foreach my $line (@data) { + my ($time,$thisip,$port,$inout,$timeout,$message) = split(/\|/,$line); + if ($thisip eq $ip) { + if ($inout =~ /in/) { + if ($port) { + foreach my $dport (split(/\,/,$port)) { + my ($tport,$proto) = split(/\;/,$dport); + $dport = $tport; + if ($proto eq "") {$proto = "tcp"} + if ($iptype == 6) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D ALLOWIN $eth6devin -p $proto --dport $dport -s $ip -j $accept"); + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D ALLOWIN $ethdevin -p $proto --dport $dport -s $ip -j $accept"); + } + } + } else { + if ($iptype == 6) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D ALLOWIN $eth6devin -s $ip -j $accept"); + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D ALLOWIN $ethdevin -s $ip -j $accept"); + } + } + } + if ($inout =~ /out/) { + if ($port) { + foreach my $dport (split(/\,/,$port)) { + my ($tport,$proto) = split(/\;/,$dport); + $dport = $tport; + if ($proto eq "") {$proto = "tcp"} + if ($iptype == 6) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D ALLOWOUT $eth6devout -p $proto --dport $dport -d $ip -j $accept"); + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D ALLOWOUT $ethdevout -p $proto --dport $dport -d $ip -j $accept"); + } + } + } else { + if ($iptype == 6) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D ALLOWOUT $eth6devout -d $ip -j $accept"); + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D ALLOWOUT $ethdevout -d $ip -j $accept"); + } + } + } + if ($config{CF_ENABLE} and $message =~ /\(CF_ENABLE\)/) {ConfigServer::CloudFlare::action("remove",$ip,"whitelist")} + print "csf: $ip temporary allow removed\n"; + $unblock = 1; + } else { + push @newdata, $line; + } + } + seek ($TEMPALLOW, 0, 0); + truncate ($TEMPALLOW, 0); + foreach my $line (@newdata) {print $TEMPALLOW "$line\n"} + close ($TEMPALLOW); + unless ($unblock) { + print "csf: $ip not found in temporary allows\n"; + } + } else { + print "csf: There are no temporary IP allows\n"; + } + return; +} +# end dotemprm +############################################################################### +# start dotemprmd +sub dotemprmd { + my $ip = $input{argument}; + + if ($ip eq "") { + print "csf: No IP specified\n"; + return; + } + + my $iptype = checkip(\$ip); + if ($iptype == 6 and !$config{IPV6}) { + print "failed: [$ip] is valid IPv6 but IPV6 is not enabled in csf.conf\n"; + } + + unless ($iptype) { + print "csf: [$ip] is not a valid PUBLIC IP\n"; + return; + } + &getethdev; + if (! -z "/var/lib/csf/csf.tempban") { + my $unblock = 0; + sysopen (my $TEMPBAN, "/var/lib/csf/csf.tempban", O_RDWR | O_CREAT); + flock ($TEMPBAN, LOCK_EX); + my @data = <$TEMPBAN>; + chomp @data; + + my @newdata; + foreach my $line (@data) { + my ($time,$thisip,$port,$inout,$timeout,$message) = split(/\|/,$line); + if ($thisip eq $ip) { + my $dropin = $config{DROP}; + my $dropout = $config{DROP_OUT}; + if ($config{DROP_IP_LOGGING}) {$dropin = "LOGDROPIN"} + if ($config{DROP_OUT_LOGGING}) {$dropout = "LOGDROPOUT"} + + if ($inout =~ /in/) { + if ($port) { + foreach my $dport (split(/\,/,$port)) { + my ($tport,$proto) = split(/\;/,$dport); + $dport = $tport; + if ($proto eq "") {$proto = "tcp"} + if ($iptype == 6) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D DENYIN $eth6devin -p $proto --dport $dport -s $ip -j $dropin"); + if ($messengerports{$dport} and $config{MESSENGER6} and $config{MESSENGER_TEMP}) {&domessenger($ip,"D",$dport)} + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D DENYIN $ethdevin -p $proto --dport $dport -s $ip -j $dropin"); + if ($messengerports{$dport} and $config{MESSENGER} and $config{MESSENGER_TEMP}) {&domessenger($ip,"D",$dport)} + } + } + } else { + if ($iptype == 6) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D DENYIN $eth6devin -s $ip -j $dropin"); + if ($config{MESSENGER6} and $config{MESSENGER_TEMP}) {&domessenger($ip,"D")} + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D DENYIN $ethdevin -s $ip -j $dropin"); + if ($config{MESSENGER} and $config{MESSENGER_TEMP}) {&domessenger($ip,"D")} + } + } + } + if ($inout =~ /out/) { + if ($port) { + foreach my $dport (split(/\,/,$port)) { + my ($tport,$proto) = split(/\;/,$dport); + $dport = $tport; + if ($proto eq "") {$proto = "tcp"} + if ($iptype == 6) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D DENYOUT $eth6devout -p $proto --dport $dport -d $ip -j $dropout"); + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D DENYOUT $ethdevout -p $proto --dport $dport -d $ip -j $dropout"); + } + } + } else { + if ($iptype == 6) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D DENYOUT $eth6devout -d $ip -j $dropout"); + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D DENYOUT $ethdevout -d $ip -j $dropout"); + } + } + } + if ($config{CF_ENABLE} and $message =~ /\(CF_ENABLE\)/) {ConfigServer::CloudFlare::action("remove",$ip,$config{CF_BLOCK})} + print "csf: $ip temporary block removed\n"; + $unblock = 1; + } else { + push @newdata, $line; + } + } + seek ($TEMPBAN, 0, 0); + truncate ($TEMPBAN, 0); + foreach my $line (@newdata) {print $TEMPBAN "$line\n"} + close ($TEMPBAN); + unless ($unblock) { + print "csf: $ip not found in temporary bans\n"; + } + } else { + print "csf: There are no temporary IP bans\n"; + } + + return; +} +# end dotemprmd +############################################################################### +# start dotemprma +sub dotemprma { + my $ip = $input{argument}; + + if ($ip eq "") { + print "csf: No IP specified\n"; + return; + } + + my $iptype = checkip(\$ip); + if ($iptype == 6 and !$config{IPV6}) { + print "failed: [$ip] is valid IPv6 but IPV6 is not enabled in csf.conf\n"; + } + + unless ($iptype) { + print "csf: [$ip] is not a valid PUBLIC IP\n"; + return; + } + &getethdev; + if (! -z "/var/lib/csf/csf.tempallow") { + my $unblock = 0; + sysopen (my $TEMPALLOW, "/var/lib/csf/csf.tempallow", O_RDWR | O_CREAT); + flock ($TEMPALLOW, LOCK_EX); + my @data = <$TEMPALLOW>; + chomp @data; + + my @newdata; + foreach my $line (@data) { + my ($time,$thisip,$port,$inout,$timeout,$message) = split(/\|/,$line); + if ($thisip eq $ip) { + if ($inout =~ /in/) { + if ($port) { + foreach my $dport (split(/\,/,$port)) { + my ($tport,$proto) = split(/\;/,$dport); + $dport = $tport; + if ($proto eq "") {$proto = "tcp"} + if ($iptype == 6) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D ALLOWIN $eth6devin -p $proto --dport $dport -s $ip -j $accept"); + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D ALLOWIN $ethdevin -p $proto --dport $dport -s $ip -j $accept"); + } + } + } else { + if ($iptype == 6) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D ALLOWIN $eth6devin -s $ip -j $accept"); + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D ALLOWIN $ethdevin -s $ip -j $accept"); + } + } + } + if ($inout =~ /out/) { + if ($port) { + foreach my $dport (split(/\,/,$port)) { + my ($tport,$proto) = split(/\;/,$dport); + $dport = $tport; + if ($proto eq "") {$proto = "tcp"} + if ($iptype == 6) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D ALLOWOUT $eth6devout -p $proto --dport $dport -d $ip -j $accept"); + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D ALLOWOUT $ethdevout -p $proto --dport $dport -d $ip -j $accept"); + } + } + } else { + if ($iptype == 6) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D ALLOWOUT $eth6devout -d $ip -j $accept"); + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D ALLOWOUT $ethdevout -d $ip -j $accept"); + } + } + } + if ($config{CF_ENABLE} and $message =~ /\(CF_ENABLE\)/) {ConfigServer::CloudFlare::action("remove",$ip,"whitelist")} + print "csf: $ip temporary allow removed\n"; + $unblock = 1; + } else { + push @newdata, $line; + } + } + seek ($TEMPALLOW, 0, 0); + truncate ($TEMPALLOW, 0); + foreach my $line (@newdata) {print $TEMPALLOW "$line\n"} + close ($TEMPALLOW); + unless ($unblock) { + print "csf: $ip not found in temporary allows\n"; + } + } else { + print "csf: There are no temporary IP allows\n"; + } + return; +} +# end dotemprma +############################################################################### +# start dotempf +sub dotempf { + &getethdev; + if (! -z "/var/lib/csf/csf.tempban") { + sysopen (my $TEMPBAN, "/var/lib/csf/csf.tempban", O_RDWR | O_CREAT); + flock ($TEMPBAN, LOCK_EX); + my @data = <$TEMPBAN>; + chomp @data; + + foreach my $line (@data) { + if ($line eq "") {next} + my ($time,$ip,$port,$inout,$timeout,$message) = split(/\|/,$line); + my $iptype = checkip(\$ip); + if ($iptype == 6 and !$config{IPV6}) {next} + my $dropin = $config{DROP}; + my $dropout = $config{DROP_OUT}; + if ($config{DROP_IP_LOGGING}) {$dropin = "LOGDROPIN"} + if ($config{DROP_OUT_LOGGING}) {$dropout = "LOGDROPOUT"} + + if ($inout =~ /in/) { + if ($port) { + foreach my $dport (split(/\,/,$port)) { + my ($tport,$proto) = split(/\;/,$dport); + $dport = $tport; + if ($proto eq "") {$proto = "tcp"} + if ($iptype == 6) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D DENYIN $eth6devin -p $proto --dport $dport -s $ip -j $dropin"); + if ($messengerports{$dport} and $config{MESSENGER6} and $config{MESSENGER_TEMP}) {&domessenger($ip,"D",$dport)} + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D DENYIN $ethdevin -p $proto --dport $dport -s $ip -j $dropin"); + if ($messengerports{$dport} and $config{MESSENGER} and $config{MESSENGER_TEMP}) {&domessenger($ip,"D",$dport)} + } + } + } else { + if ($iptype == 6) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D DENYIN $eth6devin -s $ip -j $dropin"); + if ($config{MESSENGER6} and $config{MESSENGER_TEMP}) {&domessenger($ip,"D")} + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D DENYIN $ethdevin -s $ip -j $dropin"); + if ($config{MESSENGER} and $config{MESSENGER_TEMP}) {&domessenger($ip,"D")} + } + } + } + if ($inout =~ /out/) { + if ($port) { + foreach my $dport (split(/\,/,$port)) { + my ($tport,$proto) = split(/\;/,$dport); + $dport = $tport; + if ($proto eq "") {$proto = "tcp"} + if ($iptype == 6) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D DENYOUT $eth6devout -p $proto --dport $dport -d $ip -j $dropout"); + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D DENYOUT $ethdevout -p $proto --dport $dport -d $ip -j $dropout"); + } + } + } else { + if ($iptype == 6) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D DENYOUT $eth6devout -d $ip -j $dropout"); + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D DENYOUT $ethdevout -d $ip -j $dropout"); + } + } + } + if ($config{CF_ENABLE} and $message =~ /\(CF_ENABLE\)/) {ConfigServer::CloudFlare::action("remove",$ip,$config{CF_BLOCK})} + print "csf: $ip temporary block removed\n"; + } + seek ($TEMPBAN, 0, 0); + truncate ($TEMPBAN, 0); + close ($TEMPBAN); + } else { + print "csf: There are no temporary IP bans\n"; + } + if (! -z "/var/lib/csf/csf.tempallow") { + sysopen (my $TEMPALLOW, "/var/lib/csf/csf.tempallow", O_RDWR | O_CREAT); + flock ($TEMPALLOW, LOCK_EX); + my @data = <$TEMPALLOW>; + chomp @data; + + foreach my $line (@data) { + if ($line eq "") {next} + my ($time,$ip,$port,$inout,$timeout,$message) = split(/\|/,$line); + my $iptype = checkip(\$ip); + if ($iptype == 6 and !$config{IPV6}) {next} + if ($inout =~ /in/) { + if ($port) { + foreach my $dport (split(/\,/,$port)) { + my ($tport,$proto) = split(/\;/,$dport); + $dport = $tport; + if ($proto eq "") {$proto = "tcp"} + if ($iptype == 6) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D ALLOWIN $eth6devin -p $proto --dport $dport -s $ip -j $accept"); + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D ALLOWIN $ethdevin -p $proto --dport $dport -s $ip -j $accept"); + } + } + } else { + if ($iptype == 6) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D ALLOWIN $eth6devin -s $ip -j $accept"); + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D ALLOWIN $ethdevin -s $ip -j $accept"); + } + } + } + if ($inout =~ /out/) { + if ($port) { + foreach my $dport (split(/\,/,$port)) { + my ($tport,$proto) = split(/\;/,$dport); + $dport = $tport; + if ($proto eq "") {$proto = "tcp"} + if ($iptype == 6) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D ALLOWOUT $eth6devout -p $proto --dport $dport -d $ip -j $accept"); + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D ALLOWOUT $ethdevout -p $proto --dport $dport -d $ip -j $accept"); + } + } + } else { + if ($iptype == 6) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -D ALLOWOUT $eth6devout -d $ip -j $accept"); + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -D ALLOWOUT $ethdevout -d $ip -j $accept"); + } + } + } + if ($config{CF_ENABLE} and $message =~ /\(CF_ENABLE\)/) {ConfigServer::CloudFlare::action("remove",$ip,"whitelist")} + print "csf: $ip temporary allow removed\n"; + } + seek ($TEMPALLOW, 0, 0); + truncate ($TEMPALLOW, 0); + close ($TEMPALLOW); + } else { + print "csf: There are no temporary IP allows\n"; + } + return; +} +# end dotempf +############################################################################### +# start dowatch +sub dowatch { + print "csf: --watch, -w is no longer supported. Use --trace instead\n"; + return; +} +# end dowatch +############################################################################### +# start dotrace +sub dotrace { + my $cmd = $ARGV[1]; + my $ip = $ARGV[2]; + + if ($ip eq "") { + print "csf: No IP specified\n"; + return; + } + + my $checkip = checkip(\$ip); + unless ($checkip) { + print "csf: [$ip] is not a valid PUBLIC IP\n"; + return; + } + + if ($cmd eq "add") { + if ($checkip == 4) { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -t raw -I PREROUTING -p tcp --syn --source $ip -j TRACE"); + } else { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -t raw -I PREROUTING -p tcp --syn --source $ip -j TRACE"); + } + print "csf: Added trace for $ip\n"; + } + elsif ($cmd eq "remove") { + if ($checkip == 4) { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -t raw -D PREROUTING -p tcp --syn --source $ip -j TRACE"); + } else { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -t raw -D PREROUTING -p tcp --syn --source $ip -j TRACE"); + } + print "csf: Removed trace for $ip\n"; + } + else { + print "csf: Error, use [add|remove] [ip]\n"; + } + + return; +} +# end dotrace +############################################################################### +# start dologrun +sub dologrun { + if ($config{LOGSCANNER}) { + open (my $OUT, ">", "/var/lib/csf/csf.logrun") or &error(__LINE__,"Could not create /var/lib/csf/csf.logrun: $!"); + flock ($OUT, LOCK_EX); + close ($OUT); + } else { + print "Option LOGSCANNER needs to be enabled in csf.conf for this feature\n"; + } + return; +} +# end dologrun +############################################################################### +# start domessenger +sub domessenger { + my $ip = shift; + my $delete = shift; + my $ports = shift; + if ($ports eq "") {$ports = "$config{MESSENGER_HTTPS_IN},$config{MESSENGER_HTML_IN},$config{MESSENGER_TEXT_IN}"} + my $iptype = checkip(\$ip); + + if ($config{CC_MESSENGER_ALLOW} or $config{CC_MESSENGER_DENY}) { + my ($cc,$asn) = iplookup($ip,1); + ($asn,undef) = split(/\s+/,$asn); + + if ($config{CC_MESSENGER_ALLOW}) { + my $allow = 0; + if ($cc ne "" and $config{CC_MESSENGER_ALLOW} =~ /$cc/i) {$allow = 1} + if ($asn ne "" and $config{CC_MESSENGER_ALLOW} =~ /$asn/i) {$allow = 1} + unless ($allow) {return 1} + } + + if ($config{CC_MESSENGER_DENY}) { + if ($cc ne "" and $config{CC_MESSENGER_DENY} =~ /$cc/i) {return 1} + if ($asn ne "" and $config{CC_MESSENGER_DENY} =~ /$asn/i) {return 1} + } + } + + my $del = "-A"; + if ($delete eq "D") {$del = "-D"} + + my %textin; + my %htmlin; + my %httpsin; + foreach my $port (split(/\,/,$config{MESSENGER_HTTPS_IN})) {$httpsin{$port} = 1} + foreach my $port (split(/\,/,$config{MESSENGER_HTML_IN})) {$htmlin{$port} = 1} + foreach my $port (split(/\,/,$config{MESSENGER_TEXT_IN})) {$textin{$port} = 1} + + my $textports; + my $htmlports; + my $httpsports; + foreach my $port (split(/\,/,$ports)) { + if ($httpsin{$port}) { + if ($httpsports eq "") {$httpsports = "$port"} else {$httpsports .= ",$port"} + } + if ($htmlin{$port}) { + if ($htmlports eq "") {$htmlports = "$port"} else {$htmlports .= ",$port"} + } + if ($textin{$port}) { + if ($textports eq "") {$textports = "$port"} else {$textports .= ",$port"} + } + } + + if ($config{LF_IPSET}) { + if ($ip =~ /^-m set/) { + my $ip6 = $ip; + $ip6 =~ s/MESSENGER src/MESSENGER_6 src/g; + if ($httpsports ne "") { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -t nat -A PREROUTING $ethdevin -p tcp $ip -m multiport --dports $httpsports -j REDIRECT --to-ports $config{MESSENGER_HTTPS}"); + if ($config{MESSENGER6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -t nat -A PREROUTING $ethdevin -p tcp $ip6 -m multiport --dports $httpsports -j REDIRECT --to-ports $config{MESSENGER_HTTPS}"); + } + } + if ($htmlports ne "") { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -t nat -A PREROUTING $ethdevin -p tcp $ip -m multiport --dports $htmlports -j REDIRECT --to-ports $config{MESSENGER_HTML}"); + if ($config{MESSENGER6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -t nat -A PREROUTING $ethdevin -p tcp $ip6 -m multiport --dports $htmlports -j REDIRECT --to-ports $config{MESSENGER_HTML}"); + } + } + if ($textports ne "") { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -t nat -A PREROUTING $ethdevin -p tcp $ip -m multiport --dports $textports -j REDIRECT --to-ports $config{MESSENGER_TEXT}"); + if ($config{MESSENGER6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -t nat -A PREROUTING $ethdevin -p tcp $ip6 -m multiport --dports $textports -j REDIRECT --to-ports $config{MESSENGER_TEXT}"); + } + } + } else { + if ($delete eq "D") { + if ($iptype == 4) { + &ipsetdel("MESSENGER",$ip); + } + if ($iptype == 6 and $config{MESSENGER6}) { + &ipsetdel("MESSENGER_6",$ip); + } + } else { + if ($iptype == 4) { + &ipsetadd("MESSENGER",$ip); + } + if ($iptype == 6 and $config{MESSENGER6}) { + &ipsetadd("MESSENGER_6",$ip); + } + } + } + } else { + if ($httpsports ne "") { + if ($iptype == 4) { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -t nat $del PREROUTING $ethdevin -p tcp -s $ip -m multiport --dports $httpsports -j REDIRECT --to-ports $config{MESSENGER_HTTPS}"); + } + if ($iptype == 6 and $config{MESSENGER6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -t nat $del PREROUTING $ethdevin -p tcp -s $ip -m multiport --dports $httpsports -j REDIRECT --to-ports $config{MESSENGER_HTTPS}"); + } + } + if ($htmlports ne "") { + if ($iptype == 4) { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -t nat $del PREROUTING $ethdevin -p tcp -s $ip -m multiport --dports $htmlports -j REDIRECT --to-ports $config{MESSENGER_HTML}"); + } + if ($iptype == 6 and $config{MESSENGER6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -t nat $del PREROUTING $ethdevin -p tcp -s $ip -m multiport --dports $htmlports -j REDIRECT --to-ports $config{MESSENGER_HTML}"); + } + } + if ($textports ne "") { + if ($iptype == 4) { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} $verbose -t nat $del PREROUTING $ethdevin -p tcp -s $ip -m multiport --dports $textports -j REDIRECT --to-ports $config{MESSENGER_TEXT}"); + } + if ($iptype == 6 and $config{MESSENGER6}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} $verbose -t nat $del PREROUTING $ethdevin -p tcp -s $ip -m multiport --dports $textports -j REDIRECT --to-ports $config{MESSENGER_TEXT}"); + } + } + } + return; +} +# end domessenger +############################################################################### +# start domail +sub domail { + my $output = ConfigServer::ServerCheck::report(); + + if ($input{argument}) { + my $message = "From: root\n"; + $message .= "To: root\n"; + $message .= "Subject: Server Check on [hostname]\n"; + $message .= "MIME-Version: 1.0\n"; + $message .= "Content-Type: text/html\n"; + $message .= "\n"; + $message .= $output; + my @message = split(/\n/,$message); + ConfigServer::Sendmail::relay($input{argument}, "", @message); + } else { + print $output; + print "\n"; + } + return; +} +# end domail +############################################################################### +# start dorbls +sub dorbls { + my ($failures, $output) = ConfigServer::RBLCheck::report(1,"",0); + my $failure_s = "failure"; + if ($failures ne 1) {$failure_s .= "s"} + if ($failures eq "") {$failures = 0} + if ($input{argument}) { + my $message = "From: root\n"; + $message .= "To: root\n"; + $message .= "Subject: RBL Check on [hostname]: [$failures] $failure_s\n"; + $message .= "MIME-Version: 1.0\n"; + $message .= "Content-Type: text/html\n"; + $message .= "\n"; + $message .= $output; + my @message = split(/\n/,$message); + ConfigServer::Sendmail::relay($input{argument}, "", @message); + } else { + print $output; + print "\n"; + } + return; +} +# end dorbls +############################################################################### +# start doprofile +sub doprofile { + my $cmd = $ARGV[1]; + my $profile1 = $ARGV[2]; + my $profile2 = $ARGV[3]; + my $stamp = time; + + $profile1 =~ s/\W/_/g; + $profile2 =~ s/\W/_/g; + + if ($cmd eq "list") { + my @profiles = sort glob("/usr/local/csf/profiles/*"); + my @backups = reverse glob("/var/lib/csf/backup/*"); + print "\n"; + print "Configuration Profiles\n"; + print "======================\n"; + foreach my $profile (@profiles) { + my ($file, undef) = fileparse($profile); + $file =~ s/\.conf$//; + print "$file\n"; + } + print "\n"; + + print "Configuration Backups\n"; + print "=====================\n"; + foreach my $backup (@backups) { + my ($file, undef) = fileparse($backup); + my ($stamp,undef) = split(/_/,$file); + print $file." (".localtime($stamp).")\n"; + } + print "\n"; + } + elsif ($cmd eq "backup") { + unless ($profile1) {$profile1 = "backup"} + print "Creating backup...\n"; + system("/bin/cp","-avf","/etc/csf/csf.conf","/var/lib/csf/backup/${stamp}_${profile1}"); + } + elsif ($cmd eq "restore") { + if (-e "/var/lib/csf/backup/$profile1") { + print "Restoring backup...\n"; + system("/bin/cp","-avf","/var/lib/csf/backup/${profile1}","/etc/csf/csf.conf"); + print "You should now restart csf and then lfd\n"; + } else { + print "File [$profile1] not found in /var/lib/csf/backup/\n"; + } + } + elsif ($cmd eq "apply") { + if (-e "/usr/local/csf/profiles/${profile1}.conf") { + my %apply; + print "Creating backup...\n"; + system("/bin/cp","-avf","/etc/csf/csf.conf","/var/lib/csf/backup/${stamp}_pre_${profile1}"); + print "Applying profile...\n"; + open (my $IN, "<", "/usr/local/csf/profiles/${profile1}.conf") or die $!; + flock ($IN, LOCK_SH) or die $!; + my @applyconfig = <$IN>; + close ($IN); + chomp @applyconfig; + foreach my $line (@applyconfig) { + if ($line =~ /^\#/) {next} + if ($line !~ /=/) {next} + my ($name,$value) = split (/=/,$line,2); + $name =~ s/\s//g; + if ($value =~ /\"(.*)\"/) {$value = $1} + $apply{$name} = $value; + } + + sysopen (my $CONF, "/etc/csf/csf.conf", O_RDWR | O_CREAT) or die "Unable to open file: $!"; + flock ($CONF, LOCK_SH); + my @confdata = <$CONF>; + close ($CONF); + chomp @confdata; + + sysopen (my $OUT, "/etc/csf/csf.conf", O_WRONLY | O_CREAT) or die "Unable to open file: $!"; + flock ($OUT, LOCK_EX); + seek ($OUT, 0, 0); + truncate ($OUT, 0); + for (my $x = 0; $x < @confdata;$x++) { + if (($confdata[$x] !~ /^\#/) and ($confdata[$x] =~ /=/)) { + my ($name,$value) = split (/=/,$confdata[$x],2); + $name =~ s/\s//g; + if ($value =~ /\"(.*)\"/) {$value = $1} + if (defined $apply{$name} and ($apply{$name} ne $value)) {$value = $apply{$name}} + print $OUT "$name = \"$value\"\n"; + } else { + print $OUT "$confdata[$x]\n"; + } + } + close ($OUT); + + print "[$profile1] has been applied. You should now restart csf and then lfd\n"; + } else { + print "[$profile1] is not a valid profile\n"; + } + } + elsif ($cmd eq "keep") { + if ($profile1 =~ /^\d+$/) { + my @backups = reverse glob("/var/lib/csf/backup/*"); + for ($profile1..(@backups -1)) { + system("/bin/rm","-fv",$backups[$_]); + } + } else { + print "You must specify the number of backups to keep\n"; + } + } + elsif ($cmd eq "diff") { + my $firstfile = "/var/lib/csf/backup/$profile1"; + my $secondfile = "/var/lib/csf/backup/$profile2"; + if (-e "/usr/local/csf/profiles/${profile1}.conf") { + $firstfile = "/usr/local/csf/profiles/${profile1}.conf"; + } + if (-e "/usr/local/csf/profiles/${profile2}.conf") { + $secondfile = "/usr/local/csf/profiles/${profile2}.conf"; + } + if (-e $firstfile) { + if (-e $secondfile or $profile2 eq "" or $profile2 eq "current") { + my %config1; + open (my $IN, "<",$firstfile) or die $!; + flock ($IN, LOCK_SH) or die $!; + my @configdata = <$IN>; + close ($IN); + chomp @configdata; + foreach my $line (@configdata) { + if ($line =~ /^\#/) {next} + if ($line !~ /=/) {next} + my ($name,$value) = split (/=/,$line,2); + $name =~ s/\s//g; + if ($value =~ /\"(.*)\"/) {$value = $1} + $config1{$name} = $value; + } + + my $PROFILE; + if ($profile2 eq "" or $profile2 eq "current") { + $profile2 = "current"; + open ($PROFILE, "<", "/etc/csf/csf.conf") or die $!; + } else { + open ($PROFILE, "<", $secondfile) or die $!; + } + flock ($PROFILE, LOCK_SH) or die $!; + @configdata = sort <$PROFILE>; + close ($PROFILE); + chomp @configdata; + + print "[SETTING]\t[$profile1]\t[$profile2]\n\n"; + foreach my $line (@configdata) { + if ($line =~ /^\#/) {next} + if ($line !~ /=/) {next} + my ($name,$value) = split (/=/,$line,2); + $name =~ s/\s//g; + if ($value =~ /\"(.*)\"/) {$value = $1} + if (defined $config1{$name} and ($config1{$name} ne $value)) { + print "[$name]\t[$config1{$name}]\t[$value]\n"; + } + } + } else { + print "File [$profile2] not found in /var/lib/csf/backup/\n"; + } + } else { + print "File [$profile1] not found in /var/lib/csf/backup/\n"; + } + } + else { + print "Incorrect syntax for command\n"; + } + return; +} +# end doprofile +############################################################################### +# start doports +sub doports { + my ($fport,$fopen,$fconn,$fpid,$fexe,$fcmd); + format PORTS = +@<<<<<<<<< @<<< @<<<< @<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<... @* +$fport, $fopen,$fconn,$fpid, $fcmd, $fexe +. + local $~ = "PORTS"; + + print "Ports listening for external connections and the executables running behind them:\n"; + print "Port/Proto Open Conn PID/User Command Line Executable\n"; + my %listen = ConfigServer::Ports->listening; + my %ports = ConfigServer::Ports->openports; + foreach my $protocol (sort keys %listen) { + foreach my $port (sort {$a <=> $b} keys %{$listen{$protocol}}) { + foreach my $pid (sort {$a <=> $b} keys %{$listen{$protocol}{$port}}) { + $fport = "$port/$protocol"; + if ($ports{$protocol}{$port}) {$fopen = "4"} else {$fopen = "-"} + if ($config{IPV6} and $ports{$protocol."6"}{$port}) {$fopen .= "/6"} else {$fopen .= "/-"} + $fpid = "($pid/".$listen{$protocol}{$port}{$pid}{user}.")"; + $fexe = $listen{$protocol}{$port}{$pid}{exe}; + $fcmd = $listen{$protocol}{$port}{$pid}{cmd}; + $fconn = $listen{$protocol}{$port}{$pid}{conn}; + write; + } + } + } + return; +} +# end doports +############################################################################### +# start domessengerv2 +sub domessengerv2 { + print "csf - MESSENGERV2 /etc/apache2/conf.d/csf_messenger.conf regeneration:\n\n"; + ConfigServer::Messenger::messengerv2(); + print "\n...Done.\n"; + return; +} +# end domessengerv2 +############################################################################### +# start docloudflare +sub docloudflare { + my $cmd = $ARGV[1]; + my $setting = $ARGV[2]; + my $value = $ARGV[3]; + my $valuemore = $ARGV[4]; + my $valuelist; + my $valuemorelist; + foreach my $i (3..$#ARGV) {$valuelist .= $ARGV[$i]} + foreach my $i (4..$#ARGV) {$valuemorelist .= $ARGV[$i]} + + unless ($config{CF_ENABLE}) { + print "csf - CF_ENABLE must be enabled and CloudFlare access details configured to use these commands\n"; + exit 1; + } + + if ($cmd eq "list") { + my %modes; + unless ($setting eq "all" or $setting eq "block" or $setting eq "challenge" or $setting eq "whitelist") { + print "Invalid list type, must be: [block], [challenge], [whitelist] or [all]\n"; + exit 1; + } + my ($ip,$domain, $mode,$date,$comment); + format CLOUDFLARE = +@<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<< @<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<< @* +$ip, $domain, $mode, $date, $comment +. + local $~ = "CLOUDFLARE"; + + print "Target Local User Mode Date Notes\n"; + print "====== ========== ==== ==== =====\n"; + my @domains = ConfigServer::CloudFlare::action("getlist","","","",$valuelist); + foreach my $domainkey (@domains) { + foreach my $key (sort {$domainkey->{$a}{created_on} <=> $domainkey->{$b}{created_on}} keys %{$domainkey}) { + if ($domainkey->{$key}{success}) { + if ($setting eq "all" or $domainkey->{$key}{mode} eq $setting) { + $ip = $key; + $date = localtime($domainkey->{$key}{created_on}); + $comment = $domainkey->{$key}{notes}; + $domain = $domainkey->{$key}{domain}; + $mode = $domainkey->{$key}{mode}; + write; + } + } else { + print $domainkey->{$key}{domain}."\n"; + } + } + } + } + elsif ($cmd eq "add") { + my $mode; + if ($setting eq "block") {$mode = "block"} + elsif ($setting eq "challenge") {$mode = "challenge"} + elsif ($setting eq "whitelist") {$mode = "whitelist"} + else { + print "Invalid add type, must be: [block], [challenge] or [whitelist]\n"; + exit 1; + } + my $status = ConfigServer::CloudFlare::action("add",$value,$mode,"",$valuemorelist); + } + elsif ($cmd eq "del") { + my $status = ConfigServer::CloudFlare::action("del",$setting,"whitelist","",$valuelist); + } + elsif ($cmd eq "tempadd") { + my $mode; + if ($setting eq "deny") {$mode = "block"} + elsif ($setting eq "allow") {$mode = "whitelist"} + else { + print "Invalid tempadd type, must be: [deny], or [allow]\n"; + exit 1; + } + $input{argument} = "$value $config{CF_TEMP}"; + if ($setting eq "deny") { + my $status = ConfigServer::CloudFlare::action("deny",$value,$mode,"",$valuemorelist,1); + &dotempdeny("cf"); + } + elsif ($setting eq "allow") { + my $status = ConfigServer::CloudFlare::action("allow",$value,$mode,"",$valuemorelist,1); + &dotempallow("cf"); + } + } + else { + print "Invalid command, must be: [list], [remove], [add], or [tempadd]\n"; + exit 1; + } + + return; +} +# end docloudflare +############################################################################### +# start dographs +sub dographs { + my ($type, $dir) = split(/\s/,$input{argument}); + my %types = ("load" => 1, + "cpu" => 1, + "mem" => 1, + "net" => 1, + "disk" => 1, + "diskw" => 1, + "email" => 1, + "temp" => 1, + "mysqldata" => 1, + "mysqlqueries" => 1, + "mysqlslowqueries" => 1, + "mysqlconns" => 1, + "apachecpu" => 1, + "apacheconn" => 1, + "apachework" => 1); + if ($dir !~ /\/$/) {$dir .= "/"} + + unless ($config{ST_ENABLE}) { + print "ST_ENABLE is disabled\n"; + exit 1; + } + unless ($config{ST_SYSTEM}) { + print "ST_SYSTEM is disabled\n"; + exit 1; + } + if (!defined ConfigServer::ServerStats::init()) { + print "Perl module GD::Graph is not installed/working\n"; + exit 1; + } + + if ($type eq "" and $dir eq "") { + print "Valid graph types:\n"; + foreach my $key (keys %types) {print "$key "} + print "\n"; + print "Usage: csf [graph type] [directory]\n"; + exit 1; + } + + if ($type eq "" or !$types{$type}) { + print "Invalid graph type. Choose one of:\n"; + foreach my $key (keys %types) {print "$key "} + print "\n"; + print "Usage: csf [graph type] [directory]\n"; + exit 1; + } + if ($dir eq "" or !(-d $dir)) { + print "You must specify a valid directory in which to create the graphs and html pages\n"; + print "Usage: csf [graph type] [directory]\n"; + exit 1; + } + + print "Creating html pages and images...\n"; + + ConfigServer::ServerStats::charts($config{CC_LOOKUPS},$dir); + open (my $CHARTS, ">", $dir."/charts.html"); + flock ($CHARTS, LOCK_EX); + print $CHARTS ConfigServer::ServerStats::charts_html($config{CC_LOOKUPS},""); + close ($CHARTS); + + ConfigServer::ServerStats::graphs($type,$config{ST_SYSTEM_MAXDAYS},$dir); + open (my $GRAPHS, ">", $dir."/graphs.html"); + flock ($GRAPHS, LOCK_EX); + print $GRAPHS ConfigServer::ServerStats::graphs_html(""); + close ($GRAPHS); + + print "Created charts.html, graphs.html and their images in $dir\n"; + return; +} +# end dographs +############################################################################### +# start loadmodule +sub loadmodule { + my $module = shift; + my @output; + + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die}; + alarm(5); + my ($childin, $childout); + my $pid = open3($childin, $childout, $childout, $config{MODPROBE},$module); + @output = <$childout>; + waitpid ($pid, 0); + alarm(0); + }; + alarm(0); + + return @output; +} +# end loadmodule +############################################################################### +# start syscommand +sub syscommand { + my $line = shift; + my $command = shift; + my $force = shift; + my $status = 0; + my $iptableslock = 0; + if ($command =~ /^($config{IPTABLES}|$config{IP6TABLES})/) {$iptableslock = 1} + if ($faststart) { + if ($command =~ /^$config{IPTABLES}\s+(.*)$/) { + my $fastcmd = $1; + $fastcmd =~ s/-v//; + $fastcmd =~ s/--wait//; + if ($fastcmd =~ /-t\s+nat/) { + $fastcmd =~ s/-t\s+nat//; + push @faststart4nat,$fastcmd; + } else { + push @faststart4,$fastcmd; + } + } + if ($command =~ /^$config{IP6TABLES}\s+(.*)$/) { + my $fastcmd = $1; + $fastcmd =~ s/-v//; + $fastcmd =~ s/--wait//; + if ($fastcmd =~ /-t\s+nat/) { + $fastcmd =~ s/-t\s+nat//; + push @faststart6nat,$fastcmd; + } else { + push @faststart6,$fastcmd; + } + } + return; + } + + if ($config{VPS}) {$status = &checkvps} + + if ($status) { + &error($line,$status); + } else { + if ($config{DEBUG} >= 1) {print "debug[$line]: Command:$command\n";} + + if ($iptableslock) {&iptableslock("lock")} + my @output; + if ($iptableslock and $config{WAITLOCK}) { + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die "alarm\n"}; + alarm($config{WAITLOCK_TIMEOUT}); + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, $command); + @output = <$childout>; + waitpid ($cmdpid, 0); + alarm(0); + }; + alarm(0); + if ($@ eq "alarm\n") { + &error(__LINE__,"*Error* timeout after iptables --wait for $config{WAITLOCK_TIMEOUT} seconds - WAITLOCK"); + } + } else { + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, $command); + @output = <$childout>; + waitpid ($cmdpid, 0); + } + if ($iptableslock) {&iptableslock("unlock")} + + chomp @output; + if ($output[0] =~ /# Warning: iptables-legacy tables present/) {shift @output} + foreach my $line (@output) { + if ($line =~ /^Using intrapositioned negation/) {next} + print $line."\n";; + } + if ($output[0] =~ /(^iptables: Unknown error 4294967295)|(xtables lock)/ and !$config{WAITLOCK}) { + my $cnt = 0; + my $repeat = 6; + while ($cnt < $repeat) { + sleep 1; + if ($config{DEBUG} >= 1) {print "debug[$line]: Retry (".($cnt+1).") [$command] due to [$output[0]]"} + if ($iptableslock) {&iptableslock("lock")} + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, $command); + my @output = <$childout>; + waitpid ($cmdpid, 0); + if ($iptableslock) {&iptableslock("unlock")} + chomp @output; + if ($output[0] =~ /# Warning: iptables-legacy tables present/) {shift @output} + $cnt++; + if ($output[0] =~ /(^iptables: Unknown error 4294967295)|(xtables lock)/ and $cnt == $repeat) {&error($line,"Error processing command for line [$line] ($repeat times): [$output[0]]");} + unless ($output[0] =~ /(^iptables: Unknown error 4294967295)|(xtables lock)/) {$cnt = $repeat} + } + } + if ($output[0] =~ /^(iptables|xtables|Bad|Another)/ and ($config{TESTING} or $force)) { + if ($output[0] =~ /iptables: No chain\/target\/match by that name/) { + &error($line,"iptables command [$command] failed, you appear to be missing a required iptables module") + } else { + &error($line,"iptables command [$command] failed"); + } + } + if ($output[0] =~ /^(ip6tables|Bad|Another)/ and ($config{TESTING} or $force)) { + if ($output[0] =~ /ip6tables: No chain\/target\/match by that name/) { + &error($line,"ip6tables command [$command] failed, you appear to be missing a required ip6tables module") + } else { + &error($line,"ip6tables command [$command] failed"); + } + } + if ($output[0] =~ /xtables lock/) { + $warning .= "iptables command [$command] failed due to xtables lock, enable WAITLOCK in csf.conf\n\n"; + } + if ($output[0] =~ /^(iptables|xtables|ip6tables|Bad|Another)/) { + $warning .= "*ERROR* line:[$line]\nCommand:[$command]\nError:[$output[0]]\nYou should check through the main output carefully\n\n"; + } + } + return; +} +# end syscommand +############################################################################### +# start iptableslock +sub iptableslock { + my $lock = shift; + my $iptablesx = shift; + if ($lock eq "lock") { + sysopen ($IPTABLESLOCK, "/var/lib/csf/lock/command.lock", O_RDWR | O_CREAT); + flock ($IPTABLESLOCK, LOCK_EX); + autoflush $IPTABLESLOCK 1; + seek ($IPTABLESLOCK, 0, 0); + truncate ($IPTABLESLOCK, 0); + print $IPTABLESLOCK $$; + } else { + close ($IPTABLESLOCK); + } + return; +} +# end iptableslock +############################################################################### +# start checkvps +sub checkvps { + if (-e "/proc/user_beancounters" and !(-e "/proc/vz/version")) { + open (my $INVPS, "<", "/proc/user_beancounters"); + flock ($INVPS, LOCK_SH); + my @data = <$INVPS>; + close ($INVPS); + chomp @data; + + foreach my $line (@data) { + if ($line =~ /^\s*numiptent\s+(\d*)\s+(\d*)\s+(\d*)\s+(\d*)/) { + if ($1 > $4 - 10) {return "The VPS iptables rule limit (numiptent) is too low ($1/$4) - stopping firewall to prevent iptables blocking all connections"} + } + } + } + return 0; +} +# end checkvps +############################################################################### +# start modprobe +sub modprobe { + if (-e $config{MODPROBE}) { + my @modules = ("ip_tables","ipt_multiport","iptable_filter","ipt_limit","ipt_LOG","ipt_REJECT","ipt_conntrack","ip_conntrack","ip_conntrack_ftp","iptable_mangle","ipt_REDIRECT","iptable_nat"); + + unless (&loadmodule("xt_multiport")) { + @modules = ("ip_tables","xt_multiport","iptable_filter","xt_limit","ipt_LOG","ipt_REJECT","ip_conntrack_ftp","iptable_mangle","xt_conntrack","ipt_REDIRECT","iptable_nat","nf_conntrack_ftp","nf_nat_ftp"); + } + + if ($config{SMTP_BLOCK}) { + push @modules,"ipt_owner"; + push @modules,"xt_owner"; + } + if ($config{PORTFLOOD} or $config{PORTFLOOD6} or $config{PORTKNOCKING}) { + push @modules,"ipt_recent ip_list_tot=1000 ip_list_hash_size=0"; + } + if ($config{CONNLIMIT}) { + push @modules,"xt_connlimit"; + } + + foreach my $module (@modules) {&loadmodule($module)} + } + return; +} +# end modprobe +############################################################################### +# start faststart +sub faststart { + my $text = shift; + if (@faststart4) { + if ($verbose) {print "csf: FASTSTART loading $text (IPv4)\n"} + my $status; + if ($config{VPS}) {$status = &fastvps(scalar @faststart4)} + if ($status) {&error(__LINE__,$status)} + if ($config{DEBUG} >= 2) {print join("\n",@faststart4)."\n"}; + &iptableslock("lock"); + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, "$config{IPTABLES_RESTORE} $config{IPTABLESWAIT} -n"); + print $childin "*filter\n".join("\n",@faststart4)."\nCOMMIT\n"; + close $childin; + my @results = <$childout>; + waitpid ($cmdpid, 0); + chomp @results; + if ($results[0] =~ /# Warning: iptables-legacy tables present/) {shift @results} + if ($results[0] =~ /^(iptables|ip6tables|xtables|Bad|Another)/) { + my $cmd; + if ($results[1] =~ /^Error occurred at line: (\d+)$/) {$cmd = $faststart4[$1 - 1]} + &error(__LINE__,"FASTSTART: ($text IPv4) [$cmd] [$results[0]]. Try restarting csf with FASTSTART disabled"); + } + &iptableslock("unlock",1); + } + if (@faststart4nat) { + if ($verbose) {print "csf: FASTSTART loading $text (IPv4 nat)\n"} + my $status; + if ($config{VPS}) {$status = &fastvps(scalar @faststart4nat)} + if ($status) {&error(__LINE__,$status)} + if ($config{DEBUG} >= 2) {print join("\n",@faststart4nat)."\n"}; + &iptableslock("lock"); + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, "$config{IPTABLES_RESTORE} $config{IPTABLESWAIT} -n"); + print $childin "*nat\n".join("\n",@faststart4nat)."\nCOMMIT\n"; + close $childin; + my @results = <$childout>; + waitpid ($cmdpid, 0); + chomp @results; + if ($results[0] =~ /# Warning: iptables-legacy tables present/) {shift @results} + if ($results[0] =~ /^(iptables|ip6tables|xtables|Bad|Another)/) { + my $cmd; + if ($results[1] =~ /^Error occurred at line: (\d+)$/) {$cmd = $faststart4[$1 - 1]} + &error(__LINE__,"FASTSTART: ($text IPv4nat) [$cmd] [$results[0]]. Try restarting csf with FASTSTART disabled"); + } + &iptableslock("unlock",1); + } + if (@faststart6 and $config{IPV6}) { + if ($verbose) {print "csf: FASTSTART loading $text (IPv6)\n"} + my $status; + if ($config{VPS}) {$status = &fastvps(scalar @faststart6)} + if ($status) {&error(__LINE__,$status)} + if ($config{DEBUG} >= 2) {print join("\n",@faststart6)."\n"}; + &iptableslock("lock"); + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, "$config{IP6TABLES_RESTORE} $config{IPTABLESWAIT} -n"); + print $childin "*filter\n".join("\n",@faststart6)."\nCOMMIT\n"; + close $childin; + my @results = <$childout>; + waitpid ($cmdpid, 0); + chomp @results; + if ($results[0] =~ /# Warning: iptables-legacy tables present/) {shift @results} + if ($results[0] =~ /^(iptables|ip6tables|xtables|Bad|Another)/) { + my $cmd; + if ($results[1] =~ /^Error occurred at line: (\d+)$/) {$cmd = $faststart4[$1 - 1]} + &error(__LINE__,"FASTSTART: ($text IPv6) [$cmd] [$results[0]]. Try restarting csf with FASTSTART disabled"); + } + &iptableslock("unlock",1); + } + if (@faststart6nat and $config{IPV6}) { + if ($verbose) {print "csf: FASTSTART loading $text (IPv6 nat)\n"} + my $status; + if ($config{VPS}) {$status = &fastvps(scalar @faststart6nat)} + if ($status) {&error(__LINE__,$status)} + if ($config{DEBUG} >= 2) {print join("\n",@faststart6nat)."\n"}; + &iptableslock("lock"); + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, "$config{IP6TABLES_RESTORE} $config{IPTABLESWAIT} -n"); + print $childin "*nat\n".join("\n",@faststart6nat)."\nCOMMIT\n"; + close $childin; + my @results = <$childout>; + waitpid ($cmdpid, 0); + chomp @results; + if ($results[0] =~ /# Warning: iptables-legacy tables present/) {shift @results} + if ($results[0] =~ /^(iptables|ip6tables|xtables|Bad|Another)/) { + my $cmd; + if ($results[1] =~ /^Error occurred at line: (\d+)$/) {$cmd = $faststart6[$1 - 1]} + &error(__LINE__,"FASTSTART: ($text IPv6nat) [$cmd] [$results[0]]. Try restarting csf with FASTSTART disabled"); + } + &iptableslock("unlock",1); + } + if (@faststartipset) { + if ($verbose) {print "csf: FASTSTART loading $text (IPSET)\n"} + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, $config{IPSET},"restore"); + print $childin join("\n",@faststartipset)."\n"; + close $childin; + my @results = <$childout>; + waitpid ($cmdpid, 0); + chomp @results; + if ($results[0] =~ /^ipset/) { + print "FASTSTART: (IPSET) Error:[$results[0]]. Try restarting csf with FASTSTART disabled"; + } + } + undef @faststart4; + undef @faststart4nat; + undef @faststart6; + undef @faststart6nat; + undef @faststartipset; + $faststart = 0; + return; +} +# end faststart +############################################################################### +# start fastvps +sub fastvps { + my $size = shift; + if (-e "/proc/user_beancounters" and !(-e "/proc/vz/version")) { + open (my $INVPS, "<", "/proc/user_beancounters"); + flock ($INVPS, LOCK_SH); + my @data = <$INVPS>; + close ($INVPS); + chomp @data; + + foreach my $line (@data) { + if ($line =~ /^\s*numiptent\s+(\d*)\s+(\d*)\s+(\d*)\s+(\d*)/) { + if ($1 > $4 - ($size + 10)) {return "The VPS iptables rule limit (numiptent) is too low to add $size rules ($1/$4) - *IPs not added*"} + } + } + } + return 0; +} +# end fastvps +############################################################################### +# start ipsetcreate +sub ipsetcreate { + my $set = shift; + $SIG{PIPE} = 'IGNORE'; + my $family = "inet"; + if ($set =~ /_6/) {$family = "inet6"} + if ($verbose) {print "csf: IPSET creating set $set\n"} + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, $config{IPSET},"create","-exist",$set,"hash:net","family",$family,"hashsize",$config{LF_IPSET_HASHSIZE},"maxelem",$config{LF_IPSET_MAXELEM}); + close $childin; + my @results = <$childout>; + waitpid ($cmdpid, 0); + chomp @results; + if ($results[0] =~ /^ipset/) { + print "IPSET: [$results[0]]\n"; + $warning .= "*ERROR* IPSET: [$results[0]]\n"; + } + return; +} +# end ipsetcreate +############################################################################### +# start ipsetrestore +sub ipsetrestore { + my $set = shift; + $SIG{PIPE} = 'IGNORE'; + if ($verbose) {print "csf: IPSET loading set $set with ".scalar(@ipset)." entries\n"} + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, $config{IPSET},"restore"); + print $childin join("\n",@ipset)."\n"; + close $childin; + my @results = <$childout>; + waitpid ($cmdpid, 0); + chomp @results; + if ($results[0] =~ /^ipset/) { + print "IPSET: [$results[0]]\n"; + $warning .= "*ERROR* IPSET: [$results[0]]\n"; + } + undef @ipset; + return; +} +# end ipsetrestore +############################################################################### +# start ipsetadd +sub ipsetadd { + my $set = shift; + my $ip = shift; + $SIG{PIPE} = 'IGNORE'; + if ($set =~ /^chain(_6)?_NEW(\w+)$/) {$set = "chain".$1."_".$2} + if ($set =~ /^(\w+)(IN|OUT)$/) {$set = $1} + if ($set =~ /^bl(_6)?_NEW(\w+)$/) {$set = "bl".$1."_".$2} + if ($set eq "" or $ip eq "") {return} + if ($faststart) { + push @faststartipset, "add -exist $set $ip"; + return; + } + if ($verbose) {print "csf: IPSET adding [$ip] to set [$set]\n"} + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, $config{IPSET},"add","-exist",$set,$ip); + close $childin; + my @results = <$childout>; + waitpid ($cmdpid, 0); + chomp @results; + if ($results[0] =~ /^ipset/) { + print "IPSET: [$results[0]]\n"; + $warning .= "*ERROR* IPSET: [$results[0]]\n"; + } + return; +} +# end ipsetadd +############################################################################### +# start ipsetdel +sub ipsetdel { + my $set = shift; + my $ip = shift; + $SIG{PIPE} = 'IGNORE'; + if ($set =~ /^chain(_6)?_NEW(\w+)$/) {$set = "chain".$1."_".$2} + if ($set =~ /^(\w+)(IN|OUT)$/) {$set = $1} + if ($set =~ /^bl(_6)?_NEW(\w+)$/) {$set = "bl".$1."_".$2} + if ($set eq "" or $ip eq "") {return} + if ($verbose) {print "csf: IPSET deleting [$ip] from set [$set]\n"} + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, $config{IPSET},"del",$set,$ip); + close $childin; + my @results = <$childout>; + waitpid ($cmdpid, 0); + chomp @results; + if ($results[0] =~ /^ipset/) { + print "IPSET: [$results[0]]\n"; + $warning .= "*ERROR* IPSET: [$results[0]]\n"; + } + return; +} +# end ipsetadd +############################################################################### diff --git a/csf/csf.rblconf b/csf/csf.rblconf new file mode 100644 index 0000000..7418b92 --- /dev/null +++ b/csf/csf.rblconf @@ -0,0 +1,35 @@ +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +# This file configures optional entries for the IP checking against RBLs within +# csf +# +# There are 4 options available to enable/disable RBLs and IPs: +# +# To disable inbuilt RBLs or to enable other RBLs, e.g.: +# +# enablerbl:my.dnsrbl.net +# disablerbl:bl.spamcop.net +# +# To disable local IPs or to enable other IPs, e.g.: +# +# enableip:11.22.33.44 +# disableip:10.10.10.10 +# +# There should be no spaces on any of the configuration lines. Lines beginning +# with # are comments diff --git a/csf/csf.rbls b/csf/csf.rbls new file mode 100644 index 0000000..1949d19 --- /dev/null +++ b/csf/csf.rbls @@ -0,0 +1,41 @@ +all.s5h.net:http://www.usenix.org.uk/content/rbl.html +b.barracudacentral.org:http://www.barracudacentral.org/rbl +cbl.abuseat.org:http://abuseat.org/ +csi.cloudmark.com:https://csi.cloudmark.com/en/reset/ +db.wpbl.info:http://www.wpbl.info/ +dnsbl-1.uceprotect.net:http://www.uceprotect.net/ +dnsbl-2.uceprotect.net:http://www.uceprotect.net/ +dnsbl-3.uceprotect.net:http://www.uceprotect.net/ +dnsbl.dronebl.org:https://dronebl.org/ +dnsbl.inps.de:http://dnsbl.inps.de/?lang=en +dnsbl.sorbs.net:http://www.sorbs.net/ +drone.abuse.ch:https://www.abuse.ch/ +dul.dnsbl.sorbs.net:http://www.sorbs.net/ +dyna.spamrats.com:http://www.spamrats.com/rats-dyna.php +http.dnsbl.sorbs.net:http://www.sorbs.net/ +httpbl.abuse.ch:https://www.abuse.ch/ +ips.backscatterer.org:http://www.backscatterer.org/ +ix.dnsbl.manitu.net:http://www.dnsbl.manitu.net/ +misc.dnsbl.sorbs.net:http://www.sorbs.net/ +multi.surbl.org:http://www.surbl.org/ +noptr.spamrats.com:http://www.spamrats.com/rats-noptr.php +opm.tornevall.org:https://dnsbl.tornevall.org/ +pbl.spamhaus.org:https://www.spamhaus.org/pbl/ +psbl.surriel.com:http://psbl.org/ +query.senderbase.org:https://www.senderbase.org/lookup/ +rbl.efnetrbl.org:http://efnetrbl.org/ +rbl.interserver.net:http://rbldata.interserver.net/index.php +sbl.spamhaus.org:https://www.spamhaus.org/sbl/ +smtp.dnsbl.sorbs.net:http://www.sorbs.net/ +socks.dnsbl.sorbs.net:http://www.sorbs.net/ +spam.dnsbl.sorbs.net:http://www.sorbs.net/ +spam.spamrats.com:http://www.spamrats.com/rats-spam.php +spamrbl.imp.ch:http://antispam.imp.ch +tor.dan.me.uk:https://www.dan.me.uk/dnsbl +ubl.unsubscore.com:http://blacklist.lashback.com/ +virbl.bit.nl:https://virbl.bit.nl/ +web.dnsbl.sorbs.net:http://www.sorbs.net/ +wormrbl.imp.ch:http://antispam.imp.ch +xbl.spamhaus.org:https://www.spamhaus.org/xbl/ +zen.spamhaus.org:https://www.spamhaus.org/zen/ +zombie.dnsbl.sorbs.net:http://www.sorbs.net/ diff --git a/csf/csf.redirect b/csf/csf.redirect new file mode 100644 index 0000000..5226cad --- /dev/null +++ b/csf/csf.redirect @@ -0,0 +1,47 @@ +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +# The following is a list of port and/or IP address assignments to direct +# traffic to alternative ports/IP addresses +# +# Requirements: +# nat tables +# ipt_DNAT iptables module +# ipt_SNAT iptables module +# ipt_REDIRECT iptables module +# +# The following are the allowed redirection formats +# +# DNAT (redirect from one IP address to a different one): +# IPx|*|IPy|*|tcp/udp - To IPx redirects to IPy +# IPx|portA|IPy|portB|tcp/udp - To IPx to portA redirects to IPy portB +# +# DNAT examples: +# 192.168.254.62|*|10.0.0.1|*|tcp +# 192.168.254.62|666|10.0.0.1|25|tcp +# +# REDIRECT (redirect from port to a different one): +# IPx|portA|*|portB|tcp/udp - To IPx to portA redirects to portB +# *|portA|*|portB|tcp/udp - To portA redirects to portB +# +# REDIRECT examples: +# 192.168.254.60|666|*|25|tcp +# *|666|*|25|tcp +# +# See readme.txt for more information +# diff --git a/csf/csf.resellers b/csf/csf.resellers new file mode 100644 index 0000000..79f3405 --- /dev/null +++ b/csf/csf.resellers @@ -0,0 +1,60 @@ +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +# The following is a list of Reseller accounts that you want to allow access to +# limited csf functionality. +# +# WARNING: You should only ever provide access to this facility to people you +# trust as it could easily render your server inaccessible or open to attack. +# For security reasons, resellers cannot list blocked IP addresses or the whole +# iptables configuration. They must know what IP address they want to use with +# this facility. +# +# You should list each account, one per line, followed by a colon, then a 0 or +# 1 depending on whether you want an email alert sent using the email template +# reselleralter.txt whenever an ALLOW/DENY or UNBLOCK is performed, then a +# colon, then a comma separated list of the feature codes that you want each +# reseller to have access to. +# +# As of writing, the following is a list of the available feature codes. More +# may be added in the feature, in which case they will be listed in the main +# csf readme.txt: +# +# USE - The reseller can use this facility through WHM (required) +# UNBLOCK - The reseller can use the Quick Unblock feature +# GREP - The reseller can use the Search IP feature +# ALLOW - The reseller can use the Quick Allow feature +# DENY - The reseller can use the Quick Deny feature +# +# For example, to allow reseller "someuser" to unblock IP addresses and have an +# alert email sent to root, use: +# +#someuser:1:USE,UNBLOCK +# +# For example, to allow reseller "someuser" to allow, deny and unblock IP +# addresses, but no alert sent, use: +# +#someuser:0:USE,ALLOW,DENY,UNBLOCK +# +# RECOMMEND: For security reasons, we recommend only allowing resellers USE, +# UNBLOCK and GREP +# +# NOTE: As of version cPanel v11.8.1 you must additionally grant resellers +# access via "WHM > Edit Reseller Nameservers and Privileges > Third Party +# Services > ConfigServer Security & Firewall (Reseller UI)". +# \ No newline at end of file diff --git a/csf/csf.rignore b/csf/csf.rignore new file mode 100644 index 0000000..465ea21 --- /dev/null +++ b/csf/csf.rignore @@ -0,0 +1,53 @@ +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +# The following is a list of domains and partial domain that lfd process +# tracking will ignore based on reverse and forward DNS lookups. An example of +# its use is to prevent web crawlers from being blocked by lfd, e.g. +# .googlebot.com and .crawl.yahoo.net +# +# You must use either a Fully Qualified Domain Name (FQDN) or a unique ending +# subset of the domain name which must begin with a dot (wildcards are NOT +# otherwise permitted) +# +# For example, the following are all valid entries: +# www.configserver.com +# .configserver.com +# .configserver.co.uk +# .googlebot.com +# .crawl.yahoo.net +# .search.msn.com +# +# The following are NOT valid entries: +# *.configserver.com +# *google.com +# google.com (unless the lookup is EXACTLY google.com with no subdomain +# +# When a candidate IP address is inspected a reverse DNS lookup is performed on +# the IP address. A forward DNS lookup is then performed on the result from the +# reverse DNS lookup. The IP address will only be ignored if: +# +# 1. The results of the final lookup matches the original IP address +# AND +# 2a. The results of the rDNS lookup matches the FQDN +# OR +# 2b. The results of the rDNS lookup matches the partial subset of the domain +# +# Note: If the DNS lookups are too slow or do not return the expected results +# the IP address will be counted towards the blocking trigger as normal +# diff --git a/csf/csf.service b/csf/csf.service new file mode 100644 index 0000000..e8dae8f --- /dev/null +++ b/csf/csf.service @@ -0,0 +1,13 @@ +[Unit] +Description=ConfigServer Firewall & Security - csf +After=network.target +Before=lfd.service + +[Service] +ExecStart=/usr/sbin/csf --initup +ExecStop=/usr/sbin/csf --initdown ; /usr/sbin/csf --stop +RemainAfterExit=yes +Type=oneshot + +[Install] +WantedBy=multi-user.target diff --git a/csf/csf.sh b/csf/csf.sh new file mode 100644 index 0000000..a17bd83 --- /dev/null +++ b/csf/csf.sh @@ -0,0 +1,103 @@ +#!/bin/bash +# +############################################################################### +# lfd +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +# +# chkconfig: 2345 15 80 +# description: ConfigServer Firewall +# +### BEGIN INIT INFO +# Provides: csf +# Required-Start: $network +# Required-Stop: $network +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# X-Start-Before: $syslog +# Short-Description: ConfigServer Firewall (csf) +# Description: ConfigServer Firewall (csf) init script +### END INIT INFO +# + +[ -f /usr/sbin/csf ] || exit 0 + +# Source function library. +if [ -f /etc/init.d/functions ]; then + . /etc/init.d/functions +fi + +DAEMON=/usr/sbin/csf +LOCKFILE=/var/lock/subsys/csf + +if [ -f /etc/SuSE-release ]; then + . /etc/rc.status + rc_reset +fi + +case "$1" in + start) + echo -n "Starting csf:" + $DAEMON --initup + if [ -f /etc/SuSE-release ]; then + rc_status -v + elif [ -f /etc/debian_version ] || [ -f /etc/lsb-release ] || [ -f /etc/gentoo-release ]; then + echo " Done" + else + success + echo + fi + echo + if [ -e /var/lock/subsys/ ]; then + touch $LOCKFILE + fi + ;; + stop) + echo "WARNING: This script should ONLY be used by the init process. To restart csf use the CLI command 'csf -r'" + echo + echo -n "Stopping csf:" + $DAEMON --initdown + $DAEMON --stop > /dev/null 2>&1 + if [ -f /etc/SuSE-release ]; then + rc_status -v + elif [ -f /etc/debian_version ] || [ -f /etc/lsb-release ] || [ -f /etc/gentoo-release ]; then + echo " Done" + else + success + echo + fi + echo + if [ -e /var/lock/subsys/ ]; then + rm -f $LOCKFILE + fi + ;; + status) + echo -n "Status of csf:" + $DAEMON --status + echo + ;; + restart|force-reload|reload) + $0 stop + $0 start + ;; + *) + echo "Usage: /etc/init.d/csf start|stop|restart|force-reload|status" + exit 1 +esac + +exit 0 diff --git a/csf/csf.signore b/csf/csf.signore new file mode 100644 index 0000000..6c1b0fd --- /dev/null +++ b/csf/csf.signore @@ -0,0 +1,20 @@ +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +# The following is a list of files that LF_SCRIPT_ALERT will ignore. You must +# specify the full path to the directory containing the script diff --git a/csf/csf.sips b/csf/csf.sips new file mode 100644 index 0000000..9d49aae --- /dev/null +++ b/csf/csf.sips @@ -0,0 +1,22 @@ +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +# The purpose of this file is to list any server configured IP addresses for +# which you don't want to allow any incoming or outgoing traffic. This is +# useful if you have IP addresses setup but do not yet wish to allow traffic +# on them diff --git a/csf/csf.smtpauth b/csf/csf.smtpauth new file mode 100644 index 0000000..4253842 --- /dev/null +++ b/csf/csf.smtpauth @@ -0,0 +1,25 @@ +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +# The following IP addresses will allow EXIM to advertise SMTP AUTH +# One IP address per line. +# CIDR addressing allowed with a quaded IP (e.g. 192.168.254.0/24). +# Only list IP addresses, not domain names (they will be ignored) +# +# You need to enable SMTPAUTH_RESTRICT and modify the exim configuration to use +# this file. CC_ALLOW_SMTPAUTH can also be used to allow whole Country Codes diff --git a/csf/csf.suignore b/csf/csf.suignore new file mode 100644 index 0000000..fc94a90 --- /dev/null +++ b/csf/csf.suignore @@ -0,0 +1,20 @@ +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +# The following is a list of usernames that are ignored during the LF_EXPLOIT +# SUPERUSER check diff --git a/csf/csf.syslogs b/csf/csf.syslogs new file mode 100644 index 0000000..7e7c373 --- /dev/null +++ b/csf/csf.syslogs @@ -0,0 +1,103 @@ +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +# The following is a list of log files for the UI System Log Watch and Search +# features. IF they exists they will apear in the drop-down lists +# +# File globbing is supported for logs listed below + +# All: +/var/log/cron +/var/log/cxswatch.log +/var/log/lfd.log +/var/log/maillog +/var/log/messages +/var/log/rkhunter.log +/var/log/secure + +# Apache: +/usr/local/apache/logs/apache_log +/usr/local/apache/logs/error_log +/usr/local/apache/logs/suexec +/usr/local/apache/logs/suphp_log +/usr/local/apache/logs/modsec_audit.log +/var/log/httpd/access_log +/var/log/httpd/error_log +/var/log/httpd/suexec +/var/log/httpd/suphp_log +/var/log/httpd/modsec_audit.log + +# Nginx: +/var/log/nginx/error_log + +# Webmin: +/var/webmin/miniserv.error +/var/webmin/miniserv.log +/var/webmin/webmin.log + +# Exim: +/var/log/exim/mainlog +/var/log/exim/paniclog +/var/log/exim/rejectlog +/var/log/exim4/mainlog +/var/log/exim4/paniclog +/var/log/exim4/rejectlog +/var/log/exim_mainlog +/var/log/exim_paniclog +/var/log/exim_rejectlog + +# Debian/Ubuntu: +/var/log/auth.log +/var/log/daemon.log +/var/log/debug +/var/log/kern.log +/var/log/mysql.err +/var/log/mysql.log +/var/log/syslog +/var/log/user.log +/var/log/mail.err +/var/log/mail.log + +# cPanel: +/usr/local/cpanel/logs/access_log +/usr/local/cpanel/logs/error_log +/usr/local/cpanel/logs/stats_log +/var/log/chkservd.log + +# DirectAdmin: +/var/log/directadmin/error.log +/var/log/directadmin/errortaskq.log +/var/log/directadmin/security.log +/var/log/directadmin/system.log + +# InterWorx +/usr/local/interworx/var/log/iworx.log +/usr/local/interworx/var/log/iworx-init.log +/usr/local/interworx/var/log/error.log +/usr/local/interworx/var/log/stack.log + +# CyberPanel +/home/cyberpanel/error-logs.txt +/usr/local/lscp/cyberpanel/logs/error.log +/usr/local/lscp/cyberpanel/logs/access.log +/usr/local/lscp/cyberpanel/logs/stderr.log + +# Litespeed/Openlitespeed +/usr/local/lsws/logs/error.log +/usr/local/lsws/logs/access.log +/usr/local/lsws/logs/auditmodsec.log diff --git a/csf/csf.syslogusers b/csf/csf.syslogusers new file mode 100644 index 0000000..069cd3a --- /dev/null +++ b/csf/csf.syslogusers @@ -0,0 +1,79 @@ +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +# This file contains the usernames which should be allowed to log via +# syslog/rsyslog. All the users that exist on the server that are listed in +# this file will be added to the system group defined in /etc/csf/csf.conf for +# the option RESTRICT_SYSLOG_GROUP if RESTRICT_SYSLOG is set to "3" +# +# This WILL break user cron job logging in /var/log/cron for non-listed user +# accounts +# +# Remove any accounts that do not apply to your server +# +# Add any accounts that log through syslog that are not listed that you need +# +# You should only add user accounts and/or the default apache account if +# absolutely necessary, otherwise you are compromising the effectiveness of +# this feature + +# OS application users: +daemon +dbus +haldaemon +messagebus +mysql +named +nfsnobody +ntp +polkitd +root +rpc +rpcuser +smmsp +statd + +# cPanel application users: +cpanel +cpses +dovecot +dovenull +mailman +mailnull + +# DirectAdmin application users: +dovecot +mail + +# InterWorx users: +qmailq +qmails +qmailr +qmailp +qmaill +qmaild +alias +iworx-horde +iworx-roundcube +iworx-pma +iworx-backup +iworx-web +iworx +vpopmail + +# Other users: diff --git a/csf/csf.uidignore b/csf/csf.uidignore new file mode 100644 index 0000000..c8da1df --- /dev/null +++ b/csf/csf.uidignore @@ -0,0 +1,22 @@ +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +# The following is a list of user ID's (UID) that are ignored by the User ID +# Tracking feature - UID_INTERVAL +# +# For example, to ignore all root connections add 0 on a line by itself diff --git a/csf/csf.vesta.allow b/csf/csf.vesta.allow new file mode 100644 index 0000000..19ec008 --- /dev/null +++ b/csf/csf.vesta.allow @@ -0,0 +1,30 @@ +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +# The following IP addresses will be allowed through iptables. +# One IP address per line. +# CIDR addressing allowed with a quaded IP (e.g. 192.168.254.0/24). +# Only list IP addresses, not domain names (they will be ignored) +# +# Advanced port+ip filtering allowed with the following format +# tcp/udp|in/out|s/d=port|s/d=ip +# See readme.txt for more information +# +# Note: IP addressess listed in this file will NOT be ignored by lfd, so they +# can still be blocked. If you do not want lfd to block an IP address you must +# add it to csf.ignore diff --git a/csf/csf.vesta.conf b/csf/csf.vesta.conf new file mode 100644 index 0000000..d30993c --- /dev/null +++ b/csf/csf.vesta.conf @@ -0,0 +1,2685 @@ +############################################################################### +# SECTION:Initial Settings +############################################################################### +# Testing flag - enables a CRON job that clears iptables incase of +# configuration problems when you start csf. This should be enabled until you +# are sure that the firewall works - i.e. incase you get locked out of your +# server! Then do remember to set it to 0 and restart csf when you're sure +# everything is OK. Stopping csf will remove the line from /etc/crontab +# +# lfd will not start while this is enabled +TESTING = "1" + +# The interval for the crontab in minutes. Since this uses the system clock the +# CRON job will run at the interval past the hour and not from when you issue +# the start command. Therefore an interval of 5 minutes means the firewall +# will be cleared in 0-5 minutes from the firewall start +TESTING_INTERVAL = "5" + +# SECURITY WARNING +# ================ +# +# Unfortunately, syslog and rsyslog allow end-users to log messages to some +# system logs via the same unix socket that other local services use. This +# means that any log line shown in these system logs that syslog or rsyslog +# maintain can be spoofed (they are exactly the same as real log lines). +# +# Since some of the features of lfd rely on such log lines, spoofed messages +# can cause false-positive matches which can lead to confusion at best, or +# blocking of any innocent IP address or making the server inaccessible at +# worst. +# +# Any option that relies on the log entries in the files listed in +# /etc/syslog.conf and /etc/rsyslog.conf should therefore be considered +# vulnerable to exploitation by end-users and scripts run by end-users. +# +# NOTE: Not all log files are affected as they may not use syslog/rsyslog +# +# The option RESTRICT_SYSLOG disables all these features that rely on affected +# logs. These options are: +# LF_SSHD LF_FTPD LF_IMAPD LF_POP3D LF_BIND LF_SUHOSIN LF_SSH_EMAIL_ALERT +# LF_SU_EMAIL_ALERT LF_CONSOLE_EMAIL_ALERT LF_DISTATTACK LF_DISTFTP +# LT_POP3D LT_IMAPD PS_INTERVAL UID_INTERVAL WEBMIN_LOG LF_WEBMIN_EMAIL_ALERT +# PORTKNOCKING_ALERT LF_SUDO_EMAIL_ALERT +# +# This list of options use the logs but are not disabled by RESTRICT_SYSLOG: +# ST_ENABLE SYSLOG_CHECK LOGSCANNER CUSTOM*_LOG +# +# The following options are still enabled by default on new installations so +# that, on balance, csf/lfd still provides expected levels of security: +# LF_SSHD LF_FTPD LF_POP3D LF_IMAPD LF_SSH_EMAIL_ALERT LF_SU_EMAIL_ALERT +# +# If you set RESTRICT_SYSLOG to "0" or "2" and enable any of the options listed +# above, it should be done with the knowledge that any of the those options +# that are enabled could be triggered by spoofed log lines and lead to the +# server being inaccessible in the worst case. If you do not want to take that +# risk you should set RESTRICT_SYSLOG to "1" and those features will not work +# but you will not be protected from the exploits that they normally help block +# +# The recommended setting for RESTRICT_SYSLOG is "3" to restrict who can access +# the syslog/rsyslog unix socket. +# +# For further advice on how to help mitigate these issues, see +# /etc/csf/readme.txt +# +# 0 = Allow those options listed above to be used and configured +# 1 = Disable all the options listed above and prevent them from being used +# 2 = Disable only alerts about this feature and do nothing else +# 3 = Restrict syslog/rsyslog access to RESTRICT_SYSLOG_GROUP ** RECOMMENDED ** +RESTRICT_SYSLOG = "0" + +# The following setting is used if RESTRICT_SYSLOG is set to 3. It restricts +# write access to the syslog/rsyslog unix socket(s). The group must not already +# exists in /etc/group before setting RESTRICT_SYSLOG to 3, so set the option +# to a unique name for the server +# +# You can add users to this group by changing /etc/csf/csf.syslogusers and then +# restarting lfd afterwards. This will create the system group and add the +# users from csf.syslogusers if they exist to that group and will change the +# permissions on the syslog/rsyslog unix socket(s). The socket(s) will be +# monitored and the permissions re-applied should syslog/rsyslog be restarted +# +# Using this option will prevent some legitimate logging, e.g. end-user cron +# job logs +# +# If you want to revert RESTRICT_SYSLOG to another option and disable this +# feature, change the setting of RESTRICT_SYSLOG and then restart lfd and then +# syslog/rsyslog and the unix sockets will be reset +RESTRICT_SYSLOG_GROUP = "mysyslog" + +# This options restricts the ability to modify settings within this file from +# the csf UI. Should the parent control panel be compromised, these restricted +# options could be used to further compromise the server. For this reason we +# recommend leaving this option set to at least "1" and if any of the +# restricted items need to be changed, they are done so from the root shell +# +# 0 = Unrestricted UI +# 1 = Restricted UI +# 2 = Disabled UI +RESTRICT_UI = "1" + +# Enabling auto updates creates a cron job called /etc/cron.d/csf_update which +# runs once per day to see if there is an update to csf+lfd and upgrades if +# available and restarts csf and lfd +# +# You should check for new version announcements at http://blog.configserver.com +AUTO_UPDATES = "1" + +############################################################################### +# SECTION:IPv4 Port Settings +############################################################################### +# Lists of ports in the following comma separated lists can be added using a +# colon (e.g. 30000:35000). + +# Some kernel/iptables setups do not perform stateful connection tracking +# correctly (typically some virtual servers or custom compiled kernels), so a +# SPI firewall will not function correctly. If this happens, LF_SPI can be set +# to 0 to reconfigure csf as a static firewall. +# +# As connection tracking will not be configured, applications that rely on it +# will not function unless all outgoing ports are opened. Therefore, all +# outgoing connections will be allowed once all other tests have completed. So +# TCP_OUT, UDP_OUT and ICMP_OUT will not have any affect. +# +# If you allow incoming DNS lookups you may need to use the following +# directive in the options{} section of your named.conf: +# +# query-source port 53; +# +# This will force incoming DNS traffic only through port 53 +# +# Disabling this option will break firewall functionality that relies on +# stateful packet inspection (e.g. DNAT, PACKET_FILTER) and makes the firewall +# less secure +# +# This option should be set to "1" in all other circumstances +LF_SPI = "1" + +# Allow incoming TCP ports +TCP_IN = "20,21,22,25,53,853,80,110,143,443,465,587,993,995,8083" + +# Allow outgoing TCP ports +TCP_OUT = "20,21,22,25,53,853,80,110,113,443,587,993,995" + +# Allow incoming UDP ports +UDP_IN = "20,21,53,853,80,443" + +# Allow outgoing UDP ports +# To allow outgoing traceroute add 33434:33523 to this list +UDP_OUT = "20,21,53,853,113,123" + +# Allow incoming PING. Disabling PING will likely break external uptime +# monitoring +ICMP_IN = "1" + +# Set the per IP address incoming ICMP packet rate for PING requests. This +# ratelimits PING requests which if exceeded results in silently rejected +# packets. Disable or increase this value if you are seeing PING drops that you +# do not want +# +# To disable rate limiting set to "0", otherwise set according to the iptables +# documentation for the limit module. For example, "1/s" will limit to one +# packet per second +ICMP_IN_RATE = "1/s" + +# Allow outgoing PING +# +# Unless there is a specific reason, this option should NOT be disabled as it +# could break OS functionality +ICMP_OUT = "1" + +# Set the per IP address outgoing ICMP packet rate for PING requests. This +# ratelimits PING requests which if exceeded results in silently rejected +# packets. Disable or increase this value if you are seeing PING drops that you +# do not want +# +# Unless there is a specific reason, this option should NOT be enabled as it +# could break OS functionality +# +# To disable rate limiting set to "0", otherwise set according to the iptables +# documentation for the limit module. For example, "1/s" will limit to one +# packet per second +ICMP_OUT_RATE = "0" + +# For those with PCI Compliance tools that state that ICMP timestamps (type 13) +# should be dropped, you can enable the following option. Otherwise, there +# appears to be little evidence that it has anything to do with a security risk +# and can impact network performance, so should be left disabled by everyone +# else +ICMP_TIMESTAMPDROP = "0" + +############################################################################### +# SECTION:IPv6 Port Settings +############################################################################### +# IPv6: (Requires ip6tables) +# +# Pre v2.6.20 kernels do not perform stateful connection tracking, so a static +# firewall is configured as a fallback instead if IPV6_SPI is set to 0 below +# +# Supported: +# Temporary ACCEPT/DENY, GLOBAL_DENY, GLOBAL_ALLOW, SMTP_BLOCK, LF_PERMBLOCK, +# PACKET_FILTER, Advanced Allow/Deny Filters, RELAY_*, CLUSTER_*, CC6_LOOKUPS, +# SYNFLOOD, LF_NETBLOCK +# +# Supported if CC6_LOOKUPS and CC_LOOKUPS are enabled +# CC_DENY, CC_ALLOW, CC_ALLOW_FILTER, CC_IGNORE, CC_ALLOW_PORTS, CC_DENY_PORTS, +# CC_ALLOW_SMTPAUTH +# +# Supported if ip6tables >= 1.4.3: +# PORTFLOOD, CONNLIMIT +# +# Supported if ip6tables >= 1.4.17 and perl module IO::Socket::INET6 is +# installed: +# MESSENGER DOCKER SMTP_REDIRECT +# +# Not supported: +# ICMP_IN, ICMP_OUT +# +IPV6 = "0" + +# IPv6 uses icmpv6 packets very heavily. By default, csf will allow all icmpv6 +# traffic in the INPUT and OUTPUT chains. However, this could increase the risk +# of icmpv6 attacks. To restrict incoming icmpv6, set to "1" but may break some +# connection types +IPV6_ICMP_STRICT = "0" + +# Pre v2.6.20 kernel must set this option to "0" as no working state module is +# present, so a static firewall is configured as a fallback +# +# A workaround has been added for CentOS/RedHat v5 and custom kernels that do +# not support IPv6 connection tracking by opening ephemeral port range +# 32768:61000. This is only applied if IPV6_SPI is not enabled. This is the +# same workaround implemented by RedHat in the sample default IPv6 rules +# +# As connection tracking will not be configured, applications that rely on it +# will not function unless all outgoing ports are opened. Therefore, all +# outgoing connections will be allowed once all other tests have completed. So +# TCP6_OUT, UDP6_OUT and ICMP6_OUT will not have any affect. +# +# If you allow incoming ipv6 DNS lookups you may need to use the following +# directive in the options{} section of your named.conf: +# +# query-source-v6 port 53; +# +# This will force ipv6 incoming DNS traffic only through port 53 +# +# These changes are not necessary if the SPI firewall is used +IPV6_SPI = "1" + +# Allow incoming IPv6 TCP ports +TCP6_IN = "20,21,22,25,53,853,80,110,143,443,465,587,993,995,8083" + +# Allow outgoing IPv6 TCP ports +TCP6_OUT = "20,21,22,25,53,853,80,110,113,443,587,993,995" + +# Allow incoming IPv6 UDP ports +UDP6_IN = "20,21,53,853,80,443" + +# Allow outgoing IPv6 UDP ports +# To allow outgoing traceroute add 33434:33523 to this list +UDP6_OUT = "20,21,53,853,113,123" + +############################################################################### +# SECTION:General Settings +############################################################################### +# By default, csf will auto-configure iptables to filter all traffic except on +# the loopback device. If you only want iptables rules applied to a specific +# NIC, then list it here (e.g. eth1, or eth+) +ETH_DEVICE = "" + +# By adding a device to this option, ip6tables can be configured only on the +# specified device. Otherwise, ETH_DEVICE and then the default setting will be +# used +ETH6_DEVICE = "" + +# If you don't want iptables rules applied to specific NICs, then list them in +# a comma separated list (e.g "eth1,eth2") +ETH_DEVICE_SKIP = "" + +# This option should be enabled unless the kernel does not support the +# "conntrack" module +# +# To use the deprecated iptables "state" module, change this to 0 +USE_CONNTRACK = "1" + +# Enable ftp helper via the iptables CT target on supporting kernels (v2.6.34+) +# instead of the current method via /proc/sys/net/netfilter/nf_conntrack_helper +# This will also remove the RELATED target from the global state iptables rule +# +# This is not needed (and will be ignored) if LF_SPI/IPV6_SPI is disabled or +# the raw tables do not exist. The USE_CONNTRACK option should be enabled +# +# To enable this option, set it to your FTP server listening port number +# (normally 21), do NOT set it to "1" +USE_FTPHELPER = "0" + +# Check whether syslog is running. Many of the lfd checks require syslog to be +# running correctly. This test will send a coded message to syslog every +# SYSLOG_CHECK seconds. lfd will check SYSLOG_LOG log lines for the coded +# message. If it fails to do so within SYSLOG_CHECK seconds an alert using +# syslogalert.txt is sent +# +# A value of between 300 and 3600 seconds is suggested. Set to 0 to disable +SYSLOG_CHECK = "0" + +# Enable this option if you want lfd to ignore (i.e. don't block) IP addresses +# listed in csf.allow in addition to csf.ignore (the default). This option +# should be used with caution as it would mean that IP's allowed through the +# firewall from infected PC's could launch attacks on the server that lfd +# would ignore +IGNORE_ALLOW = "0" + +# Enable the following option if you want to apply strict iptables rules to DNS +# traffic (i.e. relying on iptables connection tracking). Enabling this option +# could cause DNS resolution issues both to and from the server but could help +# prevent abuse of the local DNS server +DNS_STRICT = "0" + +# Enable the following option if you want to apply strict iptables rules to DNS +# traffic between the server and the nameservers listed in /etc/resolv.conf +# Enabling this option could cause DNS resolution issues both to and from the +# server but could help prevent abuse of the local DNS server +DNS_STRICT_NS = "0" + +# Limit the number of IP's kept in the /etc/csf/csf.deny file +# +# Care should be taken when increasing this value on servers with low memory +# resources or hard limits (such as Virtuozzo/OpenVZ) as too many rules (in the +# thousands) can sometimes cause network slowdown +# +# The value set here is the maximum number of IPs/CIDRs allowed +# if the limit is reached, the entries will be rotated so that the oldest +# entries (i.e. the ones at the top) will be removed and the latest is added. +# The limit is only checked when using csf -d (which is what lfd also uses) +# Set to 0 to disable limiting +# +# For implementations wishing to set this value significantly higher, we +# recommend using the IPSET option +DENY_IP_LIMIT = "200" + +# Limit the number of IP's kept in the temprary IP ban list. If the limit is +# reached the oldest IP's in the ban list will be removed and allowed +# regardless of the amount of time remaining for the block +# Set to 0 to disable limiting +DENY_TEMP_IP_LIMIT = "100" + +# Enable login failure detection daemon (lfd). If set to 0 none of the +# following settings will have any effect as the daemon won't start. +LF_DAEMON = "1" + +# Check whether csf appears to have been stopped and restart if necessary, +# unless TESTING is enabled above. The check is done every 300 seconds +LF_CSF = "1" + +# This option uses IPTABLES_SAVE, IPTABLES_RESTORE and IP6TABLES_SAVE, +# IP6TABLES_RESTORE in two ways: +# +# 1. On a clean server reboot the entire csf iptables configuration is saved +# and then restored where possible to provide a near instant firewall +# startup[*] +# +# 2. On csf restart or lfd reloading tables, CC_* as well as SPAMHAUS, DSHIELD, +# BOGON, TOR are loaded using this method in a fraction of the time than if +# this setting is disabled +# +# [*]Not supported on all OS platforms +# +# Set to "0" to disable this functionality +FASTSTART = "1" + +# This option allows you to use ipset v6+ for the following csf options: +# CC_* and /etc/csf/csf.blocklist, /etc/csf/csf.allow, /etc/csf/csf.deny, +# GLOBAL_DENY, GLOBAL_ALLOW, DYNDNS, GLOBAL_DYNDNS, MESSENGER +# +# ipset will only be used with the above options when listing IPs and CIDRs. +# Advanced Allow Filters and temporary blocks use traditional iptables +# +# Using ipset moves the onus of ip matching against large lists away from +# iptables rules and to a purpose built and optimised database matching +# utility. It also simplifies the switching in of updated lists +# +# To use this option you must have a fully functioning installation of ipset +# installed either via rpm or source from http://ipset.netfilter.org/ +# +# Note: Using ipset has many advantages, some disadvantages are that you will +# no longer see packet and byte counts against IPs and it makes identifying +# blocked/allowed IPs that little bit harder +# +# Note: If you mainly use IP address only entries in csf.deny, you can increase +# the value of DENY_IP_LIMIT significantly if you wish +# +# Note: It's highly unlikely that ipset will function on Virtuozzo/OpenVZ +# containers even if it has been installed +# +# If you find any problems, please post on forums.configserver.com with full +# details of the issue +LF_IPSET = "0" + +# Versions of iptables greater or equal to v1.4.20 should support the --wait +# option. This forces iptables commands that use the option to wait until a +# lock by any other process using iptables completes, rather than simply +# failing +# +# Enabling this feature will add the --wait option to iptables commands +# +# NOTE: The disadvantage of using this option is that any iptables command that +# uses it will hang until the lock is released. This could cause a cascade of +# hung processes trying to issue iptables commands. To try and avoid this issue +# csf uses a last ditch timeout, WAITLOCK_TIMEOUT in seconds, that will trigger +# a failure if reached +WAITLOCK = "0" +WAITLOCK_TIMEOUT = "300" + +# The following sets the hashsize for ipset sets, which must be a power of 2. +# +# Note: Increasing this value will consume more memory for all sets +# Default: "1024" +LF_IPSET_HASHSIZE = "1024" + +# The following sets the maxelem for ipset sets. +# +# Note: Increasing this value will consume more memory for all sets +# Default: "65536" +LF_IPSET_MAXELEM = "65536" + +# If you enable this option then whenever a CLI request to restart csf is used +# lfd will restart csf instead within LF_PARSE seconds +# +# This feature can be helpful for restarting configurations that cannot use +# FASTSTART +LFDSTART = "0" + +# Enable verbose output of iptables commands +VERBOSE = "1" + +# Drop out of order packets and packets in an INVALID state in iptables +# connection tracking +PACKET_FILTER = "1" + +# Perform reverse DNS lookups on IP addresses. (See also CC_LOOKUPS) +LF_LOOKUPS = "1" + +# Custom styling is possible in the csf UI. See the readme.txt for more +# information under "UI skinning and Mobile View" +# +# This option enables the use of custom styling. If the styling fails to work +# correctly, e.g. custom styling does not take into account a change in the +# standard csf UI, then disabling this option will return the standard UI +STYLE_CUSTOM = "0" + +# This option disables the presence of the Mobile View in the csf UI +STYLE_MOBILE = "1" + +############################################################################### +# SECTION:SMTP Settings +############################################################################### +# Block outgoing SMTP except for root, exim and mailman (forces scripts/users +# to use the exim/sendmail binary instead of sockets access). This replaces the +# protection as WHM > Tweak Settings > SMTP Tweaks +# +# This option uses the iptables ipt_owner/xt_owner module and must be loaded +# for it to work. It may not be available on some VPS platforms +# +# Note: Run /etc/csf/csftest.pl to check whether this option will function on +# this server +SMTP_BLOCK = "0" + +# If SMTP_BLOCK is enabled but you want to allow local connections to port 25 +# on the server (e.g. for webmail or web scripts) then enable this option to +# allow outgoing SMTP connections to the loopback device +SMTP_ALLOWLOCAL = "1" + +# This option redirects outgoing SMTP connections destined for remote servers +# for non-bypass users to the local SMTP server to force local relaying of +# email. Such email may require authentication (SMTP AUTH) +SMTP_REDIRECT = "0" + +# This is a comma separated list of the ports to block. You should list all +# ports that exim is configured to listen on +SMTP_PORTS = "25,465,587" + +# Always allow the following comma separated users and groups to bypass +# SMTP_BLOCK +# +# Note: root (UID:0) is always allowed +SMTP_ALLOWUSER = "" +SMTP_ALLOWGROUP = "mail,mailman" + +# This option will only allow SMTP AUTH to be advertised to the IP addresses +# listed in /etc/csf/csf.smtpauth on EXIM mail servers +# +# The additional option CC_ALLOW_SMTPAUTH can be used with this option to +# additionally restrict access to specific countries +# +# This is to help limit attempts at distributed attacks against SMTP AUTH which +# are difficult to achive since port 25 needs to be open to relay email +# +# The reason why this works is that if EXIM does not advertise SMTP AUTH on a +# connection, then SMTP AUTH will not accept logins, defeating the attacks +# without restricting mail relaying +# +# Note: csf and lfd must be restarted if /etc/csf/csf.smtpauth is modified so +# that the lookup file in /etc/exim.smtpauth is regenerated from the +# information from /etc/csf/csf.smtpauth plus any countries listed in +# CC_ALLOW_SMTPAUTH +# +# NOTE: To make this option work you MUST make the modifications to exim.conf +# as explained in "Exim SMTP AUTH Restriction" section in /etc/csf/readme.txt +# after enabling the option here, otherwise this option will not work +# +# To enable this option, set to 1 and make the exim configuration changes +# To disable this option, set to 0 and undo the exim configuration changes +SMTPAUTH_RESTRICT = "0" + +############################################################################### +# SECTION:Port Flood Settings +############################################################################### +# Enable SYN Flood Protection. This option configures iptables to offer some +# protection from tcp SYN packet DOS attempts. You should set the RATE so that +# false-positives are kept to a minimum otherwise visitors may see connection +# issues (check /var/log/messages for *SYNFLOOD Blocked*). See the iptables +# man page for the correct --limit rate syntax +# +# Note: This option should ONLY be enabled if you know you are under a SYN +# flood attack as it will slow down all new connections from any IP address to +# the server if triggered +SYNFLOOD = "0" +SYNFLOOD_RATE = "100/s" +SYNFLOOD_BURST = "150" + +# Connection Limit Protection. This option configures iptables to offer more +# protection from DOS attacks against specific ports. It can also be used as a +# way to simply limit resource usage by IP address to specific server services. +# This option limits the number of concurrent new connections per IP address +# that can be made to specific ports +# +# This feature does not work on servers that do not have the iptables module +# xt_connlimit loaded. Typically, this will be with MONOLITHIC kernels. VPS +# server admins should check with their VPS host provider that the iptables +# module is included +# +# For further information and syntax refer to the Connection Limit Protection +# section of the csf readme.txt +# +# Note: Run /etc/csf/csftest.pl to check whether this option will function on +# this server +CONNLIMIT = "" + +# Port Flood Protection. This option configures iptables to offer protection +# from DOS attacks against specific ports. This option limits the number of +# new connections per time interval that can be made to specific ports +# +# This feature does not work on servers that do not have the iptables module +# ipt_recent loaded. Typically, this will be with MONOLITHIC kernels. VPS +# server admins should check with their VPS host provider that the iptables +# module is included +# +# For further information and syntax refer to the Port Flood Protection +# section of the csf readme.txt +# +# Note: Run /etc/csf/csftest.pl to check whether this option will function on +# this server +PORTFLOOD = "" + +# Outgoing UDP Flood Protection. This option limits outbound UDP packet floods. +# These typically originate from exploit scripts uploaded through vulnerable +# web scripts. Care should be taken on servers that use services that utilise +# high levels of UDP outbound traffic, such as SNMP, so you may need to alter +# the UDPFLOOD_LIMIT and UDPFLOOD_BURST options to suit your environment +# +# We recommend enabling User ID Tracking (UID_INTERVAL) with this feature +UDPFLOOD = "0" +UDPFLOOD_LIMIT = "100/s" +UDPFLOOD_BURST = "500" + +# This is a list of usernames that should not be rate limited, such as "named" +# to prevent bind traffic from being limited. +# +# Note: root (UID:0) is always allowed +UDPFLOOD_ALLOWUSER = "named" + +############################################################################### +# SECTION:Logging Settings +############################################################################### +# Log lfd messages to SYSLOG in addition to /var/log/lfd.log. You must have the +# perl module Sys::Syslog installed to use this feature +SYSLOG = "0" + +# Drop target for incoming iptables rules. This can be set to either DROP or +# REJECT. REJECT will send back an error packet, DROP will not respond at all. +# REJECT is more polite, however it does provide extra information to a hacker +# and lets them know that a firewall is blocking their attempts. DROP hangs +# their connection, thereby frustrating attempts to port scan the server +DROP = "DROP" + +# Drop target for outgoing iptables rules. This can be set to either DROP or +# REJECT as with DROP, however as such connections are from this server it is +# better to REJECT connections to closed ports rather than to DROP them. This +# helps to immediately free up server resources rather than tying them up until +# a connection times out. It also tells the process making the connection that +# it has immediately failed +# +# It is possible that some monolithic kernels may not support the REJECT +# target. If this is the case, csf checks before using REJECT and falls back to +# using DROP, issuing a warning to set this to DROP instead +DROP_OUT = "REJECT" + +# Enable logging of dropped connections to blocked ports to syslog, usually +# /var/log/messages. This option needs to be enabled to use Port Scan Tracking +DROP_LOGGING = "1" + +# Enable logging of dropped incoming connections from blocked IP addresses +# +# This option will be disabled if you enable Port Scan Tracking (PS_INTERVAL) +DROP_IP_LOGGING = "0" + +# Enable logging of dropped outgoing connections +# +# Note: Only outgoing SYN packets for TCP connections are logged, other +# protocols log all packets +# +# We recommend that you enable this option +DROP_OUT_LOGGING = "1" + +# Together with DROP_OUT_LOGGING enabled, this option logs the UID connecting +# out (where available) which can help track abuse +DROP_UID_LOGGING = "1" + +# Only log incoming reserved port dropped connections (0:1023). This can reduce +# the amount of log noise from dropped connections, but will affect options +# such as Port Scan Tracking (PS_INTERVAL) +DROP_ONLYRES = "0" + +# Commonly blocked ports that you do not want logging as they tend to just fill +# up the log file. These ports are specifically blocked (applied to TCP and UDP +# protocols) for incoming connections +DROP_NOLOG = "23,67,68,111,113,135:139,445,500,513,520" + +# Log packets dropped by the packet filtering option PACKET_FILTER +DROP_PF_LOGGING = "0" + +# Log packets dropped by the Connection Limit Protection option CONNLIMIT. If +# this is enabled and Port Scan Tracking (PS_INTERVAL) is also enabled, IP +# addresses breaking the Connection Limit Protection will be blocked +CONNLIMIT_LOGGING = "0" + +# Enable logging of UDP floods. This should be enabled, especially with User ID +# Tracking enabled +UDPFLOOD_LOGGING = "1" + +# Send an alert if log file flooding is detected which causes lfd to skip log +# lines to prevent lfd from looping. If this alert is sent you should check the +# reported log file for the reason for the flooding +LOGFLOOD_ALERT = "0" + +############################################################################### +# SECTION:Reporting Settings +############################################################################### +# By default, lfd will send alert emails using the relevant alert template to +# the To: address configured within that template. Setting the following +# option will override the configured To: field in all lfd alert emails +# +# Leave this option empty to use the To: field setting in each alert template +LF_ALERT_TO = "" + +# By default, lfd will send alert emails using the relevant alert template from +# the From: address configured within that template. Setting the following +# option will override the configured From: field in all lfd alert emails +# +# Leave this option empty to use the From: field setting in each alert template +LF_ALERT_FROM = "" + +# By default, lfd will send all alerts using the SENDMAIL binary. To send using +# SMTP directly, you can set the following to a relaying SMTP server, e.g. +# "127.0.0.1". Leave this setting blank to use SENDMAIL +LF_ALERT_SMTP = "" + +# Block Reporting. lfd can run an external script when it performs and IP +# address block following for example a login failure. The following setting +# is to the full path of the external script which must be executable. See +# readme.txt for format details +# +# Leave this setting blank to disable +BLOCK_REPORT = "" + +# To also run an external script when a temporary block is unblocked. The +# following setting can be the full path of the external script which must be +# executable. See readme.txt for format details +# +# Leave this setting blank to disable +UNBLOCK_REPORT = "" + +# In addition to the standard lfd email alerts, you can additionally enable the +# sending of X-ARF reports (see http://www.xarf.org/specification.html). Only +# block alert messages will be sent. The reports use our schema at: +# https://download.configserver.com/abuse_login-attack_0.2.json +# +# These reports are in a format accepted by many Netblock owners and should +# help them investigate abuse. This option is not designed to automatically +# forward these reports to the Netblock owners and should be checked for +# false-positive blocks before reporting +# +# If available, the report will also include the abuse contact for the IP from +# the Abusix Contact DB: https://abusix.com/contactdb.html +# +# Note: The following block types are not reported through this feature: +# LF_PERMBLOCK, LF_NETBLOCK, LF_DISTATTACK, LF_DISTFTP, RT_*_ALERT +X_ARF = "0" + +# By default, lfd will send emails from the root forwarder. Setting the +# following option will override this +X_ARF_FROM = "" + +# By default, lfd will send emails to the root forwarder. Setting the following +# option will override this +X_ARF_TO = "" + +# If you want to automatically send reports to the abuse contact where found, +# you can enable the following option +# +# Note: You MUST set X_ARF_FROM to a valid email address for this option to +# work. This is so that the abuse contact can reply to the report +# +# However, you should be aware that without manual checking you could be +# reporting innocent IP addresses, including your own clients, yourself and +# your own servers +# +# Additionally, just because a contact address is found, does not mean that +# there is anyone on the end of it reading, processing or acting on such +# reports and you could conceivably reported for sending spam +# +# We do not recommend enabling this option. Abuse reports should be checked and +# verified before being forwarded to the abuse contact +X_ARF_ABUSE = "0" + +############################################################################### +# SECTION:Temp to Perm/Netblock Settings +############################################################################### +# Temporary to Permanent IP blocking. The following enables this feature to +# permanently block IP addresses that have been temporarily blocked more than +# LF_PERMBLOCK_COUNT times in the last LF_PERMBLOCK_INTERVAL seconds. Set +# LF_PERMBLOCK to "1" to enable this feature +# +# Care needs to be taken when setting LF_PERMBLOCK_INTERVAL as it needs to be +# at least LF_PERMBLOCK_COUNT multiplied by the longest temporary time setting +# (TTL) for blocked IPs, to be effective +# +# Set LF_PERMBLOCK to "0" to disable this feature +LF_PERMBLOCK = "1" +LF_PERMBLOCK_INTERVAL = "86400" +LF_PERMBLOCK_COUNT = "4" +LF_PERMBLOCK_ALERT = "1" + +# Permanently block IPs by network class. The following enables this feature +# to permanently block classes of IP address where individual IP addresses +# within the same class LF_NETBLOCK_CLASS have already been blocked more than +# LF_NETBLOCK_COUNT times in the last LF_NETBLOCK_INTERVAL seconds. Set +# LF_NETBLOCK to "1" to enable this feature +# +# This can be an affective way of blocking DDOS attacks launched from within +# the same network class +# +# Valid settings for LF_NETBLOCK_CLASS are "A", "B" and "C", care and +# consideration is required when blocking network classes A or B +# +# Set LF_NETBLOCK to "0" to disable this feature +LF_NETBLOCK = "0" +LF_NETBLOCK_INTERVAL = "86400" +LF_NETBLOCK_COUNT = "4" +LF_NETBLOCK_CLASS = "C" +LF_NETBLOCK_ALERT = "1" + +# Valid settings for LF_NETBLOCK_IPV6 are "/64", "/56", "/48", "/32" and "/24" +# Great care should be taken with IPV6 netblock ranges due to the large number +# of addresses involved +# +# To disable IPv6 netblocks set to "" +LF_NETBLOCK_IPV6 = "" + +############################################################################### +# SECTION:Global Lists/DYNDNS/Blocklists +############################################################################### +# Safe Chain Update. If enabled, all dynamic update chains (GALLOW*, GDENY*, +# SPAMHAUS, DSHIELD, BOGON, CC_ALLOW, CC_DENY, ALLOWDYN*) will create a new +# chain when updating, and insert it into the relevant LOCALINPUT/LOCALOUTPUT +# chain, then flush and delete the old dynamic chain and rename the new chain. +# +# This prevents a small window of opportunity opening when an update occurs and +# the dynamic chain is flushed for the new rules. +# +# This option should not be enabled on servers with long dynamic chains (e.g. +# CC_DENY/CC_ALLOW lists) and low memory. It should also not be enabled on +# Virtuozzo VPS servers with a restricted numiptent value. This is because each +# chain will effectively be duplicated while the update occurs, doubling the +# number of iptables rules +SAFECHAINUPDATE = "0" + +# If you wish to allow access from dynamic DNS records (for example if your IP +# address changes whenever you connect to the internet but you have a dedicated +# dynamic DNS record from the likes of dyndns.org) then you can list the FQDN +# records in csf.dyndns and then set the following to the number of seconds to +# poll for a change in the IP address. If the IP address has changed iptables +# will be updated. +# +# If the FQDN has multiple A records then all of the IP addresses will be +# processed. If IPV6 is enabled, then all IPv6 AAAA IP address records will +# also be allowed. +# +# A setting of 600 would check for IP updates every 10 minutes. Set the value +# to 0 to disable the feature +DYNDNS = "0" + +# To always ignore DYNDNS IP addresses in lfd blocking, set the following +# option to 1 +DYNDNS_IGNORE = "0" + +# The follow Global options allow you to specify a URL where csf can grab a +# centralised copy of an IP allow or deny block list of your own. You need to +# specify the full URL in the following options, i.e.: +# http://www.somelocation.com/allow.txt +# +# The actual retrieval of these IP's is controlled by lfd, so you need to set +# LF_GLOBAL to the interval (in seconds) when you want lfd to retrieve. lfd +# will perform the retrieval when it runs and then again at the specified +# interval. A sensible interval would probably be every 3600 seconds (1 hour). +# A minimum value of 300 is enforced for LF_GLOBAL if enabled +# +# You do not have to specify both an allow and a deny file +# +# You can also configure a global ignore file for IP's that lfd should ignore +LF_GLOBAL = "0" + +GLOBAL_ALLOW = "" +GLOBAL_DENY = "" +GLOBAL_IGNORE = "" + +# Provides the same functionality as DYNDNS but with a GLOBAL URL file. Set +# this to the URL of the file containing DYNDNS entries +GLOBAL_DYNDNS = "" + +# Set the following to the number of seconds to poll for a change in the IP +# address resoved from GLOBAL_DYNDNS +GLOBAL_DYNDNS_INTERVAL = "600" + +# To always ignore GLOBAL_DYNDNS IP addresses in lfd blocking, set the following +# option to 1 +GLOBAL_DYNDNS_IGNORE = "0" + +# Blocklists are controlled by modifying /etc/csf/csf.blocklists +# +# If you don't want BOGON rules applied to specific NICs, then list them in +# a comma separated list (e.g "eth1,eth2") +LF_BOGON_SKIP = "" + +# The following option can be used to select the method csf will use to +# retrieve URL data and files +# +# This can be set to use: +# +# 1. Perl module HTTP::Tiny +# 2. Perl module LWP::UserAgent +# 3. CURL/WGET (set location at the bottom of csf.conf if installed) +# +# HTTP::Tiny is much faster than LWP::UserAgent and is included in the csf +# distribution. LWP::UserAgent may have to be installed manually, but it can +# better support https:// URL's which also needs the LWP::Protocol::https perl +# module +# +# CURL/WGET uses the system binaries if installed but does not always provide +# good feedback when it fails. The script will first look for CURL, if that +# does not exist at the configured location it will then look for WGET +# +# Additionally, 1 or 2 are used and the retrieval fails, then if either CURL or +# WGET are available, an additional attempt will be using CURL/WGET. This is +# useful if the perl distribution has outdated modules that do not support +# modern SSL/TLS implementations +# +# To install the LWP perl modules required: +# +# On rpm based systems: +# +# yum install perl-libwww-perl.noarch perl-LWP-Protocol-https.noarch +# +# On APT based systems: +# +# apt-get install libwww-perl liblwp-protocol-https-perl +# +# Via cpan: +# +# perl -MCPAN -eshell +# cpan> install LWP LWP::Protocol::https +# +# We recommend setting this set to "2" or "3" as upgrades to csf will be +# performed over SSL as well as other URLs used when retrieving external data +# +# "1" = HTTP::Tiny +# "2" = LWP::UserAgent +# "3" = CURL/WGET (set location at the bottom of csf.conf) +URLGET = "2" + +# If you need csf/lfd to use a proxy, then you can set this option to the URL +# of the proxy. The proxy provided will be used for both HTTP and HTTPS +# connections +URLPROXY = "" + +############################################################################### +# SECTION:Country Code Lists and Settings +############################################################################### +# Country Code to CIDR allow/deny. In the following options you can allow or +# deny whole country CIDR ranges. The CIDR blocks are obtained from a selected +# source below. They also display Country Code Country and City for reported IP +# addresses and lookups +# +# There are a number of sources for these databases, before utilising them you +# need to visit each site and ensure you abide by their license provisions +# where stated: + +# 1. MaxMind +# +# MaxMind GeoLite2 Country/City and ASN databases at: +# https://dev.MaxMind.com/geoip/geoip2/geolite2/ +# This feature relies entirely on that service being available +# +# Advantages: This is a one stop shop for all of the databases required for +# these features. They provide a consistent dataset for blocking and reporting +# purposes +# +# Disadvantages: MaxMind require a license key to download their databases. +# This is free of charge, but requires the user to create an account on their +# website to generate the required key: +# +# WARNING: As of 2019-12-29, MaxMind REQUIRES you to create an account on their +# site and to generate a license key to use their databases. See: +# https://www.maxmind.com/en/geolite2/signup +# https://blog.maxmind.com/2019/12/18/significant-changes-to-accessing-and-using-geolite2-databases/ +# +# You MUST set the following to continue using the IP lookup features of csf, +# otherwise an error will be generated and the features will not work. +# Alternatively set CC_SRC below to a different provider +# +# MaxMind License Key: +MM_LICENSE_KEY = "" + +# 2. DB-IP, ipdeny.com, iptoasn.com +# +# Advantages: The ipdeny.com databases form CC blocking are better optimised +# and so are quicker to process and create fewer iptables entries. All of these +# databases are free to download without requiring login or key +# +# Disadvantages: Multiple sources mean that any one of the three could +# interrupt the provision of these features. It may also mean that there are +# inconsistences between them +# +# https://db-ip.com/db/lite.php +# http://ipdeny.com/ +# https://iptoasn.com/ +# http://download.geonames.org/export/dump/readme.txt + +# Set the following to your preferred source: +# +# "1" - MaxMind +# "2" - db-ip, ipdeny, iptoasn +# +# The default is "2" on new installations of csf, or set to "1" to use the +# MaxMind databases after obtaining a license key +CC_SRC = "2" + +# In the following options, specify the the two-letter ISO Country Code(s). +# The iptables rules are for incoming connections only +# +# Additionally, ASN numbers can also be added to the comma separated lists +# below that also list Country Codes. The same WARNINGS for Country Codes apply +# to the use of ASNs. More about Autonomous System Numbers (ASN): +# http://www.iana.org/assignments/as-numbers/as-numbers.xhtml +# ASNs must be listed as ASnnnn (where nnnn is the ASN number) +# +# You should consider using LF_IPSET when using any of the following options +# +# WARNING: These lists are never 100% accurate and some ISP's (e.g. AOL) use +# non-geographic IP address designations for their clients +# +# WARNING: Some of the CIDR lists are huge and each one requires a rule within +# the incoming iptables chain. This can result in significant performance +# overheads and could render the server inaccessible in some circumstances. For +# this reason (amongst others) we do not recommend using these options +# +# WARNING: Due to the resource constraints on VPS servers this feature should +# not be used on such systems unless you choose very small CC zones +# +# WARNING: CC_ALLOW allows access through all ports in the firewall. For this +# reason CC_ALLOW probably has very limited use and CC_ALLOW_FILTER is +# preferred +# +# Each option is a comma separated list of CC's, e.g. "US,GB,DE" +CC_DENY = "" +CC_ALLOW = "" + +# An alternative to CC_ALLOW is to only allow access from the following +# countries but still filter based on the port and packets rules. All other +# connections are dropped +CC_ALLOW_FILTER = "" + +# This option allows access from the following countries to specific ports +# listed in CC_ALLOW_PORTS_TCP and CC_ALLOW_PORTS_UDP +# +# Note: The rules for this feature are inserted after the allow and deny +# rules to still allow blocking of IP addresses +# +# Each option is a comma separated list of CC's, e.g. "US,GB,DE" +CC_ALLOW_PORTS = "" + +# All listed ports should be removed from TCP_IN/UDP_IN to block access from +# elsewhere. This option uses the same format as TCP_IN/UDP_IN +# +# An example would be to list port 21 here and remove it from TCP_IN/UDP_IN +# then only countries listed in CC_ALLOW_PORTS can access FTP +CC_ALLOW_PORTS_TCP = "" +CC_ALLOW_PORTS_UDP = "" + +# This option denies access from the following countries to specific ports +# listed in CC_DENY_PORTS_TCP and CC_DENY_PORTS_UDP +# +# Note: The rules for this feature are inserted after the allow and deny +# rules to still allow allowing of IP addresses +# +# Each option is a comma separated list of CC's, e.g. "US,GB,DE" +CC_DENY_PORTS = "" + +# This option uses the same format as TCP_IN/UDP_IN. The ports listed should +# NOT be removed from TCP_IN/UDP_IN +# +# An example would be to list port 21 here then countries listed in +# CC_DENY_PORTS cannot access FTP +CC_DENY_PORTS_TCP = "" +CC_DENY_PORTS_UDP = "" + +# This Country Code list will prevent lfd from blocking IP address hits for the +# listed CC's +# +# CC_LOOKUPS must be enabled to use this option +CC_IGNORE = "" + +# This Country Code list will only allow SMTP AUTH to be advertised to the +# listed countries in EXIM. This is to help limit attempts at distributed +# attacks against SMTP AUTH which are difficult to achive since port 25 needs +# to be open to relay email +# +# The reason why this works is that if EXIM does not advertise SMTP AUTH on a +# connection, then SMTP AUTH will not accept logins, defeating the attacks +# without restricting mail relaying +# +# This option can generate a very large list of IP addresses that could easily +# severely impact on SMTP (mail) performance, so care must be taken when +# selecting countries and if performance issues ensue +# +# The option SMTPAUTH_RESTRICT must be enabled to use this option +CC_ALLOW_SMTPAUTH = "" + +# These options can control which IP blocks are redirected to the MESSENGER +# service, if it is enabled +# +# If Country Codes are listed in CC_MESSENGER_ALLOW, then only a blocked IP +# that resolves to one of those Country Codes will be redirected to the +# MESSENGER service +# +# If Country Codes are listed in CC_MESSENGER_DENY, then a blocked IP that +# resolves to one of those Country Codes will NOT be redirected to the +# MESSENGER service +# +CC_MESSENGER_ALLOW = "" +CC_MESSENGER_DENY = "" + +# Set this option to a valid CIDR (i.e. 1 to 32) to ignore CIDR blocks smaller +# than this value when implementing CC_DENY/CC_ALLOW/CC_ALLOW_FILTER. This can +# help reduce the number of CC entries and may improve iptables throughput. +# Obviously, this will deny/allow fewer IP addresses depending on how small you +# configure the option +# +# For example, to ignore all CIDR (and single IP) entries small than a /16, set +# this option to "16". Set to "" to block all CC IP addresses +CC_DROP_CIDR = "" + +# Display Country Code and Country for reported IP addresses. This option can +# be configured to use the databases enabled at the top of this section. An +# additional option is also available if you cannot use those databases: +# +# "0" - disable +# "1" - Reports: Country Code and Country +# "2" - Reports: Country Code and Country and Region and City +# "3" - Reports: Country Code and Country and Region and City and ASN +# "4" - Reports: Country Code and Country and Region and City (db-ip.com) +# +# Note: "4" does not use the databases enabled at the top of this section +# directly for lookups. Instead it uses a URL-based lookup from +# https://db-ip.com and so avoids having to download and process the large +# databases. Please visit the https://db-ip.com and read their limitations and +# understand that this option will either cease to function or be removed by us +# if that site is abused or overloaded. ONLY use this option if you have +# difficulties using the databases enabled at the top of this section. This +# option is ONLY for IP lookups, NOT when using the CC_* options above, which +# will continue to use the databases enabled at the top of this section +# +CC_LOOKUPS = "1" + +# Display Country Code and Country for reported IPv6 addresses using the +# databases enabled at the top of this section +# +# "0" - disable +# "1" - enable and report the detail level as specified in CC_LOOKUPS +# +# This option must also be enabled to allow IPv6 support to CC_*, MESSENGER and +# PORTFLOOD +CC6_LOOKUPS = "0" + +# This option tells lfd how often to retrieve the databases for CC_ALLOW, +# CC_ALLOW_FILTER, CC_DENY, CC_IGNORE and CC_LOOKUPS (in days) +CC_INTERVAL = "14" + +############################################################################### +# SECTION:Login Failure Blocking and Alerts +############################################################################### +# The following[*] triggers are application specific. If you set LF_TRIGGER to +# "0" the value of each trigger is the number of failures against that +# application that will trigger lfd to block the IP address +# +# If you set LF_TRIGGER to a value greater than "0" then the following[*] +# application triggers are simply on or off ("0" or "1") and the value of +# LF_TRIGGER is the total cumulative number of failures that will trigger lfd +# to block the IP address +# +# Setting the application trigger to "0" disables it +LF_TRIGGER = "0" + +# If LF_TRIGGER is > "0" then LF_TRIGGER_PERM can be set to "1" to permanently +# block the IP address, or LF_TRIGGER_PERM can be set to a value greater than +# "1" and the IP address will be blocked temporarily for that value in seconds. +# For example: +# LF_TRIGGER_PERM = "1" => the IP is blocked permanently +# LF_TRIGGER_PERM = "3600" => the IP is blocked temporarily for 1 hour +# +# If LF_TRIGGER is "0", then the application LF_[application]_PERM value works +# in the same way as above and LF_TRIGGER_PERM serves no function +LF_TRIGGER_PERM = "1" + +# To only block access to the failed application instead of a complete block +# for an ip address, you can set the following to "1", but LF_TRIGGER must be +# set to "0" with specific application[*] trigger levels also set appropriately +# +# The ports that are blocked can be configured by changing the PORTS_* options +LF_SELECT = "0" + +# Send an email alert if an IP address is blocked by one of the [*] triggers +LF_EMAIL_ALERT = "1" + +# Send an email alert if an IP address is only temporarily blocked by one of +# the [*] triggers +# +# Note: LF_EMAIL_ALERT must still be enabled to get permanent block emails +LF_TEMP_EMAIL_ALERT = "1" + +# [*]Enable login failure detection of sshd connections +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_SSHD = "5" +LF_SSHD_PERM = "1" + +# [*]Enable login failure detection of ftp connections +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_FTPD = "10" +LF_FTPD_PERM = "1" + +# [*]Enable login failure detection of SMTP AUTH connections +LF_SMTPAUTH = "5" +LF_SMTPAUTH_PERM = "1" + +# [*]Enable syntax failure detection of Exim connections +LF_EXIMSYNTAX = "10" +LF_EXIMSYNTAX_PERM = "1" + +# [*]Enable login failure detection of pop3 connections +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_POP3D = "0" +LF_POP3D_PERM = "1" + +# [*]Enable login failure detection of imap connections +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_IMAPD = "0" +LF_IMAPD_PERM = "1" + +# [*]Enable login failure detection of Apache .htpasswd connections +# Due to the often high logging rate in the Apache error log, you might want to +# enable this option only if you know you are suffering from attacks against +# password protected directories +LF_HTACCESS = "5" +LF_HTACCESS_PERM = "1" + +# [*]Enable failure detection of repeated Apache mod_security rule triggers +LF_MODSEC = "5" +LF_MODSEC_PERM = "1" + +# [*]Enable login failure detection of VestaCP connections +LF_VESTA = "5" +LF_VESTA_PERM = "1" + +# [*]Enable detection of repeated BIND denied requests +# This option should be enabled with care as it will prevent blocked IPs from +# resolving any domains on the server. You might want to set the trigger value +# reasonably high to avoid this +# Example: LF_BIND = "100" +LF_BIND = "0" +LF_BIND_PERM = "1" + +# [*]Enable detection of repeated suhosin ALERTs +# Example: LF_SUHOSIN = "5" +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_SUHOSIN = "0" +LF_SUHOSIN_PERM = "1" + +# [*]Enable detection of repeated cxs ModSecurity mod_security rule triggers +# This option will block IP addresses if cxs detects a hits from the +# ModSecurity rule associated with it +# +# Note: This option takes precedence over LF_MODSEC and removes any hits +# counted towards LF_MODSEC for the cxs rule +# +# This setting should probably set very low, perhaps to 1, if you want to +# effectively block IP addresses for this trigger option +LF_CXS = "0" +LF_CXS_PERM = "1" + +# [*]Enable detection of repeated Apache mod_qos rule triggers +LF_QOS = "0" +LF_QOS_PERM = "1" + +# [*]Enable detection of repeated Apache symlink race condition triggers from +# the Apache patch provided by: +# http://www.mail-archive.com/dev@httpd.apache.org/msg55666.html +# This patch has also been included by cPanel via the easyapache option: +# "Symlink Race Condition Protection" +LF_SYMLINK = "0" +LF_SYMLINK_PERM = "1" + +# [*]Enable login failure detection of webmin connections +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_WEBMIN = "0" +LF_WEBMIN_PERM = "1" + +# Send an email alert if anyone logs in successfully using SSH +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_SSH_EMAIL_ALERT = "1" + +# Send an email alert if anyone uses su to access another account. This will +# send an email alert whether the attempt to use su was successful or not +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_SU_EMAIL_ALERT = "1" + +# Send an email alert if anyone uses sudo to access another account. This will +# send an email alert whether the attempt to use sudo was successful or not +# +# NOTE: This option could become onerous if sudo is used extensively for root +# access by administrators or control panels. It is provided for those where +# this is not the case +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_SUDO_EMAIL_ALERT = "0" + +# Send an email alert if anyone accesses webmin +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_WEBMIN_EMAIL_ALERT = "1" + +# Send an email alert if anyone logs in successfully to root on the console +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_CONSOLE_EMAIL_ALERT = "1" + +# This option will keep track of the number of "File does not exist" errors in +# HTACCESS_LOG. If the number of hits is more than LF_APACHE_404 in LF_INTERVAL +# seconds then the IP address will be blocked +# +# Care should be used with this option as it could generate many +# false-positives, especially Search Bots (use csf.rignore to ignore such bots) +# so only use this option if you know you are under this type of attack +# +# A sensible setting for this would be quite high, perhaps 200 +# +# To disable set to "0" +LF_APACHE_404 = "0" + +# If this option is set to 1 the blocks will be permanent +# If this option is > 1, the blocks will be temporary for the specified number +# of seconds +LF_APACHE_404_PERM = "3600" + +# This option will keep track of the number of "client denied by server +# configuration" errors in HTACCESS_LOG. If the number of hits is more than +# LF_APACHE_403 in LF_INTERVAL seconds then the IP address will be blocked +# +# Care should be used with this option as it could generate many +# false-positives, especially Search Bots (use csf.rignore to ignore such bots) +# so only use this option if you know you are under this type of attack +# +# A sensible setting for this would be quite high, perhaps 200 +# +# To disable set to "0" +LF_APACHE_403 = "0" + +# If this option is set to 1 the blocks will be permanent +# If this option is > 1, the blocks will be temporary for the specified number +# of seconds +LF_APACHE_403_PERM = "3600" + +# This option will keep track of the number of 401 failures in HTACCESS_LOG. +# If the number of hits is more than LF_APACHE_401 in LF_INTERVAL seconds then +# the IP address will be blocked +# +# To disable set to "0" +LF_APACHE_401 = "0" + +# This option is used to determine if the Apache error_log format contains the +# client port after the client IP. In Apache prior to v2.4, this was not the +# case. In Apache v2.4+ the error_log format can be configured using +# ErrorLogFormat, making the port directive optional +# +# Unfortunately v2.4 ErrorLogFormat places the port number after a colon next +# to the client IP by default. This makes determining client IPv6 addresses +# difficult unless we know whether the port is being appended or not +# +# lfd will attempt to autodetect the correct value if this option is set to "0" +# from the httpd binary found in common locations. If it fails to find a binary +# it will be set to "2", unless specified here +# +# The value can be set here explicitly if the autodetection does not work: +# 0 - autodetect +# 1 - no port directive after client IP +# 2 - port directive after client IP +LF_APACHE_ERRPORT = "0" + +# If this option is set to 1 the blocks will be permanent +# If this option is > 1, the blocks will be temporary for the specified number +# of seconds +LF_APACHE_401_PERM = "3600" + +# This option will send an alert if the ModSecurity IP persistent storage grows +# excessively large: https://goo.gl/rGh5sF +# +# More information on cPanel servers here: https://goo.gl/vo6xTE +# +# LF_MODSECIPDB_FILE must be set to the correct location of the database file +# +# The check is performed at lfd startup and then once per hour, the template +# used is modsecipdbalert.txt +# +# Set to "0" to disable this option, otherwise it is the threshold size of the +# file to report in gigabytes, e.g. set to 5 for 5GB +LF_MODSECIPDB_ALERT = "0" + +# This is the location of the persistent IP storage file on the server, e.g.: +# /var/run/modsecurity/data/ip.pag +# /var/cpanel/secdatadir/ip.pag +# /var/cache/modsecurity/ip.pag +# /usr/local/apache/conf/modsec/data/msa/ip.pag +# /var/tmp/ip.pag +# /tmp/ip.pag +LF_MODSECIPDB_FILE = "/var/run/modsecurity/data/ip.pag" + +# System Exploit Checking. This option is designed to perform a series of tests +# to send an alert in case a possible server compromise is detected +# +# To enable this feature set the following to the checking interval in seconds +# (a value of 300 would seem sensible). +# +# To disable set to "0" +LF_EXPLOIT = "300" + +# This comma separated list allows you to ignore tests LF_EXPLOIT performs +# +# For the SUPERUSER check, you can list usernames in csf.suignore to have them +# ignored for that test +# +# Valid tests are: +# SUPERUSER +# +# If you want to ignore a test add it to this as a comma separated list, e.g. +# "SUPERUSER" +LF_EXPLOIT_IGNORE = "" + +# Set the time interval to track login and other LF_ failures within (seconds), +# i.e. LF_TRIGGER failures within the last LF_INTERVAL seconds +LF_INTERVAL = "3600" + +# This is how long the lfd process sleeps (in seconds) before processing the +# log file entries and checking whether other events need to be triggered +LF_PARSE = "5" + +# This is the interval that is used to flush reports of usernames, files and +# pids so that persistent problems continue to be reported, in seconds. +# A value of 3600 seems sensible +LF_FLUSH = "3600" + +# Under some circumstances iptables can fail to include a rule instruction, +# especially if more than one request is made concurrently. In this event, a +# permanent block entry may exist in csf.deny, but not in iptables. +# +# This option instructs csf to deny an already blocked IP address the number +# of times set. The downside, is that there will be multiple entries for an IP +# address in csf.deny and possibly multiple rules for the same IP address in +# iptables. This needs to be taken into consideration when unblocking such IP +# addresses. +# +# Set to "0" to disable this feature. Do not set this too high for the reasons +# detailed above (e.g. "5" should be more than enough) +LF_REPEATBLOCK = "0" + +# By default csf will create both an inbound and outbound blocks from/to an IP +# unless otherwise specified in csf.deny and GLOBAL_DENY. This is the most +# effective way to block IP traffic. This option instructs csf to only block +# inbound traffic from those IP's and so reduces the number of iptables rules, +# but at the expense of less effectiveness. For this reason we recommend +# leaving this option disabled +# +# Set to "0" to disable this feature - the default +LF_BLOCKINONLY = "0" + +############################################################################### +# SECTION:CloudFlare +############################################################################### +# This features provides interaction with the CloudFlare Firewall +# +# As CloudFlare is a reverse proxy, any attacking IP addresses (so far as +# iptables is concerned) come from the CloudFlare IP's. To counter this, an +# Apache module (mod_cloudflare) is available that obtains the true attackers +# IP from a custom HTTP header record (similar functionality is available +# for other HTTP daemons +# +# However, despite now knowing the true attacking IP address, iptables cannot +# be used to block that IP as the traffic is still coming from the CloudFlare +# servers +# +# CloudFlare have provided a Firewall feature within the user account where +# rules can be added to block, challenge or whitelist IP addresses +# +# Using the CloudFlare API, this feature adds and removes attacking IPs from +# that firewall and provides CLI (and via the UI) additional commands +# +# See /etc/csf/readme.txt for more information about this feature and the +# restrictions for its use BEFORE enabling this feature +CF_ENABLE = "0" + +# This can be set to either "block" or "challenge" (see CloudFlare docs) +CF_BLOCK = "block" + +# This setting determines how long the temporary block will apply within csf +# and CloudFlare, keeping them in sync +# +# Block duration in seconds - overrides perm block or time of individual blocks +# in lfd for block triggers +CF_TEMP = "3600" + +############################################################################### +# SECTION:Directory Watching & Integrity +############################################################################### +# Enable Directory Watching. This enables lfd to check /tmp and /dev/shm +# directories for suspicious files, i.e. script exploits. If a suspicious +# file is found an email alert is sent. One alert per file per LF_FLUSH +# interval is sent +# +# To enable this feature set the following to the checking interval in seconds. +# To disable set to "0" +LF_DIRWATCH = "300" + +# To remove any suspicious files found during directory watching, enable the +# following. These files will be appended to a tarball in +# /var/lib/csf/suspicious.tar +LF_DIRWATCH_DISABLE = "0" + +# This option allows you to have lfd watch a particular file or directory for +# changes and should they change and email alert using watchalert.txt is sent +# +# To enable this feature set the following to the checking interval in seconds +# (a value of 60 would seem sensible) and add your entries to csf.dirwatch +# +# Set to disable set to "0" +LF_DIRWATCH_FILE = "0" + +# System Integrity Checking. This enables lfd to compare md5sums of the +# servers OS binary application files from the time when lfd starts. If the +# md5sum of a monitored file changes an alert is sent. This option is intended +# as an IDS (Intrusion Detection System) and is the last line of detection for +# a possible root compromise. +# +# There will be constant false-positives as the servers OS is updated or +# monitored application binaries are updated. However, unexpected changes +# should be carefully inspected. +# +# Modified files will only be reported via email once. +# +# To enable this feature set the following to the checking interval in seconds +# (a value of 3600 would seem sensible). This option may increase server I/O +# load onto the server as it checks system binaries. +# +# To disable set to "0" +LF_INTEGRITY = "3600" + +############################################################################### +# SECTION:Distributed Attacks +############################################################################### +# Distributed Account Attack. This option will keep track of login failures +# from distributed IP addresses to a specific application account. If the +# number of failures matches the trigger value above, ALL of the IP addresses +# involved in the attack will be blocked according to the temp/perm rules above +# +# Tracking applies to LF_SSHD, LF_FTPD, LF_SMTPAUTH, LF_POP3D, LF_IMAPD, +# LF_HTACCESS +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_DISTATTACK = "0" + +# Set the following to the minimum number of unique IP addresses that trigger +# LF_DISTATTACK +LF_DISTATTACK_UNIQ = "2" + +# Distributed FTP Logins. This option will keep track of successful FTP logins. +# If the number of successful logins to an individual account is at least +# LF_DISTFTP in LF_DIST_INTERVAL from at least LF_DISTFTP_UNIQ IP addresses, +# then all of the IP addresses will be blocked +# +# This option can help mitigate the common FTP account compromise attacks that +# use a distributed network of zombies to deface websites +# +# A sensible setting for this might be 5, depending on how many different +# IP addresses you expect to an individual FTP account within LF_DIST_INTERVAL +# +# To disable set to "0" +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LF_DISTFTP = "0" + +# Set the following to the minimum number of unique IP addresses that trigger +# LF_DISTFTP. LF_DISTFTP_UNIQ must be <= LF_DISTFTP for this to work +LF_DISTFTP_UNIQ = "3" + +# If this option is set to 1 the blocks will be permanent +# If this option is > 1, the blocks will be temporary for the specified number +# of seconds +LF_DISTFTP_PERM = "1" + +# Send an email alert if LF_DISTFTP is triggered +LF_DISTFTP_ALERT = "1" + +# Distributed SMTP Logins. This option will keep track of successful SMTP +# logins. If the number of successful logins to an individual account is at +# least LF_DISTSMTP in LF_DIST_INTERVAL from at least LF_DISTSMTP_UNIQ IP +# addresses, then all of the IP addresses will be blocked. These options only +# apply to the exim MTA +# +# This option can help mitigate the common SMTP account compromise attacks that +# use a distributed network of zombies to send spam +# +# A sensible setting for this might be 5, depending on how many different +# IP addresses you expect to an individual SMTP account within LF_DIST_INTERVAL +# +# To disable set to "0" +LF_DISTSMTP = "0" + +# Set the following to the minimum number of unique IP addresses that trigger +# LF_DISTSMTP. LF_DISTSMTP_UNIQ must be <= LF_DISTSMTP for this to work +LF_DISTSMTP_UNIQ = "3" + +# If this option is set to 1 the blocks will be permanent +# If this option is > 1, the blocks will be temporary for the specified number +# of seconds +LF_DISTSMTP_PERM = "1" + +# Send an email alert if LF_DISTSMTP is triggered +LF_DISTSMTP_ALERT = "1" + +# This is the interval during which a distributed FTP or SMTP attack is +# measured +LF_DIST_INTERVAL = "300" + +# If LF_DISTFTP or LF_DISTSMTP is triggered, then if the following contains the +# path to a script, it will run the script and pass the following as arguments: +# +# LF_DISTFTP/LF_DISTSMTP +# account name +# log file text +# +# The action script must have the execute bit and interpreter (shebang) set +LF_DIST_ACTION = "" + +############################################################################### +# SECTION:Login Tracking +############################################################################### +# Block POP3 logins if greater than LT_POP3D times per hour per account per IP +# address (0=disabled) +# +# This is a temporary block for the rest of the hour, afterwhich the IP is +# unblocked +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LT_POP3D = "0" + +# Block IMAP logins if greater than LT_IMAPD times per hour per account per IP +# address (0=disabled) - not recommended for IMAP logins due to the ethos +# within which IMAP works. If you want to use this, setting it quite high is +# probably a good idea +# +# This is a temporary block for the rest of the hour, afterwhich the IP is +# unblocked +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +LT_IMAPD = "0" + +# Send an email alert if an account exceeds LT_POP3D/LT_IMAPD logins per hour +# per IP +LT_EMAIL_ALERT = "1" + +# If LF_PERMBLOCK is enabled but you do not want this to apply to +# LT_POP3D/LT_IMAPD, then enable this option +LT_SKIPPERMBLOCK = "0" + +############################################################################### +# SECTION:Connection Tracking +############################################################################### +# Connection Tracking. This option enables tracking of all connections from IP +# addresses to the server. If the total number of connections is greater than +# this value then the offending IP address is blocked. This can be used to help +# prevent some types of DOS attack. +# +# Care should be taken with this option. It's entirely possible that you will +# see false-positives. Some protocols can be connection hungry, e.g. FTP, IMAPD +# and HTTP so it could be quite easy to trigger, especially with a lot of +# closed connections in TIME_WAIT. However, for a server that is prone to DOS +# attacks this may be very useful. A reasonable setting for this option might +# be around 300. +# +# To disable this feature, set this to 0 +CT_LIMIT = "0" + +# Connection Tracking interval. Set this to the the number of seconds between +# connection tracking scans +CT_INTERVAL = "30" + +# Send an email alert if an IP address is blocked due to connection tracking +CT_EMAIL_ALERT = "1" + +# If you want to make IP blocks permanent then set this to 1, otherwise blocks +# will be temporary and will be cleared after CT_BLOCK_TIME seconds +CT_PERMANENT = "0" + +# If you opt for temporary IP blocks for CT, then the following is the interval +# in seconds that the IP will remained blocked for (e.g. 1800 = 30 mins) +CT_BLOCK_TIME = "1800" + +# If you don't want to count the TIME_WAIT state against the connection count +# then set the following to "1" +CT_SKIP_TIME_WAIT = "0" + +# If you only want to count specific states (e.g. SYN_RECV) then add the states +# to the following as a comma separated list. E.g. "SYN_RECV,TIME_WAIT" +# +# Leave this option empty to count all states against CT_LIMIT +CT_STATES = "" + +# If you only want to count specific ports (e.g. 80,443) then add the ports +# to the following as a comma separated list. E.g. "80,443" +# +# Leave this option empty to count all ports against CT_LIMIT +CT_PORTS = "" + +# If the total number of connections from a class C subnet is greater than this +# value then the offending subnet is blocked according to the other CT_* +# settings +# +# This option can be used to help prevent some types of DOS attack where a +# range of IP's between x.y.z.1-255 has connected to the server +# +# If you use a reverse proxy service such as Cloudflare you should not enable +# this option, or should exclude the ports that you have proxied in CT_PORTS +# +# To disable this feature, set this to 0 +CT_SUBNET_LIMIT = "0" + +############################################################################### +# SECTION:Process Tracking +############################################################################### +# Process Tracking. This option enables tracking of user and nobody processes +# and examines them for suspicious executables or open network ports. Its +# purpose is to identify potential exploit processes that are running on the +# server, even if they are obfuscated to appear as system services. If a +# suspicious process is found an alert email is sent with relevant information. +# It is then the responsibility of the recipient to investigate the process +# further as the script takes no further action +# +# The following is the number of seconds a process has to be active before it +# is inspected. If you set this time too low, then you will likely trigger +# false-positives with CGI or PHP scripts. +# Set the value to 0 to disable this feature +PT_LIMIT = "60" + +# How frequently processes are checked in seconds +PT_INTERVAL = "60" + +# If you want process tracking to highlight php or perl scripts that are run +# through apache then disable the following, +# i.e. set it to 0 +# +# While enabling this setting will reduce false-positives, having it set to 0 +# does provide better checking for exploits running on the server +PT_SKIP_HTTP = "0" + +# lfd will report processes, even if they're listed in csf.pignore, if they're +# tagged as (deleted) by Linux. This information is provided in Linux under +# /proc/PID/exe. A (deleted) process is one that is running a binary that has +# the inode for the file removed from the file system directory. This usually +# happens when the binary has been replaced due to an upgrade for it by the OS +# vendor or another third party (e.g. cPanel). You need to investigate whether +# this is indeed the case to be sure that the original binary has not been +# replaced by a rootkit or is running an exploit. +# +# Note: If a deleted executable process is detected and reported then lfd will +# not report children of the parent (or the parent itself if a child triggered +# the report) if the parent is also a deleted executable process +# +# To stop lfd reporting such process you need to restart the daemon to which it +# belongs and therefore run the process using the replacement binary (presuming +# one exists). This will normally mean running the associated startup script in +# /etc/init.d/ +# +# If you do want lfd to report deleted binary processes, set to 1 +PT_DELETED = "0" + +# If a PT_DELETED event is triggered, then if the following contains the path to +# a script, it will be run in a child process and passed the executable, pid, +# account for the process, and parent pid +# +# The action script must have the execute bit and interpreter (shebang) set. An +# example is provided in /usr/local/csf/bin/pt_deleted_action.pl +# +# WARNING: Make sure you read and understand the potential security +# implications of such processes in PT_DELETED above before simply restarting +# such processes with a script +PT_DELETED_ACTION = "" + +# User Process Tracking. This option enables the tracking of the number of +# process any given account is running at one time. If the number of processes +# exceeds the value of the following setting an email alert is sent with +# details of those processes. If you specify a user in csf.pignore it will be +# ignored +# +# Set to 0 to disable this feature +PT_USERPROC = "10" + +# This User Process Tracking option sends an alert if any user process exceeds +# the virtual memory usage set (MB). To ignore specific processes or users use +# csf.pignore +# +# Set to 0 to disable this feature +PT_USERMEM = "512" + +# This User Process Tracking option sends an alert if any user process exceeds +# the RSS memory usage set (MB) - RAM used, not virtual. To ignore specific +# processes or users use csf.pignore +# +# Set to 0 to disable this feature +PT_USERRSS = "256" + +# This User Process Tracking option sends an alert if any linux user process +# exceeds the time usage set (seconds). To ignore specific processes or users +# use csf.pignore +# +# Set to 0 to disable this feature +PT_USERTIME = "1800" + +# If this option is set then processes detected by PT_USERMEM, PT_USERTIME or +# PT_USERPROC are killed +# +# Warning: We don't recommend enabling this option unless absolutely necessary +# as it can cause unexpected problems when processes are suddenly terminated. +# It can also lead to system processes being terminated which could cause +# stability issues. It is much better to leave this option disabled and to +# investigate each case as it is reported when the triggers above are breached +# +# Note: Processes that are running deleted excecutables (see PT_DELETED) will +# not be killed by lfd +PT_USERKILL = "0" + +# If you want to disable email alerts if PT_USERKILL is triggered, then set +# this option to 0 +PT_USERKILL_ALERT = "1" + +# If a PT_* event is triggered, then if the following contains the path to +# a script, it will be run in a child process and passed the PID(s) of the +# process(es) in a comma separated list. +# +# The action script must have the execute bit and interpreter (shebang) set +PT_USER_ACTION = "" + +# Check the PT_LOAD_AVG minute Load Average (can be set to 1 5 or 15 and +# defaults to 5 if set otherwise) on the server every PT_LOAD seconds. If the +# load average is greater than or equal to PT_LOAD_LEVEL then an email alert is +# sent. lfd then does not report subsequent high load until PT_LOAD_SKIP +# seconds has passed to prevent email floods. +# +# Set PT_LOAD to "0" to disable this feature +PT_LOAD = "30" +PT_LOAD_AVG = "5" +PT_LOAD_LEVEL = "6" +PT_LOAD_SKIP = "3600" + +# This is the Apache Server Status URL used in the email alert. Requires the +# Apache mod_status module to be installed and configured correctly +PT_APACHESTATUS = "http://127.0.0.1/server-status" + +# If a PT_LOAD event is triggered, then if the following contains the path to +# a script, it will be run in a child process. For example, the script could +# contain commands to terminate and restart httpd, php, exim, etc incase of +# looping processes. The action script must have the execute bit an +# interpreter (shebang) set +PT_LOAD_ACTION = "" + +# Fork Bomb Protection. This option checks the number of processes with the +# same session id and if greater than the value set, the whole session tree is +# terminated and an alert sent +# +# You can see an example of common session id processes on most Linux systems +# using: "ps axf -O sid" +# +# On cPanel servers, PT_ALL_USERS should be enabled to use this option +# effectively +# +# This option will check root owned processes. Session id 0 and 1 will always +# be ignored as they represent kernel and init processes. csf.pignore will be +# honoured, but bear in mind that a session tree can contain a variety of users +# and executables +# +# Care needs to be taken to ensure that this option only detects runaway fork +# bombs, so should be set higher than any session tree is likely to get (e.g. +# httpd could have 100s of legitimate children on very busy systems). A +# sensible starting point on most servers might be 250 +PT_FORKBOMB = "0" + +# Terminate hung SSHD sessions. When under an SSHD login attack, SSHD processes +# are often left hanging after their connecting IP addresses have been blocked +# +# This option will terminate the SSH processes created by the blocked IP. This +# option is preferred over PT_SSHDHUNG +PT_SSHDKILL = "0" + +# This option will terminate all processes with the cmdline of "sshd: unknown +# [net]" or "sshd: unknown [priv]" if they have been running for more than 60 +# seconds +PT_SSHDHUNG = "0" + +############################################################################### +# SECTION:Port Scan Tracking +############################################################################### +# Port Scan Tracking. This feature tracks port blocks logged by iptables to +# syslog. If an IP address generates a port block that is logged more than +# PS_LIMIT within PS_INTERVAL seconds, the IP address will be blocked. +# +# This feature could, for example, be useful for blocking hackers attempting +# to access the standard SSH port if you have moved it to a port other than 22 +# and have removed 22 from the TCP_IN list so that connection attempts to the +# old port are being logged +# +# This feature blocks all iptables blocks from the iptables logs, including +# repeated attempts to one port or SYN flood blocks, etc +# +# Note: This feature will only track iptables blocks from the log file set in +# IPTABLES_LOG below and if you have DROP_LOGGING enabled. However, it will +# cause redundant blocking with DROP_IP_LOGGING enabled +# +# Warning: It's possible that an elaborate DDOS (i.e. from multiple IP's) +# could very quickly fill the iptables rule chains and cause a DOS in itself. +# The DENY_IP_LIMIT should help to mitigate such problems with permanent blocks +# and the DENY_TEMP_IP_LIMIT with temporary blocks +# +# Set PS_INTERVAL to "0" to disable this feature. A value of between 60 and 300 +# would be sensible to enable this feature +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +PS_INTERVAL = "0" +PS_LIMIT = "10" + +# You can specify the ports and/or port ranges that should be tracked by the +# Port Scan Tracking feature. The following setting is a comma separated list +# of those ports and uses the same format as TCP_IN. The setting of +# 0:65535,ICMP,INVALID,OPEN,BRD covers all ports +# +# Special values are: +# ICMP - include ICMP blocks (see ICMP_*) +# INVALID - include INVALID blocks (see PACKET_FILTER) +# OPEN - include TCP_IN and UDP_IN open port blocks - *[proto]_IN Blocked* +# BRD - include UDP Broadcast IPs, otherwise they are ignored +PS_PORTS = "0:65535,ICMP" + +# To specify how many different ports qualifies as a Port Scan you can increase +# the following from the default value of 1. The risk in doing so will mean +# that persistent attempts to attack a specific closed port will not be +# detected and blocked +PS_DIVERSITY = "1" + +# You can select whether IP blocks for Port Scan Tracking should be temporary +# or permanent. Set PS_PERMANENT to "0" for temporary and "1" for permanent +# blocking. If set to "0" PS_BLOCK_TIME is the amount of time in seconds to +# temporarily block the IP address for +PS_PERMANENT = "0" +PS_BLOCK_TIME = "3600" + +# Set the following to "1" to enable Port Scan Tracking email alerts, set to +# "0" to disable them +PS_EMAIL_ALERT = "1" + +############################################################################### +# SECTION:User ID Tracking +############################################################################### +# User ID Tracking. This feature tracks UID blocks logged by iptables to +# syslog. If a UID generates a port block that is logged more than UID_LIMIT +# times within UID_INTERVAL seconds, an alert will be sent +# +# Note: This feature will only track iptables blocks from the log file set in +# IPTABLES_LOG and if DROP_OUT_LOGGING and DROP_UID_LOGGING are enabled. +# +# To ignore specific UIDs list them in csf.uidignore and then restart lfd +# +# Set UID_INTERVAL to "0" to disable this feature. A value of between 60 and 300 +# would be sensible to enable this feature +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +UID_INTERVAL = "0" +UID_LIMIT = "10" + +# You can specify the ports and/or port ranges that should be tracked by the +# User ID Tracking feature. The following setting is a comma separated list +# of those ports and uses the same format as TCP_OUT. The default setting of +# 0:65535,ICMP covers all ports +UID_PORTS = "0:65535,ICMP" + +############################################################################### +# SECTION:Account Tracking +############################################################################### +# Account Tracking. The following options enable the tracking of modifications +# to the accounts on a server. If any of the enabled options are triggered by +# a modifications to an account, an alert email is sent. Only the modification +# is reported. The cause of the modification will have to be investigated +# manually +# +# You can set AT_ALERT to the following: +# 0 = disable this feature +# 1 = enable this feature for all accounts +# 2 = enable this feature only for superuser accounts (UID = 0, e.g. root, etc) +# 3 = enable this feature only for the root account +AT_ALERT = "2" + +# This options is the interval between checks in seconds +AT_INTERVAL = "60" + +# Send alert if a new account is created +AT_NEW = "1" + +# Send alert if an existing account is deleted +AT_OLD = "1" + +# Send alert if an account password has changed +AT_PASSWD = "1" + +# Send alert if an account uid has changed +AT_UID = "1" + +# Send alert if an account gid has changed +AT_GID = "1" + +# Send alert if an account login directory has changed +AT_DIR = "1" + +# Send alert if an account login shell has changed +AT_SHELL = "1" + +############################################################################### +# SECTION:Integrated User Interface +############################################################################### +# Integrated User Interface. This feature provides a HTML UI to csf and lfd, +# without requiring a control panel or web server. The UI runs as a sub process +# to the lfd daemon +# +# As it runs under the root account and successful login provides root access +# to the server, great care should be taken when configuring and using this +# feature. There are additional restrictions to enhance secure access to the UI +# +# See readme.txt for more information about using this feature BEFORE enabling +# it for security and access reasons +# +# 1 to enable, 0 to disable +UI = "0" + +# Set this to the port that want to bind this service to. You should configure +# this port to be >1023 and different from any other port already being used +# +# Do NOT enable access to this port in TCP_IN, instead only allow trusted IP's +# to the port using Advanced Allow Filters (see readme.txt) +UI_PORT = "6666" + +# Optionally set the IP address to bind to. Normally this should be left blank +# to bind to all IP addresses on the server. +# +# If the server is configured for IPv6 but the IP to bind to is IPv4, then the +# IP address MUST use the IPv6 representation. For example 1.2.3.4 must use +# ::ffff:1.2.3.4 +# +# Leave blank to bind to all IP addresses on the server +UI_IP = "" + +# This should be a secure, hard to guess username +# +# This must be changed from the default +UI_USER = "username" + +# This should be a secure, hard to guess password. That is, at least 8 +# characters long with a mixture of upper and lowercase characters plus +# numbers and non-alphanumeric characters +# +# This must be changed from the default +UI_PASS = "password" + +# This is the login session timeout. If there is no activity for a logged in +# session within this number of seconds, the session will timeout and a new +# login will be required +# +# For security reasons, you should always keep this option low (i.e 60-300) +UI_TIMEOUT = "300" + +# This is the maximum concurrent connections allowed to the server. The default +# value should be sufficient +UI_CHILDREN = "5" + +# The number of login retries allowed within a 24 hour period. A successful +# login from the IP address will clear the failures +# +# For security reasons, you should always keep this option low (i.e 0-10) +UI_RETRY = "5" + +# If enabled, this option will add the connecting IP address to the file +# /etc/csf/ui/ui.ban after UI_RETRY login failures. The IP address will not be +# able to login to the UI while it is listed in this file. The UI_BAN setting +# does not refer to any of the csf/lfd allow or ignore files, e.g. csf.allow, +# csf.ignore, etc. +# +# For security reasons, you should always enable this option +UI_BAN = "1" + +# If enabled, only IPs (or CIDR's) listed in the file /etc/csf/ui/ui.allow will +# be allowed to login to the UI. The UI_ALLOW setting does not refer to any of +# the csf/lfd allow or ignore files, e.g. csf.allow, csf.ignore, etc. +# +# For security reasons, you should always enable this option and use ui.allow +UI_ALLOW = "1" + +# If enabled, this option will trigger an iptables block through csf after +# UI_RETRY login failures +# +# 0 = no block;1 = perm block;nn=temp block for nn secs +UI_BLOCK = "1" + +# This controls what email alerts are sent with regards to logins to the UI. It +# uses the uialert.txt template +# +# 4 = login success + login failure/ban/block + login attempts +# 3 = login success + login failure/ban/block +# 2 = login failure/ban/block +# 1 = login ban/block +# 0 = disabled +UI_ALERT = "4" + +# This is the SSL cipher list that the Integrated UI will negotiate from +UI_CIPHER = "ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:-LOW:-SSLv2:-EXP:!kEDH" + +# This is the SSL protocol version used. See IO::Socket::SSL if you wish to +# change this and to understand the implications of changing it +UI_SSL_VERSION = "SSLv23:!SSLv3:!SSLv2" + +# If cxs is installed then enabling this option will provide a dropdown box to +# switch between applications +UI_CXS = "0" + +# There is a modified installation of ConfigServer Explorer (cse) provided with +# the csf distribution. If this option is enabled it will provide a dropdown +# box to switch between applications +UI_CSE = "0" + +############################################################################### +# SECTION:Messenger service +############################################################################### +# Messenger service. This feature allows the display of a message to a blocked +# connecting IP address to inform the user that they are blocked in the +# firewall. This can help when users get themselves blocked, e.g. due to +# multiple login failures. The service is provided by two daemons running on +# ports providing either an HTML or TEXT message +# +# This feature does not work on servers that do not have the iptables module +# ipt_REDIRECT loaded. Typically, this will be with MONOLITHIC kernels. VPS +# server admins should check with their VPS host provider that the iptables +# module is included +# +# IPv6 will need the IO::Socket::INET6 perl module +# +# For further information on features and limitations refer to the csf +# readme.txt +# +# Note: Run /etc/csf/csftest.pl to check whether this option will function on +# this server +# +# 1 to enable, 0 to disable +MESSENGER = "0" + +# Provide this service to temporary IP address blocks +MESSENGER_TEMP = "1" + +# Provide this service to permanent IP address blocks +MESSENGER_PERM = "1" + +# User account to run the service servers under. We recommend creating a +# specific non-priv, non-shell account for this purpose +# +# Note: When using MESSENGERV2, this account must NOT be a valid control panel +# account, it must be created manually as explained in the csf readme.txt +MESSENGER_USER = "csf" + +# This option points to the file(s) containing the Apache VirtualHost SSL +# definitions. This can be a file glob if there are multiple files to search. +# Only Apache v2 SSL VirtualHost definitions are supported +# +# This is used by MESSENGERV1 and MESSENGERV2 only +MESSENGER_HTTPS_CONF = "/etc/httpd/conf.d/ssl.conf" + +# The following options can be specified to provide a default fallback +# certificate to be used if either SNI is not supported or a hosted domain does +# not have an SSL certificate. If a fallback is not provided, one of the certs +# obtained from MESSENGER_HTTPS_CONF will be used +# +# This is used by MESSENGERV1 and MESSENGERV2 only +MESSENGER_HTTPS_KEY = "/etc/pki/tls/private/localhost.key" +MESSENGER_HTTPS_CRT = "/etc/pki/tls/certs/localhost.crt" + +# Set this to the port that will receive the HTTPS HTML message. You should +# configure this port to be >1023 and different from the TEXT and HTML port. Do +# NOT enable access to this port in TCP_IN. This option requires the perl +# module IO::Socket::SSL at a version level that supports SNI (1.83+). +# Additionally the version of openssl on the server must also support SNI +# +# The option uses existing SSL certificates on the server for each domain to +# maintain a secure connection without browser warnings. It uses SNI to choose +# the correct certificate to use for each client connection +# +# Warning: On some servers the amount of memory used by the HTTPS MESSENGER +# service can become significant depending on various factors associated with +# the use of IO::Socket::SSL including the number of domains and certificates +# served. This is normally only an issue if using MESSENGERV1 +MESSENGER_HTTPS = "8887" + +# This comma separated list are the HTTPS HTML ports that will be redirected +# for the blocked IP address. If you are using per application blocking +# (LF_TRIGGER) then only the relevant block port will be redirected to the +# messenger port +# +# Recommended setting "443" plus any end-user control panel SSL ports. So, for +# cPanel: "443,2083,2096" +MESSENGER_HTTPS_IN = "443" + +# Set this to the port that will receive the HTML message. You should configure +# this port to be >1023 and different from the TEXT port. Do NOT enable access +# to this port in TCP_IN +MESSENGER_HTML = "8888" + +# This comma separated list are the HTML ports that will be redirected for the +# blocked IP address. If you are using per application blocking (LF_TRIGGER) +# then only the relevant block port will be redirected to the messenger port +MESSENGER_HTML_IN = "80" + +# Set this to the port that will receive the TEXT message. You should configure +# this port to be >1023 and different from the HTML port. Do NOT enable access +# to this port in TCP_IN +MESSENGER_TEXT = "8889" + +# This comma separated list are the TEXT ports that will be redirected for the +# blocked IP address. If you are using per application blocking (LF_TRIGGER) +# then only the relevant block port will be redirected to the messenger port +MESSENGER_TEXT_IN = "21" + +# These settings limit the rate at which connections can be made to the +# messenger service servers. Its intention is to provide protection from +# attacks or excessive connections to the servers. If the rate is exceeded then +# iptables will revert for the duration to the normal blocking activity +# +# See the iptables man page for the correct --limit rate syntax +MESSENGER_RATE = "100/s" +MESSENGER_BURST = "150" + +# MESSENGERV1 only: +#------------------------------------------------------------------------------ +# This is the maximum concurrent connections allowed to each service server +# +# Note: This number should be increased to cater for the number of local images +# served by this page, including one for favicon.ico. This is because each +# image displayed counts as an additional connection +MESSENGER_CHILDREN = "20" + +# This options ignores ServerAlias definitions that begin with "mail.". This +# can help reduce memory usage on systems that do not require the use of +# MESSENGER_HTTPS on those subdomains +# +# Set to 0 to include these ServerAlias definitions +MESSENGER_HTTPS_SKIPMAIL = "1" + +# MESSENGERV2 only: +#------------------------------------------------------------------------------ +# MESSENGERV2. This option is available on cPanel servers running Apache v2.4+ +# under EA4. +# +# This uses the Apache http daemon to provide the web server functionality for +# the MESSENGER HTML and HTTPS services. It uses a fraction of the resources +# that the lfd inbuilt service uses and overcomes the memory overhead of using +# the MESSENGER HTTPS service +# +# For more information consult readme.txt before enabling this option +#MESSENGERV2 = "0" + +# MESSENGERV3 only: +#------------------------------------------------------------------------------ +# MESSENGERV3. This option is available on any server running Apache v2.4+, +# Litespeed or Openlitespeed +# +# This uses the web server http daemon to provide the web server functionality +# for the MESSENGER HTML and HTTPS services. It uses a fraction of the +# resources that the lfd inbuilt service uses and overcomes the memory overhead +# of using the MESSENGER HTTPS service +# +# For more information consult readme.txt before enabling this option +MESSENGERV3 = "0" + +# This is the file or directory where the additional web server configuration +# file should be included +MESSENGERV3LOCATION = "/etc/httpd/conf.d/" + +# This is the command to restart the web server +MESSENGERV3RESTART = "service httpd restart" + +# This is the command to test the validity of the web server configuration. If +# using Litespeed, set to "" +MESSENGERV3TEST = "/usr/sbin/apachectl -t" + +# This must be set to the main httpd.conf file for either Apache or Litespeed +MESSENGERV3HTTPS_CONF = "/etc/httpd/conf/httpd.conf" + +# This can be set to either: +# "apache" - for servers running Apache v2.4+ or Litespeed using Apache +# configuration +# "litespeed" - for Litespeed or Openlitespeed +MESSENGERV3WEBSERVER = "apache" + +# On creation, set the MESSENGER_USER public_html directory permissions to +# Note: If you precreate this directory the following setting will be ignored +MESSENGERV3PERMS = "711" + +# On creation, set the MESSENGER_USER public_html directory group user to +# Note: If you precreate this directory the following setting will be ignored +MESSENGERV3GROUP = "nginx" + +# This is the web server configuration to allow PHP scripts to run. If left +# empty, the MESSENGER service will try to configure this. If this does not +# work, this should be set as an "Include /path/to/csf_php.conf" or similar +# file which must contain appropriate web server configuration to allow PHP +# scripts to run. This line will be included within each MESSENGER VirtualHost +# container. This will replace the [MESSENGERV3PHPHANDLER] line from the csf +# webserver template files +MESSENGERV3PHPHANDLER = "" + +# RECAPTCHA: +#------------------------------------------------------------------------------ +# The RECAPTCHA options provide a way for end-users that have blocked +# themselves in the firewall to unblock themselves. +# +# A valid Google ReCAPTCHA (v2) key set is required for this feature from: +# https://www.google.com/recaptcha/intro/index.html +# +# When configuring a new reCAPTCHA API key set you must ensure that the option +# for "Domain Name Validation" is unticked so that the same reCAPTCHA can be +# used for all domains hosted on the server. lfd then checks that the hostname +# of the request resolves to an IP on this server +# +# This feature requires the installation of the LWP::UserAgent perl module (see +# option URLGET for more details) +# +# The template used for this feature is /etc/csf/messenger/index.recaptcha.html +# +# Note: An unblock will fail if the end-users IP is located in a netblock, +# blocklist or CC_* deny entry +RECAPTCHA_SITEKEY = "" +RECAPTCHA_SECRET = "" + +# Send an email when an IP address successfully attempts to unblock themselves. +# This does not necessarily mean the IP was unblocked, only that the +# post-recaptcha unblock request was attempted +# +# Set to "0" to disable +RECAPTCHA_ALERT = "1" + +# If the server uses NAT then resolving the hostname to hosted IPs will likely +# not succeed. In that case, the external IP addresses must be listed as comma +# separated list here +RECAPTCHA_NAT = "" + +############################################################################### +# SECTION:lfd Clustering +############################################################################### +# lfd Clustering. This allows the configuration of an lfd cluster environment +# where a group of servers can share blocks and configuration option changes. +# Included are CLI and UI options to send requests to the cluster. +# +# See the readme.txt file for more information and details on setup and +# security risks. +# +# Set this to a comma separated list of cluster member IP addresses to send +# requests to. Alternatively, it can be set to the full path of a file that +# will read in one IP per line, e.g.: +# "/etc/csf/cluster_sendto.txt" +CLUSTER_SENDTO = "" + +# Set this to a comma separated list of cluster member IP addresses to receive +# requests from. Alternatively, it can be set to the full path of a file that +# will read in one IP per line, e.g.: +# "/etc/csf/cluster_recvfrom.txt" +CLUSTER_RECVFROM = "" + +# IP address of the master node in the cluster allowed to send CLUSTER_CONFIG +# changes +CLUSTER_MASTER = "" + +# If this is a NAT server, set this to the public IP address of this server +CLUSTER_NAT = "" + +# If a cluster member should send requests on an IP other than the default IP, +# set it here +CLUSTER_LOCALADDR = "" + +# Cluster communication port (must be the same on all member servers). There +# is no need to open this port in the firewall as csf will automatically add +# in and out bound rules to allow communication between cluster members +CLUSTER_PORT = "7777" + +# This is a secret key used to encrypt cluster communications using the +# Blowfish algorithm. It should be between 8 and 56 characters long, +# preferably > 20 random characters +# 56 chars: 01234567890123456789012345678901234567890123456789012345 +CLUSTER_KEY = "" + +# Automatically send lfd blocks to all members of CLUSTER_SENDTO. Those +# servers must have this servers IP address listed in their CLUSTER_RECVFROM +# +# Set to 0 to disable this feature +CLUSTER_BLOCK = "1" + +# This option allows the enabling and disabling of the Cluster configuration +# changing options --cconfig, --cconfigr, --cfile, --ccfile sent from the +# CLUSTER_MASTER server +# +# Set this option to 1 to allow Cluster configurations to be received +CLUSTER_CONFIG = "0" + +# Maximum number of child processes to listen on. High blocking rates or large +# clusters may need to increase this +CLUSTER_CHILDREN = "10" + +############################################################################### +# SECTION:Port Knocking +############################################################################### +# Port Knocking. This feature allows port knocking to be enabled on multiple +# ports with a variable number of knocked ports and a timeout. There must be a +# minimum of 3 ports to knock for an entry to be valid +# +# See the following for information regarding Port Knocking: +# http://www.portknocking.org/ +# +# This feature does not work on servers that do not have the iptables module +# ipt_recent loaded. Typically, this will be with MONOLITHIC kernels. VPS +# server admins should check with their VPS host provider that the iptables +# module is included +# +# For further information and syntax refer to the Port Knocking section of the +# csf readme.txt +# +# Note: Run /etc/csf/csftest.pl to check whether this option will function on +# this server +# +# openport;protocol;timeout;kport1;kport2;kport3[...;kportN],... +# e.g.: 22;TCP;20;100;200;300;400 +PORTKNOCKING = "" + +# Enable PORTKNOCKING logging by iptables +PORTKNOCKING_LOG = "1" + +# Send an email alert if the PORTKNOCKING port is opened. PORTKNOCKING_LOG must +# also be enabled to use this option +# +# SECURITY NOTE: This option is affected by the RESTRICT_SYSLOG option. Read +# this file about RESTRICT_SYSLOG before enabling this option: +PORTKNOCKING_ALERT = "0" + +############################################################################### +# SECTION:Log Scanner +############################################################################### +# Log Scanner. This feature will send out an email summary of the log lines of +# each log listed in /etc/csf/csf.logfiles. All lines will be reported unless +# they match a regular expression in /etc/csf/csf.logignore +# +# File globbing is supported for logs listed in /etc/csf/csf.logfiles. However, +# be aware that the more files lfd has to track, the greater the performance +# hit. Note: File globs are only evaluated when lfd is started +# +# Note: lfd builds the report continuously from lines logged after lfd has +# started, so any lines logged when lfd is not running will not be reported +# (e.g. during reboot). If lfd is restarted, then the report will include any +# lines logged during the previous lfd logging period that weren't reported +# +# 1 to enable, 0 to disable +LOGSCANNER = "0" + +# This is the interval each report will be sent based on the logalert.txt +# template +# +# The interval can be set to: +# "hourly" - sent on the hour +# "daily" - sent at midnight (00:00) +# "manual" - sent whenever "csf --logrun" is run. This allows for scheduling +# via cron job +LOGSCANNER_INTERVAL = "hourly" + +# Report Style +# 1 = Separate chronological log lines per log file +# 2 = Simply chronological log of all lines +LOGSCANNER_STYLE = "1" + +# Send the report email even if no log lines reported +# 1 to enable, 0 to disable +LOGSCANNER_EMPTY = "1" + +# Maximum number of lines in the report before it is truncated. This is to +# prevent log lines flooding resulting in an excessively large report. This +# might need to be increased if you choose a daily report +LOGSCANNER_LINES = "5000" + +############################################################################### +# SECTION:Statistics Settings +############################################################################### +# Statistics +# +# Some of the Statistics output requires the gd graphics library and the +# GD::Graph perl module with all dependent modules to be installed for the UI +# for them to be displayed +# +# This option enabled statistical data gathering +ST_ENABLE = "1" + +# This option determines how many iptables log lines to store for reports +ST_IPTABLES = "100" + +# This option indicates whether rDNS and CC lookups are performed at the time +# the log line is recorded (this is not performed when viewing the reports) +# +# Warning: If DROP_IP_LOGGING is enabled and there are frequent iptables hits, +# then enabling this setting could cause serious performance problems +ST_LOOKUP = "0" + +# This option will gather basic system statstics. Through the UI it displays +# various graphs for disk, cpu, memory, network, etc usage over 4 intervals: +# . Hourly (per minute) +# . 24 hours (per minute) +# . 7 days (per minute averaged over an hour) +# . 30 days (per minute averaged over an hour) - user definable +# The data is stored in /var/lib/csf/stats/system and the option requires the +# perl GD::Graph module +# +# Note: Disk graphs do not show on Virtuozzo/OpenVZ servers as the kernel on +# those systems do not store the required information in /proc/diskstats +# On new installations or when enabling this option it will take time for these +# graphs to be populated +ST_SYSTEM = "0" + +# Set the maximum days to collect statistics for. The default is 30 days, the +# more data that is collected the longer it will take for each of the graphs to +# be generated +ST_SYSTEM_MAXDAYS = "30" + +# If ST_SYSTEM is enabled, then these options can collect MySQL statistical +# data. To use this option the server must have the perl modules DBI and +# DBD::mysql installed. +# +# Set this option to "0" to disable MySQL data collection +ST_MYSQL = "0" + +# The following options are for authentication for MySQL data collection. If +# the password is left blank and the user set to "root" then the procedure will +# look for authentication data in /root/.my.cnf. Otherwise, you will need to +# provide a MySQL username and password to collect the data. Any MySQL user +# account can be used +ST_MYSQL_USER = "root" +ST_MYSQL_PASS = "" +ST_MYSQL_HOST = "localhost" + +# If ST_SYSTEM is enabled, then this option can collect Apache statistical data +# The value for PT_APACHESTATUS must be correctly set +ST_APACHE = "0" + +# The following options measure disk write performance using dd (location set +# via the DD setting). It creates a 64MB file called /var/lib/dd_write_test and +# the statistics will plot the MB/s response time of the disk. As this is an IO +# intensive operation, it may not be prudent to run this test too often, so by +# default it is only run every 5 minutes and the result duplicated for each +# intervening minute for the statistics +# +# This is not necessrily a good measure of disk performance, primarily because +# the measurements are for relatively small amounts of data over a small amount +# of time. To properly test disk performance there are a variety of tools +# available that should be run for extended periods of time to obtain an +# accurate measurement. This metric is provided to give an idea of how the disk +# is performing over time +# +# Note: There is a 15 second timeout performing the check +# +# Set to 0 to disable, 1 to enable +ST_DISKW = "0" + +# The number of minutes that elapse between tests. Default is 5, minimum is 1. +ST_DISKW_FREQ = "5" + +# This is the command line passed to dd. If you are familiar with dd, or wish +# to move the output file (of) to a different disk, then you can alter this +# command. Take great care when making any changes to this command as it is +# very easy to overwrite a disk using dd if you make a mistake +ST_DISKW_DD = "if=/dev/zero of=/var/lib/csf/dd_test bs=1MB count=64 conv=fdatasync" + +############################################################################### +# SECTION:Docker Settings +############################################################################### +# This section provides the configuration of iptables rules to allow Docker +# containers to communicate through the host. If the generated rules do not +# work with your setup you will have to use a /etc/csf/csfpost.sh file and add +# your own iptables configuration instead +# +# 1 to enable, 0 to disable +DOCKER = "0" + +# The network device on the host +DOCKER_DEVICE = "docker0" + +# Docker container IPv4 range +DOCKER_NETWORK4 = "172.17.0.0/16" + +# Docker container IPv6 range. IPV6 must be enabled and the IPv6 nat table +# available (see IPv6 section). Leave blank to disable +DOCKER_NETWORK6 = "2001:db8:1::/64" + +############################################################################### +# SECTION:OS Specific Settings +############################################################################### +# Binary locations +IPTABLES = "/sbin/iptables" +IPTABLES_SAVE = "/sbin/iptables-save" +IPTABLES_RESTORE = "/sbin/iptables-restore" +IP6TABLES = "/sbin/ip6tables" +IP6TABLES_SAVE = "/sbin/ip6tables-save" +IP6TABLES_RESTORE = "/sbin/ip6tables-restore" +MODPROBE = "/sbin/modprobe" +IFCONFIG = "/sbin/ifconfig" +SENDMAIL = "/usr/sbin/sendmail" +PS = "/bin/ps" +VMSTAT = "/usr/bin/vmstat" +NETSTAT = "/bin/netstat" +LS = "/bin/ls" +MD5SUM = "/usr/bin/md5sum" +TAR = "/bin/tar" +CHATTR = "/usr/bin/chattr" +UNZIP = "/usr/bin/unzip" +GUNZIP = "/bin/gunzip" +DD = "/bin/dd" +TAIL = "/usr/bin/tail" +GREP = "/bin/grep" +ZGREP = "/usr/bin/zgrep" +IPSET = "/usr/sbin/ipset" +SYSTEMCTL = "/usr/bin/systemctl" +HOST = "/usr/bin/host" +IP = "/sbin/ip" +CURL = "/usr/bin/curl" +WGET = "/usr/bin/wget" + +# Log file locations +# +# File globbing is allowed for the following logs. However, be aware that the +# more files lfd has to track, the greater the performance hit +# +# Note: File globs are only evaluated when lfd is started +# +HTACCESS_LOG = "/var/log/httpd/error_log" +MODSEC_LOG = "/var/log/httpd/error_log" +SSHD_LOG = "/var/log/secure" +SU_LOG = "/var/log/secure" +SUDO_LOG = "/var/log/secure" +FTPD_LOG = "/var/log/vsftpd.log" +SMTPAUTH_LOG = "/var/log/smtp/current" +POP3D_LOG = "/var/log/dovecot/dovecot.log" +IMAPD_LOG = "/var/log/dovecot/dovecot.log" +IPTABLES_LOG = "/var/log/messages" +SUHOSIN_LOG = "/var/log/messages" +BIND_LOG = "/var/log/messages" +SYSLOG_LOG = "/var/log/messages" +WEBMIN_LOG = "/var/log/secure" +VESTA_LOG = "/var/log/vesta/auth.log" + +CUSTOM1_LOG = "/var/log/customlog" +CUSTOM2_LOG = "/var/log/customlog" +CUSTOM3_LOG = "/var/log/customlog" +CUSTOM4_LOG = "/var/log/customlog" +CUSTOM5_LOG = "/var/log/customlog" +CUSTOM6_LOG = "/var/log/customlog" +CUSTOM7_LOG = "/var/log/customlog" +CUSTOM8_LOG = "/var/log/customlog" +CUSTOM9_LOG = "/var/log/customlog" + +# The following are comma separated lists used if LF_SELECT is enabled, +# otherwise they are not used. They are derived from the application returned +# from a regex match in /usr/local/csf/bin/regex.pm +# +# All ports default to tcp blocks. To specify udp or tcp use the format: +# port;protocol,port;protocol,... For example, "53;udp,53;tcp" +PORTS_pop3d = "110,995" +PORTS_imapd = "143,993" +PORTS_htpasswd = "80,443" +PORTS_mod_security = "80,443" +PORTS_mod_qos = "80,443" +PORTS_symlink = "80,443" +PORTS_suhosin = "80,443" +PORTS_cxs = "80,443" +PORTS_bind = "53;udp,53;tcp" +PORTS_ftpd = "20,21" +PORTS_webmin = "10000" +PORTS_smtpauth = "25,465,587" +PORTS_eximsyntax = "25,465,587" +PORTS_vesta = "8083" +# This list is replaced, if present, by "Port" definitions in +# /etc/ssh/sshd_config +PORTS_sshd = "22" + +# This configuration is for use with generic Linux servers, do not change the +# following settings: +GENERIC = "1" +VESTA = "1" + +# For internal use only. You should not enable this option as it could cause +# instability in csf and lfd +DEBUG = "0" +############################################################################### diff --git a/csf/csf.vesta.ignore b/csf/csf.vesta.ignore new file mode 100644 index 0000000..bf3fb2a --- /dev/null +++ b/csf/csf.vesta.ignore @@ -0,0 +1,25 @@ +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +# The following IP addresses will be ignored by all lfd checks +# One IP address per line +# CIDR addressing allowed with a quaded IP (e.g. 192.168.254.0/24) +# Only list IP addresses, not domain names (they will be ignored) +# + +127.0.0.1 diff --git a/csf/csf.vesta.pignore b/csf/csf.vesta.pignore new file mode 100644 index 0000000..3ff2be8 --- /dev/null +++ b/csf/csf.vesta.pignore @@ -0,0 +1,118 @@ +############################################################################### +# Copyright (C) 2006-2025 Jonathan Michaelson +# +# https://github.com/waytotheweb/scripts +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, see . +############################################################################### +# The following is a list of executables (exe) command lines (cmd) and +# usernames (user) that lfd process tracking will ignore. +# +# You must use the following format: +# +# exe:/full/path/to/file +# user:username +# cmd:command line +# +# Or, perl regular expression matching (regex): +# +# pexe:/full/path/to/file as a perl regex[*] +# puser:username as a perl regex[*] +# pcmd:command line as a perl regex[*] +# +# [*]You must remember to escape characters correctly when using regex's, e.g.: +# pexe:/home/.*/public_html/cgi-bin/script\.cgi +# puser:bob\d.* +# pcmd:/home/.*/command\s\to\smatch\s\.pl\s.* +# +# It is strongly recommended that you use command line ignores very carefully +# as any process can change what is reported to the OS. +# +# For more information see readme.txt + +exe:/bin/dbus-daemon +exe:/sbin/ntpd +exe:/usr/bin/dbus-daemon +exe:/usr/bin/lsmd +exe:/usr/lib/courier-imap/bin/imapd +exe:/usr/lib/courier-imap/bin/pop3d +exe:/usr/lib/polkit-1/polkitd +exe:/usr/libexec/dovecot/imap +exe:/usr/libexec/dovecot/imap +exe:/usr/libexec/dovecot/pop3 +exe:/usr/libexec/dovecot/pop3 +exe:/usr/libexec/dovecot/stats +exe:/usr/libexec/dovecot/auth +exe:/usr/libexec/mysqld +exe:/usr/local/apache/bin/httpd +exe:/usr/local/libexec/dovecot/imap +exe:/usr/local/libexec/dovecot/imap-login +exe:/usr/local/libexec/dovecot/pop3 +exe:/usr/local/libexec/dovecot/pop3-login +exe:/usr/local/libexec/dovecot/stats +exe:/usr/sbin/chronyd +exe:/usr/sbin/exim +exe:/usr/sbin/exim4 +exe:/usr/sbin/named +exe:/usr/sbin/nscd +exe:/usr/sbin/ntpd +exe:/usr/sbin/ntpd +exe:/usr/sbin/proftpd +exe:/usr/sbin/pure-ftpd +exe:/usr/sbin/sshd +exe:/usr/sbin/apache2 +exe:/usr/sbin/mysqld +exe:/lib/systemd/systemd-timesyncd +exe:/sbin/rngd +exe:/usr/bin/dbus-broker-launch +exe:/usr/bin/dbus-broker + +exe:/usr/sbin/clamd +exe:/usr/sbin/opendkim +exe:/usr/libexec/mysqld +exe:/usr/sbin/mysqld +exe:/usr/bin/postgres +exe:/usr/bin/mongod +exe:/usr/libexec/dovecot/anvil +exe:/usr/libexec/dovecot/auth +exe:/usr/libexec/dovecot/imap-login +exe:/usr/libexec/dovecot/dict +exe:/usr/libexec/dovecot/pop3-login +exe:/usr/libexec/postfix/tlsmgr +exe:/usr/libexec/postfix/qmgr +exe:/usr/libexec/postfix/pickup +exe:/usr/libexec/postfix/smtpd +exe:/usr/libexec/postfix/smtp +exe:/usr/libexec/postfix/bounce +exe:/usr/libexec/postfix/scache +exe:/usr/libexec/postfix/anvil +exe:/usr/libexec/postfix/cleanup +exe:/usr/libexec/postfix/proxymap +exe:/usr/libexec/postfix/trivial-rewrite +exe:/usr/libexec/postfix/local +exe:/usr/libexec/postfix/pipe +exe:/usr/libexec/postfix/spawn +exe:/usr/sbin/varnishd +exe:/usr/sbin/nginx +exe:/usr/local/vesta/php/sbin/vesta-php +exe:/usr/sbin/httpd +exe:/usr/local/vesta/nginx/sbin/vesta-nginx +exe:/usr/sbin/mariadbd + +# Some additional entries that you might want to ignore on cPanel servers. +# However, be aware of the security implications under "Process Tracking" in +# the csf readme.txt when using these: +# +#cmd:spamd child +#cmd:/bin/sh /usr/bin/mysqld_safe --basedir=/usr diff --git a/csf/csf/LICENSE.txt b/csf/csf/LICENSE.txt new file mode 100644 index 0000000..34da9d9 --- /dev/null +++ b/csf/csf/LICENSE.txt @@ -0,0 +1,14 @@ +Fugue Icons + +plus.png +minus.png +perm.png +ip.png +delete.png + +(C) 2013 Yusuke Kamiyamane. All rights reserved. +These icons are licensed under a Creative Commons +Attribution 3.0 License. + + + diff --git a/csf/csf/admin_icon.svg b/csf/csf/admin_icon.svg new file mode 100644 index 0000000..1c928ea --- /dev/null +++ b/csf/csf/admin_icon.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/csf/csf/bootstrap-chosen.css b/csf/csf/bootstrap-chosen.css new file mode 100644 index 0000000..54e6a13 --- /dev/null +++ b/csf/csf/bootstrap-chosen.css @@ -0,0 +1,346 @@ +.chosen-select { + width: 100%; } + +.chosen-select-deselect { + width: 100%; } + +.chosen-container { + display: inline-block; + font-size: 14px; + position: relative; + vertical-align: middle; } + .chosen-container .chosen-drop { + background: #fff; + border: 1px solid #ccc; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; + -webkit-box-shadow: 0 8px 8px rgba(0, 0, 0, 0.25); + box-shadow: 0 8px 8px rgba(0, 0, 0, 0.25); + margin-top: -1px; + position: absolute; + top: 100%; + left: -9000px; + z-index: 1060; } + .chosen-container.chosen-with-drop .chosen-drop { + left: 0; + right: 0; } + .chosen-container .chosen-results { + color: #555555; + margin: 0 4px 4px 0; + max-height: 240px; + padding: 0 0 0 4px; + position: relative; + overflow-x: hidden; + overflow-y: auto; + -webkit-overflow-scrolling: touch; } + .chosen-container .chosen-results li { + display: none; + line-height: 1.42857; + list-style: none; + margin: 0; + padding: 5px 6px; } + .chosen-container .chosen-results li em { + background: #feffde; + font-style: normal; } + .chosen-container .chosen-results li.group-result { + display: list-item; + cursor: default; + color: #999; + font-weight: bold; } + .chosen-container .chosen-results li.group-option { + padding-left: 15px; } + .chosen-container .chosen-results li.active-result { + cursor: pointer; + display: list-item; } + .chosen-container .chosen-results li.highlighted { + background-color: #337ab7; + background-image: none; + color: white; } + .chosen-container .chosen-results li.highlighted em { + background: transparent; } + .chosen-container .chosen-results li.disabled-result { + display: list-item; + color: #777777; } + .chosen-container .chosen-results .no-results { + background: #eeeeee; + display: list-item; } + .chosen-container .chosen-results-scroll { + background: white; + margin: 0 4px; + position: absolute; + text-align: center; + width: 321px; + z-index: 1; } + .chosen-container .chosen-results-scroll span { + display: inline-block; + height: 1.42857; + text-indent: -5000px; + width: 9px; } + .chosen-container .chosen-results-scroll-down { + bottom: 0; } + .chosen-container .chosen-results-scroll-down span { + background: url("chosen-sprite.png") no-repeat -4px -3px; } + .chosen-container .chosen-results-scroll-up span { + background: url("chosen-sprite.png") no-repeat -22px -3px; } + +.chosen-container-single .chosen-single { + background-color: #fff; + -webkit-background-clip: padding-box; + -moz-background-clip: padding; + background-clip: padding-box; + border: 1px solid #ccc; + border-top-right-radius: 4px; + border-top-left-radius: 4px; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + color: #555555; + display: block; + height: 34px; + overflow: hidden; + line-height: 34px; + padding: 0 0 0 8px; + position: relative; + text-decoration: none; + white-space: nowrap; } + .chosen-container-single .chosen-single span { + display: block; + margin-right: 26px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; } + .chosen-container-single .chosen-single abbr { + background: url("chosen-sprite.png") right top no-repeat; + display: block; + font-size: 1px; + height: 10px; + position: absolute; + right: 26px; + top: 12px; + width: 12px; } + .chosen-container-single .chosen-single abbr:hover { + background-position: right -11px; } + .chosen-container-single .chosen-single.chosen-disabled .chosen-single abbr:hover { + background-position: right 2px; } + .chosen-container-single .chosen-single div { + display: block; + height: 100%; + position: absolute; + top: 0; + right: 0; + width: 18px; } + .chosen-container-single .chosen-single div b { + background: url("chosen-sprite.png") no-repeat 0 7px; + display: block; + height: 100%; + width: 100%; } +.chosen-container-single .chosen-default { + color: #777777; } +.chosen-container-single .chosen-search { + margin: 0; + padding: 3px 4px; + position: relative; + white-space: nowrap; + z-index: 1000; } + .chosen-container-single .chosen-search input[type="text"] { + background: url("chosen-sprite.png") no-repeat 100% -20px, #fff; + border: 1px solid #ccc; + border-top-right-radius: 4px; + border-top-left-radius: 4px; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + margin: 1px 0; + padding: 4px 20px 4px 4px; + width: 100%; } +.chosen-container-single .chosen-drop { + margin-top: -1px; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; + -webkit-background-clip: padding-box; + -moz-background-clip: padding; + background-clip: padding-box; } + +.chosen-container-single-nosearch .chosen-search input[type="text"] { + position: absolute; + left: -9000px; } + +.chosen-container-multi .chosen-choices { + background-color: #fff; + border: 1px solid #ccc; + border-top-right-radius: 4px; + border-top-left-radius: 4px; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + cursor: text; + height: auto !important; + height: 1%; + margin: 0; + overflow: hidden; + padding: 0; + position: relative; } + .chosen-container-multi .chosen-choices li { + float: left; + list-style: none; } + .chosen-container-multi .chosen-choices .search-field { + margin: 0; + padding: 0; + white-space: nowrap; } + .chosen-container-multi .chosen-choices .search-field input[type="text"] { + background: transparent !important; + border: 0 !important; + -webkit-box-shadow: none; + box-shadow: none; + color: #555555; + height: 32px; + margin: 0; + padding: 4px; + outline: 0; } + .chosen-container-multi .chosen-choices .search-field .default { + color: #999; } + .chosen-container-multi .chosen-choices .search-choice { + -webkit-background-clip: padding-box; + -moz-background-clip: padding; + background-clip: padding-box; + background-color: #eeeeee; + border: 1px solid #ccc; + border-top-right-radius: 4px; + border-top-left-radius: 4px; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; + background-image: -webkit-linear-gradient(top, white 0%, #eeeeee 100%); + background-image: -o-linear-gradient(top, white 0%, #eeeeee 100%); + background-image: linear-gradient(to bottom, white 0%, #eeeeee 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0); + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + color: #333333; + cursor: default; + line-height: 13px; + margin: 6px 0 3px 5px; + padding: 3px 20px 3px 5px; + position: relative; } + .chosen-container-multi .chosen-choices .search-choice .search-choice-close { + background: url("chosen-sprite.png") right top no-repeat; + display: block; + font-size: 1px; + height: 10px; + position: absolute; + right: 4px; + top: 5px; + width: 12px; + cursor: pointer; } + .chosen-container-multi .chosen-choices .search-choice .search-choice-close:hover { + background-position: right -11px; } + .chosen-container-multi .chosen-choices .search-choice-focus { + background: #d4d4d4; } + .chosen-container-multi .chosen-choices .search-choice-focus .search-choice-close { + background-position: right -11px; } +.chosen-container-multi .chosen-results { + margin: 0 0 0 0; + padding: 0; } +.chosen-container-multi .chosen-drop .result-selected { + display: none; } + +.chosen-container-active .chosen-single { + border: 1px solid #66afe9; + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075) inset, 0 0 8px #66afe9; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075) inset, 0 0 8px #66afe9; + -webkit-transition: border linear 0.2s, box-shadow linear 0.2s; + -o-transition: border linear 0.2s, box-shadow linear 0.2s; + transition: border linear 0.2s, box-shadow linear 0.2s; } +.chosen-container-active.chosen-with-drop .chosen-single { + background-color: #fff; + border: 1px solid #66afe9; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075) inset, 0 0 8px #66afe9; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075) inset, 0 0 8px #66afe9; + -webkit-transition: border linear 0.2s, box-shadow linear 0.2s; + -o-transition: border linear 0.2s, box-shadow linear 0.2s; + transition: border linear 0.2s, box-shadow linear 0.2s; } + .chosen-container-active.chosen-with-drop .chosen-single div { + background: transparent; + border-left: none; } + .chosen-container-active.chosen-with-drop .chosen-single div b { + background-position: -18px 7px; } +.chosen-container-active .chosen-choices { + border: 1px solid #66afe9; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075) inset, 0 0 8px #66afe9; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075) inset, 0 0 8px #66afe9; + -webkit-transition: border linear 0.2s, box-shadow linear 0.2s; + -o-transition: border linear 0.2s, box-shadow linear 0.2s; + transition: border linear 0.2s, box-shadow linear 0.2s; } + .chosen-container-active .chosen-choices .search-field input[type="text"] { + color: #111 !important; } +.chosen-container-active.chosen-with-drop .chosen-choices { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; } + +.chosen-disabled { + cursor: default; + opacity: 0.5 !important; } + .chosen-disabled .chosen-single { + cursor: default; } + .chosen-disabled .chosen-choices .search-choice .search-choice-close { + cursor: default; } + +.chosen-rtl { + text-align: right; } + .chosen-rtl .chosen-single { + padding: 0 8px 0 0; + overflow: visible; } + .chosen-rtl .chosen-single span { + margin-left: 26px; + margin-right: 0; + direction: rtl; } + .chosen-rtl .chosen-single div { + left: 7px; + right: auto; } + .chosen-rtl .chosen-single abbr { + left: 26px; + right: auto; } + .chosen-rtl .chosen-choices .search-field input[type="text"] { + direction: rtl; } + .chosen-rtl .chosen-choices li { + float: right; } + .chosen-rtl .chosen-choices .search-choice { + margin: 6px 5px 3px 0; + padding: 3px 5px 3px 19px; } + .chosen-rtl .chosen-choices .search-choice .search-choice-close { + background-position: right top; + left: 4px; + right: auto; } + .chosen-rtl.chosen-container-single .chosen-results { + margin: 0 0 4px 4px; + padding: 0 4px 0 0; } + .chosen-rtl .chosen-results .group-option { + padding-left: 0; + padding-right: 15px; } + .chosen-rtl.chosen-container-active.chosen-with-drop .chosen-single div { + border-right: none; } + .chosen-rtl .chosen-search input[type="text"] { + background: url("chosen-sprite.png") no-repeat -28px -20px, #fff; + direction: rtl; + padding: 4px 5px 4px 20px; } + +@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min-resolution: 2dppx) { + .chosen-rtl .chosen-search input[type="text"], + .chosen-container-single .chosen-single abbr, + .chosen-container-single .chosen-single div b, + .chosen-container-single .chosen-search input[type="text"], + .chosen-container-multi .chosen-choices .search-choice .search-choice-close, + .chosen-container .chosen-results-scroll-down span, + .chosen-container .chosen-results-scroll-up span { + background-image: url("chosen-sprite@2x.png") !important; + background-size: 52px 37px !important; + background-repeat: no-repeat !important; } } + +/*# sourceMappingURL=bootstrap-chosen.css.map */ diff --git a/csf/csf/bootstrap/css/bootstrap.min.css b/csf/csf/bootstrap/css/bootstrap.min.css new file mode 100644 index 0000000..b89ef7f --- /dev/null +++ b/csf/csf/bootstrap/css/bootstrap.min.css @@ -0,0 +1,6 @@ +/*! + * Bootstrap v3.3.7 (http://getbootstrap.com) + * Copyright 2011-2017 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,:after,:before{color:#000!important;text-shadow:none!important;background:0 0!important;-webkit-box-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff2) format('woff2'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\002a"}.glyphicon-plus:before{content:"\002b"}.glyphicon-eur:before,.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:focus,a:hover{color:#23527c;text-decoration:underline}a:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.carousel-inner>.item>a>img,.carousel-inner>.item>img,.img-responsive,.thumbnail a>img,.thumbnail>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;max-width:100%;height:auto;padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role=button]{cursor:pointer}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1;color:#777}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}.small,small{font-size:85%}.mark,mark{padding:.2em;background-color:#fcf8e3}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:focus,a.text-primary:hover{color:#286090}.text-success{color:#3c763d}a.text-success:focus,a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:focus,a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:focus,a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:focus,a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:focus,a.bg-primary:hover{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:focus,a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:focus,a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:focus,a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:focus,a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ol,ul{margin-top:0;margin-bottom:10px}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;margin-left:-5px;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-top:0;margin-bottom:20px}dd,dt{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[data-original-title],abbr[title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child{margin-bottom:0}blockquote .small,blockquote footer,blockquote small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote .small:before,blockquote footer:before,blockquote small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eee;border-left:0}.blockquote-reverse .small:before,.blockquote-reverse footer:before,.blockquote-reverse small:before,blockquote.pull-right .small:before,blockquote.pull-right footer:before,blockquote.pull-right small:before{content:''}.blockquote-reverse .small:after,.blockquote-reverse footer:after,.blockquote-reverse small:after,blockquote.pull-right .small:after,blockquote.pull-right footer:after,blockquote.pull-right small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{margin-right:-15px;margin-left:-15px}.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>td,.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>td,.table>thead:first-child>tr:first-child>th{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>tbody>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>thead>tr>th{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #ddd}.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*=col-]{position:static;display:table-column;float:none}table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;float:none}.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>thead>tr>td.active,.table>thead>tr>th.active{background-color:#f5f5f5}.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover{background-color:#e8e8e8}.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{background-color:#dff0d8}.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6}.table>tbody>tr.info>td,.table>tbody>tr.info>th,.table>tbody>tr>td.info,.table>tbody>tr>th.info,.table>tfoot>tr.info>td,.table>tfoot>tr.info>th,.table>tfoot>tr>td.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>thead>tr.info>th,.table>thead>tr>td.info,.table>thead>tr>th.info{background-color:#d9edf7}.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover{background-color:#c4e3f3}.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fcf8e3}.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc}.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#f2dede}.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc}.table-responsive{min-height:.01%;overflow-x:auto}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=checkbox],input[type=radio]{margin:4px 0 0;margin-top:1px\9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[type=checkbox]:focus,input[type=radio]:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control::-ms-expand{background-color:transparent;border:0}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}input[type=search]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type=date].form-control,input[type=time].form-control,input[type=datetime-local].form-control,input[type=month].form-control{line-height:34px}.input-group-sm input[type=date],.input-group-sm input[type=time],.input-group-sm input[type=datetime-local],.input-group-sm input[type=month],input[type=date].input-sm,input[type=time].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm{line-height:30px}.input-group-lg input[type=date],.input-group-lg input[type=time],.input-group-lg input[type=datetime-local],.input-group-lg input[type=month],input[type=date].input-lg,input[type=time].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg{line-height:46px}}.form-group{margin-bottom:15px}.checkbox,.radio{position:relative;display:block;margin-top:10px;margin-bottom:10px}.checkbox label,.radio label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{position:absolute;margin-top:4px\9;margin-left:-20px}.checkbox+.checkbox,.radio+.radio{margin-top:-5px}.checkbox-inline,.radio-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px}fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox].disabled,input[type=checkbox][disabled],input[type=radio].disabled,input[type=radio][disabled]{cursor:not-allowed}.checkbox-inline.disabled,.radio-inline.disabled,fieldset[disabled] .checkbox-inline,fieldset[disabled] .radio-inline{cursor:not-allowed}.checkbox.disabled label,.radio.disabled label,fieldset[disabled] .checkbox label,fieldset[disabled] .radio label{cursor:not-allowed}.form-control-static{min-height:34px;padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}select[multiple].input-sm,textarea.input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm select[multiple].form-control,.form-group-sm textarea.form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}select[multiple].input-lg,textarea.input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:46px;line-height:46px}.form-group-lg select[multiple].form-control,.form-group-lg textarea.form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.form-group-lg .form-control+.form-control-feedback,.input-group-lg+.form-control-feedback,.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.form-group-sm .form-control+.form-control-feedback,.input-group-sm+.form-control-feedback,.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .checkbox,.has-success .checkbox-inline,.has-success .control-label,.has-success .help-block,.has-success .radio,.has-success .radio-inline,.has-success.checkbox label,.has-success.checkbox-inline label,.has-success.radio label,.has-success.radio-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .checkbox,.has-warning .checkbox-inline,.has-warning .control-label,.has-warning .help-block,.has-warning .radio,.has-warning .radio-inline,.has-warning.checkbox label,.has-warning.checkbox-inline label,.has-warning.radio label,.has-warning.radio-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .checkbox,.has-error .checkbox-inline,.has-error .control-label,.has-error .help-block,.has-error .radio,.has-error .radio-inline,.has-error.checkbox label,.has-error.checkbox-inline label,.has-error.radio label,.has-error.radio-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .form-control,.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .checkbox,.form-inline .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .checkbox label,.form-inline .radio label{padding-left:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .checkbox,.form-horizontal .radio{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:11px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:none;border:1px solid transparent;border-radius:4px}.btn.active.focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn:active:focus,.btn:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.focus,.btn:focus,.btn:hover{color:#333;text-decoration:none}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none;opacity:.65}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default.focus,.btn-default:focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.btn-default:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active.focus,.btn-default.active:focus,.btn-default.active:hover,.btn-default:active.focus,.btn-default:active:focus,.btn-default:active:hover,.open>.dropdown-toggle.btn-default.focus,.open>.dropdown-toggle.btn-default:focus,.open>.dropdown-toggle.btn-default:hover{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled.focus,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled].focus,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#286090;border-color:#122b40}.btn-primary:hover{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active.focus,.btn-primary.active:focus,.btn-primary.active:hover,.btn-primary:active.focus,.btn-primary:active:focus,.btn-primary:active:hover,.open>.dropdown-toggle.btn-primary.focus,.open>.dropdown-toggle.btn-primary:focus,.open>.dropdown-toggle.btn-primary:hover{color:#fff;background-color:#204d74;border-color:#122b40}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled.focus,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled].focus,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#449d44;border-color:#255625}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active.focus,.btn-success.active:focus,.btn-success.active:hover,.btn-success:active.focus,.btn-success:active:focus,.btn-success:active:hover,.open>.dropdown-toggle.btn-success.focus,.open>.dropdown-toggle.btn-success:focus,.open>.dropdown-toggle.btn-success:hover{color:#fff;background-color:#398439;border-color:#255625}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled.focus,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled].focus,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active.focus,.btn-info.active:focus,.btn-info.active:hover,.btn-info:active.focus,.btn-info:active:focus,.btn-info:active:hover,.open>.dropdown-toggle.btn-info.focus,.open>.dropdown-toggle.btn-info:focus,.open>.dropdown-toggle.btn-info:hover{color:#fff;background-color:#269abc;border-color:#1b6d85}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled.focus,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled].focus,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning.focus,.btn-warning:focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active.focus,.btn-warning.active:focus,.btn-warning.active:hover,.btn-warning:active.focus,.btn-warning:active:focus,.btn-warning:active:hover,.open>.dropdown-toggle.btn-warning.focus,.open>.dropdown-toggle.btn-warning:focus,.open>.dropdown-toggle.btn-warning:hover{color:#fff;background-color:#d58512;border-color:#985f0d}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled.focus,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled].focus,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c9302c;border-color:#761c19}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active.focus,.btn-danger.active:focus,.btn-danger.active:hover,.btn-danger:active.focus,.btn-danger:active:focus,.btn-danger:active:hover,.open>.dropdown-toggle.btn-danger.focus,.open>.dropdown-toggle.btn-danger:focus,.open>.dropdown-toggle.btn-danger:hover{color:#fff;background-color:#ac2925;border-color:#761c19}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled.focus,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled].focus,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#337ab7;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#777;text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-group-sm>.btn,.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-xs>.btn,.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:height,visibility;-o-transition-property:height,visibility;transition-property:height,visibility}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid\9;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown,.dropup{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;background-color:#337ab7;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#777}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px dashed;border-bottom:4px solid\9}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;float:left}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-left-radius:0;border-top-right-radius:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group .form-control:focus{z-index:3}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn,textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn,textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group .form-control,.input-group-addon,.input-group-btn{display:table-cell}.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn-group:not(:last-child)>.btn,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:first-child>.btn-group:not(:first-child)>.btn,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:focus,.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:focus,.nav>li.disabled>a:hover{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:focus,.nav .open>a:hover{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:focus,.nav-tabs>li.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:focus,.nav-pills>li.active>a:hover{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;-webkit-overflow-scrolling:touch;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1)}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:200px}}.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;height:50px;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1)}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .form-control,.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .checkbox label,.navbar-form .radio label{padding-left:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:focus,.navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:focus,.navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:focus,.navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:focus,.navbar-default .navbar-nav>.open>a:hover{color:#555;background-color:#e7e7e7}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:focus,.navbar-default .btn-link:hover{color:#333}.navbar-default .btn-link[disabled]:focus,.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:focus,fieldset[disabled] .navbar-default .btn-link:hover{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:focus,.navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:focus,.navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:focus,.navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:focus,.navbar-inverse .navbar-toggle:hover{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{color:#fff;background-color:#080808}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:focus,.navbar-inverse .btn-link:hover{color:#fff}.navbar-inverse .btn-link[disabled]:focus,.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:focus,fieldset[disabled] .navbar-inverse .btn-link:hover{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.42857143;color:#337ab7;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:2;color:#23527c;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:3;color:#fff;cursor:default;background-color:#337ab7;border-color:#337ab7}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:focus,.pager li>a:hover{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:focus,a.label:hover{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:focus,.label-default[href]:hover{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:focus,.label-primary[href]:hover{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:focus,.label-success[href]:hover{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:focus,.label-info[href]:hover{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:focus,.label-warning[href]:hover{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:focus,.label-danger[href]:hover{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:middle;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-group-xs>.btn .badge,.btn-xs .badge{top:0;padding:1px 5px}a.badge:focus,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron .h1,.jumbotron h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{padding-right:15px;padding-left:15px;border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-right:60px;padding-left:60px}.jumbotron .h1,.jumbotron h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail a>img,.thumbnail>img{margin-right:auto;margin-left:auto}a.thumbnail.active,a.thumbnail:focus,a.thumbnail:hover{border-color:#337ab7}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-bar-striped,.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress-bar.active,.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{overflow:hidden;zoom:1}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-body,.media-left,.media-right{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}a.list-group-item,button.list-group-item{color:#555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333}a.list-group-item:focus,a.list-group-item:hover,button.list-group-item:focus,button.list-group-item:hover{color:#555;text-decoration:none;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item.disabled,.list-group-item.disabled:focus,.list-group-item.disabled:hover{color:#777;cursor:not-allowed;background-color:#eee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:focus .list-group-item-text,.list-group-item.active:hover .list-group-item-text{color:#c7ddef}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:focus,a.list-group-item-success:hover,button.list-group-item-success:focus,button.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:focus,a.list-group-item-success.active:hover,button.list-group-item-success.active,button.list-group-item-success.active:focus,button.list-group-item-success.active:hover{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:focus,a.list-group-item-info:hover,button.list-group-item-info:focus,button.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:focus,a.list-group-item-info.active:hover,button.list-group-item-info.active,button.list-group-item-info.active:focus,button.list-group-item-info.active:hover{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:focus,a.list-group-item-warning:hover,button.list-group-item-warning:focus,button.list-group-item-warning:hover{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:focus,a.list-group-item-warning.active:hover,button.list-group-item-warning.active,button.list-group-item-warning.active:focus,button.list-group-item-warning.active:hover{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:focus,a.list-group-item-danger:hover,button.list-group-item-danger:focus,button.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover,button.list-group-item-danger.active,button.list-group-item-danger.active:focus,button.list-group-item-danger.active:hover{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>.small,.panel-title>.small>a,.panel-title>a,.panel-title>small,.panel-title>small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-left-radius:0;border-top-right-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.panel-collapse>.table,.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.panel-collapse>.table caption,.panel>.table caption,.panel>.table-responsive>.table caption{padding-right:15px;padding-left:15px}.panel>.table-responsive:first-child>.table:first-child,.panel>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table:first-child>thead:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table-responsive:last-child>.table:last-child,.panel>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child td,.panel>.table>tbody:first-child>tr:first-child th{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.list-group,.panel-group .panel-heading+.panel-collapse>.panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{-webkit-appearance:none;padding:0;cursor:pointer;background:0 0;border:0}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out;-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%)}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5)}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:12px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;filter:alpha(opacity=0);opacity:0;line-break:auto}.tooltip.in{filter:alpha(opacity=90);opacity:.9}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{right:5px;bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);line-break:auto}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{content:"";border-width:10px}.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25)}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>a>img,.carousel-inner>.item>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.active.right,.carousel-inner>.item.next{left:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.carousel-inner>.item.active.left,.carousel-inner>.item.prev{left:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.carousel-inner>.item.active,.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right{left:0;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);background-color:rgba(0,0,0,0);filter:alpha(opacity=50);opacity:.5}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);background-repeat:repeat-x}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);background-repeat:repeat-x}.carousel-control:focus,.carousel-control:hover{color:#fff;text-decoration:none;filter:alpha(opacity=90);outline:0;opacity:.9}.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block;margin-top:-10px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{left:50%;margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{right:50%;margin-right:-10px}.carousel-control .icon-next,.carousel-control .icon-prev{width:20px;height:20px;font-family:serif;line-height:1}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000\9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-10px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-10px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.btn-group-vertical>.btn-group:after,.btn-group-vertical>.btn-group:before,.btn-toolbar:after,.btn-toolbar:before,.clearfix:after,.clearfix:before,.container-fluid:after,.container-fluid:before,.container:after,.container:before,.dl-horizontal dd:after,.dl-horizontal dd:before,.form-horizontal .form-group:after,.form-horizontal .form-group:before,.modal-footer:after,.modal-footer:before,.modal-header:after,.modal-header:before,.nav:after,.nav:before,.navbar-collapse:after,.navbar-collapse:before,.navbar-header:after,.navbar-header:before,.navbar:after,.navbar:before,.pager:after,.pager:before,.panel-body:after,.panel-body:before,.row:after,.row:before{display:table;content:" "}.btn-group-vertical>.btn-group:after,.btn-toolbar:after,.clearfix:after,.container-fluid:after,.container:after,.dl-horizontal dd:after,.form-horizontal .form-group:after,.modal-footer:after,.modal-header:after,.nav:after,.navbar-collapse:after,.navbar-header:after,.navbar:after,.pager:after,.panel-body:after,.row:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-lg,.visible-md,.visible-sm,.visible-xs{display:none!important}.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table!important}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table!important}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table!important}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table!important}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table!important}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}} +/*# sourceMappingURL=bootstrap.min.css.map */ \ No newline at end of file diff --git a/csf/csf/bootstrap/css/bootstrap.min.css.map b/csf/csf/bootstrap/css/bootstrap.min.css.map new file mode 100644 index 0000000..0c2c934 --- /dev/null +++ b/csf/csf/bootstrap/css/bootstrap.min.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["less/normalize.less","less/print.less","bootstrap.css","dist/css/bootstrap.css","less/glyphicons.less","less/scaffolding.less","less/mixins/vendor-prefixes.less","less/mixins/tab-focus.less","less/mixins/image.less","less/type.less","less/mixins/text-emphasis.less","less/mixins/background-variant.less","less/mixins/text-overflow.less","less/code.less","less/grid.less","less/mixins/grid.less","less/mixins/grid-framework.less","less/tables.less","less/mixins/table-row.less","less/forms.less","less/mixins/forms.less","less/buttons.less","less/mixins/buttons.less","less/mixins/opacity.less","less/component-animations.less","less/dropdowns.less","less/mixins/nav-divider.less","less/mixins/reset-filter.less","less/button-groups.less","less/mixins/border-radius.less","less/input-groups.less","less/navs.less","less/navbar.less","less/mixins/nav-vertical-align.less","less/utilities.less","less/breadcrumbs.less","less/pagination.less","less/mixins/pagination.less","less/pager.less","less/labels.less","less/mixins/labels.less","less/badges.less","less/jumbotron.less","less/thumbnails.less","less/alerts.less","less/mixins/alerts.less","less/progress-bars.less","less/mixins/gradients.less","less/mixins/progress-bar.less","less/media.less","less/list-group.less","less/mixins/list-group.less","less/panels.less","less/mixins/panels.less","less/responsive-embed.less","less/wells.less","less/close.less","less/modals.less","less/tooltip.less","less/mixins/reset-text.less","less/popovers.less","less/carousel.less","less/mixins/clearfix.less","less/mixins/center-block.less","less/mixins/hide-text.less","less/responsive-utilities.less","less/mixins/responsive-visibility.less"],"names":[],"mappings":"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kDG,edokDH,MAAA,acpkDG,edukDH,MAAA,IcvkDG,ed0kDH,MAAA,ac1kDG,ed6kDH,MAAA,ac7kDG,edglDH,MAAA,IchlDG,edmlDH,MAAA,ac9kDG,edilDH,MAAA,YchmDG,edmmDH,MAAA,KcnmDG,gBdsmDH,KAAA,KctmDG,gBdymDH,KAAA,aczmDG,gBd4mDH,KAAA,ac5mDG,ed+mDH,KAAA,Ic/mDG,edknDH,KAAA,aclnDG,edqnDH,KAAA,acrnDG,edwnDH,KAAA,IcxnDG,ed2nDH,KAAA,ac3nDG,ed8nDH,KAAA,ac9nDG,edioDH,KAAA,IcjoDG,edooDH,KAAA,ac/nDG,edkoDH,KAAA,YcnnDG,edsnDH,KAAA,KctnDG,kBdynDH,YAAA,KcznDG,kBd4nDH,YAAA,ac5nDG,kBd+nDH,YAAA,ac/nDG,iBdkoDH,YAAA,IcloDG,iBdqoDH,YAAA,acroDG,iBdwoDH,YAAA,acxoDG,iBd2oDH,YAAA,Ic3oDG,iBd8oDH,YAAA,ac9oDG,iBdipDH,YAAA,acjpDG,iBdopDH,YAAA,IcppDG,iBdupDH,YAAA,acvpDG,iBd0pDH,YAAA,Yc5rDG,iBACE,YAAA,EAOJ,yBACE,UAAA,WAAA,WAAA,WAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,Ud0rDD,MAAA,Kc1rDC,Wd6rDD,MAAA,Kc7rDC,WdgsDD,MAAA,achsDC,WdmsDD,MAAA,acnsDC,UdssDD,MAAA,IctsDC,UdysDD,MAAA,aczsDC,Ud4sDD,MAAA,ac5sDC,Ud+sDD,MAAA,Ic/sDC,UdktDD,MAAA,acltDC,UdqtDD,MAAA,acrtDC,UdwtDD,MAAA,IcxtDC,Ud2tDD,MAAA,ac5sDC,Ud+sDD,MAAA,Yc/sDC,gBdktDD,MAAA,KcltDC,gBdqtDD,MAAA,acrtDC,gBdwtDD,MAAA,acxtDC,ed2tDD,MAAA,Ic3tDC,ed8tDD,MAAA,ac9tDC,ediuDD,MAAA,acjuDC,edouDD,MAAA,IcpuDC,eduuDD,MAAA,acvuDC,ed0uDD,MAAA,ac1uDC,ed6uDD,MAAA,Ic7uDC,edgvDD,MAAA,ac3uDC,ed8uDD,MAAA,Yc7vDC,edgwDD,MAAA,KchwDC,gBdmwDD,KAAA,KcnwDC,gBdswDD,KAAA,actwDC,gBdywDD,KAAA,aczwDC,ed4wDD,KAAA,Ic5wDC,ed+wDD,KAAA,ac/wDC,edkxDD,KAAA,aclxDC,edqxDD,KAAA,IcrxDC,edwxDD,KAAA,acxxDC,ed2xDD,KAAA,ac3xDC,ed8xDD,KAAA,Ic9xDC,ediyDD,KAAA,ac5xDC,ed+xDD,KAAA,YchxDC,edmxDD,KAAA,KcnxDC,kBdsxDD,YAAA,KctxDC,kBdyxDD,YAAA,aczxDC,kBd4xDD,YAAA,ac5xDC,iBd+xDD,YAAA,Ic/xDC,iBdkyDD,YAAA,aclyDC,iBdqyDD,YAAA,acryDC,iBdwyDD,YAAA,IcxyDC,iBd2yDD,YAAA,ac3yDC,iBd8yDD,YAAA,ac9yDC,iBdizDD,YAAA,IcjzDC,iBdozDD,YAAA,acpzDC,iBduzDD,YAAA,YY9yDD,iBE3CE,YAAA,GAQF,yBACE,UAAA,WAAA,WAAA,WAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,Udw1DD,MAAA,Kcx1DC,Wd21DD,MAAA,Kc31DC,Wd81DD,MAAA,ac91DC,Wdi2DD,MAAA,acj2DC,Udo2DD,MAAA,Icp2DC,Udu2DD,MAAA,acv2DC,Ud02DD,MAAA,ac12DC,Ud62DD,MAAA,Ic72DC,Udg3DD,MAAA,ach3DC,Udm3DD,MAAA,acn3DC,Uds3DD,MAAA,Ict3DC,Udy3DD,MAAA,ac12DC,Ud62DD,MAAA,Yc72DC,gBdg3DD,MAAA,Kch3DC,gBdm3DD,MAAA,acn3DC,gBds3DD,MAAA,act3DC,edy3DD,MAAA,Icz3DC,ed43DD,MAAA,ac53DC,ed+3DD,MAAA,ac/3DC,edk4DD,MAAA,Icl4DC,edq4DD,MAAA,acr4DC,edw4DD,MAAA,acx4DC,ed24DD,MAAA,Ic34DC,ed84DD,MAAA,acz4DC,ed44DD,MAAA,Yc35DC,ed85DD,MAAA,Kc95DC,gBdi6DD,KAAA,Kcj6DC,gBdo6DD,KAAA,acp6DC,gBdu6DD,KAAA,acv6DC,ed06DD,KAAA,Ic16DC,ed66DD,KAAA,ac76DC,edg7DD,KAAA,ach7DC,edm7DD,KAAA,Icn7DC,eds7DD,KAAA,act7DC,edy7DD,KAAA,acz7DC,ed47DD,KAAA,Ic57DC,ed+7DD,KAAA,ac17DC,ed67DD,KAAA,Yc96DC,edi7DD,KAAA,Kcj7DC,kBdo7DD,YAAA,Kcp7DC,kBdu7DD,YAAA,acv7DC,kBd07DD,YAAA,ac17DC,iBd67DD,YAAA,Ic77DC,iBdg8DD,YAAA,ach8DC,iBdm8DD,YAAA,acn8DC,iBds8DD,YAAA,Ict8DC,iBdy8DD,YAAA,acz8DC,iBd48DD,YAAA,ac58DC,iBd+8DD,YAAA,Ic/8DC,iBdk9DD,YAAA,acl9DC,iBdq9DD,YAAA,YYz8DD,iBE9CE,YAAA,GAQF,0BACE,UAAA,WAAA,WAAA,WAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,UAAA,Uds/DD,MAAA,Kct/DC,Wdy/DD,MAAA,Kcz/DC,Wd4/DD,MAAA,ac5/DC,Wd+/DD,MAAA,ac//DC,UdkgED,MAAA,IclgEC,UdqgED,MAAA,acrgEC,UdwgED,MAAA,acxgEC,Ud2gED,MAAA,Ic3gEC,Ud8gED,MAAA,ac9gEC,UdihED,MAAA,acjhEC,UdohED,MAAA,IcphEC,UduhED,MAAA,acxgEC,Ud2gED,MAAA,Yc3gEC,gBd8gED,MAAA,Kc9gEC,gBdihED,MAAA,acjhEC,gBdohED,MAAA,acphEC,eduhED,MAAA,IcvhEC,ed0hED,MAAA,ac1hEC,ed6hED,MAAA,ac7hEC,edgiED,MAAA,IchiEC,edmiED,MAAA,acniEC,edsiED,MAAA,actiEC,edyiED,MAAA,IcziEC,ed4iED,MAAA,acviEC,ed0iED,MAAA,YczjEC,ed4jED,MAAA,Kc5jEC,gBd+jED,KAAA,Kc/jEC,gBdkkED,KAAA,aclkEC,gBdqkED,KAAA,acrkEC,edwkED,KAAA,IcxkEC,ed2kED,KAAA,ac3kEC,ed8kED,KAAA,ac9kEC,edilED,KAAA,IcjlEC,edolED,KAAA,acplEC,edulED,KAAA,acvlEC,ed0lED,KAAA,Ic1lEC,ed6lED,KAAA,acxlEC,ed2lED,KAAA,Yc5kEC,ed+kED,KAAA,Kc/kEC,kBdklED,YAAA,KcllEC,kBdqlED,YAAA,acrlEC,kBdwlED,YAAA,acxlEC,iBd2lED,YAAA,Ic3lEC,iBd8lED,YAAA,ac9lEC,iBdimED,YAAA,acjmEC,iBdomED,YAAA,IcpmEC,iBdumED,YAAA,acvmEC,iBd0mED,YAAA,ac1mEC,iBd6mED,YAAA,Ic7mEC,iBdgnED,YAAA,achnEC,iBdmnED,YAAA,YetrED,iBACA,YAAA,GAGA,MACA,iBAAA,YAEA,QfyrED,YAAA,IevrEC,eAAgB,IAChB,MAAA,KfyrED,WAAA,KelrEC,GACA,WAAA,KfsrED,OexrEC,MAAO,KdmsEP,UAAW,KACX,cAAe,KcvrET,mBd0rER,mBczrEQ,mBAHA,mBACA,mBd0rER,mBDHC,QAAA,IensEC,YAAa,WAoBX,eAAA,IACA,WAAA,IAAA,MAAA,KArBJ,mBdktEE,eAAgB,OAChB,cAAe,IAAI,MAAM,KDJ1B,uCCMD,uCcrtEA,wCdstEA,wCclrEI,2CANI,2CforEP,WAAA,EezqEG,mBf4qEH,WAAA,IAAA,MAAA,KCWD,cACE,iBAAkB,Kc/pEpB,6BdkqEA,6BcjqEE,6BAZM,6BfsqEP,6BCMD,6BDHC,QAAA,ICWD,gBACE,OAAQ,IAAI,MAAM,Kc1qEpB,4Bd6qEA,4Bc7qEA,4BAQQ,4Bf8pEP,4BCMD,4Bc7pEM,OAAA,IAAA,MAAA,KAYF,4BAFJ,4BfopEC,oBAAA,IevoEG,yCf0oEH,iBAAA,QehoEC,4BACA,iBAAA,QfooED,uBe9nEG,SAAA,OdyoEF,QAAS,acxoEL,MAAA,KAEA,sBfioEL,sBgB7wEC,SAAA,OfwxEA,QAAS,WACT,MAAO,KAST,0BerxEE,0Bf+wEF,0BAGA,0BexxEM,0BAMJ,0BfgxEF,0BAGA,0BACA,0BDNC,0BCAD,0BAGA,0BASE,iBAAkB,QDLnB,sCgBlyEC,sCAAA,oCfyyEF,sCetxEM,sCf2xEJ,iBAAkB,QASpB,2Be1yEE,2BfoyEF,2BAGA,2Be7yEM,2BAMJ,2BfqyEF,2BAGA,2BACA,2BDNC,2BCAD,2BAGA,2BASE,iBAAkB,QDLnB,uCgBvzEC,uCAAA,qCf8zEF,uCe3yEM,uCfgzEJ,iBAAkB,QASpB,wBe/zEE,wBfyzEF,wBAGA,wBel0EM,wBAMJ,wBf0zEF,wBAGA,wBACA,wBDNC,wBCAD,wBAGA,wBASE,iBAAkB,QDLnB,oCgB50EC,oCAAA,kCfm1EF,oCeh0EM,oCfq0EJ,iBAAkB,QASpB,2Bep1EE,2Bf80EF,2BAGA,2Bev1EM,2BAMJ,2Bf+0EF,2BAGA,2BACA,2BDNC,2BCAD,2BAGA,2BASE,iBAAkB,QDLnB,uCgBj2EC,uCAAA,qCfw2EF,uCer1EM,uCf01EJ,iBAAkB,QASpB,0Bez2EE,0Bfm2EF,0BAGA,0Be52EM,0BAMJ,0Bfo2EF,0BAGA,0BACA,0BDNC,0BCAD,0BAGA,0BASE,iBAAkB,QDLnB,sCehtEC,sCADF,oCdwtEA,sCe12EM,sCDoJJ,iBAAA,QA6DF,kBACE,WAAY,KA3DV,WAAA,KAEA,oCACA,kBACA,MAAA,KfotED,cAAA,Ke7pEC,WAAY,OAnDV,mBAAA,yBfmtEH,OAAA,IAAA,MAAA,KCWD,yBACE,cAAe,Ec5qEjB,qCd+qEA,qCcjtEI,qCARM,qCfktET,qCCMD,qCDHC,YAAA,OCWD,kCACE,OAAQ,EcvrEV,0Dd0rEA,0Dc1rEA,0DAzBU,0Df4sET,0DCMD,0DAME,YAAa,Ec/rEf,yDdksEA,yDclsEA,yDArBU,yDfgtET,yDCMD,yDAME,aAAc,EDLjB,yDe1sEW,yDEzNV,yDjBk6EC,yDiBj6ED,cAAA,GAMA,SjBk6ED,UAAA,EiB/5EC,QAAS,EACT,OAAA,EACA,OAAA,EAEA,OACA,QAAA,MACA,MAAA,KACA,QAAA,EACA,cAAA,KACA,UAAA,KjBi6ED,YAAA,QiB95EC,MAAO,KACP,OAAA,EACA,cAAA,IAAA,MAAA,QAEA,MjBg6ED,QAAA,aiBr5EC,UAAW,Kb4BX,cAAA,IACG,YAAA,IJ63EJ,mBiBr5EC,mBAAoB,WhBg6EjB,gBAAiB,WgB95EpB,WAAA,WjBy5ED,qBiBv5EC,kBAGA,OAAQ,IAAI,EAAE,EACd,WAAA,MjBs5ED,YAAA,OiBj5EC,iBACA,QAAA,MAIF,kBhB25EE,QAAS,MgBz5ET,MAAA,KAIF,iBAAA,ahB05EE,OAAQ,KI99ER,uBY2EF,2BjB64EC,wBiB54EC,QAAA,IAAA,KAAA,yBACA,eAAA,KAEA,OACA,QAAA,MjB+4ED,YAAA,IiBr3EC,UAAW,KACX,YAAA,WACA,MAAA,KAEA,cACA,QAAA,MACA,MAAA,KACA,OAAA,KACA,QAAA,IAAA,KACA,UAAA,KACA,YAAA,WACA,MAAA,KbxDA,iBAAA,KACQ,iBAAA,KAyHR,OAAA,IAAA,MAAA,KACK,cAAA,IACG,mBAAA,MAAA,EAAA,IAAA,IAAA,iBJwzET,WAAA,MAAA,EAAA,IAAA,IAAA,iBkBh8EC,mBAAA,aAAA,YAAA,KAAA,mBAAA,YAAA,KACE,cAAA,aAAA,YAAA,KAAA,WAAA,YAAA,KACA,WAAA,aAAA,YAAA,KAAA,WAAA,YAAA,KdWM,oBJy7ET,aAAA,QIx5EC,QAAA,EACE,mBAAA,MAAA,EAAA,IAAA,IAAA,iBAAA,EAAA,EAAA,IAAA,qBACA,WAAA,MAAA,EAAA,IAAA,IAAA,iBAAA,EAAA,EAAA,IAAA,qBAEF,gCAA0B,MAAA,KJ25E3B,QAAA,EI15EiC,oCJ65EjC,MAAA,KiBh4EG,yCACA,MAAA,KAQF,0BhBs4EA,iBAAkB,YAClB,OAAQ,EgBn4EN,wBjB63EH,wBiB13EC,iChBq4EA,iBAAkB,KgBn4EhB,QAAA,EAIF,wBACE,iCjB03EH,OAAA,YiB72EC,sBjBg3ED,OAAA,KiB91EG,mBhB02EF,mBAAoB,KAEtB,qDgB32EM,8BjBo2EH,8BiBj2EC,wCAAA,+BhB62EA,YAAa,KgB32EX,iCjBy2EH,iCiBt2EC,2CAAA,kChB02EF,0BACA,0BACA,oCACA,2BAKE,YAAa,KgBh3EX,iCjB82EH,iCACF,2CiBp2EC,kChBu2EA,0BACA,0BACA,oCACA,2BgBz2EA,YAAA,MhBi3EF,YgBv2EE,cAAA,KAGA,UADA,OjBi2ED,SAAA,SiBr2EC,QAAS,MhBg3ET,WAAY,KgBx2EV,cAAA,KAGA,gBADA,aAEA,WAAA,KjBi2EH,aAAA,KiB91EC,cAAe,EhBy2Ef,YAAa,IACb,OAAQ,QgBp2ER,+BjBg2ED,sCiBl2EC,yBACA,gCAIA,SAAU,ShBw2EV,WAAY,MgBt2EZ,YAAA,MAIF,oBAAA,cAEE,WAAA,KAGA,iBADA,cAEA,SAAA,SACA,QAAA,aACA,aAAA,KjB61ED,cAAA,EiB31EC,YAAa,IhBs2Eb,eAAgB,OgBp2EhB,OAAA,QAUA,kCjBo1ED,4BCWC,WAAY,EACZ,YAAa,KgBv1Eb,wCAAA,qCjBm1ED,8BCOD,+BgBh2EI,2BhB+1EJ,4BAME,OAAQ,YDNT,0BiBv1EG,uBAMF,oCAAA,iChB61EA,OAAQ,YDNT,yBiBp1EK,sBAaJ,mCAFF,gCAGE,OAAA,YAGA,qBjBy0ED,WAAA,KiBv0EC,YAAA,IhBk1EA,eAAgB,IgBh1Ed,cAAA,EjB00EH,8BiB5zED,8BCnQE,cAAA,EACA,aAAA,EAEA,UACA,OAAA,KlBkkFD,QAAA,IAAA,KkBhkFC,UAAA,KACE,YAAA,IACA,cAAA,IAGF,gBjB0kFA,OAAQ,KiBxkFN,YAAA,KD2PA,0BAFJ,kBAGI,OAAA,KAEA,6BACA,OAAA,KjBy0EH,QAAA,IAAA,KiB/0EC,UAAW,KAST,YAAA,IACA,cAAA,IAVJ,mChB81EE,OAAQ,KgBh1EN,YAAA,KAGA,6CAjBJ,qCAkBI,OAAA,KAEA,oCACA,OAAA,KjBy0EH,WAAA,KiBr0EC,QAAS,IAAI,KC/Rb,UAAA,KACA,YAAA,IAEA,UACA,OAAA,KlBumFD,QAAA,KAAA,KkBrmFC,UAAA,KACE,YAAA,UACA,cAAA,IAGF,gBjB+mFA,OAAQ,KiB7mFN,YAAA,KDuRA,0BAFJ,kBAGI,OAAA,KAEA,6BACA,OAAA,KjBk1EH,QAAA,KAAA,KiBx1EC,UAAW,KAST,YAAA,UACA,cAAA,IAVJ,mChBu2EE,OAAQ,KgBz1EN,YAAA,KAGA,6CAjBJ,qCAkBI,OAAA,KAEA,oCACA,OAAA,KjBk1EH,WAAA,KiBz0EC,QAAS,KAAK,KAEd,UAAA,KjB00ED,YAAA,UiBt0EG,cjBy0EH,SAAA,SiBp0EC,4BACA,cAAA,OAEA,uBACA,SAAA,SACA,IAAA,EACA,MAAA,EACA,QAAA,EACA,QAAA,MACA,MAAA,KjBu0ED,OAAA,KiBr0EC,YAAa,KhBg1Eb,WAAY,OACZ,eAAgB,KDLjB,oDiBv0EC,uCADA,iCAGA,MAAO,KhBg1EP,OAAQ,KACR,YAAa,KDLd,oDiBv0EC,uCADA,iCAKA,MAAO,KhB80EP,OAAQ,KACR,YAAa,KAKf,uBAEA,8BAJA,4BADA,yBAEA,oBAEA,2BDNC,4BkBruFG,mCAJA,yBD0ZJ,gCbvWE,MAAA,QJ2rFD,2BkBxuFG,aAAA,QACE,mBAAA,MAAA,EAAA,IAAA,IAAA,iBd4CJ,WAAA,MAAA,EAAA,IAAA,IAAA,iBJgsFD,iCiBz1EC,aAAc,QC5YZ,mBAAA,MAAA,EAAA,IAAA,IAAA,iBAAA,EAAA,EAAA,IAAA,QACA,WAAA,MAAA,EAAA,IAAA,IAAA,iBAAA,EAAA,EAAA,IAAA,QlByuFH,gCiB91EC,MAAO,QCtYL,iBAAA,QlBuuFH,aAAA,QCWD,oCACE,MAAO,QAKT,uBAEA,8BAJA,4BADA,yBAEA,oBAEA,2BDNC,4BkBnwFG,mCAJA,yBD6ZJ,gCb1WE,MAAA,QJytFD,2BkBtwFG,aAAA,QACE,mBAAA,MAAA,EAAA,IAAA,IAAA,iBd4CJ,WAAA,MAAA,EAAA,IAAA,IAAA,iBJ8tFD,iCiBp3EC,aAAc,QC/YZ,mBAAA,MAAA,EAAA,IAAA,IAAA,iBAAA,EAAA,EAAA,IAAA,QACA,WAAA,MAAA,EAAA,IAAA,IAAA,iBAAA,EAAA,EAAA,IAAA,QlBuwFH,gCiBz3EC,MAAO,QCzYL,iBAAA,QlBqwFH,aAAA,QCWD,oCACE,MAAO,QAKT,qBAEA,4BAJA,0BADA,uBAEA,kBAEA,yBDNC,0BkBjyFG,iCAJA,uBDgaJ,8Bb7WE,MAAA,QJuvFD,yBkBpyFG,aAAA,QACE,mBAAA,MAAA,EAAA,IAAA,IAAA,iBd4CJ,WAAA,MAAA,EAAA,IAAA,IAAA,iBJ4vFD,+BiB/4EC,aAAc,QClZZ,mBAAA,MAAA,EAAA,IAAA,IAAA,iBAAA,EAAA,EAAA,IAAA,QACA,WAAA,MAAA,EAAA,IAAA,IAAA,iBAAA,EAAA,EAAA,IAAA,QlBqyFH,8BiBp5EC,MAAO,QC5YL,iBAAA,QlBmyFH,aAAA,QiB/4EG,kCjBk5EH,MAAA,QiB/4EG,2CjBk5EH,IAAA,KiBv4EC,mDACA,IAAA,EAEA,YjB04ED,QAAA,MiBvzEC,WAAY,IAwEZ,cAAe,KAtIX,MAAA,QAEA,yBjBy3EH,yBiBrvEC,QAAS,aA/HP,cAAA,EACA,eAAA,OjBw3EH,2BiB1vEC,QAAS,aAxHP,MAAA,KjBq3EH,eAAA,OiBj3EG,kCACA,QAAA,aAmHJ,0BhB4wEE,QAAS,aACT,eAAgB,OgBr3Ed,wCjB82EH,6CiBtwED,2CjBywEC,MAAA,KiB72EG,wCACA,MAAA,KAmGJ,4BhBwxEE,cAAe,EgBp3Eb,eAAA,OAGA,uBADA,oBjB82EH,QAAA,aiBpxEC,WAAY,EhB+xEZ,cAAe,EgBr3EX,eAAA,OAsFN,6BAAA,0BAjFI,aAAA,EAiFJ,4CjB6xEC,sCiBx2EG,SAAA,SjB22EH,YAAA,EiBh2ED,kDhB42EE,IAAK,GgBl2EL,2BjB+1EH,kCiBh2EG,wBAEA,+BAXF,YAAa,IhBo3Eb,WAAY,EgBn2EV,cAAA,EJviBF,2BIshBF,wBJrhBE,WAAA,KI4jBA,6BAyBA,aAAc,MAnCV,YAAA,MAEA,yBjBw1EH,gCACF,YAAA,IiBx3EG,cAAe,EAwCf,WAAA,OAwBJ,sDAdQ,MAAA,KjB80EL,yBACF,+CiBn0EC,YAAA,KAEE,UAAW,MjBs0EZ,yBACF,+CmBp6FG,YAAa,IACf,UAAA,MAGA,KACA,QAAA,aACA,QAAA,IAAA,KAAA,cAAA,EACA,UAAA,KACA,YAAA,IACA,YAAA,WACA,WAAA,OC0CA,YAAA,OACA,eAAA,OACA,iBAAA,aACA,aAAA,ahB+JA,OAAA,QACG,oBAAA,KACC,iBAAA,KACI,gBAAA,KJ+tFT,YAAA,KmBv6FG,iBAAA,KlBm7FF,OAAQ,IAAI,MAAM,YAClB,cAAe,IkB96Ff,kBdzBA,kBACA,WLk8FD,kBCOD,kBADA,WAME,QAAS,IAAI,KAAK,yBAClB,eAAgB,KkBh7FhB,WnBy6FD,WmB56FG,WlBw7FF,MAAO,KkBn7FL,gBAAA,Kf6BM,YADR,YJk5FD,iBAAA,KmBz6FC,QAAA,ElBq7FA,mBAAoB,MAAM,EAAE,IAAI,IAAI,iBAC5B,WAAY,MAAM,EAAE,IAAI,IAAI,iBoBh+FpC,cAGA,ejB8DA,wBACQ,OAAA,YJ05FT,OAAA,kBmBz6FG,mBAAA,KlBq7FM,WAAY,KkBn7FhB,QAAA,IASN,eC3DE,yBACA,eAAA,KpBi+FD,aoB99FC,MAAA,KnB0+FA,iBAAkB,KmBx+FhB,aAAA,KpBk+FH,mBoBh+FO,mBAEN,MAAA,KACE,iBAAA,QACA,aAAA,QpBi+FH,mBoB99FC,MAAA,KnB0+FA,iBAAkB,QAClB,aAAc,QmBt+FR,oBADJ,oBpBi+FH,mCoB99FG,MAAA,KnB0+FF,iBAAkB,QAClB,aAAc,QmBt+FN,0BnB4+FV,0BAHA,0BmB1+FM,0BnB4+FN,0BAHA,0BDFC,yCoBx+FK,yCnB4+FN,yCmBv+FE,MAAA,KnB++FA,iBAAkB,QAClB,aAAc,QmBx+FZ,oBpBg+FH,oBoBh+FG,mCnB6+FF,iBAAkB,KmBz+FV,4BnB8+FV,4BAHA,4BDHC,6BCOD,6BAHA,6BkB39FA,sCClBM,sCnB8+FN,sCmBx+FI,iBAAA,KACA,aAAA,KDcJ,oBC9DE,MAAA,KACA,iBAAA,KpB0hGD,aoBvhGC,MAAA,KnBmiGA,iBAAkB,QmBjiGhB,aAAA,QpB2hGH,mBoBzhGO,mBAEN,MAAA,KACE,iBAAA,QACA,aAAA,QpB0hGH,mBoBvhGC,MAAA,KnBmiGA,iBAAkB,QAClB,aAAc,QmB/hGR,oBADJ,oBpB0hGH,mCoBvhGG,MAAA,KnBmiGF,iBAAkB,QAClB,aAAc,QmB/hGN,0BnBqiGV,0BAHA,0BmBniGM,0BnBqiGN,0BAHA,0BDFC,yCoBjiGK,yCnBqiGN,yCmBhiGE,MAAA,KnBwiGA,iBAAkB,QAClB,aAAc,QmBjiGZ,oBpByhGH,oBoBzhGG,mCnBsiGF,iBAAkB,KmBliGV,4BnBuiGV,4BAHA,4BDHC,6BCOD,6BAHA,6BkBjhGA,sCCrBM,sCnBuiGN,sCmBjiGI,iBAAA,QACA,aAAA,QDkBJ,oBClEE,MAAA,QACA,iBAAA,KpBmlGD,aoBhlGC,MAAA,KnB4lGA,iBAAkB,QmB1lGhB,aAAA,QpBolGH,mBoBllGO,mBAEN,MAAA,KACE,iBAAA,QACA,aAAA,QpBmlGH,mBoBhlGC,MAAA,KnB4lGA,iBAAkB,QAClB,aAAc,QmBxlGR,oBADJ,oBpBmlGH,mCoBhlGG,MAAA,KnB4lGF,iBAAkB,QAClB,aAAc,QmBxlGN,0BnB8lGV,0BAHA,0BmB5lGM,0BnB8lGN,0BAHA,0BDFC,yCoB1lGK,yCnB8lGN,yCmBzlGE,MAAA,KnBimGA,iBAAkB,QAClB,aAAc,QmB1lGZ,oBpBklGH,oBoBllGG,mCnB+lGF,iBAAkB,KmB3lGV,4BnBgmGV,4BAHA,4BDHC,6BCOD,6BAHA,6BkBtkGA,sCCzBM,sCnBgmGN,sCmB1lGI,iBAAA,QACA,aAAA,QDsBJ,oBCtEE,MAAA,QACA,iBAAA,KpB4oGD,UoBzoGC,MAAA,KnBqpGA,iBAAkB,QmBnpGhB,aAAA,QpB6oGH,gBoB3oGO,gBAEN,MAAA,KACE,iBAAA,QACA,aAAA,QpB4oGH,gBoBzoGC,MAAA,KnBqpGA,iBAAkB,QAClB,aAAc,QmBjpGR,iBADJ,iBpB4oGH,gCoBzoGG,MAAA,KnBqpGF,iBAAkB,QAClB,aAAc,QmBjpGN,uBnBupGV,uBAHA,uBmBrpGM,uBnBupGN,uBAHA,uBDFC,sCoBnpGK,sCnBupGN,sCmBlpGE,MAAA,KnB0pGA,iBAAkB,QAClB,aAAc,QmBnpGZ,iBpB2oGH,iBoB3oGG,gCnBwpGF,iBAAkB,KmBppGV,yBnBypGV,yBAHA,yBDHC,0BCOD,0BAHA,0BkB3nGA,mCC7BM,mCnBypGN,mCmBnpGI,iBAAA,QACA,aAAA,QD0BJ,iBC1EE,MAAA,QACA,iBAAA,KpBqsGD,aoBlsGC,MAAA,KnB8sGA,iBAAkB,QmB5sGhB,aAAA,QpBssGH,mBoBpsGO,mBAEN,MAAA,KACE,iBAAA,QACA,aAAA,QpBqsGH,mBoBlsGC,MAAA,KnB8sGA,iBAAkB,QAClB,aAAc,QmB1sGR,oBADJ,oBpBqsGH,mCoBlsGG,MAAA,KnB8sGF,iBAAkB,QAClB,aAAc,QmB1sGN,0BnBgtGV,0BAHA,0BmB9sGM,0BnBgtGN,0BAHA,0BDFC,yCoB5sGK,yCnBgtGN,yCmB3sGE,MAAA,KnBmtGA,iBAAkB,QAClB,aAAc,QmB5sGZ,oBpBosGH,oBoBpsGG,mCnBitGF,iBAAkB,KmB7sGV,4BnBktGV,4BAHA,4BDHC,6BCOD,6BAHA,6BkBhrGA,sCCjC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A,QkDrxKC,WAAY,IAAI,MAAM,KjDizKtB,2BAA4B,IiD9yK1B,0BAAA,IAHJ,mBAAA,mCAMM,cAAA,ElDwxKL,oCkDnxKG,oDjD+yKF,aAAc,IAAI,EiD7yKZ,cAAA,EvBtEL,4D3B61KF,4EkDjxKG,WAAA,EjD6yKF,uBAAwB,IiD3yKlB,wBAAA,IvBtEL,0D3B21KF,0EkD1yKC,cAAe,EvB1Df,2BAAA,IACC,0BAAA,IuB0FH,+EAEI,uBAAA,ElD8wKH,wBAAA,EkD1wKC,wDlD6wKD,iBAAA,EC4BD,0BACE,iBAAkB,EiDlyKpB,8BlD0wKC,ckD1wKD,gCjDuyKE,cAAe,EiDvyKjB,sCAQM,sBlDwwKL,wCC4BC,cAAe,K0Br5Kf,aAAA,KuByGF,wDlDqxKC,0BC4BC,uBAAwB,IACxB,wBAAyB,IiDlzK3B,yFAoBQ,yFlDwwKP,2DkDzwKO,2DjDqyKN,uBAAwB,IACxB,wBAAyB,IAK3B,wGiD9zKA,wGjD4zKA,wGDtBC,wGCuBD,0EiD7zKA,0EjD2zKA,0EiDnyKU,0EjD2yKR,uBAAwB,IAK1B,uGiDx0KA,uGjDs0KA,uGDtBC,uGCuBD,yEiDv0KA,yEjDq0KA,yEiDzyKU,yEvB7HR,wBAAA,IuBiGF,sDlDqzKC,yBC4BC,2BAA4B,IAC5B,0BAA2B,IiDxyKrB,qFA1CR,qFAyCQ,wDlDmxKP,wDC4BC,2BAA4B,IAC5B,0BAA2B,IAG7B,oGDtBC,oGCwBD,oGiD91KA,oGjD21KA,uEiD7yKU,uEjD+yKV,uEiD71KA,uEjDm2KE,0BAA2B,IAG7B,mGDtBC,mGCwBD,mGiDx2KA,mGjDq2KA,sEiDnzKU,sEjDqzKV,sEiDv2KA,sEjD62KE,2BAA4B,IiDlzK1B,0BlD2xKH,qCkDt1KD,0BAAA,qCA+DI,WAAA,IAAA,MAAA,KA/DJ,kDAAA,kDAmEI,WAAA,EAnEJ,uBAAA,yCjD23KE,OAAQ,EiDjzKA,+CjDqzKV,+CiD/3KA,+CjDi4KA,+CAEA,+CANA,+CDjBC,iECoBD,iEiDh4KA,iEjDk4KA,iEAEA,iEANA,iEAWE,YAAa,EiD3zKL,8CjD+zKV,8CiD74KA,8CjD+4KA,8CAEA,8CANA,8CDjBC,gECo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Dk2MD,kBACF,QAAA,iB+D91MG,yB/Dk2MD,mBACF,QAAA,kBgEh6MC,yBhEo6MC,yBgEn6MD,QAAA,wBACA,+CAAU,YhEw6MT,QAAA,gBC4BD,iB+Dl8MU,QAAA,gBhE26MX,c+Dr2MG,QAAS,oB/Dy2MV,c+D32MC,c/D42MH,QAAA,sB+Dv2MG,+C/D22MD,kBACF,QAAA,iB+Dv2MG,+C/D22MD,mBACF,QAAA,kBgE97MC,+ChEk8MC,yBgEj8MD,QAAA,wBACA,gDAAU,YhEs8MT,QAAA,gBC4BD,iB+Dh+MU,QAAA,gBhEy8MX,c+D92MG,QAAS,oB/Dk3MV,c+Dp3MC,c/Dq3MH,QAAA,sB+Dh3MG,gD/Do3MD,kBACF,QAAA,iB+Dh3MG,gD/Do3MD,mBACF,QAAA,kBgE59MC,gDhEg+MC,yBgE/9MD,QAAA,wBACA,0BAAU,YhEo+MT,QAAA,gBC4BD,iB+D9/MU,QAAA,gBhEu+MX,c+Dv3MG,QAAS,oB/D23MV,c+D73MC,c/D83MH,QAAA,sB+Dz3MG,0B/D63MD,kBACF,QAAA,iB+Dz3MG,0B/D63MD,mBACF,QAAA,kBgEl/MC,0BhEs/MC,yBACF,QAAA,wBgEv/MC,yBhE2/MC,WACF,QAAA,gBgE5/MC,+ChEggNC,WACF,QAAA,gBgEjgNC,gDhEqgNC,WACF,QAAA,gBAGA,0B+Dh3MC,WA4BE,QAAS,gBC5LX,eAAU,QAAA,eACV,aAAU,ehEyhNT,QAAA,gBC4BD,oB+DnjNU,QAAA,gBhE4hNX,iB+D93MG,QAAS,oBAMX,iB/D23MD,iB+Dt2MG,QAAS,sB/D22MZ,qB+D/3MC,QAAS,e/Dk4MV,a+D53MC,qBAcE,QAAS,iB/Dm3MZ,sB+Dh4MC,QAAS,e/Dm4MV,a+D73MC,sBAOE,QAAS,kB/D23MZ,4B+D53MC,QAAS,eCpLT,ahEojNC,4BACF,QAAA,wBC6BD,aACE,cACE,QAAS","sourcesContent":["/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */\n\n//\n// 1. Set default font family to sans-serif.\n// 2. Prevent iOS and IE text size adjust after device orientation change,\n// without disabling user zoom.\n//\n\nhtml {\n font-family: sans-serif; // 1\n -ms-text-size-adjust: 100%; // 2\n -webkit-text-size-adjust: 100%; // 2\n}\n\n//\n// Remove default margin.\n//\n\nbody {\n margin: 0;\n}\n\n// HTML5 display definitions\n// ==========================================================================\n\n//\n// Correct `block` display not defined for any HTML5 element in IE 8/9.\n// Correct `block` display not defined for `details` or `summary` in IE 10/11\n// and Firefox.\n// Correct `block` display not defined for `main` in IE 11.\n//\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nmenu,\nnav,\nsection,\nsummary {\n display: block;\n}\n\n//\n// 1. Correct `inline-block` display not defined in IE 8/9.\n// 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.\n//\n\naudio,\ncanvas,\nprogress,\nvideo {\n display: inline-block; // 1\n vertical-align: baseline; // 2\n}\n\n//\n// Prevent modern browsers from displaying `audio` without controls.\n// Remove excess height in iOS 5 devices.\n//\n\naudio:not([controls]) {\n display: none;\n height: 0;\n}\n\n//\n// Address `[hidden]` styling not present in IE 8/9/10.\n// Hide the `template` element in IE 8/9/10/11, Safari, and Firefox < 22.\n//\n\n[hidden],\ntemplate {\n display: none;\n}\n\n// Links\n// ==========================================================================\n\n//\n// Remove the gray background color from active links in IE 10.\n//\n\na {\n background-color: transparent;\n}\n\n//\n// Improve readability of focused elements when they are also in an\n// active/hover state.\n//\n\na:active,\na:hover {\n outline: 0;\n}\n\n// Text-level semantics\n// ==========================================================================\n\n//\n// Address styling not present in IE 8/9/10/11, Safari, and Chrome.\n//\n\nabbr[title] {\n border-bottom: 1px dotted;\n}\n\n//\n// Address style set to `bolder` in Firefox 4+, Safari, and Chrome.\n//\n\nb,\nstrong {\n font-weight: bold;\n}\n\n//\n// Address styling not present in Safari and Chrome.\n//\n\ndfn {\n font-style: italic;\n}\n\n//\n// Address variable `h1` font-size and margin within `section` and `article`\n// contexts in Firefox 4+, Safari, and Chrome.\n//\n\nh1 {\n font-size: 2em;\n margin: 0.67em 0;\n}\n\n//\n// Address styling not present in IE 8/9.\n//\n\nmark {\n background: #ff0;\n color: #000;\n}\n\n//\n// Address inconsistent and variable font size in all browsers.\n//\n\nsmall {\n font-size: 80%;\n}\n\n//\n// Prevent `sub` and `sup` affecting `line-height` in all browsers.\n//\n\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\n\nsup {\n top: -0.5em;\n}\n\nsub {\n bottom: -0.25em;\n}\n\n// Embedded content\n// ==========================================================================\n\n//\n// Remove border when inside `a` element in IE 8/9/10.\n//\n\nimg {\n border: 0;\n}\n\n//\n// Correct overflow not hidden in IE 9/10/11.\n//\n\nsvg:not(:root) {\n overflow: hidden;\n}\n\n// Grouping content\n// ==========================================================================\n\n//\n// Address margin not present in IE 8/9 and Safari.\n//\n\nfigure {\n margin: 1em 40px;\n}\n\n//\n// Address differences between Firefox and other browsers.\n//\n\nhr {\n box-sizing: content-box;\n height: 0;\n}\n\n//\n// Contain overflow in all browsers.\n//\n\npre {\n overflow: auto;\n}\n\n//\n// Address odd `em`-unit font size rendering in all browsers.\n//\n\ncode,\nkbd,\npre,\nsamp {\n font-family: monospace, monospace;\n font-size: 1em;\n}\n\n// Forms\n// ==========================================================================\n\n//\n// Known limitation: by default, Chrome and Safari on OS X allow very limited\n// styling of `select`, unless a `border` property is set.\n//\n\n//\n// 1. Correct color not being inherited.\n// Known issue: affects color of disabled elements.\n// 2. Correct font properties not being inherited.\n// 3. Address margins set differently in Firefox 4+, Safari, and Chrome.\n//\n\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n color: inherit; // 1\n font: inherit; // 2\n margin: 0; // 3\n}\n\n//\n// Address `overflow` set to `hidden` in IE 8/9/10/11.\n//\n\nbutton {\n overflow: visible;\n}\n\n//\n// Address inconsistent `text-transform` inheritance for `button` and `select`.\n// All other form control elements do not inherit `text-transform` values.\n// Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.\n// Correct `select` style inheritance in Firefox.\n//\n\nbutton,\nselect {\n text-transform: none;\n}\n\n//\n// 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`\n// and `video` controls.\n// 2. Correct inability to style clickable `input` types in iOS.\n// 3. Improve usability and consistency of cursor style between image-type\n// `input` and others.\n//\n\nbutton,\nhtml input[type=\"button\"], // 1\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n -webkit-appearance: button; // 2\n cursor: pointer; // 3\n}\n\n//\n// Re-set default cursor for disabled elements.\n//\n\nbutton[disabled],\nhtml input[disabled] {\n cursor: default;\n}\n\n//\n// Remove inner padding and border in Firefox 4+.\n//\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n border: 0;\n padding: 0;\n}\n\n//\n// Address Firefox 4+ setting `line-height` on `input` using `!important` in\n// the UA stylesheet.\n//\n\ninput {\n line-height: normal;\n}\n\n//\n// It's recommended that you don't attempt to style these elements.\n// Firefox's implementation doesn't respect box-sizing, padding, or width.\n//\n// 1. Address box sizing set to `content-box` in IE 8/9/10.\n// 2. Remove excess padding in IE 8/9/10.\n//\n\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n box-sizing: border-box; // 1\n padding: 0; // 2\n}\n\n//\n// Fix the cursor style for Chrome's increment/decrement buttons. For certain\n// `font-size` values of the `input`, it causes the cursor style of the\n// decrement button to change from `default` to `text`.\n//\n\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n//\n// 1. Address `appearance` set to `searchfield` in Safari and Chrome.\n// 2. Address `box-sizing` set to `border-box` in Safari and Chrome.\n//\n\ninput[type=\"search\"] {\n -webkit-appearance: textfield; // 1\n box-sizing: content-box; //2\n}\n\n//\n// Remove inner padding and search cancel button in Safari and Chrome on OS X.\n// Safari (but not Chrome) clips the cancel button when the search input has\n// padding (and `textfield` appearance).\n//\n\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n//\n// Define consistent border, margin, and padding.\n//\n\nfieldset {\n border: 1px solid #c0c0c0;\n margin: 0 2px;\n padding: 0.35em 0.625em 0.75em;\n}\n\n//\n// 1. Correct `color` not being inherited in IE 8/9/10/11.\n// 2. Remove padding so people aren't caught out if they zero out fieldsets.\n//\n\nlegend {\n border: 0; // 1\n padding: 0; // 2\n}\n\n//\n// Remove default vertical scrollbar in IE 8/9/10/11.\n//\n\ntextarea {\n overflow: auto;\n}\n\n//\n// Don't inherit the `font-weight` (applied by a rule above).\n// NOTE: the default cannot safely be changed in Chrome and Safari on OS X.\n//\n\noptgroup {\n font-weight: bold;\n}\n\n// Tables\n// ==========================================================================\n\n//\n// Remove most spacing between table cells.\n//\n\ntable {\n border-collapse: collapse;\n border-spacing: 0;\n}\n\ntd,\nth {\n padding: 0;\n}\n","/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */\n\n// ==========================================================================\n// Print styles.\n// Inlined to avoid the additional HTTP request: h5bp.com/r\n// ==========================================================================\n\n@media print {\n *,\n *:before,\n *:after {\n background: transparent !important;\n color: #000 !important; // Black prints faster: h5bp.com/s\n box-shadow: none !important;\n text-shadow: none !important;\n }\n\n a,\n a:visited {\n text-decoration: underline;\n }\n\n a[href]:after {\n content: \" (\" attr(href) \")\";\n }\n\n abbr[title]:after {\n content: \" (\" attr(title) \")\";\n }\n\n // Don't show links that are fragment identifiers,\n // or use the `javascript:` pseudo protocol\n a[href^=\"#\"]:after,\n a[href^=\"javascript:\"]:after {\n content: \"\";\n }\n\n pre,\n blockquote {\n border: 1px solid #999;\n page-break-inside: avoid;\n }\n\n thead {\n display: table-header-group; // h5bp.com/t\n }\n\n tr,\n img {\n page-break-inside: avoid;\n }\n\n img {\n max-width: 100% !important;\n }\n\n p,\n h2,\n h3 {\n orphans: 3;\n widows: 3;\n }\n\n h2,\n h3 {\n page-break-after: avoid;\n }\n\n // Bootstrap specific changes start\n\n // Bootstrap components\n .navbar {\n display: none;\n }\n .btn,\n .dropup > .btn {\n > .caret {\n border-top-color: #000 !important;\n }\n }\n .label {\n border: 1px solid #000;\n }\n\n .table {\n border-collapse: collapse !important;\n\n td,\n th {\n background-color: #fff !important;\n }\n }\n .table-bordered {\n th,\n td {\n border: 1px solid #ddd !important;\n }\n }\n\n // Bootstrap specific changes end\n}\n","/*!\n * Bootstrap v3.3.7 (http://getbootstrap.com)\n * Copyright 2011-2017 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */\nhtml {\n font-family: sans-serif;\n -ms-text-size-adjust: 100%;\n -webkit-text-size-adjust: 100%;\n}\nbody {\n margin: 0;\n}\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nmenu,\nnav,\nsection,\nsummary {\n display: block;\n}\naudio,\ncanvas,\nprogress,\nvideo {\n display: inline-block;\n vertical-align: baseline;\n}\naudio:not([controls]) {\n display: none;\n height: 0;\n}\n[hidden],\ntemplate {\n display: none;\n}\na {\n background-color: transparent;\n}\na:active,\na:hover {\n outline: 0;\n}\nabbr[title] {\n border-bottom: 1px dotted;\n}\nb,\nstrong {\n font-weight: bold;\n}\ndfn {\n font-style: italic;\n}\nh1 {\n font-size: 2em;\n margin: 0.67em 0;\n}\nmark {\n background: #ff0;\n color: #000;\n}\nsmall {\n font-size: 80%;\n}\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\nsup {\n top: -0.5em;\n}\nsub {\n bottom: -0.25em;\n}\nimg {\n border: 0;\n}\nsvg:not(:root) {\n overflow: hidden;\n}\nfigure {\n margin: 1em 40px;\n}\nhr {\n box-sizing: content-box;\n height: 0;\n}\npre {\n overflow: auto;\n}\ncode,\nkbd,\npre,\nsamp {\n font-family: monospace, monospace;\n font-size: 1em;\n}\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n color: inherit;\n font: inherit;\n margin: 0;\n}\nbutton {\n overflow: visible;\n}\nbutton,\nselect {\n text-transform: none;\n}\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n -webkit-appearance: button;\n cursor: pointer;\n}\nbutton[disabled],\nhtml input[disabled] {\n cursor: default;\n}\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n border: 0;\n padding: 0;\n}\ninput {\n line-height: normal;\n}\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n box-sizing: border-box;\n padding: 0;\n}\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\ninput[type=\"search\"] {\n -webkit-appearance: textfield;\n box-sizing: content-box;\n}\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\nfieldset {\n border: 1px solid #c0c0c0;\n margin: 0 2px;\n padding: 0.35em 0.625em 0.75em;\n}\nlegend {\n border: 0;\n padding: 0;\n}\ntextarea {\n overflow: auto;\n}\noptgroup {\n font-weight: bold;\n}\ntable {\n border-collapse: collapse;\n border-spacing: 0;\n}\ntd,\nth {\n padding: 0;\n}\n/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */\n@media print {\n *,\n *:before,\n *:after {\n background: transparent !important;\n color: #000 !important;\n box-shadow: none !important;\n text-shadow: none !important;\n }\n a,\n a:visited {\n text-decoration: underline;\n }\n a[href]:after {\n content: \" (\" attr(href) \")\";\n }\n abbr[title]:after {\n content: \" (\" attr(title) \")\";\n }\n a[href^=\"#\"]:after,\n a[href^=\"javascript:\"]:after {\n content: \"\";\n }\n pre,\n blockquote {\n border: 1px solid #999;\n page-break-inside: avoid;\n }\n thead {\n display: table-header-group;\n }\n tr,\n img {\n page-break-inside: avoid;\n }\n img {\n max-width: 100% !important;\n }\n p,\n h2,\n h3 {\n orphans: 3;\n widows: 3;\n }\n h2,\n h3 {\n page-break-after: avoid;\n }\n .navbar {\n display: none;\n }\n .btn > .caret,\n .dropup > .btn > .caret {\n border-top-color: #000 !important;\n }\n .label {\n border: 1px solid #000;\n }\n .table {\n border-collapse: collapse !important;\n }\n .table td,\n .table th {\n background-color: #fff !important;\n }\n .table-bordered th,\n .table-bordered td {\n border: 1px solid #ddd !important;\n }\n}\n@font-face {\n font-family: 'Glyphicons Halflings';\n src: url('../fonts/glyphicons-halflings-regular.eot');\n src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');\n}\n.glyphicon {\n position: relative;\n top: 1px;\n display: inline-block;\n font-family: 'Glyphicons Halflings';\n font-style: normal;\n font-weight: normal;\n line-height: 1;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n.glyphicon-asterisk:before {\n content: \"\\002a\";\n}\n.glyphicon-plus:before {\n content: \"\\002b\";\n}\n.glyphicon-euro:before,\n.glyphicon-eur:before {\n content: \"\\20ac\";\n}\n.glyphicon-minus:before {\n content: \"\\2212\";\n}\n.glyphicon-cloud:before {\n content: \"\\2601\";\n}\n.glyphicon-envelope:before {\n content: \"\\2709\";\n}\n.glyphicon-pencil:before {\n content: \"\\270f\";\n}\n.glyphicon-glass:before {\n content: \"\\e001\";\n}\n.glyphicon-music:before {\n content: \"\\e002\";\n}\n.glyphicon-search:before {\n content: \"\\e003\";\n}\n.glyphicon-heart:before {\n content: \"\\e005\";\n}\n.glyphicon-star:before {\n content: \"\\e006\";\n}\n.glyphicon-star-empty:before {\n content: \"\\e007\";\n}\n.glyphicon-user:before {\n content: \"\\e008\";\n}\n.glyphicon-film:before {\n content: \"\\e009\";\n}\n.glyphicon-th-large:before {\n content: \"\\e010\";\n}\n.glyphicon-th:before {\n content: \"\\e011\";\n}\n.glyphicon-th-list:before {\n content: \"\\e012\";\n}\n.glyphicon-ok:before {\n content: \"\\e013\";\n}\n.glyphicon-remove:before {\n content: \"\\e014\";\n}\n.glyphicon-zoom-in:before {\n content: \"\\e015\";\n}\n.glyphicon-zoom-out:before {\n content: \"\\e016\";\n}\n.glyphicon-off:before {\n content: \"\\e017\";\n}\n.glyphicon-signal:before {\n content: \"\\e018\";\n}\n.glyphicon-cog:before {\n content: \"\\e019\";\n}\n.glyphicon-trash:before {\n content: \"\\e020\";\n}\n.glyphicon-home:before {\n content: \"\\e021\";\n}\n.glyphicon-file:before {\n content: \"\\e022\";\n}\n.glyphicon-time:before {\n content: \"\\e023\";\n}\n.glyphicon-road:before {\n content: \"\\e024\";\n}\n.glyphicon-download-alt:before {\n content: \"\\e025\";\n}\n.glyphicon-download:before {\n content: \"\\e026\";\n}\n.glyphicon-upload:before {\n content: \"\\e027\";\n}\n.glyphicon-inbox:before {\n content: \"\\e028\";\n}\n.glyphicon-play-circle:before {\n content: \"\\e029\";\n}\n.glyphicon-repeat:before {\n content: \"\\e030\";\n}\n.glyphicon-refresh:before {\n content: \"\\e031\";\n}\n.glyphicon-list-alt:before {\n content: \"\\e032\";\n}\n.glyphicon-lock:before {\n content: \"\\e033\";\n}\n.glyphicon-flag:before {\n content: \"\\e034\";\n}\n.glyphicon-headphones:before {\n content: \"\\e035\";\n}\n.glyphicon-volume-off:before {\n content: \"\\e036\";\n}\n.glyphicon-volume-down:before {\n content: \"\\e037\";\n}\n.glyphicon-volume-up:before {\n content: \"\\e038\";\n}\n.glyphicon-qrcode:before {\n content: \"\\e039\";\n}\n.glyphicon-barcode:before {\n content: \"\\e040\";\n}\n.glyphicon-tag:before {\n content: \"\\e041\";\n}\n.glyphicon-tags:before {\n content: \"\\e042\";\n}\n.glyphicon-book:before {\n content: \"\\e043\";\n}\n.glyphicon-bookmark:before {\n content: \"\\e044\";\n}\n.glyphicon-print:before {\n content: \"\\e045\";\n}\n.glyphicon-camera:before {\n content: \"\\e046\";\n}\n.glyphicon-font:before {\n content: \"\\e047\";\n}\n.glyphicon-bold:before {\n content: \"\\e048\";\n}\n.glyphicon-italic:before {\n content: \"\\e049\";\n}\n.glyphicon-text-height:before {\n content: \"\\e050\";\n}\n.glyphicon-text-width:before {\n content: \"\\e051\";\n}\n.glyphicon-align-left:before {\n content: \"\\e052\";\n}\n.glyphicon-align-center:before {\n content: \"\\e053\";\n}\n.glyphicon-align-right:before {\n content: \"\\e054\";\n}\n.glyphicon-align-justify:before {\n content: \"\\e055\";\n}\n.glyphicon-list:before {\n content: \"\\e056\";\n}\n.glyphicon-indent-left:before {\n content: \"\\e057\";\n}\n.glyphicon-indent-right:before {\n content: \"\\e058\";\n}\n.glyphicon-facetime-video:before {\n content: \"\\e059\";\n}\n.glyphicon-picture:before {\n content: \"\\e060\";\n}\n.glyphicon-map-marker:before {\n content: \"\\e062\";\n}\n.glyphicon-adjust:before {\n content: \"\\e063\";\n}\n.glyphicon-tint:before {\n content: \"\\e064\";\n}\n.glyphicon-edit:before {\n content: \"\\e065\";\n}\n.glyphicon-share:before {\n content: \"\\e066\";\n}\n.glyphicon-check:before {\n content: \"\\e067\";\n}\n.glyphicon-move:before {\n content: \"\\e068\";\n}\n.glyphicon-step-backward:before {\n content: \"\\e069\";\n}\n.glyphicon-fast-backward:before {\n content: \"\\e070\";\n}\n.glyphicon-backward:before {\n content: \"\\e071\";\n}\n.glyphicon-play:before {\n content: \"\\e072\";\n}\n.glyphicon-pause:before {\n content: \"\\e073\";\n}\n.glyphicon-stop:before {\n content: \"\\e074\";\n}\n.glyphicon-forward:before {\n content: \"\\e075\";\n}\n.glyphicon-fast-forward:before {\n content: \"\\e076\";\n}\n.glyphicon-step-forward:before {\n content: \"\\e077\";\n}\n.glyphicon-eject:before {\n content: \"\\e078\";\n}\n.glyphicon-chevron-left:before {\n content: \"\\e079\";\n}\n.glyphicon-chevron-right:before {\n content: \"\\e080\";\n}\n.glyphicon-plus-sign:before {\n content: \"\\e081\";\n}\n.glyphicon-minus-sign:before {\n content: \"\\e082\";\n}\n.glyphicon-remove-sign:before {\n content: \"\\e083\";\n}\n.glyphicon-ok-sign:before {\n content: \"\\e084\";\n}\n.glyphicon-question-sign:before {\n content: \"\\e085\";\n}\n.glyphicon-info-sign:before {\n content: \"\\e086\";\n}\n.glyphicon-screenshot:before {\n content: \"\\e087\";\n}\n.glyphicon-remove-circle:before {\n content: \"\\e088\";\n}\n.glyphicon-ok-circle:before {\n content: \"\\e089\";\n}\n.glyphicon-ban-circle:before {\n content: \"\\e090\";\n}\n.glyphicon-arrow-left:before {\n content: \"\\e091\";\n}\n.glyphicon-arrow-right:before {\n content: \"\\e092\";\n}\n.glyphicon-arrow-up:before {\n content: \"\\e093\";\n}\n.glyphicon-arrow-down:before {\n content: \"\\e094\";\n}\n.glyphicon-share-alt:before {\n content: \"\\e095\";\n}\n.glyphicon-resize-full:before {\n content: \"\\e096\";\n}\n.glyphicon-resize-small:before {\n content: \"\\e097\";\n}\n.glyphicon-exclamation-sign:before {\n content: \"\\e101\";\n}\n.glyphicon-gift:before {\n content: \"\\e102\";\n}\n.glyphicon-leaf:before {\n content: \"\\e103\";\n}\n.glyphicon-fire:before {\n content: \"\\e104\";\n}\n.glyphicon-eye-open:before {\n content: \"\\e105\";\n}\n.glyphicon-eye-close:before {\n content: \"\\e106\";\n}\n.glyphicon-warning-sign:before {\n content: \"\\e107\";\n}\n.glyphicon-plane:before {\n content: \"\\e108\";\n}\n.glyphicon-calendar:before {\n content: \"\\e109\";\n}\n.glyphicon-random:before {\n content: \"\\e110\";\n}\n.glyphicon-comment:before {\n content: \"\\e111\";\n}\n.glyphicon-magnet:before {\n content: \"\\e112\";\n}\n.glyphicon-chevron-up:before {\n content: \"\\e113\";\n}\n.glyphicon-chevron-down:before {\n content: \"\\e114\";\n}\n.glyphicon-retweet:before {\n content: \"\\e115\";\n}\n.glyphicon-shopping-cart:before {\n content: \"\\e116\";\n}\n.glyphicon-folder-close:before {\n content: \"\\e117\";\n}\n.glyphicon-folder-open:before {\n content: \"\\e118\";\n}\n.glyphicon-resize-vertical:before {\n content: \"\\e119\";\n}\n.glyphicon-resize-horizontal:before {\n content: \"\\e120\";\n}\n.glyphicon-hdd:before {\n content: \"\\e121\";\n}\n.glyphicon-bullhorn:before {\n content: \"\\e122\";\n}\n.glyphicon-bell:before {\n content: \"\\e123\";\n}\n.glyphicon-certificate:before {\n content: \"\\e124\";\n}\n.glyphicon-thumbs-up:before {\n content: \"\\e125\";\n}\n.glyphicon-thumbs-down:before {\n content: \"\\e126\";\n}\n.glyphicon-hand-right:before {\n content: \"\\e127\";\n}\n.glyphicon-hand-left:before {\n content: \"\\e128\";\n}\n.glyphicon-hand-up:before {\n content: \"\\e129\";\n}\n.glyphicon-hand-down:before {\n content: \"\\e130\";\n}\n.glyphicon-circle-arrow-right:before {\n content: \"\\e131\";\n}\n.glyphicon-circle-arrow-left:before {\n content: \"\\e132\";\n}\n.glyphicon-circle-arrow-up:before {\n content: \"\\e133\";\n}\n.glyphicon-circle-arrow-down:before {\n content: \"\\e134\";\n}\n.glyphicon-globe:before {\n content: \"\\e135\";\n}\n.glyphicon-wrench:before {\n content: \"\\e136\";\n}\n.glyphicon-tasks:before {\n content: \"\\e137\";\n}\n.glyphicon-filter:before {\n content: \"\\e138\";\n}\n.glyphicon-briefcase:before {\n content: \"\\e139\";\n}\n.glyphicon-fullscreen:before {\n content: \"\\e140\";\n}\n.glyphicon-dashboard:before {\n content: \"\\e141\";\n}\n.glyphicon-paperclip:before {\n content: \"\\e142\";\n}\n.glyphicon-heart-empty:before {\n content: \"\\e143\";\n}\n.glyphicon-link:before {\n content: \"\\e144\";\n}\n.glyphicon-phone:before {\n content: \"\\e145\";\n}\n.glyphicon-pushpin:before {\n content: \"\\e146\";\n}\n.glyphicon-usd:before {\n content: \"\\e148\";\n}\n.glyphicon-gbp:before {\n content: \"\\e149\";\n}\n.glyphicon-sort:before {\n content: \"\\e150\";\n}\n.glyphicon-sort-by-alphabet:before {\n content: \"\\e151\";\n}\n.glyphicon-sort-by-alphabet-alt:before {\n content: \"\\e152\";\n}\n.glyphicon-sort-by-order:before {\n content: \"\\e153\";\n}\n.glyphicon-sort-by-order-alt:before {\n content: \"\\e154\";\n}\n.glyphicon-sort-by-attributes:before {\n content: \"\\e155\";\n}\n.glyphicon-sort-by-attributes-alt:before {\n content: \"\\e156\";\n}\n.glyphicon-unchecked:before {\n content: \"\\e157\";\n}\n.glyphicon-expand:before {\n content: \"\\e158\";\n}\n.glyphicon-collapse-down:before {\n content: \"\\e159\";\n}\n.glyphicon-collapse-up:before {\n content: \"\\e160\";\n}\n.glyphicon-log-in:before {\n content: \"\\e161\";\n}\n.glyphicon-flash:before {\n content: \"\\e162\";\n}\n.glyphicon-log-out:before {\n content: \"\\e163\";\n}\n.glyphicon-new-window:before {\n content: \"\\e164\";\n}\n.glyphicon-record:before {\n content: \"\\e165\";\n}\n.glyphicon-save:before {\n content: \"\\e166\";\n}\n.glyphicon-open:before {\n content: \"\\e167\";\n}\n.glyphicon-saved:before {\n content: \"\\e168\";\n}\n.glyphicon-import:before {\n content: \"\\e169\";\n}\n.glyphicon-export:before {\n content: \"\\e170\";\n}\n.glyphicon-send:before {\n content: \"\\e171\";\n}\n.glyphicon-floppy-disk:before {\n content: \"\\e172\";\n}\n.glyphicon-floppy-saved:before {\n content: \"\\e173\";\n}\n.glyphicon-floppy-remove:before {\n content: \"\\e174\";\n}\n.glyphicon-floppy-save:before {\n content: \"\\e175\";\n}\n.glyphicon-floppy-open:before {\n content: \"\\e176\";\n}\n.glyphicon-credit-card:before {\n content: \"\\e177\";\n}\n.glyphicon-transfer:before {\n content: \"\\e178\";\n}\n.glyphicon-cutlery:before {\n content: \"\\e179\";\n}\n.glyphicon-header:before {\n content: \"\\e180\";\n}\n.glyphicon-compressed:before {\n content: \"\\e181\";\n}\n.glyphicon-earphone:before {\n content: \"\\e182\";\n}\n.glyphicon-phone-alt:before {\n content: \"\\e183\";\n}\n.glyphicon-tower:before {\n content: \"\\e184\";\n}\n.glyphicon-stats:before {\n content: \"\\e185\";\n}\n.glyphicon-sd-video:before {\n content: \"\\e186\";\n}\n.glyphicon-hd-video:before {\n content: \"\\e187\";\n}\n.glyphicon-subtitles:before {\n content: \"\\e188\";\n}\n.glyphicon-sound-stereo:before {\n content: \"\\e189\";\n}\n.glyphicon-sound-dolby:before {\n content: \"\\e190\";\n}\n.glyphicon-sound-5-1:before {\n content: \"\\e191\";\n}\n.glyphicon-sound-6-1:before {\n content: \"\\e192\";\n}\n.glyphicon-sound-7-1:before {\n content: \"\\e193\";\n}\n.glyphicon-copyright-mark:before {\n content: \"\\e194\";\n}\n.glyphicon-registration-mark:before {\n content: \"\\e195\";\n}\n.glyphicon-cloud-download:before {\n content: \"\\e197\";\n}\n.glyphicon-cloud-upload:before {\n content: \"\\e198\";\n}\n.glyphicon-tree-conifer:before {\n content: \"\\e199\";\n}\n.glyphicon-tree-deciduous:before {\n content: \"\\e200\";\n}\n.glyphicon-cd:before {\n content: \"\\e201\";\n}\n.glyphicon-save-file:before {\n content: \"\\e202\";\n}\n.glyphicon-open-file:before {\n content: \"\\e203\";\n}\n.glyphicon-level-up:before {\n content: \"\\e204\";\n}\n.glyphicon-copy:before {\n content: \"\\e205\";\n}\n.glyphicon-paste:before {\n content: \"\\e206\";\n}\n.glyphicon-alert:before {\n content: \"\\e209\";\n}\n.glyphicon-equalizer:before {\n content: \"\\e210\";\n}\n.glyphicon-king:before {\n content: \"\\e211\";\n}\n.glyphicon-queen:before {\n content: \"\\e212\";\n}\n.glyphicon-pawn:before {\n content: \"\\e213\";\n}\n.glyphicon-bishop:before {\n content: \"\\e214\";\n}\n.glyphicon-knight:before {\n content: \"\\e215\";\n}\n.glyphicon-baby-formula:before {\n content: \"\\e216\";\n}\n.glyphicon-tent:before {\n content: \"\\26fa\";\n}\n.glyphicon-blackboard:before {\n content: \"\\e218\";\n}\n.glyphicon-bed:before {\n content: \"\\e219\";\n}\n.glyphicon-apple:before {\n content: \"\\f8ff\";\n}\n.glyphicon-erase:before {\n content: \"\\e221\";\n}\n.glyphicon-hourglass:before {\n content: \"\\231b\";\n}\n.glyphicon-lamp:before {\n content: \"\\e223\";\n}\n.glyphicon-duplicate:before {\n content: \"\\e224\";\n}\n.glyphicon-piggy-bank:before {\n content: \"\\e225\";\n}\n.glyphicon-scissors:before {\n content: \"\\e226\";\n}\n.glyphicon-bitcoin:before {\n content: \"\\e227\";\n}\n.glyphicon-btc:before {\n content: \"\\e227\";\n}\n.glyphicon-xbt:before {\n content: \"\\e227\";\n}\n.glyphicon-yen:before {\n content: \"\\00a5\";\n}\n.glyphicon-jpy:before {\n content: \"\\00a5\";\n}\n.glyphicon-ruble:before {\n content: \"\\20bd\";\n}\n.glyphicon-rub:before {\n content: \"\\20bd\";\n}\n.glyphicon-scale:before {\n content: \"\\e230\";\n}\n.glyphicon-ice-lolly:before {\n content: \"\\e231\";\n}\n.glyphicon-ice-lolly-tasted:before {\n content: \"\\e232\";\n}\n.glyphicon-education:before {\n content: \"\\e233\";\n}\n.glyphicon-option-horizontal:before {\n content: \"\\e234\";\n}\n.glyphicon-option-vertical:before {\n content: \"\\e235\";\n}\n.glyphicon-menu-hamburger:before {\n content: \"\\e236\";\n}\n.glyphicon-modal-window:before {\n content: \"\\e237\";\n}\n.glyphicon-oil:before {\n content: \"\\e238\";\n}\n.glyphicon-grain:before {\n content: \"\\e239\";\n}\n.glyphicon-sunglasses:before {\n content: \"\\e240\";\n}\n.glyphicon-text-size:before {\n content: \"\\e241\";\n}\n.glyphicon-text-color:before {\n content: \"\\e242\";\n}\n.glyphicon-text-background:before {\n content: \"\\e243\";\n}\n.glyphicon-object-align-top:before {\n content: \"\\e244\";\n}\n.glyphicon-object-align-bottom:before {\n content: \"\\e245\";\n}\n.glyphicon-object-align-horizontal:before {\n content: \"\\e246\";\n}\n.glyphicon-object-align-left:before {\n content: \"\\e247\";\n}\n.glyphicon-object-align-vertical:before {\n content: \"\\e248\";\n}\n.glyphicon-object-align-right:before {\n content: \"\\e249\";\n}\n.glyphicon-triangle-right:before {\n content: \"\\e250\";\n}\n.glyphicon-triangle-left:before {\n content: \"\\e251\";\n}\n.glyphicon-triangle-bottom:before {\n content: \"\\e252\";\n}\n.glyphicon-triangle-top:before {\n content: \"\\e253\";\n}\n.glyphicon-console:before {\n content: \"\\e254\";\n}\n.glyphicon-superscript:before {\n content: \"\\e255\";\n}\n.glyphicon-subscript:before {\n content: \"\\e256\";\n}\n.glyphicon-menu-left:before {\n content: \"\\e257\";\n}\n.glyphicon-menu-right:before {\n content: \"\\e258\";\n}\n.glyphicon-menu-down:before {\n content: \"\\e259\";\n}\n.glyphicon-menu-up:before {\n content: \"\\e260\";\n}\n* {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\n*:before,\n*:after {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\nhtml {\n font-size: 10px;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\nbody {\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-size: 14px;\n line-height: 1.42857143;\n color: #333333;\n background-color: #fff;\n}\ninput,\nbutton,\nselect,\ntextarea {\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\na {\n color: #337ab7;\n text-decoration: none;\n}\na:hover,\na:focus {\n color: #23527c;\n text-decoration: underline;\n}\na:focus {\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\nfigure {\n margin: 0;\n}\nimg {\n vertical-align: middle;\n}\n.img-responsive,\n.thumbnail > img,\n.thumbnail a > img,\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n display: block;\n max-width: 100%;\n height: auto;\n}\n.img-rounded {\n border-radius: 6px;\n}\n.img-thumbnail {\n padding: 4px;\n line-height: 1.42857143;\n background-color: #fff;\n border: 1px solid #ddd;\n border-radius: 4px;\n -webkit-transition: all 0.2s ease-in-out;\n -o-transition: all 0.2s ease-in-out;\n transition: all 0.2s ease-in-out;\n display: inline-block;\n max-width: 100%;\n height: auto;\n}\n.img-circle {\n border-radius: 50%;\n}\nhr {\n margin-top: 20px;\n margin-bottom: 20px;\n border: 0;\n border-top: 1px solid #eeeeee;\n}\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n border: 0;\n}\n.sr-only-focusable:active,\n.sr-only-focusable:focus {\n position: static;\n width: auto;\n height: auto;\n margin: 0;\n overflow: visible;\n clip: auto;\n}\n[role=\"button\"] {\n cursor: pointer;\n}\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\n.h1,\n.h2,\n.h3,\n.h4,\n.h5,\n.h6 {\n font-family: inherit;\n font-weight: 500;\n line-height: 1.1;\n color: inherit;\n}\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small,\n.h1 small,\n.h2 small,\n.h3 small,\n.h4 small,\n.h5 small,\n.h6 small,\nh1 .small,\nh2 .small,\nh3 .small,\nh4 .small,\nh5 .small,\nh6 .small,\n.h1 .small,\n.h2 .small,\n.h3 .small,\n.h4 .small,\n.h5 .small,\n.h6 .small {\n font-weight: normal;\n line-height: 1;\n color: #777777;\n}\nh1,\n.h1,\nh2,\n.h2,\nh3,\n.h3 {\n margin-top: 20px;\n margin-bottom: 10px;\n}\nh1 small,\n.h1 small,\nh2 small,\n.h2 small,\nh3 small,\n.h3 small,\nh1 .small,\n.h1 .small,\nh2 .small,\n.h2 .small,\nh3 .small,\n.h3 .small {\n font-size: 65%;\n}\nh4,\n.h4,\nh5,\n.h5,\nh6,\n.h6 {\n margin-top: 10px;\n margin-bottom: 10px;\n}\nh4 small,\n.h4 small,\nh5 small,\n.h5 small,\nh6 small,\n.h6 small,\nh4 .small,\n.h4 .small,\nh5 .small,\n.h5 .small,\nh6 .small,\n.h6 .small {\n font-size: 75%;\n}\nh1,\n.h1 {\n font-size: 36px;\n}\nh2,\n.h2 {\n font-size: 30px;\n}\nh3,\n.h3 {\n font-size: 24px;\n}\nh4,\n.h4 {\n font-size: 18px;\n}\nh5,\n.h5 {\n font-size: 14px;\n}\nh6,\n.h6 {\n font-size: 12px;\n}\np {\n margin: 0 0 10px;\n}\n.lead {\n margin-bottom: 20px;\n font-size: 16px;\n font-weight: 300;\n line-height: 1.4;\n}\n@media (min-width: 768px) {\n .lead {\n font-size: 21px;\n }\n}\nsmall,\n.small {\n font-size: 85%;\n}\nmark,\n.mark {\n background-color: #fcf8e3;\n padding: .2em;\n}\n.text-left {\n text-align: left;\n}\n.text-right {\n text-align: right;\n}\n.text-center {\n text-align: center;\n}\n.text-justify {\n text-align: justify;\n}\n.text-nowrap {\n white-space: nowrap;\n}\n.text-lowercase {\n text-transform: lowercase;\n}\n.text-uppercase {\n text-transform: uppercase;\n}\n.text-capitalize {\n text-transform: capitalize;\n}\n.text-muted {\n color: #777777;\n}\n.text-primary {\n color: #337ab7;\n}\na.text-primary:hover,\na.text-primary:focus {\n color: #286090;\n}\n.text-success {\n color: #3c763d;\n}\na.text-success:hover,\na.text-success:focus {\n color: #2b542c;\n}\n.text-info {\n color: #31708f;\n}\na.text-info:hover,\na.text-info:focus {\n color: #245269;\n}\n.text-warning {\n color: #8a6d3b;\n}\na.text-warning:hover,\na.text-warning:focus {\n color: #66512c;\n}\n.text-danger {\n color: #a94442;\n}\na.text-danger:hover,\na.text-danger:focus {\n color: #843534;\n}\n.bg-primary {\n color: #fff;\n background-color: #337ab7;\n}\na.bg-primary:hover,\na.bg-primary:focus {\n background-color: #286090;\n}\n.bg-success {\n background-color: #dff0d8;\n}\na.bg-success:hover,\na.bg-success:focus {\n background-color: #c1e2b3;\n}\n.bg-info {\n background-color: #d9edf7;\n}\na.bg-info:hover,\na.bg-info:focus {\n background-color: #afd9ee;\n}\n.bg-warning {\n background-color: #fcf8e3;\n}\na.bg-warning:hover,\na.bg-warning:focus {\n background-color: #f7ecb5;\n}\n.bg-danger {\n background-color: #f2dede;\n}\na.bg-danger:hover,\na.bg-danger:focus {\n background-color: #e4b9b9;\n}\n.page-header {\n padding-bottom: 9px;\n margin: 40px 0 20px;\n border-bottom: 1px solid #eeeeee;\n}\nul,\nol {\n margin-top: 0;\n margin-bottom: 10px;\n}\nul ul,\nol ul,\nul ol,\nol ol {\n margin-bottom: 0;\n}\n.list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n.list-inline {\n padding-left: 0;\n list-style: none;\n margin-left: -5px;\n}\n.list-inline > li {\n display: inline-block;\n padding-left: 5px;\n padding-right: 5px;\n}\ndl {\n margin-top: 0;\n margin-bottom: 20px;\n}\ndt,\ndd {\n line-height: 1.42857143;\n}\ndt {\n font-weight: bold;\n}\ndd {\n margin-left: 0;\n}\n@media (min-width: 768px) {\n .dl-horizontal dt {\n float: left;\n width: 160px;\n clear: left;\n text-align: right;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .dl-horizontal dd {\n margin-left: 180px;\n }\n}\nabbr[title],\nabbr[data-original-title] {\n cursor: help;\n border-bottom: 1px dotted #777777;\n}\n.initialism {\n font-size: 90%;\n text-transform: uppercase;\n}\nblockquote {\n padding: 10px 20px;\n margin: 0 0 20px;\n font-size: 17.5px;\n border-left: 5px solid #eeeeee;\n}\nblockquote p:last-child,\nblockquote ul:last-child,\nblockquote ol:last-child {\n margin-bottom: 0;\n}\nblockquote footer,\nblockquote small,\nblockquote .small {\n display: block;\n font-size: 80%;\n line-height: 1.42857143;\n color: #777777;\n}\nblockquote footer:before,\nblockquote small:before,\nblockquote .small:before {\n content: '\\2014 \\00A0';\n}\n.blockquote-reverse,\nblockquote.pull-right {\n padding-right: 15px;\n padding-left: 0;\n border-right: 5px solid #eeeeee;\n border-left: 0;\n text-align: right;\n}\n.blockquote-reverse footer:before,\nblockquote.pull-right footer:before,\n.blockquote-reverse small:before,\nblockquote.pull-right small:before,\n.blockquote-reverse .small:before,\nblockquote.pull-right .small:before {\n content: '';\n}\n.blockquote-reverse footer:after,\nblockquote.pull-right footer:after,\n.blockquote-reverse small:after,\nblockquote.pull-right small:after,\n.blockquote-reverse .small:after,\nblockquote.pull-right .small:after {\n content: '\\00A0 \\2014';\n}\naddress {\n margin-bottom: 20px;\n font-style: normal;\n line-height: 1.42857143;\n}\ncode,\nkbd,\npre,\nsamp {\n font-family: Menlo, Monaco, Consolas, \"Courier New\", monospace;\n}\ncode {\n padding: 2px 4px;\n font-size: 90%;\n color: #c7254e;\n background-color: #f9f2f4;\n border-radius: 4px;\n}\nkbd {\n padding: 2px 4px;\n font-size: 90%;\n color: #fff;\n background-color: #333;\n border-radius: 3px;\n box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\nkbd kbd {\n padding: 0;\n font-size: 100%;\n font-weight: bold;\n box-shadow: none;\n}\npre {\n display: block;\n padding: 9.5px;\n margin: 0 0 10px;\n font-size: 13px;\n line-height: 1.42857143;\n word-break: break-all;\n word-wrap: break-word;\n color: #333333;\n background-color: #f5f5f5;\n border: 1px solid #ccc;\n border-radius: 4px;\n}\npre code {\n padding: 0;\n font-size: inherit;\n color: inherit;\n white-space: pre-wrap;\n background-color: transparent;\n border-radius: 0;\n}\n.pre-scrollable {\n max-height: 340px;\n overflow-y: scroll;\n}\n.container {\n margin-right: auto;\n margin-left: auto;\n padding-left: 15px;\n padding-right: 15px;\n}\n@media (min-width: 768px) {\n .container {\n width: 750px;\n }\n}\n@media (min-width: 992px) {\n .container {\n width: 970px;\n }\n}\n@media (min-width: 1200px) {\n .container {\n width: 1170px;\n }\n}\n.container-fluid {\n margin-right: auto;\n margin-left: auto;\n padding-left: 15px;\n padding-right: 15px;\n}\n.row {\n margin-left: -15px;\n margin-right: -15px;\n}\n.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 {\n position: relative;\n min-height: 1px;\n padding-left: 15px;\n padding-right: 15px;\n}\n.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 {\n float: left;\n}\n.col-xs-12 {\n width: 100%;\n}\n.col-xs-11 {\n width: 91.66666667%;\n}\n.col-xs-10 {\n width: 83.33333333%;\n}\n.col-xs-9 {\n width: 75%;\n}\n.col-xs-8 {\n width: 66.66666667%;\n}\n.col-xs-7 {\n width: 58.33333333%;\n}\n.col-xs-6 {\n width: 50%;\n}\n.col-xs-5 {\n width: 41.66666667%;\n}\n.col-xs-4 {\n width: 33.33333333%;\n}\n.col-xs-3 {\n width: 25%;\n}\n.col-xs-2 {\n width: 16.66666667%;\n}\n.col-xs-1 {\n width: 8.33333333%;\n}\n.col-xs-pull-12 {\n right: 100%;\n}\n.col-xs-pull-11 {\n right: 91.66666667%;\n}\n.col-xs-pull-10 {\n right: 83.33333333%;\n}\n.col-xs-pull-9 {\n right: 75%;\n}\n.col-xs-pull-8 {\n right: 66.66666667%;\n}\n.col-xs-pull-7 {\n right: 58.33333333%;\n}\n.col-xs-pull-6 {\n right: 50%;\n}\n.col-xs-pull-5 {\n right: 41.66666667%;\n}\n.col-xs-pull-4 {\n right: 33.33333333%;\n}\n.col-xs-pull-3 {\n right: 25%;\n}\n.col-xs-pull-2 {\n right: 16.66666667%;\n}\n.col-xs-pull-1 {\n right: 8.33333333%;\n}\n.col-xs-pull-0 {\n right: auto;\n}\n.col-xs-push-12 {\n left: 100%;\n}\n.col-xs-push-11 {\n left: 91.66666667%;\n}\n.col-xs-push-10 {\n left: 83.33333333%;\n}\n.col-xs-push-9 {\n left: 75%;\n}\n.col-xs-push-8 {\n left: 66.66666667%;\n}\n.col-xs-push-7 {\n left: 58.33333333%;\n}\n.col-xs-push-6 {\n left: 50%;\n}\n.col-xs-push-5 {\n left: 41.66666667%;\n}\n.col-xs-push-4 {\n left: 33.33333333%;\n}\n.col-xs-push-3 {\n left: 25%;\n}\n.col-xs-push-2 {\n left: 16.66666667%;\n}\n.col-xs-push-1 {\n left: 8.33333333%;\n}\n.col-xs-push-0 {\n left: auto;\n}\n.col-xs-offset-12 {\n margin-left: 100%;\n}\n.col-xs-offset-11 {\n margin-left: 91.66666667%;\n}\n.col-xs-offset-10 {\n margin-left: 83.33333333%;\n}\n.col-xs-offset-9 {\n margin-left: 75%;\n}\n.col-xs-offset-8 {\n margin-left: 66.66666667%;\n}\n.col-xs-offset-7 {\n margin-left: 58.33333333%;\n}\n.col-xs-offset-6 {\n margin-left: 50%;\n}\n.col-xs-offset-5 {\n margin-left: 41.66666667%;\n}\n.col-xs-offset-4 {\n margin-left: 33.33333333%;\n}\n.col-xs-offset-3 {\n margin-left: 25%;\n}\n.col-xs-offset-2 {\n margin-left: 16.66666667%;\n}\n.col-xs-offset-1 {\n margin-left: 8.33333333%;\n}\n.col-xs-offset-0 {\n margin-left: 0%;\n}\n@media (min-width: 768px) {\n .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 {\n float: left;\n }\n .col-sm-12 {\n width: 100%;\n }\n .col-sm-11 {\n width: 91.66666667%;\n }\n .col-sm-10 {\n width: 83.33333333%;\n }\n .col-sm-9 {\n width: 75%;\n }\n .col-sm-8 {\n width: 66.66666667%;\n }\n .col-sm-7 {\n width: 58.33333333%;\n }\n .col-sm-6 {\n width: 50%;\n }\n .col-sm-5 {\n width: 41.66666667%;\n }\n .col-sm-4 {\n width: 33.33333333%;\n }\n .col-sm-3 {\n width: 25%;\n }\n .col-sm-2 {\n width: 16.66666667%;\n }\n .col-sm-1 {\n width: 8.33333333%;\n }\n .col-sm-pull-12 {\n right: 100%;\n }\n .col-sm-pull-11 {\n right: 91.66666667%;\n }\n .col-sm-pull-10 {\n right: 83.33333333%;\n }\n .col-sm-pull-9 {\n right: 75%;\n }\n .col-sm-pull-8 {\n right: 66.66666667%;\n }\n .col-sm-pull-7 {\n right: 58.33333333%;\n }\n .col-sm-pull-6 {\n right: 50%;\n }\n .col-sm-pull-5 {\n right: 41.66666667%;\n }\n .col-sm-pull-4 {\n right: 33.33333333%;\n }\n .col-sm-pull-3 {\n right: 25%;\n }\n .col-sm-pull-2 {\n right: 16.66666667%;\n }\n .col-sm-pull-1 {\n right: 8.33333333%;\n }\n .col-sm-pull-0 {\n right: auto;\n }\n .col-sm-push-12 {\n left: 100%;\n }\n .col-sm-push-11 {\n left: 91.66666667%;\n }\n .col-sm-push-10 {\n left: 83.33333333%;\n }\n .col-sm-push-9 {\n left: 75%;\n }\n .col-sm-push-8 {\n left: 66.66666667%;\n }\n .col-sm-push-7 {\n left: 58.33333333%;\n }\n .col-sm-push-6 {\n left: 50%;\n }\n .col-sm-push-5 {\n left: 41.66666667%;\n }\n .col-sm-push-4 {\n left: 33.33333333%;\n }\n .col-sm-push-3 {\n left: 25%;\n }\n .col-sm-push-2 {\n left: 16.66666667%;\n }\n .col-sm-push-1 {\n left: 8.33333333%;\n }\n .col-sm-push-0 {\n left: auto;\n }\n .col-sm-offset-12 {\n margin-left: 100%;\n }\n .col-sm-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-sm-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-sm-offset-9 {\n margin-left: 75%;\n }\n .col-sm-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-sm-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-sm-offset-6 {\n margin-left: 50%;\n }\n .col-sm-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-sm-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-sm-offset-3 {\n margin-left: 25%;\n }\n .col-sm-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-sm-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-sm-offset-0 {\n margin-left: 0%;\n }\n}\n@media (min-width: 992px) {\n .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 {\n float: left;\n }\n .col-md-12 {\n width: 100%;\n }\n .col-md-11 {\n width: 91.66666667%;\n }\n .col-md-10 {\n width: 83.33333333%;\n }\n .col-md-9 {\n width: 75%;\n }\n .col-md-8 {\n width: 66.66666667%;\n }\n .col-md-7 {\n width: 58.33333333%;\n }\n .col-md-6 {\n width: 50%;\n }\n .col-md-5 {\n width: 41.66666667%;\n }\n .col-md-4 {\n width: 33.33333333%;\n }\n .col-md-3 {\n width: 25%;\n }\n .col-md-2 {\n width: 16.66666667%;\n }\n .col-md-1 {\n width: 8.33333333%;\n }\n .col-md-pull-12 {\n right: 100%;\n }\n .col-md-pull-11 {\n right: 91.66666667%;\n }\n .col-md-pull-10 {\n right: 83.33333333%;\n }\n .col-md-pull-9 {\n right: 75%;\n }\n .col-md-pull-8 {\n right: 66.66666667%;\n }\n .col-md-pull-7 {\n right: 58.33333333%;\n }\n .col-md-pull-6 {\n right: 50%;\n }\n .col-md-pull-5 {\n right: 41.66666667%;\n }\n .col-md-pull-4 {\n right: 33.33333333%;\n }\n .col-md-pull-3 {\n right: 25%;\n }\n .col-md-pull-2 {\n right: 16.66666667%;\n }\n .col-md-pull-1 {\n right: 8.33333333%;\n }\n .col-md-pull-0 {\n right: auto;\n }\n .col-md-push-12 {\n left: 100%;\n }\n .col-md-push-11 {\n left: 91.66666667%;\n }\n .col-md-push-10 {\n left: 83.33333333%;\n }\n .col-md-push-9 {\n left: 75%;\n }\n .col-md-push-8 {\n left: 66.66666667%;\n }\n .col-md-push-7 {\n left: 58.33333333%;\n }\n .col-md-push-6 {\n left: 50%;\n }\n .col-md-push-5 {\n left: 41.66666667%;\n }\n .col-md-push-4 {\n left: 33.33333333%;\n }\n .col-md-push-3 {\n left: 25%;\n }\n .col-md-push-2 {\n left: 16.66666667%;\n }\n .col-md-push-1 {\n left: 8.33333333%;\n }\n .col-md-push-0 {\n left: auto;\n }\n .col-md-offset-12 {\n margin-left: 100%;\n }\n .col-md-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-md-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-md-offset-9 {\n margin-left: 75%;\n }\n .col-md-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-md-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-md-offset-6 {\n margin-left: 50%;\n }\n .col-md-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-md-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-md-offset-3 {\n margin-left: 25%;\n }\n .col-md-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-md-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-md-offset-0 {\n margin-left: 0%;\n }\n}\n@media (min-width: 1200px) {\n .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 {\n float: left;\n }\n .col-lg-12 {\n width: 100%;\n }\n .col-lg-11 {\n width: 91.66666667%;\n }\n .col-lg-10 {\n width: 83.33333333%;\n }\n .col-lg-9 {\n width: 75%;\n }\n .col-lg-8 {\n width: 66.66666667%;\n }\n .col-lg-7 {\n width: 58.33333333%;\n }\n .col-lg-6 {\n width: 50%;\n }\n .col-lg-5 {\n width: 41.66666667%;\n }\n .col-lg-4 {\n width: 33.33333333%;\n }\n .col-lg-3 {\n width: 25%;\n }\n .col-lg-2 {\n width: 16.66666667%;\n }\n .col-lg-1 {\n width: 8.33333333%;\n }\n .col-lg-pull-12 {\n right: 100%;\n }\n .col-lg-pull-11 {\n right: 91.66666667%;\n }\n .col-lg-pull-10 {\n right: 83.33333333%;\n }\n .col-lg-pull-9 {\n right: 75%;\n }\n .col-lg-pull-8 {\n right: 66.66666667%;\n }\n .col-lg-pull-7 {\n right: 58.33333333%;\n }\n .col-lg-pull-6 {\n right: 50%;\n }\n .col-lg-pull-5 {\n right: 41.66666667%;\n }\n .col-lg-pull-4 {\n right: 33.33333333%;\n }\n .col-lg-pull-3 {\n right: 25%;\n }\n .col-lg-pull-2 {\n right: 16.66666667%;\n }\n .col-lg-pull-1 {\n right: 8.33333333%;\n }\n .col-lg-pull-0 {\n right: auto;\n }\n .col-lg-push-12 {\n left: 100%;\n }\n .col-lg-push-11 {\n left: 91.66666667%;\n }\n .col-lg-push-10 {\n left: 83.33333333%;\n }\n .col-lg-push-9 {\n left: 75%;\n }\n .col-lg-push-8 {\n left: 66.66666667%;\n }\n .col-lg-push-7 {\n left: 58.33333333%;\n }\n .col-lg-push-6 {\n left: 50%;\n }\n .col-lg-push-5 {\n left: 41.66666667%;\n }\n .col-lg-push-4 {\n left: 33.33333333%;\n }\n .col-lg-push-3 {\n left: 25%;\n }\n .col-lg-push-2 {\n left: 16.66666667%;\n }\n .col-lg-push-1 {\n left: 8.33333333%;\n }\n .col-lg-push-0 {\n left: auto;\n }\n .col-lg-offset-12 {\n margin-left: 100%;\n }\n .col-lg-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-lg-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-lg-offset-9 {\n margin-left: 75%;\n }\n .col-lg-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-lg-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-lg-offset-6 {\n margin-left: 50%;\n }\n .col-lg-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-lg-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-lg-offset-3 {\n margin-left: 25%;\n }\n .col-lg-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-lg-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-lg-offset-0 {\n margin-left: 0%;\n }\n}\ntable {\n background-color: transparent;\n}\ncaption {\n padding-top: 8px;\n padding-bottom: 8px;\n color: #777777;\n text-align: left;\n}\nth {\n text-align: left;\n}\n.table {\n width: 100%;\n max-width: 100%;\n margin-bottom: 20px;\n}\n.table > thead > tr > th,\n.table > tbody > tr > th,\n.table > tfoot > tr > th,\n.table > thead > tr > td,\n.table > tbody > tr > td,\n.table > tfoot > tr > td {\n padding: 8px;\n line-height: 1.42857143;\n vertical-align: top;\n border-top: 1px solid #ddd;\n}\n.table > thead > tr > th {\n vertical-align: bottom;\n border-bottom: 2px solid #ddd;\n}\n.table > caption + thead > tr:first-child > th,\n.table > colgroup + thead > tr:first-child > th,\n.table > thead:first-child > tr:first-child > th,\n.table > caption + thead > tr:first-child > td,\n.table > colgroup + thead > tr:first-child > td,\n.table > thead:first-child > tr:first-child > td {\n border-top: 0;\n}\n.table > tbody + tbody {\n border-top: 2px solid #ddd;\n}\n.table .table {\n background-color: #fff;\n}\n.table-condensed > thead > tr > th,\n.table-condensed > tbody > tr > th,\n.table-condensed > tfoot > tr > th,\n.table-condensed > thead > tr > td,\n.table-condensed > tbody > tr > td,\n.table-condensed > tfoot > tr > td {\n padding: 5px;\n}\n.table-bordered {\n border: 1px solid #ddd;\n}\n.table-bordered > thead > tr > th,\n.table-bordered > tbody > tr > th,\n.table-bordered > tfoot > tr > th,\n.table-bordered > thead > tr > td,\n.table-bordered > tbody > tr > td,\n.table-bordered > tfoot > tr > td {\n border: 1px solid #ddd;\n}\n.table-bordered > thead > tr > th,\n.table-bordered > thead > tr > td {\n border-bottom-width: 2px;\n}\n.table-striped > tbody > tr:nth-of-type(odd) {\n background-color: #f9f9f9;\n}\n.table-hover > tbody > tr:hover {\n background-color: #f5f5f5;\n}\ntable col[class*=\"col-\"] {\n position: static;\n float: none;\n display: table-column;\n}\ntable td[class*=\"col-\"],\ntable th[class*=\"col-\"] {\n position: static;\n float: none;\n display: table-cell;\n}\n.table > thead > tr > td.active,\n.table > tbody > tr > td.active,\n.table > tfoot > tr > td.active,\n.table > thead > tr > th.active,\n.table > tbody > tr > th.active,\n.table > tfoot > tr > th.active,\n.table > thead > tr.active > td,\n.table > tbody > tr.active > td,\n.table > tfoot > tr.active > td,\n.table > thead > tr.active > th,\n.table > tbody > tr.active > th,\n.table > tfoot > tr.active > th {\n background-color: #f5f5f5;\n}\n.table-hover > tbody > tr > td.active:hover,\n.table-hover > tbody > tr > th.active:hover,\n.table-hover > tbody > tr.active:hover > td,\n.table-hover > tbody > tr:hover > .active,\n.table-hover > tbody > tr.active:hover > th {\n background-color: #e8e8e8;\n}\n.table > thead > tr > td.success,\n.table > tbody > tr > td.success,\n.table > tfoot > tr > td.success,\n.table > thead > tr > th.success,\n.table > tbody > tr > th.success,\n.table > tfoot > tr > th.success,\n.table > thead > tr.success > td,\n.table > tbody > tr.success > td,\n.table > tfoot > tr.success > td,\n.table > thead > tr.success > th,\n.table > tbody > tr.success > th,\n.table > tfoot > tr.success > th {\n background-color: #dff0d8;\n}\n.table-hover > tbody > tr > td.success:hover,\n.table-hover > tbody > tr > th.success:hover,\n.table-hover > tbody > tr.success:hover > td,\n.table-hover > tbody > tr:hover > .success,\n.table-hover > tbody > tr.success:hover > th {\n background-color: #d0e9c6;\n}\n.table > thead > tr > td.info,\n.table > tbody > tr > td.info,\n.table > tfoot > tr > td.info,\n.table > thead > tr > th.info,\n.table > tbody > tr > th.info,\n.table > tfoot > tr > th.info,\n.table > thead > tr.info > td,\n.table > tbody > tr.info > td,\n.table > tfoot > tr.info > td,\n.table > thead > tr.info > th,\n.table > tbody > tr.info > th,\n.table > tfoot > tr.info > th {\n background-color: #d9edf7;\n}\n.table-hover > tbody > tr > td.info:hover,\n.table-hover > tbody > tr > th.info:hover,\n.table-hover > tbody > tr.info:hover > td,\n.table-hover > tbody > tr:hover > .info,\n.table-hover > tbody > tr.info:hover > th {\n background-color: #c4e3f3;\n}\n.table > thead > tr > td.warning,\n.table > tbody > tr > td.warning,\n.table > tfoot > tr > td.warning,\n.table > thead > tr > th.warning,\n.table > tbody > tr > th.warning,\n.table > tfoot > tr > th.warning,\n.table > thead > tr.warning > td,\n.table > tbody > tr.warning > td,\n.table > tfoot > tr.warning > td,\n.table > thead > tr.warning > th,\n.table > tbody > tr.warning > th,\n.table > tfoot > tr.warning > th {\n background-color: #fcf8e3;\n}\n.table-hover > tbody > tr > td.warning:hover,\n.table-hover > tbody > tr > th.warning:hover,\n.table-hover > tbody > tr.warning:hover > td,\n.table-hover > tbody > tr:hover > .warning,\n.table-hover > tbody > tr.warning:hover > th {\n background-color: #faf2cc;\n}\n.table > thead > tr > td.danger,\n.table > tbody > tr > td.danger,\n.table > tfoot > tr > td.danger,\n.table > thead > tr > th.danger,\n.table > tbody > tr > th.danger,\n.table > tfoot > tr > th.danger,\n.table > thead > tr.danger > td,\n.table > tbody > tr.danger > td,\n.table > tfoot > tr.danger > td,\n.table > thead > tr.danger > th,\n.table > tbody > tr.danger > th,\n.table > tfoot > tr.danger > th {\n background-color: #f2dede;\n}\n.table-hover > tbody > tr > td.danger:hover,\n.table-hover > tbody > tr > th.danger:hover,\n.table-hover > tbody > tr.danger:hover > td,\n.table-hover > tbody > tr:hover > .danger,\n.table-hover > tbody > tr.danger:hover > th {\n background-color: #ebcccc;\n}\n.table-responsive {\n overflow-x: auto;\n min-height: 0.01%;\n}\n@media screen and (max-width: 767px) {\n .table-responsive {\n width: 100%;\n margin-bottom: 15px;\n overflow-y: hidden;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n border: 1px solid #ddd;\n }\n .table-responsive > .table {\n margin-bottom: 0;\n }\n .table-responsive > .table > thead > tr > th,\n .table-responsive > .table > tbody > tr > th,\n .table-responsive > .table > tfoot > tr > th,\n .table-responsive > .table > thead > tr > td,\n .table-responsive > .table > tbody > tr > td,\n .table-responsive > .table > tfoot > tr > td {\n white-space: nowrap;\n }\n .table-responsive > .table-bordered {\n border: 0;\n }\n .table-responsive > .table-bordered > thead > tr > th:first-child,\n .table-responsive > .table-bordered > tbody > tr > th:first-child,\n .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n .table-responsive > .table-bordered > thead > tr > td:first-child,\n .table-responsive > .table-bordered > tbody > tr > td:first-child,\n .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n border-left: 0;\n }\n .table-responsive > .table-bordered > thead > tr > th:last-child,\n .table-responsive > .table-bordered > tbody > tr > th:last-child,\n .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n .table-responsive > .table-bordered > thead > tr > td:last-child,\n .table-responsive > .table-bordered > tbody > tr > td:last-child,\n .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n border-right: 0;\n }\n .table-responsive > .table-bordered > tbody > tr:last-child > th,\n .table-responsive > .table-bordered > tfoot > tr:last-child > th,\n .table-responsive > .table-bordered > tbody > tr:last-child > td,\n .table-responsive > .table-bordered > tfoot > tr:last-child > td {\n border-bottom: 0;\n }\n}\nfieldset {\n padding: 0;\n margin: 0;\n border: 0;\n min-width: 0;\n}\nlegend {\n display: block;\n width: 100%;\n padding: 0;\n margin-bottom: 20px;\n font-size: 21px;\n line-height: inherit;\n color: #333333;\n border: 0;\n border-bottom: 1px solid #e5e5e5;\n}\nlabel {\n display: inline-block;\n max-width: 100%;\n margin-bottom: 5px;\n font-weight: bold;\n}\ninput[type=\"search\"] {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n margin: 4px 0 0;\n margin-top: 1px \\9;\n line-height: normal;\n}\ninput[type=\"file\"] {\n display: block;\n}\ninput[type=\"range\"] {\n display: block;\n width: 100%;\n}\nselect[multiple],\nselect[size] {\n height: auto;\n}\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\noutput {\n display: block;\n padding-top: 7px;\n font-size: 14px;\n line-height: 1.42857143;\n color: #555555;\n}\n.form-control {\n display: block;\n width: 100%;\n height: 34px;\n padding: 6px 12px;\n font-size: 14px;\n line-height: 1.42857143;\n color: #555555;\n background-color: #fff;\n background-image: none;\n border: 1px solid #ccc;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n}\n.form-control:focus {\n border-color: #66afe9;\n outline: 0;\n -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);\n box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);\n}\n.form-control::-moz-placeholder {\n color: #999;\n opacity: 1;\n}\n.form-control:-ms-input-placeholder {\n color: #999;\n}\n.form-control::-webkit-input-placeholder {\n color: #999;\n}\n.form-control::-ms-expand {\n border: 0;\n background-color: transparent;\n}\n.form-control[disabled],\n.form-control[readonly],\nfieldset[disabled] .form-control {\n background-color: #eeeeee;\n opacity: 1;\n}\n.form-control[disabled],\nfieldset[disabled] .form-control {\n cursor: not-allowed;\n}\ntextarea.form-control {\n height: auto;\n}\ninput[type=\"search\"] {\n -webkit-appearance: none;\n}\n@media screen and (-webkit-min-device-pixel-ratio: 0) {\n input[type=\"date\"].form-control,\n input[type=\"time\"].form-control,\n input[type=\"datetime-local\"].form-control,\n input[type=\"month\"].form-control {\n line-height: 34px;\n }\n input[type=\"date\"].input-sm,\n input[type=\"time\"].input-sm,\n input[type=\"datetime-local\"].input-sm,\n input[type=\"month\"].input-sm,\n .input-group-sm input[type=\"date\"],\n .input-group-sm input[type=\"time\"],\n .input-group-sm input[type=\"datetime-local\"],\n .input-group-sm input[type=\"month\"] {\n line-height: 30px;\n }\n input[type=\"date\"].input-lg,\n input[type=\"time\"].input-lg,\n input[type=\"datetime-local\"].input-lg,\n input[type=\"month\"].input-lg,\n .input-group-lg input[type=\"date\"],\n .input-group-lg input[type=\"time\"],\n .input-group-lg input[type=\"datetime-local\"],\n .input-group-lg input[type=\"month\"] {\n line-height: 46px;\n }\n}\n.form-group {\n margin-bottom: 15px;\n}\n.radio,\n.checkbox {\n position: relative;\n display: block;\n margin-top: 10px;\n margin-bottom: 10px;\n}\n.radio label,\n.checkbox label {\n min-height: 20px;\n padding-left: 20px;\n margin-bottom: 0;\n font-weight: normal;\n cursor: pointer;\n}\n.radio input[type=\"radio\"],\n.radio-inline input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"],\n.checkbox-inline input[type=\"checkbox\"] {\n position: absolute;\n margin-left: -20px;\n margin-top: 4px \\9;\n}\n.radio + .radio,\n.checkbox + .checkbox {\n margin-top: -5px;\n}\n.radio-inline,\n.checkbox-inline {\n position: relative;\n display: inline-block;\n padding-left: 20px;\n margin-bottom: 0;\n vertical-align: middle;\n font-weight: normal;\n cursor: pointer;\n}\n.radio-inline + .radio-inline,\n.checkbox-inline + .checkbox-inline {\n margin-top: 0;\n margin-left: 10px;\n}\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"].disabled,\ninput[type=\"checkbox\"].disabled,\nfieldset[disabled] input[type=\"radio\"],\nfieldset[disabled] input[type=\"checkbox\"] {\n cursor: not-allowed;\n}\n.radio-inline.disabled,\n.checkbox-inline.disabled,\nfieldset[disabled] .radio-inline,\nfieldset[disabled] .checkbox-inline {\n cursor: not-allowed;\n}\n.radio.disabled label,\n.checkbox.disabled label,\nfieldset[disabled] .radio label,\nfieldset[disabled] .checkbox label {\n cursor: not-allowed;\n}\n.form-control-static {\n padding-top: 7px;\n padding-bottom: 7px;\n margin-bottom: 0;\n min-height: 34px;\n}\n.form-control-static.input-lg,\n.form-control-static.input-sm {\n padding-left: 0;\n padding-right: 0;\n}\n.input-sm {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\nselect.input-sm {\n height: 30px;\n line-height: 30px;\n}\ntextarea.input-sm,\nselect[multiple].input-sm {\n height: auto;\n}\n.form-group-sm .form-control {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.form-group-sm select.form-control {\n height: 30px;\n line-height: 30px;\n}\n.form-group-sm textarea.form-control,\n.form-group-sm select[multiple].form-control {\n height: auto;\n}\n.form-group-sm .form-control-static {\n height: 30px;\n min-height: 32px;\n padding: 6px 10px;\n font-size: 12px;\n line-height: 1.5;\n}\n.input-lg {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\nselect.input-lg {\n height: 46px;\n line-height: 46px;\n}\ntextarea.input-lg,\nselect[multiple].input-lg {\n height: auto;\n}\n.form-group-lg .form-control {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\n.form-group-lg select.form-control {\n height: 46px;\n line-height: 46px;\n}\n.form-group-lg textarea.form-control,\n.form-group-lg select[multiple].form-control {\n height: auto;\n}\n.form-group-lg .form-control-static {\n height: 46px;\n min-height: 38px;\n padding: 11px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n}\n.has-feedback {\n position: relative;\n}\n.has-feedback .form-control {\n padding-right: 42.5px;\n}\n.form-control-feedback {\n position: absolute;\n top: 0;\n right: 0;\n z-index: 2;\n display: block;\n width: 34px;\n height: 34px;\n line-height: 34px;\n text-align: center;\n pointer-events: none;\n}\n.input-lg + .form-control-feedback,\n.input-group-lg + .form-control-feedback,\n.form-group-lg .form-control + .form-control-feedback {\n width: 46px;\n height: 46px;\n line-height: 46px;\n}\n.input-sm + .form-control-feedback,\n.input-group-sm + .form-control-feedback,\n.form-group-sm .form-control + .form-control-feedback {\n width: 30px;\n height: 30px;\n line-height: 30px;\n}\n.has-success .help-block,\n.has-success .control-label,\n.has-success .radio,\n.has-success .checkbox,\n.has-success .radio-inline,\n.has-success .checkbox-inline,\n.has-success.radio label,\n.has-success.checkbox label,\n.has-success.radio-inline label,\n.has-success.checkbox-inline label {\n color: #3c763d;\n}\n.has-success .form-control {\n border-color: #3c763d;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-success .form-control:focus {\n border-color: #2b542c;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;\n}\n.has-success .input-group-addon {\n color: #3c763d;\n border-color: #3c763d;\n background-color: #dff0d8;\n}\n.has-success .form-control-feedback {\n color: #3c763d;\n}\n.has-warning .help-block,\n.has-warning .control-label,\n.has-warning .radio,\n.has-warning .checkbox,\n.has-warning .radio-inline,\n.has-warning .checkbox-inline,\n.has-warning.radio label,\n.has-warning.checkbox label,\n.has-warning.radio-inline label,\n.has-warning.checkbox-inline label {\n color: #8a6d3b;\n}\n.has-warning .form-control {\n border-color: #8a6d3b;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-warning .form-control:focus {\n border-color: #66512c;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;\n}\n.has-warning .input-group-addon {\n color: #8a6d3b;\n border-color: #8a6d3b;\n background-color: #fcf8e3;\n}\n.has-warning .form-control-feedback {\n color: #8a6d3b;\n}\n.has-error .help-block,\n.has-error .control-label,\n.has-error .radio,\n.has-error .checkbox,\n.has-error .radio-inline,\n.has-error .checkbox-inline,\n.has-error.radio label,\n.has-error.checkbox label,\n.has-error.radio-inline label,\n.has-error.checkbox-inline label {\n color: #a94442;\n}\n.has-error .form-control {\n border-color: #a94442;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-error .form-control:focus {\n border-color: #843534;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;\n}\n.has-error .input-group-addon {\n color: #a94442;\n border-color: #a94442;\n background-color: #f2dede;\n}\n.has-error .form-control-feedback {\n color: #a94442;\n}\n.has-feedback label ~ .form-control-feedback {\n top: 25px;\n}\n.has-feedback label.sr-only ~ .form-control-feedback {\n top: 0;\n}\n.help-block {\n display: block;\n margin-top: 5px;\n margin-bottom: 10px;\n color: #737373;\n}\n@media (min-width: 768px) {\n .form-inline .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .form-control {\n display: inline-block;\n width: auto;\n vertical-align: middle;\n }\n .form-inline .form-control-static {\n display: inline-block;\n }\n .form-inline .input-group {\n display: inline-table;\n vertical-align: middle;\n }\n .form-inline .input-group .input-group-addon,\n .form-inline .input-group .input-group-btn,\n .form-inline .input-group .form-control {\n width: auto;\n }\n .form-inline .input-group > .form-control {\n width: 100%;\n }\n .form-inline .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .radio,\n .form-inline .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .radio label,\n .form-inline .checkbox label {\n padding-left: 0;\n }\n .form-inline .radio input[type=\"radio\"],\n .form-inline .checkbox input[type=\"checkbox\"] {\n position: relative;\n margin-left: 0;\n }\n .form-inline .has-feedback .form-control-feedback {\n top: 0;\n }\n}\n.form-horizontal .radio,\n.form-horizontal .checkbox,\n.form-horizontal .radio-inline,\n.form-horizontal .checkbox-inline {\n margin-top: 0;\n margin-bottom: 0;\n padding-top: 7px;\n}\n.form-horizontal .radio,\n.form-horizontal .checkbox {\n min-height: 27px;\n}\n.form-horizontal .form-group {\n margin-left: -15px;\n margin-right: -15px;\n}\n@media (min-width: 768px) {\n .form-horizontal .control-label {\n text-align: right;\n margin-bottom: 0;\n padding-top: 7px;\n }\n}\n.form-horizontal .has-feedback .form-control-feedback {\n right: 15px;\n}\n@media (min-width: 768px) {\n .form-horizontal .form-group-lg .control-label {\n padding-top: 11px;\n font-size: 18px;\n }\n}\n@media (min-width: 768px) {\n .form-horizontal .form-group-sm .control-label {\n padding-top: 6px;\n font-size: 12px;\n }\n}\n.btn {\n display: inline-block;\n margin-bottom: 0;\n font-weight: normal;\n text-align: center;\n vertical-align: middle;\n touch-action: manipulation;\n cursor: pointer;\n background-image: none;\n border: 1px solid transparent;\n white-space: nowrap;\n padding: 6px 12px;\n font-size: 14px;\n line-height: 1.42857143;\n border-radius: 4px;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n}\n.btn:focus,\n.btn:active:focus,\n.btn.active:focus,\n.btn.focus,\n.btn:active.focus,\n.btn.active.focus {\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\n.btn:hover,\n.btn:focus,\n.btn.focus {\n color: #333;\n text-decoration: none;\n}\n.btn:active,\n.btn.active {\n outline: 0;\n background-image: none;\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn.disabled,\n.btn[disabled],\nfieldset[disabled] .btn {\n cursor: not-allowed;\n opacity: 0.65;\n filter: alpha(opacity=65);\n -webkit-box-shadow: none;\n box-shadow: none;\n}\na.btn.disabled,\nfieldset[disabled] a.btn {\n pointer-events: none;\n}\n.btn-default {\n color: #333;\n background-color: #fff;\n border-color: #ccc;\n}\n.btn-default:focus,\n.btn-default.focus {\n color: #333;\n background-color: #e6e6e6;\n border-color: #8c8c8c;\n}\n.btn-default:hover {\n color: #333;\n background-color: #e6e6e6;\n border-color: #adadad;\n}\n.btn-default:active,\n.btn-default.active,\n.open > .dropdown-toggle.btn-default {\n color: #333;\n background-color: #e6e6e6;\n border-color: #adadad;\n}\n.btn-default:active:hover,\n.btn-default.active:hover,\n.open > .dropdown-toggle.btn-default:hover,\n.btn-default:active:focus,\n.btn-default.active:focus,\n.open > .dropdown-toggle.btn-default:focus,\n.btn-default:active.focus,\n.btn-default.active.focus,\n.open > .dropdown-toggle.btn-default.focus {\n color: #333;\n background-color: #d4d4d4;\n border-color: #8c8c8c;\n}\n.btn-default:active,\n.btn-default.active,\n.open > .dropdown-toggle.btn-default {\n background-image: none;\n}\n.btn-default.disabled:hover,\n.btn-default[disabled]:hover,\nfieldset[disabled] .btn-default:hover,\n.btn-default.disabled:focus,\n.btn-default[disabled]:focus,\nfieldset[disabled] .btn-default:focus,\n.btn-default.disabled.focus,\n.btn-default[disabled].focus,\nfieldset[disabled] .btn-default.focus {\n background-color: #fff;\n border-color: #ccc;\n}\n.btn-default .badge {\n color: #fff;\n background-color: #333;\n}\n.btn-primary {\n color: #fff;\n background-color: #337ab7;\n border-color: #2e6da4;\n}\n.btn-primary:focus,\n.btn-primary.focus {\n color: #fff;\n background-color: #286090;\n border-color: #122b40;\n}\n.btn-primary:hover {\n color: #fff;\n background-color: #286090;\n border-color: #204d74;\n}\n.btn-primary:active,\n.btn-primary.active,\n.open > .dropdown-toggle.btn-primary {\n color: #fff;\n background-color: #286090;\n border-color: #204d74;\n}\n.btn-primary:active:hover,\n.btn-primary.active:hover,\n.open > .dropdown-toggle.btn-primary:hover,\n.btn-primary:active:focus,\n.btn-primary.active:focus,\n.open > .dropdown-toggle.btn-primary:focus,\n.btn-primary:active.focus,\n.btn-primary.active.focus,\n.open > .dropdown-toggle.btn-primary.focus {\n color: #fff;\n background-color: #204d74;\n border-color: #122b40;\n}\n.btn-primary:active,\n.btn-primary.active,\n.open > .dropdown-toggle.btn-primary {\n background-image: none;\n}\n.btn-primary.disabled:hover,\n.btn-primary[disabled]:hover,\nfieldset[disabled] .btn-primary:hover,\n.btn-primary.disabled:focus,\n.btn-primary[disabled]:focus,\nfieldset[disabled] .btn-primary:focus,\n.btn-primary.disabled.focus,\n.btn-primary[disabled].focus,\nfieldset[disabled] .btn-primary.focus {\n background-color: #337ab7;\n border-color: #2e6da4;\n}\n.btn-primary .badge {\n color: #337ab7;\n background-color: #fff;\n}\n.btn-success {\n color: #fff;\n background-color: #5cb85c;\n border-color: #4cae4c;\n}\n.btn-success:focus,\n.btn-success.focus {\n color: #fff;\n background-color: #449d44;\n border-color: #255625;\n}\n.btn-success:hover {\n color: #fff;\n background-color: #449d44;\n border-color: #398439;\n}\n.btn-success:active,\n.btn-success.active,\n.open > .dropdown-toggle.btn-success {\n color: #fff;\n background-color: #449d44;\n border-color: #398439;\n}\n.btn-success:active:hover,\n.btn-success.active:hover,\n.open > .dropdown-toggle.btn-success:hover,\n.btn-success:active:focus,\n.btn-success.active:focus,\n.open > .dropdown-toggle.btn-success:focus,\n.btn-success:active.focus,\n.btn-success.active.focus,\n.open > .dropdown-toggle.btn-success.focus {\n color: #fff;\n background-color: #398439;\n border-color: #255625;\n}\n.btn-success:active,\n.btn-success.active,\n.open > .dropdown-toggle.btn-success {\n background-image: none;\n}\n.btn-success.disabled:hover,\n.btn-success[disabled]:hover,\nfieldset[disabled] .btn-success:hover,\n.btn-success.disabled:focus,\n.btn-success[disabled]:focus,\nfieldset[disabled] .btn-success:focus,\n.btn-success.disabled.focus,\n.btn-success[disabled].focus,\nfieldset[disabled] .btn-success.focus {\n background-color: #5cb85c;\n border-color: #4cae4c;\n}\n.btn-success .badge {\n color: #5cb85c;\n background-color: #fff;\n}\n.btn-info {\n color: #fff;\n background-color: #5bc0de;\n border-color: #46b8da;\n}\n.btn-info:focus,\n.btn-info.focus {\n color: #fff;\n background-color: #31b0d5;\n border-color: #1b6d85;\n}\n.btn-info:hover {\n color: #fff;\n background-color: #31b0d5;\n border-color: #269abc;\n}\n.btn-info:active,\n.btn-info.active,\n.open > .dropdown-toggle.btn-info {\n color: #fff;\n background-color: #31b0d5;\n border-color: #269abc;\n}\n.btn-info:active:hover,\n.btn-info.active:hover,\n.open > .dropdown-toggle.btn-info:hover,\n.btn-info:active:focus,\n.btn-info.active:focus,\n.open > .dropdown-toggle.btn-info:focus,\n.btn-info:active.focus,\n.btn-info.active.focus,\n.open > .dropdown-toggle.btn-info.focus {\n color: #fff;\n background-color: #269abc;\n border-color: #1b6d85;\n}\n.btn-info:active,\n.btn-info.active,\n.open > .dropdown-toggle.btn-info {\n background-image: none;\n}\n.btn-info.disabled:hover,\n.btn-info[disabled]:hover,\nfieldset[disabled] .btn-info:hover,\n.btn-info.disabled:focus,\n.btn-info[disabled]:focus,\nfieldset[disabled] .btn-info:focus,\n.btn-info.disabled.focus,\n.btn-info[disabled].focus,\nfieldset[disabled] .btn-info.focus {\n background-color: #5bc0de;\n border-color: #46b8da;\n}\n.btn-info .badge {\n color: #5bc0de;\n background-color: #fff;\n}\n.btn-warning {\n color: #fff;\n background-color: #f0ad4e;\n border-color: #eea236;\n}\n.btn-warning:focus,\n.btn-warning.focus {\n color: #fff;\n background-color: #ec971f;\n border-color: #985f0d;\n}\n.btn-warning:hover {\n color: #fff;\n background-color: #ec971f;\n border-color: #d58512;\n}\n.btn-warning:active,\n.btn-warning.active,\n.open > .dropdown-toggle.btn-warning {\n color: #fff;\n background-color: #ec971f;\n border-color: #d58512;\n}\n.btn-warning:active:hover,\n.btn-warning.active:hover,\n.open > .dropdown-toggle.btn-warning:hover,\n.btn-warning:active:focus,\n.btn-warning.active:focus,\n.open > .dropdown-toggle.btn-warning:focus,\n.btn-warning:active.focus,\n.btn-warning.active.focus,\n.open > .dropdown-toggle.btn-warning.focus {\n color: #fff;\n background-color: #d58512;\n border-color: #985f0d;\n}\n.btn-warning:active,\n.btn-warning.active,\n.open > .dropdown-toggle.btn-warning {\n background-image: none;\n}\n.btn-warning.disabled:hover,\n.btn-warning[disabled]:hover,\nfieldset[disabled] .btn-warning:hover,\n.btn-warning.disabled:focus,\n.btn-warning[disabled]:focus,\nfieldset[disabled] .btn-warning:focus,\n.btn-warning.disabled.focus,\n.btn-warning[disabled].focus,\nfieldset[disabled] .btn-warning.focus {\n background-color: #f0ad4e;\n border-color: #eea236;\n}\n.btn-warning .badge {\n color: #f0ad4e;\n background-color: #fff;\n}\n.btn-danger {\n color: #fff;\n background-color: #d9534f;\n border-color: #d43f3a;\n}\n.btn-danger:focus,\n.btn-danger.focus {\n color: #fff;\n background-color: #c9302c;\n border-color: #761c19;\n}\n.btn-danger:hover {\n color: #fff;\n background-color: #c9302c;\n border-color: #ac2925;\n}\n.btn-danger:active,\n.btn-danger.active,\n.open > .dropdown-toggle.btn-danger {\n color: #fff;\n background-color: #c9302c;\n border-color: #ac2925;\n}\n.btn-danger:active:hover,\n.btn-danger.active:hover,\n.open > .dropdown-toggle.btn-danger:hover,\n.btn-danger:active:focus,\n.btn-danger.active:focus,\n.open > .dropdown-toggle.btn-danger:focus,\n.btn-danger:active.focus,\n.btn-danger.active.focus,\n.open > .dropdown-toggle.btn-danger.focus {\n color: #fff;\n background-color: #ac2925;\n border-color: #761c19;\n}\n.btn-danger:active,\n.btn-danger.active,\n.open > .dropdown-toggle.btn-danger {\n background-image: none;\n}\n.btn-danger.disabled:hover,\n.btn-danger[disabled]:hover,\nfieldset[disabled] .btn-danger:hover,\n.btn-danger.disabled:focus,\n.btn-danger[disabled]:focus,\nfieldset[disabled] .btn-danger:focus,\n.btn-danger.disabled.focus,\n.btn-danger[disabled].focus,\nfieldset[disabled] .btn-danger.focus {\n background-color: #d9534f;\n border-color: #d43f3a;\n}\n.btn-danger .badge {\n color: #d9534f;\n background-color: #fff;\n}\n.btn-link {\n color: #337ab7;\n font-weight: normal;\n border-radius: 0;\n}\n.btn-link,\n.btn-link:active,\n.btn-link.active,\n.btn-link[disabled],\nfieldset[disabled] .btn-link {\n background-color: transparent;\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn-link,\n.btn-link:hover,\n.btn-link:focus,\n.btn-link:active {\n border-color: transparent;\n}\n.btn-link:hover,\n.btn-link:focus {\n color: #23527c;\n text-decoration: underline;\n background-color: transparent;\n}\n.btn-link[disabled]:hover,\nfieldset[disabled] .btn-link:hover,\n.btn-link[disabled]:focus,\nfieldset[disabled] .btn-link:focus {\n color: #777777;\n text-decoration: none;\n}\n.btn-lg,\n.btn-group-lg > .btn {\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\n.btn-sm,\n.btn-group-sm > .btn {\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.btn-xs,\n.btn-group-xs > .btn {\n padding: 1px 5px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.btn-block {\n display: block;\n width: 100%;\n}\n.btn-block + .btn-block {\n margin-top: 5px;\n}\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n width: 100%;\n}\n.fade {\n opacity: 0;\n -webkit-transition: opacity 0.15s linear;\n -o-transition: opacity 0.15s linear;\n transition: opacity 0.15s linear;\n}\n.fade.in {\n opacity: 1;\n}\n.collapse {\n display: none;\n}\n.collapse.in {\n display: block;\n}\ntr.collapse.in {\n display: table-row;\n}\ntbody.collapse.in {\n display: table-row-group;\n}\n.collapsing {\n position: relative;\n height: 0;\n overflow: hidden;\n -webkit-transition-property: height, visibility;\n transition-property: height, visibility;\n -webkit-transition-duration: 0.35s;\n transition-duration: 0.35s;\n -webkit-transition-timing-function: ease;\n transition-timing-function: ease;\n}\n.caret {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 2px;\n vertical-align: middle;\n border-top: 4px dashed;\n border-top: 4px solid \\9;\n border-right: 4px solid transparent;\n border-left: 4px solid transparent;\n}\n.dropup,\n.dropdown {\n position: relative;\n}\n.dropdown-toggle:focus {\n outline: 0;\n}\n.dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: 1000;\n display: none;\n float: left;\n min-width: 160px;\n padding: 5px 0;\n margin: 2px 0 0;\n list-style: none;\n font-size: 14px;\n text-align: left;\n background-color: #fff;\n border: 1px solid #ccc;\n border: 1px solid rgba(0, 0, 0, 0.15);\n border-radius: 4px;\n -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\n box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\n background-clip: padding-box;\n}\n.dropdown-menu.pull-right {\n right: 0;\n left: auto;\n}\n.dropdown-menu .divider {\n height: 1px;\n margin: 9px 0;\n overflow: hidden;\n background-color: #e5e5e5;\n}\n.dropdown-menu > li > a {\n display: block;\n padding: 3px 20px;\n clear: both;\n font-weight: normal;\n line-height: 1.42857143;\n color: #333333;\n white-space: nowrap;\n}\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n text-decoration: none;\n color: #262626;\n background-color: #f5f5f5;\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n color: #fff;\n text-decoration: none;\n outline: 0;\n background-color: #337ab7;\n}\n.dropdown-menu > .disabled > a,\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n color: #777777;\n}\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n text-decoration: none;\n background-color: transparent;\n background-image: none;\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n cursor: not-allowed;\n}\n.open > .dropdown-menu {\n display: block;\n}\n.open > a {\n outline: 0;\n}\n.dropdown-menu-right {\n left: auto;\n right: 0;\n}\n.dropdown-menu-left {\n left: 0;\n right: auto;\n}\n.dropdown-header {\n display: block;\n padding: 3px 20px;\n font-size: 12px;\n line-height: 1.42857143;\n color: #777777;\n white-space: nowrap;\n}\n.dropdown-backdrop {\n position: fixed;\n left: 0;\n right: 0;\n bottom: 0;\n top: 0;\n z-index: 990;\n}\n.pull-right > .dropdown-menu {\n right: 0;\n left: auto;\n}\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n border-top: 0;\n border-bottom: 4px dashed;\n border-bottom: 4px solid \\9;\n content: \"\";\n}\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n top: auto;\n bottom: 100%;\n margin-bottom: 2px;\n}\n@media (min-width: 768px) {\n .navbar-right .dropdown-menu {\n left: auto;\n right: 0;\n }\n .navbar-right .dropdown-menu-left {\n left: 0;\n right: auto;\n }\n}\n.btn-group,\n.btn-group-vertical {\n position: relative;\n display: inline-block;\n vertical-align: middle;\n}\n.btn-group > .btn,\n.btn-group-vertical > .btn {\n position: relative;\n float: left;\n}\n.btn-group > .btn:hover,\n.btn-group-vertical > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group-vertical > .btn:focus,\n.btn-group > .btn:active,\n.btn-group-vertical > .btn:active,\n.btn-group > .btn.active,\n.btn-group-vertical > .btn.active {\n z-index: 2;\n}\n.btn-group .btn + .btn,\n.btn-group .btn + .btn-group,\n.btn-group .btn-group + .btn,\n.btn-group .btn-group + .btn-group {\n margin-left: -1px;\n}\n.btn-toolbar {\n margin-left: -5px;\n}\n.btn-toolbar .btn,\n.btn-toolbar .btn-group,\n.btn-toolbar .input-group {\n float: left;\n}\n.btn-toolbar > .btn,\n.btn-toolbar > .btn-group,\n.btn-toolbar > .input-group {\n margin-left: 5px;\n}\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n border-radius: 0;\n}\n.btn-group > .btn:first-child {\n margin-left: 0;\n}\n.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) {\n border-bottom-right-radius: 0;\n border-top-right-radius: 0;\n}\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n border-bottom-left-radius: 0;\n border-top-left-radius: 0;\n}\n.btn-group > .btn-group {\n float: left;\n}\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child,\n.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle {\n border-bottom-right-radius: 0;\n border-top-right-radius: 0;\n}\n.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {\n border-bottom-left-radius: 0;\n border-top-left-radius: 0;\n}\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n outline: 0;\n}\n.btn-group > .btn + .dropdown-toggle {\n padding-left: 8px;\n padding-right: 8px;\n}\n.btn-group > .btn-lg + .dropdown-toggle {\n padding-left: 12px;\n padding-right: 12px;\n}\n.btn-group.open .dropdown-toggle {\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn-group.open .dropdown-toggle.btn-link {\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn .caret {\n margin-left: 0;\n}\n.btn-lg .caret {\n border-width: 5px 5px 0;\n border-bottom-width: 0;\n}\n.dropup .btn-lg .caret {\n border-width: 0 5px 5px;\n}\n.btn-group-vertical > .btn,\n.btn-group-vertical > .btn-group,\n.btn-group-vertical > .btn-group > .btn {\n display: block;\n float: none;\n width: 100%;\n max-width: 100%;\n}\n.btn-group-vertical > .btn-group > .btn {\n float: none;\n}\n.btn-group-vertical > .btn + .btn,\n.btn-group-vertical > .btn + .btn-group,\n.btn-group-vertical > .btn-group + .btn,\n.btn-group-vertical > .btn-group + .btn-group {\n margin-top: -1px;\n margin-left: 0;\n}\n.btn-group-vertical > .btn:not(:first-child):not(:last-child) {\n border-radius: 0;\n}\n.btn-group-vertical > .btn:first-child:not(:last-child) {\n border-top-right-radius: 4px;\n border-top-left-radius: 4px;\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group-vertical > .btn:last-child:not(:first-child) {\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n border-bottom-right-radius: 4px;\n border-bottom-left-radius: 4px;\n}\n.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child,\n.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle {\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.btn-group-justified {\n display: table;\n width: 100%;\n table-layout: fixed;\n border-collapse: separate;\n}\n.btn-group-justified > .btn,\n.btn-group-justified > .btn-group {\n float: none;\n display: table-cell;\n width: 1%;\n}\n.btn-group-justified > .btn-group .btn {\n width: 100%;\n}\n.btn-group-justified > .btn-group .dropdown-menu {\n left: auto;\n}\n[data-toggle=\"buttons\"] > .btn input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn-group > .btn input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn input[type=\"checkbox\"],\n[data-toggle=\"buttons\"] > .btn-group > .btn input[type=\"checkbox\"] {\n position: absolute;\n clip: rect(0, 0, 0, 0);\n pointer-events: none;\n}\n.input-group {\n position: relative;\n display: table;\n border-collapse: separate;\n}\n.input-group[class*=\"col-\"] {\n float: none;\n padding-left: 0;\n padding-right: 0;\n}\n.input-group .form-control {\n position: relative;\n z-index: 2;\n float: left;\n width: 100%;\n margin-bottom: 0;\n}\n.input-group .form-control:focus {\n z-index: 3;\n}\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\nselect.input-group-lg > .form-control,\nselect.input-group-lg > .input-group-addon,\nselect.input-group-lg > .input-group-btn > .btn {\n height: 46px;\n line-height: 46px;\n}\ntextarea.input-group-lg > .form-control,\ntextarea.input-group-lg > .input-group-addon,\ntextarea.input-group-lg > .input-group-btn > .btn,\nselect[multiple].input-group-lg > .form-control,\nselect[multiple].input-group-lg > .input-group-addon,\nselect[multiple].input-group-lg > .input-group-btn > .btn {\n height: auto;\n}\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\nselect.input-group-sm > .form-control,\nselect.input-group-sm > .input-group-addon,\nselect.input-group-sm > .input-group-btn > .btn {\n height: 30px;\n line-height: 30px;\n}\ntextarea.input-group-sm > .form-control,\ntextarea.input-group-sm > .input-group-addon,\ntextarea.input-group-sm > .input-group-btn > .btn,\nselect[multiple].input-group-sm > .form-control,\nselect[multiple].input-group-sm > .input-group-addon,\nselect[multiple].input-group-sm > .input-group-btn > .btn {\n height: auto;\n}\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n display: table-cell;\n}\n.input-group-addon:not(:first-child):not(:last-child),\n.input-group-btn:not(:first-child):not(:last-child),\n.input-group .form-control:not(:first-child):not(:last-child) {\n border-radius: 0;\n}\n.input-group-addon,\n.input-group-btn {\n width: 1%;\n white-space: nowrap;\n vertical-align: middle;\n}\n.input-group-addon {\n padding: 6px 12px;\n font-size: 14px;\n font-weight: normal;\n line-height: 1;\n color: #555555;\n text-align: center;\n background-color: #eeeeee;\n border: 1px solid #ccc;\n border-radius: 4px;\n}\n.input-group-addon.input-sm {\n padding: 5px 10px;\n font-size: 12px;\n border-radius: 3px;\n}\n.input-group-addon.input-lg {\n padding: 10px 16px;\n font-size: 18px;\n border-radius: 6px;\n}\n.input-group-addon input[type=\"radio\"],\n.input-group-addon input[type=\"checkbox\"] {\n margin-top: 0;\n}\n.input-group .form-control:first-child,\n.input-group-addon:first-child,\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group > .btn,\n.input-group-btn:first-child > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {\n border-bottom-right-radius: 0;\n border-top-right-radius: 0;\n}\n.input-group-addon:first-child {\n border-right: 0;\n}\n.input-group .form-control:last-child,\n.input-group-addon:last-child,\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group > .btn,\n.input-group-btn:last-child > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child),\n.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {\n border-bottom-left-radius: 0;\n border-top-left-radius: 0;\n}\n.input-group-addon:last-child {\n border-left: 0;\n}\n.input-group-btn {\n position: relative;\n font-size: 0;\n white-space: nowrap;\n}\n.input-group-btn > .btn {\n position: relative;\n}\n.input-group-btn > .btn + .btn {\n margin-left: -1px;\n}\n.input-group-btn > .btn:hover,\n.input-group-btn > .btn:focus,\n.input-group-btn > .btn:active {\n z-index: 2;\n}\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group {\n margin-right: -1px;\n}\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group {\n z-index: 2;\n margin-left: -1px;\n}\n.nav {\n margin-bottom: 0;\n padding-left: 0;\n list-style: none;\n}\n.nav > li {\n position: relative;\n display: block;\n}\n.nav > li > a {\n position: relative;\n display: block;\n padding: 10px 15px;\n}\n.nav > li > a:hover,\n.nav > li > a:focus {\n text-decoration: none;\n background-color: #eeeeee;\n}\n.nav > li.disabled > a {\n color: #777777;\n}\n.nav > li.disabled > a:hover,\n.nav > li.disabled > a:focus {\n color: #777777;\n text-decoration: none;\n background-color: transparent;\n cursor: not-allowed;\n}\n.nav .open > a,\n.nav .open > a:hover,\n.nav .open > a:focus {\n background-color: #eeeeee;\n border-color: #337ab7;\n}\n.nav .nav-divider {\n height: 1px;\n margin: 9px 0;\n overflow: hidden;\n background-color: #e5e5e5;\n}\n.nav > li > a > img {\n max-width: none;\n}\n.nav-tabs {\n border-bottom: 1px solid #ddd;\n}\n.nav-tabs > li {\n float: left;\n margin-bottom: -1px;\n}\n.nav-tabs > li > a {\n margin-right: 2px;\n line-height: 1.42857143;\n border: 1px solid transparent;\n border-radius: 4px 4px 0 0;\n}\n.nav-tabs > li > a:hover {\n border-color: #eeeeee #eeeeee #ddd;\n}\n.nav-tabs > li.active > a,\n.nav-tabs > li.active > a:hover,\n.nav-tabs > li.active > a:focus {\n color: #555555;\n background-color: #fff;\n border: 1px solid #ddd;\n border-bottom-color: transparent;\n cursor: default;\n}\n.nav-tabs.nav-justified {\n width: 100%;\n border-bottom: 0;\n}\n.nav-tabs.nav-justified > li {\n float: none;\n}\n.nav-tabs.nav-justified > li > a {\n text-align: center;\n margin-bottom: 5px;\n}\n.nav-tabs.nav-justified > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n}\n@media (min-width: 768px) {\n .nav-tabs.nav-justified > li {\n display: table-cell;\n width: 1%;\n }\n .nav-tabs.nav-justified > li > a {\n margin-bottom: 0;\n }\n}\n.nav-tabs.nav-justified > li > a {\n margin-right: 0;\n border-radius: 4px;\n}\n.nav-tabs.nav-justified > .active > a,\n.nav-tabs.nav-justified > .active > a:hover,\n.nav-tabs.nav-justified > .active > a:focus {\n border: 1px solid #ddd;\n}\n@media (min-width: 768px) {\n .nav-tabs.nav-justified > li > a {\n border-bottom: 1px solid #ddd;\n border-radius: 4px 4px 0 0;\n }\n .nav-tabs.nav-justified > .active > a,\n .nav-tabs.nav-justified > .active > a:hover,\n .nav-tabs.nav-justified > .active > a:focus {\n border-bottom-color: #fff;\n }\n}\n.nav-pills > li {\n float: left;\n}\n.nav-pills > li > a {\n border-radius: 4px;\n}\n.nav-pills > li + li {\n margin-left: 2px;\n}\n.nav-pills > li.active > a,\n.nav-pills > li.active > a:hover,\n.nav-pills > li.active > a:focus {\n color: #fff;\n background-color: #337ab7;\n}\n.nav-stacked > li {\n float: none;\n}\n.nav-stacked > li + li {\n margin-top: 2px;\n margin-left: 0;\n}\n.nav-justified {\n width: 100%;\n}\n.nav-justified > li {\n float: none;\n}\n.nav-justified > li > a {\n text-align: center;\n margin-bottom: 5px;\n}\n.nav-justified > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n}\n@media (min-width: 768px) {\n .nav-justified > li {\n display: table-cell;\n width: 1%;\n }\n .nav-justified > li > a {\n margin-bottom: 0;\n }\n}\n.nav-tabs-justified {\n border-bottom: 0;\n}\n.nav-tabs-justified > li > a {\n margin-right: 0;\n border-radius: 4px;\n}\n.nav-tabs-justified > .active > a,\n.nav-tabs-justified > .active > a:hover,\n.nav-tabs-justified > .active > a:focus {\n border: 1px solid #ddd;\n}\n@media (min-width: 768px) {\n .nav-tabs-justified > li > a {\n border-bottom: 1px solid #ddd;\n border-radius: 4px 4px 0 0;\n }\n .nav-tabs-justified > .active > a,\n .nav-tabs-justified > .active > a:hover,\n .nav-tabs-justified > .active > a:focus {\n border-bottom-color: #fff;\n }\n}\n.tab-content > .tab-pane {\n display: none;\n}\n.tab-content > .active {\n display: block;\n}\n.nav-tabs .dropdown-menu {\n margin-top: -1px;\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.navbar {\n position: relative;\n min-height: 50px;\n margin-bottom: 20px;\n border: 1px solid transparent;\n}\n@media (min-width: 768px) {\n .navbar {\n border-radius: 4px;\n }\n}\n@media (min-width: 768px) {\n .navbar-header {\n float: left;\n }\n}\n.navbar-collapse {\n overflow-x: visible;\n padding-right: 15px;\n padding-left: 15px;\n border-top: 1px solid transparent;\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);\n -webkit-overflow-scrolling: touch;\n}\n.navbar-collapse.in {\n overflow-y: auto;\n}\n@media (min-width: 768px) {\n .navbar-collapse {\n width: auto;\n border-top: 0;\n box-shadow: none;\n }\n .navbar-collapse.collapse {\n display: block !important;\n height: auto !important;\n padding-bottom: 0;\n overflow: visible !important;\n }\n .navbar-collapse.in {\n overflow-y: visible;\n }\n .navbar-fixed-top .navbar-collapse,\n .navbar-static-top .navbar-collapse,\n .navbar-fixed-bottom .navbar-collapse {\n padding-left: 0;\n padding-right: 0;\n }\n}\n.navbar-fixed-top .navbar-collapse,\n.navbar-fixed-bottom .navbar-collapse {\n max-height: 340px;\n}\n@media (max-device-width: 480px) and (orientation: landscape) {\n .navbar-fixed-top .navbar-collapse,\n .navbar-fixed-bottom .navbar-collapse {\n max-height: 200px;\n }\n}\n.container > .navbar-header,\n.container-fluid > .navbar-header,\n.container > .navbar-collapse,\n.container-fluid > .navbar-collapse {\n margin-right: -15px;\n margin-left: -15px;\n}\n@media (min-width: 768px) {\n .container > .navbar-header,\n .container-fluid > .navbar-header,\n .container > .navbar-collapse,\n .container-fluid > .navbar-collapse {\n margin-right: 0;\n margin-left: 0;\n }\n}\n.navbar-static-top {\n z-index: 1000;\n border-width: 0 0 1px;\n}\n@media (min-width: 768px) {\n .navbar-static-top {\n border-radius: 0;\n }\n}\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n position: fixed;\n right: 0;\n left: 0;\n z-index: 1030;\n}\n@media (min-width: 768px) {\n .navbar-fixed-top,\n .navbar-fixed-bottom {\n border-radius: 0;\n }\n}\n.navbar-fixed-top {\n top: 0;\n border-width: 0 0 1px;\n}\n.navbar-fixed-bottom {\n bottom: 0;\n margin-bottom: 0;\n border-width: 1px 0 0;\n}\n.navbar-brand {\n float: left;\n padding: 15px 15px;\n font-size: 18px;\n line-height: 20px;\n height: 50px;\n}\n.navbar-brand:hover,\n.navbar-brand:focus {\n text-decoration: none;\n}\n.navbar-brand > img {\n display: block;\n}\n@media (min-width: 768px) {\n .navbar > .container .navbar-brand,\n .navbar > .container-fluid .navbar-brand {\n margin-left: -15px;\n }\n}\n.navbar-toggle {\n position: relative;\n float: right;\n margin-right: 15px;\n padding: 9px 10px;\n margin-top: 8px;\n margin-bottom: 8px;\n background-color: transparent;\n background-image: none;\n border: 1px solid transparent;\n border-radius: 4px;\n}\n.navbar-toggle:focus {\n outline: 0;\n}\n.navbar-toggle .icon-bar {\n display: block;\n width: 22px;\n height: 2px;\n border-radius: 1px;\n}\n.navbar-toggle .icon-bar + .icon-bar {\n margin-top: 4px;\n}\n@media (min-width: 768px) {\n .navbar-toggle {\n display: none;\n }\n}\n.navbar-nav {\n margin: 7.5px -15px;\n}\n.navbar-nav > li > a {\n padding-top: 10px;\n padding-bottom: 10px;\n line-height: 20px;\n}\n@media (max-width: 767px) {\n .navbar-nav .open .dropdown-menu {\n position: static;\n float: none;\n width: auto;\n margin-top: 0;\n background-color: transparent;\n border: 0;\n box-shadow: none;\n }\n .navbar-nav .open .dropdown-menu > li > a,\n .navbar-nav .open .dropdown-menu .dropdown-header {\n padding: 5px 15px 5px 25px;\n }\n .navbar-nav .open .dropdown-menu > li > a {\n line-height: 20px;\n }\n .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-nav .open .dropdown-menu > li > a:focus {\n background-image: none;\n }\n}\n@media (min-width: 768px) {\n .navbar-nav {\n float: left;\n margin: 0;\n }\n .navbar-nav > li {\n float: left;\n }\n .navbar-nav > li > a {\n padding-top: 15px;\n padding-bottom: 15px;\n }\n}\n.navbar-form {\n margin-left: -15px;\n margin-right: -15px;\n padding: 10px 15px;\n border-top: 1px solid transparent;\n border-bottom: 1px solid transparent;\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n margin-top: 8px;\n margin-bottom: 8px;\n}\n@media (min-width: 768px) {\n .navbar-form .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .form-control {\n display: inline-block;\n width: auto;\n vertical-align: middle;\n }\n .navbar-form .form-control-static {\n display: inline-block;\n }\n .navbar-form .input-group {\n display: inline-table;\n vertical-align: middle;\n }\n .navbar-form .input-group .input-group-addon,\n .navbar-form .input-group .input-group-btn,\n .navbar-form .input-group .form-control {\n width: auto;\n }\n .navbar-form .input-group > .form-control {\n width: 100%;\n }\n .navbar-form .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .radio,\n .navbar-form .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .radio label,\n .navbar-form .checkbox label {\n padding-left: 0;\n }\n .navbar-form .radio input[type=\"radio\"],\n .navbar-form .checkbox input[type=\"checkbox\"] {\n position: relative;\n margin-left: 0;\n }\n .navbar-form .has-feedback .form-control-feedback {\n top: 0;\n }\n}\n@media (max-width: 767px) {\n .navbar-form .form-group {\n margin-bottom: 5px;\n }\n .navbar-form .form-group:last-child {\n margin-bottom: 0;\n }\n}\n@media (min-width: 768px) {\n .navbar-form {\n width: auto;\n border: 0;\n margin-left: 0;\n margin-right: 0;\n padding-top: 0;\n padding-bottom: 0;\n -webkit-box-shadow: none;\n box-shadow: none;\n }\n}\n.navbar-nav > li > .dropdown-menu {\n margin-top: 0;\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n margin-bottom: 0;\n border-top-right-radius: 4px;\n border-top-left-radius: 4px;\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.navbar-btn {\n margin-top: 8px;\n margin-bottom: 8px;\n}\n.navbar-btn.btn-sm {\n margin-top: 10px;\n margin-bottom: 10px;\n}\n.navbar-btn.btn-xs {\n margin-top: 14px;\n margin-bottom: 14px;\n}\n.navbar-text {\n margin-top: 15px;\n margin-bottom: 15px;\n}\n@media (min-width: 768px) {\n .navbar-text {\n float: left;\n margin-left: 15px;\n margin-right: 15px;\n }\n}\n@media (min-width: 768px) {\n .navbar-left {\n float: left !important;\n }\n .navbar-right {\n float: right !important;\n margin-right: -15px;\n }\n .navbar-right ~ .navbar-right {\n margin-right: 0;\n }\n}\n.navbar-default {\n background-color: #f8f8f8;\n border-color: #e7e7e7;\n}\n.navbar-default .navbar-brand {\n color: #777;\n}\n.navbar-default .navbar-brand:hover,\n.navbar-default .navbar-brand:focus {\n color: #5e5e5e;\n background-color: transparent;\n}\n.navbar-default .navbar-text {\n color: #777;\n}\n.navbar-default .navbar-nav > li > a {\n color: #777;\n}\n.navbar-default .navbar-nav > li > a:hover,\n.navbar-default .navbar-nav > li > a:focus {\n color: #333;\n background-color: transparent;\n}\n.navbar-default .navbar-nav > .active > a,\n.navbar-default .navbar-nav > .active > a:hover,\n.navbar-default .navbar-nav > .active > a:focus {\n color: #555;\n background-color: #e7e7e7;\n}\n.navbar-default .navbar-nav > .disabled > a,\n.navbar-default .navbar-nav > .disabled > a:hover,\n.navbar-default .navbar-nav > .disabled > a:focus {\n color: #ccc;\n background-color: transparent;\n}\n.navbar-default .navbar-toggle {\n border-color: #ddd;\n}\n.navbar-default .navbar-toggle:hover,\n.navbar-default .navbar-toggle:focus {\n background-color: #ddd;\n}\n.navbar-default .navbar-toggle .icon-bar {\n background-color: #888;\n}\n.navbar-default .navbar-collapse,\n.navbar-default .navbar-form {\n border-color: #e7e7e7;\n}\n.navbar-default .navbar-nav > .open > a,\n.navbar-default .navbar-nav > .open > a:hover,\n.navbar-default .navbar-nav > .open > a:focus {\n background-color: #e7e7e7;\n color: #555;\n}\n@media (max-width: 767px) {\n .navbar-default .navbar-nav .open .dropdown-menu > li > a {\n color: #777;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus {\n color: #333;\n background-color: transparent;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a,\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #555;\n background-color: #e7e7e7;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a,\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n color: #ccc;\n background-color: transparent;\n }\n}\n.navbar-default .navbar-link {\n color: #777;\n}\n.navbar-default .navbar-link:hover {\n color: #333;\n}\n.navbar-default .btn-link {\n color: #777;\n}\n.navbar-default .btn-link:hover,\n.navbar-default .btn-link:focus {\n color: #333;\n}\n.navbar-default .btn-link[disabled]:hover,\nfieldset[disabled] .navbar-default .btn-link:hover,\n.navbar-default .btn-link[disabled]:focus,\nfieldset[disabled] .navbar-default .btn-link:focus {\n color: #ccc;\n}\n.navbar-inverse {\n background-color: #222;\n border-color: #080808;\n}\n.navbar-inverse .navbar-brand {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-brand:hover,\n.navbar-inverse .navbar-brand:focus {\n color: #fff;\n background-color: transparent;\n}\n.navbar-inverse .navbar-text {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-nav > li > a {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-nav > li > a:hover,\n.navbar-inverse .navbar-nav > li > a:focus {\n color: #fff;\n background-color: transparent;\n}\n.navbar-inverse .navbar-nav > .active > a,\n.navbar-inverse .navbar-nav > .active > a:hover,\n.navbar-inverse .navbar-nav > .active > a:focus {\n color: #fff;\n background-color: #080808;\n}\n.navbar-inverse .navbar-nav > .disabled > a,\n.navbar-inverse .navbar-nav > .disabled > a:hover,\n.navbar-inverse .navbar-nav > .disabled > a:focus {\n color: #444;\n background-color: transparent;\n}\n.navbar-inverse .navbar-toggle {\n border-color: #333;\n}\n.navbar-inverse .navbar-toggle:hover,\n.navbar-inverse .navbar-toggle:focus {\n background-color: #333;\n}\n.navbar-inverse .navbar-toggle .icon-bar {\n background-color: #fff;\n}\n.navbar-inverse .navbar-collapse,\n.navbar-inverse .navbar-form {\n border-color: #101010;\n}\n.navbar-inverse .navbar-nav > .open > a,\n.navbar-inverse .navbar-nav > .open > a:hover,\n.navbar-inverse .navbar-nav > .open > a:focus {\n background-color: #080808;\n color: #fff;\n}\n@media (max-width: 767px) {\n .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header {\n border-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu .divider {\n background-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a {\n color: #9d9d9d;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus {\n color: #fff;\n background-color: transparent;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #fff;\n background-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n color: #444;\n background-color: transparent;\n }\n}\n.navbar-inverse .navbar-link {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-link:hover {\n color: #fff;\n}\n.navbar-inverse .btn-link {\n color: #9d9d9d;\n}\n.navbar-inverse .btn-link:hover,\n.navbar-inverse .btn-link:focus {\n color: #fff;\n}\n.navbar-inverse .btn-link[disabled]:hover,\nfieldset[disabled] .navbar-inverse .btn-link:hover,\n.navbar-inverse .btn-link[disabled]:focus,\nfieldset[disabled] .navbar-inverse .btn-link:focus {\n color: #444;\n}\n.breadcrumb {\n padding: 8px 15px;\n margin-bottom: 20px;\n list-style: none;\n background-color: #f5f5f5;\n border-radius: 4px;\n}\n.breadcrumb > li {\n display: inline-block;\n}\n.breadcrumb > li + li:before {\n content: \"/\\00a0\";\n padding: 0 5px;\n color: #ccc;\n}\n.breadcrumb > .active {\n color: #777777;\n}\n.pagination {\n display: inline-block;\n padding-left: 0;\n margin: 20px 0;\n border-radius: 4px;\n}\n.pagination > li {\n display: inline;\n}\n.pagination > li > a,\n.pagination > li > span {\n position: relative;\n float: left;\n padding: 6px 12px;\n line-height: 1.42857143;\n text-decoration: none;\n color: #337ab7;\n background-color: #fff;\n border: 1px solid #ddd;\n margin-left: -1px;\n}\n.pagination > li:first-child > a,\n.pagination > li:first-child > span {\n margin-left: 0;\n border-bottom-left-radius: 4px;\n border-top-left-radius: 4px;\n}\n.pagination > li:last-child > a,\n.pagination > li:last-child > span {\n border-bottom-right-radius: 4px;\n border-top-right-radius: 4px;\n}\n.pagination > li > a:hover,\n.pagination > li > span:hover,\n.pagination > li > a:focus,\n.pagination > li > span:focus {\n z-index: 2;\n color: #23527c;\n background-color: #eeeeee;\n border-color: #ddd;\n}\n.pagination > .active > a,\n.pagination > .active > span,\n.pagination > .active > a:hover,\n.pagination > .active > span:hover,\n.pagination > .active > a:focus,\n.pagination > .active > span:focus {\n z-index: 3;\n color: #fff;\n background-color: #337ab7;\n border-color: #337ab7;\n cursor: default;\n}\n.pagination > .disabled > span,\n.pagination > .disabled > span:hover,\n.pagination > .disabled > span:focus,\n.pagination > .disabled > a,\n.pagination > .disabled > a:hover,\n.pagination > .disabled > a:focus {\n color: #777777;\n background-color: #fff;\n border-color: #ddd;\n cursor: not-allowed;\n}\n.pagination-lg > li > a,\n.pagination-lg > li > span {\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n}\n.pagination-lg > li:first-child > a,\n.pagination-lg > li:first-child > span {\n border-bottom-left-radius: 6px;\n border-top-left-radius: 6px;\n}\n.pagination-lg > li:last-child > a,\n.pagination-lg > li:last-child > span {\n border-bottom-right-radius: 6px;\n border-top-right-radius: 6px;\n}\n.pagination-sm > li > a,\n.pagination-sm > li > span {\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n}\n.pagination-sm > li:first-child > a,\n.pagination-sm > li:first-child > span {\n border-bottom-left-radius: 3px;\n border-top-left-radius: 3px;\n}\n.pagination-sm > li:last-child > a,\n.pagination-sm > li:last-child > span {\n border-bottom-right-radius: 3px;\n border-top-right-radius: 3px;\n}\n.pager {\n padding-left: 0;\n margin: 20px 0;\n list-style: none;\n text-align: center;\n}\n.pager li {\n display: inline;\n}\n.pager li > a,\n.pager li > span {\n display: inline-block;\n padding: 5px 14px;\n background-color: #fff;\n border: 1px solid #ddd;\n border-radius: 15px;\n}\n.pager li > a:hover,\n.pager li > a:focus {\n text-decoration: none;\n background-color: #eeeeee;\n}\n.pager .next > a,\n.pager .next > span {\n float: right;\n}\n.pager .previous > a,\n.pager .previous > span {\n float: left;\n}\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > a:focus,\n.pager .disabled > span {\n color: #777777;\n background-color: #fff;\n cursor: not-allowed;\n}\n.label {\n display: inline;\n padding: .2em .6em .3em;\n font-size: 75%;\n font-weight: bold;\n line-height: 1;\n color: #fff;\n text-align: center;\n white-space: nowrap;\n vertical-align: baseline;\n border-radius: .25em;\n}\na.label:hover,\na.label:focus {\n color: #fff;\n text-decoration: none;\n cursor: pointer;\n}\n.label:empty {\n display: none;\n}\n.btn .label {\n position: relative;\n top: -1px;\n}\n.label-default {\n background-color: #777777;\n}\n.label-default[href]:hover,\n.label-default[href]:focus {\n background-color: #5e5e5e;\n}\n.label-primary {\n background-color: #337ab7;\n}\n.label-primary[href]:hover,\n.label-primary[href]:focus {\n background-color: #286090;\n}\n.label-success {\n background-color: #5cb85c;\n}\n.label-success[href]:hover,\n.label-success[href]:focus {\n background-color: #449d44;\n}\n.label-info {\n background-color: #5bc0de;\n}\n.label-info[href]:hover,\n.label-info[href]:focus {\n background-color: #31b0d5;\n}\n.label-warning {\n background-color: #f0ad4e;\n}\n.label-warning[href]:hover,\n.label-warning[href]:focus {\n background-color: #ec971f;\n}\n.label-danger {\n background-color: #d9534f;\n}\n.label-danger[href]:hover,\n.label-danger[href]:focus {\n background-color: #c9302c;\n}\n.badge {\n display: inline-block;\n min-width: 10px;\n padding: 3px 7px;\n font-size: 12px;\n font-weight: bold;\n color: #fff;\n line-height: 1;\n vertical-align: middle;\n white-space: nowrap;\n text-align: center;\n background-color: #777777;\n border-radius: 10px;\n}\n.badge:empty {\n display: none;\n}\n.btn .badge {\n position: relative;\n top: -1px;\n}\n.btn-xs .badge,\n.btn-group-xs > .btn .badge {\n top: 0;\n padding: 1px 5px;\n}\na.badge:hover,\na.badge:focus {\n color: #fff;\n text-decoration: none;\n cursor: pointer;\n}\n.list-group-item.active > .badge,\n.nav-pills > .active > a > .badge {\n color: #337ab7;\n background-color: #fff;\n}\n.list-group-item > .badge {\n float: right;\n}\n.list-group-item > .badge + .badge {\n margin-right: 5px;\n}\n.nav-pills > li > a > .badge {\n margin-left: 3px;\n}\n.jumbotron {\n padding-top: 30px;\n padding-bottom: 30px;\n margin-bottom: 30px;\n color: inherit;\n background-color: #eeeeee;\n}\n.jumbotron h1,\n.jumbotron .h1 {\n color: inherit;\n}\n.jumbotron p {\n margin-bottom: 15px;\n font-size: 21px;\n font-weight: 200;\n}\n.jumbotron > hr {\n border-top-color: #d5d5d5;\n}\n.container .jumbotron,\n.container-fluid .jumbotron {\n border-radius: 6px;\n padding-left: 15px;\n padding-right: 15px;\n}\n.jumbotron .container {\n max-width: 100%;\n}\n@media screen and (min-width: 768px) {\n .jumbotron {\n padding-top: 48px;\n padding-bottom: 48px;\n }\n .container .jumbotron,\n .container-fluid .jumbotron {\n padding-left: 60px;\n padding-right: 60px;\n }\n .jumbotron h1,\n .jumbotron .h1 {\n font-size: 63px;\n }\n}\n.thumbnail {\n display: block;\n padding: 4px;\n margin-bottom: 20px;\n line-height: 1.42857143;\n background-color: #fff;\n border: 1px solid #ddd;\n border-radius: 4px;\n -webkit-transition: border 0.2s ease-in-out;\n -o-transition: border 0.2s ease-in-out;\n transition: border 0.2s ease-in-out;\n}\n.thumbnail > img,\n.thumbnail a > img {\n margin-left: auto;\n margin-right: auto;\n}\na.thumbnail:hover,\na.thumbnail:focus,\na.thumbnail.active {\n border-color: #337ab7;\n}\n.thumbnail .caption {\n padding: 9px;\n color: #333333;\n}\n.alert {\n padding: 15px;\n margin-bottom: 20px;\n border: 1px solid transparent;\n border-radius: 4px;\n}\n.alert h4 {\n margin-top: 0;\n color: inherit;\n}\n.alert .alert-link {\n font-weight: bold;\n}\n.alert > p,\n.alert > ul {\n margin-bottom: 0;\n}\n.alert > p + p {\n margin-top: 5px;\n}\n.alert-dismissable,\n.alert-dismissible {\n padding-right: 35px;\n}\n.alert-dismissable .close,\n.alert-dismissible .close {\n position: relative;\n top: -2px;\n right: -21px;\n color: inherit;\n}\n.alert-success {\n background-color: #dff0d8;\n border-color: #d6e9c6;\n color: #3c763d;\n}\n.alert-success hr {\n border-top-color: #c9e2b3;\n}\n.alert-success .alert-link {\n color: #2b542c;\n}\n.alert-info {\n background-color: #d9edf7;\n border-color: #bce8f1;\n color: #31708f;\n}\n.alert-info hr {\n border-top-color: #a6e1ec;\n}\n.alert-info .alert-link {\n color: #245269;\n}\n.alert-warning {\n background-color: #fcf8e3;\n border-color: #faebcc;\n color: #8a6d3b;\n}\n.alert-warning hr {\n border-top-color: #f7e1b5;\n}\n.alert-warning .alert-link {\n color: #66512c;\n}\n.alert-danger {\n background-color: #f2dede;\n border-color: #ebccd1;\n color: #a94442;\n}\n.alert-danger hr {\n border-top-color: #e4b9c0;\n}\n.alert-danger .alert-link {\n color: #843534;\n}\n@-webkit-keyframes progress-bar-stripes {\n from {\n background-position: 40px 0;\n }\n to {\n background-position: 0 0;\n }\n}\n@keyframes progress-bar-stripes {\n from {\n background-position: 40px 0;\n }\n to {\n background-position: 0 0;\n }\n}\n.progress {\n overflow: hidden;\n height: 20px;\n margin-bottom: 20px;\n background-color: #f5f5f5;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n.progress-bar {\n float: left;\n width: 0%;\n height: 100%;\n font-size: 12px;\n line-height: 20px;\n color: #fff;\n text-align: center;\n background-color: #337ab7;\n -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n -webkit-transition: width 0.6s ease;\n -o-transition: width 0.6s ease;\n transition: width 0.6s ease;\n}\n.progress-striped .progress-bar,\n.progress-bar-striped {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-size: 40px 40px;\n}\n.progress.active .progress-bar,\n.progress-bar.active {\n -webkit-animation: progress-bar-stripes 2s linear infinite;\n -o-animation: progress-bar-stripes 2s linear infinite;\n animation: progress-bar-stripes 2s linear infinite;\n}\n.progress-bar-success {\n background-color: #5cb85c;\n}\n.progress-striped .progress-bar-success {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-info {\n background-color: #5bc0de;\n}\n.progress-striped .progress-bar-info {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-warning {\n background-color: #f0ad4e;\n}\n.progress-striped .progress-bar-warning {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-danger {\n background-color: #d9534f;\n}\n.progress-striped .progress-bar-danger {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.media {\n margin-top: 15px;\n}\n.media:first-child {\n margin-top: 0;\n}\n.media,\n.media-body {\n zoom: 1;\n overflow: hidden;\n}\n.media-body {\n width: 10000px;\n}\n.media-object {\n display: block;\n}\n.media-object.img-thumbnail {\n max-width: none;\n}\n.media-right,\n.media > .pull-right {\n padding-left: 10px;\n}\n.media-left,\n.media > .pull-left {\n padding-right: 10px;\n}\n.media-left,\n.media-right,\n.media-body {\n display: table-cell;\n vertical-align: top;\n}\n.media-middle {\n vertical-align: middle;\n}\n.media-bottom {\n vertical-align: bottom;\n}\n.media-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n.media-list {\n padding-left: 0;\n list-style: none;\n}\n.list-group {\n margin-bottom: 20px;\n padding-left: 0;\n}\n.list-group-item {\n position: relative;\n display: block;\n padding: 10px 15px;\n margin-bottom: -1px;\n background-color: #fff;\n border: 1px solid #ddd;\n}\n.list-group-item:first-child {\n border-top-right-radius: 4px;\n border-top-left-radius: 4px;\n}\n.list-group-item:last-child {\n margin-bottom: 0;\n border-bottom-right-radius: 4px;\n border-bottom-left-radius: 4px;\n}\na.list-group-item,\nbutton.list-group-item {\n color: #555;\n}\na.list-group-item .list-group-item-heading,\nbutton.list-group-item .list-group-item-heading {\n color: #333;\n}\na.list-group-item:hover,\nbutton.list-group-item:hover,\na.list-group-item:focus,\nbutton.list-group-item:focus {\n text-decoration: none;\n color: #555;\n background-color: #f5f5f5;\n}\nbutton.list-group-item {\n width: 100%;\n text-align: left;\n}\n.list-group-item.disabled,\n.list-group-item.disabled:hover,\n.list-group-item.disabled:focus {\n background-color: #eeeeee;\n color: #777777;\n cursor: not-allowed;\n}\n.list-group-item.disabled .list-group-item-heading,\n.list-group-item.disabled:hover .list-group-item-heading,\n.list-group-item.disabled:focus .list-group-item-heading {\n color: inherit;\n}\n.list-group-item.disabled .list-group-item-text,\n.list-group-item.disabled:hover .list-group-item-text,\n.list-group-item.disabled:focus .list-group-item-text {\n color: #777777;\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n z-index: 2;\n color: #fff;\n background-color: #337ab7;\n border-color: #337ab7;\n}\n.list-group-item.active .list-group-item-heading,\n.list-group-item.active:hover .list-group-item-heading,\n.list-group-item.active:focus .list-group-item-heading,\n.list-group-item.active .list-group-item-heading > small,\n.list-group-item.active:hover .list-group-item-heading > small,\n.list-group-item.active:focus .list-group-item-heading > small,\n.list-group-item.active .list-group-item-heading > .small,\n.list-group-item.active:hover .list-group-item-heading > .small,\n.list-group-item.active:focus .list-group-item-heading > .small {\n color: inherit;\n}\n.list-group-item.active .list-group-item-text,\n.list-group-item.active:hover .list-group-item-text,\n.list-group-item.active:focus .list-group-item-text {\n color: #c7ddef;\n}\n.list-group-item-success {\n color: #3c763d;\n background-color: #dff0d8;\n}\na.list-group-item-success,\nbutton.list-group-item-success {\n color: #3c763d;\n}\na.list-group-item-success .list-group-item-heading,\nbutton.list-group-item-success .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-success:hover,\nbutton.list-group-item-success:hover,\na.list-group-item-success:focus,\nbutton.list-group-item-success:focus {\n color: #3c763d;\n background-color: #d0e9c6;\n}\na.list-group-item-success.active,\nbutton.list-group-item-success.active,\na.list-group-item-success.active:hover,\nbutton.list-group-item-success.active:hover,\na.list-group-item-success.active:focus,\nbutton.list-group-item-success.active:focus {\n color: #fff;\n background-color: #3c763d;\n border-color: #3c763d;\n}\n.list-group-item-info {\n color: #31708f;\n background-color: #d9edf7;\n}\na.list-group-item-info,\nbutton.list-group-item-info {\n color: #31708f;\n}\na.list-group-item-info .list-group-item-heading,\nbutton.list-group-item-info .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-info:hover,\nbutton.list-group-item-info:hover,\na.list-group-item-info:focus,\nbutton.list-group-item-info:focus {\n color: #31708f;\n background-color: #c4e3f3;\n}\na.list-group-item-info.active,\nbutton.list-group-item-info.active,\na.list-group-item-info.active:hover,\nbutton.list-group-item-info.active:hover,\na.list-group-item-info.active:focus,\nbutton.list-group-item-info.active:focus {\n color: #fff;\n background-color: #31708f;\n border-color: #31708f;\n}\n.list-group-item-warning {\n color: #8a6d3b;\n background-color: #fcf8e3;\n}\na.list-group-item-warning,\nbutton.list-group-item-warning {\n color: #8a6d3b;\n}\na.list-group-item-warning .list-group-item-heading,\nbutton.list-group-item-warning .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-warning:hover,\nbutton.list-group-item-warning:hover,\na.list-group-item-warning:focus,\nbutton.list-group-item-warning:focus {\n color: #8a6d3b;\n background-color: #faf2cc;\n}\na.list-group-item-warning.active,\nbutton.list-group-item-warning.active,\na.list-group-item-warning.active:hover,\nbutton.list-group-item-warning.active:hover,\na.list-group-item-warning.active:focus,\nbutton.list-group-item-warning.active:focus {\n color: #fff;\n background-color: #8a6d3b;\n border-color: #8a6d3b;\n}\n.list-group-item-danger {\n color: #a94442;\n background-color: #f2dede;\n}\na.list-group-item-danger,\nbutton.list-group-item-danger {\n color: #a94442;\n}\na.list-group-item-danger .list-group-item-heading,\nbutton.list-group-item-danger .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-danger:hover,\nbutton.list-group-item-danger:hover,\na.list-group-item-danger:focus,\nbutton.list-group-item-danger:focus {\n color: #a94442;\n background-color: #ebcccc;\n}\na.list-group-item-danger.active,\nbutton.list-group-item-danger.active,\na.list-group-item-danger.active:hover,\nbutton.list-group-item-danger.active:hover,\na.list-group-item-danger.active:focus,\nbutton.list-group-item-danger.active:focus {\n color: #fff;\n background-color: #a94442;\n border-color: #a94442;\n}\n.list-group-item-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n.list-group-item-text {\n margin-bottom: 0;\n line-height: 1.3;\n}\n.panel {\n margin-bottom: 20px;\n background-color: #fff;\n border: 1px solid transparent;\n border-radius: 4px;\n -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\n box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n.panel-body {\n padding: 15px;\n}\n.panel-heading {\n padding: 10px 15px;\n border-bottom: 1px solid transparent;\n border-top-right-radius: 3px;\n border-top-left-radius: 3px;\n}\n.panel-heading > .dropdown .dropdown-toggle {\n color: inherit;\n}\n.panel-title {\n margin-top: 0;\n margin-bottom: 0;\n font-size: 16px;\n color: inherit;\n}\n.panel-title > a,\n.panel-title > small,\n.panel-title > .small,\n.panel-title > small > a,\n.panel-title > .small > a {\n color: inherit;\n}\n.panel-footer {\n padding: 10px 15px;\n background-color: #f5f5f5;\n border-top: 1px solid #ddd;\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .list-group,\n.panel > .panel-collapse > .list-group {\n margin-bottom: 0;\n}\n.panel > .list-group .list-group-item,\n.panel > .panel-collapse > .list-group .list-group-item {\n border-width: 1px 0;\n border-radius: 0;\n}\n.panel > .list-group:first-child .list-group-item:first-child,\n.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child {\n border-top: 0;\n border-top-right-radius: 3px;\n border-top-left-radius: 3px;\n}\n.panel > .list-group:last-child .list-group-item:last-child,\n.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child {\n border-bottom: 0;\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .panel-heading + .panel-collapse > .list-group .list-group-item:first-child {\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.panel-heading + .list-group .list-group-item:first-child {\n border-top-width: 0;\n}\n.list-group + .panel-footer {\n border-top-width: 0;\n}\n.panel > .table,\n.panel > .table-responsive > .table,\n.panel > .panel-collapse > .table {\n margin-bottom: 0;\n}\n.panel > .table caption,\n.panel > .table-responsive > .table caption,\n.panel > .panel-collapse > .table caption {\n padding-left: 15px;\n padding-right: 15px;\n}\n.panel > .table:first-child,\n.panel > .table-responsive:first-child > .table:first-child {\n border-top-right-radius: 3px;\n border-top-left-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child {\n border-top-left-radius: 3px;\n border-top-right-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child td:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child,\n.panel > .table:first-child > thead:first-child > tr:first-child th:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child {\n border-top-left-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child td:last-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child,\n.panel > .table:first-child > thead:first-child > tr:first-child th:last-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child {\n border-top-right-radius: 3px;\n}\n.panel > .table:last-child,\n.panel > .table-responsive:last-child > .table:last-child {\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child {\n border-bottom-left-radius: 3px;\n border-bottom-right-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child {\n border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child {\n border-bottom-right-radius: 3px;\n}\n.panel > .panel-body + .table,\n.panel > .panel-body + .table-responsive,\n.panel > .table + .panel-body,\n.panel > .table-responsive + .panel-body {\n border-top: 1px solid #ddd;\n}\n.panel > .table > tbody:first-child > tr:first-child th,\n.panel > .table > tbody:first-child > tr:first-child td {\n border-top: 0;\n}\n.panel > .table-bordered,\n.panel > .table-responsive > .table-bordered {\n border: 0;\n}\n.panel > .table-bordered > thead > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > thead > tr > th:first-child,\n.panel > .table-bordered > tbody > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child,\n.panel > .table-bordered > tfoot > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n.panel > .table-bordered > thead > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > thead > tr > td:first-child,\n.panel > .table-bordered > tbody > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child,\n.panel > .table-bordered > tfoot > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n border-left: 0;\n}\n.panel > .table-bordered > thead > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > thead > tr > th:last-child,\n.panel > .table-bordered > tbody > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child,\n.panel > .table-bordered > tfoot > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n.panel > .table-bordered > thead > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > thead > tr > td:last-child,\n.panel > .table-bordered > tbody > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child,\n.panel > .table-bordered > tfoot > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n border-right: 0;\n}\n.panel > .table-bordered > thead > tr:first-child > td,\n.panel > .table-responsive > .table-bordered > thead > tr:first-child > td,\n.panel > .table-bordered > tbody > tr:first-child > td,\n.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td,\n.panel > .table-bordered > thead > tr:first-child > th,\n.panel > .table-responsive > .table-bordered > thead > tr:first-child > th,\n.panel > .table-bordered > tbody > tr:first-child > th,\n.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th {\n border-bottom: 0;\n}\n.panel > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-bordered > tfoot > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td,\n.panel > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-bordered > tfoot > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th {\n border-bottom: 0;\n}\n.panel > .table-responsive {\n border: 0;\n margin-bottom: 0;\n}\n.panel-group {\n margin-bottom: 20px;\n}\n.panel-group .panel {\n margin-bottom: 0;\n border-radius: 4px;\n}\n.panel-group .panel + .panel {\n margin-top: 5px;\n}\n.panel-group .panel-heading {\n border-bottom: 0;\n}\n.panel-group .panel-heading + .panel-collapse > .panel-body,\n.panel-group .panel-heading + .panel-collapse > .list-group {\n border-top: 1px solid #ddd;\n}\n.panel-group .panel-footer {\n border-top: 0;\n}\n.panel-group .panel-footer + .panel-collapse .panel-body {\n border-bottom: 1px solid #ddd;\n}\n.panel-default {\n border-color: #ddd;\n}\n.panel-default > .panel-heading {\n color: #333333;\n background-color: #f5f5f5;\n border-color: #ddd;\n}\n.panel-default > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #ddd;\n}\n.panel-default > .panel-heading .badge {\n color: #f5f5f5;\n background-color: #333333;\n}\n.panel-default > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #ddd;\n}\n.panel-primary {\n border-color: #337ab7;\n}\n.panel-primary > .panel-heading {\n color: #fff;\n background-color: #337ab7;\n border-color: #337ab7;\n}\n.panel-primary > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #337ab7;\n}\n.panel-primary > .panel-heading .badge {\n color: #337ab7;\n background-color: #fff;\n}\n.panel-primary > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #337ab7;\n}\n.panel-success {\n border-color: #d6e9c6;\n}\n.panel-success > .panel-heading {\n color: #3c763d;\n background-color: #dff0d8;\n border-color: #d6e9c6;\n}\n.panel-success > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #d6e9c6;\n}\n.panel-success > .panel-heading .badge {\n color: #dff0d8;\n background-color: #3c763d;\n}\n.panel-success > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #d6e9c6;\n}\n.panel-info {\n border-color: #bce8f1;\n}\n.panel-info > .panel-heading {\n color: #31708f;\n background-color: #d9edf7;\n border-color: #bce8f1;\n}\n.panel-info > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #bce8f1;\n}\n.panel-info > .panel-heading .badge {\n color: #d9edf7;\n background-color: #31708f;\n}\n.panel-info > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #bce8f1;\n}\n.panel-warning {\n border-color: #faebcc;\n}\n.panel-warning > .panel-heading {\n color: #8a6d3b;\n background-color: #fcf8e3;\n border-color: #faebcc;\n}\n.panel-warning > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #faebcc;\n}\n.panel-warning > .panel-heading .badge {\n color: #fcf8e3;\n background-color: #8a6d3b;\n}\n.panel-warning > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #faebcc;\n}\n.panel-danger {\n border-color: #ebccd1;\n}\n.panel-danger > .panel-heading {\n color: #a94442;\n background-color: #f2dede;\n border-color: #ebccd1;\n}\n.panel-danger > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #ebccd1;\n}\n.panel-danger > .panel-heading .badge {\n color: #f2dede;\n background-color: #a94442;\n}\n.panel-danger > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #ebccd1;\n}\n.embed-responsive {\n position: relative;\n display: block;\n height: 0;\n padding: 0;\n overflow: hidden;\n}\n.embed-responsive .embed-responsive-item,\n.embed-responsive iframe,\n.embed-responsive embed,\n.embed-responsive object,\n.embed-responsive video {\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n height: 100%;\n width: 100%;\n border: 0;\n}\n.embed-responsive-16by9 {\n padding-bottom: 56.25%;\n}\n.embed-responsive-4by3 {\n padding-bottom: 75%;\n}\n.well {\n min-height: 20px;\n padding: 19px;\n margin-bottom: 20px;\n background-color: #f5f5f5;\n border: 1px solid #e3e3e3;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n.well blockquote {\n border-color: #ddd;\n border-color: rgba(0, 0, 0, 0.15);\n}\n.well-lg {\n padding: 24px;\n border-radius: 6px;\n}\n.well-sm {\n padding: 9px;\n border-radius: 3px;\n}\n.close {\n float: right;\n font-size: 21px;\n font-weight: bold;\n line-height: 1;\n color: #000;\n text-shadow: 0 1px 0 #fff;\n opacity: 0.2;\n filter: alpha(opacity=20);\n}\n.close:hover,\n.close:focus {\n color: #000;\n text-decoration: none;\n cursor: pointer;\n opacity: 0.5;\n filter: alpha(opacity=50);\n}\nbutton.close {\n padding: 0;\n cursor: pointer;\n background: transparent;\n border: 0;\n -webkit-appearance: none;\n}\n.modal-open {\n overflow: hidden;\n}\n.modal {\n display: none;\n overflow: hidden;\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1050;\n -webkit-overflow-scrolling: touch;\n outline: 0;\n}\n.modal.fade .modal-dialog {\n -webkit-transform: translate(0, -25%);\n -ms-transform: translate(0, -25%);\n -o-transform: translate(0, -25%);\n transform: translate(0, -25%);\n -webkit-transition: -webkit-transform 0.3s ease-out;\n -moz-transition: -moz-transform 0.3s ease-out;\n -o-transition: -o-transform 0.3s ease-out;\n transition: transform 0.3s ease-out;\n}\n.modal.in .modal-dialog {\n -webkit-transform: translate(0, 0);\n -ms-transform: translate(0, 0);\n -o-transform: translate(0, 0);\n transform: translate(0, 0);\n}\n.modal-open .modal {\n overflow-x: hidden;\n overflow-y: auto;\n}\n.modal-dialog {\n position: relative;\n width: auto;\n margin: 10px;\n}\n.modal-content {\n position: relative;\n background-color: #fff;\n border: 1px solid #999;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 6px;\n -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);\n box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);\n background-clip: padding-box;\n outline: 0;\n}\n.modal-backdrop {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1040;\n background-color: #000;\n}\n.modal-backdrop.fade {\n opacity: 0;\n filter: alpha(opacity=0);\n}\n.modal-backdrop.in {\n opacity: 0.5;\n filter: alpha(opacity=50);\n}\n.modal-header {\n padding: 15px;\n border-bottom: 1px solid #e5e5e5;\n}\n.modal-header .close {\n margin-top: -2px;\n}\n.modal-title {\n margin: 0;\n line-height: 1.42857143;\n}\n.modal-body {\n position: relative;\n padding: 15px;\n}\n.modal-footer {\n padding: 15px;\n text-align: right;\n border-top: 1px solid #e5e5e5;\n}\n.modal-footer .btn + .btn {\n margin-left: 5px;\n margin-bottom: 0;\n}\n.modal-footer .btn-group .btn + .btn {\n margin-left: -1px;\n}\n.modal-footer .btn-block + .btn-block {\n margin-left: 0;\n}\n.modal-scrollbar-measure {\n position: absolute;\n top: -9999px;\n width: 50px;\n height: 50px;\n overflow: scroll;\n}\n@media (min-width: 768px) {\n .modal-dialog {\n width: 600px;\n margin: 30px auto;\n }\n .modal-content {\n -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);\n box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);\n }\n .modal-sm {\n width: 300px;\n }\n}\n@media (min-width: 992px) {\n .modal-lg {\n width: 900px;\n }\n}\n.tooltip {\n position: absolute;\n z-index: 1070;\n display: block;\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-style: normal;\n font-weight: normal;\n letter-spacing: normal;\n line-break: auto;\n line-height: 1.42857143;\n text-align: left;\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n white-space: normal;\n word-break: normal;\n word-spacing: normal;\n word-wrap: normal;\n font-size: 12px;\n opacity: 0;\n filter: alpha(opacity=0);\n}\n.tooltip.in {\n opacity: 0.9;\n filter: alpha(opacity=90);\n}\n.tooltip.top {\n margin-top: -3px;\n padding: 5px 0;\n}\n.tooltip.right {\n margin-left: 3px;\n padding: 0 5px;\n}\n.tooltip.bottom {\n margin-top: 3px;\n padding: 5px 0;\n}\n.tooltip.left {\n margin-left: -3px;\n padding: 0 5px;\n}\n.tooltip-inner {\n max-width: 200px;\n padding: 3px 8px;\n color: #fff;\n text-align: center;\n background-color: #000;\n border-radius: 4px;\n}\n.tooltip-arrow {\n position: absolute;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n}\n.tooltip.top .tooltip-arrow {\n bottom: 0;\n left: 50%;\n margin-left: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000;\n}\n.tooltip.top-left .tooltip-arrow {\n bottom: 0;\n right: 5px;\n margin-bottom: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000;\n}\n.tooltip.top-right .tooltip-arrow {\n bottom: 0;\n left: 5px;\n margin-bottom: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000;\n}\n.tooltip.right .tooltip-arrow {\n top: 50%;\n left: 0;\n margin-top: -5px;\n border-width: 5px 5px 5px 0;\n border-right-color: #000;\n}\n.tooltip.left .tooltip-arrow {\n top: 50%;\n right: 0;\n margin-top: -5px;\n border-width: 5px 0 5px 5px;\n border-left-color: #000;\n}\n.tooltip.bottom .tooltip-arrow {\n top: 0;\n left: 50%;\n margin-left: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000;\n}\n.tooltip.bottom-left .tooltip-arrow {\n top: 0;\n right: 5px;\n margin-top: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000;\n}\n.tooltip.bottom-right .tooltip-arrow {\n top: 0;\n left: 5px;\n margin-top: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000;\n}\n.popover {\n position: absolute;\n top: 0;\n left: 0;\n z-index: 1060;\n display: none;\n max-width: 276px;\n padding: 1px;\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-style: normal;\n font-weight: normal;\n letter-spacing: normal;\n line-break: auto;\n line-height: 1.42857143;\n text-align: left;\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n white-space: normal;\n word-break: normal;\n word-spacing: normal;\n word-wrap: normal;\n font-size: 14px;\n background-color: #fff;\n background-clip: padding-box;\n border: 1px solid #ccc;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 6px;\n -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n}\n.popover.top {\n margin-top: -10px;\n}\n.popover.right {\n margin-left: 10px;\n}\n.popover.bottom {\n margin-top: 10px;\n}\n.popover.left {\n margin-left: -10px;\n}\n.popover-title {\n margin: 0;\n padding: 8px 14px;\n font-size: 14px;\n background-color: #f7f7f7;\n border-bottom: 1px solid #ebebeb;\n border-radius: 5px 5px 0 0;\n}\n.popover-content {\n padding: 9px 14px;\n}\n.popover > .arrow,\n.popover > .arrow:after {\n position: absolute;\n display: block;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n}\n.popover > .arrow {\n border-width: 11px;\n}\n.popover > .arrow:after {\n border-width: 10px;\n content: \"\";\n}\n.popover.top > .arrow {\n left: 50%;\n margin-left: -11px;\n border-bottom-width: 0;\n border-top-color: #999999;\n border-top-color: rgba(0, 0, 0, 0.25);\n bottom: -11px;\n}\n.popover.top > .arrow:after {\n content: \" \";\n bottom: 1px;\n margin-left: -10px;\n border-bottom-width: 0;\n border-top-color: #fff;\n}\n.popover.right > .arrow {\n top: 50%;\n left: -11px;\n margin-top: -11px;\n border-left-width: 0;\n border-right-color: #999999;\n border-right-color: rgba(0, 0, 0, 0.25);\n}\n.popover.right > .arrow:after {\n content: \" \";\n left: 1px;\n bottom: -10px;\n border-left-width: 0;\n border-right-color: #fff;\n}\n.popover.bottom > .arrow {\n left: 50%;\n margin-left: -11px;\n border-top-width: 0;\n border-bottom-color: #999999;\n border-bottom-color: rgba(0, 0, 0, 0.25);\n top: -11px;\n}\n.popover.bottom > .arrow:after {\n content: \" \";\n top: 1px;\n margin-left: -10px;\n border-top-width: 0;\n border-bottom-color: #fff;\n}\n.popover.left > .arrow {\n top: 50%;\n right: -11px;\n margin-top: -11px;\n border-right-width: 0;\n border-left-color: #999999;\n border-left-color: rgba(0, 0, 0, 0.25);\n}\n.popover.left > .arrow:after {\n content: \" \";\n right: 1px;\n border-right-width: 0;\n border-left-color: #fff;\n bottom: -10px;\n}\n.carousel {\n position: relative;\n}\n.carousel-inner {\n position: relative;\n overflow: hidden;\n width: 100%;\n}\n.carousel-inner > .item {\n display: none;\n position: relative;\n -webkit-transition: 0.6s ease-in-out left;\n -o-transition: 0.6s ease-in-out left;\n transition: 0.6s ease-in-out left;\n}\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n line-height: 1;\n}\n@media all and (transform-3d), (-webkit-transform-3d) {\n .carousel-inner > .item {\n -webkit-transition: -webkit-transform 0.6s ease-in-out;\n -moz-transition: -moz-transform 0.6s ease-in-out;\n -o-transition: -o-transform 0.6s ease-in-out;\n transition: transform 0.6s ease-in-out;\n -webkit-backface-visibility: hidden;\n -moz-backface-visibility: hidden;\n backface-visibility: hidden;\n -webkit-perspective: 1000px;\n -moz-perspective: 1000px;\n perspective: 1000px;\n }\n .carousel-inner > .item.next,\n .carousel-inner > .item.active.right {\n -webkit-transform: translate3d(100%, 0, 0);\n transform: translate3d(100%, 0, 0);\n left: 0;\n }\n .carousel-inner > .item.prev,\n .carousel-inner > .item.active.left {\n -webkit-transform: translate3d(-100%, 0, 0);\n transform: translate3d(-100%, 0, 0);\n left: 0;\n }\n .carousel-inner > .item.next.left,\n .carousel-inner > .item.prev.right,\n .carousel-inner > .item.active {\n -webkit-transform: translate3d(0, 0, 0);\n transform: translate3d(0, 0, 0);\n left: 0;\n }\n}\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n display: block;\n}\n.carousel-inner > .active {\n left: 0;\n}\n.carousel-inner > .next,\n.carousel-inner > .prev {\n position: absolute;\n top: 0;\n width: 100%;\n}\n.carousel-inner > .next {\n left: 100%;\n}\n.carousel-inner > .prev {\n left: -100%;\n}\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n left: 0;\n}\n.carousel-inner > .active.left {\n left: -100%;\n}\n.carousel-inner > .active.right {\n left: 100%;\n}\n.carousel-control {\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n width: 15%;\n opacity: 0.5;\n filter: alpha(opacity=50);\n font-size: 20px;\n color: #fff;\n text-align: center;\n text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);\n background-color: rgba(0, 0, 0, 0);\n}\n.carousel-control.left {\n background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);\n}\n.carousel-control.right {\n left: auto;\n right: 0;\n background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);\n}\n.carousel-control:hover,\n.carousel-control:focus {\n outline: 0;\n color: #fff;\n text-decoration: none;\n opacity: 0.9;\n filter: alpha(opacity=90);\n}\n.carousel-control .icon-prev,\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-left,\n.carousel-control .glyphicon-chevron-right {\n position: absolute;\n top: 50%;\n margin-top: -10px;\n z-index: 5;\n display: inline-block;\n}\n.carousel-control .icon-prev,\n.carousel-control .glyphicon-chevron-left {\n left: 50%;\n margin-left: -10px;\n}\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-right {\n right: 50%;\n margin-right: -10px;\n}\n.carousel-control .icon-prev,\n.carousel-control .icon-next {\n width: 20px;\n height: 20px;\n line-height: 1;\n font-family: serif;\n}\n.carousel-control .icon-prev:before {\n content: '\\2039';\n}\n.carousel-control .icon-next:before {\n content: '\\203a';\n}\n.carousel-indicators {\n position: absolute;\n bottom: 10px;\n left: 50%;\n z-index: 15;\n width: 60%;\n margin-left: -30%;\n padding-left: 0;\n list-style: none;\n text-align: center;\n}\n.carousel-indicators li {\n display: inline-block;\n width: 10px;\n height: 10px;\n margin: 1px;\n text-indent: -999px;\n border: 1px solid #fff;\n border-radius: 10px;\n cursor: pointer;\n background-color: #000 \\9;\n background-color: rgba(0, 0, 0, 0);\n}\n.carousel-indicators .active {\n margin: 0;\n width: 12px;\n height: 12px;\n background-color: #fff;\n}\n.carousel-caption {\n position: absolute;\n left: 15%;\n right: 15%;\n bottom: 20px;\n z-index: 10;\n padding-top: 20px;\n padding-bottom: 20px;\n color: #fff;\n text-align: center;\n text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);\n}\n.carousel-caption .btn {\n text-shadow: none;\n}\n@media screen and (min-width: 768px) {\n .carousel-control .glyphicon-chevron-left,\n .carousel-control .glyphicon-chevron-right,\n .carousel-control .icon-prev,\n .carousel-control .icon-next {\n width: 30px;\n height: 30px;\n margin-top: -10px;\n font-size: 30px;\n }\n .carousel-control .glyphicon-chevron-left,\n .carousel-control .icon-prev {\n margin-left: -10px;\n }\n .carousel-control .glyphicon-chevron-right,\n .carousel-control .icon-next {\n margin-right: -10px;\n }\n .carousel-caption {\n left: 20%;\n right: 20%;\n padding-bottom: 30px;\n }\n .carousel-indicators {\n bottom: 20px;\n }\n}\n.clearfix:before,\n.clearfix:after,\n.dl-horizontal dd:before,\n.dl-horizontal dd:after,\n.container:before,\n.container:after,\n.container-fluid:before,\n.container-fluid:after,\n.row:before,\n.row:after,\n.form-horizontal .form-group:before,\n.form-horizontal .form-group:after,\n.btn-toolbar:before,\n.btn-toolbar:after,\n.btn-group-vertical > .btn-group:before,\n.btn-group-vertical > .btn-group:after,\n.nav:before,\n.nav:after,\n.navbar:before,\n.navbar:after,\n.navbar-header:before,\n.navbar-header:after,\n.navbar-collapse:before,\n.navbar-collapse:after,\n.pager:before,\n.pager:after,\n.panel-body:before,\n.panel-body:after,\n.modal-header:before,\n.modal-header:after,\n.modal-footer:before,\n.modal-footer:after {\n content: \" \";\n display: table;\n}\n.clearfix:after,\n.dl-horizontal dd:after,\n.container:after,\n.container-fluid:after,\n.row:after,\n.form-horizontal .form-group:after,\n.btn-toolbar:after,\n.btn-group-vertical > .btn-group:after,\n.nav:after,\n.navbar:after,\n.navbar-header:after,\n.navbar-collapse:after,\n.pager:after,\n.panel-body:after,\n.modal-header:after,\n.modal-footer:after {\n clear: both;\n}\n.center-block {\n display: block;\n margin-left: auto;\n margin-right: auto;\n}\n.pull-right {\n float: right !important;\n}\n.pull-left {\n float: left !important;\n}\n.hide {\n display: none !important;\n}\n.show {\n display: block !important;\n}\n.invisible {\n visibility: hidden;\n}\n.text-hide {\n font: 0/0 a;\n color: transparent;\n text-shadow: none;\n background-color: transparent;\n border: 0;\n}\n.hidden {\n display: none !important;\n}\n.affix {\n position: fixed;\n}\n@-ms-viewport {\n width: device-width;\n}\n.visible-xs,\n.visible-sm,\n.visible-md,\n.visible-lg {\n display: none !important;\n}\n.visible-xs-block,\n.visible-xs-inline,\n.visible-xs-inline-block,\n.visible-sm-block,\n.visible-sm-inline,\n.visible-sm-inline-block,\n.visible-md-block,\n.visible-md-inline,\n.visible-md-inline-block,\n.visible-lg-block,\n.visible-lg-inline,\n.visible-lg-inline-block {\n display: none !important;\n}\n@media (max-width: 767px) {\n .visible-xs {\n display: block !important;\n }\n table.visible-xs {\n display: table !important;\n }\n tr.visible-xs {\n display: table-row !important;\n }\n th.visible-xs,\n td.visible-xs {\n display: table-cell !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-block {\n display: block !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-inline {\n display: inline !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm {\n display: block !important;\n }\n table.visible-sm {\n display: table !important;\n }\n tr.visible-sm {\n display: table-row !important;\n }\n th.visible-sm,\n td.visible-sm {\n display: table-cell !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-block {\n display: block !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-inline {\n display: inline !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md {\n display: block !important;\n }\n table.visible-md {\n display: table !important;\n }\n tr.visible-md {\n display: table-row !important;\n }\n th.visible-md,\n td.visible-md {\n display: table-cell !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-block {\n display: block !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-inline {\n display: inline !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg {\n display: block !important;\n }\n table.visible-lg {\n display: table !important;\n }\n tr.visible-lg {\n display: table-row !important;\n }\n th.visible-lg,\n td.visible-lg {\n display: table-cell !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-block {\n display: block !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-inline {\n display: inline !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-inline-block {\n display: inline-block !important;\n }\n}\n@media (max-width: 767px) {\n .hidden-xs {\n display: none !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .hidden-sm {\n display: none !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .hidden-md {\n display: none !important;\n }\n}\n@media (min-width: 1200px) {\n .hidden-lg {\n display: none !important;\n }\n}\n.visible-print {\n display: none !important;\n}\n@media print {\n .visible-print {\n display: block !important;\n }\n table.visible-print {\n display: table !important;\n }\n tr.visible-print {\n display: table-row !important;\n }\n th.visible-print,\n td.visible-print {\n display: table-cell !important;\n }\n}\n.visible-print-block {\n display: none !important;\n}\n@media print {\n .visible-print-block {\n display: block !important;\n }\n}\n.visible-print-inline {\n display: none !important;\n}\n@media print {\n .visible-print-inline {\n display: inline !important;\n }\n}\n.visible-print-inline-block {\n display: none !important;\n}\n@media print {\n .visible-print-inline-block {\n display: inline-block !important;\n }\n}\n@media print {\n .hidden-print {\n display: none !important;\n }\n}\n/*# sourceMappingURL=bootstrap.css.map */","/*!\n * Bootstrap v3.3.7 (http://getbootstrap.com)\n * Copyright 2011-2017 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */\nhtml {\n font-family: sans-serif;\n -webkit-text-size-adjust: 100%;\n -ms-text-size-adjust: 100%;\n}\nbody {\n margin: 0;\n}\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nmenu,\nnav,\nsection,\nsummary {\n display: block;\n}\naudio,\ncanvas,\nprogress,\nvideo {\n display: inline-block;\n vertical-align: baseline;\n}\naudio:not([controls]) {\n display: none;\n height: 0;\n}\n[hidden],\ntemplate {\n display: none;\n}\na {\n background-color: transparent;\n}\na:active,\na:hover {\n outline: 0;\n}\nabbr[title] {\n border-bottom: 1px dotted;\n}\nb,\nstrong {\n font-weight: bold;\n}\ndfn {\n font-style: italic;\n}\nh1 {\n margin: .67em 0;\n font-size: 2em;\n}\nmark {\n color: #000;\n background: #ff0;\n}\nsmall {\n font-size: 80%;\n}\nsub,\nsup {\n position: relative;\n font-size: 75%;\n line-height: 0;\n vertical-align: baseline;\n}\nsup {\n top: -.5em;\n}\nsub {\n bottom: -.25em;\n}\nimg {\n border: 0;\n}\nsvg:not(:root) {\n overflow: hidden;\n}\nfigure {\n margin: 1em 40px;\n}\nhr {\n height: 0;\n -webkit-box-sizing: content-box;\n -moz-box-sizing: content-box;\n box-sizing: content-box;\n}\npre {\n overflow: auto;\n}\ncode,\nkbd,\npre,\nsamp {\n font-family: monospace, monospace;\n font-size: 1em;\n}\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n margin: 0;\n font: inherit;\n color: inherit;\n}\nbutton {\n overflow: visible;\n}\nbutton,\nselect {\n text-transform: none;\n}\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n -webkit-appearance: button;\n cursor: pointer;\n}\nbutton[disabled],\nhtml input[disabled] {\n cursor: default;\n}\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n padding: 0;\n border: 0;\n}\ninput {\n line-height: normal;\n}\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n padding: 0;\n}\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\ninput[type=\"search\"] {\n -webkit-box-sizing: content-box;\n -moz-box-sizing: content-box;\n box-sizing: content-box;\n -webkit-appearance: textfield;\n}\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\nfieldset {\n padding: .35em .625em .75em;\n margin: 0 2px;\n border: 1px solid #c0c0c0;\n}\nlegend {\n padding: 0;\n border: 0;\n}\ntextarea {\n overflow: auto;\n}\noptgroup {\n font-weight: bold;\n}\ntable {\n border-spacing: 0;\n border-collapse: collapse;\n}\ntd,\nth {\n padding: 0;\n}\n/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */\n@media print {\n *,\n *:before,\n *:after {\n color: #000 !important;\n text-shadow: none !important;\n background: transparent !important;\n -webkit-box-shadow: none !important;\n box-shadow: none !important;\n }\n a,\n a:visited {\n text-decoration: underline;\n }\n a[href]:after {\n content: \" (\" attr(href) \")\";\n }\n abbr[title]:after {\n content: \" (\" attr(title) \")\";\n }\n a[href^=\"#\"]:after,\n a[href^=\"javascript:\"]:after {\n content: \"\";\n }\n pre,\n blockquote {\n border: 1px solid #999;\n\n page-break-inside: avoid;\n }\n thead {\n display: table-header-group;\n }\n tr,\n img {\n page-break-inside: avoid;\n }\n img {\n max-width: 100% !important;\n }\n p,\n h2,\n h3 {\n orphans: 3;\n widows: 3;\n }\n h2,\n h3 {\n page-break-after: avoid;\n }\n .navbar {\n display: none;\n }\n .btn > .caret,\n .dropup > .btn > .caret {\n border-top-color: #000 !important;\n }\n .label {\n border: 1px solid #000;\n }\n .table {\n border-collapse: collapse !important;\n }\n .table td,\n .table th {\n background-color: #fff !important;\n }\n .table-bordered th,\n .table-bordered td {\n border: 1px solid #ddd !important;\n }\n}\n@font-face {\n font-family: 'Glyphicons Halflings';\n\n src: url('../fonts/glyphicons-halflings-regular.eot');\n src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');\n}\n.glyphicon {\n position: relative;\n top: 1px;\n display: inline-block;\n font-family: 'Glyphicons Halflings';\n font-style: normal;\n font-weight: normal;\n line-height: 1;\n\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n.glyphicon-asterisk:before {\n content: \"\\002a\";\n}\n.glyphicon-plus:before {\n content: \"\\002b\";\n}\n.glyphicon-euro:before,\n.glyphicon-eur:before {\n content: \"\\20ac\";\n}\n.glyphicon-minus:before {\n content: \"\\2212\";\n}\n.glyphicon-cloud:before {\n content: \"\\2601\";\n}\n.glyphicon-envelope:before {\n content: \"\\2709\";\n}\n.glyphicon-pencil:before {\n content: \"\\270f\";\n}\n.glyphicon-glass:before {\n content: \"\\e001\";\n}\n.glyphicon-music:before {\n content: \"\\e002\";\n}\n.glyphicon-search:before {\n content: \"\\e003\";\n}\n.glyphicon-heart:before {\n content: \"\\e005\";\n}\n.glyphicon-star:before {\n content: \"\\e006\";\n}\n.glyphicon-star-empty:before {\n content: \"\\e007\";\n}\n.glyphicon-user:before {\n content: \"\\e008\";\n}\n.glyphicon-film:before {\n content: \"\\e009\";\n}\n.glyphicon-th-large:before {\n content: \"\\e010\";\n}\n.glyphicon-th:before {\n content: \"\\e011\";\n}\n.glyphicon-th-list:before {\n content: \"\\e012\";\n}\n.glyphicon-ok:before {\n content: \"\\e013\";\n}\n.glyphicon-remove:before {\n content: \"\\e014\";\n}\n.glyphicon-zoom-in:before {\n content: \"\\e015\";\n}\n.glyphicon-zoom-out:before {\n content: \"\\e016\";\n}\n.glyphicon-off:before {\n content: \"\\e017\";\n}\n.glyphicon-signal:before {\n content: \"\\e018\";\n}\n.glyphicon-cog:before {\n content: \"\\e019\";\n}\n.glyphicon-trash:before {\n content: \"\\e020\";\n}\n.glyphicon-home:before {\n content: \"\\e021\";\n}\n.glyphicon-file:before {\n content: \"\\e022\";\n}\n.glyphicon-time:before {\n content: \"\\e023\";\n}\n.glyphicon-road:before {\n content: \"\\e024\";\n}\n.glyphicon-download-alt:before {\n content: \"\\e025\";\n}\n.glyphicon-download:before {\n content: \"\\e026\";\n}\n.glyphicon-upload:before {\n content: \"\\e027\";\n}\n.glyphicon-inbox:before {\n content: \"\\e028\";\n}\n.glyphicon-play-circle:before {\n content: \"\\e029\";\n}\n.glyphicon-repeat:before {\n content: \"\\e030\";\n}\n.glyphicon-refresh:before {\n content: \"\\e031\";\n}\n.glyphicon-list-alt:before {\n content: \"\\e032\";\n}\n.glyphicon-lock:before {\n content: \"\\e033\";\n}\n.glyphicon-flag:before {\n content: \"\\e034\";\n}\n.glyphicon-headphones:before {\n content: \"\\e035\";\n}\n.glyphicon-volume-off:before {\n content: \"\\e036\";\n}\n.glyphicon-volume-down:before {\n content: \"\\e037\";\n}\n.glyphicon-volume-up:before {\n content: \"\\e038\";\n}\n.glyphicon-qrcode:before {\n content: \"\\e039\";\n}\n.glyphicon-barcode:before {\n content: \"\\e040\";\n}\n.glyphicon-tag:before {\n content: \"\\e041\";\n}\n.glyphicon-tags:before {\n content: \"\\e042\";\n}\n.glyphicon-book:before {\n content: \"\\e043\";\n}\n.glyphicon-bookmark:before {\n content: \"\\e044\";\n}\n.glyphicon-print:before {\n content: \"\\e045\";\n}\n.glyphicon-camera:before {\n content: \"\\e046\";\n}\n.glyphicon-font:before {\n content: \"\\e047\";\n}\n.glyphicon-bold:before {\n content: \"\\e048\";\n}\n.glyphicon-italic:before {\n content: \"\\e049\";\n}\n.glyphicon-text-height:before {\n content: \"\\e050\";\n}\n.glyphicon-text-width:before {\n content: \"\\e051\";\n}\n.glyphicon-align-left:before {\n content: \"\\e052\";\n}\n.glyphicon-align-center:before {\n content: \"\\e053\";\n}\n.glyphicon-align-right:before {\n content: \"\\e054\";\n}\n.glyphicon-align-justify:before {\n content: \"\\e055\";\n}\n.glyphicon-list:before {\n content: \"\\e056\";\n}\n.glyphicon-indent-left:before {\n content: \"\\e057\";\n}\n.glyphicon-indent-right:before {\n content: \"\\e058\";\n}\n.glyphicon-facetime-video:before {\n content: \"\\e059\";\n}\n.glyphicon-picture:before {\n content: \"\\e060\";\n}\n.glyphicon-map-marker:before {\n content: \"\\e062\";\n}\n.glyphicon-adjust:before {\n content: \"\\e063\";\n}\n.glyphicon-tint:before {\n content: \"\\e064\";\n}\n.glyphicon-edit:before {\n content: \"\\e065\";\n}\n.glyphicon-share:before {\n content: \"\\e066\";\n}\n.glyphicon-check:before {\n content: \"\\e067\";\n}\n.glyphicon-move:before {\n content: \"\\e068\";\n}\n.glyphicon-step-backward:before {\n content: \"\\e069\";\n}\n.glyphicon-fast-backward:before {\n content: \"\\e070\";\n}\n.glyphicon-backward:before {\n content: \"\\e071\";\n}\n.glyphicon-play:before {\n content: \"\\e072\";\n}\n.glyphicon-pause:before {\n content: \"\\e073\";\n}\n.glyphicon-stop:before {\n content: \"\\e074\";\n}\n.glyphicon-forward:before {\n content: \"\\e075\";\n}\n.glyphicon-fast-forward:before {\n content: \"\\e076\";\n}\n.glyphicon-step-forward:before {\n content: \"\\e077\";\n}\n.glyphicon-eject:before {\n content: \"\\e078\";\n}\n.glyphicon-chevron-left:before {\n content: \"\\e079\";\n}\n.glyphicon-chevron-right:before {\n content: \"\\e080\";\n}\n.glyphicon-plus-sign:before {\n content: \"\\e081\";\n}\n.glyphicon-minus-sign:before {\n content: \"\\e082\";\n}\n.glyphicon-remove-sign:before {\n content: \"\\e083\";\n}\n.glyphicon-ok-sign:before {\n content: \"\\e084\";\n}\n.glyphicon-question-sign:before {\n content: \"\\e085\";\n}\n.glyphicon-info-sign:before {\n content: \"\\e086\";\n}\n.glyphicon-screenshot:before {\n content: \"\\e087\";\n}\n.glyphicon-remove-circle:before {\n content: \"\\e088\";\n}\n.glyphicon-ok-circle:before {\n content: \"\\e089\";\n}\n.glyphicon-ban-circle:before {\n content: \"\\e090\";\n}\n.glyphicon-arrow-left:before {\n content: \"\\e091\";\n}\n.glyphicon-arrow-right:before {\n content: \"\\e092\";\n}\n.glyphicon-arrow-up:before {\n content: \"\\e093\";\n}\n.glyphicon-arrow-down:before {\n content: \"\\e094\";\n}\n.glyphicon-share-alt:before {\n content: \"\\e095\";\n}\n.glyphicon-resize-full:before {\n content: \"\\e096\";\n}\n.glyphicon-resize-small:before {\n content: \"\\e097\";\n}\n.glyphicon-exclamation-sign:before {\n content: \"\\e101\";\n}\n.glyphicon-gift:before {\n content: \"\\e102\";\n}\n.glyphicon-leaf:before {\n content: \"\\e103\";\n}\n.glyphicon-fire:before {\n content: \"\\e104\";\n}\n.glyphicon-eye-open:before {\n content: \"\\e105\";\n}\n.glyphicon-eye-close:before {\n content: \"\\e106\";\n}\n.glyphicon-warning-sign:before {\n content: \"\\e107\";\n}\n.glyphicon-plane:before {\n content: \"\\e108\";\n}\n.glyphicon-calendar:before {\n content: \"\\e109\";\n}\n.glyphicon-random:before {\n content: \"\\e110\";\n}\n.glyphicon-comment:before {\n content: \"\\e111\";\n}\n.glyphicon-magnet:before {\n content: \"\\e112\";\n}\n.glyphicon-chevron-up:before {\n content: \"\\e113\";\n}\n.glyphicon-chevron-down:before {\n content: \"\\e114\";\n}\n.glyphicon-retweet:before {\n content: \"\\e115\";\n}\n.glyphicon-shopping-cart:before {\n content: \"\\e116\";\n}\n.glyphicon-folder-close:before {\n content: \"\\e117\";\n}\n.glyphicon-folder-open:before {\n content: \"\\e118\";\n}\n.glyphicon-resize-vertical:before {\n content: \"\\e119\";\n}\n.glyphicon-resize-horizontal:before {\n content: \"\\e120\";\n}\n.glyphicon-hdd:before {\n content: \"\\e121\";\n}\n.glyphicon-bullhorn:before {\n content: \"\\e122\";\n}\n.glyphicon-bell:before {\n content: \"\\e123\";\n}\n.glyphicon-certificate:before {\n content: \"\\e124\";\n}\n.glyphicon-thumbs-up:before {\n content: \"\\e125\";\n}\n.glyphicon-thumbs-down:before {\n content: \"\\e126\";\n}\n.glyphicon-hand-right:before {\n content: \"\\e127\";\n}\n.glyphicon-hand-left:before {\n content: \"\\e128\";\n}\n.glyphicon-hand-up:before {\n content: \"\\e129\";\n}\n.glyphicon-hand-down:before {\n content: \"\\e130\";\n}\n.glyphicon-circle-arrow-right:before {\n content: \"\\e131\";\n}\n.glyphicon-circle-arrow-left:before {\n content: \"\\e132\";\n}\n.glyphicon-circle-arrow-up:before {\n content: \"\\e133\";\n}\n.glyphicon-circle-arrow-down:before {\n content: \"\\e134\";\n}\n.glyphicon-globe:before {\n content: \"\\e135\";\n}\n.glyphicon-wrench:before {\n content: \"\\e136\";\n}\n.glyphicon-tasks:before {\n content: \"\\e137\";\n}\n.glyphicon-filter:before {\n content: \"\\e138\";\n}\n.glyphicon-briefcase:before {\n content: \"\\e139\";\n}\n.glyphicon-fullscreen:before {\n content: \"\\e140\";\n}\n.glyphicon-dashboard:before {\n content: \"\\e141\";\n}\n.glyphicon-paperclip:before {\n content: \"\\e142\";\n}\n.glyphicon-heart-empty:before {\n content: \"\\e143\";\n}\n.glyphicon-link:before {\n content: \"\\e144\";\n}\n.glyphicon-phone:before {\n content: \"\\e145\";\n}\n.glyphicon-pushpin:before {\n content: \"\\e146\";\n}\n.glyphicon-usd:before {\n content: \"\\e148\";\n}\n.glyphicon-gbp:before {\n content: \"\\e149\";\n}\n.glyphicon-sort:before {\n content: \"\\e150\";\n}\n.glyphicon-sort-by-alphabet:before {\n content: \"\\e151\";\n}\n.glyphicon-sort-by-alphabet-alt:before {\n content: \"\\e152\";\n}\n.glyphicon-sort-by-order:before {\n content: \"\\e153\";\n}\n.glyphicon-sort-by-order-alt:before {\n content: \"\\e154\";\n}\n.glyphicon-sort-by-attributes:before {\n content: \"\\e155\";\n}\n.glyphicon-sort-by-attributes-alt:before {\n content: \"\\e156\";\n}\n.glyphicon-unchecked:before {\n content: \"\\e157\";\n}\n.glyphicon-expand:before {\n content: \"\\e158\";\n}\n.glyphicon-collapse-down:before {\n content: \"\\e159\";\n}\n.glyphicon-collapse-up:before {\n content: \"\\e160\";\n}\n.glyphicon-log-in:before {\n content: \"\\e161\";\n}\n.glyphicon-flash:before {\n content: \"\\e162\";\n}\n.glyphicon-log-out:before {\n content: \"\\e163\";\n}\n.glyphicon-new-window:before {\n content: \"\\e164\";\n}\n.glyphicon-record:before {\n content: \"\\e165\";\n}\n.glyphicon-save:before {\n content: \"\\e166\";\n}\n.glyphicon-open:before {\n content: \"\\e167\";\n}\n.glyphicon-saved:before {\n content: \"\\e168\";\n}\n.glyphicon-import:before {\n content: \"\\e169\";\n}\n.glyphicon-export:before {\n content: \"\\e170\";\n}\n.glyphicon-send:before {\n content: \"\\e171\";\n}\n.glyphicon-floppy-disk:before {\n content: \"\\e172\";\n}\n.glyphicon-floppy-saved:before {\n content: \"\\e173\";\n}\n.glyphicon-floppy-remove:before {\n content: \"\\e174\";\n}\n.glyphicon-floppy-save:before {\n content: \"\\e175\";\n}\n.glyphicon-floppy-open:before {\n content: \"\\e176\";\n}\n.glyphicon-credit-card:before {\n content: \"\\e177\";\n}\n.glyphicon-transfer:before {\n content: \"\\e178\";\n}\n.glyphicon-cutlery:before {\n content: \"\\e179\";\n}\n.glyphicon-header:before {\n content: \"\\e180\";\n}\n.glyphicon-compressed:before {\n content: \"\\e181\";\n}\n.glyphicon-earphone:before {\n content: \"\\e182\";\n}\n.glyphicon-phone-alt:before {\n content: \"\\e183\";\n}\n.glyphicon-tower:before {\n content: \"\\e184\";\n}\n.glyphicon-stats:before {\n content: \"\\e185\";\n}\n.glyphicon-sd-video:before {\n content: \"\\e186\";\n}\n.glyphicon-hd-video:before {\n content: \"\\e187\";\n}\n.glyphicon-subtitles:before {\n content: \"\\e188\";\n}\n.glyphicon-sound-stereo:before {\n content: \"\\e189\";\n}\n.glyphicon-sound-dolby:before {\n content: \"\\e190\";\n}\n.glyphicon-sound-5-1:before {\n content: \"\\e191\";\n}\n.glyphicon-sound-6-1:before {\n content: \"\\e192\";\n}\n.glyphicon-sound-7-1:before {\n content: \"\\e193\";\n}\n.glyphicon-copyright-mark:before {\n content: \"\\e194\";\n}\n.glyphicon-registration-mark:before {\n content: \"\\e195\";\n}\n.glyphicon-cloud-download:before {\n content: \"\\e197\";\n}\n.glyphicon-cloud-upload:before {\n content: \"\\e198\";\n}\n.glyphicon-tree-conifer:before {\n content: \"\\e199\";\n}\n.glyphicon-tree-deciduous:before {\n content: \"\\e200\";\n}\n.glyphicon-cd:before {\n content: \"\\e201\";\n}\n.glyphicon-save-file:before {\n content: \"\\e202\";\n}\n.glyphicon-open-file:before {\n content: \"\\e203\";\n}\n.glyphicon-level-up:before {\n content: \"\\e204\";\n}\n.glyphicon-copy:before {\n content: \"\\e205\";\n}\n.glyphicon-paste:before {\n content: \"\\e206\";\n}\n.glyphicon-alert:before {\n content: \"\\e209\";\n}\n.glyphicon-equalizer:before {\n content: \"\\e210\";\n}\n.glyphicon-king:before {\n content: \"\\e211\";\n}\n.glyphicon-queen:before {\n content: \"\\e212\";\n}\n.glyphicon-pawn:before {\n content: \"\\e213\";\n}\n.glyphicon-bishop:before {\n content: \"\\e214\";\n}\n.glyphicon-knight:before {\n content: \"\\e215\";\n}\n.glyphicon-baby-formula:before {\n content: \"\\e216\";\n}\n.glyphicon-tent:before {\n content: \"\\26fa\";\n}\n.glyphicon-blackboard:before {\n content: \"\\e218\";\n}\n.glyphicon-bed:before {\n content: \"\\e219\";\n}\n.glyphicon-apple:before {\n content: \"\\f8ff\";\n}\n.glyphicon-erase:before {\n content: \"\\e221\";\n}\n.glyphicon-hourglass:before {\n content: \"\\231b\";\n}\n.glyphicon-lamp:before {\n content: \"\\e223\";\n}\n.glyphicon-duplicate:before {\n content: \"\\e224\";\n}\n.glyphicon-piggy-bank:before {\n content: \"\\e225\";\n}\n.glyphicon-scissors:before {\n content: \"\\e226\";\n}\n.glyphicon-bitcoin:before {\n content: \"\\e227\";\n}\n.glyphicon-btc:before {\n content: \"\\e227\";\n}\n.glyphicon-xbt:before {\n content: \"\\e227\";\n}\n.glyphicon-yen:before {\n content: \"\\00a5\";\n}\n.glyphicon-jpy:before {\n content: \"\\00a5\";\n}\n.glyphicon-ruble:before {\n content: \"\\20bd\";\n}\n.glyphicon-rub:before {\n content: \"\\20bd\";\n}\n.glyphicon-scale:before {\n content: \"\\e230\";\n}\n.glyphicon-ice-lolly:before {\n content: \"\\e231\";\n}\n.glyphicon-ice-lolly-tasted:before {\n content: \"\\e232\";\n}\n.glyphicon-education:before {\n content: \"\\e233\";\n}\n.glyphicon-option-horizontal:before {\n content: \"\\e234\";\n}\n.glyphicon-option-vertical:before {\n content: \"\\e235\";\n}\n.glyphicon-menu-hamburger:before {\n content: \"\\e236\";\n}\n.glyphicon-modal-window:before {\n content: \"\\e237\";\n}\n.glyphicon-oil:before {\n content: \"\\e238\";\n}\n.glyphicon-grain:before {\n content: \"\\e239\";\n}\n.glyphicon-sunglasses:before {\n content: \"\\e240\";\n}\n.glyphicon-text-size:before {\n content: \"\\e241\";\n}\n.glyphicon-text-color:before {\n content: \"\\e242\";\n}\n.glyphicon-text-background:before {\n content: \"\\e243\";\n}\n.glyphicon-object-align-top:before {\n content: \"\\e244\";\n}\n.glyphicon-object-align-bottom:before {\n content: \"\\e245\";\n}\n.glyphicon-object-align-horizontal:before {\n content: \"\\e246\";\n}\n.glyphicon-object-align-left:before {\n content: \"\\e247\";\n}\n.glyphicon-object-align-vertical:before {\n content: \"\\e248\";\n}\n.glyphicon-object-align-right:before {\n content: \"\\e249\";\n}\n.glyphicon-triangle-right:before {\n content: \"\\e250\";\n}\n.glyphicon-triangle-left:before {\n content: \"\\e251\";\n}\n.glyphicon-triangle-bottom:before {\n content: \"\\e252\";\n}\n.glyphicon-triangle-top:before {\n content: \"\\e253\";\n}\n.glyphicon-console:before {\n content: \"\\e254\";\n}\n.glyphicon-superscript:before {\n content: \"\\e255\";\n}\n.glyphicon-subscript:before {\n content: \"\\e256\";\n}\n.glyphicon-menu-left:before {\n content: \"\\e257\";\n}\n.glyphicon-menu-right:before {\n content: \"\\e258\";\n}\n.glyphicon-menu-down:before {\n content: \"\\e259\";\n}\n.glyphicon-menu-up:before {\n content: \"\\e260\";\n}\n* {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\n*:before,\n*:after {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\nhtml {\n font-size: 10px;\n\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\nbody {\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-size: 14px;\n line-height: 1.42857143;\n color: #333;\n background-color: #fff;\n}\ninput,\nbutton,\nselect,\ntextarea {\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\na {\n color: #337ab7;\n text-decoration: none;\n}\na:hover,\na:focus {\n color: #23527c;\n text-decoration: underline;\n}\na:focus {\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\nfigure {\n margin: 0;\n}\nimg {\n vertical-align: middle;\n}\n.img-responsive,\n.thumbnail > img,\n.thumbnail a > img,\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n display: block;\n max-width: 100%;\n height: auto;\n}\n.img-rounded {\n border-radius: 6px;\n}\n.img-thumbnail {\n display: inline-block;\n max-width: 100%;\n height: auto;\n padding: 4px;\n line-height: 1.42857143;\n background-color: #fff;\n border: 1px solid #ddd;\n border-radius: 4px;\n -webkit-transition: all .2s ease-in-out;\n -o-transition: all .2s ease-in-out;\n transition: all .2s ease-in-out;\n}\n.img-circle {\n border-radius: 50%;\n}\nhr {\n margin-top: 20px;\n margin-bottom: 20px;\n border: 0;\n border-top: 1px solid #eee;\n}\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n border: 0;\n}\n.sr-only-focusable:active,\n.sr-only-focusable:focus {\n position: static;\n width: auto;\n height: auto;\n margin: 0;\n overflow: visible;\n clip: auto;\n}\n[role=\"button\"] {\n cursor: pointer;\n}\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\n.h1,\n.h2,\n.h3,\n.h4,\n.h5,\n.h6 {\n font-family: inherit;\n font-weight: 500;\n line-height: 1.1;\n color: inherit;\n}\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small,\n.h1 small,\n.h2 small,\n.h3 small,\n.h4 small,\n.h5 small,\n.h6 small,\nh1 .small,\nh2 .small,\nh3 .small,\nh4 .small,\nh5 .small,\nh6 .small,\n.h1 .small,\n.h2 .small,\n.h3 .small,\n.h4 .small,\n.h5 .small,\n.h6 .small {\n font-weight: normal;\n line-height: 1;\n color: #777;\n}\nh1,\n.h1,\nh2,\n.h2,\nh3,\n.h3 {\n margin-top: 20px;\n margin-bottom: 10px;\n}\nh1 small,\n.h1 small,\nh2 small,\n.h2 small,\nh3 small,\n.h3 small,\nh1 .small,\n.h1 .small,\nh2 .small,\n.h2 .small,\nh3 .small,\n.h3 .small {\n font-size: 65%;\n}\nh4,\n.h4,\nh5,\n.h5,\nh6,\n.h6 {\n margin-top: 10px;\n margin-bottom: 10px;\n}\nh4 small,\n.h4 small,\nh5 small,\n.h5 small,\nh6 small,\n.h6 small,\nh4 .small,\n.h4 .small,\nh5 .small,\n.h5 .small,\nh6 .small,\n.h6 .small {\n font-size: 75%;\n}\nh1,\n.h1 {\n font-size: 36px;\n}\nh2,\n.h2 {\n font-size: 30px;\n}\nh3,\n.h3 {\n font-size: 24px;\n}\nh4,\n.h4 {\n font-size: 18px;\n}\nh5,\n.h5 {\n font-size: 14px;\n}\nh6,\n.h6 {\n font-size: 12px;\n}\np {\n margin: 0 0 10px;\n}\n.lead {\n margin-bottom: 20px;\n font-size: 16px;\n font-weight: 300;\n line-height: 1.4;\n}\n@media (min-width: 768px) {\n .lead {\n font-size: 21px;\n }\n}\nsmall,\n.small {\n font-size: 85%;\n}\nmark,\n.mark {\n padding: .2em;\n background-color: #fcf8e3;\n}\n.text-left {\n text-align: left;\n}\n.text-right {\n text-align: right;\n}\n.text-center {\n text-align: center;\n}\n.text-justify {\n text-align: justify;\n}\n.text-nowrap {\n white-space: nowrap;\n}\n.text-lowercase {\n text-transform: lowercase;\n}\n.text-uppercase {\n text-transform: uppercase;\n}\n.text-capitalize {\n text-transform: capitalize;\n}\n.text-muted {\n color: #777;\n}\n.text-primary {\n color: #337ab7;\n}\na.text-primary:hover,\na.text-primary:focus {\n color: #286090;\n}\n.text-success {\n color: #3c763d;\n}\na.text-success:hover,\na.text-success:focus {\n color: #2b542c;\n}\n.text-info {\n color: #31708f;\n}\na.text-info:hover,\na.text-info:focus {\n color: #245269;\n}\n.text-warning {\n color: #8a6d3b;\n}\na.text-warning:hover,\na.text-warning:focus {\n color: #66512c;\n}\n.text-danger {\n color: #a94442;\n}\na.text-danger:hover,\na.text-danger:focus {\n color: #843534;\n}\n.bg-primary {\n color: #fff;\n background-color: #337ab7;\n}\na.bg-primary:hover,\na.bg-primary:focus {\n background-color: #286090;\n}\n.bg-success {\n background-color: #dff0d8;\n}\na.bg-success:hover,\na.bg-success:focus {\n background-color: #c1e2b3;\n}\n.bg-info {\n background-color: #d9edf7;\n}\na.bg-info:hover,\na.bg-info:focus {\n background-color: #afd9ee;\n}\n.bg-warning {\n background-color: #fcf8e3;\n}\na.bg-warning:hover,\na.bg-warning:focus {\n background-color: #f7ecb5;\n}\n.bg-danger {\n background-color: #f2dede;\n}\na.bg-danger:hover,\na.bg-danger:focus {\n background-color: #e4b9b9;\n}\n.page-header {\n padding-bottom: 9px;\n margin: 40px 0 20px;\n border-bottom: 1px solid #eee;\n}\nul,\nol {\n margin-top: 0;\n margin-bottom: 10px;\n}\nul ul,\nol ul,\nul ol,\nol ol {\n margin-bottom: 0;\n}\n.list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n.list-inline {\n padding-left: 0;\n margin-left: -5px;\n list-style: none;\n}\n.list-inline > li {\n display: inline-block;\n padding-right: 5px;\n padding-left: 5px;\n}\ndl {\n margin-top: 0;\n margin-bottom: 20px;\n}\ndt,\ndd {\n line-height: 1.42857143;\n}\ndt {\n font-weight: bold;\n}\ndd {\n margin-left: 0;\n}\n@media (min-width: 768px) {\n .dl-horizontal dt {\n float: left;\n width: 160px;\n overflow: hidden;\n clear: left;\n text-align: right;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .dl-horizontal dd {\n margin-left: 180px;\n }\n}\nabbr[title],\nabbr[data-original-title] {\n cursor: help;\n border-bottom: 1px dotted #777;\n}\n.initialism {\n font-size: 90%;\n text-transform: uppercase;\n}\nblockquote {\n padding: 10px 20px;\n margin: 0 0 20px;\n font-size: 17.5px;\n border-left: 5px solid #eee;\n}\nblockquote p:last-child,\nblockquote ul:last-child,\nblockquote ol:last-child {\n margin-bottom: 0;\n}\nblockquote footer,\nblockquote small,\nblockquote .small {\n display: block;\n font-size: 80%;\n line-height: 1.42857143;\n color: #777;\n}\nblockquote footer:before,\nblockquote small:before,\nblockquote .small:before {\n content: '\\2014 \\00A0';\n}\n.blockquote-reverse,\nblockquote.pull-right {\n padding-right: 15px;\n padding-left: 0;\n text-align: right;\n border-right: 5px solid #eee;\n border-left: 0;\n}\n.blockquote-reverse footer:before,\nblockquote.pull-right footer:before,\n.blockquote-reverse small:before,\nblockquote.pull-right small:before,\n.blockquote-reverse .small:before,\nblockquote.pull-right .small:before {\n content: '';\n}\n.blockquote-reverse footer:after,\nblockquote.pull-right footer:after,\n.blockquote-reverse small:after,\nblockquote.pull-right small:after,\n.blockquote-reverse .small:after,\nblockquote.pull-right .small:after {\n content: '\\00A0 \\2014';\n}\naddress {\n margin-bottom: 20px;\n font-style: normal;\n line-height: 1.42857143;\n}\ncode,\nkbd,\npre,\nsamp {\n font-family: Menlo, Monaco, Consolas, \"Courier New\", monospace;\n}\ncode {\n padding: 2px 4px;\n font-size: 90%;\n color: #c7254e;\n background-color: #f9f2f4;\n border-radius: 4px;\n}\nkbd {\n padding: 2px 4px;\n font-size: 90%;\n color: #fff;\n background-color: #333;\n border-radius: 3px;\n -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25);\n box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25);\n}\nkbd kbd {\n padding: 0;\n font-size: 100%;\n font-weight: bold;\n -webkit-box-shadow: none;\n box-shadow: none;\n}\npre {\n display: block;\n padding: 9.5px;\n margin: 0 0 10px;\n font-size: 13px;\n line-height: 1.42857143;\n color: #333;\n word-break: break-all;\n word-wrap: break-word;\n background-color: #f5f5f5;\n border: 1px solid #ccc;\n border-radius: 4px;\n}\npre code {\n padding: 0;\n font-size: inherit;\n color: inherit;\n white-space: pre-wrap;\n background-color: transparent;\n border-radius: 0;\n}\n.pre-scrollable {\n max-height: 340px;\n overflow-y: scroll;\n}\n.container {\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto;\n}\n@media (min-width: 768px) {\n .container {\n width: 750px;\n }\n}\n@media (min-width: 992px) {\n .container {\n width: 970px;\n }\n}\n@media (min-width: 1200px) {\n .container {\n width: 1170px;\n }\n}\n.container-fluid {\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto;\n}\n.row {\n margin-right: -15px;\n margin-left: -15px;\n}\n.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 {\n position: relative;\n min-height: 1px;\n padding-right: 15px;\n padding-left: 15px;\n}\n.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 {\n float: left;\n}\n.col-xs-12 {\n width: 100%;\n}\n.col-xs-11 {\n width: 91.66666667%;\n}\n.col-xs-10 {\n width: 83.33333333%;\n}\n.col-xs-9 {\n width: 75%;\n}\n.col-xs-8 {\n width: 66.66666667%;\n}\n.col-xs-7 {\n width: 58.33333333%;\n}\n.col-xs-6 {\n width: 50%;\n}\n.col-xs-5 {\n width: 41.66666667%;\n}\n.col-xs-4 {\n width: 33.33333333%;\n}\n.col-xs-3 {\n width: 25%;\n}\n.col-xs-2 {\n width: 16.66666667%;\n}\n.col-xs-1 {\n width: 8.33333333%;\n}\n.col-xs-pull-12 {\n right: 100%;\n}\n.col-xs-pull-11 {\n right: 91.66666667%;\n}\n.col-xs-pull-10 {\n right: 83.33333333%;\n}\n.col-xs-pull-9 {\n right: 75%;\n}\n.col-xs-pull-8 {\n right: 66.66666667%;\n}\n.col-xs-pull-7 {\n right: 58.33333333%;\n}\n.col-xs-pull-6 {\n right: 50%;\n}\n.col-xs-pull-5 {\n right: 41.66666667%;\n}\n.col-xs-pull-4 {\n right: 33.33333333%;\n}\n.col-xs-pull-3 {\n right: 25%;\n}\n.col-xs-pull-2 {\n right: 16.66666667%;\n}\n.col-xs-pull-1 {\n right: 8.33333333%;\n}\n.col-xs-pull-0 {\n right: auto;\n}\n.col-xs-push-12 {\n left: 100%;\n}\n.col-xs-push-11 {\n left: 91.66666667%;\n}\n.col-xs-push-10 {\n left: 83.33333333%;\n}\n.col-xs-push-9 {\n left: 75%;\n}\n.col-xs-push-8 {\n left: 66.66666667%;\n}\n.col-xs-push-7 {\n left: 58.33333333%;\n}\n.col-xs-push-6 {\n left: 50%;\n}\n.col-xs-push-5 {\n left: 41.66666667%;\n}\n.col-xs-push-4 {\n left: 33.33333333%;\n}\n.col-xs-push-3 {\n left: 25%;\n}\n.col-xs-push-2 {\n left: 16.66666667%;\n}\n.col-xs-push-1 {\n left: 8.33333333%;\n}\n.col-xs-push-0 {\n left: auto;\n}\n.col-xs-offset-12 {\n margin-left: 100%;\n}\n.col-xs-offset-11 {\n margin-left: 91.66666667%;\n}\n.col-xs-offset-10 {\n margin-left: 83.33333333%;\n}\n.col-xs-offset-9 {\n margin-left: 75%;\n}\n.col-xs-offset-8 {\n margin-left: 66.66666667%;\n}\n.col-xs-offset-7 {\n margin-left: 58.33333333%;\n}\n.col-xs-offset-6 {\n margin-left: 50%;\n}\n.col-xs-offset-5 {\n margin-left: 41.66666667%;\n}\n.col-xs-offset-4 {\n margin-left: 33.33333333%;\n}\n.col-xs-offset-3 {\n margin-left: 25%;\n}\n.col-xs-offset-2 {\n margin-left: 16.66666667%;\n}\n.col-xs-offset-1 {\n margin-left: 8.33333333%;\n}\n.col-xs-offset-0 {\n margin-left: 0;\n}\n@media (min-width: 768px) {\n .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 {\n float: left;\n }\n .col-sm-12 {\n width: 100%;\n }\n .col-sm-11 {\n width: 91.66666667%;\n }\n .col-sm-10 {\n width: 83.33333333%;\n }\n .col-sm-9 {\n width: 75%;\n }\n .col-sm-8 {\n width: 66.66666667%;\n }\n .col-sm-7 {\n width: 58.33333333%;\n }\n .col-sm-6 {\n width: 50%;\n }\n .col-sm-5 {\n width: 41.66666667%;\n }\n .col-sm-4 {\n width: 33.33333333%;\n }\n .col-sm-3 {\n width: 25%;\n }\n .col-sm-2 {\n width: 16.66666667%;\n }\n .col-sm-1 {\n width: 8.33333333%;\n }\n .col-sm-pull-12 {\n right: 100%;\n }\n .col-sm-pull-11 {\n right: 91.66666667%;\n }\n .col-sm-pull-10 {\n right: 83.33333333%;\n }\n .col-sm-pull-9 {\n right: 75%;\n }\n .col-sm-pull-8 {\n right: 66.66666667%;\n }\n .col-sm-pull-7 {\n right: 58.33333333%;\n }\n .col-sm-pull-6 {\n right: 50%;\n }\n .col-sm-pull-5 {\n right: 41.66666667%;\n }\n .col-sm-pull-4 {\n right: 33.33333333%;\n }\n .col-sm-pull-3 {\n right: 25%;\n }\n .col-sm-pull-2 {\n right: 16.66666667%;\n }\n .col-sm-pull-1 {\n right: 8.33333333%;\n }\n .col-sm-pull-0 {\n right: auto;\n }\n .col-sm-push-12 {\n left: 100%;\n }\n .col-sm-push-11 {\n left: 91.66666667%;\n }\n .col-sm-push-10 {\n left: 83.33333333%;\n }\n .col-sm-push-9 {\n left: 75%;\n }\n .col-sm-push-8 {\n left: 66.66666667%;\n }\n .col-sm-push-7 {\n left: 58.33333333%;\n }\n .col-sm-push-6 {\n left: 50%;\n }\n .col-sm-push-5 {\n left: 41.66666667%;\n }\n .col-sm-push-4 {\n left: 33.33333333%;\n }\n .col-sm-push-3 {\n left: 25%;\n }\n .col-sm-push-2 {\n left: 16.66666667%;\n }\n .col-sm-push-1 {\n left: 8.33333333%;\n }\n .col-sm-push-0 {\n left: auto;\n }\n .col-sm-offset-12 {\n margin-left: 100%;\n }\n .col-sm-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-sm-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-sm-offset-9 {\n margin-left: 75%;\n }\n .col-sm-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-sm-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-sm-offset-6 {\n margin-left: 50%;\n }\n .col-sm-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-sm-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-sm-offset-3 {\n margin-left: 25%;\n }\n .col-sm-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-sm-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-sm-offset-0 {\n margin-left: 0;\n }\n}\n@media (min-width: 992px) {\n .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 {\n float: left;\n }\n .col-md-12 {\n width: 100%;\n }\n .col-md-11 {\n width: 91.66666667%;\n }\n .col-md-10 {\n width: 83.33333333%;\n }\n .col-md-9 {\n width: 75%;\n }\n .col-md-8 {\n width: 66.66666667%;\n }\n .col-md-7 {\n width: 58.33333333%;\n }\n .col-md-6 {\n width: 50%;\n }\n .col-md-5 {\n width: 41.66666667%;\n }\n .col-md-4 {\n width: 33.33333333%;\n }\n .col-md-3 {\n width: 25%;\n }\n .col-md-2 {\n width: 16.66666667%;\n }\n .col-md-1 {\n width: 8.33333333%;\n }\n .col-md-pull-12 {\n right: 100%;\n }\n .col-md-pull-11 {\n right: 91.66666667%;\n }\n .col-md-pull-10 {\n right: 83.33333333%;\n }\n .col-md-pull-9 {\n right: 75%;\n }\n .col-md-pull-8 {\n right: 66.66666667%;\n }\n .col-md-pull-7 {\n right: 58.33333333%;\n }\n .col-md-pull-6 {\n right: 50%;\n }\n .col-md-pull-5 {\n right: 41.66666667%;\n }\n .col-md-pull-4 {\n right: 33.33333333%;\n }\n .col-md-pull-3 {\n right: 25%;\n }\n .col-md-pull-2 {\n right: 16.66666667%;\n }\n .col-md-pull-1 {\n right: 8.33333333%;\n }\n .col-md-pull-0 {\n right: auto;\n }\n .col-md-push-12 {\n left: 100%;\n }\n .col-md-push-11 {\n left: 91.66666667%;\n }\n .col-md-push-10 {\n left: 83.33333333%;\n }\n .col-md-push-9 {\n left: 75%;\n }\n .col-md-push-8 {\n left: 66.66666667%;\n }\n .col-md-push-7 {\n left: 58.33333333%;\n }\n .col-md-push-6 {\n left: 50%;\n }\n .col-md-push-5 {\n left: 41.66666667%;\n }\n .col-md-push-4 {\n left: 33.33333333%;\n }\n .col-md-push-3 {\n left: 25%;\n }\n .col-md-push-2 {\n left: 16.66666667%;\n }\n .col-md-push-1 {\n left: 8.33333333%;\n }\n .col-md-push-0 {\n left: auto;\n }\n .col-md-offset-12 {\n margin-left: 100%;\n }\n .col-md-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-md-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-md-offset-9 {\n margin-left: 75%;\n }\n .col-md-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-md-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-md-offset-6 {\n margin-left: 50%;\n }\n .col-md-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-md-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-md-offset-3 {\n margin-left: 25%;\n }\n .col-md-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-md-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-md-offset-0 {\n margin-left: 0;\n }\n}\n@media (min-width: 1200px) {\n .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 {\n float: left;\n }\n .col-lg-12 {\n width: 100%;\n }\n .col-lg-11 {\n width: 91.66666667%;\n }\n .col-lg-10 {\n width: 83.33333333%;\n }\n .col-lg-9 {\n width: 75%;\n }\n .col-lg-8 {\n width: 66.66666667%;\n }\n .col-lg-7 {\n width: 58.33333333%;\n }\n .col-lg-6 {\n width: 50%;\n }\n .col-lg-5 {\n width: 41.66666667%;\n }\n .col-lg-4 {\n width: 33.33333333%;\n }\n .col-lg-3 {\n width: 25%;\n }\n .col-lg-2 {\n width: 16.66666667%;\n }\n .col-lg-1 {\n width: 8.33333333%;\n }\n .col-lg-pull-12 {\n right: 100%;\n }\n .col-lg-pull-11 {\n right: 91.66666667%;\n }\n .col-lg-pull-10 {\n right: 83.33333333%;\n }\n .col-lg-pull-9 {\n right: 75%;\n }\n .col-lg-pull-8 {\n right: 66.66666667%;\n }\n .col-lg-pull-7 {\n right: 58.33333333%;\n }\n .col-lg-pull-6 {\n right: 50%;\n }\n .col-lg-pull-5 {\n right: 41.66666667%;\n }\n .col-lg-pull-4 {\n right: 33.33333333%;\n }\n .col-lg-pull-3 {\n right: 25%;\n }\n .col-lg-pull-2 {\n right: 16.66666667%;\n }\n .col-lg-pull-1 {\n right: 8.33333333%;\n }\n .col-lg-pull-0 {\n right: auto;\n }\n .col-lg-push-12 {\n left: 100%;\n }\n .col-lg-push-11 {\n left: 91.66666667%;\n }\n .col-lg-push-10 {\n left: 83.33333333%;\n }\n .col-lg-push-9 {\n left: 75%;\n }\n .col-lg-push-8 {\n left: 66.66666667%;\n }\n .col-lg-push-7 {\n left: 58.33333333%;\n }\n .col-lg-push-6 {\n left: 50%;\n }\n .col-lg-push-5 {\n left: 41.66666667%;\n }\n .col-lg-push-4 {\n left: 33.33333333%;\n }\n .col-lg-push-3 {\n left: 25%;\n }\n .col-lg-push-2 {\n left: 16.66666667%;\n }\n .col-lg-push-1 {\n left: 8.33333333%;\n }\n .col-lg-push-0 {\n left: auto;\n }\n .col-lg-offset-12 {\n margin-left: 100%;\n }\n .col-lg-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-lg-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-lg-offset-9 {\n margin-left: 75%;\n }\n .col-lg-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-lg-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-lg-offset-6 {\n margin-left: 50%;\n }\n .col-lg-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-lg-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-lg-offset-3 {\n margin-left: 25%;\n }\n .col-lg-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-lg-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-lg-offset-0 {\n margin-left: 0;\n }\n}\ntable {\n background-color: transparent;\n}\ncaption {\n padding-top: 8px;\n padding-bottom: 8px;\n color: #777;\n text-align: left;\n}\nth {\n text-align: left;\n}\n.table {\n width: 100%;\n max-width: 100%;\n margin-bottom: 20px;\n}\n.table > thead > tr > th,\n.table > tbody > tr > th,\n.table > tfoot > tr > th,\n.table > thead > tr > td,\n.table > tbody > tr > td,\n.table > tfoot > tr > td {\n padding: 8px;\n line-height: 1.42857143;\n vertical-align: top;\n border-top: 1px solid #ddd;\n}\n.table > thead > tr > th {\n vertical-align: bottom;\n border-bottom: 2px solid #ddd;\n}\n.table > caption + thead > tr:first-child > th,\n.table > colgroup + thead > tr:first-child > th,\n.table > thead:first-child > tr:first-child > th,\n.table > caption + thead > tr:first-child > td,\n.table > colgroup + thead > tr:first-child > td,\n.table > thead:first-child > tr:first-child > td {\n border-top: 0;\n}\n.table > tbody + tbody {\n border-top: 2px solid #ddd;\n}\n.table .table {\n background-color: #fff;\n}\n.table-condensed > thead > tr > th,\n.table-condensed > tbody > tr > th,\n.table-condensed > tfoot > tr > th,\n.table-condensed > thead > tr > td,\n.table-condensed > tbody > tr > td,\n.table-condensed > tfoot > tr > td {\n padding: 5px;\n}\n.table-bordered {\n border: 1px solid #ddd;\n}\n.table-bordered > thead > tr > th,\n.table-bordered > tbody > tr > th,\n.table-bordered > tfoot > tr > th,\n.table-bordered > thead > tr > td,\n.table-bordered > tbody > tr > td,\n.table-bordered > tfoot > tr > td {\n border: 1px solid #ddd;\n}\n.table-bordered > thead > tr > th,\n.table-bordered > thead > tr > td {\n border-bottom-width: 2px;\n}\n.table-striped > tbody > tr:nth-of-type(odd) {\n background-color: #f9f9f9;\n}\n.table-hover > tbody > tr:hover {\n background-color: #f5f5f5;\n}\ntable col[class*=\"col-\"] {\n position: static;\n display: table-column;\n float: none;\n}\ntable td[class*=\"col-\"],\ntable th[class*=\"col-\"] {\n position: static;\n display: table-cell;\n float: none;\n}\n.table > thead > tr > td.active,\n.table > tbody > tr > td.active,\n.table > tfoot > tr > td.active,\n.table > thead > tr > th.active,\n.table > tbody > tr > th.active,\n.table > tfoot > tr > th.active,\n.table > thead > tr.active > td,\n.table > tbody > tr.active > td,\n.table > tfoot > tr.active > td,\n.table > thead > tr.active > th,\n.table > tbody > tr.active > th,\n.table > tfoot > tr.active > th {\n background-color: #f5f5f5;\n}\n.table-hover > tbody > tr > td.active:hover,\n.table-hover > tbody > tr > th.active:hover,\n.table-hover > tbody > tr.active:hover > td,\n.table-hover > tbody > tr:hover > .active,\n.table-hover > tbody > tr.active:hover > th {\n background-color: #e8e8e8;\n}\n.table > thead > tr > td.success,\n.table > tbody > tr > td.success,\n.table > tfoot > tr > td.success,\n.table > thead > tr > th.success,\n.table > tbody > tr > th.success,\n.table > tfoot > tr > th.success,\n.table > thead > tr.success > td,\n.table > tbody > tr.success > td,\n.table > tfoot > tr.success > td,\n.table > thead > tr.success > th,\n.table > tbody > tr.success > th,\n.table > tfoot > tr.success > th {\n background-color: #dff0d8;\n}\n.table-hover > tbody > tr > td.success:hover,\n.table-hover > tbody > tr > th.success:hover,\n.table-hover > tbody > tr.success:hover > td,\n.table-hover > tbody > tr:hover > .success,\n.table-hover > tbody > tr.success:hover > th {\n background-color: #d0e9c6;\n}\n.table > thead > tr > td.info,\n.table > tbody > tr > td.info,\n.table > tfoot > tr > td.info,\n.table > thead > tr > th.info,\n.table > tbody > tr > th.info,\n.table > tfoot > tr > th.info,\n.table > thead > tr.info > td,\n.table > tbody > tr.info > td,\n.table > tfoot > tr.info > td,\n.table > thead > tr.info > th,\n.table > tbody > tr.info > th,\n.table > tfoot > tr.info > th {\n background-color: #d9edf7;\n}\n.table-hover > tbody > tr > td.info:hover,\n.table-hover > tbody > tr > th.info:hover,\n.table-hover > tbody > tr.info:hover > td,\n.table-hover > tbody > tr:hover > .info,\n.table-hover > tbody > tr.info:hover > th {\n background-color: #c4e3f3;\n}\n.table > thead > tr > td.warning,\n.table > tbody > tr > td.warning,\n.table > tfoot > tr > td.warning,\n.table > thead > tr > th.warning,\n.table > tbody > tr > th.warning,\n.table > tfoot > tr > th.warning,\n.table > thead > tr.warning > td,\n.table > tbody > tr.warning > td,\n.table > tfoot > tr.warning > td,\n.table > thead > tr.warning > th,\n.table > tbody > tr.warning > th,\n.table > tfoot > tr.warning > th {\n background-color: #fcf8e3;\n}\n.table-hover > tbody > tr > td.warning:hover,\n.table-hover > tbody > tr > th.warning:hover,\n.table-hover > tbody > tr.warning:hover > td,\n.table-hover > tbody > tr:hover > .warning,\n.table-hover > tbody > tr.warning:hover > th {\n background-color: #faf2cc;\n}\n.table > thead > tr > td.danger,\n.table > tbody > tr > td.danger,\n.table > tfoot > tr > td.danger,\n.table > thead > tr > th.danger,\n.table > tbody > tr > th.danger,\n.table > tfoot > tr > th.danger,\n.table > thead > tr.danger > td,\n.table > tbody > tr.danger > td,\n.table > tfoot > tr.danger > td,\n.table > thead > tr.danger > th,\n.table > tbody > tr.danger > th,\n.table > tfoot > tr.danger > th {\n background-color: #f2dede;\n}\n.table-hover > tbody > tr > td.danger:hover,\n.table-hover > tbody > tr > th.danger:hover,\n.table-hover > tbody > tr.danger:hover > td,\n.table-hover > tbody > tr:hover > .danger,\n.table-hover > tbody > tr.danger:hover > th {\n background-color: #ebcccc;\n}\n.table-responsive {\n min-height: .01%;\n overflow-x: auto;\n}\n@media screen and (max-width: 767px) {\n .table-responsive {\n width: 100%;\n margin-bottom: 15px;\n overflow-y: hidden;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n border: 1px solid #ddd;\n }\n .table-responsive > .table {\n margin-bottom: 0;\n }\n .table-responsive > .table > thead > tr > th,\n .table-responsive > .table > tbody > tr > th,\n .table-responsive > .table > tfoot > tr > th,\n .table-responsive > .table > thead > tr > td,\n .table-responsive > .table > tbody > tr > td,\n .table-responsive > .table > tfoot > tr > td {\n white-space: nowrap;\n }\n .table-responsive > .table-bordered {\n border: 0;\n }\n .table-responsive > .table-bordered > thead > tr > th:first-child,\n .table-responsive > .table-bordered > tbody > tr > th:first-child,\n .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n .table-responsive > .table-bordered > thead > tr > td:first-child,\n .table-responsive > .table-bordered > tbody > tr > td:first-child,\n .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n border-left: 0;\n }\n .table-responsive > .table-bordered > thead > tr > th:last-child,\n .table-responsive > .table-bordered > tbody > tr > th:last-child,\n .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n .table-responsive > .table-bordered > thead > tr > td:last-child,\n .table-responsive > .table-bordered > tbody > tr > td:last-child,\n .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n border-right: 0;\n }\n .table-responsive > .table-bordered > tbody > tr:last-child > th,\n .table-responsive > .table-bordered > tfoot > tr:last-child > th,\n .table-responsive > .table-bordered > tbody > tr:last-child > td,\n .table-responsive > .table-bordered > tfoot > tr:last-child > td {\n border-bottom: 0;\n }\n}\nfieldset {\n min-width: 0;\n padding: 0;\n margin: 0;\n border: 0;\n}\nlegend {\n display: block;\n width: 100%;\n padding: 0;\n margin-bottom: 20px;\n font-size: 21px;\n line-height: inherit;\n color: #333;\n border: 0;\n border-bottom: 1px solid #e5e5e5;\n}\nlabel {\n display: inline-block;\n max-width: 100%;\n margin-bottom: 5px;\n font-weight: bold;\n}\ninput[type=\"search\"] {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n margin: 4px 0 0;\n margin-top: 1px \\9;\n line-height: normal;\n}\ninput[type=\"file\"] {\n display: block;\n}\ninput[type=\"range\"] {\n display: block;\n width: 100%;\n}\nselect[multiple],\nselect[size] {\n height: auto;\n}\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\noutput {\n display: block;\n padding-top: 7px;\n font-size: 14px;\n line-height: 1.42857143;\n color: #555;\n}\n.form-control {\n display: block;\n width: 100%;\n height: 34px;\n padding: 6px 12px;\n font-size: 14px;\n line-height: 1.42857143;\n color: #555;\n background-color: #fff;\n background-image: none;\n border: 1px solid #ccc;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);\n -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s;\n -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n}\n.form-control:focus {\n border-color: #66afe9;\n outline: 0;\n -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6);\n box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6);\n}\n.form-control::-moz-placeholder {\n color: #999;\n opacity: 1;\n}\n.form-control:-ms-input-placeholder {\n color: #999;\n}\n.form-control::-webkit-input-placeholder {\n color: #999;\n}\n.form-control::-ms-expand {\n background-color: transparent;\n border: 0;\n}\n.form-control[disabled],\n.form-control[readonly],\nfieldset[disabled] .form-control {\n background-color: #eee;\n opacity: 1;\n}\n.form-control[disabled],\nfieldset[disabled] .form-control {\n cursor: not-allowed;\n}\ntextarea.form-control {\n height: auto;\n}\ninput[type=\"search\"] {\n -webkit-appearance: none;\n}\n@media screen and (-webkit-min-device-pixel-ratio: 0) {\n input[type=\"date\"].form-control,\n input[type=\"time\"].form-control,\n input[type=\"datetime-local\"].form-control,\n input[type=\"month\"].form-control {\n line-height: 34px;\n }\n input[type=\"date\"].input-sm,\n input[type=\"time\"].input-sm,\n input[type=\"datetime-local\"].input-sm,\n input[type=\"month\"].input-sm,\n .input-group-sm input[type=\"date\"],\n .input-group-sm input[type=\"time\"],\n .input-group-sm input[type=\"datetime-local\"],\n .input-group-sm input[type=\"month\"] {\n line-height: 30px;\n }\n input[type=\"date\"].input-lg,\n input[type=\"time\"].input-lg,\n input[type=\"datetime-local\"].input-lg,\n input[type=\"month\"].input-lg,\n .input-group-lg input[type=\"date\"],\n .input-group-lg input[type=\"time\"],\n .input-group-lg input[type=\"datetime-local\"],\n .input-group-lg input[type=\"month\"] {\n line-height: 46px;\n }\n}\n.form-group {\n margin-bottom: 15px;\n}\n.radio,\n.checkbox {\n position: relative;\n display: block;\n margin-top: 10px;\n margin-bottom: 10px;\n}\n.radio label,\n.checkbox label {\n min-height: 20px;\n padding-left: 20px;\n margin-bottom: 0;\n font-weight: normal;\n cursor: pointer;\n}\n.radio input[type=\"radio\"],\n.radio-inline input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"],\n.checkbox-inline input[type=\"checkbox\"] {\n position: absolute;\n margin-top: 4px \\9;\n margin-left: -20px;\n}\n.radio + .radio,\n.checkbox + .checkbox {\n margin-top: -5px;\n}\n.radio-inline,\n.checkbox-inline {\n position: relative;\n display: inline-block;\n padding-left: 20px;\n margin-bottom: 0;\n font-weight: normal;\n vertical-align: middle;\n cursor: pointer;\n}\n.radio-inline + .radio-inline,\n.checkbox-inline + .checkbox-inline {\n margin-top: 0;\n margin-left: 10px;\n}\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"].disabled,\ninput[type=\"checkbox\"].disabled,\nfieldset[disabled] input[type=\"radio\"],\nfieldset[disabled] input[type=\"checkbox\"] {\n cursor: not-allowed;\n}\n.radio-inline.disabled,\n.checkbox-inline.disabled,\nfieldset[disabled] .radio-inline,\nfieldset[disabled] .checkbox-inline {\n cursor: not-allowed;\n}\n.radio.disabled label,\n.checkbox.disabled label,\nfieldset[disabled] .radio label,\nfieldset[disabled] .checkbox label {\n cursor: not-allowed;\n}\n.form-control-static {\n min-height: 34px;\n padding-top: 7px;\n padding-bottom: 7px;\n margin-bottom: 0;\n}\n.form-control-static.input-lg,\n.form-control-static.input-sm {\n padding-right: 0;\n padding-left: 0;\n}\n.input-sm {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\nselect.input-sm {\n height: 30px;\n line-height: 30px;\n}\ntextarea.input-sm,\nselect[multiple].input-sm {\n height: auto;\n}\n.form-group-sm .form-control {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.form-group-sm select.form-control {\n height: 30px;\n line-height: 30px;\n}\n.form-group-sm textarea.form-control,\n.form-group-sm select[multiple].form-control {\n height: auto;\n}\n.form-group-sm .form-control-static {\n height: 30px;\n min-height: 32px;\n padding: 6px 10px;\n font-size: 12px;\n line-height: 1.5;\n}\n.input-lg {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\nselect.input-lg {\n height: 46px;\n line-height: 46px;\n}\ntextarea.input-lg,\nselect[multiple].input-lg {\n height: auto;\n}\n.form-group-lg .form-control {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\n.form-group-lg select.form-control {\n height: 46px;\n line-height: 46px;\n}\n.form-group-lg textarea.form-control,\n.form-group-lg select[multiple].form-control {\n height: auto;\n}\n.form-group-lg .form-control-static {\n height: 46px;\n min-height: 38px;\n padding: 11px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n}\n.has-feedback {\n position: relative;\n}\n.has-feedback .form-control {\n padding-right: 42.5px;\n}\n.form-control-feedback {\n position: absolute;\n top: 0;\n right: 0;\n z-index: 2;\n display: block;\n width: 34px;\n height: 34px;\n line-height: 34px;\n text-align: center;\n pointer-events: none;\n}\n.input-lg + .form-control-feedback,\n.input-group-lg + .form-control-feedback,\n.form-group-lg .form-control + .form-control-feedback {\n width: 46px;\n height: 46px;\n line-height: 46px;\n}\n.input-sm + .form-control-feedback,\n.input-group-sm + .form-control-feedback,\n.form-group-sm .form-control + .form-control-feedback {\n width: 30px;\n height: 30px;\n line-height: 30px;\n}\n.has-success .help-block,\n.has-success .control-label,\n.has-success .radio,\n.has-success .checkbox,\n.has-success .radio-inline,\n.has-success .checkbox-inline,\n.has-success.radio label,\n.has-success.checkbox label,\n.has-success.radio-inline label,\n.has-success.checkbox-inline label {\n color: #3c763d;\n}\n.has-success .form-control {\n border-color: #3c763d;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);\n}\n.has-success .form-control:focus {\n border-color: #2b542c;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168;\n}\n.has-success .input-group-addon {\n color: #3c763d;\n background-color: #dff0d8;\n border-color: #3c763d;\n}\n.has-success .form-control-feedback {\n color: #3c763d;\n}\n.has-warning .help-block,\n.has-warning .control-label,\n.has-warning .radio,\n.has-warning .checkbox,\n.has-warning .radio-inline,\n.has-warning .checkbox-inline,\n.has-warning.radio label,\n.has-warning.checkbox label,\n.has-warning.radio-inline label,\n.has-warning.checkbox-inline label {\n color: #8a6d3b;\n}\n.has-warning .form-control {\n border-color: #8a6d3b;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);\n}\n.has-warning .form-control:focus {\n border-color: #66512c;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b;\n}\n.has-warning .input-group-addon {\n color: #8a6d3b;\n background-color: #fcf8e3;\n border-color: #8a6d3b;\n}\n.has-warning .form-control-feedback {\n color: #8a6d3b;\n}\n.has-error .help-block,\n.has-error .control-label,\n.has-error .radio,\n.has-error .checkbox,\n.has-error .radio-inline,\n.has-error .checkbox-inline,\n.has-error.radio label,\n.has-error.checkbox label,\n.has-error.radio-inline label,\n.has-error.checkbox-inline label {\n color: #a94442;\n}\n.has-error .form-control {\n border-color: #a94442;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);\n}\n.has-error .form-control:focus {\n border-color: #843534;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483;\n}\n.has-error .input-group-addon {\n color: #a94442;\n background-color: #f2dede;\n border-color: #a94442;\n}\n.has-error .form-control-feedback {\n color: #a94442;\n}\n.has-feedback label ~ .form-control-feedback {\n top: 25px;\n}\n.has-feedback label.sr-only ~ .form-control-feedback {\n top: 0;\n}\n.help-block {\n display: block;\n margin-top: 5px;\n margin-bottom: 10px;\n color: #737373;\n}\n@media (min-width: 768px) {\n .form-inline .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .form-control {\n display: inline-block;\n width: auto;\n vertical-align: middle;\n }\n .form-inline .form-control-static {\n display: inline-block;\n }\n .form-inline .input-group {\n display: inline-table;\n vertical-align: middle;\n }\n .form-inline .input-group .input-group-addon,\n .form-inline .input-group .input-group-btn,\n .form-inline .input-group .form-control {\n width: auto;\n }\n .form-inline .input-group > .form-control {\n width: 100%;\n }\n .form-inline .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .radio,\n .form-inline .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .radio label,\n .form-inline .checkbox label {\n padding-left: 0;\n }\n .form-inline .radio input[type=\"radio\"],\n .form-inline .checkbox input[type=\"checkbox\"] {\n position: relative;\n margin-left: 0;\n }\n .form-inline .has-feedback .form-control-feedback {\n top: 0;\n }\n}\n.form-horizontal .radio,\n.form-horizontal .checkbox,\n.form-horizontal .radio-inline,\n.form-horizontal .checkbox-inline {\n padding-top: 7px;\n margin-top: 0;\n margin-bottom: 0;\n}\n.form-horizontal .radio,\n.form-horizontal .checkbox {\n min-height: 27px;\n}\n.form-horizontal .form-group {\n margin-right: -15px;\n margin-left: -15px;\n}\n@media (min-width: 768px) {\n .form-horizontal .control-label {\n padding-top: 7px;\n margin-bottom: 0;\n text-align: right;\n }\n}\n.form-horizontal .has-feedback .form-control-feedback {\n right: 15px;\n}\n@media (min-width: 768px) {\n .form-horizontal .form-group-lg .control-label {\n padding-top: 11px;\n font-size: 18px;\n }\n}\n@media (min-width: 768px) {\n .form-horizontal .form-group-sm .control-label {\n padding-top: 6px;\n font-size: 12px;\n }\n}\n.btn {\n display: inline-block;\n padding: 6px 12px;\n margin-bottom: 0;\n font-size: 14px;\n font-weight: normal;\n line-height: 1.42857143;\n text-align: center;\n white-space: nowrap;\n vertical-align: middle;\n -ms-touch-action: manipulation;\n touch-action: manipulation;\n cursor: pointer;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n background-image: none;\n border: 1px solid transparent;\n border-radius: 4px;\n}\n.btn:focus,\n.btn:active:focus,\n.btn.active:focus,\n.btn.focus,\n.btn:active.focus,\n.btn.active.focus {\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\n.btn:hover,\n.btn:focus,\n.btn.focus {\n color: #333;\n text-decoration: none;\n}\n.btn:active,\n.btn.active {\n background-image: none;\n outline: 0;\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);\n}\n.btn.disabled,\n.btn[disabled],\nfieldset[disabled] .btn {\n cursor: not-allowed;\n filter: alpha(opacity=65);\n -webkit-box-shadow: none;\n box-shadow: none;\n opacity: .65;\n}\na.btn.disabled,\nfieldset[disabled] a.btn {\n pointer-events: none;\n}\n.btn-default {\n color: #333;\n background-color: #fff;\n border-color: #ccc;\n}\n.btn-default:focus,\n.btn-default.focus {\n color: #333;\n background-color: #e6e6e6;\n border-color: #8c8c8c;\n}\n.btn-default:hover {\n color: #333;\n background-color: #e6e6e6;\n border-color: #adadad;\n}\n.btn-default:active,\n.btn-default.active,\n.open > .dropdown-toggle.btn-default {\n color: #333;\n background-color: #e6e6e6;\n border-color: #adadad;\n}\n.btn-default:active:hover,\n.btn-default.active:hover,\n.open > .dropdown-toggle.btn-default:hover,\n.btn-default:active:focus,\n.btn-default.active:focus,\n.open > .dropdown-toggle.btn-default:focus,\n.btn-default:active.focus,\n.btn-default.active.focus,\n.open > .dropdown-toggle.btn-default.focus {\n color: #333;\n background-color: #d4d4d4;\n border-color: #8c8c8c;\n}\n.btn-default:active,\n.btn-default.active,\n.open > .dropdown-toggle.btn-default {\n background-image: none;\n}\n.btn-default.disabled:hover,\n.btn-default[disabled]:hover,\nfieldset[disabled] .btn-default:hover,\n.btn-default.disabled:focus,\n.btn-default[disabled]:focus,\nfieldset[disabled] .btn-default:focus,\n.btn-default.disabled.focus,\n.btn-default[disabled].focus,\nfieldset[disabled] .btn-default.focus {\n background-color: #fff;\n border-color: #ccc;\n}\n.btn-default .badge {\n color: #fff;\n background-color: #333;\n}\n.btn-primary {\n color: #fff;\n background-color: #337ab7;\n border-color: #2e6da4;\n}\n.btn-primary:focus,\n.btn-primary.focus {\n color: #fff;\n background-color: #286090;\n border-color: #122b40;\n}\n.btn-primary:hover {\n color: #fff;\n background-color: #286090;\n border-color: #204d74;\n}\n.btn-primary:active,\n.btn-primary.active,\n.open > .dropdown-toggle.btn-primary {\n color: #fff;\n background-color: #286090;\n border-color: #204d74;\n}\n.btn-primary:active:hover,\n.btn-primary.active:hover,\n.open > .dropdown-toggle.btn-primary:hover,\n.btn-primary:active:focus,\n.btn-primary.active:focus,\n.open > .dropdown-toggle.btn-primary:focus,\n.btn-primary:active.focus,\n.btn-primary.active.focus,\n.open > .dropdown-toggle.btn-primary.focus {\n color: #fff;\n background-color: #204d74;\n border-color: #122b40;\n}\n.btn-primary:active,\n.btn-primary.active,\n.open > .dropdown-toggle.btn-primary {\n background-image: none;\n}\n.btn-primary.disabled:hover,\n.btn-primary[disabled]:hover,\nfieldset[disabled] .btn-primary:hover,\n.btn-primary.disabled:focus,\n.btn-primary[disabled]:focus,\nfieldset[disabled] .btn-primary:focus,\n.btn-primary.disabled.focus,\n.btn-primary[disabled].focus,\nfieldset[disabled] .btn-primary.focus {\n background-color: #337ab7;\n border-color: #2e6da4;\n}\n.btn-primary .badge {\n color: #337ab7;\n background-color: #fff;\n}\n.btn-success {\n color: #fff;\n background-color: #5cb85c;\n border-color: #4cae4c;\n}\n.btn-success:focus,\n.btn-success.focus {\n color: #fff;\n background-color: #449d44;\n border-color: #255625;\n}\n.btn-success:hover {\n color: #fff;\n background-color: #449d44;\n border-color: #398439;\n}\n.btn-success:active,\n.btn-success.active,\n.open > .dropdown-toggle.btn-success {\n color: #fff;\n background-color: #449d44;\n border-color: #398439;\n}\n.btn-success:active:hover,\n.btn-success.active:hover,\n.open > .dropdown-toggle.btn-success:hover,\n.btn-success:active:focus,\n.btn-success.active:focus,\n.open > .dropdown-toggle.btn-success:focus,\n.btn-success:active.focus,\n.btn-success.active.focus,\n.open > .dropdown-toggle.btn-success.focus {\n color: #fff;\n background-color: #398439;\n border-color: #255625;\n}\n.btn-success:active,\n.btn-success.active,\n.open > .dropdown-toggle.btn-success {\n background-image: none;\n}\n.btn-success.disabled:hover,\n.btn-success[disabled]:hover,\nfieldset[disabled] .btn-success:hover,\n.btn-success.disabled:focus,\n.btn-success[disabled]:focus,\nfieldset[disabled] .btn-success:focus,\n.btn-success.disabled.focus,\n.btn-success[disabled].focus,\nfieldset[disabled] .btn-success.focus {\n background-color: #5cb85c;\n border-color: #4cae4c;\n}\n.btn-success .badge {\n color: #5cb85c;\n background-color: #fff;\n}\n.btn-info {\n color: #fff;\n background-color: #5bc0de;\n border-color: #46b8da;\n}\n.btn-info:focus,\n.btn-info.focus {\n color: #fff;\n background-color: #31b0d5;\n border-color: #1b6d85;\n}\n.btn-info:hover {\n color: #fff;\n background-color: #31b0d5;\n border-color: #269abc;\n}\n.btn-info:active,\n.btn-info.active,\n.open > .dropdown-toggle.btn-info {\n color: #fff;\n background-color: #31b0d5;\n border-color: #269abc;\n}\n.btn-info:active:hover,\n.btn-info.active:hover,\n.open > .dropdown-toggle.btn-info:hover,\n.btn-info:active:focus,\n.btn-info.active:focus,\n.open > .dropdown-toggle.btn-info:focus,\n.btn-info:active.focus,\n.btn-info.active.focus,\n.open > .dropdown-toggle.btn-info.focus {\n color: #fff;\n background-color: #269abc;\n border-color: #1b6d85;\n}\n.btn-info:active,\n.btn-info.active,\n.open > .dropdown-toggle.btn-info {\n background-image: none;\n}\n.btn-info.disabled:hover,\n.btn-info[disabled]:hover,\nfieldset[disabled] .btn-info:hover,\n.btn-info.disabled:focus,\n.btn-info[disabled]:focus,\nfieldset[disabled] .btn-info:focus,\n.btn-info.disabled.focus,\n.btn-info[disabled].focus,\nfieldset[disabled] .btn-info.focus {\n background-color: #5bc0de;\n border-color: #46b8da;\n}\n.btn-info .badge {\n color: #5bc0de;\n background-color: #fff;\n}\n.btn-warning {\n color: #fff;\n background-color: #f0ad4e;\n border-color: #eea236;\n}\n.btn-warning:focus,\n.btn-warning.focus {\n color: #fff;\n background-color: #ec971f;\n border-color: #985f0d;\n}\n.btn-warning:hover {\n color: #fff;\n background-color: #ec971f;\n border-color: #d58512;\n}\n.btn-warning:active,\n.btn-warning.active,\n.open > .dropdown-toggle.btn-warning {\n color: #fff;\n background-color: #ec971f;\n border-color: #d58512;\n}\n.btn-warning:active:hover,\n.btn-warning.active:hover,\n.open > .dropdown-toggle.btn-warning:hover,\n.btn-warning:active:focus,\n.btn-warning.active:focus,\n.open > .dropdown-toggle.btn-warning:focus,\n.btn-warning:active.focus,\n.btn-warning.active.focus,\n.open > .dropdown-toggle.btn-warning.focus {\n color: #fff;\n background-color: #d58512;\n border-color: #985f0d;\n}\n.btn-warning:active,\n.btn-warning.active,\n.open > .dropdown-toggle.btn-warning {\n background-image: none;\n}\n.btn-warning.disabled:hover,\n.btn-warning[disabled]:hover,\nfieldset[disabled] .btn-warning:hover,\n.btn-warning.disabled:focus,\n.btn-warning[disabled]:focus,\nfieldset[disabled] .btn-warning:focus,\n.btn-warning.disabled.focus,\n.btn-warning[disabled].focus,\nfieldset[disabled] .btn-warning.focus {\n background-color: #f0ad4e;\n border-color: #eea236;\n}\n.btn-warning .badge {\n color: #f0ad4e;\n background-color: #fff;\n}\n.btn-danger {\n color: #fff;\n background-color: #d9534f;\n border-color: #d43f3a;\n}\n.btn-danger:focus,\n.btn-danger.focus {\n color: #fff;\n background-color: #c9302c;\n border-color: #761c19;\n}\n.btn-danger:hover {\n color: #fff;\n background-color: #c9302c;\n border-color: #ac2925;\n}\n.btn-danger:active,\n.btn-danger.active,\n.open > .dropdown-toggle.btn-danger {\n color: #fff;\n background-color: #c9302c;\n border-color: #ac2925;\n}\n.btn-danger:active:hover,\n.btn-danger.active:hover,\n.open > .dropdown-toggle.btn-danger:hover,\n.btn-danger:active:focus,\n.btn-danger.active:focus,\n.open > .dropdown-toggle.btn-danger:focus,\n.btn-danger:active.focus,\n.btn-danger.active.focus,\n.open > .dropdown-toggle.btn-danger.focus {\n color: #fff;\n background-color: #ac2925;\n border-color: #761c19;\n}\n.btn-danger:active,\n.btn-danger.active,\n.open > .dropdown-toggle.btn-danger {\n background-image: none;\n}\n.btn-danger.disabled:hover,\n.btn-danger[disabled]:hover,\nfieldset[disabled] .btn-danger:hover,\n.btn-danger.disabled:focus,\n.btn-danger[disabled]:focus,\nfieldset[disabled] .btn-danger:focus,\n.btn-danger.disabled.focus,\n.btn-danger[disabled].focus,\nfieldset[disabled] .btn-danger.focus {\n background-color: #d9534f;\n border-color: #d43f3a;\n}\n.btn-danger .badge {\n color: #d9534f;\n background-color: #fff;\n}\n.btn-link {\n font-weight: normal;\n color: #337ab7;\n border-radius: 0;\n}\n.btn-link,\n.btn-link:active,\n.btn-link.active,\n.btn-link[disabled],\nfieldset[disabled] .btn-link {\n background-color: transparent;\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn-link,\n.btn-link:hover,\n.btn-link:focus,\n.btn-link:active {\n border-color: transparent;\n}\n.btn-link:hover,\n.btn-link:focus {\n color: #23527c;\n text-decoration: underline;\n background-color: transparent;\n}\n.btn-link[disabled]:hover,\nfieldset[disabled] .btn-link:hover,\n.btn-link[disabled]:focus,\nfieldset[disabled] .btn-link:focus {\n color: #777;\n text-decoration: none;\n}\n.btn-lg,\n.btn-group-lg > .btn {\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\n.btn-sm,\n.btn-group-sm > .btn {\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.btn-xs,\n.btn-group-xs > .btn {\n padding: 1px 5px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.btn-block {\n display: block;\n width: 100%;\n}\n.btn-block + .btn-block {\n margin-top: 5px;\n}\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n width: 100%;\n}\n.fade {\n opacity: 0;\n -webkit-transition: opacity .15s linear;\n -o-transition: opacity .15s linear;\n transition: opacity .15s linear;\n}\n.fade.in {\n opacity: 1;\n}\n.collapse {\n display: none;\n}\n.collapse.in {\n display: block;\n}\ntr.collapse.in {\n display: table-row;\n}\ntbody.collapse.in {\n display: table-row-group;\n}\n.collapsing {\n position: relative;\n height: 0;\n overflow: hidden;\n -webkit-transition-timing-function: ease;\n -o-transition-timing-function: ease;\n transition-timing-function: ease;\n -webkit-transition-duration: .35s;\n -o-transition-duration: .35s;\n transition-duration: .35s;\n -webkit-transition-property: height, visibility;\n -o-transition-property: height, visibility;\n transition-property: height, visibility;\n}\n.caret {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 2px;\n vertical-align: middle;\n border-top: 4px dashed;\n border-top: 4px solid \\9;\n border-right: 4px solid transparent;\n border-left: 4px solid transparent;\n}\n.dropup,\n.dropdown {\n position: relative;\n}\n.dropdown-toggle:focus {\n outline: 0;\n}\n.dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: 1000;\n display: none;\n float: left;\n min-width: 160px;\n padding: 5px 0;\n margin: 2px 0 0;\n font-size: 14px;\n text-align: left;\n list-style: none;\n background-color: #fff;\n -webkit-background-clip: padding-box;\n background-clip: padding-box;\n border: 1px solid #ccc;\n border: 1px solid rgba(0, 0, 0, .15);\n border-radius: 4px;\n -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175);\n box-shadow: 0 6px 12px rgba(0, 0, 0, .175);\n}\n.dropdown-menu.pull-right {\n right: 0;\n left: auto;\n}\n.dropdown-menu .divider {\n height: 1px;\n margin: 9px 0;\n overflow: hidden;\n background-color: #e5e5e5;\n}\n.dropdown-menu > li > a {\n display: block;\n padding: 3px 20px;\n clear: both;\n font-weight: normal;\n line-height: 1.42857143;\n color: #333;\n white-space: nowrap;\n}\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n color: #262626;\n text-decoration: none;\n background-color: #f5f5f5;\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n color: #fff;\n text-decoration: none;\n background-color: #337ab7;\n outline: 0;\n}\n.dropdown-menu > .disabled > a,\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n color: #777;\n}\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n text-decoration: none;\n cursor: not-allowed;\n background-color: transparent;\n background-image: none;\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n}\n.open > .dropdown-menu {\n display: block;\n}\n.open > a {\n outline: 0;\n}\n.dropdown-menu-right {\n right: 0;\n left: auto;\n}\n.dropdown-menu-left {\n right: auto;\n left: 0;\n}\n.dropdown-header {\n display: block;\n padding: 3px 20px;\n font-size: 12px;\n line-height: 1.42857143;\n color: #777;\n white-space: nowrap;\n}\n.dropdown-backdrop {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 990;\n}\n.pull-right > .dropdown-menu {\n right: 0;\n left: auto;\n}\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n content: \"\";\n border-top: 0;\n border-bottom: 4px dashed;\n border-bottom: 4px solid \\9;\n}\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n top: auto;\n bottom: 100%;\n margin-bottom: 2px;\n}\n@media (min-width: 768px) {\n .navbar-right .dropdown-menu {\n right: 0;\n left: auto;\n }\n .navbar-right .dropdown-menu-left {\n right: auto;\n left: 0;\n }\n}\n.btn-group,\n.btn-group-vertical {\n position: relative;\n display: inline-block;\n vertical-align: middle;\n}\n.btn-group > .btn,\n.btn-group-vertical > .btn {\n position: relative;\n float: left;\n}\n.btn-group > .btn:hover,\n.btn-group-vertical > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group-vertical > .btn:focus,\n.btn-group > .btn:active,\n.btn-group-vertical > .btn:active,\n.btn-group > .btn.active,\n.btn-group-vertical > .btn.active {\n z-index: 2;\n}\n.btn-group .btn + .btn,\n.btn-group .btn + .btn-group,\n.btn-group .btn-group + .btn,\n.btn-group .btn-group + .btn-group {\n margin-left: -1px;\n}\n.btn-toolbar {\n margin-left: -5px;\n}\n.btn-toolbar .btn,\n.btn-toolbar .btn-group,\n.btn-toolbar .input-group {\n float: left;\n}\n.btn-toolbar > .btn,\n.btn-toolbar > .btn-group,\n.btn-toolbar > .input-group {\n margin-left: 5px;\n}\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n border-radius: 0;\n}\n.btn-group > .btn:first-child {\n margin-left: 0;\n}\n.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n}\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group > .btn-group {\n float: left;\n}\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child,\n.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n}\n.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n outline: 0;\n}\n.btn-group > .btn + .dropdown-toggle {\n padding-right: 8px;\n padding-left: 8px;\n}\n.btn-group > .btn-lg + .dropdown-toggle {\n padding-right: 12px;\n padding-left: 12px;\n}\n.btn-group.open .dropdown-toggle {\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);\n}\n.btn-group.open .dropdown-toggle.btn-link {\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn .caret {\n margin-left: 0;\n}\n.btn-lg .caret {\n border-width: 5px 5px 0;\n border-bottom-width: 0;\n}\n.dropup .btn-lg .caret {\n border-width: 0 5px 5px;\n}\n.btn-group-vertical > .btn,\n.btn-group-vertical > .btn-group,\n.btn-group-vertical > .btn-group > .btn {\n display: block;\n float: none;\n width: 100%;\n max-width: 100%;\n}\n.btn-group-vertical > .btn-group > .btn {\n float: none;\n}\n.btn-group-vertical > .btn + .btn,\n.btn-group-vertical > .btn + .btn-group,\n.btn-group-vertical > .btn-group + .btn,\n.btn-group-vertical > .btn-group + .btn-group {\n margin-top: -1px;\n margin-left: 0;\n}\n.btn-group-vertical > .btn:not(:first-child):not(:last-child) {\n border-radius: 0;\n}\n.btn-group-vertical > .btn:first-child:not(:last-child) {\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group-vertical > .btn:last-child:not(:first-child) {\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n border-bottom-right-radius: 4px;\n border-bottom-left-radius: 4px;\n}\n.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child,\n.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle {\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n}\n.btn-group-justified {\n display: table;\n width: 100%;\n table-layout: fixed;\n border-collapse: separate;\n}\n.btn-group-justified > .btn,\n.btn-group-justified > .btn-group {\n display: table-cell;\n float: none;\n width: 1%;\n}\n.btn-group-justified > .btn-group .btn {\n width: 100%;\n}\n.btn-group-justified > .btn-group .dropdown-menu {\n left: auto;\n}\n[data-toggle=\"buttons\"] > .btn input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn-group > .btn input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn input[type=\"checkbox\"],\n[data-toggle=\"buttons\"] > .btn-group > .btn input[type=\"checkbox\"] {\n position: absolute;\n clip: rect(0, 0, 0, 0);\n pointer-events: none;\n}\n.input-group {\n position: relative;\n display: table;\n border-collapse: separate;\n}\n.input-group[class*=\"col-\"] {\n float: none;\n padding-right: 0;\n padding-left: 0;\n}\n.input-group .form-control {\n position: relative;\n z-index: 2;\n float: left;\n width: 100%;\n margin-bottom: 0;\n}\n.input-group .form-control:focus {\n z-index: 3;\n}\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\nselect.input-group-lg > .form-control,\nselect.input-group-lg > .input-group-addon,\nselect.input-group-lg > .input-group-btn > .btn {\n height: 46px;\n line-height: 46px;\n}\ntextarea.input-group-lg > .form-control,\ntextarea.input-group-lg > .input-group-addon,\ntextarea.input-group-lg > .input-group-btn > .btn,\nselect[multiple].input-group-lg > .form-control,\nselect[multiple].input-group-lg > .input-group-addon,\nselect[multiple].input-group-lg > .input-group-btn > .btn {\n height: auto;\n}\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\nselect.input-group-sm > .form-control,\nselect.input-group-sm > .input-group-addon,\nselect.input-group-sm > .input-group-btn > .btn {\n height: 30px;\n line-height: 30px;\n}\ntextarea.input-group-sm > .form-control,\ntextarea.input-group-sm > .input-group-addon,\ntextarea.input-group-sm > .input-group-btn > .btn,\nselect[multiple].input-group-sm > .form-control,\nselect[multiple].input-group-sm > .input-group-addon,\nselect[multiple].input-group-sm > .input-group-btn > .btn {\n height: auto;\n}\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n display: table-cell;\n}\n.input-group-addon:not(:first-child):not(:last-child),\n.input-group-btn:not(:first-child):not(:last-child),\n.input-group .form-control:not(:first-child):not(:last-child) {\n border-radius: 0;\n}\n.input-group-addon,\n.input-group-btn {\n width: 1%;\n white-space: nowrap;\n vertical-align: middle;\n}\n.input-group-addon {\n padding: 6px 12px;\n font-size: 14px;\n font-weight: normal;\n line-height: 1;\n color: #555;\n text-align: center;\n background-color: #eee;\n border: 1px solid #ccc;\n border-radius: 4px;\n}\n.input-group-addon.input-sm {\n padding: 5px 10px;\n font-size: 12px;\n border-radius: 3px;\n}\n.input-group-addon.input-lg {\n padding: 10px 16px;\n font-size: 18px;\n border-radius: 6px;\n}\n.input-group-addon input[type=\"radio\"],\n.input-group-addon input[type=\"checkbox\"] {\n margin-top: 0;\n}\n.input-group .form-control:first-child,\n.input-group-addon:first-child,\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group > .btn,\n.input-group-btn:first-child > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n}\n.input-group-addon:first-child {\n border-right: 0;\n}\n.input-group .form-control:last-child,\n.input-group-addon:last-child,\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group > .btn,\n.input-group-btn:last-child > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child),\n.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n}\n.input-group-addon:last-child {\n border-left: 0;\n}\n.input-group-btn {\n position: relative;\n font-size: 0;\n white-space: nowrap;\n}\n.input-group-btn > .btn {\n position: relative;\n}\n.input-group-btn > .btn + .btn {\n margin-left: -1px;\n}\n.input-group-btn > .btn:hover,\n.input-group-btn > .btn:focus,\n.input-group-btn > .btn:active {\n z-index: 2;\n}\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group {\n margin-right: -1px;\n}\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group {\n z-index: 2;\n margin-left: -1px;\n}\n.nav {\n padding-left: 0;\n margin-bottom: 0;\n list-style: none;\n}\n.nav > li {\n position: relative;\n display: block;\n}\n.nav > li > a {\n position: relative;\n display: block;\n padding: 10px 15px;\n}\n.nav > li > a:hover,\n.nav > li > a:focus {\n text-decoration: none;\n background-color: #eee;\n}\n.nav > li.disabled > a {\n color: #777;\n}\n.nav > li.disabled > a:hover,\n.nav > li.disabled > a:focus {\n color: #777;\n text-decoration: none;\n cursor: not-allowed;\n background-color: transparent;\n}\n.nav .open > a,\n.nav .open > a:hover,\n.nav .open > a:focus {\n background-color: #eee;\n border-color: #337ab7;\n}\n.nav .nav-divider {\n height: 1px;\n margin: 9px 0;\n overflow: hidden;\n background-color: #e5e5e5;\n}\n.nav > li > a > img {\n max-width: none;\n}\n.nav-tabs {\n border-bottom: 1px solid #ddd;\n}\n.nav-tabs > li {\n float: left;\n margin-bottom: -1px;\n}\n.nav-tabs > li > a {\n margin-right: 2px;\n line-height: 1.42857143;\n border: 1px solid transparent;\n border-radius: 4px 4px 0 0;\n}\n.nav-tabs > li > a:hover {\n border-color: #eee #eee #ddd;\n}\n.nav-tabs > li.active > a,\n.nav-tabs > li.active > a:hover,\n.nav-tabs > li.active > a:focus {\n color: #555;\n cursor: default;\n background-color: #fff;\n border: 1px solid #ddd;\n border-bottom-color: transparent;\n}\n.nav-tabs.nav-justified {\n width: 100%;\n border-bottom: 0;\n}\n.nav-tabs.nav-justified > li {\n float: none;\n}\n.nav-tabs.nav-justified > li > a {\n margin-bottom: 5px;\n text-align: center;\n}\n.nav-tabs.nav-justified > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n}\n@media (min-width: 768px) {\n .nav-tabs.nav-justified > li {\n display: table-cell;\n width: 1%;\n }\n .nav-tabs.nav-justified > li > a {\n margin-bottom: 0;\n }\n}\n.nav-tabs.nav-justified > li > a {\n margin-right: 0;\n border-radius: 4px;\n}\n.nav-tabs.nav-justified > .active > a,\n.nav-tabs.nav-justified > .active > a:hover,\n.nav-tabs.nav-justified > .active > a:focus {\n border: 1px solid #ddd;\n}\n@media (min-width: 768px) {\n .nav-tabs.nav-justified > li > a {\n border-bottom: 1px solid #ddd;\n border-radius: 4px 4px 0 0;\n }\n .nav-tabs.nav-justified > .active > a,\n .nav-tabs.nav-justified > .active > a:hover,\n .nav-tabs.nav-justified > .active > a:focus {\n border-bottom-color: #fff;\n }\n}\n.nav-pills > li {\n float: left;\n}\n.nav-pills > li > a {\n border-radius: 4px;\n}\n.nav-pills > li + li {\n margin-left: 2px;\n}\n.nav-pills > li.active > a,\n.nav-pills > li.active > a:hover,\n.nav-pills > li.active > a:focus {\n color: #fff;\n background-color: #337ab7;\n}\n.nav-stacked > li {\n float: none;\n}\n.nav-stacked > li + li {\n margin-top: 2px;\n margin-left: 0;\n}\n.nav-justified {\n width: 100%;\n}\n.nav-justified > li {\n float: none;\n}\n.nav-justified > li > a {\n margin-bottom: 5px;\n text-align: center;\n}\n.nav-justified > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n}\n@media (min-width: 768px) {\n .nav-justified > li {\n display: table-cell;\n width: 1%;\n }\n .nav-justified > li > a {\n margin-bottom: 0;\n }\n}\n.nav-tabs-justified {\n border-bottom: 0;\n}\n.nav-tabs-justified > li > a {\n margin-right: 0;\n border-radius: 4px;\n}\n.nav-tabs-justified > .active > a,\n.nav-tabs-justified > .active > a:hover,\n.nav-tabs-justified > .active > a:focus {\n border: 1px solid #ddd;\n}\n@media (min-width: 768px) {\n .nav-tabs-justified > li > a {\n border-bottom: 1px solid #ddd;\n border-radius: 4px 4px 0 0;\n }\n .nav-tabs-justified > .active > a,\n .nav-tabs-justified > .active > a:hover,\n .nav-tabs-justified > .active > a:focus {\n border-bottom-color: #fff;\n }\n}\n.tab-content > .tab-pane {\n display: none;\n}\n.tab-content > .active {\n display: block;\n}\n.nav-tabs .dropdown-menu {\n margin-top: -1px;\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n}\n.navbar {\n position: relative;\n min-height: 50px;\n margin-bottom: 20px;\n border: 1px solid transparent;\n}\n@media (min-width: 768px) {\n .navbar {\n border-radius: 4px;\n }\n}\n@media (min-width: 768px) {\n .navbar-header {\n float: left;\n }\n}\n.navbar-collapse {\n padding-right: 15px;\n padding-left: 15px;\n overflow-x: visible;\n -webkit-overflow-scrolling: touch;\n border-top: 1px solid transparent;\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1);\n}\n.navbar-collapse.in {\n overflow-y: auto;\n}\n@media (min-width: 768px) {\n .navbar-collapse {\n width: auto;\n border-top: 0;\n -webkit-box-shadow: none;\n box-shadow: none;\n }\n .navbar-collapse.collapse {\n display: block !important;\n height: auto !important;\n padding-bottom: 0;\n overflow: visible !important;\n }\n .navbar-collapse.in {\n overflow-y: visible;\n }\n .navbar-fixed-top .navbar-collapse,\n .navbar-static-top .navbar-collapse,\n .navbar-fixed-bottom .navbar-collapse {\n padding-right: 0;\n padding-left: 0;\n }\n}\n.navbar-fixed-top .navbar-collapse,\n.navbar-fixed-bottom .navbar-collapse {\n max-height: 340px;\n}\n@media (max-device-width: 480px) and (orientation: landscape) {\n .navbar-fixed-top .navbar-collapse,\n .navbar-fixed-bottom .navbar-collapse {\n max-height: 200px;\n }\n}\n.container > .navbar-header,\n.container-fluid > .navbar-header,\n.container > .navbar-collapse,\n.container-fluid > .navbar-collapse {\n margin-right: -15px;\n margin-left: -15px;\n}\n@media (min-width: 768px) {\n .container > .navbar-header,\n .container-fluid > .navbar-header,\n .container > .navbar-collapse,\n .container-fluid > .navbar-collapse {\n margin-right: 0;\n margin-left: 0;\n }\n}\n.navbar-static-top {\n z-index: 1000;\n border-width: 0 0 1px;\n}\n@media (min-width: 768px) {\n .navbar-static-top {\n border-radius: 0;\n }\n}\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n position: fixed;\n right: 0;\n left: 0;\n z-index: 1030;\n}\n@media (min-width: 768px) {\n .navbar-fixed-top,\n .navbar-fixed-bottom {\n border-radius: 0;\n }\n}\n.navbar-fixed-top {\n top: 0;\n border-width: 0 0 1px;\n}\n.navbar-fixed-bottom {\n bottom: 0;\n margin-bottom: 0;\n border-width: 1px 0 0;\n}\n.navbar-brand {\n float: left;\n height: 50px;\n padding: 15px 15px;\n font-size: 18px;\n line-height: 20px;\n}\n.navbar-brand:hover,\n.navbar-brand:focus {\n text-decoration: none;\n}\n.navbar-brand > img {\n display: block;\n}\n@media (min-width: 768px) {\n .navbar > .container .navbar-brand,\n .navbar > .container-fluid .navbar-brand {\n margin-left: -15px;\n }\n}\n.navbar-toggle {\n position: relative;\n float: right;\n padding: 9px 10px;\n margin-top: 8px;\n margin-right: 15px;\n margin-bottom: 8px;\n background-color: transparent;\n background-image: none;\n border: 1px solid transparent;\n border-radius: 4px;\n}\n.navbar-toggle:focus {\n outline: 0;\n}\n.navbar-toggle .icon-bar {\n display: block;\n width: 22px;\n height: 2px;\n border-radius: 1px;\n}\n.navbar-toggle .icon-bar + .icon-bar {\n margin-top: 4px;\n}\n@media (min-width: 768px) {\n .navbar-toggle {\n display: none;\n }\n}\n.navbar-nav {\n margin: 7.5px -15px;\n}\n.navbar-nav > li > a {\n padding-top: 10px;\n padding-bottom: 10px;\n line-height: 20px;\n}\n@media (max-width: 767px) {\n .navbar-nav .open .dropdown-menu {\n position: static;\n float: none;\n width: auto;\n margin-top: 0;\n background-color: transparent;\n border: 0;\n -webkit-box-shadow: none;\n box-shadow: none;\n }\n .navbar-nav .open .dropdown-menu > li > a,\n .navbar-nav .open .dropdown-menu .dropdown-header {\n padding: 5px 15px 5px 25px;\n }\n .navbar-nav .open .dropdown-menu > li > a {\n line-height: 20px;\n }\n .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-nav .open .dropdown-menu > li > a:focus {\n background-image: none;\n }\n}\n@media (min-width: 768px) {\n .navbar-nav {\n float: left;\n margin: 0;\n }\n .navbar-nav > li {\n float: left;\n }\n .navbar-nav > li > a {\n padding-top: 15px;\n padding-bottom: 15px;\n }\n}\n.navbar-form {\n padding: 10px 15px;\n margin-top: 8px;\n margin-right: -15px;\n margin-bottom: 8px;\n margin-left: -15px;\n border-top: 1px solid transparent;\n border-bottom: 1px solid transparent;\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1);\n}\n@media (min-width: 768px) {\n .navbar-form .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .form-control {\n display: inline-block;\n width: auto;\n vertical-align: middle;\n }\n .navbar-form .form-control-static {\n display: inline-block;\n }\n .navbar-form .input-group {\n display: inline-table;\n vertical-align: middle;\n }\n .navbar-form .input-group .input-group-addon,\n .navbar-form .input-group .input-group-btn,\n .navbar-form .input-group .form-control {\n width: auto;\n }\n .navbar-form .input-group > .form-control {\n width: 100%;\n }\n .navbar-form .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .radio,\n .navbar-form .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .radio label,\n .navbar-form .checkbox label {\n padding-left: 0;\n }\n .navbar-form .radio input[type=\"radio\"],\n .navbar-form .checkbox input[type=\"checkbox\"] {\n position: relative;\n margin-left: 0;\n }\n .navbar-form .has-feedback .form-control-feedback {\n top: 0;\n }\n}\n@media (max-width: 767px) {\n .navbar-form .form-group {\n margin-bottom: 5px;\n }\n .navbar-form .form-group:last-child {\n margin-bottom: 0;\n }\n}\n@media (min-width: 768px) {\n .navbar-form {\n width: auto;\n padding-top: 0;\n padding-bottom: 0;\n margin-right: 0;\n margin-left: 0;\n border: 0;\n -webkit-box-shadow: none;\n box-shadow: none;\n }\n}\n.navbar-nav > li > .dropdown-menu {\n margin-top: 0;\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n}\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n margin-bottom: 0;\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.navbar-btn {\n margin-top: 8px;\n margin-bottom: 8px;\n}\n.navbar-btn.btn-sm {\n margin-top: 10px;\n margin-bottom: 10px;\n}\n.navbar-btn.btn-xs {\n margin-top: 14px;\n margin-bottom: 14px;\n}\n.navbar-text {\n margin-top: 15px;\n margin-bottom: 15px;\n}\n@media (min-width: 768px) {\n .navbar-text {\n float: left;\n margin-right: 15px;\n margin-left: 15px;\n }\n}\n@media (min-width: 768px) {\n .navbar-left {\n float: left !important;\n }\n .navbar-right {\n float: right !important;\n margin-right: -15px;\n }\n .navbar-right ~ .navbar-right {\n margin-right: 0;\n }\n}\n.navbar-default {\n background-color: #f8f8f8;\n border-color: #e7e7e7;\n}\n.navbar-default .navbar-brand {\n color: #777;\n}\n.navbar-default .navbar-brand:hover,\n.navbar-default .navbar-brand:focus {\n color: #5e5e5e;\n background-color: transparent;\n}\n.navbar-default .navbar-text {\n color: #777;\n}\n.navbar-default .navbar-nav > li > a {\n color: #777;\n}\n.navbar-default .navbar-nav > li > a:hover,\n.navbar-default .navbar-nav > li > a:focus {\n color: #333;\n background-color: transparent;\n}\n.navbar-default .navbar-nav > .active > a,\n.navbar-default .navbar-nav > .active > a:hover,\n.navbar-default .navbar-nav > .active > a:focus {\n color: #555;\n background-color: #e7e7e7;\n}\n.navbar-default .navbar-nav > .disabled > a,\n.navbar-default .navbar-nav > .disabled > a:hover,\n.navbar-default .navbar-nav > .disabled > a:focus {\n color: #ccc;\n background-color: transparent;\n}\n.navbar-default .navbar-toggle {\n border-color: #ddd;\n}\n.navbar-default .navbar-toggle:hover,\n.navbar-default .navbar-toggle:focus {\n background-color: #ddd;\n}\n.navbar-default .navbar-toggle .icon-bar {\n background-color: #888;\n}\n.navbar-default .navbar-collapse,\n.navbar-default .navbar-form {\n border-color: #e7e7e7;\n}\n.navbar-default .navbar-nav > .open > a,\n.navbar-default .navbar-nav > .open > a:hover,\n.navbar-default .navbar-nav > .open > a:focus {\n color: #555;\n background-color: #e7e7e7;\n}\n@media (max-width: 767px) {\n .navbar-default .navbar-nav .open .dropdown-menu > li > a {\n color: #777;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus {\n color: #333;\n background-color: transparent;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a,\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #555;\n background-color: #e7e7e7;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a,\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n color: #ccc;\n background-color: transparent;\n }\n}\n.navbar-default .navbar-link {\n color: #777;\n}\n.navbar-default .navbar-link:hover {\n color: #333;\n}\n.navbar-default .btn-link {\n color: #777;\n}\n.navbar-default .btn-link:hover,\n.navbar-default .btn-link:focus {\n color: #333;\n}\n.navbar-default .btn-link[disabled]:hover,\nfieldset[disabled] .navbar-default .btn-link:hover,\n.navbar-default .btn-link[disabled]:focus,\nfieldset[disabled] .navbar-default .btn-link:focus {\n color: #ccc;\n}\n.navbar-inverse {\n background-color: #222;\n border-color: #080808;\n}\n.navbar-inverse .navbar-brand {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-brand:hover,\n.navbar-inverse .navbar-brand:focus {\n color: #fff;\n background-color: transparent;\n}\n.navbar-inverse .navbar-text {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-nav > li > a {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-nav > li > a:hover,\n.navbar-inverse .navbar-nav > li > a:focus {\n color: #fff;\n background-color: transparent;\n}\n.navbar-inverse .navbar-nav > .active > a,\n.navbar-inverse .navbar-nav > .active > a:hover,\n.navbar-inverse .navbar-nav > .active > a:focus {\n color: #fff;\n background-color: #080808;\n}\n.navbar-inverse .navbar-nav > .disabled > a,\n.navbar-inverse .navbar-nav > .disabled > a:hover,\n.navbar-inverse .navbar-nav > .disabled > a:focus {\n color: #444;\n background-color: transparent;\n}\n.navbar-inverse .navbar-toggle {\n border-color: #333;\n}\n.navbar-inverse .navbar-toggle:hover,\n.navbar-inverse .navbar-toggle:focus {\n background-color: #333;\n}\n.navbar-inverse .navbar-toggle .icon-bar {\n background-color: #fff;\n}\n.navbar-inverse .navbar-collapse,\n.navbar-inverse .navbar-form {\n border-color: #101010;\n}\n.navbar-inverse .navbar-nav > .open > a,\n.navbar-inverse .navbar-nav > .open > a:hover,\n.navbar-inverse .navbar-nav > .open > a:focus {\n color: #fff;\n background-color: #080808;\n}\n@media (max-width: 767px) {\n .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header {\n border-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu .divider {\n background-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a {\n color: #9d9d9d;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus {\n color: #fff;\n background-color: transparent;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #fff;\n background-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n color: #444;\n background-color: transparent;\n }\n}\n.navbar-inverse .navbar-link {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-link:hover {\n color: #fff;\n}\n.navbar-inverse .btn-link {\n color: #9d9d9d;\n}\n.navbar-inverse .btn-link:hover,\n.navbar-inverse .btn-link:focus {\n color: #fff;\n}\n.navbar-inverse .btn-link[disabled]:hover,\nfieldset[disabled] .navbar-inverse .btn-link:hover,\n.navbar-inverse .btn-link[disabled]:focus,\nfieldset[disabled] .navbar-inverse .btn-link:focus {\n color: #444;\n}\n.breadcrumb {\n padding: 8px 15px;\n margin-bottom: 20px;\n list-style: none;\n background-color: #f5f5f5;\n border-radius: 4px;\n}\n.breadcrumb > li {\n display: inline-block;\n}\n.breadcrumb > li + li:before {\n padding: 0 5px;\n color: #ccc;\n content: \"/\\00a0\";\n}\n.breadcrumb > .active {\n color: #777;\n}\n.pagination {\n display: inline-block;\n padding-left: 0;\n margin: 20px 0;\n border-radius: 4px;\n}\n.pagination > li {\n display: inline;\n}\n.pagination > li > a,\n.pagination > li > span {\n position: relative;\n float: left;\n padding: 6px 12px;\n margin-left: -1px;\n line-height: 1.42857143;\n color: #337ab7;\n text-decoration: none;\n background-color: #fff;\n border: 1px solid #ddd;\n}\n.pagination > li:first-child > a,\n.pagination > li:first-child > span {\n margin-left: 0;\n border-top-left-radius: 4px;\n border-bottom-left-radius: 4px;\n}\n.pagination > li:last-child > a,\n.pagination > li:last-child > span {\n border-top-right-radius: 4px;\n border-bottom-right-radius: 4px;\n}\n.pagination > li > a:hover,\n.pagination > li > span:hover,\n.pagination > li > a:focus,\n.pagination > li > span:focus {\n z-index: 2;\n color: #23527c;\n background-color: #eee;\n border-color: #ddd;\n}\n.pagination > .active > a,\n.pagination > .active > span,\n.pagination > .active > a:hover,\n.pagination > .active > span:hover,\n.pagination > .active > a:focus,\n.pagination > .active > span:focus {\n z-index: 3;\n color: #fff;\n cursor: default;\n background-color: #337ab7;\n border-color: #337ab7;\n}\n.pagination > .disabled > span,\n.pagination > .disabled > span:hover,\n.pagination > .disabled > span:focus,\n.pagination > .disabled > a,\n.pagination > .disabled > a:hover,\n.pagination > .disabled > a:focus {\n color: #777;\n cursor: not-allowed;\n background-color: #fff;\n border-color: #ddd;\n}\n.pagination-lg > li > a,\n.pagination-lg > li > span {\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n}\n.pagination-lg > li:first-child > a,\n.pagination-lg > li:first-child > span {\n border-top-left-radius: 6px;\n border-bottom-left-radius: 6px;\n}\n.pagination-lg > li:last-child > a,\n.pagination-lg > li:last-child > span {\n border-top-right-radius: 6px;\n border-bottom-right-radius: 6px;\n}\n.pagination-sm > li > a,\n.pagination-sm > li > span {\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n}\n.pagination-sm > li:first-child > a,\n.pagination-sm > li:first-child > span {\n border-top-left-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.pagination-sm > li:last-child > a,\n.pagination-sm > li:last-child > span {\n border-top-right-radius: 3px;\n border-bottom-right-radius: 3px;\n}\n.pager {\n padding-left: 0;\n margin: 20px 0;\n text-align: center;\n list-style: none;\n}\n.pager li {\n display: inline;\n}\n.pager li > a,\n.pager li > span {\n display: inline-block;\n padding: 5px 14px;\n background-color: #fff;\n border: 1px solid #ddd;\n border-radius: 15px;\n}\n.pager li > a:hover,\n.pager li > a:focus {\n text-decoration: none;\n background-color: #eee;\n}\n.pager .next > a,\n.pager .next > span {\n float: right;\n}\n.pager .previous > a,\n.pager .previous > span {\n float: left;\n}\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > a:focus,\n.pager .disabled > span {\n color: #777;\n cursor: not-allowed;\n background-color: #fff;\n}\n.label {\n display: inline;\n padding: .2em .6em .3em;\n font-size: 75%;\n font-weight: bold;\n line-height: 1;\n color: #fff;\n text-align: center;\n white-space: nowrap;\n vertical-align: baseline;\n border-radius: .25em;\n}\na.label:hover,\na.label:focus {\n color: #fff;\n text-decoration: none;\n cursor: pointer;\n}\n.label:empty {\n display: none;\n}\n.btn .label {\n position: relative;\n top: -1px;\n}\n.label-default {\n background-color: #777;\n}\n.label-default[href]:hover,\n.label-default[href]:focus {\n background-color: #5e5e5e;\n}\n.label-primary {\n background-color: #337ab7;\n}\n.label-primary[href]:hover,\n.label-primary[href]:focus {\n background-color: #286090;\n}\n.label-success {\n background-color: #5cb85c;\n}\n.label-success[href]:hover,\n.label-success[href]:focus {\n background-color: #449d44;\n}\n.label-info {\n background-color: #5bc0de;\n}\n.label-info[href]:hover,\n.label-info[href]:focus {\n background-color: #31b0d5;\n}\n.label-warning {\n background-color: #f0ad4e;\n}\n.label-warning[href]:hover,\n.label-warning[href]:focus {\n background-color: #ec971f;\n}\n.label-danger {\n background-color: #d9534f;\n}\n.label-danger[href]:hover,\n.label-danger[href]:focus {\n background-color: #c9302c;\n}\n.badge {\n display: inline-block;\n min-width: 10px;\n padding: 3px 7px;\n font-size: 12px;\n font-weight: bold;\n line-height: 1;\n color: #fff;\n text-align: center;\n white-space: nowrap;\n vertical-align: middle;\n background-color: #777;\n border-radius: 10px;\n}\n.badge:empty {\n display: none;\n}\n.btn .badge {\n position: relative;\n top: -1px;\n}\n.btn-xs .badge,\n.btn-group-xs > .btn .badge {\n top: 0;\n padding: 1px 5px;\n}\na.badge:hover,\na.badge:focus {\n color: #fff;\n text-decoration: none;\n cursor: pointer;\n}\n.list-group-item.active > .badge,\n.nav-pills > .active > a > .badge {\n color: #337ab7;\n background-color: #fff;\n}\n.list-group-item > .badge {\n float: right;\n}\n.list-group-item > .badge + .badge {\n margin-right: 5px;\n}\n.nav-pills > li > a > .badge {\n margin-left: 3px;\n}\n.jumbotron {\n padding-top: 30px;\n padding-bottom: 30px;\n margin-bottom: 30px;\n color: inherit;\n background-color: #eee;\n}\n.jumbotron h1,\n.jumbotron .h1 {\n color: inherit;\n}\n.jumbotron p {\n margin-bottom: 15px;\n font-size: 21px;\n font-weight: 200;\n}\n.jumbotron > hr {\n border-top-color: #d5d5d5;\n}\n.container .jumbotron,\n.container-fluid .jumbotron {\n padding-right: 15px;\n padding-left: 15px;\n border-radius: 6px;\n}\n.jumbotron .container {\n max-width: 100%;\n}\n@media screen and (min-width: 768px) {\n .jumbotron {\n padding-top: 48px;\n padding-bottom: 48px;\n }\n .container .jumbotron,\n .container-fluid .jumbotron {\n padding-right: 60px;\n padding-left: 60px;\n }\n .jumbotron h1,\n .jumbotron .h1 {\n font-size: 63px;\n }\n}\n.thumbnail {\n display: block;\n padding: 4px;\n margin-bottom: 20px;\n line-height: 1.42857143;\n background-color: #fff;\n border: 1px solid #ddd;\n border-radius: 4px;\n -webkit-transition: border .2s ease-in-out;\n -o-transition: border .2s ease-in-out;\n transition: border .2s ease-in-out;\n}\n.thumbnail > img,\n.thumbnail a > img {\n margin-right: auto;\n margin-left: auto;\n}\na.thumbnail:hover,\na.thumbnail:focus,\na.thumbnail.active {\n border-color: #337ab7;\n}\n.thumbnail .caption {\n padding: 9px;\n color: #333;\n}\n.alert {\n padding: 15px;\n margin-bottom: 20px;\n border: 1px solid transparent;\n border-radius: 4px;\n}\n.alert h4 {\n margin-top: 0;\n color: inherit;\n}\n.alert .alert-link {\n font-weight: bold;\n}\n.alert > p,\n.alert > ul {\n margin-bottom: 0;\n}\n.alert > p + p {\n margin-top: 5px;\n}\n.alert-dismissable,\n.alert-dismissible {\n padding-right: 35px;\n}\n.alert-dismissable .close,\n.alert-dismissible .close {\n position: relative;\n top: -2px;\n right: -21px;\n color: inherit;\n}\n.alert-success {\n color: #3c763d;\n background-color: #dff0d8;\n border-color: #d6e9c6;\n}\n.alert-success hr {\n border-top-color: #c9e2b3;\n}\n.alert-success .alert-link {\n color: #2b542c;\n}\n.alert-info {\n color: #31708f;\n background-color: #d9edf7;\n border-color: #bce8f1;\n}\n.alert-info hr {\n border-top-color: #a6e1ec;\n}\n.alert-info .alert-link {\n color: #245269;\n}\n.alert-warning {\n color: #8a6d3b;\n background-color: #fcf8e3;\n border-color: #faebcc;\n}\n.alert-warning hr {\n border-top-color: #f7e1b5;\n}\n.alert-warning .alert-link {\n color: #66512c;\n}\n.alert-danger {\n color: #a94442;\n background-color: #f2dede;\n border-color: #ebccd1;\n}\n.alert-danger hr {\n border-top-color: #e4b9c0;\n}\n.alert-danger .alert-link {\n color: #843534;\n}\n@-webkit-keyframes progress-bar-stripes {\n from {\n background-position: 40px 0;\n }\n to {\n background-position: 0 0;\n }\n}\n@-o-keyframes progress-bar-stripes {\n from {\n background-position: 40px 0;\n }\n to {\n background-position: 0 0;\n }\n}\n@keyframes progress-bar-stripes {\n from {\n background-position: 40px 0;\n }\n to {\n background-position: 0 0;\n }\n}\n.progress {\n height: 20px;\n margin-bottom: 20px;\n overflow: hidden;\n background-color: #f5f5f5;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1);\n box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1);\n}\n.progress-bar {\n float: left;\n width: 0;\n height: 100%;\n font-size: 12px;\n line-height: 20px;\n color: #fff;\n text-align: center;\n background-color: #337ab7;\n -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15);\n box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15);\n -webkit-transition: width .6s ease;\n -o-transition: width .6s ease;\n transition: width .6s ease;\n}\n.progress-striped .progress-bar,\n.progress-bar-striped {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n -webkit-background-size: 40px 40px;\n background-size: 40px 40px;\n}\n.progress.active .progress-bar,\n.progress-bar.active {\n -webkit-animation: progress-bar-stripes 2s linear infinite;\n -o-animation: progress-bar-stripes 2s linear infinite;\n animation: progress-bar-stripes 2s linear infinite;\n}\n.progress-bar-success {\n background-color: #5cb85c;\n}\n.progress-striped .progress-bar-success {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n}\n.progress-bar-info {\n background-color: #5bc0de;\n}\n.progress-striped .progress-bar-info {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n}\n.progress-bar-warning {\n background-color: #f0ad4e;\n}\n.progress-striped .progress-bar-warning {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n}\n.progress-bar-danger {\n background-color: #d9534f;\n}\n.progress-striped .progress-bar-danger {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);\n}\n.media {\n margin-top: 15px;\n}\n.media:first-child {\n margin-top: 0;\n}\n.media,\n.media-body {\n overflow: hidden;\n zoom: 1;\n}\n.media-body {\n width: 10000px;\n}\n.media-object {\n display: block;\n}\n.media-object.img-thumbnail {\n max-width: none;\n}\n.media-right,\n.media > .pull-right {\n padding-left: 10px;\n}\n.media-left,\n.media > .pull-left {\n padding-right: 10px;\n}\n.media-left,\n.media-right,\n.media-body {\n display: table-cell;\n vertical-align: top;\n}\n.media-middle {\n vertical-align: middle;\n}\n.media-bottom {\n vertical-align: bottom;\n}\n.media-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n.media-list {\n padding-left: 0;\n list-style: none;\n}\n.list-group {\n padding-left: 0;\n margin-bottom: 20px;\n}\n.list-group-item {\n position: relative;\n display: block;\n padding: 10px 15px;\n margin-bottom: -1px;\n background-color: #fff;\n border: 1px solid #ddd;\n}\n.list-group-item:first-child {\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n}\n.list-group-item:last-child {\n margin-bottom: 0;\n border-bottom-right-radius: 4px;\n border-bottom-left-radius: 4px;\n}\na.list-group-item,\nbutton.list-group-item {\n color: #555;\n}\na.list-group-item .list-group-item-heading,\nbutton.list-group-item .list-group-item-heading {\n color: #333;\n}\na.list-group-item:hover,\nbutton.list-group-item:hover,\na.list-group-item:focus,\nbutton.list-group-item:focus {\n color: #555;\n text-decoration: none;\n background-color: #f5f5f5;\n}\nbutton.list-group-item {\n width: 100%;\n text-align: left;\n}\n.list-group-item.disabled,\n.list-group-item.disabled:hover,\n.list-group-item.disabled:focus {\n color: #777;\n cursor: not-allowed;\n background-color: #eee;\n}\n.list-group-item.disabled .list-group-item-heading,\n.list-group-item.disabled:hover .list-group-item-heading,\n.list-group-item.disabled:focus .list-group-item-heading {\n color: inherit;\n}\n.list-group-item.disabled .list-group-item-text,\n.list-group-item.disabled:hover .list-group-item-text,\n.list-group-item.disabled:focus .list-group-item-text {\n color: #777;\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n z-index: 2;\n color: #fff;\n background-color: #337ab7;\n border-color: #337ab7;\n}\n.list-group-item.active .list-group-item-heading,\n.list-group-item.active:hover .list-group-item-heading,\n.list-group-item.active:focus .list-group-item-heading,\n.list-group-item.active .list-group-item-heading > small,\n.list-group-item.active:hover .list-group-item-heading > small,\n.list-group-item.active:focus .list-group-item-heading > small,\n.list-group-item.active .list-group-item-heading > .small,\n.list-group-item.active:hover .list-group-item-heading > .small,\n.list-group-item.active:focus .list-group-item-heading > .small {\n color: inherit;\n}\n.list-group-item.active .list-group-item-text,\n.list-group-item.active:hover .list-group-item-text,\n.list-group-item.active:focus .list-group-item-text {\n color: #c7ddef;\n}\n.list-group-item-success {\n color: #3c763d;\n background-color: #dff0d8;\n}\na.list-group-item-success,\nbutton.list-group-item-success {\n color: #3c763d;\n}\na.list-group-item-success .list-group-item-heading,\nbutton.list-group-item-success .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-success:hover,\nbutton.list-group-item-success:hover,\na.list-group-item-success:focus,\nbutton.list-group-item-success:focus {\n color: #3c763d;\n background-color: #d0e9c6;\n}\na.list-group-item-success.active,\nbutton.list-group-item-success.active,\na.list-group-item-success.active:hover,\nbutton.list-group-item-success.active:hover,\na.list-group-item-success.active:focus,\nbutton.list-group-item-success.active:focus {\n color: #fff;\n background-color: #3c763d;\n border-color: #3c763d;\n}\n.list-group-item-info {\n color: #31708f;\n background-color: #d9edf7;\n}\na.list-group-item-info,\nbutton.list-group-item-info {\n color: #31708f;\n}\na.list-group-item-info .list-group-item-heading,\nbutton.list-group-item-info .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-info:hover,\nbutton.list-group-item-info:hover,\na.list-group-item-info:focus,\nbutton.list-group-item-info:focus {\n color: #31708f;\n background-color: #c4e3f3;\n}\na.list-group-item-info.active,\nbutton.list-group-item-info.active,\na.list-group-item-info.active:hover,\nbutton.list-group-item-info.active:hover,\na.list-group-item-info.active:focus,\nbutton.list-group-item-info.active:focus {\n color: #fff;\n background-color: #31708f;\n border-color: #31708f;\n}\n.list-group-item-warning {\n color: #8a6d3b;\n background-color: #fcf8e3;\n}\na.list-group-item-warning,\nbutton.list-group-item-warning {\n color: #8a6d3b;\n}\na.list-group-item-warning .list-group-item-heading,\nbutton.list-group-item-warning .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-warning:hover,\nbutton.list-group-item-warning:hover,\na.list-group-item-warning:focus,\nbutton.list-group-item-warning:focus {\n color: #8a6d3b;\n background-color: #faf2cc;\n}\na.list-group-item-warning.active,\nbutton.list-group-item-warning.active,\na.list-group-item-warning.active:hover,\nbutton.list-group-item-warning.active:hover,\na.list-group-item-warning.active:focus,\nbutton.list-group-item-warning.active:focus {\n color: #fff;\n background-color: #8a6d3b;\n border-color: #8a6d3b;\n}\n.list-group-item-danger {\n color: #a94442;\n background-color: #f2dede;\n}\na.list-group-item-danger,\nbutton.list-group-item-danger {\n color: #a94442;\n}\na.list-group-item-danger .list-group-item-heading,\nbutton.list-group-item-danger .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-danger:hover,\nbutton.list-group-item-danger:hover,\na.list-group-item-danger:focus,\nbutton.list-group-item-danger:focus {\n color: #a94442;\n background-color: #ebcccc;\n}\na.list-group-item-danger.active,\nbutton.list-group-item-danger.active,\na.list-group-item-danger.active:hover,\nbutton.list-group-item-danger.active:hover,\na.list-group-item-danger.active:focus,\nbutton.list-group-item-danger.active:focus {\n color: #fff;\n background-color: #a94442;\n border-color: #a94442;\n}\n.list-group-item-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n.list-group-item-text {\n margin-bottom: 0;\n line-height: 1.3;\n}\n.panel {\n margin-bottom: 20px;\n background-color: #fff;\n border: 1px solid transparent;\n border-radius: 4px;\n -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05);\n box-shadow: 0 1px 1px rgba(0, 0, 0, .05);\n}\n.panel-body {\n padding: 15px;\n}\n.panel-heading {\n padding: 10px 15px;\n border-bottom: 1px solid transparent;\n border-top-left-radius: 3px;\n border-top-right-radius: 3px;\n}\n.panel-heading > .dropdown .dropdown-toggle {\n color: inherit;\n}\n.panel-title {\n margin-top: 0;\n margin-bottom: 0;\n font-size: 16px;\n color: inherit;\n}\n.panel-title > a,\n.panel-title > small,\n.panel-title > .small,\n.panel-title > small > a,\n.panel-title > .small > a {\n color: inherit;\n}\n.panel-footer {\n padding: 10px 15px;\n background-color: #f5f5f5;\n border-top: 1px solid #ddd;\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .list-group,\n.panel > .panel-collapse > .list-group {\n margin-bottom: 0;\n}\n.panel > .list-group .list-group-item,\n.panel > .panel-collapse > .list-group .list-group-item {\n border-width: 1px 0;\n border-radius: 0;\n}\n.panel > .list-group:first-child .list-group-item:first-child,\n.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child {\n border-top: 0;\n border-top-left-radius: 3px;\n border-top-right-radius: 3px;\n}\n.panel > .list-group:last-child .list-group-item:last-child,\n.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child {\n border-bottom: 0;\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .panel-heading + .panel-collapse > .list-group .list-group-item:first-child {\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n}\n.panel-heading + .list-group .list-group-item:first-child {\n border-top-width: 0;\n}\n.list-group + .panel-footer {\n border-top-width: 0;\n}\n.panel > .table,\n.panel > .table-responsive > .table,\n.panel > .panel-collapse > .table {\n margin-bottom: 0;\n}\n.panel > .table caption,\n.panel > .table-responsive > .table caption,\n.panel > .panel-collapse > .table caption {\n padding-right: 15px;\n padding-left: 15px;\n}\n.panel > .table:first-child,\n.panel > .table-responsive:first-child > .table:first-child {\n border-top-left-radius: 3px;\n border-top-right-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child {\n border-top-left-radius: 3px;\n border-top-right-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child td:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child,\n.panel > .table:first-child > thead:first-child > tr:first-child th:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child {\n border-top-left-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child td:last-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child,\n.panel > .table:first-child > thead:first-child > tr:first-child th:last-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child {\n border-top-right-radius: 3px;\n}\n.panel > .table:last-child,\n.panel > .table-responsive:last-child > .table:last-child {\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child {\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child {\n border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child {\n border-bottom-right-radius: 3px;\n}\n.panel > .panel-body + .table,\n.panel > .panel-body + .table-responsive,\n.panel > .table + .panel-body,\n.panel > .table-responsive + .panel-body {\n border-top: 1px solid #ddd;\n}\n.panel > .table > tbody:first-child > tr:first-child th,\n.panel > .table > tbody:first-child > tr:first-child td {\n border-top: 0;\n}\n.panel > .table-bordered,\n.panel > .table-responsive > .table-bordered {\n border: 0;\n}\n.panel > .table-bordered > thead > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > thead > tr > th:first-child,\n.panel > .table-bordered > tbody > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child,\n.panel > .table-bordered > tfoot > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n.panel > .table-bordered > thead > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > thead > tr > td:first-child,\n.panel > .table-bordered > tbody > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child,\n.panel > .table-bordered > tfoot > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n border-left: 0;\n}\n.panel > .table-bordered > thead > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > thead > tr > th:last-child,\n.panel > .table-bordered > tbody > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child,\n.panel > .table-bordered > tfoot > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n.panel > .table-bordered > thead > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > thead > tr > td:last-child,\n.panel > .table-bordered > tbody > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child,\n.panel > .table-bordered > tfoot > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n border-right: 0;\n}\n.panel > .table-bordered > thead > tr:first-child > td,\n.panel > .table-responsive > .table-bordered > thead > tr:first-child > td,\n.panel > .table-bordered > tbody > tr:first-child > td,\n.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td,\n.panel > .table-bordered > thead > tr:first-child > th,\n.panel > .table-responsive > .table-bordered > thead > tr:first-child > th,\n.panel > .table-bordered > tbody > tr:first-child > th,\n.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th {\n border-bottom: 0;\n}\n.panel > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-bordered > tfoot > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td,\n.panel > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-bordered > tfoot > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th {\n border-bottom: 0;\n}\n.panel > .table-responsive {\n margin-bottom: 0;\n border: 0;\n}\n.panel-group {\n margin-bottom: 20px;\n}\n.panel-group .panel {\n margin-bottom: 0;\n border-radius: 4px;\n}\n.panel-group .panel + .panel {\n margin-top: 5px;\n}\n.panel-group .panel-heading {\n border-bottom: 0;\n}\n.panel-group .panel-heading + .panel-collapse > .panel-body,\n.panel-group .panel-heading + .panel-collapse > .list-group {\n border-top: 1px solid #ddd;\n}\n.panel-group .panel-footer {\n border-top: 0;\n}\n.panel-group .panel-footer + .panel-collapse .panel-body {\n border-bottom: 1px solid #ddd;\n}\n.panel-default {\n border-color: #ddd;\n}\n.panel-default > .panel-heading {\n color: #333;\n background-color: #f5f5f5;\n border-color: #ddd;\n}\n.panel-default > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #ddd;\n}\n.panel-default > .panel-heading .badge {\n color: #f5f5f5;\n background-color: #333;\n}\n.panel-default > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #ddd;\n}\n.panel-primary {\n border-color: #337ab7;\n}\n.panel-primary > .panel-heading {\n color: #fff;\n background-color: #337ab7;\n border-color: #337ab7;\n}\n.panel-primary > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #337ab7;\n}\n.panel-primary > .panel-heading .badge {\n color: #337ab7;\n background-color: #fff;\n}\n.panel-primary > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #337ab7;\n}\n.panel-success {\n border-color: #d6e9c6;\n}\n.panel-success > .panel-heading {\n color: #3c763d;\n background-color: #dff0d8;\n border-color: #d6e9c6;\n}\n.panel-success > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #d6e9c6;\n}\n.panel-success > .panel-heading .badge {\n color: #dff0d8;\n background-color: #3c763d;\n}\n.panel-success > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #d6e9c6;\n}\n.panel-info {\n border-color: #bce8f1;\n}\n.panel-info > .panel-heading {\n color: #31708f;\n background-color: #d9edf7;\n border-color: #bce8f1;\n}\n.panel-info > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #bce8f1;\n}\n.panel-info > .panel-heading .badge {\n color: #d9edf7;\n background-color: #31708f;\n}\n.panel-info > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #bce8f1;\n}\n.panel-warning {\n border-color: #faebcc;\n}\n.panel-warning > .panel-heading {\n color: #8a6d3b;\n background-color: #fcf8e3;\n border-color: #faebcc;\n}\n.panel-warning > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #faebcc;\n}\n.panel-warning > .panel-heading .badge {\n color: #fcf8e3;\n background-color: #8a6d3b;\n}\n.panel-warning > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #faebcc;\n}\n.panel-danger {\n border-color: #ebccd1;\n}\n.panel-danger > .panel-heading {\n color: #a94442;\n background-color: #f2dede;\n border-color: #ebccd1;\n}\n.panel-danger > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #ebccd1;\n}\n.panel-danger > .panel-heading .badge {\n color: #f2dede;\n background-color: #a94442;\n}\n.panel-danger > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #ebccd1;\n}\n.embed-responsive {\n position: relative;\n display: block;\n height: 0;\n padding: 0;\n overflow: hidden;\n}\n.embed-responsive .embed-responsive-item,\n.embed-responsive iframe,\n.embed-responsive embed,\n.embed-responsive object,\n.embed-responsive video {\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n width: 100%;\n height: 100%;\n border: 0;\n}\n.embed-responsive-16by9 {\n padding-bottom: 56.25%;\n}\n.embed-responsive-4by3 {\n padding-bottom: 75%;\n}\n.well {\n min-height: 20px;\n padding: 19px;\n margin-bottom: 20px;\n background-color: #f5f5f5;\n border: 1px solid #e3e3e3;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05);\n}\n.well blockquote {\n border-color: #ddd;\n border-color: rgba(0, 0, 0, .15);\n}\n.well-lg {\n padding: 24px;\n border-radius: 6px;\n}\n.well-sm {\n padding: 9px;\n border-radius: 3px;\n}\n.close {\n float: right;\n font-size: 21px;\n font-weight: bold;\n line-height: 1;\n color: #000;\n text-shadow: 0 1px 0 #fff;\n filter: alpha(opacity=20);\n opacity: .2;\n}\n.close:hover,\n.close:focus {\n color: #000;\n text-decoration: none;\n cursor: pointer;\n filter: alpha(opacity=50);\n opacity: .5;\n}\nbutton.close {\n -webkit-appearance: none;\n padding: 0;\n cursor: pointer;\n background: transparent;\n border: 0;\n}\n.modal-open {\n overflow: hidden;\n}\n.modal {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1050;\n display: none;\n overflow: hidden;\n -webkit-overflow-scrolling: touch;\n outline: 0;\n}\n.modal.fade .modal-dialog {\n -webkit-transition: -webkit-transform .3s ease-out;\n -o-transition: -o-transform .3s ease-out;\n transition: transform .3s ease-out;\n -webkit-transform: translate(0, -25%);\n -ms-transform: translate(0, -25%);\n -o-transform: translate(0, -25%);\n transform: translate(0, -25%);\n}\n.modal.in .modal-dialog {\n -webkit-transform: translate(0, 0);\n -ms-transform: translate(0, 0);\n -o-transform: translate(0, 0);\n transform: translate(0, 0);\n}\n.modal-open .modal {\n overflow-x: hidden;\n overflow-y: auto;\n}\n.modal-dialog {\n position: relative;\n width: auto;\n margin: 10px;\n}\n.modal-content {\n position: relative;\n background-color: #fff;\n -webkit-background-clip: padding-box;\n background-clip: padding-box;\n border: 1px solid #999;\n border: 1px solid rgba(0, 0, 0, .2);\n border-radius: 6px;\n outline: 0;\n -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, .5);\n box-shadow: 0 3px 9px rgba(0, 0, 0, .5);\n}\n.modal-backdrop {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1040;\n background-color: #000;\n}\n.modal-backdrop.fade {\n filter: alpha(opacity=0);\n opacity: 0;\n}\n.modal-backdrop.in {\n filter: alpha(opacity=50);\n opacity: .5;\n}\n.modal-header {\n padding: 15px;\n border-bottom: 1px solid #e5e5e5;\n}\n.modal-header .close {\n margin-top: -2px;\n}\n.modal-title {\n margin: 0;\n line-height: 1.42857143;\n}\n.modal-body {\n position: relative;\n padding: 15px;\n}\n.modal-footer {\n padding: 15px;\n text-align: right;\n border-top: 1px solid #e5e5e5;\n}\n.modal-footer .btn + .btn {\n margin-bottom: 0;\n margin-left: 5px;\n}\n.modal-footer .btn-group .btn + .btn {\n margin-left: -1px;\n}\n.modal-footer .btn-block + .btn-block {\n margin-left: 0;\n}\n.modal-scrollbar-measure {\n position: absolute;\n top: -9999px;\n width: 50px;\n height: 50px;\n overflow: scroll;\n}\n@media (min-width: 768px) {\n .modal-dialog {\n width: 600px;\n margin: 30px auto;\n }\n .modal-content {\n -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5);\n box-shadow: 0 5px 15px rgba(0, 0, 0, .5);\n }\n .modal-sm {\n width: 300px;\n }\n}\n@media (min-width: 992px) {\n .modal-lg {\n width: 900px;\n }\n}\n.tooltip {\n position: absolute;\n z-index: 1070;\n display: block;\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-size: 12px;\n font-style: normal;\n font-weight: normal;\n line-height: 1.42857143;\n text-align: left;\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n letter-spacing: normal;\n word-break: normal;\n word-spacing: normal;\n word-wrap: normal;\n white-space: normal;\n filter: alpha(opacity=0);\n opacity: 0;\n\n line-break: auto;\n}\n.tooltip.in {\n filter: alpha(opacity=90);\n opacity: .9;\n}\n.tooltip.top {\n padding: 5px 0;\n margin-top: -3px;\n}\n.tooltip.right {\n padding: 0 5px;\n margin-left: 3px;\n}\n.tooltip.bottom {\n padding: 5px 0;\n margin-top: 3px;\n}\n.tooltip.left {\n padding: 0 5px;\n margin-left: -3px;\n}\n.tooltip-inner {\n max-width: 200px;\n padding: 3px 8px;\n color: #fff;\n text-align: center;\n background-color: #000;\n border-radius: 4px;\n}\n.tooltip-arrow {\n position: absolute;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n}\n.tooltip.top .tooltip-arrow {\n bottom: 0;\n left: 50%;\n margin-left: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000;\n}\n.tooltip.top-left .tooltip-arrow {\n right: 5px;\n bottom: 0;\n margin-bottom: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000;\n}\n.tooltip.top-right .tooltip-arrow {\n bottom: 0;\n left: 5px;\n margin-bottom: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000;\n}\n.tooltip.right .tooltip-arrow {\n top: 50%;\n left: 0;\n margin-top: -5px;\n border-width: 5px 5px 5px 0;\n border-right-color: #000;\n}\n.tooltip.left .tooltip-arrow {\n top: 50%;\n right: 0;\n margin-top: -5px;\n border-width: 5px 0 5px 5px;\n border-left-color: #000;\n}\n.tooltip.bottom .tooltip-arrow {\n top: 0;\n left: 50%;\n margin-left: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000;\n}\n.tooltip.bottom-left .tooltip-arrow {\n top: 0;\n right: 5px;\n margin-top: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000;\n}\n.tooltip.bottom-right .tooltip-arrow {\n top: 0;\n left: 5px;\n margin-top: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000;\n}\n.popover {\n position: absolute;\n top: 0;\n left: 0;\n z-index: 1060;\n display: none;\n max-width: 276px;\n padding: 1px;\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-size: 14px;\n font-style: normal;\n font-weight: normal;\n line-height: 1.42857143;\n text-align: left;\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n letter-spacing: normal;\n word-break: normal;\n word-spacing: normal;\n word-wrap: normal;\n white-space: normal;\n background-color: #fff;\n -webkit-background-clip: padding-box;\n background-clip: padding-box;\n border: 1px solid #ccc;\n border: 1px solid rgba(0, 0, 0, .2);\n border-radius: 6px;\n -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, .2);\n box-shadow: 0 5px 10px rgba(0, 0, 0, .2);\n\n line-break: auto;\n}\n.popover.top {\n margin-top: -10px;\n}\n.popover.right {\n margin-left: 10px;\n}\n.popover.bottom {\n margin-top: 10px;\n}\n.popover.left {\n margin-left: -10px;\n}\n.popover-title {\n padding: 8px 14px;\n margin: 0;\n font-size: 14px;\n background-color: #f7f7f7;\n border-bottom: 1px solid #ebebeb;\n border-radius: 5px 5px 0 0;\n}\n.popover-content {\n padding: 9px 14px;\n}\n.popover > .arrow,\n.popover > .arrow:after {\n position: absolute;\n display: block;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n}\n.popover > .arrow {\n border-width: 11px;\n}\n.popover > .arrow:after {\n content: \"\";\n border-width: 10px;\n}\n.popover.top > .arrow {\n bottom: -11px;\n left: 50%;\n margin-left: -11px;\n border-top-color: #999;\n border-top-color: rgba(0, 0, 0, .25);\n border-bottom-width: 0;\n}\n.popover.top > .arrow:after {\n bottom: 1px;\n margin-left: -10px;\n content: \" \";\n border-top-color: #fff;\n border-bottom-width: 0;\n}\n.popover.right > .arrow {\n top: 50%;\n left: -11px;\n margin-top: -11px;\n border-right-color: #999;\n border-right-color: rgba(0, 0, 0, .25);\n border-left-width: 0;\n}\n.popover.right > .arrow:after {\n bottom: -10px;\n left: 1px;\n content: \" \";\n border-right-color: #fff;\n border-left-width: 0;\n}\n.popover.bottom > .arrow {\n top: -11px;\n left: 50%;\n margin-left: -11px;\n border-top-width: 0;\n border-bottom-color: #999;\n border-bottom-color: rgba(0, 0, 0, .25);\n}\n.popover.bottom > .arrow:after {\n top: 1px;\n margin-left: -10px;\n content: \" \";\n border-top-width: 0;\n border-bottom-color: #fff;\n}\n.popover.left > .arrow {\n top: 50%;\n right: -11px;\n margin-top: -11px;\n border-right-width: 0;\n border-left-color: #999;\n border-left-color: rgba(0, 0, 0, .25);\n}\n.popover.left > .arrow:after {\n right: 1px;\n bottom: -10px;\n content: \" \";\n border-right-width: 0;\n border-left-color: #fff;\n}\n.carousel {\n position: relative;\n}\n.carousel-inner {\n position: relative;\n width: 100%;\n overflow: hidden;\n}\n.carousel-inner > .item {\n position: relative;\n display: none;\n -webkit-transition: .6s ease-in-out left;\n -o-transition: .6s ease-in-out left;\n transition: .6s ease-in-out left;\n}\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n line-height: 1;\n}\n@media all and (transform-3d), (-webkit-transform-3d) {\n .carousel-inner > .item {\n -webkit-transition: -webkit-transform .6s ease-in-out;\n -o-transition: -o-transform .6s ease-in-out;\n transition: transform .6s ease-in-out;\n\n -webkit-backface-visibility: hidden;\n backface-visibility: hidden;\n -webkit-perspective: 1000px;\n perspective: 1000px;\n }\n .carousel-inner > .item.next,\n .carousel-inner > .item.active.right {\n left: 0;\n -webkit-transform: translate3d(100%, 0, 0);\n transform: translate3d(100%, 0, 0);\n }\n .carousel-inner > .item.prev,\n .carousel-inner > .item.active.left {\n left: 0;\n -webkit-transform: translate3d(-100%, 0, 0);\n transform: translate3d(-100%, 0, 0);\n }\n .carousel-inner > .item.next.left,\n .carousel-inner > .item.prev.right,\n .carousel-inner > .item.active {\n left: 0;\n -webkit-transform: translate3d(0, 0, 0);\n transform: translate3d(0, 0, 0);\n }\n}\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n display: block;\n}\n.carousel-inner > .active {\n left: 0;\n}\n.carousel-inner > .next,\n.carousel-inner > .prev {\n position: absolute;\n top: 0;\n width: 100%;\n}\n.carousel-inner > .next {\n left: 100%;\n}\n.carousel-inner > .prev {\n left: -100%;\n}\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n left: 0;\n}\n.carousel-inner > .active.left {\n left: -100%;\n}\n.carousel-inner > .active.right {\n left: 100%;\n}\n.carousel-control {\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n width: 15%;\n font-size: 20px;\n color: #fff;\n text-align: center;\n text-shadow: 0 1px 2px rgba(0, 0, 0, .6);\n background-color: rgba(0, 0, 0, 0);\n filter: alpha(opacity=50);\n opacity: .5;\n}\n.carousel-control.left {\n background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%);\n background-image: -o-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%);\n background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .5)), to(rgba(0, 0, 0, .0001)));\n background-image: linear-gradient(to right, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);\n background-repeat: repeat-x;\n}\n.carousel-control.right {\n right: 0;\n left: auto;\n background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%);\n background-image: -o-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%);\n background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .0001)), to(rgba(0, 0, 0, .5)));\n background-image: linear-gradient(to right, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);\n background-repeat: repeat-x;\n}\n.carousel-control:hover,\n.carousel-control:focus {\n color: #fff;\n text-decoration: none;\n filter: alpha(opacity=90);\n outline: 0;\n opacity: .9;\n}\n.carousel-control .icon-prev,\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-left,\n.carousel-control .glyphicon-chevron-right {\n position: absolute;\n top: 50%;\n z-index: 5;\n display: inline-block;\n margin-top: -10px;\n}\n.carousel-control .icon-prev,\n.carousel-control .glyphicon-chevron-left {\n left: 50%;\n margin-left: -10px;\n}\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-right {\n right: 50%;\n margin-right: -10px;\n}\n.carousel-control .icon-prev,\n.carousel-control .icon-next {\n width: 20px;\n height: 20px;\n font-family: serif;\n line-height: 1;\n}\n.carousel-control .icon-prev:before {\n content: '\\2039';\n}\n.carousel-control .icon-next:before {\n content: '\\203a';\n}\n.carousel-indicators {\n position: absolute;\n bottom: 10px;\n left: 50%;\n z-index: 15;\n width: 60%;\n padding-left: 0;\n margin-left: -30%;\n text-align: center;\n list-style: none;\n}\n.carousel-indicators li {\n display: inline-block;\n width: 10px;\n height: 10px;\n margin: 1px;\n text-indent: -999px;\n cursor: pointer;\n background-color: #000 \\9;\n background-color: rgba(0, 0, 0, 0);\n border: 1px solid #fff;\n border-radius: 10px;\n}\n.carousel-indicators .active {\n width: 12px;\n height: 12px;\n margin: 0;\n background-color: #fff;\n}\n.carousel-caption {\n position: absolute;\n right: 15%;\n bottom: 20px;\n left: 15%;\n z-index: 10;\n padding-top: 20px;\n padding-bottom: 20px;\n color: #fff;\n text-align: center;\n text-shadow: 0 1px 2px rgba(0, 0, 0, .6);\n}\n.carousel-caption .btn {\n text-shadow: none;\n}\n@media screen and (min-width: 768px) {\n .carousel-control .glyphicon-chevron-left,\n .carousel-control .glyphicon-chevron-right,\n .carousel-control .icon-prev,\n .carousel-control .icon-next {\n width: 30px;\n height: 30px;\n margin-top: -10px;\n font-size: 30px;\n }\n .carousel-control .glyphicon-chevron-left,\n .carousel-control .icon-prev {\n margin-left: -10px;\n }\n .carousel-control .glyphicon-chevron-right,\n .carousel-control .icon-next {\n margin-right: -10px;\n }\n .carousel-caption {\n right: 20%;\n left: 20%;\n padding-bottom: 30px;\n }\n .carousel-indicators {\n bottom: 20px;\n }\n}\n.clearfix:before,\n.clearfix:after,\n.dl-horizontal dd:before,\n.dl-horizontal dd:after,\n.container:before,\n.container:after,\n.container-fluid:before,\n.container-fluid:after,\n.row:before,\n.row:after,\n.form-horizontal .form-group:before,\n.form-horizontal .form-group:after,\n.btn-toolbar:before,\n.btn-toolbar:after,\n.btn-group-vertical > .btn-group:before,\n.btn-group-vertical > .btn-group:after,\n.nav:before,\n.nav:after,\n.navbar:before,\n.navbar:after,\n.navbar-header:before,\n.navbar-header:after,\n.navbar-collapse:before,\n.navbar-collapse:after,\n.pager:before,\n.pager:after,\n.panel-body:before,\n.panel-body:after,\n.modal-header:before,\n.modal-header:after,\n.modal-footer:before,\n.modal-footer:after {\n display: table;\n content: \" \";\n}\n.clearfix:after,\n.dl-horizontal dd:after,\n.container:after,\n.container-fluid:after,\n.row:after,\n.form-horizontal .form-group:after,\n.btn-toolbar:after,\n.btn-group-vertical > .btn-group:after,\n.nav:after,\n.navbar:after,\n.navbar-header:after,\n.navbar-collapse:after,\n.pager:after,\n.panel-body:after,\n.modal-header:after,\n.modal-footer:after {\n clear: both;\n}\n.center-block {\n display: block;\n margin-right: auto;\n margin-left: auto;\n}\n.pull-right {\n float: right !important;\n}\n.pull-left {\n float: left !important;\n}\n.hide {\n display: none !important;\n}\n.show {\n display: block !important;\n}\n.invisible {\n visibility: hidden;\n}\n.text-hide {\n font: 0/0 a;\n color: transparent;\n text-shadow: none;\n background-color: transparent;\n border: 0;\n}\n.hidden {\n display: none !important;\n}\n.affix {\n position: fixed;\n}\n@-ms-viewport {\n width: device-width;\n}\n.visible-xs,\n.visible-sm,\n.visible-md,\n.visible-lg {\n display: none !important;\n}\n.visible-xs-block,\n.visible-xs-inline,\n.visible-xs-inline-block,\n.visible-sm-block,\n.visible-sm-inline,\n.visible-sm-inline-block,\n.visible-md-block,\n.visible-md-inline,\n.visible-md-inline-block,\n.visible-lg-block,\n.visible-lg-inline,\n.visible-lg-inline-block {\n display: none !important;\n}\n@media (max-width: 767px) {\n .visible-xs {\n display: block !important;\n }\n table.visible-xs {\n display: table !important;\n }\n tr.visible-xs {\n display: table-row !important;\n }\n th.visible-xs,\n td.visible-xs {\n display: table-cell !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-block {\n display: block !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-inline {\n display: inline !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm {\n display: block !important;\n }\n table.visible-sm {\n display: table !important;\n }\n tr.visible-sm {\n display: table-row !important;\n }\n th.visible-sm,\n td.visible-sm {\n display: table-cell !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-block {\n display: block !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-inline {\n display: inline !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md {\n display: block !important;\n }\n table.visible-md {\n display: table !important;\n }\n tr.visible-md {\n display: table-row !important;\n }\n th.visible-md,\n td.visible-md {\n display: table-cell !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-block {\n display: block !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-inline {\n display: inline !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg {\n display: block !important;\n }\n table.visible-lg {\n display: table !important;\n }\n tr.visible-lg {\n display: table-row !important;\n }\n th.visible-lg,\n td.visible-lg {\n display: table-cell !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-block {\n display: block !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-inline {\n display: inline !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-inline-block {\n display: inline-block !important;\n }\n}\n@media (max-width: 767px) {\n .hidden-xs {\n display: none !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .hidden-sm {\n display: none !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .hidden-md {\n display: none !important;\n }\n}\n@media (min-width: 1200px) {\n .hidden-lg {\n display: none !important;\n }\n}\n.visible-print {\n display: none !important;\n}\n@media print {\n .visible-print {\n display: block !important;\n }\n table.visible-print {\n display: table !important;\n }\n tr.visible-print {\n display: table-row !important;\n }\n th.visible-print,\n td.visible-print {\n display: table-cell !important;\n }\n}\n.visible-print-block {\n display: none !important;\n}\n@media print {\n .visible-print-block {\n display: block !important;\n }\n}\n.visible-print-inline {\n display: none !important;\n}\n@media print {\n .visible-print-inline {\n display: inline !important;\n }\n}\n.visible-print-inline-block {\n display: none !important;\n}\n@media print {\n .visible-print-inline-block {\n display: inline-block !important;\n }\n}\n@media print {\n .hidden-print {\n display: none !important;\n }\n}\n/*# sourceMappingURL=bootstrap.css.map */\n","//\n// Glyphicons for Bootstrap\n//\n// Since icons are fonts, they can be placed anywhere text is placed and are\n// thus automatically sized to match the surrounding child. To use, create an\n// inline element with the appropriate classes, like so:\n//\n// Star\n\n// Import the fonts\n@font-face {\n font-family: 'Glyphicons Halflings';\n src: url('@{icon-font-path}@{icon-font-name}.eot');\n src: url('@{icon-font-path}@{icon-font-name}.eot?#iefix') format('embedded-opentype'),\n url('@{icon-font-path}@{icon-font-name}.woff2') format('woff2'),\n url('@{icon-font-path}@{icon-font-name}.woff') format('woff'),\n url('@{icon-font-path}@{icon-font-name}.ttf') format('truetype'),\n url('@{icon-font-path}@{icon-font-name}.svg#@{icon-font-svg-id}') format('svg');\n}\n\n// Catchall baseclass\n.glyphicon {\n position: relative;\n top: 1px;\n display: inline-block;\n font-family: 'Glyphicons Halflings';\n font-style: normal;\n font-weight: normal;\n line-height: 1;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\n// Individual icons\n.glyphicon-asterisk { &:before { content: \"\\002a\"; } }\n.glyphicon-plus { &:before { content: \"\\002b\"; } }\n.glyphicon-euro,\n.glyphicon-eur { &:before { content: \"\\20ac\"; } }\n.glyphicon-minus { &:before { content: \"\\2212\"; } }\n.glyphicon-cloud { &:before { content: \"\\2601\"; } }\n.glyphicon-envelope { &:before { content: \"\\2709\"; } }\n.glyphicon-pencil { &:before { content: \"\\270f\"; } }\n.glyphicon-glass { &:before { content: \"\\e001\"; } }\n.glyphicon-music { &:before { content: \"\\e002\"; } }\n.glyphicon-search { &:before { content: \"\\e003\"; } }\n.glyphicon-heart { &:before { content: \"\\e005\"; } }\n.glyphicon-star { &:before { content: \"\\e006\"; } }\n.glyphicon-star-empty { &:before { content: \"\\e007\"; } }\n.glyphicon-user { &:before { content: \"\\e008\"; } }\n.glyphicon-film { &:before { content: \"\\e009\"; } }\n.glyphicon-th-large { &:before { content: \"\\e010\"; } }\n.glyphicon-th { &:before { content: \"\\e011\"; } }\n.glyphicon-th-list { &:before { content: \"\\e012\"; } }\n.glyphicon-ok { &:before { content: \"\\e013\"; } }\n.glyphicon-remove { &:before { content: \"\\e014\"; } }\n.glyphicon-zoom-in { &:before { content: \"\\e015\"; } }\n.glyphicon-zoom-out { &:before { content: \"\\e016\"; } }\n.glyphicon-off { &:before { content: \"\\e017\"; } }\n.glyphicon-signal { &:before { content: \"\\e018\"; } }\n.glyphicon-cog { &:before { content: \"\\e019\"; } }\n.glyphicon-trash { &:before { content: \"\\e020\"; } }\n.glyphicon-home { &:before { content: \"\\e021\"; } }\n.glyphicon-file { &:before { content: \"\\e022\"; } }\n.glyphicon-time { &:before { content: \"\\e023\"; } }\n.glyphicon-road { &:before { content: \"\\e024\"; } }\n.glyphicon-download-alt { &:before { content: \"\\e025\"; } }\n.glyphicon-download { &:before { content: \"\\e026\"; } }\n.glyphicon-upload { &:before { content: \"\\e027\"; } }\n.glyphicon-inbox { &:before { content: \"\\e028\"; } }\n.glyphicon-play-circle { &:before { content: \"\\e029\"; } }\n.glyphicon-repeat { &:before { content: \"\\e030\"; } }\n.glyphicon-refresh { &:before { content: \"\\e031\"; } }\n.glyphicon-list-alt { &:before { content: \"\\e032\"; } }\n.glyphicon-lock { &:before { content: \"\\e033\"; } }\n.glyphicon-flag { &:before { content: \"\\e034\"; } }\n.glyphicon-headphones { &:before { content: \"\\e035\"; } }\n.glyphicon-volume-off { &:before { content: \"\\e036\"; } }\n.glyphicon-volume-down { &:before { content: \"\\e037\"; } }\n.glyphicon-volume-up { &:before { content: \"\\e038\"; } }\n.glyphicon-qrcode { &:before { content: \"\\e039\"; } }\n.glyphicon-barcode { &:before { content: \"\\e040\"; } }\n.glyphicon-tag { &:before { content: \"\\e041\"; } }\n.glyphicon-tags { &:before { content: \"\\e042\"; } }\n.glyphicon-book { &:before { content: \"\\e043\"; } }\n.glyphicon-bookmark { &:before { content: \"\\e044\"; } }\n.glyphicon-print { &:before { content: \"\\e045\"; } }\n.glyphicon-camera { &:before { content: \"\\e046\"; } }\n.glyphicon-font { &:before { content: \"\\e047\"; } }\n.glyphicon-bold { &:before { content: \"\\e048\"; } }\n.glyphicon-italic { &:before { content: \"\\e049\"; } }\n.glyphicon-text-height { &:before { content: \"\\e050\"; } }\n.glyphicon-text-width { &:before { content: \"\\e051\"; } }\n.glyphicon-align-left { &:before { content: \"\\e052\"; } }\n.glyphicon-align-center { &:before { content: \"\\e053\"; } }\n.glyphicon-align-right { &:before { content: \"\\e054\"; } }\n.glyphicon-align-justify { &:before { content: \"\\e055\"; } }\n.glyphicon-list { &:before { content: \"\\e056\"; } }\n.glyphicon-indent-left { &:before { content: \"\\e057\"; } }\n.glyphicon-indent-right { &:before { content: \"\\e058\"; } }\n.glyphicon-facetime-video { &:before { content: \"\\e059\"; } }\n.glyphicon-picture { &:before { content: \"\\e060\"; } }\n.glyphicon-map-marker { &:before { content: \"\\e062\"; } }\n.glyphicon-adjust { &:before { content: \"\\e063\"; } }\n.glyphicon-tint { &:before { content: \"\\e064\"; } }\n.glyphicon-edit { &:before { content: \"\\e065\"; } }\n.glyphicon-share { &:before { content: \"\\e066\"; } }\n.glyphicon-check { &:before { content: \"\\e067\"; } }\n.glyphicon-move { &:before { content: \"\\e068\"; } }\n.glyphicon-step-backward { &:before { content: \"\\e069\"; } }\n.glyphicon-fast-backward { &:before { content: \"\\e070\"; } }\n.glyphicon-backward { &:before { content: \"\\e071\"; } }\n.glyphicon-play { &:before { content: \"\\e072\"; } }\n.glyphicon-pause { &:before { content: \"\\e073\"; } }\n.glyphicon-stop { &:before { content: \"\\e074\"; } }\n.glyphicon-forward { &:before { content: \"\\e075\"; } }\n.glyphicon-fast-forward { &:before { content: \"\\e076\"; } }\n.glyphicon-step-forward { &:before { content: \"\\e077\"; } }\n.glyphicon-eject { &:before { content: \"\\e078\"; } }\n.glyphicon-chevron-left { &:before { content: \"\\e079\"; } }\n.glyphicon-chevron-right { &:before { content: \"\\e080\"; } }\n.glyphicon-plus-sign { &:before { content: \"\\e081\"; } }\n.glyphicon-minus-sign { &:before { content: \"\\e082\"; } }\n.glyphicon-remove-sign { &:before { content: \"\\e083\"; } }\n.glyphicon-ok-sign { &:before { content: \"\\e084\"; } }\n.glyphicon-question-sign { &:before { content: \"\\e085\"; } }\n.glyphicon-info-sign { &:before { content: \"\\e086\"; } }\n.glyphicon-screenshot { &:before { content: \"\\e087\"; } }\n.glyphicon-remove-circle { &:before { content: \"\\e088\"; } }\n.glyphicon-ok-circle { &:before { content: \"\\e089\"; } }\n.glyphicon-ban-circle { &:before { content: \"\\e090\"; } }\n.glyphicon-arrow-left { &:before { content: \"\\e091\"; } }\n.glyphicon-arrow-right { &:before { content: \"\\e092\"; } }\n.glyphicon-arrow-up { &:before { content: \"\\e093\"; } }\n.glyphicon-arrow-down { &:before { content: \"\\e094\"; } }\n.glyphicon-share-alt { &:before { content: \"\\e095\"; } }\n.glyphicon-resize-full { &:before { content: \"\\e096\"; } }\n.glyphicon-resize-small { &:before { content: \"\\e097\"; } }\n.glyphicon-exclamation-sign { &:before { content: \"\\e101\"; } }\n.glyphicon-gift { &:before { content: \"\\e102\"; } }\n.glyphicon-leaf { &:before { content: \"\\e103\"; } }\n.glyphicon-fire { &:before { content: \"\\e104\"; } }\n.glyphicon-eye-open { &:before { content: \"\\e105\"; } }\n.glyphicon-eye-close { &:before { content: \"\\e106\"; } }\n.glyphicon-warning-sign { &:before { content: \"\\e107\"; } }\n.glyphicon-plane { &:before { content: \"\\e108\"; } }\n.glyphicon-calendar { &:before { content: \"\\e109\"; } }\n.glyphicon-random { &:before { content: \"\\e110\"; } }\n.glyphicon-comment { &:before { content: \"\\e111\"; } }\n.glyphicon-magnet { &:before { content: \"\\e112\"; } }\n.glyphicon-chevron-up { &:before { content: \"\\e113\"; } }\n.glyphicon-chevron-down { &:before { content: \"\\e114\"; } }\n.glyphicon-retweet { &:before { content: \"\\e115\"; } }\n.glyphicon-shopping-cart { &:before { content: \"\\e116\"; } }\n.glyphicon-folder-close { &:before { content: \"\\e117\"; } }\n.glyphicon-folder-open { &:before { content: \"\\e118\"; } }\n.glyphicon-resize-vertical { &:before { content: \"\\e119\"; } }\n.glyphicon-resize-horizontal { &:before { content: \"\\e120\"; } }\n.glyphicon-hdd { &:before { content: \"\\e121\"; } }\n.glyphicon-bullhorn { &:before { content: \"\\e122\"; } }\n.glyphicon-bell { &:before { content: \"\\e123\"; } }\n.glyphicon-certificate { &:before { content: \"\\e124\"; } }\n.glyphicon-thumbs-up { &:before { content: \"\\e125\"; } }\n.glyphicon-thumbs-down { &:before { content: \"\\e126\"; } }\n.glyphicon-hand-right { &:before { content: \"\\e127\"; } }\n.glyphicon-hand-left { &:before { content: \"\\e128\"; } }\n.glyphicon-hand-up { &:before { content: \"\\e129\"; } }\n.glyphicon-hand-down { &:before { content: \"\\e130\"; } }\n.glyphicon-circle-arrow-right { &:before { content: \"\\e131\"; } }\n.glyphicon-circle-arrow-left { &:before { content: \"\\e132\"; } }\n.glyphicon-circle-arrow-up { &:before { content: \"\\e133\"; } }\n.glyphicon-circle-arrow-down { &:before { content: \"\\e134\"; } }\n.glyphicon-globe { &:before { content: \"\\e135\"; } }\n.glyphicon-wrench { &:before { content: \"\\e136\"; } }\n.glyphicon-tasks { &:before { content: \"\\e137\"; } }\n.glyphicon-filter { &:before { content: \"\\e138\"; } }\n.glyphicon-briefcase { &:before { content: \"\\e139\"; } }\n.glyphicon-fullscreen { &:before { content: \"\\e140\"; } }\n.glyphicon-dashboard { &:before { content: \"\\e141\"; } }\n.glyphicon-paperclip { &:before { content: \"\\e142\"; } }\n.glyphicon-heart-empty { &:before { content: \"\\e143\"; } }\n.glyphicon-link { &:before { content: \"\\e144\"; } }\n.glyphicon-phone { &:before { content: \"\\e145\"; } }\n.glyphicon-pushpin { &:before { content: \"\\e146\"; } }\n.glyphicon-usd { &:before { content: \"\\e148\"; } }\n.glyphicon-gbp { &:before { content: \"\\e149\"; } }\n.glyphicon-sort { &:before { content: \"\\e150\"; } }\n.glyphicon-sort-by-alphabet { &:before { content: \"\\e151\"; } }\n.glyphicon-sort-by-alphabet-alt { &:before { content: \"\\e152\"; } }\n.glyphicon-sort-by-order { &:before { content: \"\\e153\"; } }\n.glyphicon-sort-by-order-alt { &:before { content: \"\\e154\"; } }\n.glyphicon-sort-by-attributes { &:before { content: \"\\e155\"; } }\n.glyphicon-sort-by-attributes-alt { &:before { content: \"\\e156\"; } }\n.glyphicon-unchecked { &:before { content: \"\\e157\"; } }\n.glyphicon-expand { &:before { content: \"\\e158\"; } }\n.glyphicon-collapse-down { &:before { content: \"\\e159\"; } }\n.glyphicon-collapse-up { &:before { content: \"\\e160\"; } }\n.glyphicon-log-in { &:before { content: \"\\e161\"; } }\n.glyphicon-flash { &:before { content: \"\\e162\"; } }\n.glyphicon-log-out { &:before { content: \"\\e163\"; } }\n.glyphicon-new-window { &:before { content: \"\\e164\"; } }\n.glyphicon-record { &:before { content: \"\\e165\"; } }\n.glyphicon-save { &:before { content: \"\\e166\"; } }\n.glyphicon-open { &:before { content: \"\\e167\"; } }\n.glyphicon-saved { &:before { content: \"\\e168\"; } }\n.glyphicon-import { &:before { content: \"\\e169\"; } }\n.glyphicon-export { &:before { content: \"\\e170\"; } }\n.glyphicon-send { &:before { content: \"\\e171\"; } }\n.glyphicon-floppy-disk { &:before { content: \"\\e172\"; } }\n.glyphicon-floppy-saved { &:before { content: \"\\e173\"; } }\n.glyphicon-floppy-remove { &:before { content: \"\\e174\"; } }\n.glyphicon-floppy-save { &:before { content: \"\\e175\"; } }\n.glyphicon-floppy-open { &:before { content: \"\\e176\"; } }\n.glyphicon-credit-card { &:before { content: \"\\e177\"; } }\n.glyphicon-transfer { &:before { content: \"\\e178\"; } }\n.glyphicon-cutlery { &:before { content: \"\\e179\"; } }\n.glyphicon-header { &:before { content: \"\\e180\"; } }\n.glyphicon-compressed { &:before { content: \"\\e181\"; } }\n.glyphicon-earphone { &:before { content: \"\\e182\"; } }\n.glyphicon-phone-alt { &:before { content: \"\\e183\"; } }\n.glyphicon-tower { &:before { content: \"\\e184\"; } }\n.glyphicon-stats { &:before { content: \"\\e185\"; } }\n.glyphicon-sd-video { &:before { content: \"\\e186\"; } }\n.glyphicon-hd-video { &:before { content: \"\\e187\"; } }\n.glyphicon-subtitles { &:before { content: \"\\e188\"; } }\n.glyphicon-sound-stereo { &:before { content: \"\\e189\"; } }\n.glyphicon-sound-dolby { &:before { content: \"\\e190\"; } }\n.glyphicon-sound-5-1 { &:before { content: \"\\e191\"; } }\n.glyphicon-sound-6-1 { &:before { content: \"\\e192\"; } }\n.glyphicon-sound-7-1 { &:before { content: \"\\e193\"; } }\n.glyphicon-copyright-mark { &:before { content: \"\\e194\"; } }\n.glyphicon-registration-mark { &:before { content: \"\\e195\"; } }\n.glyphicon-cloud-download { &:before { content: \"\\e197\"; } }\n.glyphicon-cloud-upload { &:before { content: \"\\e198\"; } }\n.glyphicon-tree-conifer { &:before { content: \"\\e199\"; } }\n.glyphicon-tree-deciduous { &:before { content: \"\\e200\"; } }\n.glyphicon-cd { &:before { content: \"\\e201\"; } }\n.glyphicon-save-file { &:before { content: \"\\e202\"; } }\n.glyphicon-open-file { &:before { content: \"\\e203\"; } }\n.glyphicon-level-up { &:before { content: \"\\e204\"; } }\n.glyphicon-copy { &:before { content: \"\\e205\"; } }\n.glyphicon-paste { &:before { content: \"\\e206\"; } }\n// The following 2 Glyphicons are omitted for the time being because\n// they currently use Unicode codepoints that are outside the\n// Basic Multilingual Plane (BMP). Older buggy versions of WebKit can't handle\n// non-BMP codepoints in CSS string escapes, and thus can't display these two icons.\n// Notably, the bug affects some older versions of the Android Browser.\n// More info: https://github.com/twbs/bootstrap/issues/10106\n// .glyphicon-door { &:before { content: \"\\1f6aa\"; } }\n// .glyphicon-key { &:before { content: \"\\1f511\"; } }\n.glyphicon-alert { &:before { content: \"\\e209\"; } }\n.glyphicon-equalizer { &:before { content: \"\\e210\"; } }\n.glyphicon-king { &:before { content: \"\\e211\"; } }\n.glyphicon-queen { &:before { content: \"\\e212\"; } }\n.glyphicon-pawn { &:before { content: \"\\e213\"; } }\n.glyphicon-bishop { &:before { content: \"\\e214\"; } }\n.glyphicon-knight { &:before { content: \"\\e215\"; } }\n.glyphicon-baby-formula { &:before { content: \"\\e216\"; } }\n.glyphicon-tent { &:before { content: \"\\26fa\"; } }\n.glyphicon-blackboard { &:before { content: \"\\e218\"; } }\n.glyphicon-bed { &:before { content: \"\\e219\"; } }\n.glyphicon-apple { &:before { content: \"\\f8ff\"; } }\n.glyphicon-erase { &:before { content: \"\\e221\"; } }\n.glyphicon-hourglass { &:before { content: \"\\231b\"; } }\n.glyphicon-lamp { &:before { content: \"\\e223\"; } }\n.glyphicon-duplicate { &:before { content: \"\\e224\"; } }\n.glyphicon-piggy-bank { &:before { content: \"\\e225\"; } }\n.glyphicon-scissors { &:before { content: \"\\e226\"; } }\n.glyphicon-bitcoin { &:before { content: \"\\e227\"; } }\n.glyphicon-btc { &:before { content: \"\\e227\"; } }\n.glyphicon-xbt { &:before { content: \"\\e227\"; } }\n.glyphicon-yen { &:before { content: \"\\00a5\"; } }\n.glyphicon-jpy { &:before { content: \"\\00a5\"; } }\n.glyphicon-ruble { &:before { content: \"\\20bd\"; } }\n.glyphicon-rub { &:before { content: \"\\20bd\"; } }\n.glyphicon-scale { &:before { content: \"\\e230\"; } }\n.glyphicon-ice-lolly { &:before { content: \"\\e231\"; } }\n.glyphicon-ice-lolly-tasted { &:before { content: \"\\e232\"; } }\n.glyphicon-education { &:before { content: \"\\e233\"; } }\n.glyphicon-option-horizontal { &:before { content: \"\\e234\"; } }\n.glyphicon-option-vertical { &:before { content: \"\\e235\"; } }\n.glyphicon-menu-hamburger { &:before { content: \"\\e236\"; } }\n.glyphicon-modal-window { &:before { content: \"\\e237\"; } }\n.glyphicon-oil { &:before { content: \"\\e238\"; } }\n.glyphicon-grain { &:before { content: \"\\e239\"; } }\n.glyphicon-sunglasses { &:before { content: \"\\e240\"; } }\n.glyphicon-text-size { &:before { content: \"\\e241\"; } }\n.glyphicon-text-color { &:before { content: \"\\e242\"; } }\n.glyphicon-text-background { &:before { content: \"\\e243\"; } }\n.glyphicon-object-align-top { &:before { content: \"\\e244\"; } }\n.glyphicon-object-align-bottom { &:before { content: \"\\e245\"; } }\n.glyphicon-object-align-horizontal{ &:before { content: \"\\e246\"; } }\n.glyphicon-object-align-left { &:before { content: \"\\e247\"; } }\n.glyphicon-object-align-vertical { &:before { content: \"\\e248\"; } }\n.glyphicon-object-align-right { &:before { content: \"\\e249\"; } }\n.glyphicon-triangle-right { &:before { content: \"\\e250\"; } }\n.glyphicon-triangle-left { &:before { content: \"\\e251\"; } }\n.glyphicon-triangle-bottom { &:before { content: \"\\e252\"; } }\n.glyphicon-triangle-top { &:before { content: \"\\e253\"; } }\n.glyphicon-console { &:before { content: \"\\e254\"; } }\n.glyphicon-superscript { &:before { content: \"\\e255\"; } }\n.glyphicon-subscript { &:before { content: \"\\e256\"; } }\n.glyphicon-menu-left { &:before { content: \"\\e257\"; } }\n.glyphicon-menu-right { &:before { content: \"\\e258\"; } }\n.glyphicon-menu-down { &:before { content: \"\\e259\"; } }\n.glyphicon-menu-up { &:before { content: \"\\e260\"; } }\n","//\n// Scaffolding\n// --------------------------------------------------\n\n\n// Reset the box-sizing\n//\n// Heads up! This reset may cause conflicts with some third-party widgets.\n// For recommendations on resolving such conflicts, see\n// http://getbootstrap.com/getting-started/#third-box-sizing\n* {\n .box-sizing(border-box);\n}\n*:before,\n*:after {\n .box-sizing(border-box);\n}\n\n\n// Body reset\n\nhtml {\n font-size: 10px;\n -webkit-tap-highlight-color: rgba(0,0,0,0);\n}\n\nbody {\n font-family: @font-family-base;\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @text-color;\n background-color: @body-bg;\n}\n\n// Reset fonts for relevant elements\ninput,\nbutton,\nselect,\ntextarea {\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\n\n// Links\n\na {\n color: @link-color;\n text-decoration: none;\n\n &:hover,\n &:focus {\n color: @link-hover-color;\n text-decoration: @link-hover-decoration;\n }\n\n &:focus {\n .tab-focus();\n }\n}\n\n\n// Figures\n//\n// We reset this here because previously Normalize had no `figure` margins. This\n// ensures we don't break anyone's use of the element.\n\nfigure {\n margin: 0;\n}\n\n\n// Images\n\nimg {\n vertical-align: middle;\n}\n\n// Responsive images (ensure images don't scale beyond their parents)\n.img-responsive {\n .img-responsive();\n}\n\n// Rounded corners\n.img-rounded {\n border-radius: @border-radius-large;\n}\n\n// Image thumbnails\n//\n// Heads up! This is mixin-ed into thumbnails.less for `.thumbnail`.\n.img-thumbnail {\n padding: @thumbnail-padding;\n line-height: @line-height-base;\n background-color: @thumbnail-bg;\n border: 1px solid @thumbnail-border;\n border-radius: @thumbnail-border-radius;\n .transition(all .2s ease-in-out);\n\n // Keep them at most 100% wide\n .img-responsive(inline-block);\n}\n\n// Perfect circle\n.img-circle {\n border-radius: 50%; // set radius in percents\n}\n\n\n// Horizontal rules\n\nhr {\n margin-top: @line-height-computed;\n margin-bottom: @line-height-computed;\n border: 0;\n border-top: 1px solid @hr-border;\n}\n\n\n// Only display content to screen readers\n//\n// See: http://a11yproject.com/posts/how-to-hide-content\n\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0,0,0,0);\n border: 0;\n}\n\n// Use in conjunction with .sr-only to only display content when it's focused.\n// Useful for \"Skip to main content\" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1\n// Credit: HTML5 Boilerplate\n\n.sr-only-focusable {\n &:active,\n &:focus {\n position: static;\n width: auto;\n height: auto;\n margin: 0;\n overflow: visible;\n clip: auto;\n }\n}\n\n\n// iOS \"clickable elements\" fix for role=\"button\"\n//\n// Fixes \"clickability\" issue (and more generally, the firing of events such as focus as well)\n// for traditionally non-focusable elements with role=\"button\"\n// see https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile\n\n[role=\"button\"] {\n cursor: pointer;\n}\n","// Vendor Prefixes\n//\n// All vendor mixins are deprecated as of v3.2.0 due to the introduction of\n// Autoprefixer in our Gruntfile. They have been removed in v4.\n\n// - Animations\n// - Backface visibility\n// - Box shadow\n// - Box sizing\n// - Content columns\n// - Hyphens\n// - Placeholder text\n// - Transformations\n// - Transitions\n// - User Select\n\n\n// Animations\n.animation(@animation) {\n -webkit-animation: @animation;\n -o-animation: @animation;\n animation: @animation;\n}\n.animation-name(@name) {\n -webkit-animation-name: @name;\n animation-name: @name;\n}\n.animation-duration(@duration) {\n -webkit-animation-duration: @duration;\n animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n -webkit-animation-timing-function: @timing-function;\n animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n -webkit-animation-delay: @delay;\n animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n -webkit-animation-iteration-count: @iteration-count;\n animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n -webkit-animation-direction: @direction;\n animation-direction: @direction;\n}\n.animation-fill-mode(@fill-mode) {\n -webkit-animation-fill-mode: @fill-mode;\n animation-fill-mode: @fill-mode;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n\n.backface-visibility(@visibility) {\n -webkit-backface-visibility: @visibility;\n -moz-backface-visibility: @visibility;\n backface-visibility: @visibility;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support it.\n\n.box-shadow(@shadow) {\n -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n box-shadow: @shadow;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n -webkit-box-sizing: @boxmodel;\n -moz-box-sizing: @boxmodel;\n box-sizing: @boxmodel;\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n -webkit-column-count: @column-count;\n -moz-column-count: @column-count;\n column-count: @column-count;\n -webkit-column-gap: @column-gap;\n -moz-column-gap: @column-gap;\n column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n word-wrap: break-word;\n -webkit-hyphens: @mode;\n -moz-hyphens: @mode;\n -ms-hyphens: @mode; // IE10+\n -o-hyphens: @mode;\n hyphens: @mode;\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n // Firefox\n &::-moz-placeholder {\n color: @color;\n opacity: 1; // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526\n }\n &:-ms-input-placeholder { color: @color; } // Internet Explorer 10+\n &::-webkit-input-placeholder { color: @color; } // Safari and Chrome\n}\n\n// Transformations\n.scale(@ratio) {\n -webkit-transform: scale(@ratio);\n -ms-transform: scale(@ratio); // IE9 only\n -o-transform: scale(@ratio);\n transform: scale(@ratio);\n}\n.scale(@ratioX; @ratioY) {\n -webkit-transform: scale(@ratioX, @ratioY);\n -ms-transform: scale(@ratioX, @ratioY); // IE9 only\n -o-transform: scale(@ratioX, @ratioY);\n transform: scale(@ratioX, @ratioY);\n}\n.scaleX(@ratio) {\n -webkit-transform: scaleX(@ratio);\n -ms-transform: scaleX(@ratio); // IE9 only\n -o-transform: scaleX(@ratio);\n transform: scaleX(@ratio);\n}\n.scaleY(@ratio) {\n -webkit-transform: scaleY(@ratio);\n -ms-transform: scaleY(@ratio); // IE9 only\n -o-transform: scaleY(@ratio);\n transform: scaleY(@ratio);\n}\n.skew(@x; @y) {\n -webkit-transform: skewX(@x) skewY(@y);\n -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n -o-transform: skewX(@x) skewY(@y);\n transform: skewX(@x) skewY(@y);\n}\n.translate(@x; @y) {\n -webkit-transform: translate(@x, @y);\n -ms-transform: translate(@x, @y); // IE9 only\n -o-transform: translate(@x, @y);\n transform: translate(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n -webkit-transform: translate3d(@x, @y, @z);\n transform: translate3d(@x, @y, @z);\n}\n.rotate(@degrees) {\n -webkit-transform: rotate(@degrees);\n -ms-transform: rotate(@degrees); // IE9 only\n -o-transform: rotate(@degrees);\n transform: rotate(@degrees);\n}\n.rotateX(@degrees) {\n -webkit-transform: rotateX(@degrees);\n -ms-transform: rotateX(@degrees); // IE9 only\n -o-transform: rotateX(@degrees);\n transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n -webkit-transform: rotateY(@degrees);\n -ms-transform: rotateY(@degrees); // IE9 only\n -o-transform: rotateY(@degrees);\n transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n -webkit-perspective: @perspective;\n -moz-perspective: @perspective;\n perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n -webkit-perspective-origin: @perspective;\n -moz-perspective-origin: @perspective;\n perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n -webkit-transform-origin: @origin;\n -moz-transform-origin: @origin;\n -ms-transform-origin: @origin; // IE9 only\n transform-origin: @origin;\n}\n\n\n// Transitions\n\n.transition(@transition) {\n -webkit-transition: @transition;\n -o-transition: @transition;\n transition: @transition;\n}\n.transition-property(@transition-property) {\n -webkit-transition-property: @transition-property;\n transition-property: @transition-property;\n}\n.transition-delay(@transition-delay) {\n -webkit-transition-delay: @transition-delay;\n transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n -webkit-transition-duration: @transition-duration;\n transition-duration: @transition-duration;\n}\n.transition-timing-function(@timing-function) {\n -webkit-transition-timing-function: @timing-function;\n transition-timing-function: @timing-function;\n}\n.transition-transform(@transition) {\n -webkit-transition: -webkit-transform @transition;\n -moz-transition: -moz-transform @transition;\n -o-transition: -o-transform @transition;\n transition: transform @transition;\n}\n\n\n// User select\n// For selecting text on the page\n\n.user-select(@select) {\n -webkit-user-select: @select;\n -moz-user-select: @select;\n -ms-user-select: @select; // IE10+\n user-select: @select;\n}\n","// WebKit-style focus\n\n.tab-focus() {\n // WebKit-specific. Other browsers will keep their default outline style.\n // (Initially tried to also force default via `outline: initial`,\n // but that seems to erroneously remove the outline in Firefox altogether.)\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\n","// Image Mixins\n// - Responsive image\n// - Retina image\n\n\n// Responsive image\n//\n// Keep images from scaling beyond the width of their parents.\n.img-responsive(@display: block) {\n display: @display;\n max-width: 100%; // Part 1: Set a maximum relative to the parent\n height: auto; // Part 2: Scale the height according to the width, otherwise you get stretching\n}\n\n\n// Retina image\n//\n// Short retina mixin for setting background-image and -size. Note that the\n// spelling of `min--moz-device-pixel-ratio` is intentional.\n.img-retina(@file-1x; @file-2x; @width-1x; @height-1x) {\n background-image: url(\"@{file-1x}\");\n\n @media\n only screen and (-webkit-min-device-pixel-ratio: 2),\n only screen and ( min--moz-device-pixel-ratio: 2),\n only screen and ( -o-min-device-pixel-ratio: 2/1),\n only screen and ( min-device-pixel-ratio: 2),\n only screen and ( min-resolution: 192dpi),\n only screen and ( min-resolution: 2dppx) {\n background-image: url(\"@{file-2x}\");\n background-size: @width-1x @height-1x;\n }\n}\n","//\n// Typography\n// --------------------------------------------------\n\n\n// Headings\n// -------------------------\n\nh1, h2, h3, h4, h5, h6,\n.h1, .h2, .h3, .h4, .h5, .h6 {\n font-family: @headings-font-family;\n font-weight: @headings-font-weight;\n line-height: @headings-line-height;\n color: @headings-color;\n\n small,\n .small {\n font-weight: normal;\n line-height: 1;\n color: @headings-small-color;\n }\n}\n\nh1, .h1,\nh2, .h2,\nh3, .h3 {\n margin-top: @line-height-computed;\n margin-bottom: (@line-height-computed / 2);\n\n small,\n .small {\n font-size: 65%;\n }\n}\nh4, .h4,\nh5, .h5,\nh6, .h6 {\n margin-top: (@line-height-computed / 2);\n margin-bottom: (@line-height-computed / 2);\n\n small,\n .small {\n font-size: 75%;\n }\n}\n\nh1, .h1 { font-size: @font-size-h1; }\nh2, .h2 { font-size: @font-size-h2; }\nh3, .h3 { font-size: @font-size-h3; }\nh4, .h4 { font-size: @font-size-h4; }\nh5, .h5 { font-size: @font-size-h5; }\nh6, .h6 { font-size: @font-size-h6; }\n\n\n// Body text\n// -------------------------\n\np {\n margin: 0 0 (@line-height-computed / 2);\n}\n\n.lead {\n margin-bottom: @line-height-computed;\n font-size: floor((@font-size-base * 1.15));\n font-weight: 300;\n line-height: 1.4;\n\n @media (min-width: @screen-sm-min) {\n font-size: (@font-size-base * 1.5);\n }\n}\n\n\n// Emphasis & misc\n// -------------------------\n\n// Ex: (12px small font / 14px base font) * 100% = about 85%\nsmall,\n.small {\n font-size: floor((100% * @font-size-small / @font-size-base));\n}\n\nmark,\n.mark {\n background-color: @state-warning-bg;\n padding: .2em;\n}\n\n// Alignment\n.text-left { text-align: left; }\n.text-right { text-align: right; }\n.text-center { text-align: center; }\n.text-justify { text-align: justify; }\n.text-nowrap { white-space: nowrap; }\n\n// Transformation\n.text-lowercase { text-transform: lowercase; }\n.text-uppercase { text-transform: uppercase; }\n.text-capitalize { text-transform: capitalize; }\n\n// Contextual colors\n.text-muted {\n color: @text-muted;\n}\n.text-primary {\n .text-emphasis-variant(@brand-primary);\n}\n.text-success {\n .text-emphasis-variant(@state-success-text);\n}\n.text-info {\n .text-emphasis-variant(@state-info-text);\n}\n.text-warning {\n .text-emphasis-variant(@state-warning-text);\n}\n.text-danger {\n .text-emphasis-variant(@state-danger-text);\n}\n\n// Contextual backgrounds\n// For now we'll leave these alongside the text classes until v4 when we can\n// safely shift things around (per SemVer rules).\n.bg-primary {\n // Given the contrast here, this is the only class to have its color inverted\n // automatically.\n color: #fff;\n .bg-variant(@brand-primary);\n}\n.bg-success {\n .bg-variant(@state-success-bg);\n}\n.bg-info {\n .bg-variant(@state-info-bg);\n}\n.bg-warning {\n .bg-variant(@state-warning-bg);\n}\n.bg-danger {\n .bg-variant(@state-danger-bg);\n}\n\n\n// Page header\n// -------------------------\n\n.page-header {\n padding-bottom: ((@line-height-computed / 2) - 1);\n margin: (@line-height-computed * 2) 0 @line-height-computed;\n border-bottom: 1px solid @page-header-border-color;\n}\n\n\n// Lists\n// -------------------------\n\n// Unordered and Ordered lists\nul,\nol {\n margin-top: 0;\n margin-bottom: (@line-height-computed / 2);\n ul,\n ol {\n margin-bottom: 0;\n }\n}\n\n// List options\n\n// Unstyled keeps list items block level, just removes default browser padding and list-style\n.list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n\n// Inline turns list items into inline-block\n.list-inline {\n .list-unstyled();\n margin-left: -5px;\n\n > li {\n display: inline-block;\n padding-left: 5px;\n padding-right: 5px;\n }\n}\n\n// Description Lists\ndl {\n margin-top: 0; // Remove browser default\n margin-bottom: @line-height-computed;\n}\ndt,\ndd {\n line-height: @line-height-base;\n}\ndt {\n font-weight: bold;\n}\ndd {\n margin-left: 0; // Undo browser default\n}\n\n// Horizontal description lists\n//\n// Defaults to being stacked without any of the below styles applied, until the\n// grid breakpoint is reached (default of ~768px).\n\n.dl-horizontal {\n dd {\n &:extend(.clearfix all); // Clear the floated `dt` if an empty `dd` is present\n }\n\n @media (min-width: @dl-horizontal-breakpoint) {\n dt {\n float: left;\n width: (@dl-horizontal-offset - 20);\n clear: left;\n text-align: right;\n .text-overflow();\n }\n dd {\n margin-left: @dl-horizontal-offset;\n }\n }\n}\n\n\n// Misc\n// -------------------------\n\n// Abbreviations and acronyms\nabbr[title],\n// Add data-* attribute to help out our tooltip plugin, per https://github.com/twbs/bootstrap/issues/5257\nabbr[data-original-title] {\n cursor: help;\n border-bottom: 1px dotted @abbr-border-color;\n}\n.initialism {\n font-size: 90%;\n .text-uppercase();\n}\n\n// Blockquotes\nblockquote {\n padding: (@line-height-computed / 2) @line-height-computed;\n margin: 0 0 @line-height-computed;\n font-size: @blockquote-font-size;\n border-left: 5px solid @blockquote-border-color;\n\n p,\n ul,\n ol {\n &:last-child {\n margin-bottom: 0;\n }\n }\n\n // Note: Deprecated small and .small as of v3.1.0\n // Context: https://github.com/twbs/bootstrap/issues/11660\n footer,\n small,\n .small {\n display: block;\n font-size: 80%; // back to default font-size\n line-height: @line-height-base;\n color: @blockquote-small-color;\n\n &:before {\n content: '\\2014 \\00A0'; // em dash, nbsp\n }\n }\n}\n\n// Opposite alignment of blockquote\n//\n// Heads up: `blockquote.pull-right` has been deprecated as of v3.1.0.\n.blockquote-reverse,\nblockquote.pull-right {\n padding-right: 15px;\n padding-left: 0;\n border-right: 5px solid @blockquote-border-color;\n border-left: 0;\n text-align: right;\n\n // Account for citation\n footer,\n small,\n .small {\n &:before { content: ''; }\n &:after {\n content: '\\00A0 \\2014'; // nbsp, em dash\n }\n }\n}\n\n// Addresses\naddress {\n margin-bottom: @line-height-computed;\n font-style: normal;\n line-height: @line-height-base;\n}\n","// Typography\n\n.text-emphasis-variant(@color) {\n color: @color;\n a&:hover,\n a&:focus {\n color: darken(@color, 10%);\n }\n}\n","// Contextual backgrounds\n\n.bg-variant(@color) {\n background-color: @color;\n a&:hover,\n a&:focus {\n background-color: darken(@color, 10%);\n }\n}\n","// Text overflow\n// Requires inline-block or block for proper styling\n\n.text-overflow() {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n","//\n// Code (inline and block)\n// --------------------------------------------------\n\n\n// Inline and block code styles\ncode,\nkbd,\npre,\nsamp {\n font-family: @font-family-monospace;\n}\n\n// Inline code\ncode {\n padding: 2px 4px;\n font-size: 90%;\n color: @code-color;\n background-color: @code-bg;\n border-radius: @border-radius-base;\n}\n\n// User input typically entered via keyboard\nkbd {\n padding: 2px 4px;\n font-size: 90%;\n color: @kbd-color;\n background-color: @kbd-bg;\n border-radius: @border-radius-small;\n box-shadow: inset 0 -1px 0 rgba(0,0,0,.25);\n\n kbd {\n padding: 0;\n font-size: 100%;\n font-weight: bold;\n box-shadow: none;\n }\n}\n\n// Blocks of code\npre {\n display: block;\n padding: ((@line-height-computed - 1) / 2);\n margin: 0 0 (@line-height-computed / 2);\n font-size: (@font-size-base - 1); // 14px to 13px\n line-height: @line-height-base;\n word-break: break-all;\n word-wrap: break-word;\n color: @pre-color;\n background-color: @pre-bg;\n border: 1px solid @pre-border-color;\n border-radius: @border-radius-base;\n\n // Account for some code outputs that place code tags in pre tags\n code {\n padding: 0;\n font-size: inherit;\n color: inherit;\n white-space: pre-wrap;\n background-color: transparent;\n border-radius: 0;\n }\n}\n\n// Enable scrollable blocks of code\n.pre-scrollable {\n max-height: @pre-scrollable-max-height;\n overflow-y: scroll;\n}\n","//\n// Grid system\n// --------------------------------------------------\n\n\n// Container widths\n//\n// Set the container width, and override it for fixed navbars in media queries.\n\n.container {\n .container-fixed();\n\n @media (min-width: @screen-sm-min) {\n width: @container-sm;\n }\n @media (min-width: @screen-md-min) {\n width: @container-md;\n }\n @media (min-width: @screen-lg-min) {\n width: @container-lg;\n }\n}\n\n\n// Fluid container\n//\n// Utilizes the mixin meant for fixed width containers, but without any defined\n// width for fluid, full width layouts.\n\n.container-fluid {\n .container-fixed();\n}\n\n\n// Row\n//\n// Rows contain and clear the floats of your columns.\n\n.row {\n .make-row();\n}\n\n\n// Columns\n//\n// Common styles for small and large grid columns\n\n.make-grid-columns();\n\n\n// Extra small grid\n//\n// Columns, offsets, pushes, and pulls for extra small devices like\n// smartphones.\n\n.make-grid(xs);\n\n\n// Small grid\n//\n// Columns, offsets, pushes, and pulls for the small device range, from phones\n// to tablets.\n\n@media (min-width: @screen-sm-min) {\n .make-grid(sm);\n}\n\n\n// Medium grid\n//\n// Columns, offsets, pushes, and pulls for the desktop device range.\n\n@media (min-width: @screen-md-min) {\n .make-grid(md);\n}\n\n\n// Large grid\n//\n// Columns, offsets, pushes, and pulls for the large desktop device range.\n\n@media (min-width: @screen-lg-min) {\n .make-grid(lg);\n}\n","// Grid system\n//\n// Generate semantic grid columns with these mixins.\n\n// Centered container element\n.container-fixed(@gutter: @grid-gutter-width) {\n margin-right: auto;\n margin-left: auto;\n padding-left: floor((@gutter / 2));\n padding-right: ceil((@gutter / 2));\n &:extend(.clearfix all);\n}\n\n// Creates a wrapper for a series of columns\n.make-row(@gutter: @grid-gutter-width) {\n margin-left: ceil((@gutter / -2));\n margin-right: floor((@gutter / -2));\n &:extend(.clearfix all);\n}\n\n// Generate the extra small columns\n.make-xs-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n float: left;\n width: percentage((@columns / @grid-columns));\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n}\n.make-xs-column-offset(@columns) {\n margin-left: percentage((@columns / @grid-columns));\n}\n.make-xs-column-push(@columns) {\n left: percentage((@columns / @grid-columns));\n}\n.make-xs-column-pull(@columns) {\n right: percentage((@columns / @grid-columns));\n}\n\n// Generate the small columns\n.make-sm-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-sm-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-offset(@columns) {\n @media (min-width: @screen-sm-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-push(@columns) {\n @media (min-width: @screen-sm-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-pull(@columns) {\n @media (min-width: @screen-sm-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n// Generate the medium columns\n.make-md-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-md-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-offset(@columns) {\n @media (min-width: @screen-md-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-push(@columns) {\n @media (min-width: @screen-md-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-pull(@columns) {\n @media (min-width: @screen-md-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n// Generate the large columns\n.make-lg-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-lg-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-offset(@columns) {\n @media (min-width: @screen-lg-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-push(@columns) {\n @media (min-width: @screen-lg-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-pull(@columns) {\n @media (min-width: @screen-lg-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n","// Framework grid generation\n//\n// Used only by Bootstrap to generate the correct number of grid classes given\n// any value of `@grid-columns`.\n\n.make-grid-columns() {\n // Common styles for all sizes of grid columns, widths 1-12\n .col(@index) { // initial\n @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n .col((@index + 1), @item);\n }\n .col(@index, @list) when (@index =< @grid-columns) { // general; \"=<\" isn't a typo\n @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n .col((@index + 1), ~\"@{list}, @{item}\");\n }\n .col(@index, @list) when (@index > @grid-columns) { // terminal\n @{list} {\n position: relative;\n // Prevent columns from collapsing when empty\n min-height: 1px;\n // Inner gutter via padding\n padding-left: ceil((@grid-gutter-width / 2));\n padding-right: floor((@grid-gutter-width / 2));\n }\n }\n .col(1); // kickstart it\n}\n\n.float-grid-columns(@class) {\n .col(@index) { // initial\n @item: ~\".col-@{class}-@{index}\";\n .col((@index + 1), @item);\n }\n .col(@index, @list) when (@index =< @grid-columns) { // general\n @item: ~\".col-@{class}-@{index}\";\n .col((@index + 1), ~\"@{list}, @{item}\");\n }\n .col(@index, @list) when (@index > @grid-columns) { // terminal\n @{list} {\n float: left;\n }\n }\n .col(1); // kickstart it\n}\n\n.calc-grid-column(@index, @class, @type) when (@type = width) and (@index > 0) {\n .col-@{class}-@{index} {\n width: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = push) and (@index > 0) {\n .col-@{class}-push-@{index} {\n left: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = push) and (@index = 0) {\n .col-@{class}-push-0 {\n left: auto;\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = pull) and (@index > 0) {\n .col-@{class}-pull-@{index} {\n right: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = pull) and (@index = 0) {\n .col-@{class}-pull-0 {\n right: auto;\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = offset) {\n .col-@{class}-offset-@{index} {\n margin-left: percentage((@index / @grid-columns));\n }\n}\n\n// Basic looping in LESS\n.loop-grid-columns(@index, @class, @type) when (@index >= 0) {\n .calc-grid-column(@index, @class, @type);\n // next iteration\n .loop-grid-columns((@index - 1), @class, @type);\n}\n\n// Create grid for specific class\n.make-grid(@class) {\n .float-grid-columns(@class);\n .loop-grid-columns(@grid-columns, @class, width);\n .loop-grid-columns(@grid-columns, @class, pull);\n .loop-grid-columns(@grid-columns, @class, push);\n .loop-grid-columns(@grid-columns, @class, offset);\n}\n","//\n// Tables\n// --------------------------------------------------\n\n\ntable {\n background-color: @table-bg;\n}\ncaption {\n padding-top: @table-cell-padding;\n padding-bottom: @table-cell-padding;\n color: @text-muted;\n text-align: left;\n}\nth {\n text-align: left;\n}\n\n\n// Baseline styles\n\n.table {\n width: 100%;\n max-width: 100%;\n margin-bottom: @line-height-computed;\n // Cells\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n padding: @table-cell-padding;\n line-height: @line-height-base;\n vertical-align: top;\n border-top: 1px solid @table-border-color;\n }\n }\n }\n // Bottom align for column headings\n > thead > tr > th {\n vertical-align: bottom;\n border-bottom: 2px solid @table-border-color;\n }\n // Remove top border from thead by default\n > caption + thead,\n > colgroup + thead,\n > thead:first-child {\n > tr:first-child {\n > th,\n > td {\n border-top: 0;\n }\n }\n }\n // Account for multiple tbody instances\n > tbody + tbody {\n border-top: 2px solid @table-border-color;\n }\n\n // Nesting\n .table {\n background-color: @body-bg;\n }\n}\n\n\n// Condensed table w/ half padding\n\n.table-condensed {\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n padding: @table-condensed-cell-padding;\n }\n }\n }\n}\n\n\n// Bordered version\n//\n// Add borders all around the table and between all the columns.\n\n.table-bordered {\n border: 1px solid @table-border-color;\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n border: 1px solid @table-border-color;\n }\n }\n }\n > thead > tr {\n > th,\n > td {\n border-bottom-width: 2px;\n }\n }\n}\n\n\n// Zebra-striping\n//\n// Default zebra-stripe styles (alternating gray and transparent backgrounds)\n\n.table-striped {\n > tbody > tr:nth-of-type(odd) {\n background-color: @table-bg-accent;\n }\n}\n\n\n// Hover effect\n//\n// Placed here since it has to come after the potential zebra striping\n\n.table-hover {\n > tbody > tr:hover {\n background-color: @table-bg-hover;\n }\n}\n\n\n// Table cell sizing\n//\n// Reset default table behavior\n\ntable col[class*=\"col-\"] {\n position: static; // Prevent border hiding in Firefox and IE9-11 (see https://github.com/twbs/bootstrap/issues/11623)\n float: none;\n display: table-column;\n}\ntable {\n td,\n th {\n &[class*=\"col-\"] {\n position: static; // Prevent border hiding in Firefox and IE9-11 (see https://github.com/twbs/bootstrap/issues/11623)\n float: none;\n display: table-cell;\n }\n }\n}\n\n\n// Table backgrounds\n//\n// Exact selectors below required to override `.table-striped` and prevent\n// inheritance to nested tables.\n\n// Generate the contextual variants\n.table-row-variant(active; @table-bg-active);\n.table-row-variant(success; @state-success-bg);\n.table-row-variant(info; @state-info-bg);\n.table-row-variant(warning; @state-warning-bg);\n.table-row-variant(danger; @state-danger-bg);\n\n\n// Responsive tables\n//\n// Wrap your tables in `.table-responsive` and we'll make them mobile friendly\n// by enabling horizontal scrolling. Only applies <768px. Everything above that\n// will display normally.\n\n.table-responsive {\n overflow-x: auto;\n min-height: 0.01%; // Workaround for IE9 bug (see https://github.com/twbs/bootstrap/issues/14837)\n\n @media screen and (max-width: @screen-xs-max) {\n width: 100%;\n margin-bottom: (@line-height-computed * 0.75);\n overflow-y: hidden;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n border: 1px solid @table-border-color;\n\n // Tighten up spacing\n > .table {\n margin-bottom: 0;\n\n // Ensure the content doesn't wrap\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n white-space: nowrap;\n }\n }\n }\n }\n\n // Special overrides for the bordered tables\n > .table-bordered {\n border: 0;\n\n // Nuke the appropriate borders so that the parent can handle them\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th:first-child,\n > td:first-child {\n border-left: 0;\n }\n > th:last-child,\n > td:last-child {\n border-right: 0;\n }\n }\n }\n\n // Only nuke the last row's bottom-border in `tbody` and `tfoot` since\n // chances are there will be only one `tr` in a `thead` and that would\n // remove the border altogether.\n > tbody,\n > tfoot {\n > tr:last-child {\n > th,\n > td {\n border-bottom: 0;\n }\n }\n }\n\n }\n }\n}\n","// Tables\n\n.table-row-variant(@state; @background) {\n // Exact selectors below required to override `.table-striped` and prevent\n // inheritance to nested tables.\n .table > thead > tr,\n .table > tbody > tr,\n .table > tfoot > tr {\n > td.@{state},\n > th.@{state},\n &.@{state} > td,\n &.@{state} > th {\n background-color: @background;\n }\n }\n\n // Hover states for `.table-hover`\n // Note: this is not available for cells or rows within `thead` or `tfoot`.\n .table-hover > tbody > tr {\n > td.@{state}:hover,\n > th.@{state}:hover,\n &.@{state}:hover > td,\n &:hover > .@{state},\n &.@{state}:hover > th {\n background-color: darken(@background, 5%);\n }\n }\n}\n","//\n// Forms\n// --------------------------------------------------\n\n\n// Normalize non-controls\n//\n// Restyle and baseline non-control form elements.\n\nfieldset {\n padding: 0;\n margin: 0;\n border: 0;\n // Chrome and Firefox set a `min-width: min-content;` on fieldsets,\n // so we reset that to ensure it behaves more like a standard block element.\n // See https://github.com/twbs/bootstrap/issues/12359.\n min-width: 0;\n}\n\nlegend {\n display: block;\n width: 100%;\n padding: 0;\n margin-bottom: @line-height-computed;\n font-size: (@font-size-base * 1.5);\n line-height: inherit;\n color: @legend-color;\n border: 0;\n border-bottom: 1px solid @legend-border-color;\n}\n\nlabel {\n display: inline-block;\n max-width: 100%; // Force IE8 to wrap long content (see https://github.com/twbs/bootstrap/issues/13141)\n margin-bottom: 5px;\n font-weight: bold;\n}\n\n\n// Normalize form controls\n//\n// While most of our form styles require extra classes, some basic normalization\n// is required to ensure optimum display with or without those classes to better\n// address browser inconsistencies.\n\n// Override content-box in Normalize (* isn't specific enough)\ninput[type=\"search\"] {\n .box-sizing(border-box);\n}\n\n// Position radios and checkboxes better\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n margin: 4px 0 0;\n margin-top: 1px \\9; // IE8-9\n line-height: normal;\n}\n\ninput[type=\"file\"] {\n display: block;\n}\n\n// Make range inputs behave like textual form controls\ninput[type=\"range\"] {\n display: block;\n width: 100%;\n}\n\n// Make multiple select elements height not fixed\nselect[multiple],\nselect[size] {\n height: auto;\n}\n\n// Focus for file, radio, and checkbox\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n .tab-focus();\n}\n\n// Adjust output element\noutput {\n display: block;\n padding-top: (@padding-base-vertical + 1);\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @input-color;\n}\n\n\n// Common form controls\n//\n// Shared size and type resets for form controls. Apply `.form-control` to any\n// of the following form controls:\n//\n// select\n// textarea\n// input[type=\"text\"]\n// input[type=\"password\"]\n// input[type=\"datetime\"]\n// input[type=\"datetime-local\"]\n// input[type=\"date\"]\n// input[type=\"month\"]\n// input[type=\"time\"]\n// input[type=\"week\"]\n// input[type=\"number\"]\n// input[type=\"email\"]\n// input[type=\"url\"]\n// input[type=\"search\"]\n// input[type=\"tel\"]\n// input[type=\"color\"]\n\n.form-control {\n display: block;\n width: 100%;\n height: @input-height-base; // Make inputs at least the height of their button counterpart (base line-height + padding + border)\n padding: @padding-base-vertical @padding-base-horizontal;\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @input-color;\n background-color: @input-bg;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid @input-border;\n border-radius: @input-border-radius; // Note: This has no effect on s in CSS.\n .box-shadow(inset 0 1px 1px rgba(0,0,0,.075));\n .transition(~\"border-color ease-in-out .15s, box-shadow ease-in-out .15s\");\n\n // Customize the `:focus` state to imitate native WebKit styles.\n .form-control-focus();\n\n // Placeholder\n .placeholder();\n\n // Unstyle the caret on ``\n// element gets special love because it's special, and that's a fact!\n.input-size(@input-height; @padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n height: @input-height;\n padding: @padding-vertical @padding-horizontal;\n font-size: @font-size;\n line-height: @line-height;\n border-radius: @border-radius;\n\n select& {\n height: @input-height;\n line-height: @input-height;\n }\n\n textarea&,\n select[multiple]& {\n height: auto;\n }\n}\n","//\n// Buttons\n// --------------------------------------------------\n\n\n// Base styles\n// --------------------------------------------------\n\n.btn {\n display: inline-block;\n margin-bottom: 0; // For input.btn\n font-weight: @btn-font-weight;\n text-align: center;\n vertical-align: middle;\n touch-action: manipulation;\n cursor: pointer;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid transparent;\n white-space: nowrap;\n .button-size(@padding-base-vertical; @padding-base-horizontal; @font-size-base; @line-height-base; @btn-border-radius-base);\n .user-select(none);\n\n &,\n &:active,\n &.active {\n &:focus,\n &.focus {\n .tab-focus();\n }\n }\n\n &:hover,\n &:focus,\n &.focus {\n color: @btn-default-color;\n text-decoration: none;\n }\n\n &:active,\n &.active {\n outline: 0;\n background-image: none;\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n cursor: @cursor-disabled;\n .opacity(.65);\n .box-shadow(none);\n }\n\n a& {\n &.disabled,\n fieldset[disabled] & {\n pointer-events: none; // Future-proof disabling of clicks on `` elements\n }\n }\n}\n\n\n// Alternate buttons\n// --------------------------------------------------\n\n.btn-default {\n .button-variant(@btn-default-color; @btn-default-bg; @btn-default-border);\n}\n.btn-primary {\n .button-variant(@btn-primary-color; @btn-primary-bg; @btn-primary-border);\n}\n// Success appears as green\n.btn-success {\n .button-variant(@btn-success-color; @btn-success-bg; @btn-success-border);\n}\n// Info appears as blue-green\n.btn-info {\n .button-variant(@btn-info-color; @btn-info-bg; @btn-info-border);\n}\n// Warning appears as orange\n.btn-warning {\n .button-variant(@btn-warning-color; @btn-warning-bg; @btn-warning-border);\n}\n// Danger and error appear as red\n.btn-danger {\n .button-variant(@btn-danger-color; @btn-danger-bg; @btn-danger-border);\n}\n\n\n// Link buttons\n// -------------------------\n\n// Make a button look and behave like a link\n.btn-link {\n color: @link-color;\n font-weight: normal;\n border-radius: 0;\n\n &,\n &:active,\n &.active,\n &[disabled],\n fieldset[disabled] & {\n background-color: transparent;\n .box-shadow(none);\n }\n &,\n &:hover,\n &:focus,\n &:active {\n border-color: transparent;\n }\n &:hover,\n &:focus {\n color: @link-hover-color;\n text-decoration: @link-hover-decoration;\n background-color: transparent;\n }\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus {\n color: @btn-link-disabled-color;\n text-decoration: none;\n }\n }\n}\n\n\n// Button Sizes\n// --------------------------------------------------\n\n.btn-lg {\n // line-height: ensure even-numbered height of button next to large input\n .button-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @btn-border-radius-large);\n}\n.btn-sm {\n // line-height: ensure proper height of button next to small input\n .button-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @btn-border-radius-small);\n}\n.btn-xs {\n .button-size(@padding-xs-vertical; @padding-xs-horizontal; @font-size-small; @line-height-small; @btn-border-radius-small);\n}\n\n\n// Block button\n// --------------------------------------------------\n\n.btn-block {\n display: block;\n width: 100%;\n}\n\n// Vertically space out multiple block buttons\n.btn-block + .btn-block {\n margin-top: 5px;\n}\n\n// Specificity overrides\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"] {\n &.btn-block {\n width: 100%;\n }\n}\n","// Button variants\n//\n// Easily pump out default styles, as well as :hover, :focus, :active,\n// and disabled options for all buttons\n\n.button-variant(@color; @background; @border) {\n color: @color;\n background-color: @background;\n border-color: @border;\n\n &:focus,\n &.focus {\n color: @color;\n background-color: darken(@background, 10%);\n border-color: darken(@border, 25%);\n }\n &:hover {\n color: @color;\n background-color: darken(@background, 10%);\n border-color: darken(@border, 12%);\n }\n &:active,\n &.active,\n .open > .dropdown-toggle& {\n color: @color;\n background-color: darken(@background, 10%);\n border-color: darken(@border, 12%);\n\n &:hover,\n &:focus,\n &.focus {\n color: @color;\n background-color: darken(@background, 17%);\n border-color: darken(@border, 25%);\n }\n }\n &:active,\n &.active,\n .open > .dropdown-toggle& {\n background-image: none;\n }\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus,\n &.focus {\n background-color: @background;\n border-color: @border;\n }\n }\n\n .badge {\n color: @background;\n background-color: @color;\n }\n}\n\n// Button sizes\n.button-size(@padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n padding: @padding-vertical @padding-horizontal;\n font-size: @font-size;\n line-height: @line-height;\n border-radius: @border-radius;\n}\n","// Opacity\n\n.opacity(@opacity) {\n opacity: @opacity;\n // IE8 filter\n @opacity-ie: (@opacity * 100);\n filter: ~\"alpha(opacity=@{opacity-ie})\";\n}\n","//\n// Component animations\n// --------------------------------------------------\n\n// Heads up!\n//\n// We don't use the `.opacity()` mixin here since it causes a bug with text\n// fields in IE7-8. Source: https://github.com/twbs/bootstrap/pull/3552.\n\n.fade {\n opacity: 0;\n .transition(opacity .15s linear);\n &.in {\n opacity: 1;\n }\n}\n\n.collapse {\n display: none;\n\n &.in { display: block; }\n tr&.in { display: table-row; }\n tbody&.in { display: table-row-group; }\n}\n\n.collapsing {\n position: relative;\n height: 0;\n overflow: hidden;\n .transition-property(~\"height, visibility\");\n .transition-duration(.35s);\n .transition-timing-function(ease);\n}\n","//\n// Dropdown menus\n// --------------------------------------------------\n\n\n// Dropdown arrow/caret\n.caret {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 2px;\n vertical-align: middle;\n border-top: @caret-width-base dashed;\n border-top: @caret-width-base solid ~\"\\9\"; // IE8\n border-right: @caret-width-base solid transparent;\n border-left: @caret-width-base solid transparent;\n}\n\n// The dropdown wrapper (div)\n.dropup,\n.dropdown {\n position: relative;\n}\n\n// Prevent the focus on the dropdown toggle when closing dropdowns\n.dropdown-toggle:focus {\n outline: 0;\n}\n\n// The dropdown menu (ul)\n.dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: @zindex-dropdown;\n display: none; // none by default, but block on \"open\" of the menu\n float: left;\n min-width: 160px;\n padding: 5px 0;\n margin: 2px 0 0; // override default ul\n list-style: none;\n font-size: @font-size-base;\n text-align: left; // Ensures proper alignment if parent has it changed (e.g., modal footer)\n background-color: @dropdown-bg;\n border: 1px solid @dropdown-fallback-border; // IE8 fallback\n border: 1px solid @dropdown-border;\n border-radius: @border-radius-base;\n .box-shadow(0 6px 12px rgba(0,0,0,.175));\n background-clip: padding-box;\n\n // Aligns the dropdown menu to right\n //\n // Deprecated as of 3.1.0 in favor of `.dropdown-menu-[dir]`\n &.pull-right {\n right: 0;\n left: auto;\n }\n\n // Dividers (basically an hr) within the dropdown\n .divider {\n .nav-divider(@dropdown-divider-bg);\n }\n\n // Links within the dropdown menu\n > li > a {\n display: block;\n padding: 3px 20px;\n clear: both;\n font-weight: normal;\n line-height: @line-height-base;\n color: @dropdown-link-color;\n white-space: nowrap; // prevent links from randomly breaking onto new lines\n }\n}\n\n// Hover/Focus state\n.dropdown-menu > li > a {\n &:hover,\n &:focus {\n text-decoration: none;\n color: @dropdown-link-hover-color;\n background-color: @dropdown-link-hover-bg;\n }\n}\n\n// Active state\n.dropdown-menu > .active > a {\n &,\n &:hover,\n &:focus {\n color: @dropdown-link-active-color;\n text-decoration: none;\n outline: 0;\n background-color: @dropdown-link-active-bg;\n }\n}\n\n// Disabled state\n//\n// Gray out text and ensure the hover/focus state remains gray\n\n.dropdown-menu > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @dropdown-link-disabled-color;\n }\n\n // Nuke hover/focus effects\n &:hover,\n &:focus {\n text-decoration: none;\n background-color: transparent;\n background-image: none; // Remove CSS gradient\n .reset-filter();\n cursor: @cursor-disabled;\n }\n}\n\n// Open state for the dropdown\n.open {\n // Show the menu\n > .dropdown-menu {\n display: block;\n }\n\n // Remove the outline when :focus is triggered\n > a {\n outline: 0;\n }\n}\n\n// Menu positioning\n//\n// Add extra class to `.dropdown-menu` to flip the alignment of the dropdown\n// menu with the parent.\n.dropdown-menu-right {\n left: auto; // Reset the default from `.dropdown-menu`\n right: 0;\n}\n// With v3, we enabled auto-flipping if you have a dropdown within a right\n// aligned nav component. To enable the undoing of that, we provide an override\n// to restore the default dropdown menu alignment.\n//\n// This is only for left-aligning a dropdown menu within a `.navbar-right` or\n// `.pull-right` nav component.\n.dropdown-menu-left {\n left: 0;\n right: auto;\n}\n\n// Dropdown section headers\n.dropdown-header {\n display: block;\n padding: 3px 20px;\n font-size: @font-size-small;\n line-height: @line-height-base;\n color: @dropdown-header-color;\n white-space: nowrap; // as with > li > a\n}\n\n// Backdrop to catch body clicks on mobile, etc.\n.dropdown-backdrop {\n position: fixed;\n left: 0;\n right: 0;\n bottom: 0;\n top: 0;\n z-index: (@zindex-dropdown - 10);\n}\n\n// Right aligned dropdowns\n.pull-right > .dropdown-menu {\n right: 0;\n left: auto;\n}\n\n// Allow for dropdowns to go bottom up (aka, dropup-menu)\n//\n// Just add .dropup after the standard .dropdown class and you're set, bro.\n// TODO: abstract this so that the navbar fixed styles are not placed here?\n\n.dropup,\n.navbar-fixed-bottom .dropdown {\n // Reverse the caret\n .caret {\n border-top: 0;\n border-bottom: @caret-width-base dashed;\n border-bottom: @caret-width-base solid ~\"\\9\"; // IE8\n content: \"\";\n }\n // Different positioning for bottom up menu\n .dropdown-menu {\n top: auto;\n bottom: 100%;\n margin-bottom: 2px;\n }\n}\n\n\n// Component alignment\n//\n// Reiterate per navbar.less and the modified component alignment there.\n\n@media (min-width: @grid-float-breakpoint) {\n .navbar-right {\n .dropdown-menu {\n .dropdown-menu-right();\n }\n // Necessary for overrides of the default right aligned menu.\n // Will remove come v4 in all likelihood.\n .dropdown-menu-left {\n .dropdown-menu-left();\n }\n }\n}\n","// Horizontal dividers\n//\n// Dividers (basically an hr) within dropdowns and nav lists\n\n.nav-divider(@color: #e5e5e5) {\n height: 1px;\n margin: ((@line-height-computed / 2) - 1) 0;\n overflow: hidden;\n background-color: @color;\n}\n","// Reset filters for IE\n//\n// When you need to remove a gradient background, do not forget to use this to reset\n// the IE filter for IE9 and below.\n\n.reset-filter() {\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(enabled = false)\"));\n}\n","//\n// Button groups\n// --------------------------------------------------\n\n// Make the div behave like a button\n.btn-group,\n.btn-group-vertical {\n position: relative;\n display: inline-block;\n vertical-align: middle; // match .btn alignment given font-size hack above\n > .btn {\n position: relative;\n float: left;\n // Bring the \"active\" button to the front\n &:hover,\n &:focus,\n &:active,\n &.active {\n z-index: 2;\n }\n }\n}\n\n// Prevent double borders when buttons are next to each other\n.btn-group {\n .btn + .btn,\n .btn + .btn-group,\n .btn-group + .btn,\n .btn-group + .btn-group {\n margin-left: -1px;\n }\n}\n\n// Optional: Group multiple button groups together for a toolbar\n.btn-toolbar {\n margin-left: -5px; // Offset the first child's margin\n &:extend(.clearfix all);\n\n .btn,\n .btn-group,\n .input-group {\n float: left;\n }\n > .btn,\n > .btn-group,\n > .input-group {\n margin-left: 5px;\n }\n}\n\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n border-radius: 0;\n}\n\n// Set corners individual because sometimes a single button can be in a .btn-group and we need :first-child and :last-child to both match\n.btn-group > .btn:first-child {\n margin-left: 0;\n &:not(:last-child):not(.dropdown-toggle) {\n .border-right-radius(0);\n }\n}\n// Need .dropdown-toggle since :last-child doesn't apply, given that a .dropdown-menu is used immediately after it\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n .border-left-radius(0);\n}\n\n// Custom edits for including btn-groups within btn-groups (useful for including dropdown buttons within a btn-group)\n.btn-group > .btn-group {\n float: left;\n}\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group > .btn-group:first-child:not(:last-child) {\n > .btn:last-child,\n > .dropdown-toggle {\n .border-right-radius(0);\n }\n}\n.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {\n .border-left-radius(0);\n}\n\n// On active and open, don't show outline\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n outline: 0;\n}\n\n\n// Sizing\n//\n// Remix the default button sizing classes into new ones for easier manipulation.\n\n.btn-group-xs > .btn { &:extend(.btn-xs); }\n.btn-group-sm > .btn { &:extend(.btn-sm); }\n.btn-group-lg > .btn { &:extend(.btn-lg); }\n\n\n// Split button dropdowns\n// ----------------------\n\n// Give the line between buttons some depth\n.btn-group > .btn + .dropdown-toggle {\n padding-left: 8px;\n padding-right: 8px;\n}\n.btn-group > .btn-lg + .dropdown-toggle {\n padding-left: 12px;\n padding-right: 12px;\n}\n\n// The clickable button for toggling the menu\n// Remove the gradient and set the same inset shadow as the :active state\n.btn-group.open .dropdown-toggle {\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n\n // Show no shadow for `.btn-link` since it has no other button styles.\n &.btn-link {\n .box-shadow(none);\n }\n}\n\n\n// Reposition the caret\n.btn .caret {\n margin-left: 0;\n}\n// Carets in other button sizes\n.btn-lg .caret {\n border-width: @caret-width-large @caret-width-large 0;\n border-bottom-width: 0;\n}\n// Upside down carets for .dropup\n.dropup .btn-lg .caret {\n border-width: 0 @caret-width-large @caret-width-large;\n}\n\n\n// Vertical button groups\n// ----------------------\n\n.btn-group-vertical {\n > .btn,\n > .btn-group,\n > .btn-group > .btn {\n display: block;\n float: none;\n width: 100%;\n max-width: 100%;\n }\n\n // Clear floats so dropdown menus can be properly placed\n > .btn-group {\n &:extend(.clearfix all);\n > .btn {\n float: none;\n }\n }\n\n > .btn + .btn,\n > .btn + .btn-group,\n > .btn-group + .btn,\n > .btn-group + .btn-group {\n margin-top: -1px;\n margin-left: 0;\n }\n}\n\n.btn-group-vertical > .btn {\n &:not(:first-child):not(:last-child) {\n border-radius: 0;\n }\n &:first-child:not(:last-child) {\n .border-top-radius(@btn-border-radius-base);\n .border-bottom-radius(0);\n }\n &:last-child:not(:first-child) {\n .border-top-radius(0);\n .border-bottom-radius(@btn-border-radius-base);\n }\n}\n.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group-vertical > .btn-group:first-child:not(:last-child) {\n > .btn:last-child,\n > .dropdown-toggle {\n .border-bottom-radius(0);\n }\n}\n.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {\n .border-top-radius(0);\n}\n\n\n// Justified button groups\n// ----------------------\n\n.btn-group-justified {\n display: table;\n width: 100%;\n table-layout: fixed;\n border-collapse: separate;\n > .btn,\n > .btn-group {\n float: none;\n display: table-cell;\n width: 1%;\n }\n > .btn-group .btn {\n width: 100%;\n }\n\n > .btn-group .dropdown-menu {\n left: auto;\n }\n}\n\n\n// Checkbox and radio options\n//\n// In order to support the browser's form validation feedback, powered by the\n// `required` attribute, we have to \"hide\" the inputs via `clip`. We cannot use\n// `display: none;` or `visibility: hidden;` as that also hides the popover.\n// Simply visually hiding the inputs via `opacity` would leave them clickable in\n// certain cases which is prevented by using `clip` and `pointer-events`.\n// This way, we ensure a DOM element is visible to position the popover from.\n//\n// See https://github.com/twbs/bootstrap/pull/12794 and\n// https://github.com/twbs/bootstrap/pull/14559 for more information.\n\n[data-toggle=\"buttons\"] {\n > .btn,\n > .btn-group > .btn {\n input[type=\"radio\"],\n input[type=\"checkbox\"] {\n position: absolute;\n clip: rect(0,0,0,0);\n pointer-events: none;\n }\n }\n}\n","// Single side border-radius\n\n.border-top-radius(@radius) {\n border-top-right-radius: @radius;\n border-top-left-radius: @radius;\n}\n.border-right-radius(@radius) {\n border-bottom-right-radius: @radius;\n border-top-right-radius: @radius;\n}\n.border-bottom-radius(@radius) {\n border-bottom-right-radius: @radius;\n border-bottom-left-radius: @radius;\n}\n.border-left-radius(@radius) {\n border-bottom-left-radius: @radius;\n border-top-left-radius: @radius;\n}\n","//\n// Input groups\n// --------------------------------------------------\n\n// Base styles\n// -------------------------\n.input-group {\n position: relative; // For dropdowns\n display: table;\n border-collapse: separate; // prevent input groups from inheriting border styles from table cells when placed within a table\n\n // Undo padding and float of grid classes\n &[class*=\"col-\"] {\n float: none;\n padding-left: 0;\n padding-right: 0;\n }\n\n .form-control {\n // Ensure that the input is always above the *appended* addon button for\n // proper border colors.\n position: relative;\n z-index: 2;\n\n // IE9 fubars the placeholder attribute in text inputs and the arrows on\n // select elements in input groups. To fix it, we float the input. Details:\n // https://github.com/twbs/bootstrap/issues/11561#issuecomment-28936855\n float: left;\n\n width: 100%;\n margin-bottom: 0;\n\n &:focus {\n z-index: 3;\n }\n }\n}\n\n// Sizing options\n//\n// Remix the default form control sizing classes into new ones for easier\n// manipulation.\n\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn {\n .input-lg();\n}\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn {\n .input-sm();\n}\n\n\n// Display as table-cell\n// -------------------------\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n display: table-cell;\n\n &:not(:first-child):not(:last-child) {\n border-radius: 0;\n }\n}\n// Addon and addon wrapper for buttons\n.input-group-addon,\n.input-group-btn {\n width: 1%;\n white-space: nowrap;\n vertical-align: middle; // Match the inputs\n}\n\n// Text input groups\n// -------------------------\n.input-group-addon {\n padding: @padding-base-vertical @padding-base-horizontal;\n font-size: @font-size-base;\n font-weight: normal;\n line-height: 1;\n color: @input-color;\n text-align: center;\n background-color: @input-group-addon-bg;\n border: 1px solid @input-group-addon-border-color;\n border-radius: @input-border-radius;\n\n // Sizing\n &.input-sm {\n padding: @padding-small-vertical @padding-small-horizontal;\n font-size: @font-size-small;\n border-radius: @input-border-radius-small;\n }\n &.input-lg {\n padding: @padding-large-vertical @padding-large-horizontal;\n font-size: @font-size-large;\n border-radius: @input-border-radius-large;\n }\n\n // Nuke default margins from checkboxes and radios to vertically center within.\n input[type=\"radio\"],\n input[type=\"checkbox\"] {\n margin-top: 0;\n }\n}\n\n// Reset rounded corners\n.input-group .form-control:first-child,\n.input-group-addon:first-child,\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group > .btn,\n.input-group-btn:first-child > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {\n .border-right-radius(0);\n}\n.input-group-addon:first-child {\n border-right: 0;\n}\n.input-group .form-control:last-child,\n.input-group-addon:last-child,\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group > .btn,\n.input-group-btn:last-child > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child),\n.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {\n .border-left-radius(0);\n}\n.input-group-addon:last-child {\n border-left: 0;\n}\n\n// Button input groups\n// -------------------------\n.input-group-btn {\n position: relative;\n // Jankily prevent input button groups from wrapping with `white-space` and\n // `font-size` in combination with `inline-block` on buttons.\n font-size: 0;\n white-space: nowrap;\n\n // Negative margin for spacing, position for bringing hovered/focused/actived\n // element above the siblings.\n > .btn {\n position: relative;\n + .btn {\n margin-left: -1px;\n }\n // Bring the \"active\" button to the front\n &:hover,\n &:focus,\n &:active {\n z-index: 2;\n }\n }\n\n // Negative margin to only have a 1px border between the two\n &:first-child {\n > .btn,\n > .btn-group {\n margin-right: -1px;\n }\n }\n &:last-child {\n > .btn,\n > .btn-group {\n z-index: 2;\n margin-left: -1px;\n }\n }\n}\n","//\n// Navs\n// --------------------------------------------------\n\n\n// Base class\n// --------------------------------------------------\n\n.nav {\n margin-bottom: 0;\n padding-left: 0; // Override default ul/ol\n list-style: none;\n &:extend(.clearfix all);\n\n > li {\n position: relative;\n display: block;\n\n > a {\n position: relative;\n display: block;\n padding: @nav-link-padding;\n &:hover,\n &:focus {\n text-decoration: none;\n background-color: @nav-link-hover-bg;\n }\n }\n\n // Disabled state sets text to gray and nukes hover/tab effects\n &.disabled > a {\n color: @nav-disabled-link-color;\n\n &:hover,\n &:focus {\n color: @nav-disabled-link-hover-color;\n text-decoration: none;\n background-color: transparent;\n cursor: @cursor-disabled;\n }\n }\n }\n\n // Open dropdowns\n .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @nav-link-hover-bg;\n border-color: @link-color;\n }\n }\n\n // Nav dividers (deprecated with v3.0.1)\n //\n // This should have been removed in v3 with the dropping of `.nav-list`, but\n // we missed it. We don't currently support this anywhere, but in the interest\n // of maintaining backward compatibility in case you use it, it's deprecated.\n .nav-divider {\n .nav-divider();\n }\n\n // Prevent IE8 from misplacing imgs\n //\n // See https://github.com/h5bp/html5-boilerplate/issues/984#issuecomment-3985989\n > li > a > img {\n max-width: none;\n }\n}\n\n\n// Tabs\n// -------------------------\n\n// Give the tabs something to sit on\n.nav-tabs {\n border-bottom: 1px solid @nav-tabs-border-color;\n > li {\n float: left;\n // Make the list-items overlay the bottom border\n margin-bottom: -1px;\n\n // Actual tabs (as links)\n > a {\n margin-right: 2px;\n line-height: @line-height-base;\n border: 1px solid transparent;\n border-radius: @border-radius-base @border-radius-base 0 0;\n &:hover {\n border-color: @nav-tabs-link-hover-border-color @nav-tabs-link-hover-border-color @nav-tabs-border-color;\n }\n }\n\n // Active state, and its :hover to override normal :hover\n &.active > a {\n &,\n &:hover,\n &:focus {\n color: @nav-tabs-active-link-hover-color;\n background-color: @nav-tabs-active-link-hover-bg;\n border: 1px solid @nav-tabs-active-link-hover-border-color;\n border-bottom-color: transparent;\n cursor: default;\n }\n }\n }\n // pulling this in mainly for less shorthand\n &.nav-justified {\n .nav-justified();\n .nav-tabs-justified();\n }\n}\n\n\n// Pills\n// -------------------------\n.nav-pills {\n > li {\n float: left;\n\n // Links rendered as pills\n > a {\n border-radius: @nav-pills-border-radius;\n }\n + li {\n margin-left: 2px;\n }\n\n // Active state\n &.active > a {\n &,\n &:hover,\n &:focus {\n color: @nav-pills-active-link-hover-color;\n background-color: @nav-pills-active-link-hover-bg;\n }\n }\n }\n}\n\n\n// Stacked pills\n.nav-stacked {\n > li {\n float: none;\n + li {\n margin-top: 2px;\n margin-left: 0; // no need for this gap between nav items\n }\n }\n}\n\n\n// Nav variations\n// --------------------------------------------------\n\n// Justified nav links\n// -------------------------\n\n.nav-justified {\n width: 100%;\n\n > li {\n float: none;\n > a {\n text-align: center;\n margin-bottom: 5px;\n }\n }\n\n > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n }\n\n @media (min-width: @screen-sm-min) {\n > li {\n display: table-cell;\n width: 1%;\n > a {\n margin-bottom: 0;\n }\n }\n }\n}\n\n// Move borders to anchors instead of bottom of list\n//\n// Mixin for adding on top the shared `.nav-justified` styles for our tabs\n.nav-tabs-justified {\n border-bottom: 0;\n\n > li > a {\n // Override margin from .nav-tabs\n margin-right: 0;\n border-radius: @border-radius-base;\n }\n\n > .active > a,\n > .active > a:hover,\n > .active > a:focus {\n border: 1px solid @nav-tabs-justified-link-border-color;\n }\n\n @media (min-width: @screen-sm-min) {\n > li > a {\n border-bottom: 1px solid @nav-tabs-justified-link-border-color;\n border-radius: @border-radius-base @border-radius-base 0 0;\n }\n > .active > a,\n > .active > a:hover,\n > .active > a:focus {\n border-bottom-color: @nav-tabs-justified-active-link-border-color;\n }\n }\n}\n\n\n// Tabbable tabs\n// -------------------------\n\n// Hide tabbable panes to start, show them when `.active`\n.tab-content {\n > .tab-pane {\n display: none;\n }\n > .active {\n display: block;\n }\n}\n\n\n// Dropdowns\n// -------------------------\n\n// Specific dropdowns\n.nav-tabs .dropdown-menu {\n // make dropdown border overlap tab border\n margin-top: -1px;\n // Remove the top rounded corners here since there is a hard edge above the menu\n .border-top-radius(0);\n}\n","//\n// Navbars\n// --------------------------------------------------\n\n\n// Wrapper and base class\n//\n// Provide a static navbar from which we expand to create full-width, fixed, and\n// other navbar variations.\n\n.navbar {\n position: relative;\n min-height: @navbar-height; // Ensure a navbar always shows (e.g., without a .navbar-brand in collapsed mode)\n margin-bottom: @navbar-margin-bottom;\n border: 1px solid transparent;\n\n // Prevent floats from breaking the navbar\n &:extend(.clearfix all);\n\n @media (min-width: @grid-float-breakpoint) {\n border-radius: @navbar-border-radius;\n }\n}\n\n\n// Navbar heading\n//\n// Groups `.navbar-brand` and `.navbar-toggle` into a single component for easy\n// styling of responsive aspects.\n\n.navbar-header {\n &:extend(.clearfix all);\n\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n }\n}\n\n\n// Navbar collapse (body)\n//\n// Group your navbar content into this for easy collapsing and expanding across\n// various device sizes. By default, this content is collapsed when <768px, but\n// will expand past that for a horizontal display.\n//\n// To start (on mobile devices) the navbar links, forms, and buttons are stacked\n// vertically and include a `max-height` to overflow in case you have too much\n// content for the user's viewport.\n\n.navbar-collapse {\n overflow-x: visible;\n padding-right: @navbar-padding-horizontal;\n padding-left: @navbar-padding-horizontal;\n border-top: 1px solid transparent;\n box-shadow: inset 0 1px 0 rgba(255,255,255,.1);\n &:extend(.clearfix all);\n -webkit-overflow-scrolling: touch;\n\n &.in {\n overflow-y: auto;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n width: auto;\n border-top: 0;\n box-shadow: none;\n\n &.collapse {\n display: block !important;\n height: auto !important;\n padding-bottom: 0; // Override default setting\n overflow: visible !important;\n }\n\n &.in {\n overflow-y: visible;\n }\n\n // Undo the collapse side padding for navbars with containers to ensure\n // alignment of right-aligned contents.\n .navbar-fixed-top &,\n .navbar-static-top &,\n .navbar-fixed-bottom & {\n padding-left: 0;\n padding-right: 0;\n }\n }\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n .navbar-collapse {\n max-height: @navbar-collapse-max-height;\n\n @media (max-device-width: @screen-xs-min) and (orientation: landscape) {\n max-height: 200px;\n }\n }\n}\n\n\n// Both navbar header and collapse\n//\n// When a container is present, change the behavior of the header and collapse.\n\n.container,\n.container-fluid {\n > .navbar-header,\n > .navbar-collapse {\n margin-right: -@navbar-padding-horizontal;\n margin-left: -@navbar-padding-horizontal;\n\n @media (min-width: @grid-float-breakpoint) {\n margin-right: 0;\n margin-left: 0;\n }\n }\n}\n\n\n//\n// Navbar alignment options\n//\n// Display the navbar across the entirety of the page or fixed it to the top or\n// bottom of the page.\n\n// Static top (unfixed, but 100% wide) navbar\n.navbar-static-top {\n z-index: @zindex-navbar;\n border-width: 0 0 1px;\n\n @media (min-width: @grid-float-breakpoint) {\n border-radius: 0;\n }\n}\n\n// Fix the top/bottom navbars when screen real estate supports it\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n position: fixed;\n right: 0;\n left: 0;\n z-index: @zindex-navbar-fixed;\n\n // Undo the rounded corners\n @media (min-width: @grid-float-breakpoint) {\n border-radius: 0;\n }\n}\n.navbar-fixed-top {\n top: 0;\n border-width: 0 0 1px;\n}\n.navbar-fixed-bottom {\n bottom: 0;\n margin-bottom: 0; // override .navbar defaults\n border-width: 1px 0 0;\n}\n\n\n// Brand/project name\n\n.navbar-brand {\n float: left;\n padding: @navbar-padding-vertical @navbar-padding-horizontal;\n font-size: @font-size-large;\n line-height: @line-height-computed;\n height: @navbar-height;\n\n &:hover,\n &:focus {\n text-decoration: none;\n }\n\n > img {\n display: block;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n .navbar > .container &,\n .navbar > .container-fluid & {\n margin-left: -@navbar-padding-horizontal;\n }\n }\n}\n\n\n// Navbar toggle\n//\n// Custom button for toggling the `.navbar-collapse`, powered by the collapse\n// JavaScript plugin.\n\n.navbar-toggle {\n position: relative;\n float: right;\n margin-right: @navbar-padding-horizontal;\n padding: 9px 10px;\n .navbar-vertical-align(34px);\n background-color: transparent;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid transparent;\n border-radius: @border-radius-base;\n\n // We remove the `outline` here, but later compensate by attaching `:hover`\n // styles to `:focus`.\n &:focus {\n outline: 0;\n }\n\n // Bars\n .icon-bar {\n display: block;\n width: 22px;\n height: 2px;\n border-radius: 1px;\n }\n .icon-bar + .icon-bar {\n margin-top: 4px;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n display: none;\n }\n}\n\n\n// Navbar nav links\n//\n// Builds on top of the `.nav` components with its own modifier class to make\n// the nav the full height of the horizontal nav (above 768px).\n\n.navbar-nav {\n margin: (@navbar-padding-vertical / 2) -@navbar-padding-horizontal;\n\n > li > a {\n padding-top: 10px;\n padding-bottom: 10px;\n line-height: @line-height-computed;\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display when collapsed\n .open .dropdown-menu {\n position: static;\n float: none;\n width: auto;\n margin-top: 0;\n background-color: transparent;\n border: 0;\n box-shadow: none;\n > li > a,\n .dropdown-header {\n padding: 5px 15px 5px 25px;\n }\n > li > a {\n line-height: @line-height-computed;\n &:hover,\n &:focus {\n background-image: none;\n }\n }\n }\n }\n\n // Uncollapse the nav\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n margin: 0;\n\n > li {\n float: left;\n > a {\n padding-top: @navbar-padding-vertical;\n padding-bottom: @navbar-padding-vertical;\n }\n }\n }\n}\n\n\n// Navbar form\n//\n// Extension of the `.form-inline` with some extra flavor for optimum display in\n// our navbars.\n\n.navbar-form {\n margin-left: -@navbar-padding-horizontal;\n margin-right: -@navbar-padding-horizontal;\n padding: 10px @navbar-padding-horizontal;\n border-top: 1px solid transparent;\n border-bottom: 1px solid transparent;\n @shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1);\n .box-shadow(@shadow);\n\n // Mixin behavior for optimum display\n .form-inline();\n\n .form-group {\n @media (max-width: @grid-float-breakpoint-max) {\n margin-bottom: 5px;\n\n &:last-child {\n margin-bottom: 0;\n }\n }\n }\n\n // Vertically center in expanded, horizontal navbar\n .navbar-vertical-align(@input-height-base);\n\n // Undo 100% width for pull classes\n @media (min-width: @grid-float-breakpoint) {\n width: auto;\n border: 0;\n margin-left: 0;\n margin-right: 0;\n padding-top: 0;\n padding-bottom: 0;\n .box-shadow(none);\n }\n}\n\n\n// Dropdown menus\n\n// Menu position and menu carets\n.navbar-nav > li > .dropdown-menu {\n margin-top: 0;\n .border-top-radius(0);\n}\n// Menu position and menu caret support for dropups via extra dropup class\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n margin-bottom: 0;\n .border-top-radius(@navbar-border-radius);\n .border-bottom-radius(0);\n}\n\n\n// Buttons in navbars\n//\n// Vertically center a button within a navbar (when *not* in a form).\n\n.navbar-btn {\n .navbar-vertical-align(@input-height-base);\n\n &.btn-sm {\n .navbar-vertical-align(@input-height-small);\n }\n &.btn-xs {\n .navbar-vertical-align(22);\n }\n}\n\n\n// Text in navbars\n//\n// Add a class to make any element properly align itself vertically within the navbars.\n\n.navbar-text {\n .navbar-vertical-align(@line-height-computed);\n\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n margin-left: @navbar-padding-horizontal;\n margin-right: @navbar-padding-horizontal;\n }\n}\n\n\n// Component alignment\n//\n// Repurpose the pull utilities as their own navbar utilities to avoid specificity\n// issues with parents and chaining. Only do this when the navbar is uncollapsed\n// though so that navbar contents properly stack and align in mobile.\n//\n// Declared after the navbar components to ensure more specificity on the margins.\n\n@media (min-width: @grid-float-breakpoint) {\n .navbar-left { .pull-left(); }\n .navbar-right {\n .pull-right();\n margin-right: -@navbar-padding-horizontal;\n\n ~ .navbar-right {\n margin-right: 0;\n }\n }\n}\n\n\n// Alternate navbars\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n background-color: @navbar-default-bg;\n border-color: @navbar-default-border;\n\n .navbar-brand {\n color: @navbar-default-brand-color;\n &:hover,\n &:focus {\n color: @navbar-default-brand-hover-color;\n background-color: @navbar-default-brand-hover-bg;\n }\n }\n\n .navbar-text {\n color: @navbar-default-color;\n }\n\n .navbar-nav {\n > li > a {\n color: @navbar-default-link-color;\n\n &:hover,\n &:focus {\n color: @navbar-default-link-hover-color;\n background-color: @navbar-default-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-active-color;\n background-color: @navbar-default-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-disabled-color;\n background-color: @navbar-default-link-disabled-bg;\n }\n }\n }\n\n .navbar-toggle {\n border-color: @navbar-default-toggle-border-color;\n &:hover,\n &:focus {\n background-color: @navbar-default-toggle-hover-bg;\n }\n .icon-bar {\n background-color: @navbar-default-toggle-icon-bar-bg;\n }\n }\n\n .navbar-collapse,\n .navbar-form {\n border-color: @navbar-default-border;\n }\n\n // Dropdown menu items\n .navbar-nav {\n // Remove background color from open dropdown\n > .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @navbar-default-link-active-bg;\n color: @navbar-default-link-active-color;\n }\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display when collapsed\n .open .dropdown-menu {\n > li > a {\n color: @navbar-default-link-color;\n &:hover,\n &:focus {\n color: @navbar-default-link-hover-color;\n background-color: @navbar-default-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-active-color;\n background-color: @navbar-default-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-disabled-color;\n background-color: @navbar-default-link-disabled-bg;\n }\n }\n }\n }\n }\n\n\n // Links in navbars\n //\n // Add a class to ensure links outside the navbar nav are colored correctly.\n\n .navbar-link {\n color: @navbar-default-link-color;\n &:hover {\n color: @navbar-default-link-hover-color;\n }\n }\n\n .btn-link {\n color: @navbar-default-link-color;\n &:hover,\n &:focus {\n color: @navbar-default-link-hover-color;\n }\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus {\n color: @navbar-default-link-disabled-color;\n }\n }\n }\n}\n\n// Inverse navbar\n\n.navbar-inverse {\n background-color: @navbar-inverse-bg;\n border-color: @navbar-inverse-border;\n\n .navbar-brand {\n color: @navbar-inverse-brand-color;\n &:hover,\n &:focus {\n color: @navbar-inverse-brand-hover-color;\n background-color: @navbar-inverse-brand-hover-bg;\n }\n }\n\n .navbar-text {\n color: @navbar-inverse-color;\n }\n\n .navbar-nav {\n > li > a {\n color: @navbar-inverse-link-color;\n\n &:hover,\n &:focus {\n color: @navbar-inverse-link-hover-color;\n background-color: @navbar-inverse-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-active-color;\n background-color: @navbar-inverse-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-disabled-color;\n background-color: @navbar-inverse-link-disabled-bg;\n }\n }\n }\n\n // Darken the responsive nav toggle\n .navbar-toggle {\n border-color: @navbar-inverse-toggle-border-color;\n &:hover,\n &:focus {\n background-color: @navbar-inverse-toggle-hover-bg;\n }\n .icon-bar {\n background-color: @navbar-inverse-toggle-icon-bar-bg;\n }\n }\n\n .navbar-collapse,\n .navbar-form {\n border-color: darken(@navbar-inverse-bg, 7%);\n }\n\n // Dropdowns\n .navbar-nav {\n > .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @navbar-inverse-link-active-bg;\n color: @navbar-inverse-link-active-color;\n }\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display\n .open .dropdown-menu {\n > .dropdown-header {\n border-color: @navbar-inverse-border;\n }\n .divider {\n background-color: @navbar-inverse-border;\n }\n > li > a {\n color: @navbar-inverse-link-color;\n &:hover,\n &:focus {\n color: @navbar-inverse-link-hover-color;\n background-color: @navbar-inverse-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-active-color;\n background-color: @navbar-inverse-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-disabled-color;\n background-color: @navbar-inverse-link-disabled-bg;\n }\n }\n }\n }\n }\n\n .navbar-link {\n color: @navbar-inverse-link-color;\n &:hover {\n color: @navbar-inverse-link-hover-color;\n }\n }\n\n .btn-link {\n color: @navbar-inverse-link-color;\n &:hover,\n &:focus {\n color: @navbar-inverse-link-hover-color;\n }\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus {\n color: @navbar-inverse-link-disabled-color;\n }\n }\n }\n}\n","// Navbar vertical align\n//\n// Vertically center elements in the navbar.\n// Example: an element has a height of 30px, so write out `.navbar-vertical-align(30px);` to calculate the appropriate top margin.\n\n.navbar-vertical-align(@element-height) {\n margin-top: ((@navbar-height - @element-height) / 2);\n margin-bottom: ((@navbar-height - @element-height) / 2);\n}\n","//\n// Utility classes\n// --------------------------------------------------\n\n\n// Floats\n// -------------------------\n\n.clearfix {\n .clearfix();\n}\n.center-block {\n .center-block();\n}\n.pull-right {\n float: right !important;\n}\n.pull-left {\n float: left !important;\n}\n\n\n// Toggling content\n// -------------------------\n\n// Note: Deprecated .hide in favor of .hidden or .sr-only (as appropriate) in v3.0.1\n.hide {\n display: none !important;\n}\n.show {\n display: block !important;\n}\n.invisible {\n visibility: hidden;\n}\n.text-hide {\n .text-hide();\n}\n\n\n// Hide from screenreaders and browsers\n//\n// Credit: HTML5 Boilerplate\n\n.hidden {\n display: none !important;\n}\n\n\n// For Affix plugin\n// -------------------------\n\n.affix {\n position: fixed;\n}\n","//\n// Breadcrumbs\n// --------------------------------------------------\n\n\n.breadcrumb {\n padding: @breadcrumb-padding-vertical @breadcrumb-padding-horizontal;\n margin-bottom: @line-height-computed;\n list-style: none;\n background-color: @breadcrumb-bg;\n border-radius: @border-radius-base;\n\n > li {\n display: inline-block;\n\n + li:before {\n content: \"@{breadcrumb-separator}\\00a0\"; // Unicode space added since inline-block means non-collapsing white-space\n padding: 0 5px;\n color: @breadcrumb-color;\n }\n }\n\n > .active {\n color: @breadcrumb-active-color;\n }\n}\n","//\n// Pagination (multiple pages)\n// --------------------------------------------------\n.pagination {\n display: inline-block;\n padding-left: 0;\n margin: @line-height-computed 0;\n border-radius: @border-radius-base;\n\n > li {\n display: inline; // Remove list-style and block-level defaults\n > a,\n > span {\n position: relative;\n float: left; // Collapse white-space\n padding: @padding-base-vertical @padding-base-horizontal;\n line-height: @line-height-base;\n text-decoration: none;\n color: @pagination-color;\n background-color: @pagination-bg;\n border: 1px solid @pagination-border;\n margin-left: -1px;\n }\n &:first-child {\n > a,\n > span {\n margin-left: 0;\n .border-left-radius(@border-radius-base);\n }\n }\n &:last-child {\n > a,\n > span {\n .border-right-radius(@border-radius-base);\n }\n }\n }\n\n > li > a,\n > li > span {\n &:hover,\n &:focus {\n z-index: 2;\n color: @pagination-hover-color;\n background-color: @pagination-hover-bg;\n border-color: @pagination-hover-border;\n }\n }\n\n > .active > a,\n > .active > span {\n &,\n &:hover,\n &:focus {\n z-index: 3;\n color: @pagination-active-color;\n background-color: @pagination-active-bg;\n border-color: @pagination-active-border;\n cursor: default;\n }\n }\n\n > .disabled {\n > span,\n > span:hover,\n > span:focus,\n > a,\n > a:hover,\n > a:focus {\n color: @pagination-disabled-color;\n background-color: @pagination-disabled-bg;\n border-color: @pagination-disabled-border;\n cursor: @cursor-disabled;\n }\n }\n}\n\n// Sizing\n// --------------------------------------------------\n\n// Large\n.pagination-lg {\n .pagination-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @border-radius-large);\n}\n\n// Small\n.pagination-sm {\n .pagination-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @border-radius-small);\n}\n","// Pagination\n\n.pagination-size(@padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n > li {\n > a,\n > span {\n padding: @padding-vertical @padding-horizontal;\n font-size: @font-size;\n line-height: @line-height;\n }\n &:first-child {\n > a,\n > span {\n .border-left-radius(@border-radius);\n }\n }\n &:last-child {\n > a,\n > span {\n .border-right-radius(@border-radius);\n }\n }\n }\n}\n","//\n// Pager pagination\n// --------------------------------------------------\n\n\n.pager {\n padding-left: 0;\n margin: @line-height-computed 0;\n list-style: none;\n text-align: center;\n &:extend(.clearfix all);\n li {\n display: inline;\n > a,\n > span {\n display: inline-block;\n padding: 5px 14px;\n background-color: @pager-bg;\n border: 1px solid @pager-border;\n border-radius: @pager-border-radius;\n }\n\n > a:hover,\n > a:focus {\n text-decoration: none;\n background-color: @pager-hover-bg;\n }\n }\n\n .next {\n > a,\n > span {\n float: right;\n }\n }\n\n .previous {\n > a,\n > span {\n float: left;\n }\n }\n\n .disabled {\n > a,\n > a:hover,\n > a:focus,\n > span {\n color: @pager-disabled-color;\n background-color: @pager-bg;\n cursor: @cursor-disabled;\n }\n }\n}\n","//\n// Labels\n// --------------------------------------------------\n\n.label {\n display: inline;\n padding: .2em .6em .3em;\n font-size: 75%;\n font-weight: bold;\n line-height: 1;\n color: @label-color;\n text-align: center;\n white-space: nowrap;\n vertical-align: baseline;\n border-radius: .25em;\n\n // Add hover effects, but only for links\n a& {\n &:hover,\n &:focus {\n color: @label-link-hover-color;\n text-decoration: none;\n cursor: pointer;\n }\n }\n\n // Empty labels collapse automatically (not available in IE8)\n &:empty {\n display: none;\n }\n\n // Quick fix for labels in buttons\n .btn & {\n position: relative;\n top: -1px;\n }\n}\n\n// Colors\n// Contextual variations (linked labels get darker on :hover)\n\n.label-default {\n .label-variant(@label-default-bg);\n}\n\n.label-primary {\n .label-variant(@label-primary-bg);\n}\n\n.label-success {\n .label-variant(@label-success-bg);\n}\n\n.label-info {\n .label-variant(@label-info-bg);\n}\n\n.label-warning {\n .label-variant(@label-warning-bg);\n}\n\n.label-danger {\n .label-variant(@label-danger-bg);\n}\n","// Labels\n\n.label-variant(@color) {\n background-color: @color;\n\n &[href] {\n &:hover,\n &:focus {\n background-color: darken(@color, 10%);\n }\n }\n}\n","//\n// Badges\n// --------------------------------------------------\n\n\n// Base class\n.badge {\n display: inline-block;\n min-width: 10px;\n padding: 3px 7px;\n font-size: @font-size-small;\n font-weight: @badge-font-weight;\n color: @badge-color;\n line-height: @badge-line-height;\n vertical-align: middle;\n white-space: nowrap;\n text-align: center;\n background-color: @badge-bg;\n border-radius: @badge-border-radius;\n\n // Empty badges collapse automatically (not available in IE8)\n &:empty {\n display: none;\n }\n\n // Quick fix for badges in buttons\n .btn & {\n position: relative;\n top: -1px;\n }\n\n .btn-xs &,\n .btn-group-xs > .btn & {\n top: 0;\n padding: 1px 5px;\n }\n\n // Hover state, but only for links\n a& {\n &:hover,\n &:focus {\n color: @badge-link-hover-color;\n text-decoration: none;\n cursor: pointer;\n }\n }\n\n // Account for badges in navs\n .list-group-item.active > &,\n .nav-pills > .active > a > & {\n color: @badge-active-color;\n background-color: @badge-active-bg;\n }\n\n .list-group-item > & {\n float: right;\n }\n\n .list-group-item > & + & {\n margin-right: 5px;\n }\n\n .nav-pills > li > a > & {\n margin-left: 3px;\n }\n}\n","//\n// Jumbotron\n// --------------------------------------------------\n\n\n.jumbotron {\n padding-top: @jumbotron-padding;\n padding-bottom: @jumbotron-padding;\n margin-bottom: @jumbotron-padding;\n color: @jumbotron-color;\n background-color: @jumbotron-bg;\n\n h1,\n .h1 {\n color: @jumbotron-heading-color;\n }\n\n p {\n margin-bottom: (@jumbotron-padding / 2);\n font-size: @jumbotron-font-size;\n font-weight: 200;\n }\n\n > hr {\n border-top-color: darken(@jumbotron-bg, 10%);\n }\n\n .container &,\n .container-fluid & {\n border-radius: @border-radius-large; // Only round corners at higher resolutions if contained in a container\n padding-left: (@grid-gutter-width / 2);\n padding-right: (@grid-gutter-width / 2);\n }\n\n .container {\n max-width: 100%;\n }\n\n @media screen and (min-width: @screen-sm-min) {\n padding-top: (@jumbotron-padding * 1.6);\n padding-bottom: (@jumbotron-padding * 1.6);\n\n .container &,\n .container-fluid & {\n padding-left: (@jumbotron-padding * 2);\n padding-right: (@jumbotron-padding * 2);\n }\n\n h1,\n .h1 {\n font-size: @jumbotron-heading-font-size;\n }\n }\n}\n","//\n// Thumbnails\n// --------------------------------------------------\n\n\n// Mixin and adjust the regular image class\n.thumbnail {\n display: block;\n padding: @thumbnail-padding;\n margin-bottom: @line-height-computed;\n line-height: @line-height-base;\n background-color: @thumbnail-bg;\n border: 1px solid @thumbnail-border;\n border-radius: @thumbnail-border-radius;\n .transition(border .2s ease-in-out);\n\n > img,\n a > img {\n &:extend(.img-responsive);\n margin-left: auto;\n margin-right: auto;\n }\n\n // Add a hover state for linked versions only\n a&:hover,\n a&:focus,\n a&.active {\n border-color: @link-color;\n }\n\n // Image captions\n .caption {\n padding: @thumbnail-caption-padding;\n color: @thumbnail-caption-color;\n }\n}\n","//\n// Alerts\n// --------------------------------------------------\n\n\n// Base styles\n// -------------------------\n\n.alert {\n padding: @alert-padding;\n margin-bottom: @line-height-computed;\n border: 1px solid transparent;\n border-radius: @alert-border-radius;\n\n // Headings for larger alerts\n h4 {\n margin-top: 0;\n // Specified for the h4 to prevent conflicts of changing @headings-color\n color: inherit;\n }\n\n // Provide class for links that match alerts\n .alert-link {\n font-weight: @alert-link-font-weight;\n }\n\n // Improve alignment and spacing of inner content\n > p,\n > ul {\n margin-bottom: 0;\n }\n\n > p + p {\n margin-top: 5px;\n }\n}\n\n// Dismissible alerts\n//\n// Expand the right padding and account for the close button's positioning.\n\n.alert-dismissable, // The misspelled .alert-dismissable was deprecated in 3.2.0.\n.alert-dismissible {\n padding-right: (@alert-padding + 20);\n\n // Adjust close link position\n .close {\n position: relative;\n top: -2px;\n right: -21px;\n color: inherit;\n }\n}\n\n// Alternate styles\n//\n// Generate contextual modifier classes for colorizing the alert.\n\n.alert-success {\n .alert-variant(@alert-success-bg; @alert-success-border; @alert-success-text);\n}\n\n.alert-info {\n .alert-variant(@alert-info-bg; @alert-info-border; @alert-info-text);\n}\n\n.alert-warning {\n .alert-variant(@alert-warning-bg; @alert-warning-border; @alert-warning-text);\n}\n\n.alert-danger {\n .alert-variant(@alert-danger-bg; @alert-danger-border; @alert-danger-text);\n}\n","// Alerts\n\n.alert-variant(@background; @border; @text-color) {\n background-color: @background;\n border-color: @border;\n color: @text-color;\n\n hr {\n border-top-color: darken(@border, 5%);\n }\n .alert-link {\n color: darken(@text-color, 10%);\n }\n}\n","//\n// Progress bars\n// --------------------------------------------------\n\n\n// Bar animations\n// -------------------------\n\n// WebKit\n@-webkit-keyframes progress-bar-stripes {\n from { background-position: 40px 0; }\n to { background-position: 0 0; }\n}\n\n// Spec and IE10+\n@keyframes progress-bar-stripes {\n from { background-position: 40px 0; }\n to { background-position: 0 0; }\n}\n\n\n// Bar itself\n// -------------------------\n\n// Outer container\n.progress {\n overflow: hidden;\n height: @line-height-computed;\n margin-bottom: @line-height-computed;\n background-color: @progress-bg;\n border-radius: @progress-border-radius;\n .box-shadow(inset 0 1px 2px rgba(0,0,0,.1));\n}\n\n// Bar of progress\n.progress-bar {\n float: left;\n width: 0%;\n height: 100%;\n font-size: @font-size-small;\n line-height: @line-height-computed;\n color: @progress-bar-color;\n text-align: center;\n background-color: @progress-bar-bg;\n .box-shadow(inset 0 -1px 0 rgba(0,0,0,.15));\n .transition(width .6s ease);\n}\n\n// Striped bars\n//\n// `.progress-striped .progress-bar` is deprecated as of v3.2.0 in favor of the\n// `.progress-bar-striped` class, which you just add to an existing\n// `.progress-bar`.\n.progress-striped .progress-bar,\n.progress-bar-striped {\n #gradient > .striped();\n background-size: 40px 40px;\n}\n\n// Call animation for the active one\n//\n// `.progress.active .progress-bar` is deprecated as of v3.2.0 in favor of the\n// `.progress-bar.active` approach.\n.progress.active .progress-bar,\n.progress-bar.active {\n .animation(progress-bar-stripes 2s linear infinite);\n}\n\n\n// Variations\n// -------------------------\n\n.progress-bar-success {\n .progress-bar-variant(@progress-bar-success-bg);\n}\n\n.progress-bar-info {\n .progress-bar-variant(@progress-bar-info-bg);\n}\n\n.progress-bar-warning {\n .progress-bar-variant(@progress-bar-warning-bg);\n}\n\n.progress-bar-danger {\n .progress-bar-variant(@progress-bar-danger-bg);\n}\n","// Gradients\n\n#gradient {\n\n // Horizontal gradient, from left to right\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n // Vertical gradient, from top to bottom\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n .directional(@start-color: #555; @end-color: #333; @deg: 45deg) {\n background-repeat: repeat-x;\n background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(@deg, @start-color, @end-color); // Opera 12\n background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n }\n .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .radial(@inner-color: #555; @outer-color: #333) {\n background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);\n background-image: radial-gradient(circle, @inner-color, @outer-color);\n background-repeat: no-repeat;\n }\n .striped(@color: rgba(255,255,255,.15); @angle: 45deg) {\n background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n }\n}\n","// Progress bars\n\n.progress-bar-variant(@color) {\n background-color: @color;\n\n // Deprecated parent class requirement as of v3.2.0\n .progress-striped & {\n #gradient > .striped();\n }\n}\n",".media {\n // Proper spacing between instances of .media\n margin-top: 15px;\n\n &:first-child {\n margin-top: 0;\n }\n}\n\n.media,\n.media-body {\n zoom: 1;\n overflow: hidden;\n}\n\n.media-body {\n width: 10000px;\n}\n\n.media-object {\n display: block;\n\n // Fix collapse in webkit from max-width: 100% and display: table-cell.\n &.img-thumbnail {\n max-width: none;\n }\n}\n\n.media-right,\n.media > .pull-right {\n padding-left: 10px;\n}\n\n.media-left,\n.media > .pull-left {\n padding-right: 10px;\n}\n\n.media-left,\n.media-right,\n.media-body {\n display: table-cell;\n vertical-align: top;\n}\n\n.media-middle {\n vertical-align: middle;\n}\n\n.media-bottom {\n vertical-align: bottom;\n}\n\n// Reset margins on headings for tighter default spacing\n.media-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n\n// Media list variation\n//\n// Undo default ul/ol styles\n.media-list {\n padding-left: 0;\n list-style: none;\n}\n","//\n// List groups\n// --------------------------------------------------\n\n\n// Base class\n//\n// Easily usable on

©2009-2019, ConfigServer Services (Jonathan Michaelson)