From c3ba828153ce8f88ad8ac23969136acec61f9664 Mon Sep 17 00:00:00 2001 From: Aetherinox Date: Sat, 31 Aug 2024 20:17:23 -0700 Subject: [PATCH] chore: update sources --- src/{ => official}/.gitattributes | 0 src/{ => official}/ConfigServer/AbuseIP.pm | 0 src/{ => official}/ConfigServer/CheckIP.pm | 0 src/{ => official}/ConfigServer/CloudFlare.pm | 0 src/{ => official}/ConfigServer/Config.pm | 0 .../ConfigServer/DisplayResellerUI.pm | 0 src/{ => official}/ConfigServer/DisplayUI.pm | 0 src/{ => official}/ConfigServer/GetEthDev.pm | 0 src/{ => official}/ConfigServer/GetIPs.pm | 0 src/{ => official}/ConfigServer/KillSSH.pm | 0 src/{ => official}/ConfigServer/Logger.pm | 0 src/{ => official}/ConfigServer/LookUpIP.pm | 0 src/{ => official}/ConfigServer/Messenger.pm | 0 src/{ => official}/ConfigServer/Ports.pm | 0 src/{ => official}/ConfigServer/RBLCheck.pm | 0 src/{ => official}/ConfigServer/RBLLookup.pm | 0 src/{ => official}/ConfigServer/RegexMain.pm | 0 src/{ => official}/ConfigServer/Sanity.pm | 0 src/{ => official}/ConfigServer/Sendmail.pm | 0 .../ConfigServer/ServerCheck.pm | 0 .../ConfigServer/ServerStats.pm | 0 src/{ => official}/ConfigServer/Service.pm | 0 src/{ => official}/ConfigServer/Slurp.pm | 0 src/{ => official}/ConfigServer/URLGet.pm | 0 src/{ => official}/ConfigServer/cseUI.pm | 0 src/{ => official}/Crypt/Blowfish_PP.pm | 0 src/{ => official}/Crypt/CBC.pm | 0 src/{ => official}/HTTP/Tiny.pm | 0 src/{ => official}/JSON/Tiny.pm | 0 src/{ => official}/Module/Installed/Tiny.pm | 0 src/{ => official}/Net/CIDR/Lite.pm | 0 src/{ => official}/Net/IP.pm | 0 src/{ => official}/accounttracking.txt | 0 src/{ => official}/alert.txt | 0 src/{ => official}/apache.http.txt | 0 src/{ => official}/apache.https.txt | 0 src/{ => official}/apache.main.txt | 0 src/{ => official}/apf_stub.pl | 0 src/{ => official}/auto.cwp.pl | 0 src/{ => official}/auto.cyberpanel.pl | 0 src/{ => official}/auto.directadmin.pl | 0 src/{ => official}/auto.generic.pl | 0 src/{ => official}/auto.interworx.pl | 0 src/{ => official}/auto.pl | 0 src/{ => official}/auto.vesta.pl | 0 src/{ => official}/changelog.txt | 0 src/{ => official}/connectiontracking.txt | 0 src/{ => official}/consolealert.txt | 0 src/{ => official}/cpanel.allow | 0 src/{ => official}/cpanel.comodo.allow | 0 src/{ => official}/cpanel.comodo.ignore | 0 src/{ => official}/cpanel.ignore | 0 .../cpanel/Driver/ConfigServercsf.pm | 0 .../cpanel/Driver/ConfigServercsf/META.pm | 0 src/{ => official}/cpanel/csf.cgi | 0 src/{ => official}/cpanel/csf.conf | 0 src/{ => official}/cpanel/csf.tmpl | 0 src/{ => official}/cpanel/upgrade.sh | 0 src/{ => official}/cpanelalert.txt | 0 src/{ => official}/csf.1.txt | 0 src/{ => official}/csf.allow | 0 src/{ => official}/csf.blocklists | 0 src/{ => official}/csf.c | 0 src/{ => official}/csf.cloudflare | 0 src/{ => official}/csf.conf | 0 src/{ => official}/csf.cwp.allow | 0 src/{ => official}/csf.cwp.conf | 0 src/{ => official}/csf.cwp.ignore | 0 src/{ => official}/csf.cwp.pignore | 0 src/{ => official}/csf.cyberpanel.allow | 0 src/{ => official}/csf.cyberpanel.conf | 0 src/{ => official}/csf.cyberpanel.ignore | 0 src/{ => official}/csf.cyberpanel.pignore | 0 src/{ => official}/csf.deny | 0 src/{ => official}/csf.directadmin.allow | 0 src/{ => official}/csf.directadmin.conf | 0 src/{ => official}/csf.directadmin.ignore | 0 src/{ => official}/csf.directadmin.pignore | 0 src/{ => official}/csf.dirwatch | 0 src/{ => official}/csf.div | 0 src/{ => official}/csf.dyndns | 0 src/{ => official}/csf.fignore | 0 src/{ => official}/csf.generic.allow | 0 src/{ => official}/csf.generic.conf | 0 src/{ => official}/csf.generic.ignore | 0 src/{ => official}/csf.generic.pignore | 0 src/{ => official}/csf.help | 0 src/{ => official}/csf.ignore | 0 src/{ => official}/csf.interworx.allow | 0 src/{ => official}/csf.interworx.conf | 0 src/{ => official}/csf.interworx.ignore | 0 src/{ => official}/csf.interworx.pignore | 0 src/{ => official}/csf.logfiles | 0 src/{ => official}/csf.logignore | 0 src/{ => official}/csf.mignore | 0 src/{ => official}/csf.pignore | 0 src/{ => official}/csf.pl | 0 src/{ => official}/csf.rblconf | 0 src/{ => official}/csf.rbls | 0 src/{ => official}/csf.redirect | 0 src/{ => official}/csf.resellers | 0 src/{ => official}/csf.rignore | 0 src/{ => official}/csf.service | 0 src/{ => official}/csf.sh | 0 src/{ => official}/csf.signore | 0 src/{ => official}/csf.sips | 0 src/{ => official}/csf.smtpauth | 0 src/{ => official}/csf.suignore | 0 src/{ => official}/csf.syslogs | 0 src/{ => official}/csf.syslogusers | 0 src/{ => official}/csf.uidignore | 0 src/{ => official}/csf.vesta.allow | 0 src/{ => official}/csf.vesta.conf | 0 src/{ => official}/csf.vesta.ignore | 0 src/{ => official}/csf.vesta.pignore | 0 src/{ => official}/csf/LICENSE.txt | 0 src/{ => official}/csf/admin_icon.svg | 0 src/{ => official}/csf/bootstrap-chosen.css | 0 .../csf/bootstrap/css/bootstrap.min.css | 0 .../csf/bootstrap/css/bootstrap.min.css.map | 0 .../fonts/glyphicons-halflings-regular.eot | Bin .../fonts/glyphicons-halflings-regular.svg | 0 .../fonts/glyphicons-halflings-regular.ttf | Bin .../fonts/glyphicons-halflings-regular.woff | Bin .../fonts/glyphicons-halflings-regular.woff2 | Bin .../csf/bootstrap/js/bootstrap.min.js | 0 src/{ => official}/csf/chosen-sprite.png | Bin src/{ => official}/csf/chosen-sprite@2x.png | Bin src/{ => official}/csf/chosen.min.css | 0 src/{ => official}/csf/chosen.min.js | 0 src/{ => official}/csf/configserver.css | 0 src/{ => official}/csf/csf-loader.gif | Bin src/{ => official}/csf/csf.svg | 0 src/{ => official}/csf/csf_small.png | Bin src/{ => official}/csf/jquery.min.js | 0 src/{ => official}/csf/loader.gif | Bin src/{ => official}/csf/reseller_icon.svg | 0 src/{ => official}/csfajaxtail.js | 0 src/{ => official}/csfcron.sh | 0 src/{ => official}/csftest.pl | 0 src/{ => official}/csget.pl | 0 src/{ => official}/cwp/ajax_csfframe.php | 0 src/{ => official}/cwp/configserver.php | 0 src/{ => official}/cwp/csf.pl | 0 src/{ => official}/cwp/csfofficial.php | 0 .../cyberpanel/configservercsf/__init__.py | 0 .../cyberpanel/configservercsf/admin.py | 0 .../cyberpanel/configservercsf/apps.py | 0 .../cyberpanel/configservercsf/config | 0 .../cyberpanel/configservercsf/meta.xml | 0 .../configservercsf/migrations/__init__.py | 0 .../cyberpanel/configservercsf/models.py | 0 .../cyberpanel/configservercsf/signals.py | 0 .../templates/configservercsf/index.html | 0 .../templates/configservercsf/menu.html | 0 .../cyberpanel/configservercsf/tests.py | 0 .../cyberpanel/configservercsf/urls.py | 0 .../cyberpanel/configservercsf/views.py | 0 src/{ => official}/cyberpanel/cyberpanel.pl | 0 src/{ => official}/da/admin/index.html | 0 src/{ => official}/da/admin/index.raw | 0 src/{ => official}/da/exec/da_csf.cgi | 0 .../da/exec/da_csf_reseller.cgi | 0 src/{ => official}/da/hooks/admin_img.html | 0 src/{ => official}/da/hooks/admin_txt.html | 0 src/{ => official}/da/hooks/reseller_img.html | 0 src/{ => official}/da/hooks/reseller_txt.html | 0 src/{ => official}/da/images/LICENSE.txt | 0 src/{ => official}/da/images/admin_icon.svg | 0 .../da/images/bootstrap-chosen.css | 0 .../da/images/bootstrap/css/bootstrap.min.css | 0 .../bootstrap/css/bootstrap.min.css.map | 0 .../fonts/glyphicons-halflings-regular.eot | Bin .../fonts/glyphicons-halflings-regular.svg | 0 .../fonts/glyphicons-halflings-regular.ttf | Bin .../fonts/glyphicons-halflings-regular.woff | Bin .../fonts/glyphicons-halflings-regular.woff2 | Bin .../da/images/bootstrap/js/bootstrap.min.js | 0 .../da/images/chosen-sprite.png | Bin .../da/images/chosen-sprite@2x.png | Bin src/{ => official}/da/images/chosen.min.css | 0 src/{ => official}/da/images/chosen.min.js | 0 src/{ => official}/da/images/configserver.css | 0 src/{ => official}/da/images/csf-loader.gif | Bin src/{ => official}/da/images/csf.svg | 0 src/{ => official}/da/images/csf_small.png | Bin src/{ => official}/da/images/jquery.min.js | 0 src/{ => official}/da/images/loader.gif | Bin .../da/images/reseller_icon.svg | 0 src/{ => official}/da/plugin.conf | 0 src/{ => official}/da/reseller/index.html | 0 src/{ => official}/da/reseller/index.raw | 0 src/{ => official}/da/scripts/install.sh | 0 src/{ => official}/da/scripts/uninstall.sh | 0 src/{ => official}/da/scripts/update.sh | 0 src/{ => official}/downloadservers | 0 src/{ => official}/exploitalert.txt | 0 src/{ => official}/filealert.txt | 0 src/{ => official}/forkbombalert.txt | 0 src/{ => official}/install.cpanel.sh | 0 src/{ => official}/install.cwp.sh | 0 src/{ => official}/install.cyberpanel.sh | 0 src/{ => official}/install.directadmin.sh | 0 src/{ => official}/install.generic.sh | 0 src/{ => official}/install.interworx.sh | 0 src/{ => official}/install.sh | 0 src/{ => official}/install.txt | 0 src/{ => official}/install.vesta.sh | 0 src/{ => official}/integrityalert.txt | 0 .../Ctrl/Nodeworx/Configservercsf.php | 0 .../interworx/Plugin/Configservercsf.php | 0 .../interworx/images/LICENSE.txt | 0 .../interworx/images/admin_icon.svg | 0 .../interworx/images/bootstrap-chosen.css | 0 .../images/bootstrap/css/bootstrap.min.css | 0 .../bootstrap/css/bootstrap.min.css.map | 0 .../fonts/glyphicons-halflings-regular.eot | Bin .../fonts/glyphicons-halflings-regular.svg | 0 .../fonts/glyphicons-halflings-regular.ttf | Bin .../fonts/glyphicons-halflings-regular.woff | Bin .../fonts/glyphicons-halflings-regular.woff2 | Bin .../images/bootstrap/js/bootstrap.min.js | 0 .../interworx/images/chosen-sprite.png | Bin .../interworx/images/chosen-sprite@2x.png | Bin .../interworx/images/chosen.min.css | 0 .../interworx/images/chosen.min.js | 0 .../interworx/images/configserver.css | 0 .../interworx/images/csf-loader.gif | Bin src/{ => official}/interworx/images/csf.svg | 0 .../interworx/images/csf_small.png | Bin .../interworx/images/jquery.min.js | 0 .../interworx/images/loader.gif | Bin .../interworx/images/reseller_icon.svg | 0 src/{ => official}/interworx/lib/index.pl | 0 src/{ => official}/interworx/lib/reseller.pl | 0 src/{ => official}/interworx/plugin.ini | 0 .../interworx/templates/admin.tpl | 0 .../interworx/templates/reseller.tpl | 0 src/{ => official}/lfd.logrotate | 0 src/{ => official}/lfd.pl | 0 src/{ => official}/lfd.service | 0 src/{ => official}/lfd.sh | 0 src/{ => official}/lfdcron.directadmin.sh | 0 src/{ => official}/lfdcron.sh | 0 src/{ => official}/license.txt | 0 src/{ => official}/litespeed.http.txt | 0 src/{ => official}/litespeed.https.txt | 0 src/{ => official}/litespeed.main.txt | 0 src/{ => official}/loadalert.txt | 0 src/{ => official}/logalert.txt | 0 src/{ => official}/logfloodalert.txt | 0 src/{ => official}/messenger/en.php | 0 src/{ => official}/messenger/index.html | 0 src/{ => official}/messenger/index.php | 0 .../messenger/index.recaptcha.html | 0 .../messenger/index.recaptcha.php | 0 src/{ => official}/messenger/index.text | 0 src/{ => official}/migratedata.sh | 0 src/{ => official}/modsecipdbalert.txt | 0 src/{ => official}/netblock.txt | 0 src/{ => official}/os.pl | 0 src/{ => official}/perf.sh | 0 src/{ => official}/permblock.txt | 0 src/{ => official}/portknocking.txt | 0 src/{ => official}/portscan.txt | 0 src/{ => official}/processtracking.txt | 0 .../profiles/block_all_perm.conf | 0 .../profiles/block_all_temp.conf | 0 .../profiles/disable_alerts.conf | 0 .../profiles/protection_high.conf | 0 .../profiles/protection_low.conf | 0 .../profiles/protection_medium.conf | 0 src/{ => official}/pt_deleted_action.pl | 0 src/{ => official}/queuealert.txt | 0 src/{ => official}/readme.txt | 0 src/{ => official}/recaptcha.txt | 0 src/{ => official}/regex.custom.pm | 0 src/{ => official}/regex.txt | 0 src/{ => official}/relayalert.txt | 0 src/{ => official}/remove_apf_bfd.sh | 0 src/{ => official}/resalert.txt | 0 src/{ => official}/reselleralert.txt | 0 src/{ => official}/restricted.txt | 0 src/{ => official}/sanity.txt | 0 src/{ => official}/scriptalert.txt | 0 src/{ => official}/sshalert.txt | 0 src/{ => official}/sualert.txt | 0 src/{ => official}/sudoalert.txt | 0 src/{ => official}/syslogalert.txt | 0 src/{ => official}/tracking.txt | 0 src/{ => official}/ui/images/LICENSE.txt | 0 src/{ => official}/ui/images/admin_icon.svg | 0 .../ui/images/bootstrap-chosen.css | 0 .../ui/images/bootstrap/css/bootstrap.min.css | 0 .../bootstrap/css/bootstrap.min.css.map | 0 .../fonts/glyphicons-halflings-regular.eot | Bin .../fonts/glyphicons-halflings-regular.svg | 0 .../fonts/glyphicons-halflings-regular.ttf | Bin .../fonts/glyphicons-halflings-regular.woff | Bin .../fonts/glyphicons-halflings-regular.woff2 | Bin .../ui/images/bootstrap/js/bootstrap.min.js | 0 .../ui/images/chosen-sprite.png | Bin .../ui/images/chosen-sprite@2x.png | Bin src/{ => official}/ui/images/chosen.min.css | 0 src/{ => official}/ui/images/chosen.min.js | 0 src/{ => official}/ui/images/configserver.css | 0 src/{ => official}/ui/images/csf-loader.gif | Bin src/{ => official}/ui/images/csf.svg | 0 src/{ => official}/ui/images/csf_small.png | Bin src/{ => official}/ui/images/jquery.min.js | 0 src/{ => official}/ui/images/loader.gif | Bin .../ui/images/reseller_icon.svg | 0 src/{ => official}/ui/server.crt | 0 src/{ => official}/ui/server.key | 0 src/{ => official}/ui/ui.allow | 0 src/{ => official}/ui/ui.ban | 0 src/{ => official}/uialert.txt | 0 src/{ => official}/uidscan.txt | 0 src/{ => official}/uninstall.cwp.sh | 0 src/{ => official}/uninstall.cyberpanel.sh | 0 src/{ => official}/uninstall.directadmin.sh | 0 src/{ => official}/uninstall.generic.sh | 0 src/{ => official}/uninstall.interworx.sh | 0 src/{ => official}/uninstall.sh | 0 src/{ => official}/uninstall.vesta.sh | 0 src/{ => official}/upgrade.txt | 0 src/{ => official}/usertracking.txt | 0 src/{ => official}/version.txt | 0 src/{ => official}/version/version.pm | 0 src/{ => official}/version/version/regex.pm | 0 src/{ => official}/version/version/vpp.pm | 0 src/{ => official}/vestacp/csf.pl | 0 src/{ => official}/vestacp/frame.php | 0 src/{ => official}/vestacp/index.php | 0 src/{ => official}/watchalert.txt | 0 .../webmin/csf/images/LICENSE.txt | 0 .../webmin/csf/images/admin_icon.svg | 0 .../webmin/csf/images/bootstrap-chosen.css | 0 .../images/bootstrap/css/bootstrap.min.css | 0 .../bootstrap/css/bootstrap.min.css.map | 0 .../fonts/glyphicons-halflings-regular.eot | Bin .../fonts/glyphicons-halflings-regular.svg | 0 .../fonts/glyphicons-halflings-regular.ttf | Bin .../fonts/glyphicons-halflings-regular.woff | Bin .../fonts/glyphicons-halflings-regular.woff2 | Bin .../csf/images/bootstrap/js/bootstrap.min.js | 0 .../webmin/csf/images/chosen-sprite.png | Bin .../webmin/csf/images/chosen-sprite@2x.png | Bin .../webmin/csf/images/chosen.min.css | 0 .../webmin/csf/images/chosen.min.js | 0 .../webmin/csf/images/configserver.css | 0 .../webmin/csf/images/csf-loader.gif | Bin src/{ => official}/webmin/csf/images/csf.svg | 0 .../webmin/csf/images/csf_small.png | Bin .../webmin/csf/images/jquery.min.js | 0 .../webmin/csf/images/loader.gif | Bin .../webmin/csf/images/reseller_icon.svg | 0 src/{ => official}/webmin/csf/index.cgi | 0 src/{ => official}/webmin/csf/module.info | 0 src/{ => official}/webminalert.txt | 0 src/{ => official}/x-arf.txt | 0 src/redux/.gitattributes | 2 + src/redux/ConfigServer/AbuseIP.pm | 87 + src/redux/ConfigServer/CheckIP.pm | 147 + src/redux/ConfigServer/CloudFlare.pm | 520 + src/redux/ConfigServer/Config.pm | 437 + src/redux/ConfigServer/DisplayResellerUI.pm | 228 + src/redux/ConfigServer/DisplayUI.pm | 2941 ++++ src/redux/ConfigServer/GetEthDev.pm | 157 + src/redux/ConfigServer/GetIPs.pm | 82 + src/redux/ConfigServer/KillSSH.pm | 94 + src/redux/ConfigServer/Logger.pm | 70 + src/redux/ConfigServer/LookUpIP.pm | 426 + src/redux/ConfigServer/Messenger.pm | 1277 ++ src/redux/ConfigServer/Ports.pm | 213 + src/redux/ConfigServer/RBLCheck.pm | 242 + src/redux/ConfigServer/RBLLookup.pm | 103 + src/redux/ConfigServer/RegexMain.pm | 1015 ++ src/redux/ConfigServer/Sanity.pm | 73 + src/redux/ConfigServer/Sendmail.pm | 166 + src/redux/ConfigServer/ServerCheck.pm | 1762 +++ src/redux/ConfigServer/ServerStats.pm | 3547 +++++ src/redux/ConfigServer/Service.pm | 118 + src/redux/ConfigServer/Slurp.pm | 55 + src/redux/ConfigServer/URLGet.pm | 292 + src/redux/ConfigServer/cseUI.pm | 1029 ++ src/redux/Crypt/Blowfish_PP.pm | 519 + src/redux/Crypt/CBC.pm | 1064 ++ src/redux/HTTP/Tiny.pm | 2425 ++++ src/redux/JSON/Tiny.pm | 306 + src/redux/Module/Installed/Tiny.pm | 223 + src/redux/Net/CIDR/Lite.pm | 685 + src/redux/Net/IP.pm | 2679 ++++ src/redux/accounttracking.txt | 9 + src/redux/alert.txt | 13 + src/redux/apache.http.txt | 35 + src/redux/apache.https.txt | 43 + src/redux/apache.main.txt | 0 src/redux/apf_stub.pl | 43 + src/redux/auto.cwp.pl | 592 + src/redux/auto.cyberpanel.pl | 576 + src/redux/auto.directadmin.pl | 605 + src/redux/auto.generic.pl | 576 + src/redux/auto.interworx.pl | 576 + src/redux/auto.pl | 1239 ++ src/redux/auto.vesta.pl | 592 + src/redux/changelog.txt | 6127 +++++++++ src/redux/connectiontracking.txt | 11 + src/redux/consolealert.txt | 5 + src/redux/cpanel.allow | 87 + src/redux/cpanel.comodo.allow | 43 + src/redux/cpanel.comodo.ignore | 23 + src/redux/cpanel.ignore | 22 + src/redux/cpanel/Driver/ConfigServercsf.pm | 51 + .../cpanel/Driver/ConfigServercsf/META.pm | 46 + src/redux/cpanel/csf.cgi | 327 + src/redux/cpanel/csf.conf | 28 + src/redux/cpanel/csf.tmpl | 29 + src/redux/cpanel/upgrade.sh | 12 + src/redux/cpanelalert.txt | 11 + src/redux/csf.1.txt | 284 + src/redux/csf.allow | 20 + src/redux/csf.blocklists | 103 + src/redux/csf.c | 72 + src/redux/csf.cloudflare | 50 + src/redux/csf.conf | 2825 ++++ src/redux/csf.cwp.allow | 17 + src/redux/csf.cwp.conf | 2685 ++++ src/redux/csf.cwp.ignore | 12 + src/redux/csf.cwp.pignore | 103 + src/redux/csf.cyberpanel.allow | 17 + src/redux/csf.cyberpanel.conf | 2679 ++++ src/redux/csf.cyberpanel.ignore | 12 + src/redux/csf.cyberpanel.pignore | 95 + src/redux/csf.deny | 18 + src/redux/csf.directadmin.allow | 17 + src/redux/csf.directadmin.conf | 2739 ++++ src/redux/csf.directadmin.ignore | 12 + src/redux/csf.directadmin.pignore | 82 + src/redux/csf.dirwatch | 14 + src/redux/csf.div | 230 + src/redux/csf.dyndns | 18 + src/redux/csf.fignore | 28 + src/redux/csf.generic.allow | 17 + src/redux/csf.generic.conf | 2678 ++++ src/redux/csf.generic.ignore | 12 + src/redux/csf.generic.pignore | 68 + src/redux/csf.help | 222 + src/redux/csf.ignore | 15 + src/redux/csf.interworx.allow | 17 + src/redux/csf.interworx.conf | 2686 ++++ src/redux/csf.interworx.ignore | 12 + src/redux/csf.interworx.pignore | 88 + src/redux/csf.logfiles | 36 + src/redux/csf.logignore | 75 + src/redux/csf.mignore | 9 + src/redux/csf.pignore | 145 + src/redux/csf.pl | 5996 ++++++++ src/redux/csf.rblconf | 22 + src/redux/csf.rbls | 41 + src/redux/csf.redirect | 34 + src/redux/csf.resellers | 47 + src/redux/csf.rignore | 40 + src/redux/csf.service | 13 + src/redux/csf.sh | 90 + src/redux/csf.signore | 7 + src/redux/csf.sips | 9 + src/redux/csf.smtpauth | 12 + src/redux/csf.suignore | 7 + src/redux/csf.syslogs | 90 + src/redux/csf.syslogusers | 66 + src/redux/csf.uidignore | 9 + src/redux/csf.vesta.allow | 17 + src/redux/csf.vesta.conf | 2685 ++++ src/redux/csf.vesta.ignore | 12 + src/redux/csf.vesta.pignore | 105 + src/redux/csf/LICENSE.txt | 14 + src/redux/csf/admin_icon.svg | 25 + src/redux/csf/bootstrap-chosen.css | 346 + src/redux/csf/bootstrap/css/bootstrap.min.css | 6 + .../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 src/redux/csf/bootstrap/js/bootstrap.min.js | 7 + src/redux/csf/chosen-sprite.png | Bin 0 -> 646 bytes src/redux/csf/chosen-sprite@2x.png | Bin 0 -> 872 bytes src/redux/csf/chosen.min.css | 11 + src/redux/csf/chosen.min.js | 3 + src/redux/csf/configserver.css | 193 + src/redux/csf/csf-loader.gif | Bin 0 -> 3951 bytes src/redux/csf/csf.svg | 25 + src/redux/csf/csf_small.png | Bin 0 -> 2211 bytes src/redux/csf/jquery.min.js | 5 + src/redux/csf/loader.gif | Bin 0 -> 3951 bytes src/redux/csf/reseller_icon.svg | 25 + src/redux/csfajaxtail.js | 132 + src/redux/csfcron.sh | 1 + src/redux/csftest.pl | 168 + src/redux/csget.pl | 90 + src/redux/cwp/ajax_csfframe.php | 22 + src/redux/cwp/configserver.php | 22 + src/redux/cwp/csf.pl | 195 + src/redux/cwp/csfofficial.php | 9 + .../cyberpanel/configservercsf/__init__.py | 1 + src/redux/cyberpanel/configservercsf/admin.py | 6 + src/redux/cyberpanel/configservercsf/apps.py | 10 + src/redux/cyberpanel/configservercsf/config | 0 src/redux/cyberpanel/configservercsf/meta.xml | 7 + .../configservercsf/migrations/__init__.py | 0 .../cyberpanel/configservercsf/models.py | 6 + .../cyberpanel/configservercsf/signals.py | 13 + .../templates/configservercsf/index.html | 17 + .../templates/configservercsf/menu.html | 25 + src/redux/cyberpanel/configservercsf/tests.py | 6 + src/redux/cyberpanel/configservercsf/urls.py | 8 + src/redux/cyberpanel/configservercsf/views.py | 64 + src/redux/cyberpanel/cyberpanel.pl | 205 + src/redux/da/admin/index.html | 31 + src/redux/da/admin/index.raw | 7 + src/redux/da/exec/da_csf.cgi | 309 + src/redux/da/exec/da_csf_reseller.cgi | 302 + src/redux/da/hooks/admin_img.html | 4 + src/redux/da/hooks/admin_txt.html | 1 + src/redux/da/hooks/reseller_img.html | 4 + src/redux/da/hooks/reseller_txt.html | 1 + src/redux/da/images/LICENSE.txt | 14 + src/redux/da/images/admin_icon.svg | 25 + src/redux/da/images/bootstrap-chosen.css | 346 + .../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 .../da/images/bootstrap/js/bootstrap.min.js | 7 + src/redux/da/images/chosen-sprite.png | Bin 0 -> 646 bytes src/redux/da/images/chosen-sprite@2x.png | Bin 0 -> 872 bytes src/redux/da/images/chosen.min.css | 11 + src/redux/da/images/chosen.min.js | 3 + src/redux/da/images/configserver.css | 193 + src/redux/da/images/csf-loader.gif | Bin 0 -> 3951 bytes src/redux/da/images/csf.svg | 25 + src/redux/da/images/csf_small.png | Bin 0 -> 2211 bytes src/redux/da/images/jquery.min.js | 5 + src/redux/da/images/loader.gif | Bin 0 -> 3951 bytes src/redux/da/images/reseller_icon.svg | 25 + src/redux/da/plugin.conf | 8 + src/redux/da/reseller/index.html | 31 + src/redux/da/reseller/index.raw | 7 + src/redux/da/scripts/install.sh | 5 + src/redux/da/scripts/uninstall.sh | 5 + src/redux/da/scripts/update.sh | 5 + src/redux/downloadservers | 2 + src/redux/exploitalert.txt | 7 + src/redux/filealert.txt | 9 + src/redux/forkbombalert.txt | 10 + src/redux/install.cpanel.sh | 567 + src/redux/install.cwp.sh | 543 + src/redux/install.cyberpanel.sh | 536 + src/redux/install.directadmin.sh | 521 + src/redux/install.generic.sh | 515 + src/redux/install.interworx.sh | 540 + src/redux/install.sh | 40 + src/redux/install.txt | 93 + src/redux/install.vesta.sh | 523 + src/redux/integrityalert.txt | 9 + .../Ctrl/Nodeworx/Configservercsf.php | 36 + .../interworx/Plugin/Configservercsf.php | 134 + src/redux/interworx/images/LICENSE.txt | 14 + src/redux/interworx/images/admin_icon.svg | 25 + .../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 + src/redux/interworx/images/chosen-sprite.png | Bin 0 -> 646 bytes .../interworx/images/chosen-sprite@2x.png | Bin 0 -> 872 bytes src/redux/interworx/images/chosen.min.css | 11 + src/redux/interworx/images/chosen.min.js | 3 + src/redux/interworx/images/configserver.css | 193 + src/redux/interworx/images/csf-loader.gif | Bin 0 -> 3951 bytes src/redux/interworx/images/csf.svg | 25 + src/redux/interworx/images/csf_small.png | Bin 0 -> 2211 bytes src/redux/interworx/images/jquery.min.js | 5 + src/redux/interworx/images/loader.gif | Bin 0 -> 3951 bytes src/redux/interworx/images/reseller_icon.svg | 25 + src/redux/interworx/lib/index.pl | 200 + src/redux/interworx/lib/reseller.pl | 228 + src/redux/interworx/plugin.ini | 5 + src/redux/interworx/templates/admin.tpl | 10 + src/redux/interworx/templates/reseller.tpl | 10 + src/redux/lfd.logrotate | 12 + src/redux/lfd.pl | 11370 ++++++++++++++++ src/redux/lfd.service | 12 + src/redux/lfd.sh | 102 + src/redux/lfdcron.directadmin.sh | 2 + src/redux/lfdcron.sh | 2 + src/redux/license.txt | 234 + src/redux/litespeed.http.txt | 15 + src/redux/litespeed.https.txt | 32 + src/redux/litespeed.main.txt | 0 src/redux/loadalert.txt | 55 + src/redux/logalert.txt | 5 + src/redux/logfloodalert.txt | 6 + src/redux/messenger/en.php | 15 + src/redux/messenger/index.html | 195 + src/redux/messenger/index.php | 212 + src/redux/messenger/index.recaptcha.html | 229 + src/redux/messenger/index.recaptcha.php | 273 + src/redux/messenger/index.text | 4 + src/redux/migratedata.sh | 244 + src/redux/modsecipdbalert.txt | 9 + src/redux/netblock.txt | 10 + src/redux/os.pl | 172 + src/redux/perf.sh | 9 + src/redux/permblock.txt | 10 + src/redux/portknocking.txt | 7 + src/redux/portscan.txt | 11 + src/redux/processtracking.txt | 31 + src/redux/profiles/block_all_perm.conf | 32 + src/redux/profiles/block_all_temp.conf | 32 + src/redux/profiles/disable_alerts.conf | 38 + src/redux/profiles/protection_high.conf | 61 + src/redux/profiles/protection_low.conf | 60 + src/redux/profiles/protection_medium.conf | 62 + src/redux/pt_deleted_action.pl | 26 + src/redux/queuealert.txt | 7 + src/redux/readme.txt | 1734 +++ src/redux/recaptcha.txt | 8 + src/redux/regex.custom.pm | 50 + src/redux/regex.txt | 143 + src/redux/relayalert.txt | 12 + src/redux/remove_apf_bfd.sh | 22 + src/redux/resalert.txt | 12 + src/redux/reselleralert.txt | 10 + src/redux/restricted.txt | 105 + src/redux/sanity.txt | 232 + src/redux/scriptalert.txt | 15 + src/redux/sshalert.txt | 12 + src/redux/sualert.txt | 12 + src/redux/sudoalert.txt | 12 + src/redux/syslogalert.txt | 8 + src/redux/tracking.txt | 12 + src/redux/ui/images/LICENSE.txt | 14 + src/redux/ui/images/admin_icon.svg | 25 + src/redux/ui/images/bootstrap-chosen.css | 346 + .../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 .../ui/images/bootstrap/js/bootstrap.min.js | 7 + src/redux/ui/images/chosen-sprite.png | Bin 0 -> 646 bytes src/redux/ui/images/chosen-sprite@2x.png | Bin 0 -> 872 bytes src/redux/ui/images/chosen.min.css | 11 + src/redux/ui/images/chosen.min.js | 3 + src/redux/ui/images/configserver.css | 193 + src/redux/ui/images/csf-loader.gif | Bin 0 -> 3951 bytes src/redux/ui/images/csf.svg | 25 + src/redux/ui/images/csf_small.png | Bin 0 -> 2211 bytes src/redux/ui/images/jquery.min.js | 5 + src/redux/ui/images/loader.gif | Bin 0 -> 3951 bytes src/redux/ui/images/reseller_icon.svg | 25 + src/redux/ui/server.crt | 20 + src/redux/ui/server.key | 28 + src/redux/ui/ui.allow | 0 src/redux/ui/ui.ban | 0 src/redux/uialert.txt | 9 + src/redux/uidscan.txt | 10 + src/redux/uninstall.cwp.sh | 61 + src/redux/uninstall.cyberpanel.sh | 70 + src/redux/uninstall.directadmin.sh | 61 + src/redux/uninstall.generic.sh | 58 + src/redux/uninstall.interworx.sh | 64 + src/redux/uninstall.sh | 77 + src/redux/uninstall.vesta.sh | 61 + src/redux/upgrade.txt | 22 + src/redux/usertracking.txt | 11 + src/redux/version.txt | 1 + src/redux/version/version.pm | 126 + src/redux/version/version/regex.pm | 117 + src/redux/version/version/vpp.pm | 1037 ++ src/redux/vestacp/csf.pl | 194 + src/redux/vestacp/frame.php | 30 + src/redux/vestacp/index.php | 34 + src/redux/watchalert.txt | 10 + src/redux/webmin/csf/images/LICENSE.txt | 14 + src/redux/webmin/csf/images/admin_icon.svg | 25 + .../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 + src/redux/webmin/csf/images/chosen-sprite.png | Bin 0 -> 646 bytes .../webmin/csf/images/chosen-sprite@2x.png | Bin 0 -> 872 bytes src/redux/webmin/csf/images/chosen.min.css | 11 + src/redux/webmin/csf/images/chosen.min.js | 3 + src/redux/webmin/csf/images/configserver.css | 193 + src/redux/webmin/csf/images/csf-loader.gif | Bin 0 -> 3951 bytes src/redux/webmin/csf/images/csf.svg | 25 + src/redux/webmin/csf/images/csf_small.png | Bin 0 -> 2211 bytes src/redux/webmin/csf/images/jquery.min.js | 5 + src/redux/webmin/csf/images/loader.gif | Bin 0 -> 3951 bytes src/redux/webmin/csf/images/reseller_icon.svg | 25 + src/redux/webmin/csf/index.cgi | 236 + src/redux/webmin/csf/module.info | 3 + src/redux/webminalert.txt | 11 + src/redux/x-arf.txt | 45 + src/web/downloads/CHANGELOG.msfe.txt | 1162 ++ src/web/downloads/LICENSE.msfe.txt | 257 + src/web/downloads/cmc.gz | Bin 0 -> 202427 bytes src/web/downloads/cmc/INSTALL.txt | 24 + src/web/downloads/cmc/changelog.txt | 171 + src/web/downloads/cmc/license.txt | 234 + src/web/downloads/cmm.gz | Bin 0 -> 211938 bytes src/web/downloads/cmm/CHANGELOG.txt | 213 + src/web/downloads/cmm/INSTALL.txt | 22 + src/web/downloads/cmm/license.txt | 234 + src/web/downloads/cmq.gz | Bin 0 -> 213961 bytes src/web/downloads/cmq/CHANGELOG.txt | 181 + src/web/downloads/cmq/INSTALL.txt | 15 + src/web/downloads/cmq/license.txt | 234 + src/web/downloads/cse.gz | Bin 0 -> 202845 bytes src/web/downloads/cse/CHANGELOG.txt | 98 + src/web/downloads/cse/INSTALL.txt | 22 + src/web/downloads/cse/license.txt | 234 + src/web/downloads/csf.gz | Bin 0 -> 2283133 bytes src/web/downloads/csf/changelog.txt | 6127 +++++++++ src/web/downloads/csf/install.txt | 93 + src/web/downloads/csf/license.txt | 234 + src/web/downloads/csf/readme.txt | 1734 +++ src/web/downloads/cxs/changelog.txt | 3217 +++++ src/web/downloads/cxs/license.txt | 582 + src/web/downloads/cxs/version.txt | 1 + src/web/downloads/msfeversion.txt | 1 + src/web/downloads/osm/changelog.txt | 149 + src/web/downloads/osm/license.txt | 234 + src/web/downloads/osm/osmversion.txt | 1 + .../schema/abuse_login-attack_0.2.json | 54 + src/web/templates/versions/ccm/cmmversion.txt | 1 + src/web/templates/versions/cmc/cmcversion.txt | 1 + src/web/templates/versions/cmq/cmqversion.txt | 1 + src/web/templates/versions/cse/cseversion.txt | 1 + src/web/templates/versions/csf/version.txt | 1 + src/web/templates/versions/cxs/version.txt | 1 + src/web/templates/versions/msfeversion | 1 + src/web/templates/versions/osm/osmversion.txt | 1 + src/web/templates/versions/version.txt | 1 + 762 files changed, 107157 insertions(+) rename src/{ => official}/.gitattributes (100%) rename src/{ => official}/ConfigServer/AbuseIP.pm (100%) rename src/{ => official}/ConfigServer/CheckIP.pm (100%) rename src/{ => official}/ConfigServer/CloudFlare.pm (100%) rename src/{ => official}/ConfigServer/Config.pm (100%) rename src/{ => official}/ConfigServer/DisplayResellerUI.pm (100%) rename src/{ => official}/ConfigServer/DisplayUI.pm (100%) rename src/{ => official}/ConfigServer/GetEthDev.pm (100%) rename src/{ => official}/ConfigServer/GetIPs.pm (100%) rename src/{ => official}/ConfigServer/KillSSH.pm (100%) rename src/{ => official}/ConfigServer/Logger.pm (100%) rename src/{ => official}/ConfigServer/LookUpIP.pm (100%) rename src/{ => official}/ConfigServer/Messenger.pm (100%) rename src/{ => official}/ConfigServer/Ports.pm (100%) rename src/{ => official}/ConfigServer/RBLCheck.pm (100%) rename src/{ => official}/ConfigServer/RBLLookup.pm (100%) rename src/{ => official}/ConfigServer/RegexMain.pm (100%) rename src/{ => official}/ConfigServer/Sanity.pm (100%) rename src/{ => official}/ConfigServer/Sendmail.pm (100%) rename src/{ => official}/ConfigServer/ServerCheck.pm (100%) rename src/{ => official}/ConfigServer/ServerStats.pm (100%) rename src/{ => official}/ConfigServer/Service.pm (100%) rename src/{ => official}/ConfigServer/Slurp.pm (100%) rename src/{ => official}/ConfigServer/URLGet.pm (100%) rename src/{ => official}/ConfigServer/cseUI.pm (100%) rename src/{ => official}/Crypt/Blowfish_PP.pm (100%) rename src/{ => official}/Crypt/CBC.pm (100%) rename src/{ => official}/HTTP/Tiny.pm (100%) rename src/{ => official}/JSON/Tiny.pm (100%) rename src/{ => official}/Module/Installed/Tiny.pm (100%) rename src/{ => official}/Net/CIDR/Lite.pm (100%) rename src/{ => official}/Net/IP.pm (100%) rename src/{ => official}/accounttracking.txt (100%) rename src/{ => official}/alert.txt (100%) rename src/{ => official}/apache.http.txt (100%) rename src/{ => official}/apache.https.txt (100%) rename src/{ => official}/apache.main.txt (100%) rename src/{ => official}/apf_stub.pl (100%) rename src/{ => official}/auto.cwp.pl (100%) rename src/{ => official}/auto.cyberpanel.pl (100%) rename src/{ => official}/auto.directadmin.pl (100%) rename src/{ => official}/auto.generic.pl (100%) rename src/{ => official}/auto.interworx.pl (100%) rename src/{ => official}/auto.pl (100%) rename src/{ => official}/auto.vesta.pl (100%) rename src/{ => official}/changelog.txt (100%) rename src/{ => official}/connectiontracking.txt (100%) rename src/{ => official}/consolealert.txt (100%) rename src/{ => official}/cpanel.allow (100%) rename src/{ => official}/cpanel.comodo.allow (100%) rename src/{ => official}/cpanel.comodo.ignore (100%) rename src/{ => official}/cpanel.ignore (100%) rename src/{ => official}/cpanel/Driver/ConfigServercsf.pm (100%) rename src/{ => official}/cpanel/Driver/ConfigServercsf/META.pm (100%) rename src/{ => official}/cpanel/csf.cgi (100%) rename src/{ => official}/cpanel/csf.conf (100%) rename src/{ => official}/cpanel/csf.tmpl (100%) rename src/{ => official}/cpanel/upgrade.sh (100%) rename src/{ => official}/cpanelalert.txt (100%) rename src/{ => official}/csf.1.txt (100%) rename src/{ => official}/csf.allow (100%) rename src/{ => official}/csf.blocklists (100%) rename src/{ => official}/csf.c (100%) rename src/{ => official}/csf.cloudflare (100%) rename src/{ => official}/csf.conf (100%) rename src/{ => official}/csf.cwp.allow (100%) rename src/{ => official}/csf.cwp.conf (100%) rename src/{ => official}/csf.cwp.ignore (100%) rename src/{ => official}/csf.cwp.pignore (100%) rename src/{ => official}/csf.cyberpanel.allow (100%) rename src/{ => official}/csf.cyberpanel.conf (100%) rename src/{ => official}/csf.cyberpanel.ignore (100%) rename src/{ => official}/csf.cyberpanel.pignore (100%) rename src/{ => official}/csf.deny (100%) rename src/{ => official}/csf.directadmin.allow (100%) rename src/{ => official}/csf.directadmin.conf (100%) rename src/{ => official}/csf.directadmin.ignore (100%) rename src/{ => official}/csf.directadmin.pignore (100%) rename src/{ => official}/csf.dirwatch (100%) rename src/{ => official}/csf.div (100%) rename src/{ => official}/csf.dyndns (100%) rename src/{ => official}/csf.fignore (100%) rename src/{ => official}/csf.generic.allow (100%) rename src/{ => official}/csf.generic.conf (100%) rename src/{ => official}/csf.generic.ignore (100%) rename src/{ => official}/csf.generic.pignore (100%) rename src/{ => official}/csf.help (100%) rename src/{ => official}/csf.ignore (100%) rename src/{ => official}/csf.interworx.allow (100%) rename src/{ => official}/csf.interworx.conf (100%) rename src/{ => official}/csf.interworx.ignore (100%) rename src/{ => official}/csf.interworx.pignore (100%) rename src/{ => official}/csf.logfiles (100%) rename src/{ => official}/csf.logignore (100%) rename src/{ => official}/csf.mignore (100%) rename src/{ => official}/csf.pignore (100%) rename src/{ => official}/csf.pl (100%) rename src/{ => official}/csf.rblconf (100%) rename src/{ => official}/csf.rbls (100%) rename src/{ => official}/csf.redirect (100%) rename src/{ => official}/csf.resellers (100%) rename src/{ => official}/csf.rignore (100%) rename src/{ => official}/csf.service (100%) rename src/{ => official}/csf.sh (100%) rename src/{ => official}/csf.signore (100%) rename src/{ => official}/csf.sips (100%) rename src/{ => official}/csf.smtpauth (100%) rename src/{ => official}/csf.suignore (100%) rename src/{ => official}/csf.syslogs (100%) rename src/{ => official}/csf.syslogusers (100%) rename src/{ => official}/csf.uidignore (100%) rename src/{ => official}/csf.vesta.allow (100%) rename src/{ => official}/csf.vesta.conf (100%) rename src/{ => official}/csf.vesta.ignore (100%) rename src/{ => official}/csf.vesta.pignore (100%) rename src/{ => official}/csf/LICENSE.txt (100%) rename src/{ => official}/csf/admin_icon.svg (100%) rename src/{ => official}/csf/bootstrap-chosen.css (100%) rename src/{ => official}/csf/bootstrap/css/bootstrap.min.css (100%) rename src/{ => official}/csf/bootstrap/css/bootstrap.min.css.map (100%) rename src/{ => official}/csf/bootstrap/fonts/glyphicons-halflings-regular.eot (100%) rename src/{ => official}/csf/bootstrap/fonts/glyphicons-halflings-regular.svg (100%) rename src/{ => official}/csf/bootstrap/fonts/glyphicons-halflings-regular.ttf (100%) rename src/{ => official}/csf/bootstrap/fonts/glyphicons-halflings-regular.woff (100%) rename src/{ => official}/csf/bootstrap/fonts/glyphicons-halflings-regular.woff2 (100%) rename src/{ => official}/csf/bootstrap/js/bootstrap.min.js (100%) rename src/{ => official}/csf/chosen-sprite.png (100%) rename src/{ => official}/csf/chosen-sprite@2x.png (100%) rename src/{ => official}/csf/chosen.min.css (100%) rename src/{ => official}/csf/chosen.min.js (100%) rename src/{ => official}/csf/configserver.css (100%) rename src/{ => official}/csf/csf-loader.gif (100%) rename src/{ => official}/csf/csf.svg (100%) rename src/{ => official}/csf/csf_small.png (100%) rename src/{ => official}/csf/jquery.min.js (100%) rename src/{ => official}/csf/loader.gif (100%) rename src/{ => official}/csf/reseller_icon.svg (100%) rename src/{ => official}/csfajaxtail.js (100%) rename src/{ => official}/csfcron.sh (100%) rename src/{ => official}/csftest.pl (100%) rename src/{ => official}/csget.pl (100%) rename src/{ => official}/cwp/ajax_csfframe.php (100%) rename src/{ => official}/cwp/configserver.php (100%) rename src/{ => official}/cwp/csf.pl (100%) rename src/{ => official}/cwp/csfofficial.php (100%) rename src/{ => official}/cyberpanel/configservercsf/__init__.py (100%) rename src/{ => official}/cyberpanel/configservercsf/admin.py (100%) rename src/{ => official}/cyberpanel/configservercsf/apps.py (100%) rename src/{ => official}/cyberpanel/configservercsf/config (100%) rename src/{ => official}/cyberpanel/configservercsf/meta.xml (100%) rename src/{ => official}/cyberpanel/configservercsf/migrations/__init__.py (100%) rename src/{ => official}/cyberpanel/configservercsf/models.py (100%) rename src/{ => official}/cyberpanel/configservercsf/signals.py (100%) rename src/{ => official}/cyberpanel/configservercsf/templates/configservercsf/index.html (100%) rename src/{ => official}/cyberpanel/configservercsf/templates/configservercsf/menu.html (100%) rename src/{ => official}/cyberpanel/configservercsf/tests.py (100%) rename src/{ => official}/cyberpanel/configservercsf/urls.py (100%) rename src/{ => official}/cyberpanel/configservercsf/views.py (100%) rename src/{ => official}/cyberpanel/cyberpanel.pl (100%) rename src/{ => official}/da/admin/index.html (100%) rename src/{ => official}/da/admin/index.raw (100%) rename src/{ => official}/da/exec/da_csf.cgi (100%) rename src/{ => official}/da/exec/da_csf_reseller.cgi (100%) rename src/{ => official}/da/hooks/admin_img.html (100%) rename src/{ => official}/da/hooks/admin_txt.html (100%) rename src/{ => official}/da/hooks/reseller_img.html (100%) rename src/{ => official}/da/hooks/reseller_txt.html (100%) rename src/{ => official}/da/images/LICENSE.txt (100%) rename src/{ => official}/da/images/admin_icon.svg (100%) rename src/{ => official}/da/images/bootstrap-chosen.css (100%) rename src/{ => official}/da/images/bootstrap/css/bootstrap.min.css (100%) rename src/{ => official}/da/images/bootstrap/css/bootstrap.min.css.map (100%) rename src/{ => official}/da/images/bootstrap/fonts/glyphicons-halflings-regular.eot (100%) rename src/{ => official}/da/images/bootstrap/fonts/glyphicons-halflings-regular.svg (100%) rename src/{ => official}/da/images/bootstrap/fonts/glyphicons-halflings-regular.ttf (100%) rename src/{ => official}/da/images/bootstrap/fonts/glyphicons-halflings-regular.woff (100%) rename src/{ => official}/da/images/bootstrap/fonts/glyphicons-halflings-regular.woff2 (100%) rename src/{ => official}/da/images/bootstrap/js/bootstrap.min.js (100%) rename src/{ => official}/da/images/chosen-sprite.png (100%) rename src/{ => official}/da/images/chosen-sprite@2x.png (100%) rename src/{ => official}/da/images/chosen.min.css (100%) rename src/{ => official}/da/images/chosen.min.js (100%) rename src/{ => official}/da/images/configserver.css (100%) rename src/{ => official}/da/images/csf-loader.gif (100%) rename src/{ => official}/da/images/csf.svg (100%) rename src/{ => official}/da/images/csf_small.png (100%) rename src/{ => official}/da/images/jquery.min.js (100%) rename src/{ => official}/da/images/loader.gif (100%) rename src/{ => official}/da/images/reseller_icon.svg (100%) rename src/{ => official}/da/plugin.conf (100%) rename src/{ => official}/da/reseller/index.html (100%) rename src/{ => official}/da/reseller/index.raw (100%) rename src/{ => official}/da/scripts/install.sh (100%) rename src/{ => official}/da/scripts/uninstall.sh (100%) rename src/{ => official}/da/scripts/update.sh (100%) rename src/{ => official}/downloadservers (100%) rename src/{ => official}/exploitalert.txt (100%) rename src/{ => official}/filealert.txt (100%) rename src/{ => official}/forkbombalert.txt (100%) rename src/{ => official}/install.cpanel.sh (100%) rename src/{ => official}/install.cwp.sh (100%) rename src/{ => official}/install.cyberpanel.sh (100%) rename src/{ => official}/install.directadmin.sh (100%) rename src/{ => official}/install.generic.sh (100%) rename src/{ => official}/install.interworx.sh (100%) rename src/{ => official}/install.sh (100%) rename src/{ => official}/install.txt (100%) rename src/{ => official}/install.vesta.sh (100%) rename src/{ => official}/integrityalert.txt (100%) rename src/{ => official}/interworx/Ctrl/Nodeworx/Configservercsf.php (100%) rename src/{ => official}/interworx/Plugin/Configservercsf.php (100%) rename src/{ => official}/interworx/images/LICENSE.txt (100%) rename src/{ => official}/interworx/images/admin_icon.svg (100%) rename src/{ => official}/interworx/images/bootstrap-chosen.css (100%) rename src/{ => official}/interworx/images/bootstrap/css/bootstrap.min.css (100%) rename src/{ => official}/interworx/images/bootstrap/css/bootstrap.min.css.map (100%) rename src/{ => official}/interworx/images/bootstrap/fonts/glyphicons-halflings-regular.eot (100%) rename src/{ => official}/interworx/images/bootstrap/fonts/glyphicons-halflings-regular.svg (100%) rename src/{ => official}/interworx/images/bootstrap/fonts/glyphicons-halflings-regular.ttf (100%) rename src/{ => official}/interworx/images/bootstrap/fonts/glyphicons-halflings-regular.woff (100%) rename src/{ => official}/interworx/images/bootstrap/fonts/glyphicons-halflings-regular.woff2 (100%) rename src/{ => official}/interworx/images/bootstrap/js/bootstrap.min.js (100%) rename src/{ => official}/interworx/images/chosen-sprite.png (100%) rename src/{ => official}/interworx/images/chosen-sprite@2x.png (100%) rename src/{ => official}/interworx/images/chosen.min.css (100%) rename src/{ => official}/interworx/images/chosen.min.js (100%) rename src/{ => official}/interworx/images/configserver.css (100%) rename src/{ => official}/interworx/images/csf-loader.gif (100%) rename src/{ => official}/interworx/images/csf.svg (100%) rename src/{ => official}/interworx/images/csf_small.png (100%) rename src/{ => official}/interworx/images/jquery.min.js (100%) rename src/{ => official}/interworx/images/loader.gif (100%) rename src/{ => official}/interworx/images/reseller_icon.svg (100%) rename src/{ => official}/interworx/lib/index.pl (100%) rename src/{ => official}/interworx/lib/reseller.pl (100%) rename src/{ => official}/interworx/plugin.ini (100%) rename src/{ => official}/interworx/templates/admin.tpl (100%) rename src/{ => official}/interworx/templates/reseller.tpl (100%) rename src/{ => official}/lfd.logrotate (100%) rename src/{ => official}/lfd.pl (100%) rename src/{ => official}/lfd.service (100%) rename src/{ => official}/lfd.sh (100%) rename src/{ => official}/lfdcron.directadmin.sh (100%) rename src/{ => official}/lfdcron.sh (100%) rename src/{ => official}/license.txt (100%) rename src/{ => official}/litespeed.http.txt (100%) rename src/{ => official}/litespeed.https.txt (100%) rename src/{ => official}/litespeed.main.txt (100%) rename src/{ => official}/loadalert.txt (100%) rename src/{ => official}/logalert.txt (100%) rename src/{ => official}/logfloodalert.txt (100%) rename src/{ => official}/messenger/en.php (100%) rename src/{ => official}/messenger/index.html (100%) rename src/{ => official}/messenger/index.php (100%) rename src/{ => official}/messenger/index.recaptcha.html (100%) rename src/{ => official}/messenger/index.recaptcha.php (100%) rename src/{ => official}/messenger/index.text (100%) rename src/{ => official}/migratedata.sh (100%) rename src/{ => official}/modsecipdbalert.txt (100%) rename src/{ => official}/netblock.txt (100%) rename src/{ => official}/os.pl (100%) rename src/{ => official}/perf.sh (100%) rename src/{ => official}/permblock.txt (100%) rename src/{ => official}/portknocking.txt (100%) rename src/{ => official}/portscan.txt (100%) rename src/{ => official}/processtracking.txt (100%) rename src/{ => official}/profiles/block_all_perm.conf (100%) rename src/{ => official}/profiles/block_all_temp.conf (100%) rename src/{ => official}/profiles/disable_alerts.conf (100%) rename src/{ => official}/profiles/protection_high.conf (100%) rename src/{ => official}/profiles/protection_low.conf (100%) rename src/{ => official}/profiles/protection_medium.conf (100%) rename src/{ => official}/pt_deleted_action.pl (100%) rename src/{ => official}/queuealert.txt (100%) rename src/{ => official}/readme.txt (100%) rename src/{ => official}/recaptcha.txt (100%) rename src/{ => official}/regex.custom.pm (100%) rename src/{ => official}/regex.txt (100%) rename src/{ => official}/relayalert.txt (100%) rename src/{ => official}/remove_apf_bfd.sh (100%) rename src/{ => official}/resalert.txt (100%) rename src/{ => official}/reselleralert.txt (100%) rename src/{ => official}/restricted.txt (100%) rename src/{ => official}/sanity.txt (100%) rename src/{ => official}/scriptalert.txt (100%) rename src/{ => official}/sshalert.txt (100%) rename src/{ => official}/sualert.txt (100%) rename src/{ => official}/sudoalert.txt (100%) rename src/{ => official}/syslogalert.txt (100%) rename src/{ => official}/tracking.txt (100%) rename src/{ => official}/ui/images/LICENSE.txt (100%) rename src/{ => official}/ui/images/admin_icon.svg (100%) rename src/{ => official}/ui/images/bootstrap-chosen.css (100%) rename src/{ => official}/ui/images/bootstrap/css/bootstrap.min.css (100%) rename src/{ => official}/ui/images/bootstrap/css/bootstrap.min.css.map (100%) rename src/{ => official}/ui/images/bootstrap/fonts/glyphicons-halflings-regular.eot (100%) rename src/{ => official}/ui/images/bootstrap/fonts/glyphicons-halflings-regular.svg (100%) rename src/{ => official}/ui/images/bootstrap/fonts/glyphicons-halflings-regular.ttf (100%) rename src/{ => official}/ui/images/bootstrap/fonts/glyphicons-halflings-regular.woff (100%) rename src/{ => official}/ui/images/bootstrap/fonts/glyphicons-halflings-regular.woff2 (100%) rename src/{ => official}/ui/images/bootstrap/js/bootstrap.min.js (100%) rename src/{ => official}/ui/images/chosen-sprite.png (100%) rename src/{ => official}/ui/images/chosen-sprite@2x.png (100%) rename src/{ => official}/ui/images/chosen.min.css (100%) rename src/{ => official}/ui/images/chosen.min.js (100%) rename src/{ => official}/ui/images/configserver.css (100%) rename src/{ => official}/ui/images/csf-loader.gif (100%) rename src/{ => official}/ui/images/csf.svg (100%) rename src/{ => official}/ui/images/csf_small.png (100%) rename src/{ => official}/ui/images/jquery.min.js (100%) rename src/{ => official}/ui/images/loader.gif (100%) rename src/{ => official}/ui/images/reseller_icon.svg (100%) rename src/{ => official}/ui/server.crt (100%) rename src/{ => official}/ui/server.key (100%) rename src/{ => official}/ui/ui.allow (100%) rename src/{ => official}/ui/ui.ban (100%) rename src/{ => official}/uialert.txt (100%) rename src/{ => official}/uidscan.txt (100%) rename src/{ => official}/uninstall.cwp.sh (100%) rename src/{ => official}/uninstall.cyberpanel.sh (100%) rename src/{ => official}/uninstall.directadmin.sh (100%) rename src/{ => official}/uninstall.generic.sh (100%) rename src/{ => official}/uninstall.interworx.sh (100%) rename src/{ => official}/uninstall.sh (100%) rename src/{ => official}/uninstall.vesta.sh (100%) rename src/{ => official}/upgrade.txt (100%) rename src/{ => official}/usertracking.txt (100%) rename src/{ => official}/version.txt (100%) rename src/{ => official}/version/version.pm (100%) rename src/{ => official}/version/version/regex.pm (100%) rename src/{ => official}/version/version/vpp.pm (100%) rename src/{ => official}/vestacp/csf.pl (100%) rename src/{ => official}/vestacp/frame.php (100%) rename src/{ => official}/vestacp/index.php (100%) rename src/{ => official}/watchalert.txt (100%) rename src/{ => official}/webmin/csf/images/LICENSE.txt (100%) rename src/{ => official}/webmin/csf/images/admin_icon.svg (100%) rename src/{ => official}/webmin/csf/images/bootstrap-chosen.css (100%) rename src/{ => official}/webmin/csf/images/bootstrap/css/bootstrap.min.css (100%) rename src/{ => official}/webmin/csf/images/bootstrap/css/bootstrap.min.css.map (100%) rename src/{ => official}/webmin/csf/images/bootstrap/fonts/glyphicons-halflings-regular.eot (100%) rename src/{ => official}/webmin/csf/images/bootstrap/fonts/glyphicons-halflings-regular.svg (100%) rename src/{ => official}/webmin/csf/images/bootstrap/fonts/glyphicons-halflings-regular.ttf (100%) rename src/{ => official}/webmin/csf/images/bootstrap/fonts/glyphicons-halflings-regular.woff (100%) rename src/{ => official}/webmin/csf/images/bootstrap/fonts/glyphicons-halflings-regular.woff2 (100%) rename src/{ => official}/webmin/csf/images/bootstrap/js/bootstrap.min.js (100%) rename src/{ => official}/webmin/csf/images/chosen-sprite.png (100%) rename src/{ => official}/webmin/csf/images/chosen-sprite@2x.png (100%) rename src/{ => official}/webmin/csf/images/chosen.min.css (100%) rename src/{ => official}/webmin/csf/images/chosen.min.js (100%) rename src/{ => official}/webmin/csf/images/configserver.css (100%) rename src/{ => official}/webmin/csf/images/csf-loader.gif (100%) rename src/{ => official}/webmin/csf/images/csf.svg (100%) rename src/{ => official}/webmin/csf/images/csf_small.png (100%) rename src/{ => official}/webmin/csf/images/jquery.min.js (100%) rename src/{ => official}/webmin/csf/images/loader.gif (100%) rename src/{ => official}/webmin/csf/images/reseller_icon.svg (100%) rename src/{ => official}/webmin/csf/index.cgi (100%) rename src/{ => official}/webmin/csf/module.info (100%) rename src/{ => official}/webminalert.txt (100%) rename src/{ => official}/x-arf.txt (100%) create mode 100644 src/redux/.gitattributes create mode 100644 src/redux/ConfigServer/AbuseIP.pm create mode 100644 src/redux/ConfigServer/CheckIP.pm create mode 100644 src/redux/ConfigServer/CloudFlare.pm create mode 100644 src/redux/ConfigServer/Config.pm create mode 100644 src/redux/ConfigServer/DisplayResellerUI.pm create mode 100644 src/redux/ConfigServer/DisplayUI.pm create mode 100644 src/redux/ConfigServer/GetEthDev.pm create mode 100644 src/redux/ConfigServer/GetIPs.pm create mode 100644 src/redux/ConfigServer/KillSSH.pm create mode 100644 src/redux/ConfigServer/Logger.pm create mode 100644 src/redux/ConfigServer/LookUpIP.pm create mode 100644 src/redux/ConfigServer/Messenger.pm create mode 100644 src/redux/ConfigServer/Ports.pm create mode 100644 src/redux/ConfigServer/RBLCheck.pm create mode 100644 src/redux/ConfigServer/RBLLookup.pm create mode 100644 src/redux/ConfigServer/RegexMain.pm create mode 100644 src/redux/ConfigServer/Sanity.pm create mode 100644 src/redux/ConfigServer/Sendmail.pm create mode 100644 src/redux/ConfigServer/ServerCheck.pm create mode 100644 src/redux/ConfigServer/ServerStats.pm create mode 100644 src/redux/ConfigServer/Service.pm create mode 100644 src/redux/ConfigServer/Slurp.pm create mode 100644 src/redux/ConfigServer/URLGet.pm create mode 100644 src/redux/ConfigServer/cseUI.pm create mode 100644 src/redux/Crypt/Blowfish_PP.pm create mode 100644 src/redux/Crypt/CBC.pm create mode 100644 src/redux/HTTP/Tiny.pm create mode 100644 src/redux/JSON/Tiny.pm create mode 100644 src/redux/Module/Installed/Tiny.pm create mode 100644 src/redux/Net/CIDR/Lite.pm create mode 100644 src/redux/Net/IP.pm create mode 100644 src/redux/accounttracking.txt create mode 100644 src/redux/alert.txt create mode 100644 src/redux/apache.http.txt create mode 100644 src/redux/apache.https.txt create mode 100644 src/redux/apache.main.txt create mode 100644 src/redux/apf_stub.pl create mode 100644 src/redux/auto.cwp.pl create mode 100644 src/redux/auto.cyberpanel.pl create mode 100644 src/redux/auto.directadmin.pl create mode 100644 src/redux/auto.generic.pl create mode 100644 src/redux/auto.interworx.pl create mode 100644 src/redux/auto.pl create mode 100644 src/redux/auto.vesta.pl create mode 100644 src/redux/changelog.txt create mode 100644 src/redux/connectiontracking.txt create mode 100644 src/redux/consolealert.txt create mode 100644 src/redux/cpanel.allow create mode 100644 src/redux/cpanel.comodo.allow create mode 100644 src/redux/cpanel.comodo.ignore create mode 100644 src/redux/cpanel.ignore create mode 100644 src/redux/cpanel/Driver/ConfigServercsf.pm create mode 100644 src/redux/cpanel/Driver/ConfigServercsf/META.pm create mode 100644 src/redux/cpanel/csf.cgi create mode 100644 src/redux/cpanel/csf.conf create mode 100644 src/redux/cpanel/csf.tmpl create mode 100644 src/redux/cpanel/upgrade.sh create mode 100644 src/redux/cpanelalert.txt create mode 100644 src/redux/csf.1.txt create mode 100644 src/redux/csf.allow create mode 100644 src/redux/csf.blocklists create mode 100644 src/redux/csf.c create mode 100644 src/redux/csf.cloudflare create mode 100644 src/redux/csf.conf create mode 100644 src/redux/csf.cwp.allow create mode 100644 src/redux/csf.cwp.conf create mode 100644 src/redux/csf.cwp.ignore create mode 100644 src/redux/csf.cwp.pignore create mode 100644 src/redux/csf.cyberpanel.allow create mode 100644 src/redux/csf.cyberpanel.conf create mode 100644 src/redux/csf.cyberpanel.ignore create mode 100644 src/redux/csf.cyberpanel.pignore create mode 100644 src/redux/csf.deny create mode 100644 src/redux/csf.directadmin.allow create mode 100644 src/redux/csf.directadmin.conf create mode 100644 src/redux/csf.directadmin.ignore create mode 100644 src/redux/csf.directadmin.pignore create mode 100644 src/redux/csf.dirwatch create mode 100644 src/redux/csf.div create mode 100644 src/redux/csf.dyndns create mode 100644 src/redux/csf.fignore create mode 100644 src/redux/csf.generic.allow create mode 100644 src/redux/csf.generic.conf create mode 100644 src/redux/csf.generic.ignore create mode 100644 src/redux/csf.generic.pignore create mode 100644 src/redux/csf.help create mode 100644 src/redux/csf.ignore create mode 100644 src/redux/csf.interworx.allow create mode 100644 src/redux/csf.interworx.conf create mode 100644 src/redux/csf.interworx.ignore create mode 100644 src/redux/csf.interworx.pignore create mode 100644 src/redux/csf.logfiles create mode 100644 src/redux/csf.logignore create mode 100644 src/redux/csf.mignore create mode 100644 src/redux/csf.pignore create mode 100644 src/redux/csf.pl create mode 100644 src/redux/csf.rblconf create mode 100644 src/redux/csf.rbls create mode 100644 src/redux/csf.redirect create mode 100644 src/redux/csf.resellers create mode 100644 src/redux/csf.rignore create mode 100644 src/redux/csf.service create mode 100644 src/redux/csf.sh create mode 100644 src/redux/csf.signore create mode 100644 src/redux/csf.sips create mode 100644 src/redux/csf.smtpauth create mode 100644 src/redux/csf.suignore create mode 100644 src/redux/csf.syslogs create mode 100644 src/redux/csf.syslogusers create mode 100644 src/redux/csf.uidignore create mode 100644 src/redux/csf.vesta.allow create mode 100644 src/redux/csf.vesta.conf create mode 100644 src/redux/csf.vesta.ignore create mode 100644 src/redux/csf.vesta.pignore create mode 100644 src/redux/csf/LICENSE.txt create mode 100644 src/redux/csf/admin_icon.svg create mode 100644 src/redux/csf/bootstrap-chosen.css create mode 100644 src/redux/csf/bootstrap/css/bootstrap.min.css create mode 100644 src/redux/csf/bootstrap/css/bootstrap.min.css.map create mode 100644 src/redux/csf/bootstrap/fonts/glyphicons-halflings-regular.eot create mode 100644 src/redux/csf/bootstrap/fonts/glyphicons-halflings-regular.svg create mode 100644 src/redux/csf/bootstrap/fonts/glyphicons-halflings-regular.ttf create mode 100644 src/redux/csf/bootstrap/fonts/glyphicons-halflings-regular.woff create mode 100644 src/redux/csf/bootstrap/fonts/glyphicons-halflings-regular.woff2 create mode 100644 src/redux/csf/bootstrap/js/bootstrap.min.js create mode 100644 src/redux/csf/chosen-sprite.png create mode 100644 src/redux/csf/chosen-sprite@2x.png create mode 100644 src/redux/csf/chosen.min.css create mode 100644 src/redux/csf/chosen.min.js create mode 100644 src/redux/csf/configserver.css create mode 100644 src/redux/csf/csf-loader.gif create mode 100644 src/redux/csf/csf.svg create mode 100644 src/redux/csf/csf_small.png create mode 100644 src/redux/csf/jquery.min.js create mode 100644 src/redux/csf/loader.gif create mode 100644 src/redux/csf/reseller_icon.svg create mode 100644 src/redux/csfajaxtail.js create mode 100644 src/redux/csfcron.sh create mode 100644 src/redux/csftest.pl create mode 100644 src/redux/csget.pl create mode 100644 src/redux/cwp/ajax_csfframe.php create mode 100644 src/redux/cwp/configserver.php create mode 100644 src/redux/cwp/csf.pl create mode 100644 src/redux/cwp/csfofficial.php create mode 100644 src/redux/cyberpanel/configservercsf/__init__.py create mode 100644 src/redux/cyberpanel/configservercsf/admin.py create mode 100644 src/redux/cyberpanel/configservercsf/apps.py create mode 100644 src/redux/cyberpanel/configservercsf/config create mode 100644 src/redux/cyberpanel/configservercsf/meta.xml create mode 100644 src/redux/cyberpanel/configservercsf/migrations/__init__.py create mode 100644 src/redux/cyberpanel/configservercsf/models.py create mode 100644 src/redux/cyberpanel/configservercsf/signals.py create mode 100644 src/redux/cyberpanel/configservercsf/templates/configservercsf/index.html create mode 100644 src/redux/cyberpanel/configservercsf/templates/configservercsf/menu.html create mode 100644 src/redux/cyberpanel/configservercsf/tests.py create mode 100644 src/redux/cyberpanel/configservercsf/urls.py create mode 100644 src/redux/cyberpanel/configservercsf/views.py create mode 100644 src/redux/cyberpanel/cyberpanel.pl create mode 100644 src/redux/da/admin/index.html create mode 100644 src/redux/da/admin/index.raw create mode 100644 src/redux/da/exec/da_csf.cgi create mode 100644 src/redux/da/exec/da_csf_reseller.cgi create mode 100644 src/redux/da/hooks/admin_img.html create mode 100644 src/redux/da/hooks/admin_txt.html create mode 100644 src/redux/da/hooks/reseller_img.html create mode 100644 src/redux/da/hooks/reseller_txt.html create mode 100644 src/redux/da/images/LICENSE.txt create mode 100644 src/redux/da/images/admin_icon.svg create mode 100644 src/redux/da/images/bootstrap-chosen.css create mode 100644 src/redux/da/images/bootstrap/css/bootstrap.min.css create mode 100644 src/redux/da/images/bootstrap/css/bootstrap.min.css.map create mode 100644 src/redux/da/images/bootstrap/fonts/glyphicons-halflings-regular.eot create mode 100644 src/redux/da/images/bootstrap/fonts/glyphicons-halflings-regular.svg create mode 100644 src/redux/da/images/bootstrap/fonts/glyphicons-halflings-regular.ttf create mode 100644 src/redux/da/images/bootstrap/fonts/glyphicons-halflings-regular.woff create mode 100644 src/redux/da/images/bootstrap/fonts/glyphicons-halflings-regular.woff2 create mode 100644 src/redux/da/images/bootstrap/js/bootstrap.min.js create mode 100644 src/redux/da/images/chosen-sprite.png create mode 100644 src/redux/da/images/chosen-sprite@2x.png create mode 100644 src/redux/da/images/chosen.min.css create mode 100644 src/redux/da/images/chosen.min.js create mode 100644 src/redux/da/images/configserver.css create mode 100644 src/redux/da/images/csf-loader.gif create mode 100644 src/redux/da/images/csf.svg create mode 100644 src/redux/da/images/csf_small.png create mode 100644 src/redux/da/images/jquery.min.js create mode 100644 src/redux/da/images/loader.gif create mode 100644 src/redux/da/images/reseller_icon.svg create mode 100644 src/redux/da/plugin.conf create mode 100644 src/redux/da/reseller/index.html create mode 100644 src/redux/da/reseller/index.raw create mode 100644 src/redux/da/scripts/install.sh create mode 100644 src/redux/da/scripts/uninstall.sh create mode 100644 src/redux/da/scripts/update.sh create mode 100644 src/redux/downloadservers create mode 100644 src/redux/exploitalert.txt create mode 100644 src/redux/filealert.txt create mode 100644 src/redux/forkbombalert.txt create mode 100644 src/redux/install.cpanel.sh create mode 100644 src/redux/install.cwp.sh create mode 100644 src/redux/install.cyberpanel.sh create mode 100644 src/redux/install.directadmin.sh create mode 100644 src/redux/install.generic.sh create mode 100644 src/redux/install.interworx.sh create mode 100644 src/redux/install.sh create mode 100644 src/redux/install.txt create mode 100644 src/redux/install.vesta.sh create mode 100644 src/redux/integrityalert.txt create mode 100644 src/redux/interworx/Ctrl/Nodeworx/Configservercsf.php create mode 100644 src/redux/interworx/Plugin/Configservercsf.php create mode 100644 src/redux/interworx/images/LICENSE.txt create mode 100644 src/redux/interworx/images/admin_icon.svg create mode 100644 src/redux/interworx/images/bootstrap-chosen.css create mode 100644 src/redux/interworx/images/bootstrap/css/bootstrap.min.css create mode 100644 src/redux/interworx/images/bootstrap/css/bootstrap.min.css.map create mode 100644 src/redux/interworx/images/bootstrap/fonts/glyphicons-halflings-regular.eot create mode 100644 src/redux/interworx/images/bootstrap/fonts/glyphicons-halflings-regular.svg create mode 100644 src/redux/interworx/images/bootstrap/fonts/glyphicons-halflings-regular.ttf create mode 100644 src/redux/interworx/images/bootstrap/fonts/glyphicons-halflings-regular.woff create mode 100644 src/redux/interworx/images/bootstrap/fonts/glyphicons-halflings-regular.woff2 create mode 100644 src/redux/interworx/images/bootstrap/js/bootstrap.min.js create mode 100644 src/redux/interworx/images/chosen-sprite.png create mode 100644 src/redux/interworx/images/chosen-sprite@2x.png create mode 100644 src/redux/interworx/images/chosen.min.css create mode 100644 src/redux/interworx/images/chosen.min.js create mode 100644 src/redux/interworx/images/configserver.css create mode 100644 src/redux/interworx/images/csf-loader.gif create mode 100644 src/redux/interworx/images/csf.svg create mode 100644 src/redux/interworx/images/csf_small.png create mode 100644 src/redux/interworx/images/jquery.min.js create mode 100644 src/redux/interworx/images/loader.gif create mode 100644 src/redux/interworx/images/reseller_icon.svg create mode 100644 src/redux/interworx/lib/index.pl create mode 100644 src/redux/interworx/lib/reseller.pl create mode 100644 src/redux/interworx/plugin.ini create mode 100644 src/redux/interworx/templates/admin.tpl create mode 100644 src/redux/interworx/templates/reseller.tpl create mode 100644 src/redux/lfd.logrotate create mode 100644 src/redux/lfd.pl create mode 100644 src/redux/lfd.service create mode 100644 src/redux/lfd.sh create mode 100644 src/redux/lfdcron.directadmin.sh create mode 100644 src/redux/lfdcron.sh create mode 100644 src/redux/license.txt create mode 100644 src/redux/litespeed.http.txt create mode 100644 src/redux/litespeed.https.txt create mode 100644 src/redux/litespeed.main.txt create mode 100644 src/redux/loadalert.txt create mode 100644 src/redux/logalert.txt create mode 100644 src/redux/logfloodalert.txt create mode 100644 src/redux/messenger/en.php create mode 100644 src/redux/messenger/index.html create mode 100644 src/redux/messenger/index.php create mode 100644 src/redux/messenger/index.recaptcha.html create mode 100644 src/redux/messenger/index.recaptcha.php create mode 100644 src/redux/messenger/index.text create mode 100644 src/redux/migratedata.sh create mode 100644 src/redux/modsecipdbalert.txt create mode 100644 src/redux/netblock.txt create mode 100644 src/redux/os.pl create mode 100644 src/redux/perf.sh create mode 100644 src/redux/permblock.txt create mode 100644 src/redux/portknocking.txt create mode 100644 src/redux/portscan.txt create mode 100644 src/redux/processtracking.txt create mode 100644 src/redux/profiles/block_all_perm.conf create mode 100644 src/redux/profiles/block_all_temp.conf create mode 100644 src/redux/profiles/disable_alerts.conf create mode 100644 src/redux/profiles/protection_high.conf create mode 100644 src/redux/profiles/protection_low.conf create mode 100644 src/redux/profiles/protection_medium.conf create mode 100644 src/redux/pt_deleted_action.pl create mode 100644 src/redux/queuealert.txt create mode 100644 src/redux/readme.txt create mode 100644 src/redux/recaptcha.txt create mode 100644 src/redux/regex.custom.pm create mode 100644 src/redux/regex.txt create mode 100644 src/redux/relayalert.txt create mode 100644 src/redux/remove_apf_bfd.sh create mode 100644 src/redux/resalert.txt create mode 100644 src/redux/reselleralert.txt create mode 100644 src/redux/restricted.txt create mode 100644 src/redux/sanity.txt create mode 100644 src/redux/scriptalert.txt create mode 100644 src/redux/sshalert.txt create mode 100644 src/redux/sualert.txt create mode 100644 src/redux/sudoalert.txt create mode 100644 src/redux/syslogalert.txt create mode 100644 src/redux/tracking.txt create mode 100644 src/redux/ui/images/LICENSE.txt create mode 100644 src/redux/ui/images/admin_icon.svg create mode 100644 src/redux/ui/images/bootstrap-chosen.css create mode 100644 src/redux/ui/images/bootstrap/css/bootstrap.min.css create mode 100644 src/redux/ui/images/bootstrap/css/bootstrap.min.css.map create mode 100644 src/redux/ui/images/bootstrap/fonts/glyphicons-halflings-regular.eot create mode 100644 src/redux/ui/images/bootstrap/fonts/glyphicons-halflings-regular.svg create mode 100644 src/redux/ui/images/bootstrap/fonts/glyphicons-halflings-regular.ttf create mode 100644 src/redux/ui/images/bootstrap/fonts/glyphicons-halflings-regular.woff create mode 100644 src/redux/ui/images/bootstrap/fonts/glyphicons-halflings-regular.woff2 create mode 100644 src/redux/ui/images/bootstrap/js/bootstrap.min.js create mode 100644 src/redux/ui/images/chosen-sprite.png create mode 100644 src/redux/ui/images/chosen-sprite@2x.png create mode 100644 src/redux/ui/images/chosen.min.css create mode 100644 src/redux/ui/images/chosen.min.js create mode 100644 src/redux/ui/images/configserver.css create mode 100644 src/redux/ui/images/csf-loader.gif create mode 100644 src/redux/ui/images/csf.svg create mode 100644 src/redux/ui/images/csf_small.png create mode 100644 src/redux/ui/images/jquery.min.js create mode 100644 src/redux/ui/images/loader.gif create mode 100644 src/redux/ui/images/reseller_icon.svg create mode 100644 src/redux/ui/server.crt create mode 100644 src/redux/ui/server.key create mode 100644 src/redux/ui/ui.allow create mode 100644 src/redux/ui/ui.ban create mode 100644 src/redux/uialert.txt create mode 100644 src/redux/uidscan.txt create mode 100644 src/redux/uninstall.cwp.sh create mode 100644 src/redux/uninstall.cyberpanel.sh create mode 100644 src/redux/uninstall.directadmin.sh create mode 100644 src/redux/uninstall.generic.sh create mode 100644 src/redux/uninstall.interworx.sh create mode 100644 src/redux/uninstall.sh create mode 100644 src/redux/uninstall.vesta.sh create mode 100644 src/redux/upgrade.txt create mode 100644 src/redux/usertracking.txt create mode 100644 src/redux/version.txt create mode 100644 src/redux/version/version.pm create mode 100644 src/redux/version/version/regex.pm create mode 100644 src/redux/version/version/vpp.pm create mode 100644 src/redux/vestacp/csf.pl create mode 100644 src/redux/vestacp/frame.php create mode 100644 src/redux/vestacp/index.php create mode 100644 src/redux/watchalert.txt create mode 100644 src/redux/webmin/csf/images/LICENSE.txt create mode 100644 src/redux/webmin/csf/images/admin_icon.svg create mode 100644 src/redux/webmin/csf/images/bootstrap-chosen.css create mode 100644 src/redux/webmin/csf/images/bootstrap/css/bootstrap.min.css create mode 100644 src/redux/webmin/csf/images/bootstrap/css/bootstrap.min.css.map create mode 100644 src/redux/webmin/csf/images/bootstrap/fonts/glyphicons-halflings-regular.eot create mode 100644 src/redux/webmin/csf/images/bootstrap/fonts/glyphicons-halflings-regular.svg create mode 100644 src/redux/webmin/csf/images/bootstrap/fonts/glyphicons-halflings-regular.ttf create mode 100644 src/redux/webmin/csf/images/bootstrap/fonts/glyphicons-halflings-regular.woff create mode 100644 src/redux/webmin/csf/images/bootstrap/fonts/glyphicons-halflings-regular.woff2 create mode 100644 src/redux/webmin/csf/images/bootstrap/js/bootstrap.min.js create mode 100644 src/redux/webmin/csf/images/chosen-sprite.png create mode 100644 src/redux/webmin/csf/images/chosen-sprite@2x.png create mode 100644 src/redux/webmin/csf/images/chosen.min.css create mode 100644 src/redux/webmin/csf/images/chosen.min.js create mode 100644 src/redux/webmin/csf/images/configserver.css create mode 100644 src/redux/webmin/csf/images/csf-loader.gif create mode 100644 src/redux/webmin/csf/images/csf.svg create mode 100644 src/redux/webmin/csf/images/csf_small.png create mode 100644 src/redux/webmin/csf/images/jquery.min.js create mode 100644 src/redux/webmin/csf/images/loader.gif create mode 100644 src/redux/webmin/csf/images/reseller_icon.svg create mode 100644 src/redux/webmin/csf/index.cgi create mode 100644 src/redux/webmin/csf/module.info create mode 100644 src/redux/webminalert.txt create mode 100644 src/redux/x-arf.txt create mode 100644 src/web/downloads/CHANGELOG.msfe.txt create mode 100644 src/web/downloads/LICENSE.msfe.txt create mode 100644 src/web/downloads/cmc.gz create mode 100644 src/web/downloads/cmc/INSTALL.txt create mode 100644 src/web/downloads/cmc/changelog.txt create mode 100644 src/web/downloads/cmc/license.txt create mode 100644 src/web/downloads/cmm.gz create mode 100644 src/web/downloads/cmm/CHANGELOG.txt create mode 100644 src/web/downloads/cmm/INSTALL.txt create mode 100644 src/web/downloads/cmm/license.txt create mode 100644 src/web/downloads/cmq.gz create mode 100644 src/web/downloads/cmq/CHANGELOG.txt create mode 100644 src/web/downloads/cmq/INSTALL.txt create mode 100644 src/web/downloads/cmq/license.txt create mode 100644 src/web/downloads/cse.gz create mode 100644 src/web/downloads/cse/CHANGELOG.txt create mode 100644 src/web/downloads/cse/INSTALL.txt create mode 100644 src/web/downloads/cse/license.txt create mode 100644 src/web/downloads/csf.gz create mode 100644 src/web/downloads/csf/changelog.txt create mode 100644 src/web/downloads/csf/install.txt create mode 100644 src/web/downloads/csf/license.txt create mode 100644 src/web/downloads/csf/readme.txt create mode 100644 src/web/downloads/cxs/changelog.txt create mode 100644 src/web/downloads/cxs/license.txt create mode 100644 src/web/downloads/cxs/version.txt create mode 100644 src/web/downloads/msfeversion.txt create mode 100644 src/web/downloads/osm/changelog.txt create mode 100644 src/web/downloads/osm/license.txt create mode 100644 src/web/downloads/osm/osmversion.txt create mode 100644 src/web/templates/schema/abuse_login-attack_0.2.json create mode 100644 src/web/templates/versions/ccm/cmmversion.txt create mode 100644 src/web/templates/versions/cmc/cmcversion.txt create mode 100644 src/web/templates/versions/cmq/cmqversion.txt create mode 100644 src/web/templates/versions/cse/cseversion.txt create mode 100644 src/web/templates/versions/csf/version.txt create mode 100644 src/web/templates/versions/cxs/version.txt create mode 100644 src/web/templates/versions/msfeversion create mode 100644 src/web/templates/versions/osm/osmversion.txt create mode 100644 src/web/templates/versions/version.txt diff --git a/src/.gitattributes b/src/official/.gitattributes similarity index 100% rename from src/.gitattributes rename to src/official/.gitattributes diff --git a/src/ConfigServer/AbuseIP.pm b/src/official/ConfigServer/AbuseIP.pm similarity index 100% rename from src/ConfigServer/AbuseIP.pm rename to src/official/ConfigServer/AbuseIP.pm diff --git a/src/ConfigServer/CheckIP.pm b/src/official/ConfigServer/CheckIP.pm similarity index 100% rename from src/ConfigServer/CheckIP.pm rename to src/official/ConfigServer/CheckIP.pm diff --git a/src/ConfigServer/CloudFlare.pm b/src/official/ConfigServer/CloudFlare.pm similarity index 100% rename from src/ConfigServer/CloudFlare.pm rename to src/official/ConfigServer/CloudFlare.pm diff --git a/src/ConfigServer/Config.pm b/src/official/ConfigServer/Config.pm similarity index 100% rename from src/ConfigServer/Config.pm rename to src/official/ConfigServer/Config.pm diff --git a/src/ConfigServer/DisplayResellerUI.pm b/src/official/ConfigServer/DisplayResellerUI.pm similarity index 100% rename from src/ConfigServer/DisplayResellerUI.pm rename to src/official/ConfigServer/DisplayResellerUI.pm diff --git a/src/ConfigServer/DisplayUI.pm b/src/official/ConfigServer/DisplayUI.pm similarity index 100% rename from src/ConfigServer/DisplayUI.pm rename to src/official/ConfigServer/DisplayUI.pm diff --git a/src/ConfigServer/GetEthDev.pm b/src/official/ConfigServer/GetEthDev.pm similarity index 100% rename from src/ConfigServer/GetEthDev.pm rename to src/official/ConfigServer/GetEthDev.pm diff --git a/src/ConfigServer/GetIPs.pm b/src/official/ConfigServer/GetIPs.pm similarity index 100% rename from src/ConfigServer/GetIPs.pm rename to src/official/ConfigServer/GetIPs.pm diff --git a/src/ConfigServer/KillSSH.pm b/src/official/ConfigServer/KillSSH.pm similarity index 100% rename from src/ConfigServer/KillSSH.pm rename to src/official/ConfigServer/KillSSH.pm diff --git a/src/ConfigServer/Logger.pm b/src/official/ConfigServer/Logger.pm similarity index 100% rename from src/ConfigServer/Logger.pm rename to src/official/ConfigServer/Logger.pm diff --git a/src/ConfigServer/LookUpIP.pm b/src/official/ConfigServer/LookUpIP.pm similarity index 100% rename from src/ConfigServer/LookUpIP.pm rename to src/official/ConfigServer/LookUpIP.pm diff --git a/src/ConfigServer/Messenger.pm b/src/official/ConfigServer/Messenger.pm similarity index 100% rename from src/ConfigServer/Messenger.pm rename to src/official/ConfigServer/Messenger.pm diff --git a/src/ConfigServer/Ports.pm b/src/official/ConfigServer/Ports.pm similarity index 100% rename from src/ConfigServer/Ports.pm rename to src/official/ConfigServer/Ports.pm diff --git a/src/ConfigServer/RBLCheck.pm b/src/official/ConfigServer/RBLCheck.pm similarity index 100% rename from src/ConfigServer/RBLCheck.pm rename to src/official/ConfigServer/RBLCheck.pm diff --git a/src/ConfigServer/RBLLookup.pm b/src/official/ConfigServer/RBLLookup.pm similarity index 100% rename from src/ConfigServer/RBLLookup.pm rename to src/official/ConfigServer/RBLLookup.pm diff --git a/src/ConfigServer/RegexMain.pm b/src/official/ConfigServer/RegexMain.pm similarity index 100% rename from src/ConfigServer/RegexMain.pm rename to src/official/ConfigServer/RegexMain.pm diff --git a/src/ConfigServer/Sanity.pm b/src/official/ConfigServer/Sanity.pm similarity index 100% rename from src/ConfigServer/Sanity.pm rename to src/official/ConfigServer/Sanity.pm diff --git a/src/ConfigServer/Sendmail.pm b/src/official/ConfigServer/Sendmail.pm similarity index 100% rename from src/ConfigServer/Sendmail.pm rename to src/official/ConfigServer/Sendmail.pm diff --git a/src/ConfigServer/ServerCheck.pm b/src/official/ConfigServer/ServerCheck.pm similarity index 100% rename from src/ConfigServer/ServerCheck.pm rename to src/official/ConfigServer/ServerCheck.pm diff --git a/src/ConfigServer/ServerStats.pm b/src/official/ConfigServer/ServerStats.pm similarity index 100% rename from src/ConfigServer/ServerStats.pm rename to src/official/ConfigServer/ServerStats.pm diff --git a/src/ConfigServer/Service.pm b/src/official/ConfigServer/Service.pm similarity index 100% rename from src/ConfigServer/Service.pm rename to src/official/ConfigServer/Service.pm diff --git a/src/ConfigServer/Slurp.pm b/src/official/ConfigServer/Slurp.pm similarity index 100% rename from src/ConfigServer/Slurp.pm rename to src/official/ConfigServer/Slurp.pm diff --git a/src/ConfigServer/URLGet.pm b/src/official/ConfigServer/URLGet.pm similarity index 100% rename from src/ConfigServer/URLGet.pm rename to src/official/ConfigServer/URLGet.pm diff --git a/src/ConfigServer/cseUI.pm b/src/official/ConfigServer/cseUI.pm similarity index 100% rename from src/ConfigServer/cseUI.pm rename to src/official/ConfigServer/cseUI.pm diff --git a/src/Crypt/Blowfish_PP.pm b/src/official/Crypt/Blowfish_PP.pm similarity index 100% rename from src/Crypt/Blowfish_PP.pm rename to src/official/Crypt/Blowfish_PP.pm diff --git a/src/Crypt/CBC.pm b/src/official/Crypt/CBC.pm similarity index 100% rename from src/Crypt/CBC.pm rename to src/official/Crypt/CBC.pm diff --git a/src/HTTP/Tiny.pm b/src/official/HTTP/Tiny.pm similarity index 100% rename from src/HTTP/Tiny.pm rename to src/official/HTTP/Tiny.pm diff --git a/src/JSON/Tiny.pm b/src/official/JSON/Tiny.pm similarity index 100% rename from src/JSON/Tiny.pm rename to src/official/JSON/Tiny.pm diff --git a/src/Module/Installed/Tiny.pm b/src/official/Module/Installed/Tiny.pm similarity index 100% rename from src/Module/Installed/Tiny.pm rename to src/official/Module/Installed/Tiny.pm diff --git a/src/Net/CIDR/Lite.pm b/src/official/Net/CIDR/Lite.pm similarity index 100% rename from src/Net/CIDR/Lite.pm rename to src/official/Net/CIDR/Lite.pm diff --git a/src/Net/IP.pm b/src/official/Net/IP.pm similarity index 100% rename from src/Net/IP.pm rename to src/official/Net/IP.pm diff --git a/src/accounttracking.txt b/src/official/accounttracking.txt similarity index 100% rename from src/accounttracking.txt rename to src/official/accounttracking.txt diff --git a/src/alert.txt b/src/official/alert.txt similarity index 100% rename from src/alert.txt rename to src/official/alert.txt diff --git a/src/apache.http.txt b/src/official/apache.http.txt similarity index 100% rename from src/apache.http.txt rename to src/official/apache.http.txt diff --git a/src/apache.https.txt b/src/official/apache.https.txt similarity index 100% rename from src/apache.https.txt rename to src/official/apache.https.txt diff --git a/src/apache.main.txt b/src/official/apache.main.txt similarity index 100% rename from src/apache.main.txt rename to src/official/apache.main.txt diff --git a/src/apf_stub.pl b/src/official/apf_stub.pl similarity index 100% rename from src/apf_stub.pl rename to src/official/apf_stub.pl diff --git a/src/auto.cwp.pl b/src/official/auto.cwp.pl similarity index 100% rename from src/auto.cwp.pl rename to src/official/auto.cwp.pl diff --git a/src/auto.cyberpanel.pl b/src/official/auto.cyberpanel.pl similarity index 100% rename from src/auto.cyberpanel.pl rename to src/official/auto.cyberpanel.pl diff --git a/src/auto.directadmin.pl b/src/official/auto.directadmin.pl similarity index 100% rename from src/auto.directadmin.pl rename to src/official/auto.directadmin.pl diff --git a/src/auto.generic.pl b/src/official/auto.generic.pl similarity index 100% rename from src/auto.generic.pl rename to src/official/auto.generic.pl diff --git a/src/auto.interworx.pl b/src/official/auto.interworx.pl similarity index 100% rename from src/auto.interworx.pl rename to src/official/auto.interworx.pl diff --git a/src/auto.pl b/src/official/auto.pl similarity index 100% rename from src/auto.pl rename to src/official/auto.pl diff --git a/src/auto.vesta.pl b/src/official/auto.vesta.pl similarity index 100% rename from src/auto.vesta.pl rename to src/official/auto.vesta.pl diff --git a/src/changelog.txt b/src/official/changelog.txt similarity index 100% rename from src/changelog.txt rename to src/official/changelog.txt diff --git a/src/connectiontracking.txt b/src/official/connectiontracking.txt similarity index 100% rename from src/connectiontracking.txt rename to src/official/connectiontracking.txt diff --git a/src/consolealert.txt b/src/official/consolealert.txt similarity index 100% rename from src/consolealert.txt rename to src/official/consolealert.txt diff --git a/src/cpanel.allow b/src/official/cpanel.allow similarity index 100% rename from src/cpanel.allow rename to src/official/cpanel.allow diff --git a/src/cpanel.comodo.allow b/src/official/cpanel.comodo.allow similarity index 100% rename from src/cpanel.comodo.allow rename to src/official/cpanel.comodo.allow diff --git a/src/cpanel.comodo.ignore b/src/official/cpanel.comodo.ignore similarity index 100% rename from src/cpanel.comodo.ignore rename to src/official/cpanel.comodo.ignore diff --git a/src/cpanel.ignore b/src/official/cpanel.ignore similarity index 100% rename from src/cpanel.ignore rename to src/official/cpanel.ignore diff --git a/src/cpanel/Driver/ConfigServercsf.pm b/src/official/cpanel/Driver/ConfigServercsf.pm similarity index 100% rename from src/cpanel/Driver/ConfigServercsf.pm rename to src/official/cpanel/Driver/ConfigServercsf.pm diff --git a/src/cpanel/Driver/ConfigServercsf/META.pm b/src/official/cpanel/Driver/ConfigServercsf/META.pm similarity index 100% rename from src/cpanel/Driver/ConfigServercsf/META.pm rename to src/official/cpanel/Driver/ConfigServercsf/META.pm diff --git a/src/cpanel/csf.cgi b/src/official/cpanel/csf.cgi similarity index 100% rename from src/cpanel/csf.cgi rename to src/official/cpanel/csf.cgi diff --git a/src/cpanel/csf.conf b/src/official/cpanel/csf.conf similarity index 100% rename from src/cpanel/csf.conf rename to src/official/cpanel/csf.conf diff --git a/src/cpanel/csf.tmpl b/src/official/cpanel/csf.tmpl similarity index 100% rename from src/cpanel/csf.tmpl rename to src/official/cpanel/csf.tmpl diff --git a/src/cpanel/upgrade.sh b/src/official/cpanel/upgrade.sh similarity index 100% rename from src/cpanel/upgrade.sh rename to src/official/cpanel/upgrade.sh diff --git a/src/cpanelalert.txt b/src/official/cpanelalert.txt similarity index 100% rename from src/cpanelalert.txt rename to src/official/cpanelalert.txt diff --git a/src/csf.1.txt b/src/official/csf.1.txt similarity index 100% rename from src/csf.1.txt rename to src/official/csf.1.txt diff --git a/src/csf.allow b/src/official/csf.allow similarity index 100% rename from src/csf.allow rename to src/official/csf.allow diff --git a/src/csf.blocklists b/src/official/csf.blocklists similarity index 100% rename from src/csf.blocklists rename to src/official/csf.blocklists diff --git a/src/csf.c b/src/official/csf.c similarity index 100% rename from src/csf.c rename to src/official/csf.c diff --git a/src/csf.cloudflare b/src/official/csf.cloudflare similarity index 100% rename from src/csf.cloudflare rename to src/official/csf.cloudflare diff --git a/src/csf.conf b/src/official/csf.conf similarity index 100% rename from src/csf.conf rename to src/official/csf.conf diff --git a/src/csf.cwp.allow b/src/official/csf.cwp.allow similarity index 100% rename from src/csf.cwp.allow rename to src/official/csf.cwp.allow diff --git a/src/csf.cwp.conf b/src/official/csf.cwp.conf similarity index 100% rename from src/csf.cwp.conf rename to src/official/csf.cwp.conf diff --git a/src/csf.cwp.ignore b/src/official/csf.cwp.ignore similarity index 100% rename from src/csf.cwp.ignore rename to src/official/csf.cwp.ignore diff --git a/src/csf.cwp.pignore b/src/official/csf.cwp.pignore similarity index 100% rename from src/csf.cwp.pignore rename to src/official/csf.cwp.pignore diff --git a/src/csf.cyberpanel.allow b/src/official/csf.cyberpanel.allow similarity index 100% rename from src/csf.cyberpanel.allow rename to src/official/csf.cyberpanel.allow diff --git a/src/csf.cyberpanel.conf b/src/official/csf.cyberpanel.conf similarity index 100% rename from src/csf.cyberpanel.conf rename to src/official/csf.cyberpanel.conf diff --git a/src/csf.cyberpanel.ignore b/src/official/csf.cyberpanel.ignore similarity index 100% rename from src/csf.cyberpanel.ignore rename to src/official/csf.cyberpanel.ignore diff --git a/src/csf.cyberpanel.pignore b/src/official/csf.cyberpanel.pignore similarity index 100% rename from src/csf.cyberpanel.pignore rename to src/official/csf.cyberpanel.pignore diff --git a/src/csf.deny b/src/official/csf.deny similarity index 100% rename from src/csf.deny rename to src/official/csf.deny diff --git a/src/csf.directadmin.allow b/src/official/csf.directadmin.allow similarity index 100% rename from src/csf.directadmin.allow rename to src/official/csf.directadmin.allow diff --git a/src/csf.directadmin.conf b/src/official/csf.directadmin.conf similarity index 100% rename from src/csf.directadmin.conf rename to src/official/csf.directadmin.conf diff --git a/src/csf.directadmin.ignore b/src/official/csf.directadmin.ignore similarity index 100% rename from src/csf.directadmin.ignore rename to src/official/csf.directadmin.ignore diff --git a/src/csf.directadmin.pignore b/src/official/csf.directadmin.pignore similarity index 100% rename from src/csf.directadmin.pignore rename to src/official/csf.directadmin.pignore diff --git a/src/csf.dirwatch b/src/official/csf.dirwatch similarity index 100% rename from src/csf.dirwatch rename to src/official/csf.dirwatch diff --git a/src/csf.div b/src/official/csf.div similarity index 100% rename from src/csf.div rename to src/official/csf.div diff --git a/src/csf.dyndns b/src/official/csf.dyndns similarity index 100% rename from src/csf.dyndns rename to src/official/csf.dyndns diff --git a/src/csf.fignore b/src/official/csf.fignore similarity index 100% rename from src/csf.fignore rename to src/official/csf.fignore diff --git a/src/csf.generic.allow b/src/official/csf.generic.allow similarity index 100% rename from src/csf.generic.allow rename to src/official/csf.generic.allow diff --git a/src/csf.generic.conf b/src/official/csf.generic.conf similarity index 100% rename from src/csf.generic.conf rename to src/official/csf.generic.conf diff --git a/src/csf.generic.ignore b/src/official/csf.generic.ignore similarity index 100% rename from src/csf.generic.ignore rename to src/official/csf.generic.ignore diff --git a/src/csf.generic.pignore b/src/official/csf.generic.pignore similarity index 100% rename from src/csf.generic.pignore rename to src/official/csf.generic.pignore diff --git a/src/csf.help b/src/official/csf.help similarity index 100% rename from src/csf.help rename to src/official/csf.help diff --git a/src/csf.ignore b/src/official/csf.ignore similarity index 100% rename from src/csf.ignore rename to src/official/csf.ignore diff --git a/src/csf.interworx.allow b/src/official/csf.interworx.allow similarity index 100% rename from src/csf.interworx.allow rename to src/official/csf.interworx.allow diff --git a/src/csf.interworx.conf b/src/official/csf.interworx.conf similarity index 100% rename from src/csf.interworx.conf rename to src/official/csf.interworx.conf diff --git a/src/csf.interworx.ignore b/src/official/csf.interworx.ignore similarity index 100% rename from src/csf.interworx.ignore rename to src/official/csf.interworx.ignore diff --git a/src/csf.interworx.pignore b/src/official/csf.interworx.pignore similarity index 100% rename from src/csf.interworx.pignore rename to src/official/csf.interworx.pignore diff --git a/src/csf.logfiles b/src/official/csf.logfiles similarity index 100% rename from src/csf.logfiles rename to src/official/csf.logfiles diff --git a/src/csf.logignore b/src/official/csf.logignore similarity index 100% rename from src/csf.logignore rename to src/official/csf.logignore diff --git a/src/csf.mignore b/src/official/csf.mignore similarity index 100% rename from src/csf.mignore rename to src/official/csf.mignore diff --git a/src/csf.pignore b/src/official/csf.pignore similarity index 100% rename from src/csf.pignore rename to src/official/csf.pignore diff --git a/src/csf.pl b/src/official/csf.pl similarity index 100% rename from src/csf.pl rename to src/official/csf.pl diff --git a/src/csf.rblconf b/src/official/csf.rblconf similarity index 100% rename from src/csf.rblconf rename to src/official/csf.rblconf diff --git a/src/csf.rbls b/src/official/csf.rbls similarity index 100% rename from src/csf.rbls rename to src/official/csf.rbls diff --git a/src/csf.redirect b/src/official/csf.redirect similarity index 100% rename from src/csf.redirect rename to src/official/csf.redirect diff --git a/src/csf.resellers b/src/official/csf.resellers similarity index 100% rename from src/csf.resellers rename to src/official/csf.resellers diff --git a/src/csf.rignore b/src/official/csf.rignore similarity index 100% rename from src/csf.rignore rename to src/official/csf.rignore diff --git a/src/csf.service b/src/official/csf.service similarity index 100% rename from src/csf.service rename to src/official/csf.service diff --git a/src/csf.sh b/src/official/csf.sh similarity index 100% rename from src/csf.sh rename to src/official/csf.sh diff --git a/src/csf.signore b/src/official/csf.signore similarity index 100% rename from src/csf.signore rename to src/official/csf.signore diff --git a/src/csf.sips b/src/official/csf.sips similarity index 100% rename from src/csf.sips rename to src/official/csf.sips diff --git a/src/csf.smtpauth b/src/official/csf.smtpauth similarity index 100% rename from src/csf.smtpauth rename to src/official/csf.smtpauth diff --git a/src/csf.suignore b/src/official/csf.suignore similarity index 100% rename from src/csf.suignore rename to src/official/csf.suignore diff --git a/src/csf.syslogs b/src/official/csf.syslogs similarity index 100% rename from src/csf.syslogs rename to src/official/csf.syslogs diff --git a/src/csf.syslogusers b/src/official/csf.syslogusers similarity index 100% rename from src/csf.syslogusers rename to src/official/csf.syslogusers diff --git a/src/csf.uidignore b/src/official/csf.uidignore similarity index 100% rename from src/csf.uidignore rename to src/official/csf.uidignore diff --git a/src/csf.vesta.allow b/src/official/csf.vesta.allow similarity index 100% rename from src/csf.vesta.allow rename to src/official/csf.vesta.allow diff --git a/src/csf.vesta.conf b/src/official/csf.vesta.conf similarity index 100% rename from src/csf.vesta.conf rename to src/official/csf.vesta.conf diff --git a/src/csf.vesta.ignore b/src/official/csf.vesta.ignore similarity index 100% rename from src/csf.vesta.ignore rename to src/official/csf.vesta.ignore diff --git a/src/csf.vesta.pignore b/src/official/csf.vesta.pignore similarity index 100% rename from src/csf.vesta.pignore rename to src/official/csf.vesta.pignore diff --git a/src/csf/LICENSE.txt b/src/official/csf/LICENSE.txt similarity index 100% rename from src/csf/LICENSE.txt rename to src/official/csf/LICENSE.txt diff --git a/src/csf/admin_icon.svg b/src/official/csf/admin_icon.svg similarity index 100% rename from src/csf/admin_icon.svg rename to src/official/csf/admin_icon.svg diff --git a/src/csf/bootstrap-chosen.css b/src/official/csf/bootstrap-chosen.css similarity index 100% rename from src/csf/bootstrap-chosen.css rename to src/official/csf/bootstrap-chosen.css diff --git a/src/csf/bootstrap/css/bootstrap.min.css b/src/official/csf/bootstrap/css/bootstrap.min.css similarity index 100% rename from src/csf/bootstrap/css/bootstrap.min.css rename to src/official/csf/bootstrap/css/bootstrap.min.css diff --git a/src/csf/bootstrap/css/bootstrap.min.css.map b/src/official/csf/bootstrap/css/bootstrap.min.css.map similarity index 100% rename from src/csf/bootstrap/css/bootstrap.min.css.map rename to src/official/csf/bootstrap/css/bootstrap.min.css.map diff --git a/src/csf/bootstrap/fonts/glyphicons-halflings-regular.eot b/src/official/csf/bootstrap/fonts/glyphicons-halflings-regular.eot similarity index 100% rename from src/csf/bootstrap/fonts/glyphicons-halflings-regular.eot rename to src/official/csf/bootstrap/fonts/glyphicons-halflings-regular.eot diff --git a/src/csf/bootstrap/fonts/glyphicons-halflings-regular.svg b/src/official/csf/bootstrap/fonts/glyphicons-halflings-regular.svg similarity index 100% rename from src/csf/bootstrap/fonts/glyphicons-halflings-regular.svg rename to src/official/csf/bootstrap/fonts/glyphicons-halflings-regular.svg diff --git a/src/csf/bootstrap/fonts/glyphicons-halflings-regular.ttf b/src/official/csf/bootstrap/fonts/glyphicons-halflings-regular.ttf similarity index 100% rename from src/csf/bootstrap/fonts/glyphicons-halflings-regular.ttf rename to src/official/csf/bootstrap/fonts/glyphicons-halflings-regular.ttf diff --git a/src/csf/bootstrap/fonts/glyphicons-halflings-regular.woff b/src/official/csf/bootstrap/fonts/glyphicons-halflings-regular.woff similarity index 100% rename from src/csf/bootstrap/fonts/glyphicons-halflings-regular.woff rename to src/official/csf/bootstrap/fonts/glyphicons-halflings-regular.woff diff --git a/src/csf/bootstrap/fonts/glyphicons-halflings-regular.woff2 b/src/official/csf/bootstrap/fonts/glyphicons-halflings-regular.woff2 similarity index 100% rename from src/csf/bootstrap/fonts/glyphicons-halflings-regular.woff2 rename to src/official/csf/bootstrap/fonts/glyphicons-halflings-regular.woff2 diff --git a/src/csf/bootstrap/js/bootstrap.min.js b/src/official/csf/bootstrap/js/bootstrap.min.js similarity index 100% rename from src/csf/bootstrap/js/bootstrap.min.js rename to src/official/csf/bootstrap/js/bootstrap.min.js diff --git a/src/csf/chosen-sprite.png b/src/official/csf/chosen-sprite.png similarity index 100% rename from src/csf/chosen-sprite.png rename to src/official/csf/chosen-sprite.png diff --git a/src/csf/chosen-sprite@2x.png b/src/official/csf/chosen-sprite@2x.png similarity index 100% rename from src/csf/chosen-sprite@2x.png rename to src/official/csf/chosen-sprite@2x.png diff --git a/src/csf/chosen.min.css b/src/official/csf/chosen.min.css similarity index 100% rename from src/csf/chosen.min.css rename to src/official/csf/chosen.min.css diff --git a/src/csf/chosen.min.js b/src/official/csf/chosen.min.js similarity index 100% rename from src/csf/chosen.min.js rename to src/official/csf/chosen.min.js diff --git a/src/csf/configserver.css b/src/official/csf/configserver.css similarity index 100% rename from src/csf/configserver.css rename to src/official/csf/configserver.css diff --git a/src/csf/csf-loader.gif b/src/official/csf/csf-loader.gif similarity index 100% rename from src/csf/csf-loader.gif rename to src/official/csf/csf-loader.gif diff --git a/src/csf/csf.svg b/src/official/csf/csf.svg similarity index 100% rename from src/csf/csf.svg rename to src/official/csf/csf.svg diff --git a/src/csf/csf_small.png b/src/official/csf/csf_small.png similarity index 100% rename from src/csf/csf_small.png rename to src/official/csf/csf_small.png diff --git a/src/csf/jquery.min.js b/src/official/csf/jquery.min.js similarity index 100% rename from src/csf/jquery.min.js rename to src/official/csf/jquery.min.js diff --git a/src/csf/loader.gif b/src/official/csf/loader.gif similarity index 100% rename from src/csf/loader.gif rename to src/official/csf/loader.gif diff --git a/src/csf/reseller_icon.svg b/src/official/csf/reseller_icon.svg similarity index 100% rename from src/csf/reseller_icon.svg rename to src/official/csf/reseller_icon.svg diff --git a/src/csfajaxtail.js b/src/official/csfajaxtail.js similarity index 100% rename from src/csfajaxtail.js rename to src/official/csfajaxtail.js diff --git a/src/csfcron.sh b/src/official/csfcron.sh similarity index 100% rename from src/csfcron.sh rename to src/official/csfcron.sh diff --git a/src/csftest.pl b/src/official/csftest.pl similarity index 100% rename from src/csftest.pl rename to src/official/csftest.pl diff --git a/src/csget.pl b/src/official/csget.pl similarity index 100% rename from src/csget.pl rename to src/official/csget.pl diff --git a/src/cwp/ajax_csfframe.php b/src/official/cwp/ajax_csfframe.php similarity index 100% rename from src/cwp/ajax_csfframe.php rename to src/official/cwp/ajax_csfframe.php diff --git a/src/cwp/configserver.php b/src/official/cwp/configserver.php similarity index 100% rename from src/cwp/configserver.php rename to src/official/cwp/configserver.php diff --git a/src/cwp/csf.pl b/src/official/cwp/csf.pl similarity index 100% rename from src/cwp/csf.pl rename to src/official/cwp/csf.pl diff --git a/src/cwp/csfofficial.php b/src/official/cwp/csfofficial.php similarity index 100% rename from src/cwp/csfofficial.php rename to src/official/cwp/csfofficial.php diff --git a/src/cyberpanel/configservercsf/__init__.py b/src/official/cyberpanel/configservercsf/__init__.py similarity index 100% rename from src/cyberpanel/configservercsf/__init__.py rename to src/official/cyberpanel/configservercsf/__init__.py diff --git a/src/cyberpanel/configservercsf/admin.py b/src/official/cyberpanel/configservercsf/admin.py similarity index 100% rename from src/cyberpanel/configservercsf/admin.py rename to src/official/cyberpanel/configservercsf/admin.py diff --git a/src/cyberpanel/configservercsf/apps.py b/src/official/cyberpanel/configservercsf/apps.py similarity index 100% rename from src/cyberpanel/configservercsf/apps.py rename to src/official/cyberpanel/configservercsf/apps.py diff --git a/src/cyberpanel/configservercsf/config b/src/official/cyberpanel/configservercsf/config similarity index 100% rename from src/cyberpanel/configservercsf/config rename to src/official/cyberpanel/configservercsf/config diff --git a/src/cyberpanel/configservercsf/meta.xml b/src/official/cyberpanel/configservercsf/meta.xml similarity index 100% rename from src/cyberpanel/configservercsf/meta.xml rename to src/official/cyberpanel/configservercsf/meta.xml diff --git a/src/cyberpanel/configservercsf/migrations/__init__.py b/src/official/cyberpanel/configservercsf/migrations/__init__.py similarity index 100% rename from src/cyberpanel/configservercsf/migrations/__init__.py rename to src/official/cyberpanel/configservercsf/migrations/__init__.py diff --git a/src/cyberpanel/configservercsf/models.py b/src/official/cyberpanel/configservercsf/models.py similarity index 100% rename from src/cyberpanel/configservercsf/models.py rename to src/official/cyberpanel/configservercsf/models.py diff --git a/src/cyberpanel/configservercsf/signals.py b/src/official/cyberpanel/configservercsf/signals.py similarity index 100% rename from src/cyberpanel/configservercsf/signals.py rename to src/official/cyberpanel/configservercsf/signals.py diff --git a/src/cyberpanel/configservercsf/templates/configservercsf/index.html b/src/official/cyberpanel/configservercsf/templates/configservercsf/index.html similarity index 100% rename from src/cyberpanel/configservercsf/templates/configservercsf/index.html rename to src/official/cyberpanel/configservercsf/templates/configservercsf/index.html diff --git a/src/cyberpanel/configservercsf/templates/configservercsf/menu.html b/src/official/cyberpanel/configservercsf/templates/configservercsf/menu.html similarity index 100% rename from src/cyberpanel/configservercsf/templates/configservercsf/menu.html rename to src/official/cyberpanel/configservercsf/templates/configservercsf/menu.html diff --git a/src/cyberpanel/configservercsf/tests.py b/src/official/cyberpanel/configservercsf/tests.py similarity index 100% rename from src/cyberpanel/configservercsf/tests.py rename to src/official/cyberpanel/configservercsf/tests.py diff --git a/src/cyberpanel/configservercsf/urls.py b/src/official/cyberpanel/configservercsf/urls.py similarity index 100% rename from src/cyberpanel/configservercsf/urls.py rename to src/official/cyberpanel/configservercsf/urls.py diff --git a/src/cyberpanel/configservercsf/views.py b/src/official/cyberpanel/configservercsf/views.py similarity index 100% rename from src/cyberpanel/configservercsf/views.py rename to src/official/cyberpanel/configservercsf/views.py diff --git a/src/cyberpanel/cyberpanel.pl b/src/official/cyberpanel/cyberpanel.pl similarity index 100% rename from src/cyberpanel/cyberpanel.pl rename to src/official/cyberpanel/cyberpanel.pl diff --git a/src/da/admin/index.html b/src/official/da/admin/index.html similarity index 100% rename from src/da/admin/index.html rename to src/official/da/admin/index.html diff --git a/src/da/admin/index.raw b/src/official/da/admin/index.raw similarity index 100% rename from src/da/admin/index.raw rename to src/official/da/admin/index.raw diff --git a/src/da/exec/da_csf.cgi b/src/official/da/exec/da_csf.cgi similarity index 100% rename from src/da/exec/da_csf.cgi rename to src/official/da/exec/da_csf.cgi diff --git a/src/da/exec/da_csf_reseller.cgi b/src/official/da/exec/da_csf_reseller.cgi similarity index 100% rename from src/da/exec/da_csf_reseller.cgi rename to src/official/da/exec/da_csf_reseller.cgi diff --git a/src/da/hooks/admin_img.html b/src/official/da/hooks/admin_img.html similarity index 100% rename from src/da/hooks/admin_img.html rename to src/official/da/hooks/admin_img.html diff --git a/src/da/hooks/admin_txt.html b/src/official/da/hooks/admin_txt.html similarity index 100% rename from src/da/hooks/admin_txt.html rename to src/official/da/hooks/admin_txt.html diff --git a/src/da/hooks/reseller_img.html b/src/official/da/hooks/reseller_img.html similarity index 100% rename from src/da/hooks/reseller_img.html rename to src/official/da/hooks/reseller_img.html diff --git a/src/da/hooks/reseller_txt.html b/src/official/da/hooks/reseller_txt.html similarity index 100% rename from src/da/hooks/reseller_txt.html rename to src/official/da/hooks/reseller_txt.html diff --git a/src/da/images/LICENSE.txt b/src/official/da/images/LICENSE.txt similarity index 100% rename from src/da/images/LICENSE.txt rename to src/official/da/images/LICENSE.txt diff --git a/src/da/images/admin_icon.svg b/src/official/da/images/admin_icon.svg similarity index 100% rename from src/da/images/admin_icon.svg rename to src/official/da/images/admin_icon.svg diff --git a/src/da/images/bootstrap-chosen.css b/src/official/da/images/bootstrap-chosen.css similarity index 100% rename from src/da/images/bootstrap-chosen.css rename to src/official/da/images/bootstrap-chosen.css diff --git a/src/da/images/bootstrap/css/bootstrap.min.css b/src/official/da/images/bootstrap/css/bootstrap.min.css similarity index 100% rename from src/da/images/bootstrap/css/bootstrap.min.css rename to src/official/da/images/bootstrap/css/bootstrap.min.css diff --git a/src/da/images/bootstrap/css/bootstrap.min.css.map b/src/official/da/images/bootstrap/css/bootstrap.min.css.map similarity index 100% rename from src/da/images/bootstrap/css/bootstrap.min.css.map rename to src/official/da/images/bootstrap/css/bootstrap.min.css.map diff --git a/src/da/images/bootstrap/fonts/glyphicons-halflings-regular.eot b/src/official/da/images/bootstrap/fonts/glyphicons-halflings-regular.eot similarity index 100% rename from src/da/images/bootstrap/fonts/glyphicons-halflings-regular.eot rename to src/official/da/images/bootstrap/fonts/glyphicons-halflings-regular.eot diff --git a/src/da/images/bootstrap/fonts/glyphicons-halflings-regular.svg b/src/official/da/images/bootstrap/fonts/glyphicons-halflings-regular.svg similarity index 100% rename from src/da/images/bootstrap/fonts/glyphicons-halflings-regular.svg rename to src/official/da/images/bootstrap/fonts/glyphicons-halflings-regular.svg diff --git a/src/da/images/bootstrap/fonts/glyphicons-halflings-regular.ttf b/src/official/da/images/bootstrap/fonts/glyphicons-halflings-regular.ttf similarity index 100% rename from src/da/images/bootstrap/fonts/glyphicons-halflings-regular.ttf rename to src/official/da/images/bootstrap/fonts/glyphicons-halflings-regular.ttf diff --git a/src/da/images/bootstrap/fonts/glyphicons-halflings-regular.woff b/src/official/da/images/bootstrap/fonts/glyphicons-halflings-regular.woff similarity index 100% rename from src/da/images/bootstrap/fonts/glyphicons-halflings-regular.woff rename to src/official/da/images/bootstrap/fonts/glyphicons-halflings-regular.woff diff --git a/src/da/images/bootstrap/fonts/glyphicons-halflings-regular.woff2 b/src/official/da/images/bootstrap/fonts/glyphicons-halflings-regular.woff2 similarity index 100% rename from src/da/images/bootstrap/fonts/glyphicons-halflings-regular.woff2 rename to src/official/da/images/bootstrap/fonts/glyphicons-halflings-regular.woff2 diff --git a/src/da/images/bootstrap/js/bootstrap.min.js b/src/official/da/images/bootstrap/js/bootstrap.min.js similarity index 100% rename from src/da/images/bootstrap/js/bootstrap.min.js rename to src/official/da/images/bootstrap/js/bootstrap.min.js diff --git a/src/da/images/chosen-sprite.png b/src/official/da/images/chosen-sprite.png similarity index 100% rename from src/da/images/chosen-sprite.png rename to src/official/da/images/chosen-sprite.png diff --git a/src/da/images/chosen-sprite@2x.png b/src/official/da/images/chosen-sprite@2x.png similarity index 100% rename from src/da/images/chosen-sprite@2x.png rename to src/official/da/images/chosen-sprite@2x.png diff --git a/src/da/images/chosen.min.css b/src/official/da/images/chosen.min.css similarity index 100% rename from src/da/images/chosen.min.css rename to src/official/da/images/chosen.min.css diff --git a/src/da/images/chosen.min.js b/src/official/da/images/chosen.min.js similarity index 100% rename from src/da/images/chosen.min.js rename to src/official/da/images/chosen.min.js diff --git a/src/da/images/configserver.css b/src/official/da/images/configserver.css similarity index 100% rename from src/da/images/configserver.css rename to src/official/da/images/configserver.css diff --git a/src/da/images/csf-loader.gif b/src/official/da/images/csf-loader.gif similarity index 100% rename from src/da/images/csf-loader.gif rename to src/official/da/images/csf-loader.gif diff --git a/src/da/images/csf.svg b/src/official/da/images/csf.svg similarity index 100% rename from src/da/images/csf.svg rename to src/official/da/images/csf.svg diff --git a/src/da/images/csf_small.png b/src/official/da/images/csf_small.png similarity index 100% rename from src/da/images/csf_small.png rename to src/official/da/images/csf_small.png diff --git a/src/da/images/jquery.min.js b/src/official/da/images/jquery.min.js similarity index 100% rename from src/da/images/jquery.min.js rename to src/official/da/images/jquery.min.js diff --git a/src/da/images/loader.gif b/src/official/da/images/loader.gif similarity index 100% rename from src/da/images/loader.gif rename to src/official/da/images/loader.gif diff --git a/src/da/images/reseller_icon.svg b/src/official/da/images/reseller_icon.svg similarity index 100% rename from src/da/images/reseller_icon.svg rename to src/official/da/images/reseller_icon.svg diff --git a/src/da/plugin.conf b/src/official/da/plugin.conf similarity index 100% rename from src/da/plugin.conf rename to src/official/da/plugin.conf diff --git a/src/da/reseller/index.html b/src/official/da/reseller/index.html similarity index 100% rename from src/da/reseller/index.html rename to src/official/da/reseller/index.html diff --git a/src/da/reseller/index.raw b/src/official/da/reseller/index.raw similarity index 100% rename from src/da/reseller/index.raw rename to src/official/da/reseller/index.raw diff --git a/src/da/scripts/install.sh b/src/official/da/scripts/install.sh similarity index 100% rename from src/da/scripts/install.sh rename to src/official/da/scripts/install.sh diff --git a/src/da/scripts/uninstall.sh b/src/official/da/scripts/uninstall.sh similarity index 100% rename from src/da/scripts/uninstall.sh rename to src/official/da/scripts/uninstall.sh diff --git a/src/da/scripts/update.sh b/src/official/da/scripts/update.sh similarity index 100% rename from src/da/scripts/update.sh rename to src/official/da/scripts/update.sh diff --git a/src/downloadservers b/src/official/downloadservers similarity index 100% rename from src/downloadservers rename to src/official/downloadservers diff --git a/src/exploitalert.txt b/src/official/exploitalert.txt similarity index 100% rename from src/exploitalert.txt rename to src/official/exploitalert.txt diff --git a/src/filealert.txt b/src/official/filealert.txt similarity index 100% rename from src/filealert.txt rename to src/official/filealert.txt diff --git a/src/forkbombalert.txt b/src/official/forkbombalert.txt similarity index 100% rename from src/forkbombalert.txt rename to src/official/forkbombalert.txt diff --git a/src/install.cpanel.sh b/src/official/install.cpanel.sh similarity index 100% rename from src/install.cpanel.sh rename to src/official/install.cpanel.sh diff --git a/src/install.cwp.sh b/src/official/install.cwp.sh similarity index 100% rename from src/install.cwp.sh rename to src/official/install.cwp.sh diff --git a/src/install.cyberpanel.sh b/src/official/install.cyberpanel.sh similarity index 100% rename from src/install.cyberpanel.sh rename to src/official/install.cyberpanel.sh diff --git a/src/install.directadmin.sh b/src/official/install.directadmin.sh similarity index 100% rename from src/install.directadmin.sh rename to src/official/install.directadmin.sh diff --git a/src/install.generic.sh b/src/official/install.generic.sh similarity index 100% rename from src/install.generic.sh rename to src/official/install.generic.sh diff --git a/src/install.interworx.sh b/src/official/install.interworx.sh similarity index 100% rename from src/install.interworx.sh rename to src/official/install.interworx.sh diff --git a/src/install.sh b/src/official/install.sh similarity index 100% rename from src/install.sh rename to src/official/install.sh diff --git a/src/install.txt b/src/official/install.txt similarity index 100% rename from src/install.txt rename to src/official/install.txt diff --git a/src/install.vesta.sh b/src/official/install.vesta.sh similarity index 100% rename from src/install.vesta.sh rename to src/official/install.vesta.sh diff --git a/src/integrityalert.txt b/src/official/integrityalert.txt similarity index 100% rename from src/integrityalert.txt rename to src/official/integrityalert.txt diff --git a/src/interworx/Ctrl/Nodeworx/Configservercsf.php b/src/official/interworx/Ctrl/Nodeworx/Configservercsf.php similarity index 100% rename from src/interworx/Ctrl/Nodeworx/Configservercsf.php rename to src/official/interworx/Ctrl/Nodeworx/Configservercsf.php diff --git a/src/interworx/Plugin/Configservercsf.php b/src/official/interworx/Plugin/Configservercsf.php similarity index 100% rename from src/interworx/Plugin/Configservercsf.php rename to src/official/interworx/Plugin/Configservercsf.php diff --git a/src/interworx/images/LICENSE.txt b/src/official/interworx/images/LICENSE.txt similarity index 100% rename from src/interworx/images/LICENSE.txt rename to src/official/interworx/images/LICENSE.txt diff --git a/src/interworx/images/admin_icon.svg b/src/official/interworx/images/admin_icon.svg similarity index 100% rename from src/interworx/images/admin_icon.svg rename to src/official/interworx/images/admin_icon.svg diff --git a/src/interworx/images/bootstrap-chosen.css b/src/official/interworx/images/bootstrap-chosen.css similarity index 100% rename from src/interworx/images/bootstrap-chosen.css rename to src/official/interworx/images/bootstrap-chosen.css diff --git a/src/interworx/images/bootstrap/css/bootstrap.min.css b/src/official/interworx/images/bootstrap/css/bootstrap.min.css similarity index 100% rename from src/interworx/images/bootstrap/css/bootstrap.min.css rename to src/official/interworx/images/bootstrap/css/bootstrap.min.css diff --git a/src/interworx/images/bootstrap/css/bootstrap.min.css.map b/src/official/interworx/images/bootstrap/css/bootstrap.min.css.map similarity index 100% rename from src/interworx/images/bootstrap/css/bootstrap.min.css.map rename to src/official/interworx/images/bootstrap/css/bootstrap.min.css.map diff --git a/src/interworx/images/bootstrap/fonts/glyphicons-halflings-regular.eot b/src/official/interworx/images/bootstrap/fonts/glyphicons-halflings-regular.eot similarity index 100% rename from src/interworx/images/bootstrap/fonts/glyphicons-halflings-regular.eot rename to src/official/interworx/images/bootstrap/fonts/glyphicons-halflings-regular.eot diff --git a/src/interworx/images/bootstrap/fonts/glyphicons-halflings-regular.svg b/src/official/interworx/images/bootstrap/fonts/glyphicons-halflings-regular.svg similarity index 100% rename from src/interworx/images/bootstrap/fonts/glyphicons-halflings-regular.svg rename to src/official/interworx/images/bootstrap/fonts/glyphicons-halflings-regular.svg diff --git a/src/interworx/images/bootstrap/fonts/glyphicons-halflings-regular.ttf b/src/official/interworx/images/bootstrap/fonts/glyphicons-halflings-regular.ttf similarity index 100% rename from src/interworx/images/bootstrap/fonts/glyphicons-halflings-regular.ttf rename to src/official/interworx/images/bootstrap/fonts/glyphicons-halflings-regular.ttf diff --git a/src/interworx/images/bootstrap/fonts/glyphicons-halflings-regular.woff b/src/official/interworx/images/bootstrap/fonts/glyphicons-halflings-regular.woff similarity index 100% rename from src/interworx/images/bootstrap/fonts/glyphicons-halflings-regular.woff rename to src/official/interworx/images/bootstrap/fonts/glyphicons-halflings-regular.woff diff --git a/src/interworx/images/bootstrap/fonts/glyphicons-halflings-regular.woff2 b/src/official/interworx/images/bootstrap/fonts/glyphicons-halflings-regular.woff2 similarity index 100% rename from src/interworx/images/bootstrap/fonts/glyphicons-halflings-regular.woff2 rename to src/official/interworx/images/bootstrap/fonts/glyphicons-halflings-regular.woff2 diff --git a/src/interworx/images/bootstrap/js/bootstrap.min.js b/src/official/interworx/images/bootstrap/js/bootstrap.min.js similarity index 100% rename from src/interworx/images/bootstrap/js/bootstrap.min.js rename to src/official/interworx/images/bootstrap/js/bootstrap.min.js diff --git a/src/interworx/images/chosen-sprite.png b/src/official/interworx/images/chosen-sprite.png similarity index 100% rename from src/interworx/images/chosen-sprite.png rename to src/official/interworx/images/chosen-sprite.png diff --git a/src/interworx/images/chosen-sprite@2x.png b/src/official/interworx/images/chosen-sprite@2x.png similarity index 100% rename from src/interworx/images/chosen-sprite@2x.png rename to src/official/interworx/images/chosen-sprite@2x.png diff --git a/src/interworx/images/chosen.min.css b/src/official/interworx/images/chosen.min.css similarity index 100% rename from src/interworx/images/chosen.min.css rename to src/official/interworx/images/chosen.min.css diff --git a/src/interworx/images/chosen.min.js b/src/official/interworx/images/chosen.min.js similarity index 100% rename from src/interworx/images/chosen.min.js rename to src/official/interworx/images/chosen.min.js diff --git a/src/interworx/images/configserver.css b/src/official/interworx/images/configserver.css similarity index 100% rename from src/interworx/images/configserver.css rename to src/official/interworx/images/configserver.css diff --git a/src/interworx/images/csf-loader.gif b/src/official/interworx/images/csf-loader.gif similarity index 100% rename from src/interworx/images/csf-loader.gif rename to src/official/interworx/images/csf-loader.gif diff --git a/src/interworx/images/csf.svg b/src/official/interworx/images/csf.svg similarity index 100% rename from src/interworx/images/csf.svg rename to src/official/interworx/images/csf.svg diff --git a/src/interworx/images/csf_small.png b/src/official/interworx/images/csf_small.png similarity index 100% rename from src/interworx/images/csf_small.png rename to src/official/interworx/images/csf_small.png diff --git a/src/interworx/images/jquery.min.js b/src/official/interworx/images/jquery.min.js similarity index 100% rename from src/interworx/images/jquery.min.js rename to src/official/interworx/images/jquery.min.js diff --git a/src/interworx/images/loader.gif b/src/official/interworx/images/loader.gif similarity index 100% rename from src/interworx/images/loader.gif rename to src/official/interworx/images/loader.gif diff --git a/src/interworx/images/reseller_icon.svg b/src/official/interworx/images/reseller_icon.svg similarity index 100% rename from src/interworx/images/reseller_icon.svg rename to src/official/interworx/images/reseller_icon.svg diff --git a/src/interworx/lib/index.pl b/src/official/interworx/lib/index.pl similarity index 100% rename from src/interworx/lib/index.pl rename to src/official/interworx/lib/index.pl diff --git a/src/interworx/lib/reseller.pl b/src/official/interworx/lib/reseller.pl similarity index 100% rename from src/interworx/lib/reseller.pl rename to src/official/interworx/lib/reseller.pl diff --git a/src/interworx/plugin.ini b/src/official/interworx/plugin.ini similarity index 100% rename from src/interworx/plugin.ini rename to src/official/interworx/plugin.ini diff --git a/src/interworx/templates/admin.tpl b/src/official/interworx/templates/admin.tpl similarity index 100% rename from src/interworx/templates/admin.tpl rename to src/official/interworx/templates/admin.tpl diff --git a/src/interworx/templates/reseller.tpl b/src/official/interworx/templates/reseller.tpl similarity index 100% rename from src/interworx/templates/reseller.tpl rename to src/official/interworx/templates/reseller.tpl diff --git a/src/lfd.logrotate b/src/official/lfd.logrotate similarity index 100% rename from src/lfd.logrotate rename to src/official/lfd.logrotate diff --git a/src/lfd.pl b/src/official/lfd.pl similarity index 100% rename from src/lfd.pl rename to src/official/lfd.pl diff --git a/src/lfd.service b/src/official/lfd.service similarity index 100% rename from src/lfd.service rename to src/official/lfd.service diff --git a/src/lfd.sh b/src/official/lfd.sh similarity index 100% rename from src/lfd.sh rename to src/official/lfd.sh diff --git a/src/lfdcron.directadmin.sh b/src/official/lfdcron.directadmin.sh similarity index 100% rename from src/lfdcron.directadmin.sh rename to src/official/lfdcron.directadmin.sh diff --git a/src/lfdcron.sh b/src/official/lfdcron.sh similarity index 100% rename from src/lfdcron.sh rename to src/official/lfdcron.sh diff --git a/src/license.txt b/src/official/license.txt similarity index 100% rename from src/license.txt rename to src/official/license.txt diff --git a/src/litespeed.http.txt b/src/official/litespeed.http.txt similarity index 100% rename from src/litespeed.http.txt rename to src/official/litespeed.http.txt diff --git a/src/litespeed.https.txt b/src/official/litespeed.https.txt similarity index 100% rename from src/litespeed.https.txt rename to src/official/litespeed.https.txt diff --git a/src/litespeed.main.txt b/src/official/litespeed.main.txt similarity index 100% rename from src/litespeed.main.txt rename to src/official/litespeed.main.txt diff --git a/src/loadalert.txt b/src/official/loadalert.txt similarity index 100% rename from src/loadalert.txt rename to src/official/loadalert.txt diff --git a/src/logalert.txt b/src/official/logalert.txt similarity index 100% rename from src/logalert.txt rename to src/official/logalert.txt diff --git a/src/logfloodalert.txt b/src/official/logfloodalert.txt similarity index 100% rename from src/logfloodalert.txt rename to src/official/logfloodalert.txt diff --git a/src/messenger/en.php b/src/official/messenger/en.php similarity index 100% rename from src/messenger/en.php rename to src/official/messenger/en.php diff --git a/src/messenger/index.html b/src/official/messenger/index.html similarity index 100% rename from src/messenger/index.html rename to src/official/messenger/index.html diff --git a/src/messenger/index.php b/src/official/messenger/index.php similarity index 100% rename from src/messenger/index.php rename to src/official/messenger/index.php diff --git a/src/messenger/index.recaptcha.html b/src/official/messenger/index.recaptcha.html similarity index 100% rename from src/messenger/index.recaptcha.html rename to src/official/messenger/index.recaptcha.html diff --git a/src/messenger/index.recaptcha.php b/src/official/messenger/index.recaptcha.php similarity index 100% rename from src/messenger/index.recaptcha.php rename to src/official/messenger/index.recaptcha.php diff --git a/src/messenger/index.text b/src/official/messenger/index.text similarity index 100% rename from src/messenger/index.text rename to src/official/messenger/index.text diff --git a/src/migratedata.sh b/src/official/migratedata.sh similarity index 100% rename from src/migratedata.sh rename to src/official/migratedata.sh diff --git a/src/modsecipdbalert.txt b/src/official/modsecipdbalert.txt similarity index 100% rename from src/modsecipdbalert.txt rename to src/official/modsecipdbalert.txt diff --git a/src/netblock.txt b/src/official/netblock.txt similarity index 100% rename from src/netblock.txt rename to src/official/netblock.txt diff --git a/src/os.pl b/src/official/os.pl similarity index 100% rename from src/os.pl rename to src/official/os.pl diff --git a/src/perf.sh b/src/official/perf.sh similarity index 100% rename from src/perf.sh rename to src/official/perf.sh diff --git a/src/permblock.txt b/src/official/permblock.txt similarity index 100% rename from src/permblock.txt rename to src/official/permblock.txt diff --git a/src/portknocking.txt b/src/official/portknocking.txt similarity index 100% rename from src/portknocking.txt rename to src/official/portknocking.txt diff --git a/src/portscan.txt b/src/official/portscan.txt similarity index 100% rename from src/portscan.txt rename to src/official/portscan.txt diff --git a/src/processtracking.txt b/src/official/processtracking.txt similarity index 100% rename from src/processtracking.txt rename to src/official/processtracking.txt diff --git a/src/profiles/block_all_perm.conf b/src/official/profiles/block_all_perm.conf similarity index 100% rename from src/profiles/block_all_perm.conf rename to src/official/profiles/block_all_perm.conf diff --git a/src/profiles/block_all_temp.conf b/src/official/profiles/block_all_temp.conf similarity index 100% rename from src/profiles/block_all_temp.conf rename to src/official/profiles/block_all_temp.conf diff --git a/src/profiles/disable_alerts.conf b/src/official/profiles/disable_alerts.conf similarity index 100% rename from src/profiles/disable_alerts.conf rename to src/official/profiles/disable_alerts.conf diff --git a/src/profiles/protection_high.conf b/src/official/profiles/protection_high.conf similarity index 100% rename from src/profiles/protection_high.conf rename to src/official/profiles/protection_high.conf diff --git a/src/profiles/protection_low.conf b/src/official/profiles/protection_low.conf similarity index 100% rename from src/profiles/protection_low.conf rename to src/official/profiles/protection_low.conf diff --git a/src/profiles/protection_medium.conf b/src/official/profiles/protection_medium.conf similarity index 100% rename from src/profiles/protection_medium.conf rename to src/official/profiles/protection_medium.conf diff --git a/src/pt_deleted_action.pl b/src/official/pt_deleted_action.pl similarity index 100% rename from src/pt_deleted_action.pl rename to src/official/pt_deleted_action.pl diff --git a/src/queuealert.txt b/src/official/queuealert.txt similarity index 100% rename from src/queuealert.txt rename to src/official/queuealert.txt diff --git a/src/readme.txt b/src/official/readme.txt similarity index 100% rename from src/readme.txt rename to src/official/readme.txt diff --git a/src/recaptcha.txt b/src/official/recaptcha.txt similarity index 100% rename from src/recaptcha.txt rename to src/official/recaptcha.txt diff --git a/src/regex.custom.pm b/src/official/regex.custom.pm similarity index 100% rename from src/regex.custom.pm rename to src/official/regex.custom.pm diff --git a/src/regex.txt b/src/official/regex.txt similarity index 100% rename from src/regex.txt rename to src/official/regex.txt diff --git a/src/relayalert.txt b/src/official/relayalert.txt similarity index 100% rename from src/relayalert.txt rename to src/official/relayalert.txt diff --git a/src/remove_apf_bfd.sh b/src/official/remove_apf_bfd.sh similarity index 100% rename from src/remove_apf_bfd.sh rename to src/official/remove_apf_bfd.sh diff --git a/src/resalert.txt b/src/official/resalert.txt similarity index 100% rename from src/resalert.txt rename to src/official/resalert.txt diff --git a/src/reselleralert.txt b/src/official/reselleralert.txt similarity index 100% rename from src/reselleralert.txt rename to src/official/reselleralert.txt diff --git a/src/restricted.txt b/src/official/restricted.txt similarity index 100% rename from src/restricted.txt rename to src/official/restricted.txt diff --git a/src/sanity.txt b/src/official/sanity.txt similarity index 100% rename from src/sanity.txt rename to src/official/sanity.txt diff --git a/src/scriptalert.txt b/src/official/scriptalert.txt similarity index 100% rename from src/scriptalert.txt rename to src/official/scriptalert.txt diff --git a/src/sshalert.txt b/src/official/sshalert.txt similarity index 100% rename from src/sshalert.txt rename to src/official/sshalert.txt diff --git a/src/sualert.txt b/src/official/sualert.txt similarity index 100% rename from src/sualert.txt rename to src/official/sualert.txt diff --git a/src/sudoalert.txt b/src/official/sudoalert.txt similarity index 100% rename from src/sudoalert.txt rename to src/official/sudoalert.txt diff --git a/src/syslogalert.txt b/src/official/syslogalert.txt similarity index 100% rename from src/syslogalert.txt rename to src/official/syslogalert.txt diff --git a/src/tracking.txt b/src/official/tracking.txt similarity index 100% rename from src/tracking.txt rename to src/official/tracking.txt diff --git a/src/ui/images/LICENSE.txt b/src/official/ui/images/LICENSE.txt similarity index 100% rename from src/ui/images/LICENSE.txt rename to src/official/ui/images/LICENSE.txt diff --git a/src/ui/images/admin_icon.svg b/src/official/ui/images/admin_icon.svg similarity index 100% rename from src/ui/images/admin_icon.svg rename to src/official/ui/images/admin_icon.svg diff --git a/src/ui/images/bootstrap-chosen.css b/src/official/ui/images/bootstrap-chosen.css similarity index 100% rename from src/ui/images/bootstrap-chosen.css rename to src/official/ui/images/bootstrap-chosen.css diff --git a/src/ui/images/bootstrap/css/bootstrap.min.css b/src/official/ui/images/bootstrap/css/bootstrap.min.css similarity index 100% rename from src/ui/images/bootstrap/css/bootstrap.min.css rename to src/official/ui/images/bootstrap/css/bootstrap.min.css diff --git a/src/ui/images/bootstrap/css/bootstrap.min.css.map b/src/official/ui/images/bootstrap/css/bootstrap.min.css.map similarity index 100% rename from src/ui/images/bootstrap/css/bootstrap.min.css.map rename to src/official/ui/images/bootstrap/css/bootstrap.min.css.map diff --git a/src/ui/images/bootstrap/fonts/glyphicons-halflings-regular.eot b/src/official/ui/images/bootstrap/fonts/glyphicons-halflings-regular.eot similarity index 100% rename from src/ui/images/bootstrap/fonts/glyphicons-halflings-regular.eot rename to src/official/ui/images/bootstrap/fonts/glyphicons-halflings-regular.eot diff --git a/src/ui/images/bootstrap/fonts/glyphicons-halflings-regular.svg b/src/official/ui/images/bootstrap/fonts/glyphicons-halflings-regular.svg similarity index 100% rename from src/ui/images/bootstrap/fonts/glyphicons-halflings-regular.svg rename to src/official/ui/images/bootstrap/fonts/glyphicons-halflings-regular.svg diff --git a/src/ui/images/bootstrap/fonts/glyphicons-halflings-regular.ttf b/src/official/ui/images/bootstrap/fonts/glyphicons-halflings-regular.ttf similarity index 100% rename from src/ui/images/bootstrap/fonts/glyphicons-halflings-regular.ttf rename to src/official/ui/images/bootstrap/fonts/glyphicons-halflings-regular.ttf diff --git a/src/ui/images/bootstrap/fonts/glyphicons-halflings-regular.woff b/src/official/ui/images/bootstrap/fonts/glyphicons-halflings-regular.woff similarity index 100% rename from src/ui/images/bootstrap/fonts/glyphicons-halflings-regular.woff rename to src/official/ui/images/bootstrap/fonts/glyphicons-halflings-regular.woff diff --git a/src/ui/images/bootstrap/fonts/glyphicons-halflings-regular.woff2 b/src/official/ui/images/bootstrap/fonts/glyphicons-halflings-regular.woff2 similarity index 100% rename from src/ui/images/bootstrap/fonts/glyphicons-halflings-regular.woff2 rename to src/official/ui/images/bootstrap/fonts/glyphicons-halflings-regular.woff2 diff --git a/src/ui/images/bootstrap/js/bootstrap.min.js b/src/official/ui/images/bootstrap/js/bootstrap.min.js similarity index 100% rename from src/ui/images/bootstrap/js/bootstrap.min.js rename to src/official/ui/images/bootstrap/js/bootstrap.min.js diff --git a/src/ui/images/chosen-sprite.png b/src/official/ui/images/chosen-sprite.png similarity index 100% rename from src/ui/images/chosen-sprite.png rename to src/official/ui/images/chosen-sprite.png diff --git a/src/ui/images/chosen-sprite@2x.png b/src/official/ui/images/chosen-sprite@2x.png similarity index 100% rename from src/ui/images/chosen-sprite@2x.png rename to src/official/ui/images/chosen-sprite@2x.png diff --git a/src/ui/images/chosen.min.css b/src/official/ui/images/chosen.min.css similarity index 100% rename from src/ui/images/chosen.min.css rename to src/official/ui/images/chosen.min.css diff --git a/src/ui/images/chosen.min.js b/src/official/ui/images/chosen.min.js similarity index 100% rename from src/ui/images/chosen.min.js rename to src/official/ui/images/chosen.min.js diff --git a/src/ui/images/configserver.css b/src/official/ui/images/configserver.css similarity index 100% rename from src/ui/images/configserver.css rename to src/official/ui/images/configserver.css diff --git a/src/ui/images/csf-loader.gif b/src/official/ui/images/csf-loader.gif similarity index 100% rename from src/ui/images/csf-loader.gif rename to src/official/ui/images/csf-loader.gif diff --git a/src/ui/images/csf.svg b/src/official/ui/images/csf.svg similarity index 100% rename from src/ui/images/csf.svg rename to src/official/ui/images/csf.svg diff --git a/src/ui/images/csf_small.png b/src/official/ui/images/csf_small.png similarity index 100% rename from src/ui/images/csf_small.png rename to src/official/ui/images/csf_small.png diff --git a/src/ui/images/jquery.min.js b/src/official/ui/images/jquery.min.js similarity index 100% rename from src/ui/images/jquery.min.js rename to src/official/ui/images/jquery.min.js diff --git a/src/ui/images/loader.gif b/src/official/ui/images/loader.gif similarity index 100% rename from src/ui/images/loader.gif rename to src/official/ui/images/loader.gif diff --git a/src/ui/images/reseller_icon.svg b/src/official/ui/images/reseller_icon.svg similarity index 100% rename from src/ui/images/reseller_icon.svg rename to src/official/ui/images/reseller_icon.svg diff --git a/src/ui/server.crt b/src/official/ui/server.crt similarity index 100% rename from src/ui/server.crt rename to src/official/ui/server.crt diff --git a/src/ui/server.key b/src/official/ui/server.key similarity index 100% rename from src/ui/server.key rename to src/official/ui/server.key diff --git a/src/ui/ui.allow b/src/official/ui/ui.allow similarity index 100% rename from src/ui/ui.allow rename to src/official/ui/ui.allow diff --git a/src/ui/ui.ban b/src/official/ui/ui.ban similarity index 100% rename from src/ui/ui.ban rename to src/official/ui/ui.ban diff --git a/src/uialert.txt b/src/official/uialert.txt similarity index 100% rename from src/uialert.txt rename to src/official/uialert.txt diff --git a/src/uidscan.txt b/src/official/uidscan.txt similarity index 100% rename from src/uidscan.txt rename to src/official/uidscan.txt diff --git a/src/uninstall.cwp.sh b/src/official/uninstall.cwp.sh similarity index 100% rename from src/uninstall.cwp.sh rename to src/official/uninstall.cwp.sh diff --git a/src/uninstall.cyberpanel.sh b/src/official/uninstall.cyberpanel.sh similarity index 100% rename from src/uninstall.cyberpanel.sh rename to src/official/uninstall.cyberpanel.sh diff --git a/src/uninstall.directadmin.sh b/src/official/uninstall.directadmin.sh similarity index 100% rename from src/uninstall.directadmin.sh rename to src/official/uninstall.directadmin.sh diff --git a/src/uninstall.generic.sh b/src/official/uninstall.generic.sh similarity index 100% rename from src/uninstall.generic.sh rename to src/official/uninstall.generic.sh diff --git a/src/uninstall.interworx.sh b/src/official/uninstall.interworx.sh similarity index 100% rename from src/uninstall.interworx.sh rename to src/official/uninstall.interworx.sh diff --git a/src/uninstall.sh b/src/official/uninstall.sh similarity index 100% rename from src/uninstall.sh rename to src/official/uninstall.sh diff --git a/src/uninstall.vesta.sh b/src/official/uninstall.vesta.sh similarity index 100% rename from src/uninstall.vesta.sh rename to src/official/uninstall.vesta.sh diff --git a/src/upgrade.txt b/src/official/upgrade.txt similarity index 100% rename from src/upgrade.txt rename to src/official/upgrade.txt diff --git a/src/usertracking.txt b/src/official/usertracking.txt similarity index 100% rename from src/usertracking.txt rename to src/official/usertracking.txt diff --git a/src/version.txt b/src/official/version.txt similarity index 100% rename from src/version.txt rename to src/official/version.txt diff --git a/src/version/version.pm b/src/official/version/version.pm similarity index 100% rename from src/version/version.pm rename to src/official/version/version.pm diff --git a/src/version/version/regex.pm b/src/official/version/version/regex.pm similarity index 100% rename from src/version/version/regex.pm rename to src/official/version/version/regex.pm diff --git a/src/version/version/vpp.pm b/src/official/version/version/vpp.pm similarity index 100% rename from src/version/version/vpp.pm rename to src/official/version/version/vpp.pm diff --git a/src/vestacp/csf.pl b/src/official/vestacp/csf.pl similarity index 100% rename from src/vestacp/csf.pl rename to src/official/vestacp/csf.pl diff --git a/src/vestacp/frame.php b/src/official/vestacp/frame.php similarity index 100% rename from src/vestacp/frame.php rename to src/official/vestacp/frame.php diff --git a/src/vestacp/index.php b/src/official/vestacp/index.php similarity index 100% rename from src/vestacp/index.php rename to src/official/vestacp/index.php diff --git a/src/watchalert.txt b/src/official/watchalert.txt similarity index 100% rename from src/watchalert.txt rename to src/official/watchalert.txt diff --git a/src/webmin/csf/images/LICENSE.txt b/src/official/webmin/csf/images/LICENSE.txt similarity index 100% rename from src/webmin/csf/images/LICENSE.txt rename to src/official/webmin/csf/images/LICENSE.txt diff --git a/src/webmin/csf/images/admin_icon.svg b/src/official/webmin/csf/images/admin_icon.svg similarity index 100% rename from src/webmin/csf/images/admin_icon.svg rename to src/official/webmin/csf/images/admin_icon.svg diff --git a/src/webmin/csf/images/bootstrap-chosen.css b/src/official/webmin/csf/images/bootstrap-chosen.css similarity index 100% rename from src/webmin/csf/images/bootstrap-chosen.css rename to src/official/webmin/csf/images/bootstrap-chosen.css diff --git a/src/webmin/csf/images/bootstrap/css/bootstrap.min.css b/src/official/webmin/csf/images/bootstrap/css/bootstrap.min.css similarity index 100% rename from src/webmin/csf/images/bootstrap/css/bootstrap.min.css rename to src/official/webmin/csf/images/bootstrap/css/bootstrap.min.css diff --git a/src/webmin/csf/images/bootstrap/css/bootstrap.min.css.map b/src/official/webmin/csf/images/bootstrap/css/bootstrap.min.css.map similarity index 100% rename from src/webmin/csf/images/bootstrap/css/bootstrap.min.css.map rename to src/official/webmin/csf/images/bootstrap/css/bootstrap.min.css.map diff --git a/src/webmin/csf/images/bootstrap/fonts/glyphicons-halflings-regular.eot b/src/official/webmin/csf/images/bootstrap/fonts/glyphicons-halflings-regular.eot similarity index 100% rename from src/webmin/csf/images/bootstrap/fonts/glyphicons-halflings-regular.eot rename to src/official/webmin/csf/images/bootstrap/fonts/glyphicons-halflings-regular.eot diff --git a/src/webmin/csf/images/bootstrap/fonts/glyphicons-halflings-regular.svg b/src/official/webmin/csf/images/bootstrap/fonts/glyphicons-halflings-regular.svg similarity index 100% rename from src/webmin/csf/images/bootstrap/fonts/glyphicons-halflings-regular.svg rename to src/official/webmin/csf/images/bootstrap/fonts/glyphicons-halflings-regular.svg diff --git a/src/webmin/csf/images/bootstrap/fonts/glyphicons-halflings-regular.ttf b/src/official/webmin/csf/images/bootstrap/fonts/glyphicons-halflings-regular.ttf similarity index 100% rename from src/webmin/csf/images/bootstrap/fonts/glyphicons-halflings-regular.ttf rename to src/official/webmin/csf/images/bootstrap/fonts/glyphicons-halflings-regular.ttf diff --git a/src/webmin/csf/images/bootstrap/fonts/glyphicons-halflings-regular.woff b/src/official/webmin/csf/images/bootstrap/fonts/glyphicons-halflings-regular.woff similarity index 100% rename from src/webmin/csf/images/bootstrap/fonts/glyphicons-halflings-regular.woff rename to src/official/webmin/csf/images/bootstrap/fonts/glyphicons-halflings-regular.woff diff --git a/src/webmin/csf/images/bootstrap/fonts/glyphicons-halflings-regular.woff2 b/src/official/webmin/csf/images/bootstrap/fonts/glyphicons-halflings-regular.woff2 similarity index 100% rename from src/webmin/csf/images/bootstrap/fonts/glyphicons-halflings-regular.woff2 rename to src/official/webmin/csf/images/bootstrap/fonts/glyphicons-halflings-regular.woff2 diff --git a/src/webmin/csf/images/bootstrap/js/bootstrap.min.js b/src/official/webmin/csf/images/bootstrap/js/bootstrap.min.js similarity index 100% rename from src/webmin/csf/images/bootstrap/js/bootstrap.min.js rename to src/official/webmin/csf/images/bootstrap/js/bootstrap.min.js diff --git a/src/webmin/csf/images/chosen-sprite.png b/src/official/webmin/csf/images/chosen-sprite.png similarity index 100% rename from src/webmin/csf/images/chosen-sprite.png rename to src/official/webmin/csf/images/chosen-sprite.png diff --git a/src/webmin/csf/images/chosen-sprite@2x.png b/src/official/webmin/csf/images/chosen-sprite@2x.png similarity index 100% rename from src/webmin/csf/images/chosen-sprite@2x.png rename to src/official/webmin/csf/images/chosen-sprite@2x.png diff --git a/src/webmin/csf/images/chosen.min.css b/src/official/webmin/csf/images/chosen.min.css similarity index 100% rename from src/webmin/csf/images/chosen.min.css rename to src/official/webmin/csf/images/chosen.min.css diff --git a/src/webmin/csf/images/chosen.min.js b/src/official/webmin/csf/images/chosen.min.js similarity index 100% rename from src/webmin/csf/images/chosen.min.js rename to src/official/webmin/csf/images/chosen.min.js diff --git a/src/webmin/csf/images/configserver.css b/src/official/webmin/csf/images/configserver.css similarity index 100% rename from src/webmin/csf/images/configserver.css rename to src/official/webmin/csf/images/configserver.css diff --git a/src/webmin/csf/images/csf-loader.gif b/src/official/webmin/csf/images/csf-loader.gif similarity index 100% rename from src/webmin/csf/images/csf-loader.gif rename to src/official/webmin/csf/images/csf-loader.gif diff --git a/src/webmin/csf/images/csf.svg b/src/official/webmin/csf/images/csf.svg similarity index 100% rename from src/webmin/csf/images/csf.svg rename to src/official/webmin/csf/images/csf.svg diff --git a/src/webmin/csf/images/csf_small.png b/src/official/webmin/csf/images/csf_small.png similarity index 100% rename from src/webmin/csf/images/csf_small.png rename to src/official/webmin/csf/images/csf_small.png diff --git a/src/webmin/csf/images/jquery.min.js b/src/official/webmin/csf/images/jquery.min.js similarity index 100% rename from src/webmin/csf/images/jquery.min.js rename to src/official/webmin/csf/images/jquery.min.js diff --git a/src/webmin/csf/images/loader.gif b/src/official/webmin/csf/images/loader.gif similarity index 100% rename from src/webmin/csf/images/loader.gif rename to src/official/webmin/csf/images/loader.gif diff --git a/src/webmin/csf/images/reseller_icon.svg b/src/official/webmin/csf/images/reseller_icon.svg similarity index 100% rename from src/webmin/csf/images/reseller_icon.svg rename to src/official/webmin/csf/images/reseller_icon.svg diff --git a/src/webmin/csf/index.cgi b/src/official/webmin/csf/index.cgi similarity index 100% rename from src/webmin/csf/index.cgi rename to src/official/webmin/csf/index.cgi diff --git a/src/webmin/csf/module.info b/src/official/webmin/csf/module.info similarity index 100% rename from src/webmin/csf/module.info rename to src/official/webmin/csf/module.info diff --git a/src/webminalert.txt b/src/official/webminalert.txt similarity index 100% rename from src/webminalert.txt rename to src/official/webminalert.txt diff --git a/src/x-arf.txt b/src/official/x-arf.txt similarity index 100% rename from src/x-arf.txt rename to src/official/x-arf.txt diff --git a/src/redux/.gitattributes b/src/redux/.gitattributes new file mode 100644 index 000000000..dfe077042 --- /dev/null +++ b/src/redux/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=auto diff --git a/src/redux/ConfigServer/AbuseIP.pm b/src/redux/ConfigServer/AbuseIP.pm new file mode 100644 index 000000000..8aea600ca --- /dev/null +++ b/src/redux/ConfigServer/AbuseIP.pm @@ -0,0 +1,87 @@ +############################################################################### +# Copyright 2006-2023, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +## no critic (RequireUseWarnings, ProhibitExplicitReturnUndef, ProhibitMixedBooleanOperators, RequireBriefOpen) +# start main +package ConfigServer::AbuseIP; + +use strict; +use lib '/usr/local/csf/lib'; +use Carp; +use IPC::Open3; +use Net::IP; +use ConfigServer::Config; +use ConfigServer::CheckIP qw(checkip); + +use Exporter qw(import); +our $VERSION = 1.03; +our @ISA = qw(Exporter); +our @EXPORT_OK = qw(abuseip); + +my $abusemsg = 'Abuse Contact for [ip]: [[contact]] + +The Abuse Contact of this report was provided by the Abuse Contact DB by abusix.com. abusix.com does not maintain the content of the database. All information which we pass out, derives from the RIR databases and is processed for ease of use. If you want to change or report non working abuse contacts please contact the appropriate RIR. If you have any further question, contact abusix.com directly via email (info@abusix.com). Information about the Abuse Contact Database can be found here: + +https://abusix.com/global-reporting/abuse-contact-db + +abusix.com is neither responsible nor liable for the content or accuracy of this message.'; + +my $config = ConfigServer::Config->loadconfig(); +my %config = $config->config(); + +# end main +############################################################################### +# start abuseip +sub abuseip { + my $ip = shift; + my $abuse = ""; + my $netip; + my $reversed_ip; + + if (checkip(\$ip)) { + eval { + local $SIG{__DIE__} = undef; + $netip = Net::IP->new($ip); + $reversed_ip = $netip->reverse_ip(); + }; + + if ($reversed_ip =~ /^(\S+)\.in-addr\.arpa/) {$reversed_ip = $1} + if ($reversed_ip =~ /^(\S+)\s+(\S+)\.in-addr\.arpa/) {$reversed_ip = $2} + if ($reversed_ip =~ /^(\S+)\.ip6\.arpa/) {$reversed_ip = $1} + if ($reversed_ip =~ /^(\S+)\s+(\S+)\.ip6\.arpa/) {$reversed_ip = $2} + + if ($reversed_ip ne "") { + $reversed_ip .= ".abuse-contacts.abusix.org"; + + my $cmdpid; + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die}; + alarm(10); + my ($childin, $childout); + $cmdpid = open3($childin, $childout, $childout, $config{HOST},"-W","5","-t","TXT",$reversed_ip); + close $childin; + my @results = <$childout>; + waitpid ($cmdpid, 0); + chomp @results; + if ($results[0] =~ /^${reversed_ip}.+"(.*)"$/) {$abuse = $1} + alarm(0); + }; + alarm(0); + if ($cmdpid =~ /\d+/ and $cmdpid > 1 and kill(0,$cmdpid)) {kill(9,$cmdpid)} + + if ($abuse ne "") { + my $msg = $abusemsg; + $msg =~ s/\[ip\]/$ip/g; + $msg =~ s/\[contact\]/$abuse/g; + return $abuse, $msg; + } + } + } +} +# end abuseip +############################################################################### + +1; diff --git a/src/redux/ConfigServer/CheckIP.pm b/src/redux/ConfigServer/CheckIP.pm new file mode 100644 index 000000000..c34fc4f73 --- /dev/null +++ b/src/redux/ConfigServer/CheckIP.pm @@ -0,0 +1,147 @@ +############################################################################### +# Copyright 2006-2023, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +## no critic (RequireUseWarnings, ProhibitExplicitReturnUndef, ProhibitMixedBooleanOperators, RequireBriefOpen) +# start main +package ConfigServer::CheckIP; + +use strict; +use lib '/usr/local/csf/lib'; +use Carp; +use Net::IP; +use ConfigServer::Config; + +use Exporter qw(import); +our $VERSION = 1.03; +our @ISA = qw(Exporter); +our @EXPORT_OK = qw(checkip cccheckip); + +my $ipv4reg = ConfigServer::Config->ipv4reg; +my $ipv6reg = ConfigServer::Config->ipv6reg; + +# end main +############################################################################### +# start checkip +sub checkip { + my $ipin = shift; + my $ret = 0; + my $ipref = 0; + my $ip; + my $cidr; + if (ref $ipin) { + ($ip,$cidr) = split(/\//,${$ipin}); + $ipref = 1; + } else { + ($ip,$cidr) = split(/\//,$ipin); + } + my $testip = $ip; + + if ($cidr ne "") { + unless ($cidr =~ /^\d+$/) {return 0} + } + + if ($ip =~ /^$ipv4reg$/) { + $ret = 4; + if ($cidr) { + unless ($cidr >= 1 && $cidr <= 32) {return 0} + } + if ($ip eq "127.0.0.1") {return 0} + } + + if ($ip =~ /^$ipv6reg$/) { + $ret = 6; + if ($cidr) { + unless ($cidr >= 1 && $cidr <= 128) {return 0} + } + $ip =~ s/://g; + $ip =~ s/^0*//g; + if ($ip == 1) {return 0} + if ($ipref) { + eval { + local $SIG{__DIE__} = undef; + my $netip = Net::IP->new($testip); + my $myip = $netip->short(); + if ($myip ne "") { + if ($cidr eq "") { + ${$ipin} = $myip; + } else { + ${$ipin} = $myip."/".$cidr; + } + } + }; + if ($@) {return 0} + } + } + + return $ret; +} +# end checkip +############################################################################### +# start cccheckip +sub cccheckip { + my $ipin = shift; + my $ret = 0; + my $ipref = 0; + my $ip; + my $cidr; + if (ref $ipin) { + ($ip,$cidr) = split(/\//,${$ipin}); + $ipref = 1; + } else { + ($ip,$cidr) = split(/\//,$ipin); + } + my $testip = $ip; + + if ($cidr ne "") { + unless ($cidr =~ /^\d+$/) {return 0} + } + + if ($ip =~ /^$ipv4reg$/) { + $ret = 4; + if ($cidr) { + unless ($cidr >= 1 && $cidr <= 32) {return 0} + } + if ($ip eq "127.0.0.1") {return 0} + my $type; + eval { + local $SIG{__DIE__} = undef; + my $netip = Net::IP->new($testip); + $type = $netip->iptype(); + }; + if ($@) {return 0} + if ($type ne "PUBLIC") {return 0} + } + + if ($ip =~ /^$ipv6reg$/) { + $ret = 6; + if ($cidr) { + unless ($cidr >= 1 && $cidr <= 128) {return 0} + } + $ip =~ s/://g; + $ip =~ s/^0*//g; + if ($ip == 1) {return 0} + if ($ipref) { + eval { + local $SIG{__DIE__} = undef; + my $netip = Net::IP->new($testip); + my $myip = $netip->short(); + if ($myip ne "") { + if ($cidr eq "") { + ${$ipin} = $myip; + } else { + ${$ipin} = $myip."/".$cidr; + } + } + }; + if ($@) {return 0} + } + } + + return $ret; +} +# end cccheckip +############################################################################### + +1; \ No newline at end of file diff --git a/src/redux/ConfigServer/CloudFlare.pm b/src/redux/ConfigServer/CloudFlare.pm new file mode 100644 index 000000000..22365fc43 --- /dev/null +++ b/src/redux/ConfigServer/CloudFlare.pm @@ -0,0 +1,520 @@ +############################################################################### +# Copyright 2006-2023, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# no critic (RequireUseWarnings, ProhibitExplicitReturnUndef, ProhibitMixedBooleanOperators, RequireBriefOpen) +# start main +package ConfigServer::CloudFlare; + +use strict; +use lib '/usr/local/csf/lib'; +use Carp; +use Fcntl qw(:DEFAULT :flock); +use JSON::Tiny(); +use LWP::UserAgent; +use Time::Local(); +use ConfigServer::Config; +use ConfigServer::Slurp qw(slurp); +use ConfigServer::Logger qw(logfile); + +use Exporter qw(import); +our $VERSION = 1.00; +our @ISA = qw(Exporter); +our @EXPORT_OK = qw(); + +my $config = ConfigServer::Config->loadconfig(); +my %config = $config->config(); + +my $slurpreg = ConfigServer::Slurp->slurpreg; +my $cleanreg = ConfigServer::Slurp->cleanreg; + +my %args; +$args{"content-type"} = "application/json"; + +if ($config{DEBUG} >= 2) { + require Data::Dumper; + import Data::Dumper; +} + +if (-e "/usr/local/cpanel/version") { + require YAML::Tiny; +} + +# end main +############################################################################### +# start action +sub action { + my $action = shift; + my $ip = shift; + my $mode = shift; + my $id = shift; + my $domainlist = shift; + my $allowany = shift; + + my $status; + my $return; + + if ($config{DEBUG} == 1) {logfile("Debug: CloudFlare - [$action] [$ip] [$mode] [$id] [$domainlist] [$allowany]")} + unless ($config{URLGET}) { + logfile("CloudFlare: URLGET must be set to 1 to use LWP for this feature"); + return; + } + + if ($action eq "remove") { + my @newfile; + sysopen (my $TEMP, "/var/lib/csf/cloudflare.temp", O_RDWR | O_CREAT); + flock($TEMP, LOCK_EX); + my $hit; + while (my $line = <$TEMP>) { + chomp $line; + my ($rip,$mode,$user,$raccount,$rapikey,$rid,$time) = split(/\|/,$line); + + if ($ip eq $rip) { + $args{"X-Auth-Email"} = $raccount; + $args{"X-Auth-Key"} = $rapikey; + + $status = &remove($ip,$mode,$rid); + logfile($status." ($user)"); + $hit = 1; + } else { + push @newfile, $line; + } + } + if ($hit) { + seek ($TEMP, 0, 0); + truncate ($TEMP, 0); + foreach my $line (@newfile) { + print $TEMP $line."\n"; + } + } + close ($TEMP); + } else { + my %authlist; + my %domains; + foreach my $domain (split(/\,/,$domainlist)) { + $domain =~ s/\s//g; + if ($domain eq "") {next} + $domain =~ s/^www\.//; + $domains{$domain} = 1; + } + + my $scope = &getscope(); + + foreach my $user (keys %{$scope->{user}}) { + if ($allowany and ($scope->{user}{$user}{domain} eq "any" or $scope->{user}{$user}{any})) { + $authlist{$scope->{user}{$user}{account}}{apikey} = $scope->{user}{$user}{apikey}; + $authlist{$scope->{user}{$user}{account}}{user} = $user; + } + + foreach my $domain (keys %domains) { + if ($scope->{domain}{$domain}{user} eq $user) { + $authlist{$scope->{domain}{$domain}{account}}{apikey} = $scope->{domain}{$domain}{apikey}; + $authlist{$scope->{domain}{$domain}{account}}{user} = $scope->{domain}{$domain}{user}; + } + foreach my $userdomain (keys %{$scope->{user}{$user}{domain}}) { + if ($user eq $domain and $scope->{user}{$user}{domain}{$userdomain} ne "") { + $authlist{$scope->{user}{$user}{account}}{apikey} = $scope->{user}{$user}{apikey}; + $authlist{$scope->{user}{$user}{account}}{user} = $user; + } + } + } + } + + my @list; + foreach my $account (sort keys %authlist) { + $args{"X-Auth-Email"} = $account; + $args{"X-Auth-Key"} = $authlist{$account}{apikey}; + my $user = $authlist{$account}{user}; + + if ($action eq "deny") { + my ($id,$status) = &block($ip); + logfile($status." ($user)"); + sysopen (my $TEMP, "/var/lib/csf/cloudflare.temp", O_WRONLY | O_APPEND | O_CREAT); + flock($TEMP, LOCK_EX); + print $TEMP "$ip|$mode|$user|$account|$authlist{$account}{apikey}|$id|".time."\n"; + close ($TEMP); + } + elsif ($action eq "allow") { + my ($id,$status) = &whitelist($ip); + logfile($status." ($user)"); + sysopen (my $TEMP, "/var/lib/csf/cloudflare.temp", O_WRONLY | O_APPEND | O_CREAT); + flock($TEMP, LOCK_EX); + print $TEMP "$ip|$mode|$user|$account|$authlist{$account}{apikey}|$id|".time."\n"; + close ($TEMP); + } + elsif ($action eq "del") { + my $status = &remove($ip,$mode); + print "csf - $status ($user)\n"; + } + elsif ($action eq "add") { + my $id; + my $status; + if ($mode eq "block") {($id,$status) = &block($ip)} + if ($mode eq "challenge") {($id,$status) = &challenge($ip)} + if ($mode eq "whitelist") {($id,$status) = &whitelist($ip)} + print "csf - $status ($user)\n"; + } + elsif ($action eq "getlist") { + push @list, &getlist($user); + } + } + if ($action eq "getlist") {return @list} + } + + return; +} +# end action +############################################################################### +# start block +sub block { + my $ip = shift; + my $target = &checktarget($ip); + + my $block->{mode} = $config{CF_BLOCK}; + $block->{configuration}->{target} = $target; + $block->{configuration}->{value} = $ip; + $block->{notes} = "csf $config{CF_BLOCK}"; + + my $content; + eval { + local $SIG{__DIE__} = undef; + $content = JSON::Tiny::encode_json($block); + }; + + my $ua = LWP::UserAgent->new; + my $res = $ua->post('https://api.cloudflare.com/client/v4/user/firewall/access_rules/rules', %args, Content => $content); + + if ($res->is_success) { + my $id = JSON::Tiny::decode_json($res->content); + return $id->{result}->{id},"CloudFlare: $config{CF_BLOCK} $target $ip"; + } else { + if ($config{DEBUG} == 1) {print "Debug: ".$res->content."\n"} + elsif ($config{DEBUG} >= 2) { + eval { + local $SIG{__DIE__} = undef; + print Dumper(JSON::Tiny::decode_json($res->content)); + }; + } + return "CloudFlare: [$ip] $config{CF_BLOCK} failed: ".$res->status_line; + } +} +# end block +############################################################################### +# start whitelist +sub whitelist { + my $ip = shift; + my $target = &checktarget($ip); + + my $whitelist->{mode} = "whitelist"; + $whitelist->{configuration}->{target} = $target; + $whitelist->{configuration}->{value} = $ip; + $whitelist->{notes} = "csf whitelist"; + + my $content; + eval { + local $SIG{__DIE__} = undef; + $content = JSON::Tiny::encode_json($whitelist); + }; + + my $ua = LWP::UserAgent->new; + my $res = $ua->post('https://api.cloudflare.com/client/v4/user/firewall/access_rules/rules', %args, Content => $content); + + if ($res->is_success) { + my $id = JSON::Tiny::decode_json($res->content); + return $id->{result}->{id}, "CloudFlare: whitelisted $target $ip"; + } else { + if ($config{DEBUG} == 1) {print "Debug: ".$res->content."\n"} + elsif ($config{DEBUG} >= 2) { + eval { + local $SIG{__DIE__} = undef; + print Dumper(JSON::Tiny::decode_json($res->content)); + }; + } + return "CloudFlare: [$ip] whitelist failed: ".$res->status_line; + } +} +# end whitelist +############################################################################### +# start challenge +sub challenge { + my $ip = shift; + my $target = &checktarget($ip); + + my $challenge->{mode} = "challenge"; + $challenge->{configuration}->{target} = $target; + $challenge->{configuration}->{value} = $ip; + $challenge->{notes} = "csf challenge"; + + my $content; + eval { + local $SIG{__DIE__} = undef; + $content = JSON::Tiny::encode_json($challenge); + }; + + my $ua = LWP::UserAgent->new; + my $res = $ua->post('https://api.cloudflare.com/client/v4/user/firewall/access_rules/rules', %args, Content => $content); + + if ($res->is_success) { + my $id = JSON::Tiny::decode_json($res->content); + return $id->{result}->{id}, "CloudFlare: challenged $target $ip"; + } else { + if ($config{DEBUG} == 1) {print "Debug: ".$res->content."\n"} + elsif ($config{DEBUG} >= 2) { + eval { + local $SIG{__DIE__} = undef; + print Dumper(JSON::Tiny::decode_json($res->content)); + }; + } + return "CloudFlare: [$ip] challenge failed: ".$res->status_line; + } +} +# end challenge +############################################################################### +# start add +sub add { + my $ip = shift; + my $mode = shift; + my $target = &checktarget($ip); + + my $add->{mode} = $mode; + $add->{configuration}->{target} = $target; + $add->{configuration}->{value} = $ip; + + my $content; + eval { + local $SIG{__DIE__} = undef; + $content = JSON::Tiny::encode_json($add); + }; + + my $ua = LWP::UserAgent->new; + my $res = $ua->post('https://api.cloudflare.com/client/v4/user/firewall/access_rules/rules', %args, Content => $content); + + if ($res->is_success) { + my $id = JSON::Tiny::decode_json($res->content); + return $id->{result}->{id}, "CloudFlare: $mode added $target $ip"; + } else { + if ($config{DEBUG} == 1) {print "Debug: ".$res->content."\n"} + elsif ($config{DEBUG} >= 2) { + eval { + local $SIG{__DIE__} = undef; + print Dumper(JSON::Tiny::decode_json($res->content)); + }; + } + return "CloudFlare: [$ip] $mode failed: ".$res->status_line; + } +} +# end whitelist +############################################################################### +# start remove +sub remove { + my $ip = shift; + my $mode = shift; + my $id = shift; + my $target = &checktarget($ip); + + if ($id eq "") { + $id = getid($ip,$mode); + if ($id =~ /CloudFlare:/) {return $id} + if ($id eq "") {return "CloudFlare: [$ip] remove failed: id not found"} + } + + my $ua = LWP::UserAgent->new; + my $res = $ua->delete('https://api.cloudflare.com/client/v4/user/firewall/access_rules/rules/'.$id, %args); + + if ($res->is_success) { + return "CloudFlare: removed $target $ip"; + } else { + if ($config{DEBUG} == 1) {print "Debug: ".$res->content."\n"} + elsif ($config{DEBUG} >= 2) { + eval { + local $SIG{__DIE__} = undef; + print Dumper(JSON::Tiny::decode_json($res->content)); + }; + } + return "CloudFlare: [$ip] [$id] remove failed: ".$res->status_line; + } +} +# end remove +############################################################################### +# start getid +sub getid { + my $ip = shift; + my $mode = shift; + my $target = &checktarget($ip); + + my $ua = LWP::UserAgent->new; + my $res = $ua->get('https://api.cloudflare.com/client/v4/user/firewall/access_rules/rules?page=1&per_page=100&configuration.target='.$target.'&configuration.value='.$ip.'&match=all&order=mode&direction=desc', %args); + + if ($res->is_success) { + my $result = JSON::Tiny::decode_json($res->content); + my $entry = @{$result->{result}}[0]; + return $entry->{id}; + } else { + if ($config{DEBUG} == 1) {print "Debug: ".$res->content."\n"} + elsif ($config{DEBUG} >= 2) { + eval { + local $SIG{__DIE__} = undef; + print Dumper(JSON::Tiny::decode_json($res->content)); + }; + } + return "CloudFlare: [$ip] id [$mode] failed: ".$res->status_line; + } +} +# end getid +############################################################################### +# start getlist +sub getlist { + my $domain = shift; + + my %ips; + my $page = 1; + my $pages = 1; + my $result; + + my $ua = LWP::UserAgent->new; + + while (1) { + my $res = $ua->get('https://api.cloudflare.com/client/v4/user/firewall/access_rules/rules?page='.$page.'&per_page=100&order=created_on&direction=asc&match=all', %args); + if ($res->is_success) { + my $result = JSON::Tiny::decode_json($res->content); + + $pages = $result->{result_info}->{total_pages}; + foreach my $entry (@{$result->{result}}) { + if ($entry->{configuration}->{target} eq "ip" or $entry->{configuration}->{target} eq "country" or $entry->{configuration}->{target} eq "ip_range") { + my ($date, $time) = split /T/ => $entry->{created_on}; + my ($year, $mon, $mday) = split /-/ => $date; + $year -= 1900; + $mon -= 1; + my ($hour, $min, $sec) = split /:/ => $time; + my $timelocal = Time::Local::timelocal($sec, $min, $hour, $mday, $mon, $year); + + $ips{$entry->{configuration}->{value}}{notes} = $entry->{notes}; + $ips{$entry->{configuration}->{value}}{mode} = $entry->{mode}; + $ips{$entry->{configuration}->{value}}{created_on} = $timelocal; + $ips{$entry->{configuration}->{value}}{domain} = $domain; + $ips{$entry->{configuration}->{value}}{success} = 1; + } + } + } else { + if ($config{DEBUG} >= 2) { + eval { + local $SIG{__DIE__} = undef; + print Dumper(JSON::Tiny::decode_json($res->content)); + }; + } + $ips{$domain}{success} = 0; + $ips{$domain}{domain} = "CloudFlare: list failed for ($domain): ".$res->status_line; + return \%ips; + } + $page++; + if ($pages < $page) {last} + } + return \%ips; +} +# end getlist +############################################################################### +# start getscope +sub getscope { + my %scope; + my %disabled; + my %any; + my @entries = slurp("/etc/csf/csf.cloudflare"); + 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 @setting = split(/\:/,$line); + + if ($setting[0] eq "DOMAIN") { + my $domain = $setting[1]; + my $user = $setting[3]; + my $account = $setting[5]; + my $apikey = $setting[7]; + + $scope{domain}{$domain}{account} = $account; + $scope{domain}{$domain}{apikey} = $apikey; + $scope{domain}{$domain}{user} = $user; + $scope{user}{$user}{account} = $account; + $scope{user}{$user}{apikey} = $apikey; + $scope{user}{$user}{domain}{$domain} = $domain; + if ($domain eq "any") {$scope{user}{$user}{any} = 1} + } + if ($setting[0] eq "DISABLE") { + $disabled{$setting[1]} = 1; + } + if ($setting[0] eq "ANY") { + $any{$setting[1]} = 1; + } + } + if ($config{CF_CPANEL}) { + my %userdomains; + my %accounts; + my %creds; + + open (my $IN, "<","/etc/userdomains"); + flock ($IN, LOCK_SH); + my @localusers = <$IN>; + close ($IN); + chomp @localusers; + foreach my $line (@localusers) { + my ($domain,$user) = split(/\:\s*/,$line,2); + $userdomains{$domain} = $user; + $accounts{$user} = 1; + } + + foreach my $user (keys %accounts) { + if ($disabled{$user}) {next} + my $userhome = (getpwnam($user))[7]; + + if (-e "$userhome/.cpanel/datastore/cloudflare_data.yaml") { + my $yaml = YAML::Tiny->read("$userhome/.cpanel/datastore/cloudflare_data.yaml"); + if ($yaml->[0]->{client_api_key} ne "") { + $creds{$user}{account} = $yaml->[0]->{cloudflare_email}; + $creds{$user}{apikey} = $yaml->[0]->{client_api_key}; + } + } + } + + foreach my $domain (keys %userdomains) { + my $user = $userdomains{$domain}; + if ($disabled{$user}) {next} + if ($creds{$user}{apikey} ne "") { + $scope{domain}{$domain}{account} = $creds{$user}{account}; + $scope{domain}{$domain}{apikey} = $creds{$user}{apikey}; + $scope{domain}{$domain}{user} = $user; + $scope{user}{$user}{account} = $creds{$user}{account}; + $scope{user}{$user}{apikey} = $creds{$user}{apikey}; + $scope{user}{$user}{domain}{$domain} = $domain; + if ($any{$user}) { + $scope{domain}{any}{account} = $creds{$user}{account}; + $scope{domain}{any}{apikey} = $creds{$user}{apikey}; + $scope{domain}{any}{user} = $user; + $scope{user}{$user}{domain}{any} = "any"; + $scope{user}{$user}{any} = 1; + } + } + } + } + return \%scope; +} +# end getscope +############################################################################### +# start checktarget +sub checktarget { + my $arg = shift; + if ($arg =~ /^\w\w$/) {return "country"} + elsif ($arg =~ /\/16$/) {return "ip_range"} + elsif ($arg =~ /\/24$/) {return "ip_range"} + else {return "ip"} +} +# end checktarget +############################################################################### +1; diff --git a/src/redux/ConfigServer/Config.pm b/src/redux/ConfigServer/Config.pm new file mode 100644 index 000000000..70495f456 --- /dev/null +++ b/src/redux/ConfigServer/Config.pm @@ -0,0 +1,437 @@ +############################################################################### +# Copyright 2006-2023, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +## no critic (RequireUseWarnings, ProhibitExplicitReturnUndef, ProhibitMixedBooleanOperators, RequireBriefOpen) +# start main +package ConfigServer::Config; + +use strict; +use lib '/usr/local/csf/lib'; +use version; +use Fcntl qw(:DEFAULT :flock); +use Carp; +use IPC::Open3; +use ConfigServer::Slurp qw(slurp); + +use Exporter qw(import); +our $VERSION = 1.05; +our @ISA = qw(Exporter); +our @EXPORT_OK = qw(); + +our $ipv4reg = qr/(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/; +our $ipv6reg = qr/((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?/; + +my %config; +my %configsetting; +my $warning; +my $version; + +my $slurpreg = ConfigServer::Slurp->slurpreg; +my $cleanreg = ConfigServer::Slurp->cleanreg; +my $configfile = "/etc/csf/csf.conf"; + +# end main +############################################################################### +# start loadconfig +sub loadconfig { + my $class = shift; + my $self = {}; + bless $self,$class; + + if (%config) { + $self->{warning} = $warning; + return $self; + } + + undef %configsetting; + undef %config; + undef $warning; + + my @file = slurp($configfile); + foreach my $line (@file) { + $line =~ s/$cleanreg//g; + if ($line =~ /^(\s|\#|$)/) {next} + if ($line !~ /=/) {next} + my ($name,$value) = split (/=/,$line,2); + $name =~ s/\s//g; + if ($value =~ /\"(.*)\"/) { + $value = $1; + } else { + croak "*Error* Invalid configuration line [$line] in $configfile"; + } + if ($configsetting{$name}) { + croak "*Error* Setting $name is repeated in $configfile - you must remove the duplicates and then restart csf and lfd"; + } + $config{$name} = $value; + $configsetting{$name} = 1; + } + + if ($config{LF_IPSET}) { + unless ($config{LF_IPSET_HASHSIZE}) { + $config{LF_IPSET_HASHSIZE} = "1024"; + $configsetting{LF_IPSET_HASHSIZE} = 1; + } + unless ($config{LF_IPSET_MAXELEM}) { + $config{LF_IPSET_MAXELEM} = "65536"; + $configsetting{LF_IPSET_MAXELEM} = 1; + } + } + + if ($config{USE_FTPHELPER} eq "1") { + $warning .= "USE_FTPHELPER should be set to your FTP server port (21), not 1. USE_FTPHELPER has been disabled\n"; + $config{USE_FTPHELPER} = 0; + } + + if ($config{IPTABLES} eq "" or !(-x $config{IPTABLES})) { + croak "*Error* The path to iptables is either not set or incorrect for IPTABLES [$config{IPTABLES}] in /etc/csf/csf.conf"; + } + + if (-e "/proc/sys/net/netfilter/nf_conntrack_helper" and !$config{USE_FTPHELPER}) { + my $setting = slurp("/proc/sys/net/netfilter/nf_conntrack_helper"); + chomp $setting; + + if ($setting == 0) { + open (my $PROC, ">", "/proc/sys/net/netfilter/nf_conntrack_helper"); + print $PROC "1\n"; + close $PROC; + } + } + + if ($config{WAITLOCK}) {$config{IPTABLESWAIT} = "--wait";} + my @results = &systemcmd("$config{IPTABLES} $config{IPTABLESWAIT} --version"); + if ($results[0] =~ /iptables v(\d+\.\d+\.\d+)/) { + $version = $1; + + $config{IPTABLESWAIT} = ""; + if ($config{WAITLOCK}) { + my @ipdata; + 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, "$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 ($@ eq "alarm\n") { + croak "*ERROR* Timeout after $config{WAITLOCK_TIMEOUT} seconds for iptables --wait - WAITLOCK\n"; + } + if ($ipdata[0] =~ /^Chain OUTPUT/) { + $config{IPTABLESWAIT} = "--wait"; + } else { + $warning .= "*WARNING* This version of iptables does not support the --wait option - disabling WAITLOCK\n"; + $config{WAITLOCK} = 0; + } + } + } else { + $warning .= "*WARNING* Unable to detect iptables version [$results[0]]\n"; + } + + if ($config{CC_LOOKUPS} and $config{CC_LOOKUPS} != 4 and $config{CC_SRC} eq "1") { + if ($config{MM_LICENSE_KEY} eq "") { + $warning .= "*ERROR*: Country Code Lookups setting MM_LICENSE_KEY must be set in /etc/csf/csf.conf to continue using the MaxMind databases\n"; + } + } + if ($config{CC_DENY} or $config{CC_ALLOW} or $config{CC_ALLOW_FILTER} or $config{CC_ALLOW_PORTS} or $config{CC_DENY_PORTS} or $config{CC_ALLOW_SMTPAUTH}) { + if ($config{MM_LICENSE_KEY} eq "" and $config{CC_SRC} eq "1") { + $warning .= "*ERROR*: Country Code Filters setting MM_LICENSE_KEY must be set in /etc/csf/csf.conf to continue updating the MaxMind databases\n"; + } + } + + if ($config{DROP_OUT} ne "DROP") { + my @data = &systemcmd("$config{IPTABLES} $config{IPTABLESWAIT} -N TESTDENY"); + unless ($data[0] =~ /^iptables/) { + my @ipdata = &systemcmd("$config{IPTABLES} $config{IPTABLESWAIT} -I TESTDENY -j $config{DROP_OUT}"); + if ($ipdata[0] =~ /^iptables/) { + $warning .= "*WARNING* Cannot use DROP_OUT value of [$config{DROP_OUT}] on this server, set to DROP\n"; + $config{DROP_OUT} = "DROP"; + } + &systemcmd("$config{IPTABLES} $config{IPTABLESWAIT} -F TESTDENY"); + &systemcmd("$config{IPTABLES} $config{IPTABLESWAIT} -X TESTDENY"); + } + } + my @raw = &systemcmd("$config{IPTABLES} $config{IPTABLESWAIT} -L PREROUTING -t raw"); + if ($raw[0] =~ /^Chain PREROUTING/) {$config{RAW} = 1} else {$config{RAW} = 0} + my @mangle = &systemcmd("$config{IPTABLES} $config{IPTABLESWAIT} -L PREROUTING -t mangle"); + if ($mangle[0] =~ /^Chain PREROUTING/) {$config{MANGLE} = 1} else {$config{MANGLE} = 0} + + if ($config{IPV6} and -x $config{IP6TABLES} and $version) { + if ($config{USE_CONNTRACK} and version->parse($version) <= version->parse("1.3.5")) {$config{USE_CONNTRACK} = 0} + if ($config{PORTFLOOD} and version->parse($version) >= version->parse("1.4.3")) {$config{PORTFLOOD6} = 1} + if ($config{CONNLIMIT} and version->parse($version) >= version->parse("1.4.3")) {$config{CONNLIMIT6} = 1} + if ($config{MESSENGER} and version->parse($version) >= version->parse("1.4.17")) {$config{MESSENGER6} = 1} + if ($config{SMTP_REDIRECT} and version->parse($version) >= version->parse("1.4.17")) {$config{SMTP_REDIRECT6} = 1} + my @ipdata = &systemcmd("$config{IP6TABLES} $config{IPTABLESWAIT} -t nat -L POSTROUTING -nv"); + if ($ipdata[0] =~ /^Chain POSTROUTING/) { + $config{NAT6} = 1; + } + elsif (version->parse($version) >= version->parse("1.4.17")) { + if ($config{SMTP_REDIRECT}) { + $warning .= "*WARNING* ip6tables nat table not present - disabling SMTP_REDIRECT for IPv6\n"; + $config{SMTP_REDIRECT6} = 0; + } + if ($config{MESSENGER}) { + $warning .= "*WARNING* ip6tables nat table not present - disabling MESSENGER Service for IPv6\n"; + $config{MESSENGER6} = 0; + } + if ($config{DOCKER} and $config{DOCKER_NETWORK6} ne "") { + $warning .= "*WARNING* ip6tables nat table not present - disabling DOCKER for IPv6\n"; + } + } + my @raw = &systemcmd("$config{IP6TABLES} $config{IPTABLESWAIT} -L PREROUTING -t raw"); + if ($raw[0] =~ /^Chain PREROUTING/) {$config{RAW6} = 1} else {$config{RAW6} = 0} + my @mangle = &systemcmd("$config{IP6TABLES} $config{IPTABLESWAIT} -L PREROUTING -t mangle"); + if ($mangle[0] =~ /^Chain PREROUTING/) {$config{MANGLE6} = 1} else {$config{MANGLE6} = 0} + } + elsif ($config{IPV6}) { + $warning .= "*WARNING* incorrect ip6tables binary location [$config{IP6TABLES}] - IPV6 disabled\n"; + $config{IPV6} = 0; + } + + if (!$config{GENERIC} and -e "/var/cpanel/dnsonly") {$config{DNSONLY} = 1} + + if (-e "/var/cpanel/smtpgidonlytweak" and !$config{GENERIC}) { + if ($config{DNSONLY}) { + $warning .= "*WARNING* The cPanel option to 'Restrict outgoing SMTP to root, exim, and mailman' is incompatible with this firewall. The option must be disabled using \"/usr/local/cpanel/scripts/smtpmailgidonly off\" and the SMTP_BLOCK alternative in csf used instead\n"; + } else { + $warning .= "*WARNING* The option \"WHM > Tweak Settings > Restrict outgoing SMTP to root, exim, and mailman (FKA SMTP Tweak)\" is incompatible with this firewall. The option must be disabled in WHM and the SMTP_BLOCK alternative in csf used instead\n"; + } + } + if (-e "/proc/vz/veinfo") {$config{VPS} = 1} + else { + foreach my $line (slurp("/proc/self/status")) { + $line =~ s/$cleanreg//g; + if ($line =~ /^envID:\s*(\d+)\s*$/) { + if ($1 > 0) { + $config{VPS} = 1; + last; + } + } + } + } + if ($config{DROP_IP_LOGGING} and $config{PS_INTERVAL}) { + $warning .= "*WARNING* Cannot use PS_INTERVAL with DROP_IP_LOGGING enabled. DROP_IP_LOGGING disabled\n"; + $config{DROP_IP_LOGGING} = 0; + } + + if ($config{FASTSTART}) { + unless (-x $config{IPTABLES_RESTORE}) { + $warning .= "*WARNING* Unable to use FASTSTART as [$config{IPTABLES_RESTORE}] is not executable or does not exist\n"; + $config{FASTSTART} = 0; + } + if ($config{IPV6}) { + unless (-x $config{IP6TABLES_RESTORE}) { + $warning .= "*WARNING* Unable to use FASTSTART as (IPv6) [$config{IP6TABLES_RESTORE}] is not executable or does not exist\n"; + $config{FASTSTART} = 0; + } + } + } + + if ($config{MESSENGER}) { + if ($config{MESSENGERV2}) { + if (!-e "/etc/cpanel/ea4/is_ea4") { + $warning .= "*WARNING* EA4 is not in use - disabling MESSENGERV2 and MESSENGER HTTPS Service\n"; + $config{MESSENGERV2} = "0"; + $config{MESSENGER_HTTPS_IN} = ""; + $config{MESSENGER_HTTPS_DISABLED} = "*WARNING* EA4 is not in use - disabling MESSENGERV2 and MESSENGER HTTPS Service"; + } + } + if ($config{MESSENGER_HTTPS_IN} and (!$config{MESSENGERV2} or $config{MESSENGER_HTTPS_DISABLED})) { + eval { + local $SIG{__DIE__} = undef; + require IO::Socket::SSL; + }; + if ($@) { + $warning .= "*WARNING* Perl module IO::Socket::SSL missing - disabling MESSENGER HTTPS Service\n"; + $config{MESSENGER_HTTPS_IN} = ""; + $config{MESSENGER_HTTPS_DISABLED} = "*WARNING* Perl module IO::Socket::SSL missing - disabling MESSENGER HTTPS Service"; + } + elsif (version->parse($IO::Socket::SSL::VERSION) < version->parse("1.83")) { + $warning .= "*WARNING* Perl module IO::Socket::SSL v$IO::Socket::SSL::VERSION does not support SNI - disabling MESSENGER HTTPS Service\n"; + $config{MESSENGER_HTTPS_IN} = ""; + $config{MESSENGER_HTTPS_DISABLED} = "*WARNING* Perl module IO::Socket::SSL v$IO::Socket::SSL::VERSION does not support SNI - disabling MESSENGER HTTPS Service"; + } + } + my $pcnt = 0; + foreach my $port (split(/\,/,$config{MESSENGER_HTML_IN})) { + $pcnt++; + } + if ($pcnt > 15) { + $warning .= "*WARNING* MESSENGER_HTML_IN contains more than 15 ports - disabling MESSENGER Service\n"; + $config{MESSENGER} = 0; + } else { + $pcnt = 0; + foreach my $port (split(/\,/,$config{MESSENGER_TEXT_IN})) { + $pcnt++; + } + if ($pcnt > 15) { + $warning .= "*WARNING* MESSENGER_TEXT_IN contains more than 15 ports - disabling MESSENGER Service\n"; + $config{MESSENGER} = 0; + } else { + $pcnt = 0; + foreach my $port (split(/\,/,$config{MESSENGER_HTTPS_IN})) { + $pcnt++; + } + if ($pcnt > 15) { + $warning .= "*WARNING* MESSENGER_HTTPS_IN contains more than 15 ports - disabling MESSENGER Service\n"; + $config{MESSENGER} = 0; + } + } + } + } + + if ($config{IPV6} and $config{IPV6_SPI}) { + 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 > 6)) or (($maj > 1) and ($mid > 5) and ($min > 19))) { + } else { + $warning .= "*WARNING* Kernel $data[0] may not support an ip6tables SPI firewall. You should set IPV6_SPI to \"0\" in /etc/csf/csf.conf\n\n"; + } + } + } + + if (($config{CLUSTER_SENDTO} or $config{CLUSTER_RECVFROM})) { + if (-f $config{CLUSTER_SENDTO}) { + if ($config{DEBUG} >= 1) {$warning .= "*DEBUG* CLUSTER_SENDTO retrieved from $config{CLUSTER_SENDTO} and set to: "} + $config{CLUSTER_SENDTO} = join(",", slurp($config{CLUSTER_SENDTO})); + if ($config{DEBUG} >= 1) {$warning .= "[$config{CLUSTER_SENDTO}]\n"} + } + if (-f $config{CLUSTER_RECVFROM}) { + if ($config{DEBUG} >= 1) {$warning .= "*DEBUG* CLUSTER_RECVFROM retrieved from $config{CLUSTER_RECVFROM} and set to: "} + $config{CLUSTER_RECVFROM} = join(",", slurp($config{CLUSTER_RECVFROM})); + if ($config{DEBUG} >= 1) {$warning .= "[$config{CLUSTER_RECVFROM}]\n"} + } + } + + my @ipdata = &systemcmd("$config{IPTABLES} $config{IPTABLESWAIT} -t nat -L POSTROUTING -nv"); + if ($ipdata[0] =~ /^Chain POSTROUTING/) { + $config{NAT} = 1; + } else { + if ($config{MESSENGER}) { + $warning .= "*WARNING* iptables nat table not present - disabling MESSENGER Service\n"; + $config{MESSENGER} = 0; + } + } + + if ($config{PT_USERKILL}) { + $warning .= "*WARNING* PT_USERKILL should not normally be enabled as it can easily lead to legitimate processes being terminated, use csf.pignore instead\n"; + } + + $config{cc_src} = "MaxMind"; + $config{asn_src} = "MaxMind"; + $config{cc_country} = "https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-Country-CSV&suffix=zip&license_key=$config{MM_LICENSE_KEY}"; + $config{cc_city} = "https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-City-CSV&suffix=zip&license_key=$config{MM_LICENSE_KEY}"; + $config{cc_asn} = "https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-ASN-CSV&suffix=zip&license_key=$config{MM_LICENSE_KEY}"; + if ($config{CC_SRC} eq "2") { + $config{cc_src} = "DB-IP"; + $config{asn_src} = "iptoasn.com"; + $config{ccl_src} = "ipdeny.com"; + my ($month,$year) = sub{ 1+shift, 1900+shift }->((localtime time)[4,5]); + $month = sprintf("%02d", $month); + $config{cc_country} = "http://download.db-ip.com/free/dbip-country-lite-$year-$month.csv.gz"; + $config{cc_city} = "http://download.db-ip.com/free/dbip-city-lite-$year-$month.csv.gz"; + $config{cc_asn} = "http://iptoasn.com/data/ip2asn-combined.tsv.gz"; + $config{cc_cc} = "http://download.geonames.org/export/dump/countryInfo.txt"; + } + + $config{DOWNLOADSERVER} = &getdownloadserver; + + $self->{warning} = $warning; + + return $self; +} +# end loadconfig +############################################################################### +# start config +sub config { + return %config; +} +# end config +############################################################################### +# start resetconfig +sub resetconfig { + undef %config; + undef %configsetting; + undef $warning; + + return; +} +# end resetconfig +############################################################################### +# start configsetting +sub configsetting { + return %configsetting; +} +# end configsetting +############################################################################### +# start ipv4reg +sub ipv4reg { + return $ipv4reg; +} +# end ipv4reg +############################################################################### +# start ipv6reg +sub ipv6reg { + return $ipv6reg; +} +# end ipv6reg +############################################################################### +# start systemcmd +sub systemcmd { + my @command = @_; + my @result; + + eval { + my ($childin, $childout); + my $pid = open3($childin, $childout, $childout, @command); + @result = <$childout>; + waitpid ($pid, 0); + chomp @result; + if ($result[0] =~ /# Warning: iptables-legacy tables present/) {shift @result} + }; + + return @result; +} +# end systemcmd +############################################################################### +## start getdownloadserver +sub getdownloadserver { + my @servers; + my $downloadservers = "/etc/csf/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; \ No newline at end of file diff --git a/src/redux/ConfigServer/DisplayResellerUI.pm b/src/redux/ConfigServer/DisplayResellerUI.pm new file mode 100644 index 000000000..d0fddf5c9 --- /dev/null +++ b/src/redux/ConfigServer/DisplayResellerUI.pm @@ -0,0 +1,228 @@ +############################################################################### +# Copyright 2006-2023, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +## no critic (RequireUseWarnings, ProhibitExplicitReturnUndef, ProhibitMixedBooleanOperators, RequireBriefOpen) +package ConfigServer::DisplayResellerUI; + +use strict; +use lib '/usr/local/csf/lib'; +use Fcntl qw(:DEFAULT :flock); +use POSIX qw(:sys_wait_h sysconf strftime); +use File::Basename; +use Net::CIDR::Lite; +use IPC::Open3; + +use ConfigServer::Config; +use ConfigServer::CheckIP qw(checkip); +use ConfigServer::Sendmail; +use ConfigServer::Logger; + +use Exporter qw(import); +our $VERSION = 1.01; +our @ISA = qw(Exporter); +our @EXPORT_OK = qw(); + +umask(0177); + +our ($chart, $ipscidr6, $ipv6reg, $ipv4reg, %config, %ips, $mobile, + %FORM, $script, $script_da, $images, $myv, %rprivs, $hostname, + $hostshort, $tz, $panel); + +# +############################################################################### +# start main +sub main { + my $form_ref = shift; + %FORM = %{$form_ref}; + $script = shift; + $script_da = shift; + $images = shift; + $myv = shift; + + open (my $IN,"<","/etc/csf/csf.resellers"); + flock ($IN, LOCK_SH); + while (my $line = <$IN>) { + my ($user,$alert,$privs) = split(/\:/,$line); + $privs =~ s/\s//g; + foreach my $priv (split(/\,/,$privs)) { + $rprivs{$user}{$priv} = 1; + } + $rprivs{$user}{ALERT} = $alert; + } + close ($IN); + + open (my $HOSTNAME, "<","/proc/sys/kernel/hostname"); + flock ($HOSTNAME, LOCK_SH); + $hostname = <$HOSTNAME>; + chomp $hostname; + close ($HOSTNAME); + $hostshort = (split(/\./,$hostname))[0]; + $tz = strftime("%z", localtime); + + my $config = ConfigServer::Config->loadconfig(); + %config = $config->config(); + + $panel = "cPanel"; + if ($config{GENERIC}) {$panel = "Generic"} + if ($config{INTERWORX}) {$panel = "InterWorx"} + if ($config{DIRECTADMIN}) {$panel = "DirectAdmin"} + + if ($FORM{ip} ne "") {$FORM{ip} =~ s/(^\s+)|(\s+$)//g} + + if ($FORM{action} ne "" and !checkip(\$FORM{ip})) { + print "\n"; + print "
"; + print "[$FORM{ip}] is not a valid IP address\n"; + print "
\n"; + print "

\n"; + } else { + if ($FORM{action} eq "qallow" and $rprivs{$ENV{REMOTE_USER}}{ALLOW}) { + if ($FORM{comment} eq "") { + print "\n"; + print "
You must provide a Comment for this option
\n"; + } else { + $FORM{comment} =~ s/"//g; + print "\n"; + print "
"; + print "

Allowing $FORM{ip}...

\n

\n";
+				my $text = &printcmd("/usr/sbin/csf","-a",$FORM{ip},"ALLOW by Reseller $ENV{REMOTE_USER} ($FORM{comment})");
+				print "

\n

...Done.

\n"; + print "
\n"; + if ($rprivs{$ENV{REMOTE_USER}}{ALERT}) { + open (my $IN, "<", "/usr/local/csf/tpl/reselleralert.txt"); + flock ($IN, LOCK_SH); + my @alert = <$IN>; + close ($IN); + chomp @alert; + + my @message; + foreach my $line (@alert) { + $line =~ s/\[reseller\]/$ENV{REMOTE_USER}/ig; + $line =~ s/\[action\]/ALLOW/ig; + $line =~ s/\[ip\]/$FORM{ip}/ig; + $line =~ s/\[rip\]/$ENV{REMOTE_HOST}/ig; + $line =~ s/\[text\]/Result of ALLOW:\n\n$text/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + } + ConfigServer::Logger::logfile("$panel Reseller [$ENV{REMOTE_USER}]: ALLOW $FORM{ip}"); + } + print "

\n"; + } + elsif ($FORM{action} eq "qdeny" and $rprivs{$ENV{REMOTE_USER}}{DENY}) { + if ($FORM{comment} eq "") { + print "\n"; + print "
You must provide a Comment for this option
\n"; + } else { + $FORM{comment} =~ s/"//g; + print "\n"; + print "
"; + print "

Blocking $FORM{ip}...

\n

\n";
+				my $text = &printcmd("/usr/sbin/csf","-d",$FORM{ip},"DENY by Reseller $ENV{REMOTE_USER} ($FORM{comment})");
+				print "

\n

...Done.

\n"; + print "
\n"; + if ($rprivs{$ENV{REMOTE_USER}}{ALERT}) { + open (my $IN, "<", "/usr/local/csf/tpl/reselleralert.txt"); + flock ($IN, LOCK_SH); + my @alert = <$IN>; + close ($IN); + chomp @alert; + + my @message; + foreach my $line (@alert) { + $line =~ s/\[reseller\]/$ENV{REMOTE_USER}/ig; + $line =~ s/\[action\]/DENY/ig; + $line =~ s/\[ip\]/$FORM{ip}/ig; + $line =~ s/\[rip\]/$ENV{REMOTE_HOST}/ig; + $line =~ s/\[text\]/Result of DENY:\n\n$text/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + } + ConfigServer::Logger::logfile("$panel Reseller [$ENV{REMOTE_USER}]: DENY $FORM{ip}"); + } + print "

\n"; + } + elsif ($FORM{action} eq "qkill" and $rprivs{$ENV{REMOTE_USER}}{UNBLOCK}) { + my $text = ""; + if ($rprivs{$ENV{REMOTE_USER}}{ALERT}) { + my ($childin, $childout); + my $pid = open3($childin, $childout, $childout, "/usr/sbin/csf","-g",$FORM{ip}); + while (<$childout>) {$text .= $_} + waitpid ($pid, 0); + } + print "\n"; + print "
"; + print "

Unblock $FORM{ip}, trying permanent blocks...

\n

\n";
+			my $text1 = &printcmd("/usr/sbin/csf","-dr",$FORM{ip});
+			print "

\n

...Done.

\n"; + print "

Unblock $FORM{ip}, trying temporary blocks...

\n

\n";
+			my $text2 = &printcmd("/usr/sbin/csf","-tr",$FORM{ip});
+			print "

\n

...Done.

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

\n"; + if ($rprivs{$ENV{REMOTE_USER}}{ALERT}) { + open (my $IN, "<", "/usr/local/csf/tpl/reselleralert.txt"); + flock ($IN, LOCK_SH); + my @alert = <$IN>; + close ($IN); + chomp @alert; + + my @message; + foreach my $line (@alert) { + $line =~ s/\[reseller\]/$ENV{REMOTE_USER}/ig; + $line =~ s/\[action\]/UNBLOCK/ig; + $line =~ s/\[ip\]/$FORM{ip}/ig; + $line =~ s/\[rip\]/$ENV{REMOTE_HOST}/ig; + $line =~ s/\[text\]/Result of GREP before UNBLOCK:\n$text\n\nResult of UNBLOCK:\nPermanent:\n$text1\nTemporary:\n$text2\n/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + } + ConfigServer::Logger::logfile("$panel Reseller [$ENV{REMOTE_USER}]: UNBLOCK $FORM{ip}"); + } + elsif ($FORM{action} eq "grep" and $rprivs{$ENV{REMOTE_USER}}{GREP}) { + print "\n"; + print "
"; + print "

Searching for $FORM{ip}...

\n

\n";
+			&printcmd("/usr/sbin/csf","-g",$FORM{ip});
+			print "

\n

...Done.

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

\n"; + } + else { + print "\n"; + print ""; + if ($rprivs{$ENV{REMOTE_USER}}{ALLOW}) {print "\n"} + if ($rprivs{$ENV{REMOTE_USER}}{DENY}) {print "\n"} + if ($rprivs{$ENV{REMOTE_USER}}{UNBLOCK}) {print "\n"} + if ($rprivs{$ENV{REMOTE_USER}}{GREP}) {print "\n"} + print "
csf - ConfigServer Firewall options for $ENV{REMOTE_USER}
Allow IP address through the firewall and add to the allow file (csf.allow).
Comment for Allow: (required)
Block IP address in the firewall and add to the deny file (csf.deny).
Comment for Block: (required)
Remove IP address from the firewall (temp and perm blocks)
Search iptables for IP address

\n"; + } + } + + print "
\n"; + print "
csf: v$myv
"; + print "

©2006-2023, ConfigServer Services (Way to the Web Limited)

\n"; + + return; +} +# end main +############################################################################### +# start printcmd +sub printcmd { + my @command = @_; + my $text; + my ($childin, $childout); + my $pid = open3($childin, $childout, $childout, @command); + while (<$childout>) {print $_ ; $text .= $_} + waitpid ($pid, 0); + return $text; +} +# end printcmd +############################################################################### + +1; diff --git a/src/redux/ConfigServer/DisplayUI.pm b/src/redux/ConfigServer/DisplayUI.pm new file mode 100644 index 000000000..d58961399 --- /dev/null +++ b/src/redux/ConfigServer/DisplayUI.pm @@ -0,0 +1,2941 @@ +############################################################################### +# Copyright 2006-2023, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +## no critic (RequireUseWarnings, ProhibitExplicitReturnUndef, ProhibitMixedBooleanOperators, RequireBriefOpen) +package ConfigServer::DisplayUI; + +use strict; +use lib '/usr/local/csf/lib'; +use Fcntl qw(:DEFAULT :flock); +use File::Basename; +use File::Copy; +use Net::CIDR::Lite; +use IPC::Open3; + +use ConfigServer::Config; +use ConfigServer::CheckIP qw(checkip); +use ConfigServer::Ports; +use ConfigServer::URLGet; +use ConfigServer::Sanity qw(sanity);; +use ConfigServer::ServerCheck; +use ConfigServer::ServerStats; +use ConfigServer::Service; +use ConfigServer::RBLCheck; +use ConfigServer::GetEthDev; +use ConfigServer::Slurp qw(slurp); + +use Exporter qw(import); +our $VERSION = 1.01; +our @ISA = qw(Exporter); +our @EXPORT_OK = qw(); + +umask(0177); + +our ($chart, $ipscidr6, $ipv6reg, $ipv4reg, %config, %ips, $mobile, + $urlget, %FORM, $script, $script_da, $images, $myv); + +my $slurpreg = ConfigServer::Slurp->slurpreg; +my $cleanreg = ConfigServer::Slurp->cleanreg; + +# +############################################################################### +# start main +sub main { + my $form_ref = shift; + %FORM = %{$form_ref}; + $script = shift; + $script_da = shift; + $images = shift; + $myv = shift; + $config{THIS_UI} = shift; + $| = 1; + + $ipscidr6 = Net::CIDR::Lite->new; + + my $thisui = $config{THIS_UI}; + my $config = ConfigServer::Config->loadconfig(); + %config = $config->config; + $config{THIS_UI} = $thisui; + + $ipv4reg = $config->ipv4reg; + $ipv6reg = $config->ipv6reg; + + if ($config{CF_ENABLE}) { + require ConfigServer::CloudFlare; + import ConfigServer::CloudFlare; + } + + $mobile = 0; + if ($FORM{mobi}) {$mobile = 1} + + $chart = 1; + if ($config{ST_ENABLE}) { + if (!defined ConfigServer::ServerStats::init()) {$chart = 0} + } + + $urlget = ConfigServer::URLGet->new($config{URLGET}, "csf/$myv", $config{URLPROXY}); + unless (defined $urlget) { + $config{URLGET} = 1; + $urlget = ConfigServer::URLGet->new($config{URLGET}, "csf/$myv", $config{URLPROXY}); + print "

*WARNING* URLGET set to use LWP but perl module is not installed, reverting to HTTP::Tiny

\n"; + } + + if ($config{RESTRICT_UI} == 2) { + print "\n"; + print "\n"; + print "
csf UI Disabled via the RESTRICT_UI option in /etc/csf/csf.conf
\n"; + exit; + } + + if ($FORM{ip} ne "") {$FORM{ip} =~ s/(^\s+)|(\s+$)//g} + + if (($FORM{ip} ne "") and ($FORM{ip} ne "all") and (!checkip(\$FORM{ip}))) { + print "[$FORM{ip}] is not a valid IP/CIDR"; + } + elsif (($FORM{ignorefile} ne "") and ($FORM{ignorefile} =~ /[^\w\.]/)) { + print "[$FORM{ignorefile}] is not a valid file"; + } + elsif (($FORM{template} ne "") and ($FORM{template} =~ /[^\w\.]/)) { + print "[$FORM{template}] is not a valid file"; + } + elsif ($FORM{action} eq "manualcheck") { + print "

Checking version...

\n\n"; + my ($upgrade, $actv) = &manualversion($myv); + if ($upgrade) { + print "
A new version of csf (v$actv) is available. Upgrading will retain your settings. View ChangeLog
\n"; + } else { + if ($actv ne "") { + print "
$actv
\n"; + } + else { + print "
You are running the latest version of csf (v$myv). An Upgrade button will appear here if a new version becomes available
\n"; + } + } + print "
\n"; + &printreturn; + } + elsif ($FORM{action} eq "lfdstatus") { + print "

Show lfd status...

\n
\n";
+		ConfigServer::Service::statuslfd();
+		print "
\n

...Done.

\n"; + &printreturn; + } + elsif ($FORM{action} eq "ms_list") { + &modsec; + } + elsif ($FORM{action} eq "chart") { + &chart; + } + elsif ($FORM{action} eq "systemstats") { + &systemstats($FORM{graph}); + } + elsif ($FORM{action} eq "lfdstart") { + print "

Starting lfd...

\n
\n";
+		ConfigServer::Service::startlfd();
+		print "
\n

...Done.

\n"; + &printreturn; + } + elsif ($FORM{action} eq "lfdrestart") { + if ($config{THIS_UI}) { + print "

Signal lfd to restart...

\n
\n";
+			sysopen (my $OUT, "/var/lib/csf/lfd.restart",, O_WRONLY | O_CREAT) or die "Unable to open file: $!";
+			close ($OUT);
+		} else {
+			print "

Restarting lfd...

\n
\n";
+			ConfigServer::Service::restartlfd();
+		}
+		print "
\n

...Done.

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

Stopping lfd...

\n
\n";
+		ConfigServer::Service::stoplfd();
+		print "
\n

...Done.

\n"; + &printreturn; + } + elsif ($FORM{action} eq "status") { + &resize("top"); + print "
\n";
+		&printcmd("/usr/sbin/csf","-l");
+		if ($config{IPV6}) {
+			print "\n\nip6tables:\n\n";
+			&printcmd("/usr/sbin/csf","-l6");
+		}
+		print "
\n"; + &resize("bot",1); + &printreturn; + } + elsif ($FORM{action} eq "start") { + print "

Starting csf...

\n"; + &resize("top"); + print "
\n";
+		&printcmd("/usr/sbin/csf","-sf");
+		print "
\n

...Done.

\n"; + &resize("bot",1); + &printreturn; + } + elsif ($FORM{action} eq "restart") { + print "

Restarting csf...

\n"; + &resize("top"); + print "
\n";
+		&printcmd("/usr/sbin/csf","-sf");
+		print "
\n

...Done.

\n"; + &resize("bot",1); + &printreturn; + } + elsif ($FORM{action} eq "restartq") { + print "

Restarting csf via lfd...

\n
\n";
+		&printcmd("/usr/sbin/csf","-q");
+		print "
\n

...Done.

\n"; + &printreturn; + } + elsif ($FORM{action} eq "temp") { + print "\n"; + print "\n"; + my @deny; + if (! -z "/var/lib/csf/csf.tempban") { + open (my $IN, "<", "/var/lib/csf/csf.tempban") or die $!; + flock ($IN, LOCK_SH); + @deny = <$IN>; + chomp @deny; + close ($IN); + } + foreach my $line (reverse @deny) { + if ($line eq "") {next} + my ($time,$ip,$port,$inout,$timeout,$message) = split(/\|/,$line); + $time = $timeout - (time - $time); + if ($port eq "") {$port = "*"} + 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'; + } + print "\n"; + print "\n"; + } + my @allow; + if (! -z "/var/lib/csf/csf.tempallow") { + open (my $IN, "<", "/var/lib/csf/csf.tempallow") or die $!; + flock ($IN, LOCK_SH); + @allow = <$IN>; + chomp @allow; + close ($IN); + } + foreach my $line (@allow) { + if ($line eq "") {next} + my ($time,$ip,$port,$inout,$timeout,$message) = split(/\|/,$line); + $time = $timeout - (time - $time); + if ($port eq "") {$port = "*"} + 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'; + } + print "\n"; + } + print "
 A/DIP addressPortDirTime To LiveComment
\n"; + print "DENY$ip$port$inout$time$message
\n"; + print "ALLOW$ip$port$inout$time$message
\n"; + if (@deny or @allow) { + print "
Flush all temporary blocks
\n"; + } else { + print "
There are no temporary IP entries
\n"; + } + &printreturn; + } + elsif ($FORM{action} eq "temprm") { + print "

Removing all temporary entries:

\n
\n";
+		if ($FORM{ip} eq "all") {
+			&printcmd("/usr/sbin/csf","-tf");
+		}
+		print "
\n

...Done.

\n"; + print "
\n"; + } + elsif ($FORM{action} eq "temprmd") { + print "

Removing temporary deny entry for $FORM{ip}:

\n
\n";
+		&printcmd("/usr/sbin/csf","-trd",$FORM{ip});
+		print "
\n

...Done.

\n"; + print "
\n"; + } + elsif ($FORM{action} eq "temprma") { + print "

Removing temporary allow entry for $FORM{ip}:

\n
\n";
+		&printcmd("/usr/sbin/csf","-tra",$FORM{ip});
+		print "
\n

...Done.

\n"; + print "
\n"; + } + elsif ($FORM{action} eq "temptoperm") { + print "

Permanent ban for $FORM{ip}:

\n
\n";
+		&printcmd("/usr/sbin/csf","-tr",$FORM{ip});
+		&printcmd("/usr/sbin/csf","-d",$FORM{ip});
+		print "
\n

...Done.

\n"; + print "
\n"; + } + elsif ($FORM{action} eq "tempdeny") { + $FORM{timeout} =~ s/\D//g; + if ($FORM{dur} eq "minutes") {$FORM{timeout} = $FORM{timeout} * 60} + if ($FORM{dur} eq "hours") {$FORM{timeout} = $FORM{timeout} * 60 * 60} + if ($FORM{dur} eq "days") {$FORM{timeout} = $FORM{timeout} * 60 * 60 * 24} + if ($FORM{ports} eq "") {$FORM{ports} = "*"} + print "

Temporarily $FORM{do}ing $FORM{ip} for $FORM{timeout} seconds:

\n
\n";
+		if ($FORM{do} eq "block") {
+			&printcmd("/usr/sbin/csf","-td",$FORM{ip},$FORM{timeout},"-p",$FORM{ports},$FORM{comment});
+		} else {
+			&printcmd("/usr/sbin/csf","-ta",$FORM{ip},$FORM{timeout},"-p",$FORM{ports},$FORM{comment});
+		}
+		print "
\n

...Done.

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

Stopping csf...

\n"; + &resize("top"); + print "
\n";
+		&printcmd("/usr/sbin/csf","-f");
+		print "
\n

...Done.

\n"; + &resize("bot",1); + &printreturn; + } + elsif ($FORM{action} eq "disable") { + print "

Disabling csf...

\n"; + &resize("top"); + print "
\n";
+		&printcmd("/usr/sbin/csf","-x");
+		print "
\n

...Done.

\n"; + &resize("bot",1); + &printreturn; + } + elsif ($FORM{action} eq "enable") { + if ($config{THIS_UI}) { + print "

You must login to the root shell to enable csf using:\n

csf -e

\n"; + } else { + print "

Enabling csf...

\n"; + &resize("top"); + print "
\n";
+			&printcmd("/usr/sbin/csf","-e");
+			print "
"; + &resize("bot",1); + } + print "

...Done.

\n"; + &printreturn; + } + elsif ($FORM{action} eq "logtail") { + $FORM{lines} =~ s/\D//g; + if ($FORM{lines} eq "" or $FORM{lines} == 0) {$FORM{lines} = 30} + my $script_safe = $script; + my $CSFfrombot = 120; + my $CSFfromright = 10; + if ($config{DIRECTADMIN}) { + $script = $script_da; + $CSFfrombot = 400; + $CSFfromright = 150; + } + my @data = slurp("/etc/csf/csf.syslogs"); + foreach my $line (@data) { + if ($line =~ /^Include\s*(.*)$/) { + my @incfile = slurp($1); + push @data,@incfile; + } + } + @data = sort @data; + my $options = "  
+
Refresh in 0
+
+
+
   
+ + +EOF + if ($config{DIRECTADMIN}) {$script = $script_safe} + &printreturn; + } + elsif ($FORM{action} eq "logtailcmd") { + $FORM{lines} =~ s/\D//g; + if ($FORM{lines} eq "" or $FORM{lines} == 0) {$FORM{lines} = 30} + + my @data = slurp("/etc/csf/csf.syslogs"); + foreach my $line (@data) { + if ($line =~ /^Include\s*(.*)$/) { + my @incfile = slurp($1); + push @data,@incfile; + } + } + @data = sort @data; + my $cnt = 0; + my $logfile = "/var/log/lfd.log"; + my $hit = 0; + foreach my $file (@data) { + $file =~ s/$cleanreg//g; + if ($file eq "") {next} + if ($file =~ /^\s*\#|Include/) {next} + my @globfiles; + if ($file =~ /\*|\?|\[/) { + foreach my $log (glob $file) {push @globfiles, $log} + } else {push @globfiles, $file} + + foreach my $globfile (@globfiles) { + if (-f $globfile) { + if ($FORM{lognum} == $cnt) { + $logfile = $globfile; + $hit = 1; + last; + } + $cnt++; + } + } + if ($hit) {last} + } + if (-z $logfile) { + print "<---- $logfile is currently empty ---->"; + } else { + if (-x $config{TAIL}) { + my $timeout = 30; + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die}; + alarm($timeout); + my ($childin, $childout); + my $pid = open3($childin, $childout, $childout,$config{TAIL},"-$FORM{lines}",$logfile); + while (<$childout>) { + my $line = $_; + $line =~ s/&/&/g; + $line =~ s//>/g; + print $line; + } + waitpid ($pid, 0); + alarm(0); + }; + alarm(0); + if ($@) {print "TIMEOUT: tail command took too long. Timed out after $timeout seconds\n"} + } else { + print "Executable [$config{TAIL}] invalid"; + } + } + } + elsif ($FORM{action} eq "loggrep") { + $FORM{lines} =~ s/\D//g; + if ($FORM{lines} eq "" or $FORM{lines} == 0) {$FORM{lines} = 30} + my $script_safe = $script; + my $CSFfrombot = 120; + my $CSFfromright = 10; + if ($config{DIRECTADMIN}) { + $script = $script_da; + $CSFfrombot = 400; + $CSFfromright = 150; + } + my @data = slurp("/etc/csf/csf.syslogs"); + foreach my $line (@data) { + if ($line =~ /^Include\s*(.*)$/) { + my @incfile = slurp($1); + push @data,@incfile; + } + } + @data = sort @data; + my $options = "  +-i  +-E  + wildcard  +  +
+
+
+
+Please Note:
+
+ 1. Searches use $config{GREP}/$config{ZGREP} if wildcard is used), so the search text/regex must be syntactically correct
+ 2. Use the "-i" option to ignore case
+ 3. Use the "-E" option to perform an extended regular expression search
+ 4. Searching large log files can take a long time. This feature has a 30 second timeout
+ 5. The searched for text will usually be highlighted but may not always be successful
+ 6. Only log files listed in /etc/csf/csf.syslogs can be searched. You can add to this file
+ 7. The wildcard option will use $config{ZGREP} and search logs with a wildcard suffix, e.g. /var/log/lfd.log*
+
+ + +EOF + if ($config{DIRECTADMIN}) {$script = $script_safe} + &printreturn; + } + elsif ($FORM{action} eq "loggrepcmd") { + my @data = slurp("/etc/csf/csf.syslogs"); + foreach my $line (@data) { + if ($line =~ /^Include\s*(.*)$/) { + my @incfile = slurp($1); + push @data,@incfile; + } + } + @data = sort @data; + my $cnt = 0; + my $logfile = "/var/log/lfd.log"; + my $hit = 0; + foreach my $file (@data) { + $file =~ s/$cleanreg//g; + if ($file eq "") {next} + if ($file =~ /^\s*\#|Include/) {next} + my @globfiles; + if ($file =~ /\*|\?|\[/) { + foreach my $log (glob $file) {push @globfiles, $log} + } else {push @globfiles, $file} + + foreach my $globfile (@globfiles) { + if (-f $globfile) { + if ($FORM{lognum} == $cnt) { + $logfile = $globfile; + $hit = 1; + last; + } + $cnt++; + } + } + if ($hit) {last} + } + my @cmd; + my $grepbin = $config{GREP}; + if ($FORM{grepZ}) {$grepbin = $config{ZGREP}} + if ($FORM{grepi}) {push @cmd, "-i"} + if ($FORM{grepE}) {push @cmd, "-E"} + push @cmd, $FORM{grep}; + + if (-z $logfile) { + print "<---- $logfile is currently empty ---->"; + } else { + if (-x $grepbin) { + my $timeout = 30; + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die}; + my $total; + if ($FORM{grepZ}) { + foreach my $file (glob $logfile."\*") { + print "\nSearching $file:\n"; + alarm($timeout); + my ($childin, $childout); + my $pid = open3($childin, $childout, $childout,$grepbin,@cmd,$file); + while (<$childout>) { + my $line = $_; + $line =~ s/&/&/g; + $line =~ s//>/g; + if ($FORM{grep} ne "") { + eval { + local $SIG{__DIE__} = undef; + if ($FORM{grepi}) { + $line =~ s/$FORM{grep}/$&<\/mark>/ig; + } else { + $line =~ s/$FORM{grep}/$&<\/mark>/g; + } + }; + } + print $line; + $total += length $line; + } + waitpid ($pid, 0); + unless ($total) {print "<---- No matches found for \"$FORM{grep}\" in $file ---->\n"} + alarm(0); + } + } else { + alarm($timeout); + my ($childin, $childout); + my $pid = open3($childin, $childout, $childout,$grepbin,@cmd,$logfile); + while (<$childout>) { + my $line = $_; + $line =~ s/&/&/g; + $line =~ s//>/g; + if ($FORM{grep} ne "") { + eval { + local $SIG{__DIE__} = undef; + if ($FORM{grepi}) { + $line =~ s/$FORM{grep}/$&<\/mark>/ig; + } else { + $line =~ s/$FORM{grep}/$&<\/mark>/g; + } + }; + } + print $line; + $total += length $line; + } + waitpid ($pid, 0); + unless ($total) {print "<---- No matches found for \"$FORM{grep}\" in $logfile ---->\n"} + alarm(0); + } + }; + alarm(0); + if ($@) {print "TIMEOUT: grep command took too long. Timed out after $timeout seconds\n"} + } else { + print "Executable [$grepbin] invalid"; + } + } + } + elsif ($FORM{action} eq "readme") { + &resize("top"); + print "
\n";
+		open (my $IN, "<", "/etc/csf/readme.txt") or die $!;
+		flock ($IN, LOCK_SH);
+		my @readme = <$IN>;
+		close ($IN);
+		chomp @readme;
+
+		foreach my $line (@readme) {
+			$line =~ s/\/\>\;/g;
+			print $line."\n";
+		}
+		print "
\n"; + &resize("bot",0); + &printreturn; + } + elsif ($FORM{action} eq "servercheck") { + print ConfigServer::ServerCheck::report($FORM{verbose}); + + open (my $IN, "<", "/etc/cron.d/csf-cron"); + flock ($IN, LOCK_SH); + my @data = <$IN>; + close ($IN); + chomp @data; + my $optionselected = "never"; + my $email; + if (my @ls = grep {$_ =~ /csf \-m/} @data) { + if ($ls[0] =~ /\@(\w+)\s+root\s+\/usr\/sbin\/csf \-m (.*)/) {$optionselected = $1; $email = $2} + } + print "
\n"; + print "Generate and email this report to the email address
\n"; + + print "
\n"; + print "
\n"; + &printreturn; + } + elsif ($FORM{action} eq "serverchecksave") { + my $extra = ""; + my $freq = "daily"; + my $email; + if ($FORM{email} ne "") {$email = "root"} + if ($FORM{email} =~ /^[a-zA-Z0-9\-\_\.\@\+]+$/) {$email = $FORM{email}} + foreach my $option ("never","hourly","daily","weekly","monthly") {if ($FORM{freq} eq $option) {$freq = $option}} + unless ($email) {$freq = "never"; $extra = "(no valid email address supplied)";} + sysopen (my $CRON, "/etc/cron.d/csf-cron", O_RDWR | O_CREAT) or die "Unable to open file: $!"; + flock ($CRON, LOCK_EX); + my @data = <$CRON>; + chomp @data; + seek ($CRON, 0, 0); + truncate ($CRON, 0); + my $done = 0; + foreach my $line (@data) { + if ($line =~ /csf \-m/) { + if ($freq and ($freq ne "never") and !$done) { + print $CRON "\@$freq root /usr/sbin/csf -m $email\n"; + $done = 1; + } + } else { + print $CRON "$line\n"; + } + } + if (!$done and ($freq ne "never")) { + print $CRON "\@$freq root /usr/sbin/csf -m $email\n"; + } + close ($CRON); + + if ($freq and $freq ne "never") { + print "
Report scheduled to be emailed to $email $freq
\n"; + } else { + print "
Report schedule cancelled $extra
\n"; + } + print "
\n"; + } + elsif ($FORM{action} eq "rblcheck") { + my ($status, undef) = ConfigServer::RBLCheck::report($FORM{verbose},$images,1); + + print "
These options can take a long time to run (several minutes) depending on the number of IP addresses to check and the response speed of the DNS requests:
\n"; + print "
Generates the normal report showing exceptions only
\n"; + print "
Generates the normal report but shows successes and failures
\n"; + print "
Edit csf.rblconf to enable and disable IPs and RBLs
\n"; + + open (my $IN, "<", "/etc/cron.d/csf-cron"); + flock ($IN, LOCK_SH); + my @data = <$IN>; + close ($IN); + chomp @data; + my $optionselected = "never"; + my $email; + if (my @ls = grep {$_ =~ /csf \-\-rbl/} @data) { + if ($ls[0] =~ /\@(\w+)\s+root\s+\/usr\/sbin\/csf \-\-rbl (.*)/) {$optionselected = $1; $email = $2} + } + print "
\n"; + print "Generate and email this report to the email address
\n"; + &printreturn; + } + elsif ($FORM{action} eq "rblchecksave") { + my $extra = ""; + my $freq = "daily"; + my $email; + if ($FORM{email} ne "") {$email = "root"} + if ($FORM{email} =~ /^[a-zA-Z0-9\-\_\.\@\+]+$/) {$email = $FORM{email}} + foreach my $option ("never","hourly","daily","weekly","monthly") {if ($FORM{freq} eq $option) {$freq = $option}} + unless ($email) {$freq = "never"; $extra = "(no valid email address supplied)";} + sysopen (my $CRON, "/etc/cron.d/csf-cron", O_RDWR | O_CREAT) or die "Unable to open file: $!"; + flock ($CRON, LOCK_EX); + my @data = <$CRON>; + chomp @data; + seek ($CRON, 0, 0); + truncate ($CRON, 0); + my $done = 0; + foreach my $line (@data) { + if ($line =~ /csf \-\-rbl/) { + if ($freq and ($freq ne "never") and !$done) { + print $CRON "\@$freq root /usr/sbin/csf --rbl $email\n"; + $done = 1; + } + } else { + print $CRON "$line\n"; + } + } + if (!$done and ($freq ne "never")) { + print $CRON "\@$freq root /usr/sbin/csf --rbl $email\n"; + } + close ($CRON); + + if ($freq and $freq ne "never") { + print "
Report scheduled to be emailed to $email $freq
\n"; + } else { + print "
Report schedule cancelled $extra
\n"; + } + print "
\n"; + } + elsif ($FORM{action} eq "rblcheckedit") { + &editfile("/etc/csf/csf.rblconf","saverblcheckedit"); + print "
\n"; + } + elsif ($FORM{action} eq "saverblcheckedit") { + &savefile("/etc/csf/csf.rblconf",""); + print "
\n"; + } + elsif ($FORM{action} eq "cloudflareedit") { + &editfile("/etc/csf/csf.cloudflare","savecloudflareedit"); + &printreturn; + } + elsif ($FORM{action} eq "savecloudflareedit") { + &savefile("/etc/csf/csf.cloudflare",""); + &printreturn; + } + elsif ($FORM{action} eq "restartboth") { + print "

Restarting csf...

\n"; + &resize("top"); + print "
\n";
+		&printcmd("/usr/sbin/csf","-sf");
+		print "
\n

...Done.

\n"; + if ($config{THIS_UI}) { + print "

Signal lfd to restart...

\n
\n";
+			sysopen (my $OUT, "/var/lib/csf/lfd.restart",, O_WRONLY | O_CREAT) or die "Unable to open file: $!";
+			close ($OUT);
+		} else {
+			print "

Restarting lfd...

\n
\n";
+			ConfigServer::Service::restartlfd();
+		}
+		print "
\n

...Done.

\n"; + &resize("bot",1); + &printreturn; + } + elsif ($FORM{action} eq "remapf") { + print "

Removing APF/BFD...

\n
\n";
+		&printcmd("sh","/usr/local/csf/bin/remove_apf_bfd.sh");
+		print "
\n

...Done.

\n"; + print "

Note: You should check the root cron and /etc/crontab to ensure that there are no apf or bfd related cron jobs remaining

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

Allowing $FORM{ip}...

\n
\n";
+		&printcmd("/usr/sbin/csf","-a",$FORM{ip},$FORM{comment});
+		print "
\n

...Done.

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

Blocking $FORM{ip}...

\n
\n";
+		&printcmd("/usr/sbin/csf","-d",$FORM{ip},$FORM{comment});
+		print "
\n

...Done.

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

Ignoring $FORM{ip}...\n"; + open (my $OUT, ">>", "/etc/csf/csf.ignore"); + flock ($OUT, LOCK_EX); + print $OUT "$FORM{ip}\n"; + close ($OUT); + print "Done.

\n"; + if ($config{THIS_UI}) { + print "

Signal lfd to restart...

\n
\n";
+			sysopen (my $OUT, "/var/lib/csf/lfd.restart",, O_WRONLY | O_CREAT) or die "Unable to open file: $!";
+			close ($OUT);
+		} else {
+			print "

Restarting lfd...

\n
\n";
+			ConfigServer::Service::restartlfd();
+		}
+		print "
\n

...Done.

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

Unblock $FORM{ip}, trying permanent blocks...

\n
\n";
+		&printcmd("/usr/sbin/csf","-dr",$FORM{ip});
+		print "
\n

...Done.

\n"; + print "

Unblock $FORM{ip}, trying temporary blocks...

\n
\n";
+		&printcmd("/usr/sbin/csf","-trd",$FORM{ip});
+		print "
\n

...Done.

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

Unblock $FORM{ip}, trying permanent blocks...

\n
\n";
+		&printcmd("/usr/sbin/csf","-ar",$FORM{ip});
+		print "
\n

...Done.

\n"; + print "

Unblock $FORM{ip}, trying temporary blocks...

\n
\n";
+		&printcmd("/usr/sbin/csf","-tra",$FORM{ip});
+		print "
\n

...Done.

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

Searching for $FORM{ip}...

\n"; + &resize("top"); + print "
\n";
+		my ($childin, $childout);
+		my $pid = open3($childin, $childout, $childout, "/usr/sbin/csf","-g",$FORM{ip});
+		my $unblock;
+		my $unallow;
+		while (<$childout>) {
+			my $line = $_;
+			if ($line =~ /^csf.deny:\s(\S+)\s*/) {$unblock = 1}
+			if ($line =~ /^Temporary Blocks: IP:(\S+)\s*/) {$unblock = 1}
+			if ($line =~ /^csf.allow:\s(\S+)\s*/) {$unallow = 1}
+			if ($line =~ /^Temporary Allows: IP:(\S+)\s*/) {$unallow = 1}
+			print $_;
+		}
+		waitpid ($pid, 0);
+		print "
\n

...Done.

\n"; + &resize("bot",1); + if ($unblock) {print "\n"} + if ($unallow) {print "\n"} + &printreturn; + } + elsif ($FORM{action} eq "callow") { + print "

Cluster Allow $FORM{ip}...

\n
\n";
+		&printcmd("/usr/sbin/csf","-ca",$FORM{ip},$FORM{comment});
+		print "
\n

...Done.

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

Cluster Ignore $FORM{ip}...

\n
\n";
+		&printcmd("/usr/sbin/csf","-ci",$FORM{ip},$FORM{comment});
+		print "
\n

...Done.

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

Cluster Remove ignore $FORM{ip}...

\n
\n";
+		&printcmd("/usr/sbin/csf","-cir",$FORM{ip});
+		print "
\n

...Done.

\n"; + &printreturn; + } + elsif ($FORM{action} eq "cloudflare") { + &cloudflare; + } + elsif ($FORM{action} eq "cflist") { + print "
CloudFlare list $FORM{type} rules for user(s) $FORM{domains}:
\n"; + print "
";
+		&printcmd("/usr/sbin/csf","--cloudflare","list",$FORM{type},$FORM{domains});
+		print "
\n
\n"; + } + elsif ($FORM{action} eq "cftempdeny") { + print "
CloudFlare $FORM{do} $FORM{target} for user(s) $FORM{domains}:
\n"; + print "
\n";
+		&printcmd("/usr/sbin/csf","--cloudflare","tempadd",$FORM{do},$FORM{target},$FORM{domains});
+		print "
\n
\n"; + } + elsif ($FORM{action} eq "cfadd") { + print "
CloudFlare Add $FORM{type} $FORM{target} for user(s) $FORM{domains}:
\n"; + print "
";
+		&printcmd("/usr/sbin/csf","--cloudflare","add",$FORM{type},$FORM{target},$FORM{domains});
+		print "
\n
\n"; + } + elsif ($FORM{action} eq "cfremove") { + print "
CloudFlare Delete $FORM{type} $FORM{target} for user(s) $FORM{domains}:
\n"; + print "
";
+		&printcmd("/usr/sbin/csf","--cloudflare","del", $FORM{target},$FORM{domains});
+		print "
\n
\n"; + } + elsif ($FORM{action} eq "cdeny") { + print "

Cluster Deny $FORM{ip}...

\n
\n";
+		&printcmd("/usr/sbin/csf","-cd",$FORM{ip},$FORM{comment});
+		print "
\n

...Done.

\n"; + &printreturn; + } + elsif ($FORM{action} eq "ctempdeny") { + $FORM{timeout} =~ s/\D//g; + if ($FORM{dur} eq "minutes") {$FORM{timeout} = $FORM{timeout} * 60} + if ($FORM{dur} eq "hours") {$FORM{timeout} = $FORM{timeout} * 60 * 60} + if ($FORM{dur} eq "days") {$FORM{timeout} = $FORM{timeout} * 60 * 60 * 24} + if ($FORM{ports} eq "") {$FORM{ports} = "*"} + print "

cluster Temporarily $FORM{do}ing $FORM{ip} for $FORM{timeout} seconds:

\n
\n";
+		if ($FORM{do} eq "block") {
+			&printcmd("/usr/sbin/csf","-ctd",$FORM{ip},$FORM{timeout},"-p",$FORM{ports},$FORM{comment});
+		} else {
+			&printcmd("/usr/sbin/csf","-cta",$FORM{ip},$FORM{timeout},"-p",$FORM{ports},$FORM{comment});
+		}
+		print "
\n

...Done.

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

Cluster Remove Deny $FORM{ip}...

\n
\n";
+		&printcmd("/usr/sbin/csf","-cr",$FORM{ip});
+		print "
\n

...Done.

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

Cluster Remove Allow $FORM{ip}...

\n
\n";
+		&printcmd("/usr/sbin/csf","-car",$FORM{ip});
+		print "
\n

...Done.

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

Cluster PING...

\n
\n";
+		&printcmd("/usr/sbin/csf","-cp");
+		print "
\n

...Done.

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

Cluster GREP for $FORM{ip}...

\n"; + print "
\n";
+		my ($childin, $childout);
+		my $pid = open3($childin, $childout, $childout, "/usr/sbin/csf","-cg",$FORM{ip});
+		my $unblock;
+		my $start = 0;
+		while (<$childout>) {
+			my $line = $_;
+			if ($line =~ /^====/) {
+				if ($start) {
+					print "$line
";
+					$start = 0;
+				} else {
+					print "
$line";
+					$start = 1;
+				}
+			} else {
+				print $line;
+			}
+		}
+		waitpid ($pid, 0);
+		print "...Done\n
\n"; + &printreturn; + } + elsif ($FORM{action} eq "cconfig") { + $FORM{option} =~ s/\s*//g; + my %restricted; + if ($config{RESTRICT_UI}) { + sysopen (my $IN, "/usr/local/csf/lib/restricted.txt", O_RDWR | O_CREAT) or die "Unable to open file: $!"; + flock ($IN, LOCK_SH); + while (my $entry = <$IN>) { + chomp $entry; + $restricted{$entry} = 1; + } + close ($IN); + } + if ($restricted{$FORM{option}}) { + print "
Option $FORM{option} cannot be set with RESTRICT_UI enabled
\n"; + exit; + } + print "

Cluster configuration option...

\n
\n";
+		&printcmd("/usr/sbin/csf","-cc",$FORM{option},$FORM{value});
+		print "
\n

...Done.

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

Cluster restart csf and lfd...

\n
\n";
+		&printcmd("/usr/sbin/csf --crestart");
+		print "
\n

...Done.

\n"; + &printreturn; + } + elsif ($FORM{action} eq "allow") { + &editfile("/etc/csf/csf.allow","saveallow"); + &printreturn; + } + elsif ($FORM{action} eq "saveallow") { + &savefile("/etc/csf/csf.allow","both"); + &printreturn; + } + elsif ($FORM{action} eq "redirect") { + &editfile("/etc/csf/csf.redirect","saveredirect"); + &printreturn; + } + elsif ($FORM{action} eq "saveredirect") { + &savefile("/etc/csf/csf.redirect","both"); + &printreturn; + } + elsif ($FORM{action} eq "smtpauth") { + &editfile("/etc/csf/csf.smtpauth","savesmtpauth"); + &printreturn; + } + elsif ($FORM{action} eq "savesmtpauth") { + &savefile("/etc/csf/csf.smtpauth","both"); + &printreturn; + } + elsif ($FORM{action} eq "reseller") { + &editfile("/etc/csf/csf.resellers","savereseller"); + &printreturn; + } + elsif ($FORM{action} eq "savereseller") { + &savefile("/etc/csf/csf.resellers",""); + &printreturn; + } + elsif ($FORM{action} eq "dirwatch") { + &editfile("/etc/csf/csf.dirwatch","savedirwatch"); + &printreturn; + } + elsif ($FORM{action} eq "savedirwatch") { + &savefile("/etc/csf/csf.dirwatch","lfd"); + &printreturn; + } + elsif ($FORM{action} eq "dyndns") { + &editfile("/etc/csf/csf.dyndns","savedyndns"); + &printreturn; + } + elsif ($FORM{action} eq "savedyndns") { + &savefile("/etc/csf/csf.dyndns","lfd"); + &printreturn; + } + elsif ($FORM{action} eq "blocklists") { + &editfile("/etc/csf/csf.blocklists","saveblocklists"); + &printreturn; + } + elsif ($FORM{action} eq "saveblocklists") { + &savefile("/etc/csf/csf.blocklists","both"); + &printreturn; + } + elsif ($FORM{action} eq "syslogusers") { + &editfile("/etc/csf/csf.syslogusers","savesyslogusers"); + &printreturn; + } + elsif ($FORM{action} eq "savesyslogusers") { + &savefile("/etc/csf/csf.syslogusers","lfd"); + &printreturn; + } + elsif ($FORM{action} eq "logfiles") { + &editfile("/etc/csf/csf.logfiles","savelogfiles"); + &printreturn; + } + elsif ($FORM{action} eq "savelogfiles") { + &savefile("/etc/csf/csf.logfiles","lfd"); + &printreturn; + } + elsif ($FORM{action} eq "deny") { + &editfile("/etc/csf/csf.deny","savedeny"); + &printreturn; + } + elsif ($FORM{action} eq "savedeny") { + &savefile("/etc/csf/csf.deny","both"); + &printreturn; + } + elsif ($FORM{action} eq "templates") { + &editfile("/usr/local/csf/tpl/$FORM{template}","savetemplates","template"); + &printreturn; + } + elsif ($FORM{action} eq "savetemplates") { + &savefile("/usr/local/csf/tpl/$FORM{template}","",1); + &printreturn; + } + elsif ($FORM{action} eq "ignorefiles") { + &editfile("/etc/csf/$FORM{ignorefile}","saveignorefiles","ignorefile"); + &printreturn; + } + elsif ($FORM{action} eq "saveignorefiles") { + &savefile("/etc/csf/$FORM{ignorefile}","lfd"); + &printreturn; + } + elsif ($FORM{action} eq "conf") { + sysopen (my $IN, "/etc/csf/csf.conf", O_RDWR | O_CREAT) or die "Unable to open file: $!"; + flock ($IN, LOCK_SH); + my @confdata = <$IN>; + close ($IN); + chomp @confdata; + + my %restricted; + if ($config{RESTRICT_UI}) { + sysopen (my $IN, "/usr/local/csf/lib/restricted.txt", O_RDWR | O_CREAT) or die "Unable to open file: $!"; + flock ($IN, LOCK_SH); + while (my $entry = <$IN>) { + chomp $entry; + $restricted{$entry} = 1; + } + close ($IN); + } + + print < +function CSFexpand(obj){ + if (!obj.savesize) {obj.savesize=obj.size;} + var newsize = Math.max(obj.savesize,obj.value.length); + if (newsize > 120) {newsize = 120;} + obj.size = newsize; +} + +EOF + print "\n"; + open (my $DIV, "<", "/usr/local/csf/lib/csf.div"); + flock ($DIV, LOCK_SH); + my @divdata = <$DIV>; + close ($DIV); + print @divdata; + print "
\n"; + print "
\n"; + print "\n"; + my $first = 1; + my @divnames; + my $comment = 0; + foreach my $line (@confdata) { + if (($line !~ /^\#/) and ($line =~ /=/)) { + if ($comment) {print "
\n"} + $comment = 0; + my ($start,$end) = split (/=/,$line,2); + my $name = $start; + my $cleanname = $start; + $cleanname =~ s/\s//g; + $name =~ s/\s/\_/g; + if ($end =~ /\"(.*)\"/) {$end = $1} + my $size = length($end) + 4; + my $class = "value-default"; + my ($status,$range,$default) = sanity($start,$end); + my $showrange = ""; + my $showfrom; + my $showto; + if ($range =~ /^(\d+)-(\d+)$/) { + $showfrom = $1; + $showto = $2; + } + if ($default ne "") { + $showrange = " Default: $default [$range]"; + if ($end ne $default) {$class = "value-other"} + } + if ($status) {$class = "value-warning"; $showrange = " Recommended range: $range (Default: $default)"} + if ($config{RESTRICT_UI} and ($cleanname eq "CLUSTER_KEY" or $cleanname eq "UI_PASS" or $cleanname eq "UI_USER")) { + print "
$start = (hidden restricted UI item)
\n"; + } + elsif ($restricted{$cleanname}) { + print "
$start = (restricted UI item)
\n"; + } else { + if ($range eq "0-1") { + my $switch_checked_0 = ""; + my $switch_checked_1 = ""; + my $switch_active_0 = ""; + my $switch_active_1 = ""; + if ($end == 0) {$switch_checked_0 = "checked"; $switch_active_0 = "active"} + if ($end == 1) {$switch_checked_1 = "checked"; $switch_active_1 = "active"} + print "
$start = "; + print "
\n"; + print "\n"; + print "\n"; + print "
\n"; + } + elsif ($range =~ /^(\d+)-(\d+)$/ and !(-e "/etc/csuibuttondisable") and ($showto - $showfrom <= 20) and $end >= $showfrom and $end <= $showto) { + my $selected = ""; + print "
$start =
\n"; + } else { + print "
$start = $showrange
\n"; + } + } + } else { + if ($line =~ /^\# SECTION:(.*)/) { + push @divnames, $1; + unless ($first) {print "
\n"} + print "
\n
"; + print "$1
\n"; + $first = 0; + next; + } + if ($line =~ /^\# / and $comment == 0) { + $comment = 1; + print "
\n"; + } + $line =~ s/\#//g; + $line =~ s/&/&/g; + $line =~ s//>/g; + $line =~ s/\n/
\n/g; + print "$line
\n"; + } + } + print "

\n"; + print "\n"; + print < +var pagecontent=new virtualpaginate({ + piececlass: "virtualpage", //class of container for each piece of content + piececontainer: "div", //container element type (ie: "div", "p" etc) + pieces_per_page: 1, //Pieces of content to show per page (1=1 piece, 2=2 pieces etc) + defaultpage: 0, //Default page selected (0=1st page, 1=2nd page etc). Persistence if enabled overrides this setting. + wraparound: false, + persist: false //Remember last viewed page and recall it when user returns within a browser session? +}); +EOD + print "pagecontent.buildpagination(['paginatediv','paginatediv2'],["; + foreach my $line (@divnames) {print "'$line',"} + print "''])\npagecontent.showall();\n\n"; + print "
\n"; + print "\n"; + &printreturn; + } + elsif ($FORM{action} eq "saveconf") { + sysopen (my $IN, "/etc/csf/csf.conf", O_RDWR | O_CREAT) or die "Unable to open file: $!"; + flock ($IN, LOCK_SH); + my @confdata = <$IN>; + close ($IN); + chomp @confdata; + + my %restricted; + if ($config{RESTRICT_UI}) { + sysopen (my $IN, "/usr/local/csf/lib/restricted.txt", O_RDWR | O_CREAT) or die "Unable to open file: $!"; + flock ($IN, LOCK_SH); + while (my $entry = <$IN>) { + chomp $entry; + $restricted{$entry} = 1; + } + close ($IN); + } + + 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 ($start,$end) = split (/=/,$confdata[$x],2); + if ($end =~ /\"(.*)\"/) {$end = $1} + my $name = $start; + my $sanity_name = $start; + $name =~ s/\s/\_/g; + $sanity_name =~ s/\s//g; + if ($restricted{$sanity_name}) { + print $OUT "$confdata[$x]\n"; + } else { + print $OUT "$start= \"$FORM{$name}\"\n"; + $end = $FORM{$name}; + } + } else { + print $OUT "$confdata[$x]\n"; + } + } + close ($OUT); + ConfigServer::Config::resetconfig(); + my $newconfig = ConfigServer::Config->loadconfig(); + my %newconfig = $config->config; + foreach my $key (keys %newconfig) { + my ($insane,$range,$default) = sanity($key,$newconfig{$key}); + if ($insane) {print "
WARNING: $key sanity check. $key = \"$newconfig{$key}\". Recommended range: $range (Default: $default)\n"} + } + + print "
Changes saved. You should restart both csf and lfd.
\n"; + print "
\n"; + &printreturn; + } + elsif ($FORM{action} eq "viewlogs") { + if (-e "/var/lib/csf/stats/iptables_log") { + open (my $IN, "<", "/var/lib/csf/stats/iptables_log") or die "Unable to open file: $!"; + flock ($IN, LOCK_SH); + my @iptables = <$IN>; + close ($IN); + chomp @iptables; + @iptables = reverse @iptables; + my $from; + my $to; + my $divcnt = 0; + my $expcnt = @iptables; + + if ($iptables[0] =~ /\|(\S+\s+\d+\s+\S+)/) {$from = $1} + if ($iptables[-1] =~ /\|(\S+\s+\d+\s+\S+)/) {$to = $1} + + print "
\n"; + print "
\n"; + print "

Last $config{ST_IPTABLES} iptables logs*, latest:$from oldest:$to


\n"; + print "\n"; + print "\n"; + my $size = scalar @iptables; + if ($size > $config{ST_IPTABLES}) {$size = $config{ST_IPTABLES}} + for (my $x = 0 ;$x < $size ;$x++) { + my $line = $iptables[$x]; + $divcnt++; + my ($text,$log) = split(/\|/,$line); + my ($time,$desc,$in,$out,$src,$dst,$spt,$dpt,$proto,$inout); + if ($log =~ /IN=(\S+)/) {$in = $1} + if ($log =~ /OUT=(\S+)/) {$out = $1} + if ($log =~ /SRC=(\S+)/) {$src = $1} + if ($log =~ /DST=(\S+)/) {$dst = $1} + if ($log =~ /SPT=(\d+)/) {$spt = $1} + if ($log =~ /DPT=(\d+)/) {$dpt = $1} + if ($log =~ /PROTO=(\S+)/) {$proto = $1} + + if ($text ne "") { + $text =~ s/\(/\\(/g; + if ($in and $src) {$src = $text ; $dst .= "
(server)"} + elsif ($out and $dst) {$dst = $text ; $src .= "
(server)"} + } + if ($log =~ /^(\S+\s+\d+\s+\S+)/) {$time = $1} + + $inout = "n/a"; + if ($in) {$inout = "in"} + elsif ($out) {$inout = "out"} + + print "
\n"; + + $log =~ s/\&/\&\;/g; + $log =~ s/>/\>\;/g; + $log =~ s/\n"; + } + print "
TimeFromPortI/OToPortProto
$time$src$spt$inout$dst$dpt$proto
$log
\n"; + print "
* These iptables logs taken from $config{IPTABLES_LOG} will not necessarily show all packets blocked by iptables. For example, ports listed in DROP_NOLOG or the settings for DROP_LOGGING/DROP_IP_LOGGING/DROP_ONLYRES/DROP_PF_LOGGING will affect what is logged. Additionally, there is rate limiting on all iptables log rules to prevent log file flooding
\n"; + } else { + print "
No logs entries found
\n"; + } + &printreturn; + } + elsif ($FORM{action} eq "sips") { + sysopen (my $IN, "/etc/csf/csf.sips", O_RDWR | O_CREAT) or die "Unable to open file: $!"; + flock ($IN, LOCK_SH); + my @confdata = <$IN>; + close ($IN); + chomp @confdata; + + print "

\n"; + print "\n"; + print "\n"; + + my %sips; + open (my $SIPS, "<","/etc/csf/csf.sips"); + flock ($SIPS, LOCK_SH); + my @data = <$SIPS>; + close ($SIPS); + chomp @data; + foreach my $line (@data) { + if ($line =~ /^(\s|\#|$)/) {next} + $sips{$line} = 1; + } + + my $ethdev = ConfigServer::GetEthDev->new(); + my %g_ipv4 = $ethdev->ipv4; + my %g_ipv6 = $ethdev->ipv6; + + foreach my $key (sort keys %g_ipv4) { + my $ip = $key; + if ($ip =~ /^127\.0\.0/) {next} + my $chk = "ip_$ip"; + $chk =~ s/\./\_/g; + my $checked = ""; + if ($sips{$ip}) {$checked = "checked"} + print "\n"; + } + + foreach my $key (sort keys %g_ipv6) { + my $ip = $key; + my $chk = "ip_$ip"; + $chk =~ s/\./\_/g; + my $checked = ""; + if ($sips{$ip}) {$checked = "checked"} + print "\n"; + } + + print "\n"; + print "
IP AddressDeny All Access to IP
$ip
$ip
\n"; + &printreturn; + } + elsif ($FORM{action} eq "sipsave") { + open (my $IN,"<","/etc/csf/csf.sips"); + flock ($IN, LOCK_SH); + my @data = <$IN>; + close ($IN); + chomp @data; + + open (my $OUT,">","/etc/csf/csf.sips"); + flock ($OUT, LOCK_EX); + foreach my $line (@data) { + if ($line =~ /^\#/) {print $OUT "$line\n"} else {last} + } + foreach my $key (keys %FORM) { + if ($key =~ /^ip_(.*)/) { + my $ip = $1; + $ip =~ s/\_/\./g; + print $OUT "$ip\n"; + } + } + close($OUT); + + print "
Changes saved. You should restart csf.
\n"; + print "
\n"; + &printreturn; + } + elsif ($FORM{action} eq "upgrade") { + if ($config{THIS_UI}) { + print "
You cannot upgrade through the UI as restarting lfd will interrupt this session. You must login to the root shell to upgrade csf using:\n

csf -u

\n"; + } else { + print "

Upgrading csf...

\n"; + &resize("top"); + print "
\n";
+			&printcmd("/usr/sbin/csf","-u");
+			print "
\n

...Done.

\n"; + &resize("bot",1); + + open (my $IN, "<", "/etc/csf/version.txt") or die $!; + flock ($IN, LOCK_SH); + $myv = <$IN>; + close ($IN); + chomp $myv; + } + + &printreturn; + } + elsif ($FORM{action} eq "denyf") { + print "

Removing all entries from csf.deny...

\n"; + &resize("top"); + print "
\n";
+		&printcmd("/usr/sbin/csf","-df");
+		&printcmd("/usr/sbin/csf","-tf");
+		print "
\n

...Done.

\n"; + &resize("bot",1); + &printreturn; + } + elsif ($FORM{action} eq "csftest") { + print "

Testing iptables...

\n
\n";
+		&printcmd("/usr/local/csf/bin/csftest.pl");
+		print "
\n

...Done.

\n"; + print "
You should restart csf after having run this test.
\n"; + print "
\n"; + &printreturn; + } + elsif ($FORM{action} eq "profiles") { + my @profiles = sort glob("/usr/local/csf/profiles/*"); + my @backups = reverse glob("/var/lib/csf/backup/*"); + + print "
\n"; + print "\n"; + print "\n"; + foreach my $profile (@profiles) { + my ($file, undef) = fileparse($profile); + $file =~ s/\.conf$//; + my $text; + open (my $IN, "<", $profile); + flock ($IN, LOCK_SH); + my @profiledata = <$IN>; + close ($IN); + chomp @profiledata; + + if ($file eq "reset_to_defaults") { + $text = "This is the installation default profile and will reset all csf.conf settings, including enabling TESTING mode"; + } + elsif ($profiledata[0] =~ /^\# Profile:/) { + foreach my $line (@profiledata) { + if ($line =~ /^\# (.*)$/) {$text .= "$1 "} + } + } + + print "\n"; + } + print "\n"; + print "
Preconfigured Profiles 
$file
\n$text
You can apply one or more of these profiles to csf.conf. Apart from reset_to_defaults, most of these profiles contain only a subset of settings. You can find out what will be changed by comparing the profile to the current configuration below. A backup of csf.conf will be created before any profile is applied.
\n"; + print "
\n"; + + print "
\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "
Backup csf.conf
Create a backup of csf.conf. You can use an optional name for the backup that should only contain alphanumerics. Other characters (including spaces) will be replaced with an underscore ( _ )
\n"; + print "
\n"; + + print "
\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "
Restore Backup Of csf.conf
\n"; + print "
\n"; + + print "
\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "
Compare Configurations
Select first configuration:
\n
Select second configuration:
\n
\n"; + print "
\n"; + + &printreturn; + } + elsif ($FORM{action} eq "profileapply") { + my $profile = $FORM{profile}; + $profile =~ s/\W/_/g; + print "

Applying profile ($profile)...

\n
\n";
+		&printcmd("/usr/sbin/csf","--profile","apply",$profile);
+		print "
\n

...Done.

\n"; + print "
You should restart both csf and lfd.
\n"; + print "
\n"; + &printreturn; + } + elsif ($FORM{action} eq "profilebackup") { + my $profile = $FORM{backup}; + $profile =~ s/\W/_/g; + print "

Creating backup...

\n
\n";
+		&printcmd("/usr/sbin/csf","--profile","backup",$profile);
+		print "
\n

...Done.

\n"; + &printreturn; + } + elsif ($FORM{action} eq "profilerestore") { + my $profile = $FORM{backup}; + $profile =~ s/\W/_/g; + print "

Restoring backup ($profile)...

\n
\n";
+		&printcmd("/usr/sbin/csf","--profile","restore",$profile);
+		print "
\n

...Done.

\n"; + print "
You should restart both csf and lfd.
\n"; + print "
\n"; + &printreturn; + } + elsif ($FORM{action} eq "profilediff") { + my $profile1 = $FORM{profile1}; + my $profile2 = $FORM{profile2}; + $profile2 =~ s/\W/_/g; + $profile2 =~ s/\W/_/g; + + print "\n"; + my ($childin, $childout); + my $pid = open3($childin, $childout, $childout, "/usr/sbin/csf","--profile","diff",$profile1,$profile2); + while (<$childout>) { + $_ =~ s/\[|\]//g; + my ($var,$p1,$p2) = split(/\s+/,$_); + if ($var eq "") { + next; + } + elsif ($var eq "SETTING") { + print "\n"; + } + else { + print "\n"; + } + } + waitpid ($pid, 0); + print "
$var$p1$p2
$var$p1$p2
\n"; + + &printreturn; + } + elsif ($FORM{action} eq "viewports") { + print "

Ports listening for external connections and the executables running behind them:

\n"; + print "\n"; + print "\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}}) { + my $fopen; + if ($ports{$protocol}{$port}) {$fopen = "4"} else {$fopen = "-"} + if ($config{IPV6} and $ports{$protocol."6"}{$port}) {$fopen .= "/6"} else {$fopen .= "/-"} + + my $fcmd = ($listen{$protocol}{$port}{$pid}{cmd}); + $fcmd =~ s/\\n"; + } + } + } + print "
PortProtoOpenConnsPIDUserCommand LineExecutable
$port$protocol$fopen$fconn$pid$listen{$protocol}{$port}{$pid}{user}$fcmd$fexe
\n"; + + &printreturn; + } + elsif ($mobile) { + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "
\n"; + } + elsif ($FORM{action} eq "fix") { + print "
These options should only be used as a last resort as most of them will reduce the effectiveness of csf and lfd to protect the server
\n"; + + print "\n"; + print ""; + + if ($config{LF_SPI} == 0) { + print "\n"; + + if ($config{TCP_IN} =~ /30000:35000/) { + print "\n"; + + if ($config{PT_USERKILL} == 0) { + print "\n"; + + if ($config{SMTP_BLOCK} == 0) { + print "\n"; + + print "\n"; + + print "\n"; + + print "
Fix Common Problems
\n"; + } else { + print "
\n"; + } + print "If you find that ports listed in TCP_IN/UDP_IN are being blocked by iptables (e.g. port 80) as seen in /var/log/messages and users can only connect to the server if entered in csf.allow, then it could be that the kernel (usually on virtual servers) is broken and cannot perform connection tracking. In this case, disabling the Stateful Packet Inspection functionality of csf (LF_SPI) may help\n"; + if ($config{LF_SPI} == 0) { + print "
Note: LF_SPI is already disabled"; + } + print "
\n"; + } else { + print "
\n"; + } + print "If the kernel (usually on virtual servers) is broken and cannot perform ftp connection tracking, or if you are trying to use FTP over SSL, this option will open a hole in the firewall to allow PASV connections through\n"; + if ($config{TCP_IN} =~ /30000:35000/) { + print "
Note: The port range 30000 to 35000 is already open in csf\n"; + } + print "
\n"; + } else { + print "
\n"; + } + print "If lfd is killing running processes and you have PT_USERKILL enabled, then we recommend that you disable this feature\n"; + if ($config{PT_USERKILL} == 0) { + print "
Note: PT_USERKILL is already disabled"; + } + print "
\n"; + } else { + print "
\n"; + } + print "If scripts on the server are unable to send out email via external SMTP connections and you have SMTP_BLOCK enabled then those scripts should be configured to send email either through /usr/sbin/sendmail or localhost on the server. If this is not possible then disabling SMTP_BLOCK can fix this\n"; + if ($config{SMTP_BLOCK} == 0) { + print "
Note: SMTP_BLOCK is already disabled"; + } + print "
\n"; + print "If you really want to disable all alerts in lfd you can do so here. This is not recommended in any situation - you should go through the csf configuration and only disable those you do not want. As new features are added to csf you may find that you have to go into the csf configuration and disable them manually as this procedure only disables the ones that it is aware of when applied\n"; + print "
\n"; + print "If all else fails this option will completely uninstall csf and install it again with completely default options (including TESTING mode). The previous configuration will be lost including all modifications\n"; + print "
\n"; + &printreturn; + &confirmmodal; + } + elsif ($FORM{action} eq "fixpasvftp") { + print "
\n"; + print "
Enabling pure-ftpd PASV hole:
\n"; + print "
"; + &resize("top"); + print "
\n";
+
+		my $ftpdone = 0;
+		if (-e "/usr/local/cpanel/version") {
+			require Cpanel::Config;
+			import Cpanel::Config;
+			my $cpconf = Cpanel::Config::loadcpconf();
+			if ($cpconf->{ftpserver} eq "pure-ftpd") {
+				copy("/etc/pure-ftpd.conf","/etc/pure-ftpd.conf-".time."_prefixpasvftp");
+				sysopen (my $PUREFTP,"/etc/pure-ftpd.conf", O_RDWR | O_CREAT);
+				flock ($PUREFTP, LOCK_EX);
+				my @ftp = <$PUREFTP>;
+				chomp @ftp;
+				seek ($PUREFTP, 0, 0);
+				truncate ($PUREFTP, 0);
+				my $hit = 0;
+				foreach my $line (@ftp) {
+					if ($line =~ /^#?\s*PassivePortRange/i) {
+						if ($hit) {next}
+						$line = "PassivePortRange 30000 35000";
+						$hit = 1;
+					}
+					print $PUREFTP "$line\n";
+				}
+				unless ($hit) {print $PUREFTP "PassivePortRange 30000 35000"}
+				close ($PUREFTP);
+				&printcmd("/scripts/restartsrv_pureftpd");
+				$ftpdone = 1;
+			}
+		}
+
+		if ($config{TCP_IN} =~ /30000:35000/) {
+			print "PASV port range 30000:35000 already exists in TCP_IN/TCP6_IN\n";
+		} else {
+			$config{TCP_IN} .= ",30000:35000";
+			$config{TCP6_IN} .= ",30000:35000";
+
+			copy("/etc/csf/csf.conf","/var/lib/csf/backup/".time."_prefixpasvftp");
+			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 30000:35000 added to the TCP6_IN port list\n";
+				}
+				elsif ($line =~ /^TCP_IN/) {
+					print $CSFCONF "TCP_IN = \"$config{TCP_IN}\"\n";
+					print "*** PASV port range 30000:35000 added to the TCP_IN port list\n";
+				}
+				else {
+					print $CSFCONF $line."\n";
+				}
+			}
+			close ($CSFCONF);
+		}
+
+		print "
\n"; + &resize("bot",1); + print "\n"; + print "
\n"; + print "
You MUST now restart both csf and lfd:
\n"; + print "
\n"; + &printreturn; + } + elsif ($FORM{action} eq "fixspi") { + print "
\n"; + print "
Disabling LF_SPI:
\n"; + print "
"; + + copy("/etc/csf/csf.conf","/var/lib/csf/backup/".time."_prefixspi"); + 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 =~ /^LF_SPI /) { + print $CSFCONF "LF_SPI = \"0\"\n"; + print "*** LF_SPI disabled ***\n"; + } else { + print $CSFCONF $line."\n"; + } + } + close ($CSFCONF); + + print "
\n"; + print "\n"; + print "
\n"; + print "
You MUST now restart both csf and lfd:
\n"; + print "
\n"; + &printreturn; + } + elsif ($FORM{action} eq "fixkill") { + print "
\n"; + print "
Disabling PT_USERKILL:
\n"; + print "
"; + + copy("/etc/csf/csf.conf","/var/lib/csf/backup/".time."_prefixkill"); + 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 =~ /^PT_USERKILL /) { + print $CSFCONF "PT_USERKILL = \"0\"\n"; + print "*** PT_USERKILL disabled ***\n"; + } else { + print $CSFCONF $line."\n"; + } + } + close ($CSFCONF); + + print "
\n"; + print "\n"; + print "
\n"; + print "
You MUST now restart both csf and lfd:
\n"; + print "
\n"; + &printreturn; + } + elsif ($FORM{action} eq "fixsmtp") { + print "
\n"; + print "
Disabling SMTP_BLOCK:
\n"; + print "
"; + + copy("/etc/csf/csf.conf","/var/lib/csf/backup/".time."_prefixsmtp"); + 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 =~ /^SMTP_BLOCK /) { + print $CSFCONF "SMTP_BLOCK = \"0\"\n"; + print "*** SMTP_BLOCK disabled ***\n"; + } else { + print $CSFCONF $line."\n"; + } + } + close ($CSFCONF); + + print "
\n"; + print "\n"; + print "
\n"; + print "
You MUST now restart both csf and lfd:
\n"; + print "
\n"; + &printreturn; + } + elsif ($FORM{action} eq "fixalerts") { + print "
\n"; + print "
Disabling All Alerts:
\n"; + print "
"; + + &resize("top"); + print "
\n";
+		copy("/etc/csf/csf.conf","/var/lib/csf/backup/".time."_prefixalerts");
+		&printcmd("/usr/sbin/csf","--profile","apply","disable_alerts");
+		print "
\n"; + &resize("bot",1); + print "
\n"; + print "\n"; + print "
\n"; + print "
You MUST now restart both csf and lfd:
\n"; + print "
\n"; + &printreturn; + } + elsif ($FORM{action} eq "fixnuclear") { + print "
\n"; + print "
Nuclear Option:
\n"; + print "
"; + + my $time = time; + sysopen (my $REINSTALL, "/usr/src/reinstall_$time.sh", O_WRONLY | O_CREAT | O_TRUNC); + flock ($REINSTALL, LOCK_EX); + print $REINSTALL <\n"; + &printcmd("bash","/usr/src/reinstall_$time.sh"); + unlink "/usr/src/reinstall_$time.sh"; + print "\n"; + &resize("bot",1); + print "
\n"; + print "\n"; + print "
\n"; + &printreturn; + } + else { + if (defined $ENV{WEBMIN_VAR} and defined $ENV{WEBMIN_CONFIG} and -e "module.info") { + my @data = slurp("module.info"); + foreach my $line (@data) { + if ($line =~ /^name=csf$/) { + unless (-l "index.cgi") { + unlink "index.cgi"; + my $status = symlink ("/usr/local/csf/lib/webmin/csf/index.cgi","index.cgi"); + if ($status and -l "index.cgi") { + symlink ("/usr/local/csf/lib/webmin/csf/images","csfimages"); + print "

csf updated to symlink webmin module to /usr/local/csf/lib/webmin/csf/. Click here to continue

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

Failed to symlink to /usr/local/csf/lib/webmin/csf/

\n"; + } + } + last; + } + } + } + + &getethdev; + my ($childin, $childout); + my $pid = open3($childin, $childout, $childout, "$config{IPTABLES} $config{IPTABLESWAIT} -L LOCALINPUT -n"); + my @iptstatus = <$childout>; + waitpid ($pid, 0); + chomp @iptstatus; + if ($iptstatus[0] =~ /# Warning: iptables-legacy tables present/) {shift @iptstatus} + my $status = "

Firewall Status: Enabled and Running

"; + + if (-e "/etc/csf/csf.disable") { + $status = "

Firewall Status: Disabled and Stopped

\n" + } + elsif ($config{TESTING}) { + $status = "

Firewall Status: Enabled but in Test Mode - Don't forget to disable TESTING in the Firewall Configuration

"; + } + elsif ($iptstatus[0] !~ /^Chain LOCALINPUT/) { + $status = "

Firewall Status: Enabled but Stopped

" + } + if (-e "/var/lib/csf/lfd.restart") {$status .= "

lfd restart request pending

"} + unless ($config{RESTRICT_SYSLOG}) {$status .= "

WARNING: RESTRICT_SYSLOG is disabled. See SECURITY WARNING in Firewall Configuration

\n"} + + my $tempcnt = 0; + if (! -z "/var/lib/csf/csf.tempban") { + sysopen (my $IN, "/var/lib/csf/csf.tempban", O_RDWR); + flock ($IN, LOCK_EX); + my @data = <$IN>; + close ($IN); + chomp @data; + $tempcnt = scalar @data; + } + my $tempbans = "(Currently: $tempcnt temp IP bans, "; + $tempcnt = 0; + if (! -z "/var/lib/csf/csf.tempallow") { + sysopen (my $IN, "/var/lib/csf/csf.tempallow", O_RDWR); + flock ($IN, LOCK_EX); + my @data = <$IN>; + close ($IN); + chomp @data; + $tempcnt = scalar @data; + } + $tempbans .= "$tempcnt temp IP allows)"; + + my $permcnt = 0; + if (! -z "/etc/csf/csf.deny") { + sysopen (my $IN, "/etc/csf/csf.deny", O_RDWR); + flock ($IN, LOCK_SH); + while (my $line = <$IN>) { + chomp $line; + if ($line =~ /^(\#|\n|\r)/) {next} + if ($line =~ /$ipv4reg|$ipv6reg/) {$permcnt++} + } + close ($IN); + } + my $permbans = "(Currently: $permcnt permanent IP bans)"; + + $permcnt = 0; + if (! -z "/etc/csf/csf.allow") { + sysopen (my $IN, "/etc/csf/csf.allow", O_RDWR); + flock ($IN, LOCK_SH); + while (my $line = <$IN>) { + chomp $line; + if ($line =~ /^(\#|\n|\r)/) {next} + if ($line =~ /$ipv4reg|$ipv6reg/) {$permcnt++} + } + close ($IN); + } + my $permallows = "(Currently: $permcnt permanent IP allows)"; + + print $status; + + print "
\n"; + print "

A new version of csf is available

"; + + print "
\n"; + + print "
\n"; + print "
\n"; + print "
\n"; + print "\n"; + print ""; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + if ($config{ST_ENABLE}) { + print "\n"; + if ($chart) { + print "\n"; + if ($config{ST_SYSTEM}) { + print "\n"; + } + } + } + print "
Server Information
Perform a basic security, stability and settings check on the server
View the csf+lfd readme.txt file
Watch (tail) various system log files (listed in csf.syslogs)
Search (grep) various system log files (listed in csf.syslogs)
View ports on the server that have a running process behind them listening for external connections
Check whether any of the servers IP addresses are listed in RBLs
View the last $config{ST_IPTABLES} iptables log lines
View lfd blocking statistics
View basic system statistics
\n"; + print "
\n"; + + print "
\n"; + print "\n"; + print ""; + my ($upgrade, $actv) = &csgetversion("csf",$myv); + if ($upgrade) { + print "\n"; + } else { + print "\n"; + } + else { + print "You are running the latest version of csf. An Upgrade button will appear here if a new version becomes available. New version checking is performed automatically by a daily cron job (csget)\n"; + } + } + if (!$config{INTERWORX} and (-e "/etc/apf" or -e "/usr/local/bfd")) { + print "\n"; + } + unless (-e "/etc/cxs/cxs.pl") { + if (-e "/usr/local/cpanel/version" or $config{DIRECTADMIN} or $config{INTERWORX} or $config{VESTA} or $config{CWP} or $config{CYBERPANEL}) { + print "\n"; + } + } + unless (-e "/etc/osm/osmd.pl") { + if (-e "/usr/local/cpanel/version" or $config{DIRECTADMIN}) { + print "\n"; + } + } + unless (-e "/usr/msfe/mschange.pl") { + if (-e "/usr/local/cpanel/version" or $config{DIRECTADMIN}) { + print "\n"; + } + } + print "
Upgrade
A new version of csf (v$actv) is available. Upgrading will retain your settings
View ChangeLog
"; + if ($actv ne "") { + print "(csget cron check) $actv
Remove APF/BFD from the server. You must not run both APF or BFD with csf on the same server
\n"; + print "
Add server and user data protection against exploits using ConfigServer eXploit Scanner (cxs)
\n"; + print "
\n"; + print "
Add outgoing spam monitoring and prevention using ConfigServer Outgoing Spam Monitor(osm)
\n"; + print "
\n"; + print "
Add effective incoming virus and spam detection and user level processing using ConfigServer MailScanner Front-End (msfe)
\n"; + print "
\n"; + print "
\n"; + if ($upgrade) {print "\n"} + print "
\n"; + + print "
\n"; + print "\n"; + print ""; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "
csf - Quick Actions
Allow IP address through the firewall and add to the allow file (csf.allow).
Comment for Allow:
Block IP address in the firewall and add to the deny file (csf.deny).
Comment for Block:
Ignore IP address in lfd, add to the ignore file (csf.ignore) and restart lfd
Remove IP address from the firewall (temp and perm blocks)
\n"; + + print "\n"; + print ""; + 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 "\n"; + print "
csf - ConfigServer Firewall
Edit the configuration file for the csf firewall and lfd
Apply pre-configured csf.conf profiles and backup/restore csf.conf
Display the active iptables rules
Search iptables for IP address
Edit csf.allow, the IP address allow file $permallows
Edit csf.deny, the IP address deny file $permbans
Enables csf and lfd if previously Disabled
Completely disables csf and lfd
Restart the csf iptables firewall
Have lfd restart the csf iptables firewall
Temporarily IP address to port(s) for .
Comment:
\n(ports can be either * for all ports, a single port, or a comma separated list of ports)
View/Remove the temporary IP entries $tempbans
Deny access to and from specific IP addresses configured on the server (csf.sips)
Removes and unblocks all entries in csf.deny (excluding those marked \"do not delete\") and all temporary IP entries (blocks and allows)
Redirect connections to this server to other ports/IP addresses
Offers solutions to some common problems when using an SPI firewall
\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 "\n"; + print "\n"; + print "
lfd - Login Failure Daemon
Display lfd status
Restart lfd
Edit lfd ignore file
Edit the Directory File Watching file (csf.dirwatch) - all listed files and directories will be watched for changes by lfd
Edit the Dynamic DNS file (csf.dyndns) - all listed domains will be resolved and allowed through the firewall
Edit email alert templates. See Firewall Information for details of each file
Edit the Log Scanner file (csf.logfiles) - Scan listed log files for log lines and periodically send a report
Edit the Blocklists configuration file (csf.blocklists)
Edit the syslog/rsyslog allowed users file (csf.syslogusers)
\n"; + print "
\n"; + + if ($config{CLUSTER_SENDTO}) { + print "
\n"; + print "\n"; + print ""; + + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + + if ($config{CLUSTER_CONFIG}) { + if ($ips{$config{CLUSTER_MASTER}} or $ipscidr6->find($config{CLUSTER_MASTER}) or ($config{CLUSTER_MASTER} eq $config{CLUSTER_NAT})) { + my $options; + my %restricted; + if ($config{RESTRICT_UI}) { + sysopen (my $IN, "/usr/local/csf/lib/restricted.txt", O_RDWR | O_CREAT) or die "Unable to open file: $!"; + flock ($IN, LOCK_SH); + while (my $entry = <$IN>) { + chomp $entry; + $restricted{$entry} = 1; + } + close ($IN); + } + foreach my $key (sort keys %config) { + unless ($restricted{$key}) {$options .= ""} + } + print "\n"; + print "\n"; + } + } + print "
csf - ConfigServer lfd Cluster
Ping each member of the cluster (logged in lfd.log)
Allow IP address through the Cluster and add to the allow file (csf.allow)
Comment:
Block IP address in the Cluster and add to the deny file (csf.deny)
Comment:
Ignore IP address in the Cluster and add to the ignore file (csf.ignore)
Comment: Note: This will result in lfd being restarted
Search iptables for IP address
Temporarily IP address to port(s) for .
Comment:
\n(ports can be either * for all ports, a single port, or a comma separated list of ports)
Remove Deny IP address in the Cluster (temporary or permanent)
Remove Allow IP address in the Cluster (temporary or permanent)
Remove Ignore IP address in the Cluster
Note: This will result in lfd being restarted
Change configuration option to in the Cluster"; + if ($config{RESTRICT_UI}) {print "
\nSome items have been removed with RESTRICT_UI enabled"} + print "
Restart csf and lfd on Cluster members
\n"; + print "
\n"; + } + + print "
\n"; + if ($config{CF_ENABLE}) { + print "\n"; + print ""; + print "\n"; + print "\n"; + print "
CloudFlare Firewall
Access CloudFlare firewall functionality
Edit the CloudFlare Configuration file (csf.cloudflare)
\n"; + } + if ($config{SMTPAUTH_RESTRICT}) { + print "\n"; + print ""; + print "\n"; + print "
cPanel SMTP AUTH Restrictions
Edit the file that allows SMTP AUTH to be advertised to listed IP addresses (csf.smtpauth)
\n"; + } + + if (-e "/usr/local/cpanel/version" or $config{DIRECTADMIN} or $config{INTERWORX}) { + my $resellers = "cPanel Resellers"; + if ($config{DIRECTADMIN}) {$resellers = "DirectAdmin Resellers"} + elsif ($config{INTERWORX}) {$resellers = "InterWorx Resellers"} + print "\n"; + print ""; + print "\n"; + print "
$resellers
Privileges can be assigned to $resellers accounts by editing this file (csf.resellers)
\n"; + } + + print "\n"; + print ""; + print "\n"; + print "
Extra
Check that iptables has the required modules to run csf
\n"; +# if ($config{DIRECTADMIN} and !$config{THIS_UI}) { +# print " DirectAdmin Main Page\n"; +# } + print "
\n
\n"; + + if ($config{STYLE_MOBILE}) { + if (-e "/usr/local/cpanel/version" and !$config{THIS_UI}) { + require Cpanel::Version::Tiny; + if ($Cpanel::Version::Tiny::major_version < 65) { + print " cPanel Main Page\n"; + } + } + if (defined $ENV{WEBMIN_VAR} and defined $ENV{WEBMIN_CONFIG} and !$config{THIS_UI}) { + print " Webmin Main Page\n"; + } + print "
Shows a subset of functions suitable for viewing on mobile devices
\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 "
\n"; + print "
\n"; + + if (-e "/usr/local/cpanel/version" and !$config{THIS_UI}) { + if ($Cpanel::Version::Tiny::major_version < 65) { + print "

cPanel Main Page

\n"; + } + } +# if ($config{DIRECTADMIN} and !$config{THIS_UI}) { +# print "

DirectAdmin Main Page

\n"; +# } + if (defined $ENV{WEBMIN_VAR} and defined $ENV{WEBMIN_CONFIG} and !$config{THIS_UI}) { + print "

Webmin Main Page

\n"; + } + + print "

\n"; + print "
\n

\n"; + } + + print "
\n"; + print "
Development Contribution
"; + print "
We are very happy to be able to provide this and other products for free. However, it does take time for us to develop and maintain them. If you would like to help with their development by providing a PayPal contribution, please contact us for details
\n"; + print "
\n"; + + } + + unless ($FORM{action} eq "tailcmd" or $FORM{action} =~ /^cf/ or $FORM{action} eq "logtailcmd" or $FORM{action} eq "loggrepcmd") { + print "
\n"; + print "
csf: v$myv
"; + print "

©2006-2023, ConfigServer Services (Way to the Web Limited)

\n"; + print "
\n"; + } + + return; +} +# 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 +############################################################################### +# start getethdev +sub getethdev { + my $ethdev = ConfigServer::GetEthDev->new(); + my %g_ipv4 = $ethdev->ipv4; + my %g_ipv6 = $ethdev->ipv6; + 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); + }; + } + } + + return; +} +# end getethdev +############################################################################### +# start chart +sub chart { + my $img; + my $imgdir = ""; + my $imghddir = ""; + if (-e "/usr/local/cpanel/version") { + $imgdir = "/"; + $imghddir = ""; + } + elsif (-e "/usr/local/directadmin/conf/directadmin.conf") { + $imgdir = "/CMD_PLUGINS_ADMIN/csf/images/"; + $imghddir = "plugins/csf/images/"; + umask(0133); + } + elsif (-e "/usr/local/interworx") { + $imgdir = "/configserver/csf/"; + $imghddir = "/usr/local/interworx/html/configserver/csf/"; + umask(0133); + } + elsif (-e "/usr/local/CyberCP/") { + $imgdir = "/static/configservercsf/"; + $imghddir = "/usr/local/CyberCP/public/static/configservercsf/"; + umask(0133); + } + if ($config{THIS_UI}) { + $imgdir = "$images/"; + $imghddir = "/etc/csf/ui/images/"; + } + + my $STATS; + if (-e "/var/lib/csf/stats/lfdstats") { + sysopen ($STATS,"/var/lib/csf/stats/lfdstats", O_RDWR | O_CREAT); + } + elsif (-e "/var/lib/csf/stats/lfdmain") { + sysopen (my $OLDSTATS,"/var/lib/csf/stats/lfdmain", O_RDWR | O_CREAT); + flock ($OLDSTATS, LOCK_EX); + my @stats = <$OLDSTATS>; + chomp @stats; + + my @newstats; + my $cnt = 0; + foreach my $line (@stats) { + if ($cnt == 55) {push @newstats,""} + push @newstats,$line; + $cnt++; + } + sysopen ($STATS,"/var/lib/csf/stats/lfdstats", O_RDWR | O_CREAT); + flock ($STATS, LOCK_EX); + seek ($STATS, 0, 0); + truncate ($STATS, 0); + foreach my $line (@newstats) { + print $STATS "$line\n"; + } + close ($STATS); + + rename "/var/lib/csf/stats/lfdmain", "/var/lib/csf/stats/lfdmain.".time; + close ($OLDSTATS); + sysopen ($STATS,"/var/lib/csf/stats/lfdstats", O_RDWR | O_CREAT); + } else { + sysopen ($STATS,"/var/lib/csf/stats/lfdstats", O_RDWR | O_CREAT); + } + flock ($STATS, LOCK_SH); + my @stats = <$STATS>; + chomp @stats; + close ($STATS); + + if (@stats) { + ConfigServer::ServerStats::charts($config{CC_LOOKUPS},$imghddir); + print ConfigServer::ServerStats::charts_html($config{CC_LOOKUPS},$imgdir); + } else { + print "\n"; + print "
No statistical data has been collected yet
\n"; + } + &printreturn; + + return; +} +# end chart +############################################################################### +# start systemstats +sub systemstats { + my $type = shift; + if ($type eq "") {$type = "load"} + my $img; + my $imgdir = ""; + my $imghddir = ""; + if (-e "/usr/local/cpanel/version") { + if (-e "/usr/local/cpanel/bin/register_appconfig") { + $imgdir = "csf/"; + $imghddir = "cgi/configserver/csf/"; + } else { + $imgdir = "/"; + $imghddir = ""; + } + } + elsif (-e "/usr/local/directadmin/conf/directadmin.conf") { + $imgdir = "/CMD_PLUGINS_ADMIN/csf/images/"; + $imghddir = "plugins/csf/images/"; + umask(0133); + } + elsif (-e "/usr/local/interworx") { + $imgdir = "/configserver/csf/"; + $imghddir = "/usr/local/interworx/html/configserver/csf/"; + umask(0133); + } + elsif (-e "/usr/local/CyberCP/") { + $imgdir = "/static/configservercsf/"; + $imghddir = "/usr/local/CyberCP/public/static/configservercsf/"; + umask(0133); + } + if ($config{THIS_UI}) { + $imgdir = "$images/"; + $imghddir = "/etc/csf/ui/images/"; + } + if (defined $ENV{WEBMIN_VAR} and defined $ENV{WEBMIN_CONFIG}) { + $imgdir = "/csf/"; + $imghddir = ""; + } + + sysopen (my $STATS,"/var/lib/csf/stats/system", O_RDWR | O_CREAT); + flock ($STATS, LOCK_SH); + my @stats = <$STATS>; + chomp @stats; + close ($STATS); + + if (@stats > 1) { + ConfigServer::ServerStats::graphs($type,$config{ST_SYSTEM_MAXDAYS},$imghddir); + + print "

\n"; + + print ConfigServer::ServerStats::graphs_html($imgdir); + + unless ($config{ST_MYSQL} and $config{ST_APACHE}) { + print "
\n\n"; + print "
You may be able to collect more statistics by enabling ST_MYSQL or ST_APACHE in the csf configuration
\n"; + } + } else { + print "\n"; + print "
No statistical data has been collected yet
\n"; + } + &printreturn; + + return; +} +# end systemstats +############################################################################### +# start editfile +sub editfile { + my $file = shift; + my $save = shift; + my $extra = shift; + my $ace = 0; + + sysopen (my $IN, $file, O_RDWR | O_CREAT) or die "Unable to open file: $!"; + flock ($IN, LOCK_SH); + my @confdata = <$IN>; + close ($IN); + chomp @confdata; + + if (-e "/usr/local/cpanel/3rdparty/share/ace-editor/optimized/src-min-noconflict/ace.js") {$ace = 1} + + if (-e "/usr/local/cpanel/version" and $ace and !$config{THIS_UI}) { + print "\n"; + print "

Edit $file

\n"; + print "\n"; + print "
\n"; + print "
\n"; + print "
\n"; + print "\n"; + print "\n"; + if ($extra) {print "\n";} + print "\n"; + print "

\n"; + print "
\n"; + print "
\n"; + print < + var myFont = 14; + var textarea = \$('#formdata'); + var editordiv = \$('#editor'); + var editor = ace.edit("editor"); + editor.setTheme("ace/theme/tomorrow"); + editor.setShowPrintMargin(false); + editor.setOptions({ + fontFamily: "Courier New, Courier", + fontSize: "14px" + }); + editor.getSession().setMode("ace/mode/space"); + + editor.getSession().on('change', function () { + textarea.val(editor.getSession().getValue()); + }); + + textarea.on('change', function () { + editor.getSession().setValue(textarea.val()); + }); + + editor.getSession().setValue(textarea.val()); + \$('#textarea').hide(); + editordiv.show(); + + \$("#toggletextarea-btn").on('click', function () { + \$('#textarea').toggle(); + editordiv.toggle(); + }); + \$("#fontplus-btn").on('click', function () { + myFont++; + if (myFont > 20) {myFont = 20} + editor.setFontSize(myFont) + textarea.css("font-size",myFont+"px"); + }); + \$("#fontminus-btn").on('click', function () { + myFont--; + if (myFont < 12) {myFont = 12} + editor.setFontSize(myFont) + textarea.css("font-size",myFont+"px"); + }); + +EOF + } else { + if ($config{DIRECTADMIN}) { + print "
\n
\n"; + } else { + print "\n
\n"; + } + print "
Edit $file
\n"; + print "
\n"; + print "\n"; + if ($extra) {print "\n";} + print "
\n"; + print "\n"; + print "
\n"; + } + + return; +} +# end editfile +############################################################################### +# start savefile +sub savefile { + my $file = shift; + my $restart = shift; + + $FORM{formdata} =~ s/\r//g; + if ($FORM{ace} == "1") { + if ($FORM{formdata} !~ /^# Do not remove or change this line as it is a safeguard for the UI editor\n/) { + print "
UI editor safeguard missing, changes have not been saved.
\n"; + return; + } + $FORM{formdata} =~ s/^# Do not remove or change this line as it is a safeguard for the UI editor\n//g; + } + + sysopen (my $OUT, $file, O_WRONLY | O_CREAT) or die "Unable to open file: $!"; + flock ($OUT, LOCK_EX); + seek ($OUT, 0, 0); + truncate ($OUT, 0); + if ($FORM{formdata} !~ /\n$/) {$FORM{formdata} .= "\n"} + print $OUT $FORM{formdata}; + close ($OUT); + + if ($restart eq "csf") { + print "
Changes saved. You should restart csf.
\n"; + print "
\n"; + } + elsif ($restart eq "lfd") { + print "
Changes saved. You should restart lfd.
\n"; + print "
\n"; + } + elsif ($restart eq "both") { + print "
Changes saved. You should restart csf and lfd.

\n"; + print "
\n"; + } + else { + print "
Changes saved.
\n"; + } + + return; +} +# end cloudflare +############################################################################### +# start cloudflare +sub cloudflare { + my $scope = &ConfigServer::CloudFlare::getscope(); + print "\n"; + print "\n"; + print "\n"; + + print "\n"; + print ""; + print "\n"; +# } else { +# print "\n"; +# } + print ""; + print "\n"; + print "\n"; + print ""; + print "
csf - CloudFlare
Select the user(s), then select the action below
Select the domain(s), then select the action below
List rules in CloudFlare ONLY for the chosen accounts
Add rule for target in CloudFlare ONLY for the chosen accounts
Delete rule for target in CloudFlare ONLY
Temporarily IP address for $config{CF_TEMP} secs in CloudFlare AND csf for the chosen accounts and those with to \"any\"
\n"; + print "
Output will appear here
\n"; + print "
Note:\n
    \n"; + print "
  • target can be one of:
    • An IP address
    • \n
    • 2 letter Country Code
    • \n
    • IP range CIDR
    \n
  • \n"; + print "
  • Only Enterprise customers can block a Country Code, but all can allow and challenge\n"; + print "
  • \nIP range CIDR is limited to /16 and /24
\n"; + print "\n"; + &printreturn; + return; +} +# end cloudflare +############################################################################### +# start resize +sub resize { + my $part = shift; + my $scroll = shift; + if ($part eq "top") { + print "
\n"; + print "
\n"; + } else { + print " +EOF + } + return; +} +# end resize +############################################################################### +# start printreturn +sub printreturn { + print "
\n"; + + return; +} +# end printreturn +############################################################################### +# start confirmmodal +# print "\n"; +# &confirmmodal; +sub confirmmodal { + print "\n"; + print "\n"; + return; +} +# end confirmmodal +############################################################################### +# start csgetversion +sub csgetversion { + my $product = shift; + my $current = shift; + my $upgrade = 0; + my $newversion; + if (-e "/var/lib/configserver/".$product.".txt.error") { + open (my $VERSION, "<", "/var/lib/configserver/".$product.".txt.error"); + flock ($VERSION, LOCK_SH); + $newversion = <$VERSION>; + close ($VERSION); + chomp $newversion; + if ($newversion eq "") { + $newversion = "Failed to retrieve latest version from ConfigServer"; + } else { + $newversion = "Failed to retrieve latest version from ConfigServer: $newversion"; + } + } + elsif (-e "/var/lib/configserver/".$product.".txt") { + open (my $VERSION, "<", "/var/lib/configserver/".$product.".txt"); + flock ($VERSION, LOCK_SH); + $newversion = <$VERSION>; + close ($VERSION); + chomp $newversion; + if ($newversion eq "") { + $newversion = "Failed to retrieve latest version from ConfigServer"; + } else { + if ($newversion =~ /^[\d\.]*$/) { + if ($newversion > $current) {$upgrade = 1} else {$newversion = ""} + } else {$newversion = ""} + } + } + elsif (-e "/var/lib/configserver/error") { + open (my $VERSION, "<", "/var/lib/configserver/error"); + flock ($VERSION, LOCK_SH); + $newversion = <$VERSION>; + close ($VERSION); + chomp $newversion; + if ($newversion eq "") { + $newversion = "Failed to retrieve latest version from ConfigServer"; + } else { + $newversion = "Failed to retrieve latest version from ConfigServer: $newversion"; + } + } else { + $newversion = "Failed to retrieve latest version from ConfigServer"; + } + return ($upgrade, $newversion); +} +# end csgetversion +############################################################################### +# start manualversion +sub manualversion { + my $current = shift; + my $upgrade = 0; + my $url = "https://$config{DOWNLOADSERVER}/csf/version.txt"; + if ($config{URLGET} == 1) {$url = "http://$config{DOWNLOADSERVER}/csf/version.txt";} + my ($status, $newversion) = $urlget->urlget($url); + if (!$status and $newversion ne "" and $newversion =~ /^[\d\.]*$/ and $newversion > $current) {$upgrade = 1} else {$newversion = ""} + return ($upgrade, $newversion); +} +# end manualversion +############################################################################### + +1; diff --git a/src/redux/ConfigServer/GetEthDev.pm b/src/redux/ConfigServer/GetEthDev.pm new file mode 100644 index 000000000..e9fbcd8ce --- /dev/null +++ b/src/redux/ConfigServer/GetEthDev.pm @@ -0,0 +1,157 @@ +############################################################################### +# Copyright 2006-2023, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +## no critic (RequireUseWarnings, ProhibitExplicitReturnUndef, ProhibitMixedBooleanOperators, RequireBriefOpen) +# start main +package ConfigServer::GetEthDev; + +use strict; +use lib '/usr/local/csf/lib'; +use Carp; +use Fcntl qw(:DEFAULT :flock); +use IPC::Open3; +use POSIX qw(locale_h); +use ConfigServer::Config; +use ConfigServer::CheckIP qw(checkip); +use ConfigServer::Logger; + +use Exporter qw(import); +our $VERSION = 1.01; +our @ISA = qw(Exporter); +our @EXPORT_OK = qw(); + +my (%ifaces, %ipv4, %ipv6, %brd); + +# end main +############################################################################### +# start new +sub new { + my $class = shift; + my $self = {}; + bless $self,$class; + + my $status; + my $config = ConfigServer::Config->loadconfig(); + my %config = $config->config(); + my $ipv4reg = $config->ipv4reg; + my $ipv6reg = $config->ipv6reg; + $brd{"255.255.255.255"} = 1; + setlocale(LC_ALL, "POSIX"); + + if (-e $config{IP}) { + my ($childin, $childout); + my $pid = open3($childin, $childout, $childout, $config{IP}, "-oneline", "addr"); + my @ifconfig = <$childout>; + waitpid ($pid, 0); + chomp @ifconfig; + + foreach my $line (@ifconfig) { + if ($line =~ /^\d+:\s+([\w\.\-]+)/ ) { + $ifaces{$1} = 1; + } + if ($line =~ /inet.*?($ipv4reg)/) { + my ($ip,undef) = split(/\//,$1); + if (checkip(\$ip)) { + $ipv4{$ip} = 1; + } + } + if ($line =~ /brd\s+($ipv4reg)/) { + my ($ip,undef) = split(/\//,$1); + if (checkip(\$ip)) { + $brd{$ip} = 1; + } + } + if ($line =~ /inet6.*?($ipv6reg)/) { + my ($ip,undef) = split(/\//,$1); + $ip .= "/128"; + if (checkip(\$ip)) { + $ipv6{$ip} = 1; + } + } + } + $status = 0; + } + elsif (-e $config{IFCONFIG}) { + my ($childin, $childout); + my $pid = open3($childin, $childout, $childout, $config{IFCONFIG}); + my @ifconfig = <$childout>; + waitpid ($pid, 0); + chomp @ifconfig; + + foreach my $line (@ifconfig) { + if ($line =~ /^([\w\.\-]+)/ ) { + $ifaces{$1} = 1; + } + if ($line =~ /inet.*?($ipv4reg)/) { + my ($ip,undef) = split(/\//,$1); + if (checkip(\$ip)) { + $ipv4{$ip} = 1; + } + } + if ($line =~ /Bcast:($ipv4reg)/) { + my ($ip,undef) = split(/\//,$1); + if (checkip(\$ip)) { + $brd{$ip} = 1; + } + } + if ($line =~ /inet6.*?($ipv6reg)/) { + my ($ip,undef) = split(/\//,$1); + $ip .= "/128"; + if (checkip(\$ip)) { + $ipv6{$ip} = 1; + } + } + } + $status = 0; + } + else { + $status = 1; + } + + if (-e "/var/cpanel/cpnat") { + open (my $NAT, "<", "/var/cpanel/cpnat"); + flock ($NAT, LOCK_SH); + while (my $line = <$NAT>) { + chomp $line; + if ($line =~ /^(\#|\n|\r)/) {next} + my ($internal,$external) = split(/\s+/,$line); + if (checkip(\$internal) and checkip(\$external)) { + $ipv4{$external} = 1; + } + } + close ($NAT); + } + + $self->{status} = $status; + return $self; +} +# end main +############################################################################### +# start ifaces +sub ifaces { + return %ifaces; +} +# end ifaces +############################################################################### +# start ipv4 +sub ipv4 { + return %ipv4; +} +# end ipv4 +############################################################################### +# start ipv6 +sub ipv6 { + return %ipv6; +} +# end ipv6 +############################################################################### +# start brd +sub brd { + return %brd; +} +# end brd +############################################################################### + +1; \ No newline at end of file diff --git a/src/redux/ConfigServer/GetIPs.pm b/src/redux/ConfigServer/GetIPs.pm new file mode 100644 index 000000000..0139e60bb --- /dev/null +++ b/src/redux/ConfigServer/GetIPs.pm @@ -0,0 +1,82 @@ +############################################################################### +# Copyright 2006-2023, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +## no critic (RequireUseWarnings, ProhibitExplicitReturnUndef, ProhibitMixedBooleanOperators, RequireBriefOpen) +# start main +package ConfigServer::GetIPs; + +use strict; +use lib '/usr/local/csf/lib'; +use Carp; +use Socket; +use IPC::Open3; +use ConfigServer::Config; + +use Exporter qw(import); +our $VERSION = 1.03; +our @ISA = qw(Exporter); +our @EXPORT_OK = qw(getips); + +my $config = ConfigServer::Config->loadconfig(); +my %config = $config->config(); +my $ipv4reg = ConfigServer::Config->ipv4reg; +my $ipv6reg = ConfigServer::Config->ipv6reg; + +# end main +############################################################################### +# start getips +sub getips { + my $hostname = shift; + my @ips; + + if (-e $config{HOST} and -x $config{HOST}) { + my $cmdpid; + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die}; + alarm(10); + my ($childin, $childout); + $cmdpid = open3($childin, $childout, $childout, $config{HOST},"-W","5",$hostname); + close $childin; + my @results = <$childout>; + waitpid ($cmdpid, 0); + chomp @results; + + foreach my $line (@results) { + if ($line =~ /($ipv4reg|$ipv6reg)/) {push @ips, $1} + } + alarm(0); + }; + alarm(0); + if ($cmdpid =~ /\d+/ and $cmdpid > 1 and kill(0,$cmdpid)) {kill(9,$cmdpid)} + } else { + local $SIG{__DIE__} = undef; + eval ('use Socket6;'); + if ($@) { + my @iplist; + my (undef, undef, undef, undef, @addrs) = gethostbyname($hostname); + foreach (@addrs) {push(@iplist,join(".",unpack("C4", $_)))} + push @ips,$_ foreach(@iplist); + } else { + eval (' + use Socket6; + my @res = getaddrinfo($hostname, undef, AF_UNSPEC, SOCK_STREAM); + while(scalar(@res)>=5){ + my $saddr; + (undef, undef, undef, $saddr, undef, @res) = @res; + my ($host, undef) = getnameinfo($saddr,NI_NUMERICHOST | NI_NUMERICSERV); + push @ips,$host; + + } + '); + } + } + + return @ips; +} +# end getips +############################################################################### + +1; \ No newline at end of file diff --git a/src/redux/ConfigServer/KillSSH.pm b/src/redux/ConfigServer/KillSSH.pm new file mode 100644 index 000000000..e68bfad59 --- /dev/null +++ b/src/redux/ConfigServer/KillSSH.pm @@ -0,0 +1,94 @@ +############################################################################### +# Copyright 2006-2023, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +## no critic (RequireUseWarnings, ProhibitExplicitReturnUndef, ProhibitMixedBooleanOperators, RequireBriefOpen) +# start main +package ConfigServer::KillSSH; + +use strict; +use lib '/usr/local/csf/lib'; +use Fcntl qw(:DEFAULT :flock); +use ConfigServer::Logger; + +use Exporter qw(import); +our $VERSION = 1.00; +our @ISA = qw(Exporter); +our @EXPORT_OK = qw(); + +# end main +############################################################################### +# start iplookup +sub find { + my $ip = shift; + my $ports = shift; + + my %inodes; + + if ($ports eq "" or $ip eq "") {return} + + foreach my $proto ("tcp","tcp6") { + open (my $IN, "<", "/proc/net/$proto"); + flock ($IN, LOCK_SH); + while (<$IN>) { + my @rec = split(); + if ($rec[9] =~ /uid/) {next} + + my ($dip,$dport) = split(/:/,$rec[2]); + $dport = hex($dport); + + my ($sip,$sport) = split(/:/,$rec[1]); + $sport = hex($sport); + + $dip = &hex2ip($dip); + $sip = &hex2ip($sip); + + if ($sip eq '0.0.0.1') {next} + if ($dip eq $ip) { + foreach my $port (split(/\,/, $ports)) { + if ($port eq $sport) { + $inodes{$rec[9]} = 1; + } + } + } + } + close ($IN); + } + + opendir (my $PROCDIR, "/proc"); + while (my $pid = readdir($PROCDIR)) { + if ($pid !~ /^\d+$/) {next} + opendir (DIR, "/proc/$pid/fd") or next; + while (my $file = readdir (DIR)) { + if ($file =~ /^\./) {next} + my $fd = readlink("/proc/$pid/fd/$file"); + if ($fd =~ /^socket:\[?([0-9]+)\]?$/) { + if ($inodes{$1} and readlink("/proc/$pid/exe") =~ /sshd/) { + kill (9,$pid); + ConfigServer::Logger::logfile("*PT_SSHDKILL*: Process PID:[$pid] killed for blocked IP:[$ip]"); + } + } + } + closedir (DIR); + } + closedir ($PROCDIR); + return; +} +# end find +############################################################################### +## start hex2ip +sub hex2ip { + my $bin = pack "C*" => map hex, $_[0] =~ /../g; + my @l = unpack "L*", $bin; + if (@l == 4) { + return join ':', map { sprintf "%x:%x", $_ >> 16, $_ & 0xffff } @l; + } + elsif (@l == 1) { + return join '.', map { $_ >> 24, ($_ >> 16 ) & 0xff, ($_ >> 8) & 0xff, $_ & 0xff } @l; + } +} +## end hex2ip +############################################################################### + +1; \ No newline at end of file diff --git a/src/redux/ConfigServer/Logger.pm b/src/redux/ConfigServer/Logger.pm new file mode 100644 index 000000000..250946e2a --- /dev/null +++ b/src/redux/ConfigServer/Logger.pm @@ -0,0 +1,70 @@ +############################################################################### +# Copyright 2006-2023, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +## no critic (RequireUseWarnings, ProhibitExplicitReturnUndef, ProhibitMixedBooleanOperators, RequireBriefOpen) +# start main +package ConfigServer::Logger; + +use strict; +use lib '/usr/local/csf/lib'; +use Carp; +use Fcntl qw(:DEFAULT :flock); +use ConfigServer::Config; + +use Exporter qw(import); +our $VERSION = 1.02; +our @ISA = qw(Exporter); +our @EXPORT_OK = qw(logfile); + +my $config = ConfigServer::Config->loadconfig(); +my %config = $config->config(); +my $hostname; +if (-e "/proc/sys/kernel/hostname") { + open (my $IN, "<", "/proc/sys/kernel/hostname"); + flock ($IN, LOCK_SH); + $hostname = <$IN>; + chomp $hostname; + close ($IN); +} else { + $hostname = "unknown"; +} +my $hostshort = (split(/\./,$hostname))[0]; + +my $sys_syslog; +if ($config{SYSLOG}) { + eval('use Sys::Syslog;'); ##no critic + unless ($@) {$sys_syslog = 1} +} + +# end main +############################################################################### +# start logfile +sub logfile { + my $line = shift; + my @ts = split(/\s+/,scalar localtime); + if ($ts[2] < 10) {$ts[2] = " ".$ts[2]} + + my $logfile = "/var/log/lfd.log"; + if ($< != 0) {$logfile = "/var/log/lfd_messenger.log"} + + sysopen (my $LOGFILE, $logfile, O_WRONLY | O_APPEND | O_CREAT); + flock ($LOGFILE, LOCK_EX); + print $LOGFILE "$ts[1] $ts[2] $ts[3] $hostshort lfd[$$]: $line\n"; + close ($LOGFILE); + + if ($config{SYSLOG} and $sys_syslog) { + eval { + local $SIG{__DIE__} = undef; + openlog('lfd', 'ndelay,pid', 'user'); + syslog('info', $line); + closelog(); + } + } + return; +} +# end logfile +############################################################################### + +1; \ No newline at end of file diff --git a/src/redux/ConfigServer/LookUpIP.pm b/src/redux/ConfigServer/LookUpIP.pm new file mode 100644 index 000000000..c6cd6c156 --- /dev/null +++ b/src/redux/ConfigServer/LookUpIP.pm @@ -0,0 +1,426 @@ +############################################################################### +# Copyright 2006-2023, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +## no critic (RequireUseWarnings, ProhibitExplicitReturnUndef, ProhibitMixedBooleanOperators, RequireBriefOpen) +# start main +package ConfigServer::LookUpIP; + +use strict; +use lib '/usr/local/csf/lib'; +use Carp; +use Fcntl qw(:DEFAULT :flock); +use IPC::Open3; +use JSON::Tiny; +use Net::IP; +use Socket; +use ConfigServer::CheckIP qw(checkip); +use ConfigServer::Config; +use ConfigServer::URLGet; + +use Exporter qw(import); +our $VERSION = 2.00; +our @ISA = qw(Exporter); +our @EXPORT_OK = qw(iplookup); + +my $config = ConfigServer::Config->loadconfig(); +my %config = $config->config(); + +my $urlget; +if ($config{CC_LOOKUPS} == 4) { + $urlget = ConfigServer::URLGet->new($config{URLGET}, "", $config{URLPROXY}); + unless (defined $urlget) { + $config{URLGET} = 1; + $urlget = ConfigServer::URLGet->new($config{URLGET}, "", $config{URLPROXY}); + } +} + +# end main +############################################################################### +# start iplookup +sub iplookup { + my $ip = shift; + my $cconly = shift; + my $host = "-"; + my $iptype = checkip(\$ip); + + if ($config{LF_LOOKUPS} and !$cconly) { + my $dnsip; + my $dnsrip; + my $dnshost; + my $cachehit; + open (my $DNS, "<", "/var/lib/csf/csf.dnscache"); + flock ($DNS, LOCK_SH); + while (my $line = <$DNS>) { + chomp $line; + ($dnsip,$dnsrip,$dnshost) = split(/\|/,$line); + if ($ip eq $dnsip) { + $cachehit = 1; + last; + } + } + close ($DNS); + if ($cachehit) { + $host = $dnshost; + } else { + if (-e $config{HOST} and -x $config{HOST}) { + my $cmdpid; + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die}; + alarm(10); + my ($childin, $childout); + $cmdpid = open3($childin, $childout, $childout, $config{HOST},"-W","5",$ip); + close $childin; + my @results = <$childout>; + waitpid ($cmdpid, 0); + chomp @results; + if ($results[0] =~ /(\S+)\.$/) {$host = $1} + alarm(0); + }; + alarm(0); + if ($cmdpid =~ /\d+/ and $cmdpid > 1 and kill(0,$cmdpid)) {kill(9,$cmdpid)} + } else { + if ($iptype == 4) { + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die}; + alarm(10); + my $ipaddr = inet_aton($ip); + $host = gethostbyaddr($ipaddr, AF_INET); + alarm(0); + }; + alarm(0); + } + elsif ($iptype == 6) { + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die}; + alarm(10); + eval('use Socket6;'); ##no critic + my $ipaddr = inet_pton(AF_INET6, $ip); + $host = gethostbyaddr($ipaddr, AF_INET6); + alarm(0); + }; + alarm(0); + } + } + sysopen (DNS, "/var/lib/csf/csf.dnscache", O_WRONLY | O_APPEND | O_CREAT); + flock (DNS, LOCK_EX); + print DNS "$ip|$ip|$host\n"; + close (DNS); + } + if ($host eq "") {$host = "-"} + } + + if (($config{CC_LOOKUPS} and $iptype == 4) or ($config{CC_LOOKUPS} and $config{CC6_LOOKUPS} and $iptype == 6)) { + my @result; + eval { + local $SIG{__DIE__} = undef; + @result = &geo_binary($ip,$iptype); + }; + my $asn = $result[4]; + if ($result[0] eq "") {$result[0] = "-"} + if ($result[1] eq "") {$result[1] = "-"} + if ($result[2] eq "") {$result[2] = "-"} + if ($result[3] eq "") {$result[3] = "-"} + if ($result[4] eq "") {$result[4] = "-"} else {$result[4] = "[$result[4]]"} + if ($config{CC_LOOKUPS} == 3) { + if ($cconly) {return ($result[0],$asn)} + my $return = "$ip ($result[0]/$result[1]/$result[2]/$result[3]/$host/$result[4])"; + if ($result[0] eq "-") {$return = "$ip ($host)"} + $return =~ s/'|"//g; + return $return; + } + elsif ($config{CC_LOOKUPS} == 2 or $config{CC_LOOKUPS} == 4) { + if ($cconly) {return $result[0]} + my $return = "$ip ($result[0]/$result[1]/$result[2]/$result[3]/$host)"; + if ($result[0] eq "-") {$return = "$ip ($host)"} + $return =~ s/'|"//g; + return $return; + } + else { + if ($cconly) {return $result[0]} + my $return = "$ip ($result[0]/$result[1]/$host)"; + if ($result[0] eq "-") {$return = "$ip ($host)"} + $return =~ s/'|"//g; + return $return; + } + } + + if ($config{LF_LOOKUPS}) { + if ($host eq "-") {$host = "Unknown"} + my $return = "$ip ($host)"; + $return =~ s/'//g; + return $return; + } else { + return $ip; + } +} +# end iplookup +############################################################################### +# start geo_binary +sub geo_binary { + my $myip = shift; + my $ipv = shift; + my @return; + + my $netip = Net::IP->new($myip); + my $ip = $netip->binip(); + my $type = $netip->iptype(); + if ($type eq "PRIVATE") {return} + + if ($config{CC_LOOKUPS} == 4) { + my ($status, $text) = $urlget->urlget("http://api.db-ip.com/v2/free/$myip"); + if ($status) {$text = ""} + if ($text ne "") { + my $json = JSON::Tiny::decode_json($text); + return ($json->{countryCode},$json->{countryName},$json->{stateProv},$json->{city}); + } else { + return; + } + return; + } + + if ($config{CC_SRC} eq "" or $config{CC_SRC} eq "1") { + my $file = "/var/lib/csf/Geo/GeoLite2-Country-Blocks-IPv${ipv}.csv"; + if ($config{CC_LOOKUPS} == 2 or $config{CC_LOOKUPS} == 3) { + $file = "/var/lib/csf/Geo/GeoLite2-City-Blocks-IPv${ipv}.csv"; + } + my $start = 0; + my $end = -s $file; + $end += 4; + my $cnt = 0; + my $last; + my $range; + my $geoid; + open (my $CSV, "<", $file); + flock ($CSV, LOCK_SH); + while (1) { + my $mid = int (($end + $start) / 2); + seek ($CSV, $mid, 0); + my $a = <$CSV>; + my $b = <$CSV>; + chomp $b; + ($range,$geoid,undef) = split(/\,/,$b); + if ($range !~ /^\d/ or $range eq $last or $range eq "") {return} + $last = $range; + my $netip = Net::IP->new($range); + my $lastip = $netip->last_ip(); + $lastip = Net::IP::ip_iptobin($lastip,$ipv); + my $firstip = $netip->ip(); + $firstip = Net::IP::ip_iptobin($firstip,$ipv); + if (Net::IP::ip_bincomp($ip,'lt',$firstip) == 1) { + $end = $mid; + } + elsif (Net::IP::ip_bincomp($ip,'gt',$lastip) == 1) { + $start = $mid; + } else { + last; + } + $cnt++; + if ($cnt > 200) {return} + } + close ($CSV); + + if ($geoid > 0) { + my $file = "/var/lib/csf/Geo/GeoLite2-Country-Locations-en.csv"; + if ($config{CC_LOOKUPS} == 2 or $config{CC_LOOKUPS} == 3) { + $file = "/var/lib/csf/Geo/GeoLite2-City-Locations-en.csv"; + } + my $start = 0; + my $end = -s $file; + $end += 4; + my $cnt = 0; + my $last; + open (my $CSV, "<", $file); + flock ($CSV, LOCK_SH); + while (1) { + my $mid = int (($end + $start) / 2); + seek ($CSV, $mid, 0); + my $a = <$CSV>; + my $b = <$CSV>; + chomp $b; + my @bits = split(/\,/,$b); + if ($range !~ /^\d/ or $bits[0] eq $last or $bits[0] eq "") {last} + $last = $bits[0]; + if ($geoid < $bits[0]) { + $end = $mid; + } + elsif ($geoid > $bits[0]) { + $start = $mid + 1; + } else { + $b =~ s/\"//g; + my ($geoname_id, $locale_code, $continent_code, $continent_name, $country_iso_code, $country_name, $subdivision_1_iso_code, $subdivision_1_name, $subdivision_2_iso_code, $subdivision_2_name, $city_name, $metro_code, $time_zone) = split(/\,/,$b); + my $region = $subdivision_2_name; + if ($region eq "" or $region eq $city_name) {$region = $subdivision_1_name} + $return[0] = $country_iso_code; + $return[1] = $country_name; + $return[2] = $region; + $return[3] = $city_name; + last; + } + $cnt++; + if ($cnt > 200) {return} + } + close ($CSV); + } + + if ($config{CC_LOOKUPS} == 3) { + my $file = "/var/lib/csf/Geo/GeoLite2-ASN-Blocks-IPv${ipv}.csv"; + my $start = 0; + my $end = -s $file; + $end += 4; + my $cnt = 0; + my $last; + my $range; + my $asn; + my $asnorg; + open (my $CSV, "<", $file); + flock ($CSV, LOCK_SH); + while (1) { + my $mid = int (($end + $start) / 2); + seek ($CSV, $mid, 0); + my $a = <$CSV>; + my $b = <$CSV>; + chomp $b; + ($range,$asn,$asnorg) = split(/\,/,$b,3); + if ($range !~ /^\d/ or $range eq $last or $range eq "") {last} + $last = $range; + my $netip = Net::IP->new($range); + my $lastip = $netip->last_ip(); + $lastip = Net::IP::ip_iptobin($lastip,$ipv); + my $firstip = $netip->ip(); + $firstip = Net::IP::ip_iptobin($firstip,$ipv); + if (Net::IP::ip_bincomp($ip,'lt',$firstip) == 1) { + $end = $mid; + } + elsif (Net::IP::ip_bincomp($ip,'gt',$lastip) == 1) { + $start = $mid + 1; + } else { + $return[4] = "AS$asn $asnorg"; + last; + } + $cnt++; + if ($cnt > 200) {last} + } + close ($CSV); + } + } elsif ($config{CC_SRC} eq "2") { + my %country_name; + open (my $CC, "<", "/var/lib/csf/Geo/countryInfo.txt"); + flock ($CC, LOCK_SH); + foreach my $line (<$CC>) { + if ($line eq "" or $line =~ /^\#/ or $line =~ /^\s/) {next} + my ($cc,undef,undef,undef,$country,undef) = split(/\t/, $line); + if ($cc ne "" and $country ne "") {$country_name{$cc} = $country} + } + close ($CC); + + my $file = "/var/lib/csf/Geo/dbip-country-lite.csv"; + if ($config{CC_LOOKUPS} == 2 or $config{CC_LOOKUPS} == 3) { + $file = "/var/lib/csf/Geo/dbip-city-lite.csv"; + } + my $start = 0; + my $end = -s $file; + $end += 4; + my $cnt = 0; + my $last; + my $range; + my $geoid; + open (my $CSV, "<", $file); + flock ($CSV, LOCK_SH); + while (1) { + my $mid = int (($end + $start) / 2); + seek ($CSV, $mid, 0); + my $a = <$CSV>; + my $b = <$CSV>; + chomp $b; + my ($firstip,$lastip,$cc_lookups1,$country_iso_code,$region,$city_name,undef) = split(/\,/,$b); + if ($firstip eq $lastip or $firstip eq "") {return} + if (checkip(\$firstip) ne $ipv) { + if ($ipv eq "6") { + $start = $mid; + } else { + $end = $mid; + } + } else { + my $netfirstip = Net::IP->new($firstip); + my $firstip = $netfirstip->binip(); + my $netlastip = Net::IP->new($lastip); + my $lastip = $netlastip->binip(); + if (Net::IP::ip_bincomp($ip,'lt',$firstip) == 1) { + $end = $mid; + } + elsif (Net::IP::ip_bincomp($ip,'gt',$lastip) == 1) { + $start = $mid + 1; + } else { + if ($config{CC_LOOKUPS} == 1) {$country_iso_code = $cc_lookups1} + if ($country_iso_code eq "ZZ") {last} + $return[0] = $country_iso_code; + $return[1] = $country_name{$country_iso_code}; + $return[2] = $region; + $return[3] = $city_name; + last; + } + } + $cnt++; + if ($cnt > 200) {return} + } + close ($CSV); + + if ($config{CC_LOOKUPS} == 3) { + my $file = "/var/lib/csf/Geo/ip2asn-combined.tsv"; + my $start = 0; + my $end = -s $file; + $end += 4; + my $cnt = 0; + my $last; + my $range; + my $asn; + my $asnorg; + open (my $CSV, "<", $file); + flock ($CSV, LOCK_SH); + while (1) { + my $mid = int (($end + $start) / 2); + seek ($CSV, $mid, 0); + my $a = <$CSV>; + my $b = <$CSV>; + chomp $b; + my ($firstip,$lastip,$asn,undef,$asnorg) = split(/\t/,$b); + if ($firstip eq $lastip or $firstip eq "") {last} + if (checkip(\$firstip) ne $ipv) { + if ($ipv eq "6") { + $start = $mid; + } else { + $end = $mid; + } + } else { + my $netfirstip = Net::IP->new($firstip); + my $firstip = $netfirstip->binip(); + my $netlastip = Net::IP->new($lastip); + my $lastip = $netlastip->binip(); + if (Net::IP::ip_bincomp($ip,'lt',$firstip) == 1) { + $end = $mid; + } + elsif (Net::IP::ip_bincomp($ip,'gt',$lastip) == 1) { + $start = $mid + 1; + } else { + if ($asn eq "0") {last} + $return[4] = "AS$asn $asnorg"; + last; + } + } + $cnt++; + if ($cnt > 200) {last} + } + close ($CSV); + } + } + return @return; +} +# end geo_binary +############################################################################### + +1; \ No newline at end of file diff --git a/src/redux/ConfigServer/Messenger.pm b/src/redux/ConfigServer/Messenger.pm new file mode 100644 index 000000000..ce6f26275 --- /dev/null +++ b/src/redux/ConfigServer/Messenger.pm @@ -0,0 +1,1277 @@ +############################################################################### +# Copyright 2006-2023, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +## no critic (RequireUseWarnings, ProhibitExplicitReturnUndef, ProhibitMixedBooleanOperators, RequireBriefOpen) +# start main +package ConfigServer::Messenger; + +use strict; +use lib '/usr/local/csf/lib'; +use Fcntl qw(:DEFAULT :flock); +use File::Copy; +use JSON::Tiny; +use IO::Socket::INET; +use Net::CIDR::Lite; +use Net::IP; +use IPC::Open3; +use ConfigServer::Config; +use ConfigServer::CheckIP qw(checkip); +use ConfigServer::Logger qw(logfile); +use ConfigServer::URLGet; +use ConfigServer::Slurp qw(slurp); +use ConfigServer::GetIPs qw(getips); +use ConfigServer::GetEthDev; + +use Exporter qw(import); +our $VERSION = 3.00; +our @ISA = qw(Exporter); +our @EXPORT_OK = qw(); + +my $slurpreg = ConfigServer::Slurp->slurpreg; +my $cleanreg = ConfigServer::Slurp->cleanreg; + +my $config = ConfigServer::Config->loadconfig(); +my %config = $config->config(); +my $ipv4reg = ConfigServer::Config->ipv4reg; +my $ipv6reg = ConfigServer::Config->ipv6reg; + +my $childproc; +my $hostname; + +my %ips; +my $ipscidr6; +my %sslcerts; +my %sslkeys; +my %ssldomains; +my @ssldomainkeys; +my $webserver = "apache"; +my $sslhost; +my $sslcert; +my $sslkey; +my $sslca; +my $osslcert; +my $osslkey; +my $osslca; +my $sslaliases; +my $litestart = 0; +my $ssldir = "/var/lib/csf/ssl/"; +my $phphandler; +my $version = 1; +my $serverroot; + +# end main +############################################################################### +# start init +sub init { + my $class = shift; + $version = shift; + my $self = {}; + bless $self,$class; + + if (-e "/proc/sys/kernel/hostname") { + open (my $IN, "<", "/proc/sys/kernel/hostname"); + flock ($IN, LOCK_SH); + $hostname = <$IN>; + chomp $hostname; + close ($IN); + } else { + $hostname = "unknown"; + } + if ($version == 1) { + if ($config{MESSENGER6}) { + eval('use IO::Socket::INET6;'); ##no critic + if ($@) {$config{MESSENGER6} = "0"} + } + $ipscidr6 = Net::CIDR::Lite->new; + &getethdev; + foreach my $ip (split(/,/,$config{RECAPTCHA_NAT})) { + $ip =~ s/\s*//g; + $ips{$ip} = 1; + } + } + elsif ($version == 2) { + } + elsif ($version == 3) { + mkdir $ssldir; + mkdir $ssldir."certs/"; + mkdir $ssldir."keys/"; + mkdir $ssldir."ca/"; + } + + return $self; +} +# end init +############################################################################### +# start start +sub start { + my $self = shift; + my $port = shift; + my $user = shift; + my $type = shift; + my $status; + my $reason; + if ($version == 1) { + ($status,$reason) = &messenger($port, $user, $type); + } + elsif ($version == 2) { + ($status,$reason) = &messengerv2(); + } + elsif ($version == 3) { + ($status,$reason) = &messengerv3(); + } + + return ($status,$reason); +} +# end start +############################################################################### +# start messenger +sub messenger { + my $port = shift; + my $user = shift; + my $type = shift; + my $oldtype = $type; + my $server; + my %sslcerts; + my %sslkeys; + + $SIG{CHLD} = 'IGNORE'; + $SIG{INT} = \&childcleanup; + $SIG{TERM} = \&childcleanup; + $SIG{HUP} = \&childcleanup; + $SIG{__DIE__} = sub {&childcleanup(@_);}; + $0 = "lfd $type messenger"; + $childproc = "Messenger ($type)"; + + if ($type eq "HTTPS") { + eval { + local $SIG{__DIE__} = undef; + require IO::Socket::SSL; + import IO::Socket::SSL; + }; + + my $start = 0; + my $sslhost; + my $sslcert; + my $sslkey; + my $sslaliases; + my %messengerports; + foreach my $serverports (split(/\,/,$config{MESSENGER_HTTPS_IN})) {$messengerports{$serverports} = 1} + foreach my $file (glob($config{MESSENGER_HTTPS_CONF})) { + if (-e $file) { + foreach my $line (slurp($file)) { + $line =~ s/\'|\"//g; + if ($line =~ /^\s*]+>/) { + $start = 1; + } + if ($webserver eq "apache" and $start) { + if ($line =~ /\s*ServerName\s+(\w+:\/\/)?([a-zA-Z0-9\.\-]+)(:\d+)?/) {$sslhost = $2} + if ($line =~ /\s*ServerAlias\s+(.*)/) {$sslaliases .= " ".$1} + if ($line =~ /\s*SSLCertificateFile\s+(\S+)/) { + my $match = $1; + if (-e $match) {$sslcert = $match} + } + if ($line =~ /\s*SSLCertificateKeyFile\s+(\S+)/) { + my $match = $1; + if (-e $match) {$sslkey = $match} + } + } + + if (($webserver eq "apache" and $line =~ /^\s*<\/VirtualHost\s*>/)) { + $start = 0; + if ($sslhost ne "" and !checkip($sslhost) and $sslcert ne "") { + $sslcerts{$sslhost} = $sslcert; + if ($sslkey eq "") {$sslkey = $sslcert} + $sslkeys{$sslhost} = $sslkey; + foreach my $alias (split(/\s+/,$sslaliases)) { + if ($alias eq "") {next} + if (checkip($alias)) {next} + if ($alias =~ /^[a-zA-Z0-9\.\-]+$/) { + if ($config{MESSENGER_HTTPS_SKIPMAIL} and $alias =~ /^mail\./) {next} + $sslcerts{$alias} = $sslcert; + $sslkeys{$alias} = $sslkey; + } + } + } + $sslhost = ""; + $sslcert = ""; + $sslkey = ""; + $sslaliases = ""; + } + } + } + } + if (scalar(keys %sslcerts < 1)) { + return (1, "No SSL certs found in MESSENGER_HTTPS_CONF location"); + } + if (-e $config{MESSENGER_HTTPS_KEY}) { + $sslkeys{''} = $config{MESSENGER_HTTPS_KEY}; + } + if (-e $config{MESSENGER_HTTPS_CRT}) { + $sslcerts{''} = $config{MESSENGER_HTTPS_CRT}; + } + if ($config{DEBUG} >= 1) { + foreach my $key (keys %sslcerts) { + logfile("SSL: [$key] [$sslcerts{$key}] [$sslkeys{$key}]"); + } + } + eval { + local $SIG{__DIE__} = undef; + if ($config{MESSENGER6}) { + $server = IO::Socket::SSL->new( + Domain => AF_INET6, + LocalPort => $port, + Type => SOCK_STREAM, + ReuseAddr => 1, + Listen => $config{MESSENGER_CHILDREN}, + SSL_server => 1, + SSL_use_cert => 1, + SSL_cert_file => \%sslcerts, + SSL_key_file => \%sslkeys, + ) or &error("MESSENGER: *Error* cannot open server on port $port: ".IO::Socket::SSL->errstr); + } else { + $server = IO::Socket::SSL->new( + Domain => AF_INET, + LocalPort => $port, + Type => SOCK_STREAM, + ReuseAddr => 1, + Listen => $config{MESSENGER_CHILDREN}, + SSL_server => 1, + SSL_use_cert => 1, + SSL_cert_file => \%sslcerts, + SSL_key_file => \%sslkeys, + ) or &error("MESSENGER: *Error* cannot open server on port $port: ".IO::Socket::SSL->errstr); + } + &logfile("Messenger HTTPS Service started for ".scalar(keys %sslcerts)." domains"); + $type = "HTML"; + }; + if ($@) { + return (1, $@); + } + } + elsif ($config{MESSENGER6}) { + $server = IO::Socket::INET6->new( + LocalPort => $port, + Type => SOCK_STREAM, + ReuseAddr => 1, + Listen => $config{MESSENGER_CHILDREN}) or &childcleanup(__LINE__,"*Error* cannot open server on port $port: $!"); + } else { + $server = IO::Socket::INET->new( + LocalPort => $port, + Type => SOCK_STREAM, + ReuseAddr => 1, + Listen => $config{MESSENGER_CHILDREN}) or &childcleanup(__LINE__,"*Error* cannot open server on port $port: $!"); + } + + my $index; + if ($type eq "HTML" and $config{RECAPTCHA_SITEKEY} ne "") {$index = "/etc/csf/messenger/index.recaptcha.html"} + elsif ($type eq "HTML") {$index = "/etc/csf/messenger/index.html"} + else {$index = "/etc/csf/messenger/index.text"} + open (my $IN, "<", $index); + flock ($IN, LOCK_SH); + my @message = <$IN>; + close ($IN); + chomp @message; + + my %images; + if ($type eq "HTML") { + opendir (DIR, "/etc/csf/messenger"); + foreach my $file (readdir(DIR)) { + if ($file =~ /\.(gif|png|jpg)$/) { + open (my $IN, "<", "/etc/csf/messenger/$file"); + flock ($IN, LOCK_SH); + my @data = <$IN>; + close ($IN); + chomp @data; + foreach my $line (@data) { + $images{$file} .= "$line\n"; + } + } + } + closedir (DIR); + } + my $chldallow = $config{MESSENGER_CHILDREN}; + + if ($oldtype eq "HTTPS") { + open (my $STATUS,"<", "/proc/$$/status") or next; + flock ($STATUS, LOCK_SH); + my @status = <$STATUS>; + close ($STATUS); + chomp @status; + my $vmsize = 0; + my $vmrss = 0; + foreach my $line (@status) { + if ($line =~ /^VmSize:\s+(\d+) kB$/) {$vmsize = $1} + if ($line =~ /^VmRSS:\s+(\d+) kB$/) {$vmrss = $1} + } + + logfile("lfd $oldtype messenger using $vmrss kB of RSS memory at startup, adding up to $config{MESSENGER_CHILDREN} children = ".(($config{MESSENGER_CHILDREN} + 1) * $vmrss)." kB"); + logfile("lfd $oldtype messenger using $vmsize kB of VIRT memory at startup, adding up to $config{MESSENGER_CHILDREN} children = ".(($config{MESSENGER_CHILDREN} + 1) * $vmsize)." kB"); + } + + if ($user ne "") { + my (undef,undef,$uid,$gid,undef,undef,undef,$homedir) = getpwnam($user); + if (($uid > 0) and ($gid > 0)) { + local $( = $gid; + local $) = "$gid $gid"; + local $> = local $< = $uid; + if (($) != $gid) or ($> != $uid) or ($( != $gid) or ($< != $uid)) { + logfile("MESSENGER_USER unable to drop privileges - stopping $oldtype Messenger"); + exit; + } + my %children; + while (1) { + while (my $client = $server->accept()) { + while (scalar (keys %children) >= $chldallow) { + sleep 1; + foreach my $pid (keys %children) { + unless (kill(0,$pid)) {delete $children{$pid}} + } + $0 = "lfd $oldtype messenger (busy)"; + } + $0 = "lfd $oldtype messenger"; + + $SIG{CHLD} = 'IGNORE'; + my $pid = fork; + $children{$pid} = 1; + if ($pid == 0) { + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die}; + alarm(10); + close $server; + + $0 = "lfd $oldtype messenger client"; + + binmode $client; + $| = 1; + my $firstline; + + my $hostaddress = $client->sockhost(); + my $peeraddress = $client->peerhost(); + $peeraddress =~ s/^::ffff://; + $hostaddress =~ s/^::ffff://; + + if ($type eq "HTML") { + while ($firstline !~ /\n$/) { + my $char; + $client->read($char,1); + $firstline .= $char; + if ($char eq "") {exit} + if (length $firstline > 2048) {last} + } + chomp $firstline; + if ($firstline =~ /\r$/) {chop $firstline} + } + + &messengerlog($homedir,"Client connection [$peeraddress] [$firstline]"); + my $error; + my $success; + my $failure; + if (($type eq "HTML") and ($firstline =~ /^GET \/unblk\?g-recaptcha-response=(\S+)/i)) { + my $recv = $1; + my $status = 1; + my $text; + eval { + local $SIG{__DIE__} = undef; + eval("no lib '/usr/local/csf/lib'"); + my $urlget = ConfigServer::URLGet->new(2, "", $config{URLPROXY}); + my $url = "https://www.google.com/recaptcha/api/siteverify?secret=$config{RECAPTCHA_SECRET}&response=$recv"; + ($status, $text) = $urlget->urlget($url); + }; + if ($status) { + &messengerlog($homedir,"*Error*, ReCaptcha ($peeraddress): $text"); + if ($config{DEBUG} >= 1) { + if ($@) {$error .= "Error:".$@} + if ($!) {$error .= "Error:".$!} + $error .= " Error Status: $status"; + } + $error .= "Unable to verify with Google reCAPTCHA"; + } else { + my $resp = JSON::Tiny::decode_json($text); + if ($resp->{success}) { + my $ip = $resp->{hostname}; + unless ($ip =~ /^($ipv4reg|$ipv6reg)$/) {$ip = (getips($ip))[0]} + if ($ips{$ip} or $ip eq $hostaddress or $ipscidr6->find($ip)) { + sysopen (my $UNBLOCK, "$homedir/unblock.txt", O_WRONLY | O_APPEND | O_CREAT) or $error .= "Unable to write to [$homedir/unblock.txt] (make sure that MESSENGER_USER has a home directory)"; + flock($UNBLOCK, LOCK_EX); + print $UNBLOCK "$peeraddress;$resp->{hostname};$ip\n"; + close ($UNBLOCK); + $success = 1; + &messengerlog($homedir,"*Success*, ReCaptcha ($peeraddress): [$resp->{hostname} ($ip)] requested unblock"); + } else { + $error .= "Failed, [$resp->{hostname} ($ip)] does not appear to be hosted on this server."; + &messengerlog($homedir,"*Failed*, ReCaptcha ($peeraddress): [$resp->{hostname} ($ip)] does not appear to be hosted on this server"); + } + } else { + $failure = 1; + my @codes = @{$resp->{'error-codes'}}; + &messengerlog($homedir,"*Failure*, ReCaptcha ($peeraddress): [$codes[0]]"); + } + } + } + if (($type eq "HTML") and ($firstline =~ /^GET\s+(\S*\/)?(\S*\.(gif|png|jpg))\s+/i)) { + my $type = $3; + if ($type eq "jpg") {$type = "jpeg"} + print $client "HTTP/1.1 200 OK\r\n"; + print $client "Content-type: image/$type\r\n"; + print $client "\r\n"; + print $client $images{$2}; + } else { + if ($type eq "HTML") { + print $client "HTTP/1.1 403 OK\r\n"; + print $client "Content-type: text/html\r\n"; + print $client "\r\n"; + foreach my $line (@message) { + if ($line =~ /\[IPADDRESS\]/) {$line =~ s/\[IPADDRESS\]/$peeraddress/} + if ($line =~ /\[HOSTNAME\]/) {$line =~ s/\[HOSTNAME\]/$hostname/} + if ($line =~ /\[RECAPTCHA_SITEKEY\]/) {$line =~ s/\[RECAPTCHA_SITEKEY\]/$config{RECAPTCHA_SITEKEY}/} + if ($line =~ /\[RECAPTCHA_ERROR=\"([^\"]+)\"\]/) { + my $text = $1; + if ($error ne "") {$line =~ s/\[RECAPTCHA_ERROR=\"([^\"]+)\"\]/$text $error/} else {$line =~ s/\[RECAPTCHA_ERROR=\"([^\"]+)\"\]//} + } + if ($line =~ /\[RECAPTCHA_SUCCESS=\"([^\"]+)\"\]/) { + my $text = $1; + if ($success) {$line =~ s/\[RECAPTCHA_SUCCESS=\"([^\"]+)\"\]/$text/} else {$line =~ s/\[RECAPTCHA_SUCCESS=\"([^\"]+)\"\]//} + } + if ($line =~ /\[RECAPTCHA_FAILURE=\"([^\"]+)\"\]/) { + my $text = $1; + if ($failure) {$line =~ s/\[RECAPTCHA_FAILURE=\"([^\"]+)\"\]/$text/} else {$line =~ s/\[RECAPTCHA_FAILURE=\"([^\"]+)\"\]//} + } + print $client "$line\r\n"; + } + print $client "\r\n"; + } else { + foreach my $line (@message) { + if ($line =~ /\[IPADDRESS\]/) {$line =~ s/\[IPADDRESS\]/$peeraddress/} + if ($line =~ /\[HOSTNAME\]/) {$line =~ s/\[HOSTNAME\]/$hostname/} + print $client "$line "; + } + print $client "\n"; + } + } + alarm(0); + }; + shutdown ($client,2); + $client->close(); + alarm(0); + exit; + } + if ($oldtype eq "HTTPS") { + $client->close(SSL_no_shutdown => 1); + } else { + $client->close(); + } + } + } + } else { + logfile("MESSENGER_USER invalid - stopping $oldtype Messenger"); + } + } else { + logfile("MESSENGER_USER not set - stopping $oldtype Messenger"); + } + return; +} +# end messenger +############################################################################### +# start messengerv2 +sub messengerv2 { + my (undef,undef,$uid,$gid,undef,undef,undef,$homedir) = getpwnam($config{MESSENGER_USER}); + if ($homedir eq "" or $homedir eq "/" or $homedir =~ m[/etc/csf]) { + return (1, "The home directory for $config{MESSENGER_USER} is not valid [$homedir]"); + } + if (! -e $homedir) { + return (1, "The home directory for $config{MESSENGER_USER} does not exist [$homedir]"); + } + system("chmod","711",$homedir); + my $public_html = $homedir."/public_html"; + unless (-e $public_html) { + system("mkdir","-p",$public_html); + system("chown","$config{MESSENGER_USER}:nobody",$public_html); + system("chmod","711",$public_html); + } + unless (-e $public_html."/.htaccess") { + open (my $HTACCESS, ">", $public_html."/.htaccess"); + flock ($HTACCESS, LOCK_EX); + print $HTACCESS "Require all granted\n"; + print $HTACCESS "DirectoryIndex index.php index.cgi index.html index.htm\n"; + print $HTACCESS "Options +FollowSymLinks +ExecCGI\n"; + print $HTACCESS "RewriteEngine On\n"; + print $HTACCESS "RewriteCond \%{REQUEST_FILENAME} !-f\n"; + print $HTACCESS "RewriteCond \%{REQUEST_FILENAME} !-d\n"; + print $HTACCESS "RewriteRule ^ /index.php [L,QSA]\n"; + system("chown","$config{MESSENGER_USER}:$config{MESSENGER_USER}",$public_html."/.htaccess"); + system("chmod","644",$public_html."/.htaccess"); + } + unless (-e $public_html."/index.php") { + if ($config{RECAPTCHA_SITEKEY}) { + system("cp","/etc/csf/messenger/index.recaptcha.php",$public_html."/index.php"); + } else { + system("cp","/etc/csf/messenger/index.php",$public_html."/index.php"); + } + system("chown","$config{MESSENGER_USER}:$config{MESSENGER_USER}",$public_html."/index.php"); + system("chmod","644",$public_html."/index.php"); + } + unless (-e $homedir."/en.php") { + system("cp","/etc/csf/messenger/en.php",$homedir."/en.php"); + system("chown","$config{MESSENGER_USER}:$config{MESSENGER_USER}",$homedir."/en.php"); + system("chmod","644",$homedir."/en.php"); + } + open (my $CONF, ">", $homedir."/recaptcha.php"); + flock ($CONF, LOCK_EX); + print $CONF "\n"; + system("chown","$config{MESSENGER_USER}:$config{MESSENGER_USER}",$homedir."/recaptcha.php"); + system("chmod","644",$homedir."/recaptcha.php"); + + + open (my $OUT, ">", "/var/lib/csf/csf.conf"); + flock ($OUT, LOCK_EX); + + if ($config{MESSENGER_HTML_IN} ne "") { + print $OUT "Listen 0.0.0.0:$config{MESSENGER_HTML}\n"; + if ($config{IPV6}) {print $OUT "Listen [::]:$config{MESSENGER_HTML}\n"} + print $OUT "\n"; + print $OUT " ServerName $hostname\n"; + print $OUT " DocumentRoot $public_html\n"; + print $OUT " \n"; + print $OUT " AllowOverride All\n"; + print $OUT " \n"; + print $OUT " \n"; + print $OUT " suPHP_UserGroup $config{MESSENGER_USER} $config{MESSENGER_USER}\n"; + print $OUT " \n"; + print $OUT " \n"; + print $OUT " \n"; + print $OUT " SuexecUserGroup $config{MESSENGER_USER} $config{MESSENGER_USER}\n"; + print $OUT " \n"; + print $OUT " \n"; + print $OUT " \n"; + print $OUT " RMode config\n"; + print $OUT " RUidGid $config{MESSENGER_USER} $config{MESSENGER_USER}\n"; + print $OUT " \n"; + print $OUT " \n"; + print $OUT " AssignUserID $config{MESSENGER_USER} $config{MESSENGER_USER}\n"; + print $OUT " \n"; + print $OUT " KeepAlive Off\n"; + print $OUT "\n"; + } + + if ($config{MESSENGER_HTTPS_IN} ne "") { + my %sslcerts; + my %sslkeys; + my %ssldomains; + my $start = 0; + my $sslhost; + my $sslcert; + my $sslkey; + my $sslaliases; + my $ssldir = "/var/lib/csf/ssl/"; + unless (-d $ssldir) { + mkdir $ssldir; + mkdir $ssldir."certs/"; + mkdir $ssldir."keys/"; + } + foreach my $file (glob($config{MESSENGER_HTTPS_CONF})) { + if (-e $file) { + foreach my $line (slurp($file)) { + $line =~ s/\'|\"//g; + if ($line =~ /^\s*]+>/) { + $start = 1; + } + if ($webserver eq "apache" and $start) { + if ($line =~ /\s*ServerName\s+(\w+:\/\/)?([a-zA-Z0-9\.\-]+)(:\d+)?/) {$sslhost = $2} + if ($line =~ /\s*ServerAlias\s+(.*)/) {$sslaliases .= " ".$1} + if ($line =~ /\s*SSLCertificateFile\s+(\S+)/) { + my $match = $1; + if (-e $match) { + copy($match, $ssldir."certs/".$sslhost."\.crt"); + $sslcert = $ssldir."certs/".$sslhost."\.crt"; + } + } + if ($line =~ /\s*SSLCertificateKeyFile\s+(\S+)/) { + my $match = $1; + if (-e $match) { + copy($match, $ssldir."keys/".$sslhost."\.key"); + $sslkey = $ssldir."keys/".$sslhost."\.key"; + } + } + } + + if (($webserver eq "apache" and $line =~ /^\s*<\/VirtualHost\s*>/)) { + $start = 0; + if ($sslhost ne "" and !checkip($sslhost) and $sslcert ne "") { + $ssldomains{$sslhost}{key} = $sslkey; + $ssldomains{$sslhost}{aliases} = $sslaliases; + $ssldomains{$sslhost}{cert} = $sslcert; + } + $sslhost = ""; + $sslcert = ""; + $sslkey = ""; + $sslaliases = ""; + } + } + } + } + if (scalar(keys %ssldomains < 1)) { + return (1, "No SSL domains found in MESSENGER_HTTPS_CONF location"); + } + + print $OUT "Listen 0.0.0.0:$config{MESSENGER_HTTPS}\n"; + if ($config{IPV6}) {print $OUT "Listen [::]:$config{MESSENGER_HTTPS}\n"} + if (-e $config{MESSENGER_HTTPS_KEY}) { + print $OUT "\n"; + print $OUT " ServerName $hostname\n"; + print $OUT " DocumentRoot $public_html\n"; + print $OUT " UseCanonicalName Off\n"; + print $OUT " \n"; + print $OUT " AllowOverride All\n"; + print $OUT " \n"; + print $OUT " \n"; + print $OUT " suPHP_UserGroup $config{MESSENGER_USER} $config{MESSENGER_USER}\n"; + print $OUT " \n"; + print $OUT " \n"; + print $OUT " \n"; + print $OUT " SuexecUserGroup $config{MESSENGER_USER} $config{MESSENGER_USER}\n"; + print $OUT " \n"; + print $OUT " \n"; + print $OUT " \n"; + print $OUT " RMode config\n"; + print $OUT " RUidGid $config{MESSENGER_USER} $config{MESSENGER_USER}\n"; + print $OUT " \n"; + print $OUT " \n"; + print $OUT " AssignUserID $config{MESSENGER_USER} $config{MESSENGER_USER}\n"; + print $OUT " \n"; + print $OUT " SSLEngine on\n"; + if (-e $config{MESSENGER_HTTPS_KEY}) { + copy($config{MESSENGER_HTTPS_KEY}, $ssldir."keys/".$hostname."\.key"); + print $OUT " SSLCertificateKeyFile ".$ssldir."keys/".$hostname."\.key\n"; + } + if (-e $config{MESSENGER_HTTPS_CRT}) { + copy($config{MESSENGER_HTTPS_CRT}, $ssldir."certs/".$hostname."\.crt"); + print $OUT " SSLCertificateFile ".$ssldir."certs/".$hostname."\.crt\n"; + } + print $OUT " SSLUseStapling off\n"; + print $OUT " KeepAlive Off\n"; + print $OUT "\n"; + } + foreach my $key (keys %ssldomains) { + if ($key eq "") {next} + if ($key =~ /^\s+$/) {next} + if (-e $ssldomains{$key}{cert}) { + print $OUT "\n"; + print $OUT " ServerName $key\n"; + print $OUT " ServerAlias $ssldomains{$key}{aliases}\n"; + print $OUT " DocumentRoot $public_html\n"; + print $OUT " UseCanonicalName Off\n"; + print $OUT " \n"; + print $OUT " AllowOverride All\n"; + print $OUT " \n"; + print $OUT " \n"; + print $OUT " suPHP_UserGroup $config{MESSENGER_USER} $config{MESSENGER_USER}\n"; + print $OUT " \n"; + print $OUT " \n"; + print $OUT " \n"; + print $OUT " SuexecUserGroup $config{MESSENGER_USER} $config{MESSENGER_USER}\n"; + print $OUT " \n"; + print $OUT " \n"; + print $OUT " \n"; + print $OUT " RMode config\n"; + print $OUT " RUidGid $config{MESSENGER_USER} $config{MESSENGER_USER}\n"; + print $OUT " \n"; + print $OUT " \n"; + print $OUT " AssignUserID $config{MESSENGER_USER} $config{MESSENGER_USER}\n"; + print $OUT " \n"; + print $OUT " SSLEngine on\n"; + if (-e $ssldomains{$key}{cert}) {print $OUT " SSLCertificateFile $ssldomains{$key}{cert}\n"} + if (-e $ssldomains{$key}{key}) {print $OUT " SSLCertificateKeyFile $ssldomains{$key}{key}\n"} + print $OUT " SSLUseStapling off\n"; + print $OUT " KeepAlive Off\n"; + print $OUT "\n"; + } + } + } + close ($OUT); + + system("cp","-f","/var/lib/csf/csf.conf","/etc/apache2/conf.d/csf.messenger.conf"); + + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, "/usr/sbin/apachectl", "configtest"); + my @data = <$childout>; + waitpid ($cmdpid, 0); + + if (-e "/var/lib/csf/apachectl.error") {unlink("/var/lib/csf/apachectl.error")} + my $ok = 0; + foreach (@data) { + if ($_ =~ /^Syntax OK/) {$ok = 1} + } + if ($ok) { + system("/scripts/restartsrv_httpd"); + logfile("MESSENGERV2: Started Apache MESSENGERV2 service using /etc/apache2/conf.d/csf.messenger.conf"); + } else { + logfile("*MESSENGERV2*: Unable to generate a valid Apache configuration, see /var/lib/csf/apachectl.error"); + if (-e "/etc/apache2/conf.d/csf.messenger.conf") {unlink("/etc/apache2/conf.d/csf.messenger.conf")} + system("/scripts/restartsrv_httpd"); + + open (my $ERROR, ">", "/var/lib/csf/apachectl.error"); + flock ($ERROR, LOCK_EX); + foreach (@data) {print $ERROR $_} + close ($ERROR); + } + return; +} +# end messengerv2 +############################################################################### +# start messengerv3 +sub messengerv3 { + my (undef,undef,$uid,$gid,undef,undef,undef,$homedir) = getpwnam($config{MESSENGER_USER}); + if ($homedir eq "" or $homedir eq "/" or $homedir =~ m[/etc/csf]) { + return (1, "The home directory for $config{MESSENGER_USER} is not valid [$homedir]"); + } + if (! -e $homedir) { + return (1, "The home directory for $config{MESSENGER_USER} does not exist [$homedir]"); + } + my $public_html = $homedir."/public_html"; + unless (-e $public_html) { + system("mkdir","-p",$public_html); + system("chown","$config{MESSENGER_USER}:$config{MESSENGERV3GROUP}",$public_html); + system("chmod",$config{MESSENGERV3PERMS},$public_html); + } + unless (-e $public_html."/.htaccess") { + open (my $HTACCESS, ">", $public_html."/.htaccess"); + flock ($HTACCESS, LOCK_EX); + print $HTACCESS <", $homedir."/recaptcha.php"); + flock ($CONF, LOCK_EX); + print $CONF "\n"; + system("chown","$config{MESSENGER_USER}:$config{MESSENGER_USER}",$homedir."/recaptcha.php"); + system("chmod","644",$homedir."/recaptcha.php"); + + if ($config{MESSENGERV3WEBSERVER} eq "apache") { + $webserver = "apache"; + } + elsif ($config{MESSENGERV3WEBSERVER} eq "litespeed") { + $webserver = "litespeed"; + } + + open (my $OUT, ">", "/var/lib/csf/csf.conf"); + flock ($OUT, LOCK_EX); + + if ($config{MESSENGERV3PHPHANDLER} ne "") { + $phphandler = $config{MESSENGERV3PHPHANDLER}; + } else { + my $file = "/etc/httpd/conf/extra/httpd-hostname.conf"; + if (-e $file) { + foreach my $line (slurp($file)) { + if ($line =~ /^\s*AddHandler\s+.+\s+\.php/) { + $phphandler = $line; + if ($config{DEBUG} >= 1) {logfile("SSL: PHP Handler found in [$file]")} + } + } + } + } + + foreach my $line (slurp("/usr/local/csf/tpl/$webserver.main.txt")) { + $line =~ s/\[PORT\]/$config{MESSENGER_HTML}/g; + if ($line =~ /Listen \[::\]:/ and !$config{IPV6}) {next} + $line =~ s/\[SERVERNAME\]/$hostname/g; + $line =~ s/\[DOCUMENTROOT\]/$public_html/g; + $line =~ s/\[DIRECTORY\]/$homedir/g; + $line =~ s/\[USER\]/$config{MESSENGER_USER}/g; + $line =~ s/\[PHPHANDLER\]/$phphandler/g; + print $OUT $line."\n"; + } + + if ($config{MESSENGER_HTML_IN} ne "") { + foreach my $line (slurp("/usr/local/csf/tpl/$webserver.http.txt")) { + $line =~ s/\[PORT\]/$config{MESSENGER_HTML}/g; + if ($line =~ /Listen \[::\]:/ and !$config{IPV6}) {next} + $line =~ s/\[SERVERNAME\]/$hostname/g; + $line =~ s/\[DOCUMENTROOT\]/$public_html/g; + $line =~ s/\[DIRECTORY\]/$homedir/g; + $line =~ s/\[USER\]/$config{MESSENGER_USER}/g; + $line =~ s/\[PHPHANDLER\]/$phphandler/g; + print $OUT $line."\n"; + } + } + + if ($config{MESSENGER_HTTPS_IN} ne "") { + if ($webserver eq "litespeed") { + if ($config{MESSENGERV3HTTPS_CONF} =~ /(.*\/lsws\/)/) { + $serverroot = $1; + } + } + &conftree($config{MESSENGERV3HTTPS_CONF}); + if ($webserver eq "litespeed") { + if ($sslhost ne "" and $osslcert ne "" and $ssldomains{$sslhost}{cert} eq "") { + if (-e $osslcert) { + $sslcert = $ssldir."certs/".$sslhost."\.crt"; + copy($osslcert, $ssldir."certs/".$sslhost."\.crt"); + } + if (-e $osslkey) { + $sslkey = $ssldir."keys/".$sslhost."\.key"; + copy($osslkey, $ssldir."keys/".$sslhost."\.key"); + } + if (-e $osslca) { + $sslca = $ssldir."ca/".$sslhost."\.ca"; + copy($osslca, $ssldir."ca/".$sslhost."\.ca"); + } + $sslaliases =~ s/\$VH_NAME/$sslhost/; + $ssldomains{$sslhost}{key} = $sslkey; + $ssldomains{$sslhost}{aliases} = $sslaliases; + $ssldomains{$sslhost}{cert} = $sslcert; + $ssldomains{$sslhost}{ca} = $sslca; + push @ssldomainkeys, $sslhost; + + $sslhost = ""; + $sslcert = ""; + $sslkey = ""; + $sslca = ""; + $osslcert = ""; + $osslkey = ""; + $osslca = ""; + $sslaliases = ""; + } + } + + if (scalar(keys %ssldomains < 1)) { + return (1, "No SSL domains found in MESSENGERV3HTTPS_CONF location [$config{MESSENGERV3HTTPS_CONF}] for $webserver web server"); + } + + my @virtualhost; + my $start = 0; + my $key = $ssldomainkeys[0]; + foreach my $line (slurp("/usr/local/csf/tpl/$webserver.https.txt")) { + if ($line =~ /^\# Virtualhost start/) {$start = 1} + if ($start) { + if ($line =~ /^\# Virtualhost end/) {$start = 0} + push @virtualhost, $line; + next; + } + $line =~ s/\[SSLPORT\]/$config{MESSENGER_HTTPS}/g; + if ($line =~ /Listen \[::\]:/ and !$config{IPV6}) {next} + $line =~ s/\[SERVERNAME\]/$hostname/g; + $line =~ s/\[DOCUMENTROOT\]/$public_html/g; + $line =~ s/\[DIRECTORY\]/$homedir/g; + $line =~ s/\[USER\]/$config{MESSENGER_USER}/g; + $line =~ s/\[PHPHANDLER\]/$phphandler/g; + if ($line =~ /[MAPS]/) { + my $mapping; + foreach my $map (@ssldomainkeys) { + if (-e $ssldomains{$map}{cert}) { + $mapping .= "map csfssl.${map} ${map}\n\t"; + } + } + $line =~ s/\[MAPS\]/$mapping/g; + } + if ($line =~ /\[SSLCERTIFICATEFILE\]/) { + if ( -e $ssldomains{$key}{cert}) { + $line =~ s/\[SSLCERTIFICATEFILE\]/$ssldomains{$key}{cert}/g; + } else {next} + } + + if ($line =~ /\[SSLCERTIFICATEKEYFILE\]/) { + if (-e $ssldomains{$key}{key}) { + $line =~ s/\[SSLCERTIFICATEKEYFILE\]/$ssldomains{$key}{key}/g; + } else {next} + } + + if ($line =~ /\[SSLCACERTIFICATEFILE\]/) { + if (-e $ssldomains{$key}{ca}) { + $line =~ s/\[SSLCACERTIFICATEFILE\]/$ssldomains{$key}{ca}/g; + } else {next} + } + + print $OUT $line."\n"; + } + + foreach my $key (@ssldomainkeys) { + if ($key eq "") {next} + if ($key =~ /^\s+$/) {next} + if ($config{DEBUG} >= 1) {logfile("SSL: Processing [$key]")} + + if (-e $ssldomains{$key}{cert}) { + foreach (@virtualhost) { + my $line = $_; + $line =~ s/\[SSLPORT\]/$config{MESSENGER_HTTPS}/g; + $line =~ s/\[SERVERNAME\]/$key/g; + $line =~ s/\[SERVERALIAS\]/$ssldomains{$key}{aliases}/g; + $line =~ s/\[DOCUMENTROOT\]/$public_html/g; + $line =~ s/\[DIRECTORY\]/$homedir/g; + $line =~ s/\[USER\]/$config{MESSENGER_USER}/g; + $line =~ s/\[PHPHANDLER\]/$phphandler/g; + + if ($line =~ /\[SSLCERTIFICATEFILE\]/) { + if ( -e $ssldomains{$key}{cert}) { + $line =~ s/\[SSLCERTIFICATEFILE\]/$ssldomains{$key}{cert}/g; + } else {next} + } + + if ($line =~ /\[SSLCERTIFICATEKEYFILE\]/) { + if (-e $ssldomains{$key}{key}) { + $line =~ s/\[SSLCERTIFICATEKEYFILE\]/$ssldomains{$key}{key}/g; + } else {next} + } + + if ($line =~ /\[SSLCACERTIFICATEFILE\]/) { + if (-e $ssldomains{$key}{ca}) { + $line =~ s/\[SSLCACERTIFICATEFILE\]/$ssldomains{$key}{ca}/g; + } else {next} + } + + print $OUT $line."\n"; + } + } + } + } + close ($OUT); + + my $location; + if (-d $config{MESSENGERV3LOCATION}) { + system("cp","-f","/var/lib/csf/csf.conf",$config{MESSENGERV3LOCATION}."/csf.messenger.conf"); + $location = $config{MESSENGERV3LOCATION}."/csf.messenger.conf"; + } + elsif (-f $config{MESSENGERV3LOCATION}) { + my @conf = slurp($config{MESSENGERV3LOCATION}); + unless (grep {$_ =~ m[^Include /var/lib/csf/csf.conf]i} @conf) { + sysopen (my $FILE, $config{MESSENGERV3LOCATION}, O_WRONLY | O_APPEND | O_CREAT); + flock ($FILE, LOCK_EX); + if ($webserver eq "apache") { + print $FILE "Include /var/lib/csf/csf.conf\n"; + } + elsif ($webserver eq "litespeed") { + print $FILE "include /var/lib/csf/csf.conf\n"; + } + close ($FILE); + } + $location = $config{MESSENGERV3LOCATION}; + } + else { + logfile("MESSENGERV3: [$config{MESSENGERV3LOCATION}] is neither a directory nor a file. You must manually include /var/lib/csf/csf.conf into the $webserver configuration"); + return; + } + + if ($config{MESSENGERV3TEST} ne "") { + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, $config{MESSENGERV3TEST}); + my @data = <$childout>; + waitpid ($cmdpid, 0); + + if (-e "/var/lib/csf/messenger.error") {unlink("/var/lib/csf/messenger.error")} + my $ok = 0; + foreach (@data) { + if ($_ =~ /^Syntax OK/) {$ok = 1} + } + if ($ok) { + system($config{MESSENGERV3RESTART}); + logfile("MESSENGERV3: Restarted $webserver MESSENGERV3 service using $location"); + } else { + open (my $ERROR, ">", "/var/lib/csf/messenger.error"); + flock ($ERROR, LOCK_EX); + foreach (@data) {print $ERROR $_} + close ($ERROR); + + if (-d $config{MESSENGERV3LOCATION}) { + unlink ($config{MESSENGERV3LOCATION}."/csf.messenger.conf"); + } + elsif (-f $config{MESSENGERV3LOCATION}) { + my @conf = slurp($config{MESSENGERV3LOCATION}); + if (grep {$_ =~ m[^Include /var/lib/csf/csf.conf]i} @conf) { + sysopen (my $FILE, $config{MESSENGERV3LOCATION}, O_WRONLY | O_CREAT | O_TRUNC); + flock ($FILE, LOCK_EX); + foreach my $line (@conf) { + $line =~ s/$cleanreg//g; + if ($line =~ m[^Include /var/lib/csf/csf.conf]i) {next} + print $FILE $line."\n"; + } + close ($FILE); + } + } + + system($config{MESSENGERV3RESTART}); + + logfile("*MESSENGERV3*: Unable to generate a valid $webserver configuration, see /var/lib/csf/messenger.error"); + } + } else { + system($config{MESSENGERV3RESTART}); + logfile("MESSENGERV3: Restarted $webserver MESSENGERV3 service using $location"); + } + return; +} +# end messengerv3 +############################################################################### +# start messengerlog +sub messengerlog { + my $homedir = shift; + my $message = shift; + if ($config{DEBUG}) { + sysopen (my $LOG, "/var/log/lfd_messenger.log", O_WRONLY | O_APPEND | O_CREAT); + print $LOG "[$$]: ".$message."\n"; + close ($LOG); + } + return; +} +# end messengerlog +############################################################################### +# start childcleanup +sub childcleanup { + $SIG{INT} = 'IGNORE'; + $SIG{TERM} = 'IGNORE'; + $SIG{HUP} = 'IGNORE'; + my $line = shift; + my $message = shift; + + if (($message eq "") and $line) { + $message = "Child $childproc: $line"; + $line = ""; + } + + $0 = "child - aborting"; + + if ($message) { + if ($line ne "") {$message .= ", at line $line"} + logfile("$message"); + } + exit; +} +# end childcleanup +############################################################################### +# start getethdev +sub getethdev { + my $ethdev = ConfigServer::GetEthDev->new(); + my %g_ipv4 = $ethdev->ipv4; + my %g_ipv6 = $ethdev->ipv6; + foreach my $key (keys %g_ipv4) { + my $netip = Net::IP->new($key); + my $type = $netip->iptype(); + if ($type eq "PUBLIC") {$ips{$key} = 1} + } + if ($config{IPV6}) { + foreach my $key (keys %g_ipv6) { + if ($key !~ m[::1/128]) { + eval { + local $SIG{__DIE__} = undef; + $ipscidr6->add($key); + }; + } + } + } + return; +} +# end getethdev +############################################################################### +# start error +sub error { + my $error = shift; + logfile($error); + exit; +} +# end error +############################################################################### +# start conftree +sub conftree { + my $fileglob = shift; + foreach my $file (glob($fileglob)) { + if ($file =~ /csf\.messenger\.conf$/) {next} + if ($file =~ /\/var\/lib\/csf\/csf.conf$/) {next} + if (-e $file) { + if ($config{DEBUG} >= 1) {logfile("SSL: Processing [$file]")} + my $start = 0; + foreach my $line (slurp($file)) { + if ($webserver eq "apache") { + $line =~ s/\'|\"//g; + if ($line =~ /^\s*ServerRoot\s+\"?(\S+)\"?/) { + $serverroot = $1; + unless (-d $serverroot) {$serverroot = ""} + } + if ($serverroot eq "" and -d "/etc/apache2") {$serverroot = "/etc/apache2"} + if ($line =~ /^\s*Include\s+(\S+)/) { + my $include = $1; + if ($include !~ /^\//) {$include = "$serverroot/$include"} + if ($config{DEBUG} >= 1) {logfile("SSL: Including [$include]")} + &conftree($include); + } + if ($line =~ /^\s*IncludeOptional\s+(\S+)/) { + my $include = $1; + if ($include !~ /^\//) {$include = "$serverroot/$include"} + if ($config{DEBUG} >= 1) {logfile("SSL: IncludeOptional [$include]")} + &conftree($include); + } + if ($line =~ /^\s*]+>/) { + $start = 1; + } + if ($start) { + if ($line =~ /\s*ServerName\s+(\w+:\/\/)?([a-zA-Z0-9\.\-]+)(:\d+)?/) {$sslhost = $2} + if ($line =~ /\s*ServerAlias\s+(.*)/) {$sslaliases .= " ".$1} + if ($line =~ /\s*SSLCertificateFile\s+(\S+)/) { + my $match = $1; + if (-e $match) { + $osslcert = $match; + logfile("SSL: Found [$sslhost] certificate in [$file]"); + } + } + if ($line =~ /\s*SSLCertificateKeyFile\s+(\S+)/) { + my $match = $1; + if (-e $match) { + $osslkey = $match; + logfile("SSL: Found [$sslhost] key in [$file]"); + } + } + if ($line =~ /\s*SSLCACertificateFile\s+(\S+)/) { + my $match = $1; + if (-e $match) { + $osslca = $match; + logfile("SSL: Found [$sslhost] ca bundle in [$file]"); + } + } + } + + if ($line =~ /^\s*<\/VirtualHost\s*>/) { + $start = 0; + if ($sslhost ne "" and !checkip($sslhost) and $osslcert ne "") { + if (-e $osslcert) { + $sslcert = $ssldir."certs/".$sslhost."\.crt"; + copy($osslcert, $ssldir."certs/".$sslhost."\.crt"); + } + if (-e $osslkey) { + $sslkey = $ssldir."keys/".$sslhost."\.key"; + copy($osslkey, $ssldir."keys/".$sslhost."\.key"); + } + if (-e $osslca) { + $sslca = $ssldir."ca/".$sslhost."\.ca"; + copy($osslca, $ssldir."ca/".$sslhost."\.ca"); + } + $ssldomains{$sslhost}{key} = $sslkey; + $ssldomains{$sslhost}{aliases} = $sslaliases; + $ssldomains{$sslhost}{cert} = $sslcert; + $ssldomains{$sslhost}{ca} = $sslca; + push @ssldomainkeys, $sslhost; + if ($config{DEBUG} >= 1) {logfile("SSL: Found [$sslhost] in [$file]")} + } + $sslhost = ""; + $sslcert = ""; + $sslkey = ""; + $sslca = ""; + $osslcert = ""; + $osslkey = ""; + $osslca = ""; + $sslaliases = ""; + } + } + elsif ($webserver eq "litespeed") { + $line =~ s/\'|\"//g; + if ($line =~ /^\s*include\s+(\S+)/) { + my $include = $1; + $include =~ s/\$SERVER_ROOT/$serverroot/; + $include =~ s/\$VH_NAME/$sslhost/; + if ($include !~ /^\//) {$include = "$serverroot/$include"} + if ($config{DEBUG} >= 1) {logfile("SSL: include [$include]")} + &conftree($include); + } + if ($line =~ /^\s*configFile\s+(\S+)/) { + my $include = $1; + $include =~ s/\$SERVER_ROOT/$serverroot/; + $include =~ s/\$VH_NAME/$sslhost/; + if ($include !~ /^\//) {$include = "$serverroot/$include"} + if ($config{DEBUG} >= 1) {logfile("SSL: configFile [$include]")} + &conftree($include); + } + if ($line =~ /^\s*virtualHost\s+([^\{]+)\s+\{/) { + my $newsslhost = $1; + if ($newsslhost ne "" and $config{DEBUG} >= 1) {logfile("SSL: Found [$newsslhost] in [$file]")} + if ($litestart == 1) { + if ($sslhost ne "" and $osslcert ne "") { + if (-e $osslcert) { + $sslcert = $ssldir."certs/".$sslhost."\.crt"; + copy($osslcert, $ssldir."certs/".$sslhost."\.crt"); + } + if (-e $osslkey) { + $sslkey = $ssldir."keys/".$sslhost."\.key"; + copy($osslkey, $ssldir."keys/".$sslhost."\.key"); + } + if (-e $osslca) { + $sslca = $ssldir."ca/".$sslhost."\.ca"; + copy($osslca, $ssldir."ca/".$sslhost."\.ca"); + } + $sslaliases =~ s/\$VH_NAME/$sslhost/; + $ssldomains{$sslhost}{key} = $sslkey; + $ssldomains{$sslhost}{aliases} = $sslaliases; + $ssldomains{$sslhost}{cert} = $sslcert; + $ssldomains{$sslhost}{ca} = $sslca; + push @ssldomainkeys, $sslhost; + + $sslhost = ""; + $sslcert = ""; + $sslkey = ""; + $sslca = ""; + $osslcert = ""; + $osslkey = ""; + $osslca = ""; + $sslaliases = ""; + } + } + $litestart = 1; + $sslhost = $newsslhost; + } + if ($litestart) { + if ($line =~ /\s*vhDomain\s+(\w+:\/\/)?([a-zA-Z0-9\.\-]+)(:\d+)?/) {$sslhost = $2} + if ($line =~ /\s*vhAliases\s+(.*)/) {$sslaliases .= " ".$1} + if ($line =~ /\s*certFile\s+(\S+)/) { + my $match = $1; + if (-e $match) { + $osslcert = $match; + logfile("SSL: Found [$sslhost] certificate in [$file]"); + } + } + if ($line =~ /\s*keyFile\s+(\S+)/) { + my $match = $1; + if (-e $match) { + $osslkey = $match; + logfile("SSL: Found [$sslhost] key in [$file]"); + } + } + } + } + } + } + } + return; +} +# end conftree +############################################################################### + +1; diff --git a/src/redux/ConfigServer/Ports.pm b/src/redux/ConfigServer/Ports.pm new file mode 100644 index 000000000..1e12d2a0e --- /dev/null +++ b/src/redux/ConfigServer/Ports.pm @@ -0,0 +1,213 @@ +############################################################################### +# Copyright 2006-2023, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +## no critic (RequireUseWarnings, ProhibitExplicitReturnUndef, ProhibitMixedBooleanOperators, RequireBriefOpen) +# start main +package ConfigServer::Ports; + +use strict; +use lib '/usr/local/csf/lib'; +use Fcntl qw(:DEFAULT :flock); +use ConfigServer::Config; + +use Exporter qw(import); +our $VERSION = 1.02; +our @ISA = qw(Exporter); +our @EXPORT_OK = qw(); + +my %printable = ( ( map { chr($_), unpack('H2', chr($_)) } (0..255) ), "\\"=>'\\', "\r"=>'r', "\n"=>'n', "\t"=>'t', "\""=>'"' ); ##no critic +my %tcpstates = ("01" => "ESTABLISHED", + "02" => "SYN_SENT", + "03" => "SYN_RECV", + "04" => "FIN_WAIT1", + "05" => "FIN_WAIT2", + "06" => "TIME_WAIT", + "07" => "CLOSE", + "08" => "CLOSE_WAIT", + "09" => "LAST_ACK", + "0A" => "LISTEN", + "0B" => "CLOSING"); +# end main +############################################################################### +# start listening +sub listening { + my %net; + my %conn; + my %listen; + + foreach my $proto ("tcp","udp","tcp6","udp6") { + open (my $IN, "<","/proc/net/$proto"); + flock ($IN, LOCK_SH); + while (<$IN>) { + my @rec = split(); + if ($rec[9] =~ /uid/) {next} + + my ($dip,$dport) = split(/:/,$rec[1]); + $dport = hex($dport); + + my ($sip,$sport) = split(/:/,$rec[2]); + $sport = hex($sport); + + $dip = &hex2ip($dip); + $sip = &hex2ip($sip); + + my $inode = $rec[9]; + my $state = $tcpstates{$rec[3]}; + my $protocol = $proto; + $protocol =~ s/6//; + if ($protocol eq "udp" and $state eq "CLOSE") {$state = "LISTEN"} + + if ($state eq "ESTABLISHED") {$conn{$dport}{$protocol}++} + + if ($dip =~ /^127\./) {next} + if ($dip =~ /^0\.0\.0\.1/) {next} + if ($state eq "LISTEN") {$net{$inode}{$protocol} = $dport} + } + close ($IN); + } + + opendir (PROCDIR, "/proc"); + while (my $pid = readdir(PROCDIR)) { + if ($pid !~ /^\d+$/) {next} + my $exe = readlink("/proc/$pid/exe") || ""; + my $cwd = readlink("/proc/$pid/cwd") || ""; + my $uid; + my $user; + + if (defined $exe) {$exe =~ s/([\r\n\t\"\\\x00-\x1f\x7F-\xFF])/\\$printable{$1}/sg} + open (my $CMDLINE,"<","/proc/$pid/cmdline"); + flock ($CMDLINE, LOCK_SH); + my $cmdline = <$CMDLINE>; + close ($CMDLINE); + if (defined $cmdline) { + chomp $cmdline; + $cmdline =~ s/\0$//g; + $cmdline =~ s/\0/ /g; + $cmdline =~ s/([\r\n\t\"\\\x00-\x1f\x7F-\xFF])/\\$printable{$1}/sg; + $cmdline =~ s/\s+$//; + $cmdline =~ s/^\s+//; + } + if ($exe eq "") {next} + my @fd; + opendir (DIR, "/proc/$pid/fd") or next; + while (my $file = readdir (DIR)) { + if ($file =~ /^\./) {next} + push (@fd, readlink("/proc/$pid/fd/$file")); + } + closedir (DIR); + open (my $STATUS,"<", "/proc/$pid/status") or next; + flock ($STATUS, LOCK_SH); + my @status = <$STATUS>; + close ($STATUS); + chomp @status; + foreach my $line (@status) { + if ($line =~ /^Uid:(.*)/) { + my $uidline = $1; + my @uids; + foreach my $bit (split(/\s/,$uidline)) { + if ($bit =~ /^(\d*)$/) {push @uids, $1} + } + $uid = $uids[-1]; + $user = getpwuid($uid); + if ($user eq "") {$user = $uid} + } + } + + my $files; + my $sockets; + foreach my $file (@fd) { + if ($file =~ /^socket:\[?([0-9]+)\]?$/) { + my $ino = $1; + if ($net{$ino}) { + foreach my $protocol (keys %{$net{$ino}}) { + $listen{$protocol}{$net{$ino}{$protocol}}{$pid}{user} = $user; + $listen{$protocol}{$net{$ino}{$protocol}}{$pid}{exe} = $exe; + $listen{$protocol}{$net{$ino}{$protocol}}{$pid}{cmd} = $cmdline; + $listen{$protocol}{$net{$ino}{$protocol}}{$pid}{cmd} = $cmdline; + $listen{$protocol}{$net{$ino}{$protocol}}{$pid}{conn} = $conn{$net{$ino}{$protocol}}{$protocol} | "-"; + } + } + } + } + + } + closedir (PROCDIR); + return %listen; +} +# end listening +############################################################################### +# start openports +sub openports { + my $config = ConfigServer::Config->loadconfig(); + my %config = $config->config(); + my %ports; + + $config{TCP_IN} =~ s/\s//g; + foreach my $entry (split(/,/,$config{TCP_IN})) { + if ($entry =~ /^(\d+):(\d+)$/) { + my $from = $1; + my $to = $2; + for (my $port = $from; $port < $to ; $port++) { + $ports{tcp}{$port} = 1; + } + } else { + $ports{tcp}{$entry} = 1; + } + } + $config{TCP6_IN} =~ s/\s//g; + foreach my $entry (split(/,/,$config{TCP6_IN})) { + if ($entry =~ /^(\d+):(\d+)$/) { + my $from = $1; + my $to = $2; + for (my $port = $from; $port < $to ; $port++) { + $ports{tcp6}{$port} = 1; + } + } else { + $ports{tcp6}{$entry} = 1; + } + } + $config{UDP_IN} =~ s/\s//g; + foreach my $entry (split(/,/,$config{UDP_IN})) { + if ($entry =~ /^(\d+):(\d+)$/) { + my $from = $1; + my $to = $2; + for (my $port = $from; $port < $to ; $port++) { + $ports{udp}{$port} = 1; + } + } else { + $ports{udp}{$entry} = 1; + } + } + $config{UDP6_IN} =~ s/\s//g; + foreach my $entry (split(/,/,$config{UDP6_IN})) { + if ($entry =~ /^(\d+):(\d+)$/) { + my $from = $1; + my $to = $2; + for (my $port = $from; $port < $to ; $port++) { + $ports{udp6}{$port} = 1; + } + } else { + $ports{udp6}{$entry} = 1; + } + } + return %ports; +} +# end openports +############################################################################### +## start hex2ip +sub hex2ip { + my $bin = pack "C*" => map hex, $_[0] =~ /../g; + my @l = unpack "L*", $bin; + if (@l == 4) { + return join ':', map { sprintf "%x:%x", $_ >> 16, $_ & 0xffff } @l; + } + elsif (@l == 1) { + return join '.', map { $_ >> 24, ($_ >> 16 ) & 0xff, ($_ >> 8) & 0xff, $_ & 0xff } @l; + } +} +## end hex2ip +############################################################################### + +1; \ No newline at end of file diff --git a/src/redux/ConfigServer/RBLCheck.pm b/src/redux/ConfigServer/RBLCheck.pm new file mode 100644 index 000000000..cf1558597 --- /dev/null +++ b/src/redux/ConfigServer/RBLCheck.pm @@ -0,0 +1,242 @@ +############################################################################### +# Copyright 2006-2023, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +## no critic (RequireUseWarnings, ProhibitExplicitReturnUndef, ProhibitMixedBooleanOperators, RequireBriefOpen) +# start main +package ConfigServer::RBLCheck; + +use strict; +use lib '/usr/local/csf/lib'; +use Fcntl qw(:DEFAULT :flock); +use ConfigServer::Config; +use ConfigServer::CheckIP qw(checkip); +use ConfigServer::Slurp qw(slurp); +use ConfigServer::GetIPs qw(getips); +use ConfigServer::RBLLookup qw(rbllookup); +use IPC::Open3; +use Net::IP; +use ConfigServer::GetEthDev; + +use Exporter qw(import); +our $VERSION = 1.01; +our @ISA = qw(Exporter); +our @EXPORT_OK = qw(); + +my ($ui, $failures, $verbose, $cleanreg, $status, %ips, $images, %config, + $ipresult, $output); + +my $ipv4reg = ConfigServer::Config->ipv4reg; +my $ipv6reg = ConfigServer::Config->ipv6reg; + +# end main +############################################################################### +# start report +sub report { + $verbose = shift; + $images = shift; + $ui = shift; + my $config = ConfigServer::Config->loadconfig(); + %config = $config->config(); + $cleanreg = ConfigServer::Slurp->cleanreg; + $failures = 0; + + $| = 1; + + &startoutput; + + &getethdev; + + my @RBLS = slurp("/usr/local/csf/lib/csf.rbls"); + + if (-e "/etc/csf/csf.rblconf") { + my @entries = slurp("/etc/csf/csf.rblconf"); + 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} + if ($line =~ /^enablerbl:(.*)$/) { + push @RBLS, $1; + } + elsif ($line =~ /^disablerbl:(.*)$/) { + my $hit = $1; + for (0..@RBLS) { + my $x = $_; + my ($rbl,$rblurl) = split(/:/,$RBLS[$x],2); + if ($rbl eq $hit) {$RBLS[$x] = ""} + } + } + if ($line =~ /^enableip:(.*)$/) { + if (checkip(\$1)) {$ips{$1} = 1} + } + elsif ($line =~ /^disableip:(.*)$/) { + if (checkip(\$1)) {delete $ips{$1}} + } + } + } + @RBLS = sort @RBLS; + + foreach my $ip (sort keys %ips) { + my $netip = Net::IP->new($ip); + my $type = $netip->iptype(); + if ($type eq "PUBLIC") { + + if ($verbose and -e "/var/lib/csf/${ip}.rbls") { + unlink "/var/lib/csf/${ip}.rbls"; + } + + if (-e "/var/lib/csf/${ip}.rbls") { + my $text = join("\n",slurp("/var/lib/csf/${ip}.rbls")); + if ($ui) {print $text} else {$output .= $text} + } else { + if ($verbose) { + $ipresult = ""; + my $hits = 0; + &addtitle("Checked $ip ($type) on ".localtime()); + + foreach my $line (@RBLS) { + my ($rbl,$rblurl) = split(/:/,$line,2); + if ($rbl eq "") {next} + + my ($rblhit,$rbltxt) = rbllookup($ip,$rbl); + my @tmptxt = $rbltxt; + $rbltxt = ""; + foreach my $line (@tmptxt) { + $line =~ s/(http(\S+))/$1<\/a>/g; + $rbltxt .= "${line}\n"; + } + $rbltxt =~ s/\n/
\n/g; + + if ($rblhit eq "timeout") { + &addline(0,$rbl,$rblurl,"TIMEOUT"); + } + elsif ($rblhit eq "") { + if ($verbose == 2) { + &addline(0,$rbl,$rblurl,"OK"); + } + } + else { + &addline(1,$rbl,$rblurl,$rbltxt); + $hits++; + } + } + unless ($hits) { + my $text; + $text .= "
OK
\n"; + if ($ui) {print $text} else {$output .= $text} + $ipresult .= $text; + } + sysopen (my $OUT, "/var/lib/csf/${ip}.rbls", O_WRONLY | O_CREAT); + flock($OUT, LOCK_EX); + print $OUT $ipresult; + close ($OUT); + } else { + &addtitle("New $ip ($type)"); + my $text; + $text .= "
Not Checked
\n"; + if ($ui) {print $text} else {$output .= $text} + } + } + } else { + if ($verbose == 2) { + &addtitle("Skipping $ip ($type)"); + my $text; + $text .= "
OK
\n"; + if ($ui) {print $text} else {$output .= $text} + } + } + } + &endoutput; + + return ($failures,$output); +} +# end report +############################################################################### +# start startoutput +sub startoutput { + return; +} +# end startoutput +############################################################################### +# start addline +sub addline { + my $status = shift; + my $rbl = shift; + my $rblurl = shift; + my $comment = shift; + my $text; + my $check = $rbl; + if ($rblurl ne "") {$check = "
$rbl"} + + if ($status) { + $text .= "
\n"; + $text .= "
$check
\n"; + $text .= "
$comment
\n"; + $text .= "
\n"; + $failures ++; + $ipresult .= $text; + } + elsif ($verbose) { + $text .= "
\n"; + $text .= "
$check
\n"; + $text .= "
$comment
\n"; + $text .= "
\n"; + } + if ($ui) {print $text} else {$output .= $text} + + return; +} +# end addline +############################################################################### +# start addtitle +sub addtitle { + my $title = shift; + my $text; + + $text .= "
$title
\n"; + + $ipresult .= $text; + if ($ui) {print $text} else {$output .= $text} + + return; +} +# end addtitle +############################################################################### +# start endoutput +sub endoutput { + if ($ui) {print "
\n"} else {$output .= "
\n"} + + return; +} +# end endoutput +############################################################################### +# start getethdev +sub getethdev { + my $ethdev = ConfigServer::GetEthDev->new(); + my %g_ipv4 = $ethdev->ipv4; + my %g_ipv6 = $ethdev->ipv6; + 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); +# }; +# } +# } + + return; +} +# end getethdev +############################################################################### + +1; diff --git a/src/redux/ConfigServer/RBLLookup.pm b/src/redux/ConfigServer/RBLLookup.pm new file mode 100644 index 000000000..e8686c436 --- /dev/null +++ b/src/redux/ConfigServer/RBLLookup.pm @@ -0,0 +1,103 @@ +############################################################################### +# Copyright 2006-2023, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +## no critic (RequireUseWarnings, ProhibitExplicitReturnUndef, ProhibitMixedBooleanOperators, RequireBriefOpen) +# start main +package ConfigServer::RBLLookup; + +use strict; +use lib '/usr/local/csf/lib'; +use Fcntl qw(:DEFAULT :flock); +use IPC::Open3; +use Net::IP; +use ConfigServer::Config; +use ConfigServer::CheckIP qw(checkip); + +use Exporter qw(import); +our $VERSION = 1.01; +our @ISA = qw(Exporter); +our @EXPORT_OK = qw(rbllookup); + +my $config = ConfigServer::Config->loadconfig(); +my %config = $config->config(); +my $ipv4reg = ConfigServer::Config->ipv4reg; +my $ipv6reg = ConfigServer::Config->ipv6reg; + +# end main +############################################################################### +# start rbllookup +sub rbllookup { + my $ip = shift; + my $rbl = shift; + my %rblhits; + my $netip; + my $reversed_ip; + my $timeout = 4; + my $rblhit; + my $rblhittxt; + + if (checkip(\$ip)) { + eval { + local $SIG{__DIE__} = undef; + $netip = Net::IP->new($ip); + $reversed_ip = $netip->reverse_ip(); + }; + + if ($reversed_ip =~ /^(\S+)\.in-addr\.arpa/) {$reversed_ip = $1} + if ($reversed_ip =~ /^(\S+)\s+(\S+)\.in-addr\.arpa/) {$reversed_ip = $2} + if ($reversed_ip =~ /^(\S+)\.ip6\.arpa/) {$reversed_ip = $1} + if ($reversed_ip =~ /^(\S+)\s+(\S+)\.ip6\.arpa/) {$reversed_ip = $2} + + if ($reversed_ip ne "") { + my $lookup_ip = $reversed_ip.".".$rbl; + + my $cmdpid; + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die}; + alarm($timeout); + my ($childin, $childout); + $cmdpid = open3($childin, $childout, $childout, $config{HOST},"-t","A",$lookup_ip); + close $childin; + my @results = <$childout>; + waitpid ($cmdpid, 0); + chomp @results; + if ($results[0] =~ /^${reversed_ip}.+ ($ipv4reg|$ipv6reg)$/) {$rblhit = $1} + alarm(0); + }; + alarm(0); + if ($@) {$rblhit = "timeout"} + if ($cmdpid =~ /\d+/ and $cmdpid > 1 and kill(0,$cmdpid)) {kill(9,$cmdpid)} + + if ($rblhit ne "") { + if ($rblhit ne "timeout") { + my $cmdpid; + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die}; + alarm($timeout); + my ($childin, $childout); + $cmdpid = open3($childin, $childout, $childout, $config{HOST},"-t","TXT",$lookup_ip); + close $childin; + my @results = <$childout>; + waitpid ($cmdpid, 0); + chomp @results; + foreach my $line (@results) { + if ($line =~ /^${reversed_ip}.+ "([^\"]+)"$/) {$rblhittxt .= "$1\n"} + } + alarm(0); + }; + alarm(0); + if ($cmdpid =~ /\d+/ and $cmdpid > 1 and kill(0,$cmdpid)) {kill(9,$cmdpid)} + } + } + } + } + return ($rblhit,$rblhittxt); +} +# end rbllookup +############################################################################### + +1; diff --git a/src/redux/ConfigServer/RegexMain.pm b/src/redux/ConfigServer/RegexMain.pm new file mode 100644 index 000000000..6a124ef29 --- /dev/null +++ b/src/redux/ConfigServer/RegexMain.pm @@ -0,0 +1,1015 @@ +############################################################################### +# Copyright 2006-2023, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +## no critic (RequireUseWarnings, ProhibitExplicitReturnUndef, ProhibitMixedBooleanOperators, RequireBriefOpen) +# start main +package ConfigServer::RegexMain; + +use strict; +use lib '/usr/local/csf/lib'; +use IPC::Open3; +use ConfigServer::Config; +use ConfigServer::CheckIP qw(checkip); +use ConfigServer::Slurp qw(slurp); +use ConfigServer::Logger qw(logfile); +use ConfigServer::GetEthDev; + +use Exporter qw(import); +our $VERSION = 1.03; +our @ISA = qw(Exporter); +our @EXPORT_OK = qw(); + +our (%config, %cpconfig, $slurpreg, $cleanreg, %globlogs, %brd, %ips); + +my $config = ConfigServer::Config->loadconfig(); +%config = $config->config; + +$slurpreg = ConfigServer::Slurp->slurpreg; +$cleanreg = ConfigServer::Slurp->cleanreg; + +if (-e "/etc/wwwacct.conf") { + foreach my $line (slurp("/etc/wwwacct.conf")) { + $line =~ s/$cleanreg//g; + if ($line =~ /^(\s|\#|$)/) {next} + my ($name,$value) = split (/ /,$line,2); + $cpconfig{$name} = $value; + } +} +if (-e "/usr/local/cpanel/version") { + foreach my $line (slurp("/usr/local/cpanel/version")) { + $line =~ s/$cleanreg//g; + if ($line =~ /\d/) {$cpconfig{version} = $line} + } +} + +if ($config{LF_APACHE_ERRPORT} == 0) { + my $apachebin = ""; + if (-e "/usr/local/apache/bin/httpd") {$apachebin = "/usr/local/apache/bin/httpd"} + elsif (-e "/usr/sbin/httpd") {$apachebin = "/usr/sbin/httpd"} + elsif (-e "/usr/sbin/apache2") {$apachebin = "/usr/sbin/apache2"} + elsif (-e "/usr/sbin/httpd2") {$apachebin = "/usr/sbin/httpd2"} + if (-e $apachebin) { + my ($childin, $childout); + my $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; + if ("$mas.$maj" < 2.4) {$config{LF_APACHE_ERRPORT} = 1} + } +} +unless ($config{LF_APACHE_ERRPORT} == 1) {$config{LF_APACHE_ERRPORT} = 2} +ConfigServer::Logger::logfile("LF_APACHE_ERRPORT: Set to [$config{LF_APACHE_ERRPORT}]"); + +my $ethdev = ConfigServer::GetEthDev->new(); +%brd = $ethdev->brd; +%ips = $ethdev->ipv4; + +if (-e "/usr/local/csf/bin/regex.custom.pm") {require "/usr/local/csf/bin/regex.custom.pm"} ##no critic + +# end main +############################################################################### +# start processline +sub processline { + my $line = shift; + my $lgfile = shift; + my $globlogs_ref = shift; + %globlogs = %{$globlogs_ref}; + $line =~ s/\n//g; + $line =~ s/\r//g; + + if (-e "/usr/local/csf/bin/regex.custom.pm") { + my ($text,$ip,$app,$trigger,$ports,$temp,$cf) = &custom_line($line,$lgfile); + if ($text) { + return ($text,$ip,$app,$trigger,$ports,$temp,$cf); + } + } + +#openSSH +#RH + if (($config{LF_SSHD}) and (($lgfile eq "/var/log/messages") or ($lgfile eq "/var/log/secure") or ($globlogs{SSHD_LOG}{$lgfile})) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) (\S+ )?sshd\[\d+\]: pam_unix\(sshd:auth\): authentication failure; logname=\S* uid=\S* euid=\S* tty=\S* ruser=\S* rhost=(\S+)\s+(user=(\S+))?/)) { + my $ip = $3; + my $acc = $5; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("Failed SSH login from","$ip|$acc","sshd")} else {return} + } + if (($config{LF_SSHD}) and (($lgfile eq "/var/log/messages") or ($lgfile eq "/var/log/secure") or ($globlogs{SSHD_LOG}{$lgfile})) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) (\S+ )?sshd\[\d+\]: Failed none for (\S*) from (\S+) port \S+/)) { + my $ip = $4; + my $acc = $3; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("Failed SSH login from","$ip|$acc","sshd")} else {return} + } + if (($config{LF_SSHD}) and (($lgfile eq "/var/log/messages") or ($lgfile eq "/var/log/secure") or ($globlogs{SSHD_LOG}{$lgfile})) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) (\S+ )?sshd\[\d+\]: Failed password for (invalid user |illegal user )?(\S*) from (\S+)( port \S+ \S+\s*)?/)) { + my $ip = $5; + my $acc = $4; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("Failed SSH login from","$ip|$acc","sshd")} else {return} + } + if (($config{LF_SSHD}) and (($lgfile eq "/var/log/messages") or ($lgfile eq "/var/log/secure") or ($globlogs{SSHD_LOG}{$lgfile})) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) (\S+ )?sshd\[\d+\]: Failed keyboard-interactive(\/pam)? for (invalid user )?(\S*) from (\S+) port \S+/)) { + my $ip = $6; + my $acc = $4; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("Failed SSH login from","$ip|$acc","sshd")} else {return} + } + if (($config{LF_SSHD}) and (($lgfile eq "/var/log/messages") or ($lgfile eq "/var/log/secure") or ($globlogs{SSHD_LOG}{$lgfile})) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) (\S+ )?sshd\[\d+\]: Invalid user (\S*) from (\S+)/)) { + my $ip = $4; + my $acc = $3; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("Failed SSH login from","$ip|$acc","sshd")} else {return} + } + if (($config{LF_SSHD}) and (($lgfile eq "/var/log/messages") or ($lgfile eq "/var/log/secure") or ($globlogs{SSHD_LOG}{$lgfile})) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) (\S+ )?sshd\[\d+\]: User (\S*) from (\S+)\s* not allowed because not listed in AllowUsers/)) { + my $ip = $4; + my $acc = $3; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("Failed SSH login from","$ip|$acc","sshd")} else {return} + } + if (($config{LF_SSHD}) and (($lgfile eq "/var/log/messages") or ($lgfile eq "/var/log/secure") or ($globlogs{SSHD_LOG}{$lgfile})) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) (\S+ )?sshd\[\d+\]: Did not receive identification string from (\S+)/)) { + my $ip = $3; + my $acc = ""; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("Failed SSH login from","$ip|$acc","sshd")} else {return} + } + if (($config{LF_SSHD}) and (($lgfile eq "/var/log/messages") or ($lgfile eq "/var/log/secure") or ($globlogs{SSHD_LOG}{$lgfile})) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) (\S+ )?sshd\[\d+\]: refused connect from (\S+)/)) { + my $ip = $3; + my $acc = ""; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("Failed SSH login from","$ip|$acc","sshd")} else {return} + } + if (($config{LF_SSHD}) and (($lgfile eq "/var/log/messages") or ($lgfile eq "/var/log/secure") or ($globlogs{SSHD_LOG}{$lgfile})) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) (\S+ )?sshd\[\d+\]: error: maximum authentication attempts exceeded for (\S*) from (\S+)/)) { + my $ip = $4; + my $acc = ""; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("Failed SSH login from","$ip|$acc","sshd")} else {return} + } + +#Debian/Ubuntu + if (($config{LF_SSHD}) and (($lgfile eq "/var/log/messages") or ($lgfile eq "/var/log/secure") or ($globlogs{SSHD_LOG}{$lgfile})) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) (\S+ )?sshd\[\d+\]: Illegal user (\S*) from (\S+)/)) { + my $ip = $4; + my $acc = $3; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("Failed SSH login from","$ip|$acc","sshd")} else {return} + } + +#Gentoo + if (($config{LF_SSHD}) and (($lgfile eq "/var/log/messages") or ($lgfile eq "/var/log/secure") or ($globlogs{SSHD_LOG}{$lgfile})) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) (\S+ )?sshd\[\d+\]: error: PAM: Authentication failure for (\S*) from (\S+)/)) { + my $ip = $4; + my $acc = $3; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("Failed SSH login from","$ip|$acc","sshd")} else {return} + } + +#courier-imap + if (($config{LF_POP3D}) and ($globlogs{POP3D_LOG}{$lgfile}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) \S+ pop3d(-ssl)?: LOGIN FAILED, user=(\S*), ip=\[(\S+)\]\s*$/)) { + my $ip = $4; + my $acc = $3; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("Failed POP3 login from","$ip|$acc","pop3d")} else {return} + } + if (($config{LF_IMAPD}) and ($globlogs{IMAPD_LOG}{$lgfile}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) \S+ imapd(-ssl)?: LOGIN FAILED, user=(\S*), ip=\[(\S+)\]\s*$/)) { + my $ip = $4; + my $acc = $3; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("Failed IMAP login from","$ip|$acc","imapd")} else {return} + } + +#uw-imap + if (($config{LF_POP3D}) and ($globlogs{POP3D_LOG}{$lgfile}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) \S+ ipop3d\[\d+\]: Login failed user=(\S*) auth=\S+ host=\S+ \[(\S+)\]\s*$/)) { + my $ip = $3; + my $acc = $2; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("Failed POP3 login from","$ip|$acc","pop3d")} else {return} + } + if (($config{LF_IMAPD}) and ($globlogs{IMAPD_LOG}{$lgfile}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) \S+ imapd\[\d+\]: Login failed user=(\S*) auth=\S+ host=\S+ \[(\S+)\]\s*$/)) { + my $ip = $3; + my $acc = $2; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("Failed IMAP login from","$ip|$acc","imapd")} else {return} + } + +#dovecot + if (($config{LF_POP3D}) and ($globlogs{POP3D_LOG}{$lgfile}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) \S+ dovecot(\[\d+\])?: pop3-login: (Disconnected: )?(Aborted login( by logging out)?|Connection closed|Disconnected|Disconnected: Inactivity)(:\s*\S+\sfailed: Connection reset by peer)?(\s*\(auth failed, \d+ attempts( in \d+ secs)?\))?: (user=(<\S*>)?, )?(method=\S+, )?rip=(\S+), lip=/)) { + my $ip = $12; + my $acc = $10; + $ip =~ s/^::ffff://; + $acc =~ s/^<|>$//g; + if (checkip(\$ip)) {return ("Failed POP3 login from","$ip|$acc","pop3d")} else {return} + } + if (($config{LF_IMAPD}) and ($globlogs{IMAPD_LOG}{$lgfile}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) \S+ dovecot(\[\d+\])?: imap-login: (Disconnected: )?(Aborted login( by logging out)?|Connection closed|Disconnected|Disconnected: Inactivity)(:\s*\S+\sfailed: Connection reset by peer)?(\s*\(auth failed, \d+ attempts( in \d+ secs)?\))?: (user=(<\S*>)?, )?(method=\S+, )?rip=(\S+), lip=/)) { + my $ip = $12; + my $acc = $10; + $ip =~ s/^::ffff://; + $acc =~ s/^<|>$//g; + if (checkip(\$ip)) {return ("Failed IMAP login from","$ip|$acc","imapd")} else {return} + } + if (($config{LF_POP3D}) and ($globlogs{POP3D_LOG}{$lgfile}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) pop3-login(\[\d+\])?: Info: (Aborted login( by logging out)?|Connection closed|Disconnected|Disconnected: Inactivity)(\s*\(auth failed, \d+ attempts( in \d+ secs)?\))?: (user=(<\S*>)?, )?(method=\S+, )?rip=(\S+), lip=/)) { + my $ip = $10; + my $acc = $8; + $ip =~ s/^::ffff://; + $acc =~ s/^<|>$//g; + if (checkip(\$ip)) {return ("Failed POP3 login from","$ip|$acc","pop3d")} else {return} + } + if (($config{LF_IMAPD}) and ($globlogs{IMAPD_LOG}{$lgfile}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) imap-login(\[\d+\])?: Info: (Aborted login( by logging out)?|Connection closed|Disconnected|Disconnected: Inactivity)(\s*\(auth failed, \d+ attempts( in \d+ secs)?\))?: (user=(<\S*>)?, )?(method=\S+, )?rip=(\S+), lip=/)) { + my $ip = $10; + my $acc = $8; + $ip =~ s/^::ffff://; + $acc =~ s/^<|>$//g; + if (checkip(\$ip)) {return ("Failed IMAP login from","$ip|$acc","imapd")} else {return} + } + +#Kerio Mailserver + if (($config{LF_POP3D}) and ($globlogs{POP3D_LOG}{$lgfile}) and ($line =~ /^\S+ \S+ POP3(\[\d+\])?: User (\S*) doesn\'t exist\. Attempt from IP address (\S+)\s*$/)) { + my $ip = $3; + my $acc = $2; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("Failed POP3 login from","$ip|$acc","pop3d")} else {return} + } + if (($config{LF_POP3D}) and ($globlogs{POP3D_LOG}{$lgfile}) and ($line =~ /^\S+ \S+ POP3(\[\d+\])?: Invalid password for user (\S*)\. Attempt from IP address (\S+)\s*$/)) { + my $ip = $3; + my $acc = $2; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("Failed POP3 login from","$ip|$acc","pop3d")} else {return} + } + if (($config{LF_IMAPD}) and ($globlogs{IMAPD_LOG}{$lgfile}) and ($line =~ /^\S+ \S+ IMAP(\[\d+\])?: User (\S*) doesn\'t exist\. Attempt from IP address (\S+)\s*$/)) { + my $ip = $3; + my $acc = $2; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("Failed IMAP login from","$ip|$acc","imapd")} else {return} + } + if (($config{LF_IMAPD}) and ($globlogs{IMAPD_LOG}{$lgfile}) and ($line =~ /^\S+ \S+ IMAP(\[\d+\])?: Invalid password for user (\S*)\. Attempt from IP address (\S+)\s*$/)) { + my $ip = $3; + my $acc = $2; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("Failed IMAP login from","$ip|$acc","imapd")} else {return} + } + if (($config{LF_SMTPAUTH}) and ($globlogs{SMTPAUTH_LOG}{$lgfile}) and ($line =~ /^\S+ \S+ smtp(\[\d+\])?: User (\S*) doesn\'t exist\. Attempt from IP address (\S+)\s*$/)) { + my $ip = $3; + my $acc = $2; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("Failed IMAP login from","$ip|$acc","imapd")} else {return} + } + +#pure-ftpd +#Nov 10 04:28:04 w212 pure-ftpd[3269638]: (?@152.57.198.52) [WARNING] Authentication failed for user [www] + if (($config{LF_FTPD}) and ($globlogs{FTPD_LOG}{$lgfile}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) \S+ pure-ftpd(\[\d+\])?: \(\?\@(\S+)\) \[WARNING\] Authentication failed for user \[(\S*)\]/)) { + my $ip = $3; + my $acc = $4; + $ip =~ s/^::ffff://; + $ip =~ s/\_/\:/g; + if (checkip(\$ip)) {return ("Failed FTP login from","$ip|$acc","ftpd")} else {return} + } + +#proftpd + if (($config{LF_FTPD}) and ($globlogs{FTPD_LOG}{$lgfile}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) \S+ proftpd\[\d+\]:? \S+ \([^\[]+\[(\S+)\]\)( -)?:? - no such user \'(\S*)\'/)) { + my $ip = $2; + my $acc = $4; + $ip =~ s/^::ffff://; + $acc =~ s/:$//g; + if (checkip(\$ip)) {return ("Failed FTP login from","$ip|$acc","ftpd")} else {return} + } + if (($config{LF_FTPD}) and ($globlogs{FTPD_LOG}{$lgfile}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) \S+ proftpd\[\d+\]:? \S+ \([^\[]+\[(\S+)\]\)( -)?:? USER (\S*) no such user found from/)) { + my $ip = $2; + my $acc = $4; + $ip =~ s/^::ffff://; + $acc =~ s/:$//g; + if (checkip(\$ip)) {return ("Failed FTP login from","$ip|$acc","ftpd")} else {return} + } + if (($config{LF_FTPD}) and ($globlogs{FTPD_LOG}{$lgfile}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) \S+ proftpd\[\d+\]:? \S+ \([^\[]+\[(\S+)\]\)( -)?:? - SECURITY VIOLATION/)) { + my $ip = $2; + my $acc = ""; + $ip =~ s/^::ffff://; + $acc =~ s/:$//g; + if (checkip(\$ip)) {return ("Failed FTP login from","$ip|$acc","ftpd")} else {return} + } + if (($config{LF_FTPD}) and ($globlogs{FTPD_LOG}{$lgfile}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) \S+ proftpd\[\d+\]:? \S+ \([^\[]+\[(\S+)\]\)( -)?:? - USER (\S*) \(Login failed\): Incorrect password/)) { + my $ip = $2; + my $acc = $4; + $ip =~ s/^::ffff://; + $acc =~ s/:$//g; + if (checkip(\$ip)) {return ("Failed FTP login from","$ip|$acc","ftpd")} else {return} + } + +#vsftpd + if (($config{LF_FTPD}) and ($globlogs{FTPD_LOG}{$lgfile}) and ($line =~ /^\S+\s+\S+\s+\d+\s+\S+\s+\d+ \[pid \d+] \[(\S+)\] FAIL LOGIN: Client "(\S+)"/)) { + my $ip = $2; + my $acc = $1; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("Failed FTP login from","$ip|$acc","ftpd")} else {return} + } + if (($config{LF_FTPD}) and ($globlogs{FTPD_LOG}{$lgfile}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) \S+ vsftpd\[\d+\]: pam_unix\(\S+\): authentication failure; logname=\S*\s+\S+\s+\S+\s+\S+\s+ruser=\S*\s+rhost=(\S+)(\s+user=(\S*))?/)) { + my $ip = $2; + my $acc = $4; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("Failed FTP login from","$ip|$acc","ftpd")} else {return} + } + if (($config{LF_FTPD}) and ($globlogs{FTPD_LOG}{$lgfile}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) \S+ vsftpd\(pam_unix\)\[\d+\]: authentication failure; logname=\S*\s+\S+\s+\S+\s+\S+\s+ruser=\S*\s+rhost=(\S+)(\s+user=(\S*))?/)) { + my $ip = $2; + my $acc = $4; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("Failed FTP login from","$ip|$acc","ftpd")} else {return} + } + +#apache htaccess + if (($config{LF_HTACCESS}) and ($globlogs{HTACCESS_LOG}{$lgfile}) and ($line =~ /^\[\S+\s+\S+\s+\S+\s+\S+\s+\S+\] \[(\S*:)?error\] (\[pid \d+(:tid \d+)?\] )?\[(client|remote) (\S+)\] (\w+: )?user (\S*)(( not found:)|(: authentication failure for))/)) { + my $ip = $5; + my $acc = $7; + $ip =~ s/^::ffff://; + if ($config{LF_APACHE_ERRPORT} == 2 and $ip =~ /(.*):\d+$/) {$ip = $1} + if (checkip(\$ip)) {return ("Failed web page login from","$ip|$acc","htpasswd")} else {return} + } +#nginx + if (($config{LF_HTACCESS}) and ($globlogs{HTACCESS_LOG}{$lgfile}) and ($line =~ /^\S+ \S+ \[error\] \S+ \*\S+ no user\/password was provided for basic authentication, client: (\S+),/)) { + my $ip = $1; + my $acc = ""; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("Failed web page login from","$ip|$acc","htpasswd")} else {return} + } + if (($config{LF_HTACCESS}) and ($globlogs{HTACCESS_LOG}{$lgfile}) and ($line =~ /^\S+ \S+ \[error\] \S+ \*\S+ user \"(\S*)\": password mismatch, client: (\S+),/)) { + my $ip = $2; + my $acc = $1; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("Failed web page login from","$ip|$acc","htpasswd")} else {return} + } + if (($config{LF_HTACCESS}) and ($globlogs{HTACCESS_LOG}{$lgfile}) and ($line =~ /^\S+ \S+ \[error\] \S+ \*\S+ user \"(\S*)\" was not found in \".*?\", client: (\S+),/)) { + my $ip = $2; + my $acc = $1; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("Failed web page login from","$ip|$acc","htpasswd")} else {return} + } + +#cxs Apache + if (($config{LF_CXS}) and ($globlogs{MODSEC_LOG}{$lgfile}) and ($line =~ /^\[\S+\s+\S+\s+\S+\s+\S+\s+\S+\] \[(\S*:)?error\] (\[pid \d+(:tid \d+)?\] )?\[client (\S+)\]( \[client \S+\])? (\w+: )?ModSecurity:(( \[[^]]+\])*)? Access denied with code \d\d\d \(phase 2\)\. File \"[^\"]*\" rejected by the approver script \"\/etc\/cxs\/cxscgi\.sh\"/)) { + my $ip = $4; + my $acc = ""; + my $domain = ""; + if ($line =~ /\] \[hostname "([^\"]+)"\] \[/) {$domain = $1} + $ip =~ s/^::ffff://; + if ($config{LF_APACHE_ERRPORT} == 2 and $ip =~ /(.*):\d+$/) {$ip = $1} + if (checkip(\$ip)) {return ("cxs mod_security triggered by","$ip|$acc|$domain","cxs")} else {return} + } +#cxs Litespeed + if (($config{LF_CXS}) and ($globlogs{MODSEC_LOG}{$lgfile}) and ($line =~ /^\[\S+\s+\S+\s+\S+\s+\S+\s+\S+\] \[(\S*:)?error\] (\[pid \d+(:tid \d+)?\] )?\[client (\S+)\]( \[client \S+\])? (\w+: )?ModSecurity:(( \[[^]]+\])*)? Access denied with code \d\d\d, \[Rule: 'FILES_TMPNAMES' '\@inspectFile \/etc\/cxs\/cxscgi\.sh'\] \[id "1010101"\]/)) { + my $ip = $4; + my $acc = ""; + my $domain = ""; + if ($line =~ /\] \[hostname "([^\"]+)"\] \[/) {$domain = $1} + $ip =~ s/^::ffff://; + if ($config{LF_APACHE_ERRPORT} == 2 and $ip =~ /(.*):\d+$/) {$ip = $1} + if (checkip(\$ip)) {return ("cxs mod_security triggered by","$ip|$acc|$domain","cxs")} else {return} + } + +#mod_security v1 + if (($config{LF_MODSEC}) and ($globlogs{MODSEC_LOG}{$lgfile}) and ($line =~ /^\[\S+\s+\S+\s+\S+\s+\S+\s+\S+\] \[error\] \[client (\S+)\] mod_security: Access denied/)) { + my $ip = $1; + my $acc = ""; + my $domain = ""; + if ($line =~ /\] \[hostname "([^\"]+)"\] \[/) {$domain = $1} + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("mod_security triggered by","$ip|$acc|$domain","mod_security")} else {return} + } + +#mod_security v2 (apache) + if (($config{LF_MODSEC}) and ($globlogs{MODSEC_LOG}{$lgfile}) and ($line =~ /^\[\S+\s+\S+\s+\S+\s+\S+\s+\S+\] \[(\S*:)?error\] (\[pid \d+(:tid \d+)?\] )?\[client (\S+)\]( \[client \S+\])? (\w+: )?ModSecurity:(( \[[^]]+\])*)? Access denied/)) { + my $ip = $4; + my $acc = ""; + my $domain = ""; + if ($line =~ /\] \[hostname "([^\"]+)"\] \[/) {$domain = $1} + $ip =~ s/^::ffff://; + if ($config{LF_APACHE_ERRPORT} == 2 and $ip =~ /(.*):\d+$/) {$ip = $1} + my $ruleid = "unknown"; + if ($line =~ /\[id "(\d+)"\]/) {$ruleid = $1} + if (checkip(\$ip)) {return ("mod_security (id:$ruleid) triggered by","$ip|$acc|$domain","mod_security")} else {return} + } +#mod_security v2 (nginx) + if (($config{LF_MODSEC}) and ($globlogs{MODSEC_LOG}{$lgfile}) and ($line =~ /^\S+ \S+ \[\S+\] \S+ \[client (\S+)\] ModSecurity:(( \[[^]]+\])*)? Access denied/)) { + my $ip = $1; + my $acc = ""; + my $domain = ""; + if ($line =~ /\] \[hostname "([^\"]+)"\] \[/) {$domain = $1} + $ip =~ s/^::ffff://; + my $ruleid = "unknown"; + if ($line =~ /\[id "(\d+)"\]/) {$ruleid = $1} + if (checkip(\$ip)) {return ("mod_security (id:$ruleid) triggered by","$ip|$acc|$domain","mod_security")} else {return} + } + +#BIND + if (($config{LF_BIND}) and ($globlogs{BIND_LOG}{$lgfile}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) \S+ named\[\d+\]: client( \S+)? (\S+)\#\d+(\s\(\S+\))?\:( view external\:)? (update|zone transfer|query \(cache\)) \'[^\']*\' denied$/)) { + my $ip = $3; + my $acc = ""; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("bind triggered by","$ip|$acc","bind")} else {return} + } + +#suhosin + if (($config{LF_SUHOSIN}) and ($globlogs{SUHOSIN_LOG}{$lgfile})and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) \S+ suhosin\[\d+\]: ALERT - .* \(attacker \'(\S+)\'/)) { + my $ip = $2; + my $acc = ""; + $ip =~ s/^::ffff://; + if ($line !~ /script tried to increase memory_limit/) { + if (checkip(\$ip)) {return ("Suhosin triggered by","$ip|$acc","suhosin")} else {return} + } + } + +#cPanel/WHM + if (($config{LF_CPANEL}) and ($globlogs{CPANEL_LOG}{$lgfile}) and ($line =~ /^\[\S+\s+\S+\s+\S+\] \w+ \[\w+] (\S+) - (\S+) \"[^\"]+\" FAILED LOGIN/)) { + my $ip = $1; + my $acc = $2; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("Failed cPanel login from","$ip|$acc","cpanel")} else {return} + } + if (($config{LF_CPANEL}) and ($globlogs{CPANEL_LOG}{$lgfile}) and ($line =~ /^(\S+) - (\S+)? \[\S+ \S+\] \"[^\"]*\" FAILED LOGIN/)) { + my $ip = $1; + my $acc = $2; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("Failed cPanel login from","$ip|$acc","cpanel")} else {return} + } + +#webmin + if (($config{LF_WEBMIN}) and ($globlogs{WEBMIN_LOG}{$lgfile}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) \S+ webmin\[\d+\]: Invalid login as (\S+) from (\S+)/)) { + my $ip = $3; + my $acc = $2; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("Failed Webmin login from","$ip|$acc","webmin")} else {return} + } + +#DirectAdmin + if (($config{LF_DIRECTADMIN}) and ($globlogs{DIRECTADMIN_LOG}{$lgfile}) and ($line =~ /^\S+ \'(\S+)\' \d+ (failed login attempts\. Account|failed login attempt on account) \'(\S+)\'/)) { + my $ip = $1; + my $acc = $3; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("Failed DirectAdmin login from","$ip|$acc","directadmin")} else {return} + } + if (($config{LF_DIRECTADMIN}) and ($globlogs{DIRECTADMIN_LOG_R}{$lgfile}) and ($line =~ /^\[\S+\s+\S+\s+\S+\]: (<\S+> )?IMAP Error: Login failed for (\S+) (against \S+ )?from (\S+)\. AUTHENTICATE PLAIN: Authentication failed\. in \/var\/www\/html\/roundcubemail/)) { + my $ip = $4; + my $acc = $2; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("Failed DirectAdmin Roundcube login from","$ip|$acc","directadmin")} else {return} + } + if (($config{LF_DIRECTADMIN}) and ($globlogs{DIRECTADMIN_LOG_S}{$lgfile}) and ($line =~ /^\S+\s+\S+ \[LOGIN_ERROR\] (\S+)( \(\S+\))? from (\S+): Unknown user or password incorrect\.\s*$/)) { + my $ip = $3; + my $acc = $1; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("Failed DirectAdmin SquirrelMail login from","$ip|$acc","directadmin")} else {return} + } +#Jun 12 10:58:00 phpmyadmin: user denied: bill (mysql-denied) from 192.168.254.10 + if (($config{LF_DIRECTADMIN}) and ($globlogs{DIRECTADMIN_LOG_P}{$lgfile}) and ($line =~ /^\S+\s+\S+\s+\S+: pma auth user='(\S+)' status='mysql-denied' ip='(\S+)'\s*$/)) { + my $ip = $2; + my $acc = $1; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("Failed DirectAdmin phpMyAdmin login from","$ip|$acc","directadmin")} else {return} + } + if (($config{LF_DIRECTADMIN}) and ($globlogs{DIRECTADMIN_LOG_P}{$lgfile}) and ($line =~ /^\S+\s+\S+\s+\S+ phpmyadmin: user denied: (\S+) \(mysql-denied\) from (\S+)\s*$/)) { + my $ip = $2; + my $acc = $1; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("Failed DirectAdmin phpMyAdmin login from","$ip|$acc","directadmin")} else {return} + } + +#Exim SMTP AUTH + if (($config{LF_SMTPAUTH}) and ($globlogs{SMTPAUTH_LOG}{$lgfile}) and ($line =~ /^\S+\s+\S+\s+(\[\d+\] )?(\S+) authenticator failed for \S+ (\S+ )?\[(\S+)\](:\S*:?)?( I=\S+| \d+\:)? 535 Incorrect authentication data( \(set_id=(\S+)\))?/)) { + my $ip = $4; + my $acc = $8; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("Failed SMTP AUTH login from","$ip|$acc","smtpauth")} else {return} + } + +#Exim Syntax Errors + if (($config{LF_EXIMSYNTAX}) and ($globlogs{SMTPAUTH_LOG}{$lgfile}) and ($line =~ /^\S+\s+\S+\s+(\[\d+\] )?SMTP call from (\S+ )?\[(\S+)\](:\S*:?)?( I=\S+)? dropped: too many syntax or protocol errors/)) { + my $ip = $3; + my $acc = ""; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("Exim syntax errors from","$ip|$acc","eximsyntax")} else {return} + } + if (($config{LF_EXIMSYNTAX}) and ($globlogs{SMTPAUTH_LOG}{$lgfile}) and ($line =~ /^\S+\s+\S+\s+(\[\d+\] )?SMTP protocol error in \"[^\"]+\" H=\S+ (\S+ )?\[(\S+)\](:\S*:?)?( I=\S+)? AUTH command used when not advertised/)) { + my $ip = $3; + my $acc = ""; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("Exim syntax errors from","$ip|$acc","eximsyntax")} else {return} + } + +#mod_qos + if (($config{LF_QOS}) and ($globlogs{HTACCESS_LOG}{$lgfile}) and ($line =~ /^\[\S+\s+\S+\s+\S+\s+\S+\s+\S+\] \[(\S*:)?error\] (\[pid \d+(:tid \d+)?\] )?\[client (\S+)\] (\w+: )?mod_qos\(\d+\): access denied,/)) { + my $ip = $4; + my $acc = ""; + $ip =~ s/^::ffff://; + if ($config{LF_APACHE_ERRPORT} == 2 and $ip =~ /(.*):\d+$/) {$ip = $1} + if (checkip(\$ip)) {return ("mod_qos triggered by","$ip|$acc","mod_qos")} else {return} + } + +#Apache symlink race condition + if (($config{LF_SYMLINK}) and ($globlogs{MODSEC_LOG}{$lgfile}) and ($line =~ /^\[\S+\s+\S+\s+\S+\s+\S+\s+\S+\] \[(\S*:)?error\] (\[pid \d+(:tid \d+)?\] )?\[client (\S+)\] (\w+: )?Caught race condition abuser/)) { + my $ip = $4; + my $acc = ""; + $ip =~ s/^::ffff://; + if ($config{LF_APACHE_ERRPORT} == 2 and $ip =~ /(.*):\d+$/) {$ip = $1} + if ($line !~ /\/cgi-sys\/suspendedpage\.cgi$/) { + if (checkip(\$ip)) {return ("symlink race condition triggered by","$ip|$acc","symlink")} else {return} + } + } + +#courier-imap (Plesk) + if (($config{LF_POP3D}) and ($globlogs{POP3D_LOG}{$lgfile}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) \S+ (courier-)?pop3(?:d|s)(-ssl)?(\[\d+\])?: LOGIN FAILED, user=(\S*), ip=\[(\S+)\]\s*$/)) { + my $ip = $6; + my $acc = $5; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("Failed POP3 login from","$ip|$acc","pop3d")} else {return} + } + if (($config{LF_IMAPD}) and ($globlogs{IMAPD_LOG}{$lgfile}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) \S+ (courier-)?imap(?:d|s)(-ssl)?(\[\d+\])?: LOGIN FAILED, user=(\S*), ip=\[(\S+)\]\s*$/)) { + my $ip = $6; + my $acc = $5; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("Failed IMAP login from","$ip|$acc","imapd")} else {return} + } + +#Qmail SMTP AUTH (Plesk) + if (($config{LF_SMTPAUTH}) and ($globlogs{SMTPAUTH_LOG}{$lgfile}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) \S+ smtp_auth(?:\[\d+\])?: FAILED: (\S*) - password incorrect from \S+ \[(\S+)\]\s*$/)) { + my $ip = $3; + my $acc = $2; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("Failed SMTP AUTH login from","$ip|$acc","smtpauth")} else {return} + } + +#Postfix SMTP AUTH (Plesk) + if (($config{LF_SMTPAUTH}) and ($globlogs{SMTPAUTH_LOG}{$lgfile}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) \S+ postfix\/(submission\/)?smtpd(?:\[\d+\])?: warning: \S+\[(\S+)\]: SASL (?:(?i)LOGIN|PLAIN|(?:CRAM|DIGEST)-MD5) authentication failed/)) { + my $ip = $3; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("Failed SMTP AUTH login from","$ip","smtpauth")} else {return} + } + +#InterWorx (dovecot, proftpd, qmail) + if (($config{LF_POP3D}) and ($globlogs{POP3D_LOG}{$lgfile}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) pop3-login(\[\d+\])?: Info: (Aborted login|Disconnected|Disconnected: Inactivity)( \(auth failed, \d+ attempts( in \d+ secs)?\))?: (user=(<\S*>)?, )?(method=\S+, )?rip=(\S+), lip=/)) { + my $ip = $9; + my $acc = $7; + $ip =~ s/^::ffff://; + $acc =~ s/^<|>$//g; + if (checkip(\$ip)) {return ("Failed POP3 login from","$ip|$acc","pop3d")} else {return} + } + if (($config{LF_IMAPD}) and ($globlogs{IMAPD_LOG}{$lgfile}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) imap-login(\[\d+\])?: Info: (Aborted login|Disconnected|Disconnected: Inactivity)( \(auth failed, \d+ attempts( in \d+ secs)?\))?: (user=(<\S*>)?, )?(method=\S+, )?rip=(\S+), lip=/)) { + my $ip = $9; + my $acc = $7; + $ip =~ s/^::ffff://; + $acc =~ s/^<|>$//g; + if (checkip(\$ip)) {return ("Failed IMAP login from","$ip|$acc","imapd")} else {return} + } + if (($config{LF_FTPD}) and ($globlogs{FTPD_LOG}{$lgfile}) and ($line =~ /^\S+ \S+ \S+ proftpd\[\d+\]:? \S+ \(\S+?[^\[]+\[(\S+)\]\)( -)?:? USER (\S*): no such user found from/)) { + my $ip = $1; + my $acc = $3; + $ip =~ s/^::ffff://; + $acc =~ s/:$//g; + if (checkip(\$ip)) {return ("Failed FTP login from","$ip|$acc","ftpd")} else {return} + } + if (($config{LF_FTPD}) and ($globlogs{FTPD_LOG}{$lgfile}) and ($line =~ /^\S+ \S+ \S+ proftpd\[\d+\]:? \S+ \(\S+?[^\[]+\[(\S+)\]\)( -)?:? USER (\S*) \(Login failed\): Incorrect password/)) { + my $ip = $1; + my $acc = $3; + $ip =~ s/^::ffff://; + $acc =~ s/:$//g; + if (checkip(\$ip)) {return ("Failed FTP login from","$ip|$acc","ftpd")} else {return} + } + if (($config{LF_SMTPAUTH}) and ($globlogs{SMTPAUTH_LOG}{$lgfile}) and ($line =~ /^\S+ qmail-smtpd\[\d+\]: AUTH failed \[(\S+)\] (\S+)/)) { + my $ip = $1; + my $acc = $2; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("Failed SMTP AUTH login from","$ip|$acc","smtpauth")} else {return} + } + if (($config{LF_INTERWORX}) and ($globlogs{INTERWORX_LOG}{$lgfile}) and ($line =~ /^\S+ \S+ (\S+) (\S+) (\S+)/)) { + my $iw = "SiteWorx"; + if ($1 eq "NW") {$iw = "NodeWorx"} + my $ip = $2; + my $acc = $3; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("Failed $iw login from","$ip|$acc","interworx")} else {return} + } + +# CWP + if (($config{LF_CWP}) and ($globlogs{CWP_LOG}{$lgfile}) and ($line =~ /^\S+\s+\S+\s+(\S+)\s+Failed Login from:\s+(\S+) on:/)) { + my $ip = $2; + my $acc = $1; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("Failed CWP login from","$ip|$acc","cwp")} else {return} + } +# VestaCP + if (($config{LF_VESTA}) and ($globlogs{VESTA_LOG}{$lgfile}) and ($line =~ /^\S+\s+\S+\s+(\S+)\s+(\S+) failed to login/)) { + my $ip = $2; + my $acc = $1; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("Failed VestaCP login from","$ip|$acc","vesta")} else {return} + } + +} +# end processline +############################################################################### +# start processloginline +sub processloginline { + my $line = shift; + +#courier-imap + if (($config{LT_POP3D}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) \S+ pop3d(-ssl)?: LOGIN, user=(\S*), ip=\[(\S+)\], port=\S+/)) { + my $ip = $4; + my $acc = $3; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("pop3d",$acc,$ip)} else {return} + } + if (($config{LT_IMAPD}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) \S+ imapd(-ssl)?: LOGIN, user=(\S*), ip=\[(\S+)\], port=\S+/)) { + my $ip = $4; + my $acc = $3; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("imapd",$acc,$ip)} else {return} + } + +#dovecot + if (($config{LT_POP3D}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) \S+ dovecot(\[\d+\])?: pop3-login: Login: user=<(\S*)>, method=\S+, rip=(\S+), lip=/)) { + my $ip = $4; + my $acc = $3; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("pop3d",$acc,$ip)} else {return} + } + if (($config{LT_IMAPD}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) \S+ dovecot(\[\d+\])?: imap-login: Login: user=<(\S*)>, method=\S+, rip=(\S+), lip=/)) { + my $ip = $4; + my $acc = $3; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("imapd",$acc,$ip)} else {return} + } + +#InterWorx (dovecot) + if (($config{LT_POP3D}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) pop3-login: Info: Login: user=<(\S*)>, method=\S+, rip=(\S+), lip=/)) { + my $ip = $3; + my $acc = $2; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("pop3d",$acc,$ip)} else {return} + } + if (($config{LT_IMAPD}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) imap-login: Info: Login: user=<(\S*)>, method=\S+, rip=(\S+), lip=/)) { + my $ip = $3; + my $acc = $2; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ("imapd",$acc,$ip)} else {return} + } +} +# end processloginline +############################################################################### +# start processsshline +sub processsshline { + my $line = shift; + + if (($config{LF_SSH_EMAIL_ALERT}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) (\S+ )?sshd\[\d+\]: Accepted (\S+) for (\S+) from (\S+) port \S+/)) { + my $ip = $5; + my $acc = $4; + my $how = $3; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ($acc,$ip,$how)} else {return} + } +} +# end processsshline +############################################################################### +# start processsuline +sub processsuline { + my $line = shift; + +#RH + Debian/Ubuntu + if (($config{LF_SU_EMAIL_ALERT}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) (\S+ )?su(\[\d+\])?: pam_unix\(su(-l)?:session\): session opened for user\s+(\S+)\s+by\s+(\S+)\s*$/)) { + return ($5,$6,"Successful login"); + } + if (($config{LF_SU_EMAIL_ALERT}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) (\S+ )?su(\[\d+\])?: pam_unix\(su(-l)?:auth\): authentication failure; logname=\S*\s+\S+\s+\S+\s+\S+\s+ruser=(\S+)+\s+\S+\s+user=(\S+)\s*$/)) { + return ($6,$5,"Failed login"); + } + + if (($config{LF_SU_EMAIL_ALERT}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) (\S+ )?su(\[\d+\])?: pam_unix\(su(-l)?:session\): session opened for user\s+(\S+)\s+by\s+(\S+)\s*$/)) { + return ($5,$6,"Successful login"); + } + if (($config{LF_SU_EMAIL_ALERT}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) (\S+ )?su(\[\d+\])?: pam_unix\(su(-l)?:auth\): authentication failure; logname=\S*\s+\S+\s+\S+\s+\S+\s+ruser=(\S+)+\s+\S+\s+user=(\S+)\s*$/)) { + return ($6,$5,"Failed login"); + } + + if (($config{LF_SU_EMAIL_ALERT}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) (\S+ )?su\(pam_unix\)\[\d+\]: session opened for user\s+(\S+)\s+by\s+(\S+)\s*$/)) { + return ($3,$4,"Successful login"); + } + if (($config{LF_SU_EMAIL_ALERT}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) (\S+ )?su\(pam_unix\)\[\d+\]: authentication failure; logname=\S*\s+\S+\s+\S+\s+\S+\s+ruser=(\S+)+\s+\S+\s+user=(\S+)\s*$/)) { + return ($4,$3,"Failed login"); + } + return; +} +# end processsuline +############################################################################### +# start processsudoline +sub processsudoline { + my $line = shift; + + if (($config{LF_SUDO_EMAIL_ALERT}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) (\S+ )?sudo(\[\d+\])?: pam_unix\(sudo(-l)?:auth\): authentication failure; logname=\S*\s+\S+\s+\S+\s+\S+\s+ruser=(\S+)+\s+\S+\s+user=(\S+)\s*$/)) { + return ($6,$5,"Failed login"); + } + if (($config{LF_SUDO_EMAIL_ALERT}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) (\S+ )?sudo\(pam_unix\)\[\d+\]: authentication failure; logname=\S*\s+\S+\s+\S+\s+\S+\s+ruser=(\S+)+\s+\S+\s+user=(\S+)\s*$/)) { + return ($4,$3,"Failed login"); + } + + if (($config{LF_SUDO_EMAIL_ALERT}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) (\S+ )?sudo(\[\d+\])?:\s+(\S+)\s+:\s+(.*)$/)) { + my $from = $4; + my @items = split(/\s+;\s+/, $5); + if ($items[0] =~ /^TTY/) { + if ($items[2] =~ /^USER=(\S+)$/) { + return ($1,$from,"Successful login"); + } + } + elsif ($items[0] =~ /^user NOT in sudoers/) { + if ($items[3] =~ /^USER=(\w+)$/) { + return ($1,$from,"Failed login"); + } + } + } + return; +} +# end processsudoline +############################################################################### +# start processconsoleline +sub processconsoleline { + my $line = shift; + + if (($config{LF_CONSOLE_EMAIL_ALERT}) and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) \S+ login(\[\d+\])?: ROOT LOGIN/)) { + return 1; + } +} +# end processconsoleline +############################################################################### +# start processcpanelline +sub processcpanelline { + my $line = shift; + + if ($config{LF_CPANEL_ALERT} and ($line =~ /^(\S+)\s+\-\s+(\w+)\s+\[[^\]]+\]\s\"[^\"]+\"\s200\s/)) { + my $ip = $1; + my $acc = $2; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ($ip,$acc)} else {return} + } +} +# end processcpanelline +############################################################################### +# start processwebminline +sub processwebminline { + my $line = shift; + + if ($config{LF_WEBMIN_EMAIL_ALERT} and ($line =~ /^(\S+|\S+\s+\d+\s+\S+) \S+ webmin\[\d+\]: Successful login as (\S+) from (\S+)/)) { + my $ip = $3; + my $acc = $2; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ($acc,$ip)} else {return} + } +} +# end processwebminline +############################################################################### +# start scriptlinecheck +sub scriptlinecheck { + my $line = shift; + + if ($config{LF_SCRIPT_ALERT}) { + my $fulldir; + if ($line =~ /^\S+\s+\S+\s+(\[\d+\]\s)?cwd=(.*) \d+ args:/) {$fulldir = $2} + elsif ($line =~ /^\S+\s+\S+\s+(\[\d+\]\s)?\S+ H=localhost (.*)PWD=(.*) REMOTE_ADDR=\S+$/) {$fulldir = $3} + if ($fulldir ne "") { + my (undef,$dir,undef) = split(/\//,$fulldir); + if ($dir eq "home") {return $fulldir} + if ($cpconfig{HOMEDIR} and ($fulldir =~ /^$cpconfig{HOMEDIR}/)) {return $fulldir} + if ($cpconfig{HOMEMATCH} and ($dir =~ /$cpconfig{HOMEMATCH}/)) {return $fulldir} + } + } +} +# end scriptlinecheck +############################################################################### +# start relaycheck +sub relaycheck { + my $line = shift; + my $tline = $line; + $tline =~ s/".*"/""/g; + my @bits =split(/\s+/,$tline); + my $ip; + + if ($tline !~ /^\S+\s+\S+\s+(\[\d+\]\s)?\S+ <=/) {return} + +#exim + if ($tline =~ / U=(\S+) P=local /) { + return ($1, "LOCALRELAY"); + } + + if ($tline =~ / H=[^=]*\[(\S+)\]/) { + $ip = $1; + unless (checkip(\$ip) or $ip eq "127.0.0.1" or $ip eq "::1") {return} + } else { + return; + } + + if (($tline =~ / A=(courier_plain|courier_login|dovecot_plain|dovecot_login|fixed_login|fixed_plain|login|plain):/) and ($tline =~ / P=(esmtpa|esmtpsa) /)) { + return ($ip, "AUTHRELAY"); + } + + if ($tline =~ / P=(smtp|esmtp|esmtps) /) { + return ($ip, "RELAY"); + } + +} +# end relaycheck +############################################################################### +# start pslinecheck +sub pslinecheck { + my $line = shift; + if ($line !~ /^(\S+|\S+\s+\d+\s+\S+) \S+ kernel:\s(\[[^\]]+\]\s)?Firewall:/) {return} + if ($line =~ /^(\S+|\S+\s+\d+\s+\S+) \S+ kernel:\s(\[[^\]]+\]\s)?Firewall: \*INVALID\*/ and $config{PS_PORTS} !~ /INVALID/) {return} + + if ($line =~ /IN=\S+.*SRC=(\S+).*DST=(\S+).*PROTO=(\w+).*DPT=(\d+)/) { + my $ip = $1; + my $dst = $2; + my $proto = $3; + my $port = $4; + $ip =~ s/^::ffff://; + if ($config{PS_PORTS} !~ /BRD/ and $proto eq "UDP" and $brd{$dst} and !$ips{$dst}) {return} + if ($config{PS_PORTS} !~ /OPEN/) { + my $hit = 0; + if ($proto eq "TCP" and $line =~ /kernel:\s(\[[^\]]+\]\s)?Firewall: \*TCP_IN Blocked\*/) { + foreach my $ports (split(/\,/,$config{TCP_IN})) { + if ($ports =~ /\:/) { + my ($start,$end) = split(/\:/,$ports); + if ($port >= $start and $port <= $end) {$hit = 1} + } + elsif ($port == $ports) {$hit = 1} + if ($hit) {last} + } + if ($hit) { + if ($config{DEBUG} >= 1) {ConfigServer::Logger::logfile("debug: *Port Scan* ignored TCP_IN port: $ip:$port")} + return; + } + } + elsif ($proto eq "UDP" and $line =~ /kernel:\s(\[[^\]]+\]\s)?Firewall: \*UDP_IN Blocked\*/) { + foreach my $ports (split(/\,/,$config{UDP_IN})) { + if ($ports =~ /\:/) { + my ($start,$end) = split(/\:/,$ports); + if ($port >= $start and $port <= $end) {$hit = 1} + } + elsif ($port == $ports) {$hit = 1} + if ($hit) {last} + } + if ($hit) { + if ($config{DEBUG} >= 1) {ConfigServer::Logger::logfile("debug: *Port Scan* ignored UDP_IN port: $ip:$port")} + return; + } + } + } + if (checkip(\$ip)) {return ($ip,$port)} else {return} + } + if ($line =~ /IN=\S+.*SRC=(\S+).*PROTO=(ICMP)/) { + my $ip = $1; + my $port = $2; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ($ip,$port)} else {return} + } + if ($line =~ /IN=\S+.*SRC=(\S+).*PROTO=(ICMPv6)/) { + my $ip = $1; + my $port = $2; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ($ip,$port)} else {return} + } +} +# end pslinecheck +############################################################################### +# start uidlinecheck +sub uidlinecheck { + my $line = shift; + if ($line !~ /^(\S+|\S+\s+\d+\s+\S+) \S+ kernel(\[\d+\])?:\s(\[[^\]]+\]\s)?Firewall:/) {return} + if ($line =~ /OUT=\S+.*DPT=(\S+).*UID=(\d+)/) {return ($1,$2)} +} +# end uidlinecheck +############################################################################### +# start portknockingcheck +sub portknockingcheck { + my $line = shift; + if ($line !~ /^(\S+|\S+\s+\d+\s+\S+) \S+ kernel(\[\d+\])?:\s(\[[^\]]+\]\s)?Knock: \*\d+_IN\*/) {return} + + if ($line =~ /SRC=(\S+).*DPT=(\d+)/) { + my $ip = $1; + my $port = $2; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ($ip,$port)} else {return} + } +} +# end portknockingcheck +############################################################################### +# start processdistftpline +sub processdistftpline { + my $line = shift; +#pure-ftpd + if ($line =~ /^(\S+|\S+\s+\d+\s+\S+) \S+ pure-ftpd(\[\d+\])?: \(\?\@(\S+)\) \[INFO\] (\S*) is now logged in$/) { + my $ip = $3; + my $acc = $4; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ($ip,$acc)} else {return} + } +#proftpd + if ($line =~ /^(\S+|\S+\s+\d+\s+\S+) \S+ proftpd\[\d+\]: \S+ \([^\[]+\[(\S+)\]\) - USER (\S*): Login successful\.\s*$/) { + my $ip = $2; + my $acc = $3; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ($ip,$acc)} else {return} + } +#InterWorx proftpd + if ($line =~ /^\S+ \S+ \S+ proftpd\[\d+\]:? \S+ \(\S+?[^\[]+\[(\S+)\]\)( -)?:? USER (\S*): Login successful/) { + my $ip = $1; + my $acc = $3; + $ip =~ s/^::ffff://; + if (checkip(\$ip)) {return ($ip,$acc)} else {return} + } +} +# end processdistftpline +############################################################################### +# start processdistsmtpline +sub processdistsmtpline { + my $line = shift; + my $tline = $line; + $tline =~ s/".*"/""/g; + my @bits =split(/\s+/,$tline); + my $ip; + +#postfix + if ($line =~ /^(\S+|\S+\s+\d+\s+\S+) \S+ postfix\/(submission\/)?smtpd(?:\[\d+\])?: \w+: client=\S+\[(\S+)\], sasl_method=(?:(?i)LOGIN|PLAIN|(?:CRAM|DIGEST)-MD5), sasl_username=(\S+)$/) { + $ip = $3; my $account = $4; $ip =~ s/^::ffff://; + if (checkip(\$ip) and $ip ne "127.0.0.1" and $ip ne "::1") {return ($ip,$account)} else {return} + } + +#InterWorx qmail + if ($line =~ /^\S+ qmail-smtpd\[\d+\]: AUTH successful \[(\S+)\] (\S+)/) { + $ip = $1; my $account = $2; $ip =~ s/^::ffff://; + if (checkip(\$ip) and $ip ne "127.0.0.1" and $ip ne "::1") {return ($ip,$account)} else {return} + } + +#exim + if ($tline !~ /^\S+\s+\S+\s+(\[\d+\]\s)?\S+ <=/) {return} + + if ($tline =~ / U=(\S+) P=local /) {return} + + if ($tline =~ / H=[^=]*\[(\S+)\]/) { + $ip = $1; + unless (checkip(\$ip) or $ip eq "127.0.0.1" or $ip eq "::1") {return} + } else { + return; + } + + if (($tline =~ / A=(courier_plain|courier_login|dovecot_plain|dovecot_login|fixed_login|fixed_plain|login|plain):(\S+)/)){ + my $account = $2; + if (($tline =~ / P=(esmtpa|esmtpsa) /)) {return ($ip, $account)} + } +} +# end processdistsmtpline +############################################################################### +# start loginline404 +sub loginline404 { + my $line = shift; + if ($line =~ /^\[\S+\s+\S+\s+\S+\s+\S+\s+\S+\] \[(\S*:)?(error|info)\] (\[pid \d+(:tid \d+)?\] )?\[client (\S+)\] (\w+: )?File does not exist\:/) { + my $ip = $5; + $ip =~ s/^::ffff://; + if ($config{LF_APACHE_ERRPORT} == 2 and $ip =~ /(.*):\d+$/) {$ip = $1} + if (checkip(\$ip)) {return ($ip)} else {return} + } +} +# end loginline404 +############################################################################### +# start loginline403 +sub loginline403 { + my $line = shift; + if ($line =~ /^\[\S+\s+\S+\s+\S+\s+\S+\s+\S+\] \[(\S*:)?error\] (\[pid \d+(:tid \d+)?\] )?\[client (\S+)\] (\w+: )?client denied by server configuration\:/) { + my $ip = $4; + $ip =~ s/^::ffff://; + if ($config{LF_APACHE_ERRPORT} == 2 and $ip =~ /(.*):\d+$/) {$ip = $1} + if (checkip(\$ip)) {return ($ip)} else {return} + } +} +# end loginline403 +############################################################################### +# start loginline401 +sub loginline401 { + my $line = shift; + if ($line =~ /^\[\S+\s+\S+\s+\S+\s+\S+\s+\S+\] \[(\S*:)?error\] (\[pid \d+(:tid \d+)?\] )?\[client (\S+)\] (\w+: )?(user not found|user \w+ not found|user \w+: authentication failure for "\/\w+\/")\:/) { + my $ip = $4; + $ip =~ s/^::ffff://; + if ($config{LF_APACHE_ERRPORT} == 2 and $ip =~ /(.*):\d+$/) {$ip = $1} + if (checkip(\$ip)) {return ($ip)} else {return} + } +} +# end loginline401 +############################################################################### +# start statscheck +sub statscheck { + my $line = shift; + if ($line =~ /^(\S+|\S+\s+\d+\s+\S+) \S+ kernel:\s(\[[^\]]+\]\s)?(Firewall|Knock):/) {return 1} +} +# end statscheck +############################################################################### +# start syslogcheckline +sub syslogcheckline { + my $line = shift; + my $syslogcheckcode = shift; + if ($line =~ /^(\S+|\S+\s+\d+\s+\S+) \S+ lfd\[\d+\]: SYSLOG check \[(\S+)\]\s*$/) { + if ($2 eq $syslogcheckcode) {return 1} else {return} + } +} +# end syslogcheckline +############################################################################### + +1; diff --git a/src/redux/ConfigServer/Sanity.pm b/src/redux/ConfigServer/Sanity.pm new file mode 100644 index 000000000..81a5f290b --- /dev/null +++ b/src/redux/ConfigServer/Sanity.pm @@ -0,0 +1,73 @@ +############################################################################### +# Copyright 2006-2023, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +## no critic (RequireUseWarnings, ProhibitExplicitReturnUndef, ProhibitMixedBooleanOperators, RequireBriefOpen) +# start main +package ConfigServer::Sanity; + +use strict; +use lib '/usr/local/csf/lib'; +use Fcntl qw(:DEFAULT :flock); +use Carp; +use ConfigServer::Config; + +use Exporter qw(import); +our $VERSION = 1.02; +our @ISA = qw(Exporter); +our @EXPORT_OK = qw(sanity); + +my %sanity; +my %sanitydefault; +my $sanityfile = "/usr/local/csf/lib/sanity.txt"; + +open (my $IN, "<", $sanityfile); +flock ($IN, LOCK_SH); +my @data = <$IN>; +close ($IN); +chomp @data; +foreach my $line (@data) { + my ($name,$value,$def) = split(/\=/,$line); + $sanity{$name} = $value; + $sanitydefault{$name} = $def; +} + +my $config = ConfigServer::Config->loadconfig(); +my %config = $config->config(); + +if ($config{IPSET}) { + delete $sanity{"DENY_IP_LIMIT"}; + delete $sanitydefault{"DENY_IP_LIMIT"}; +} + +# end main +############################################################################### +# start sanity +sub sanity { + my $sanity_item = shift; + my $sanity_value = shift; + my $insane = 0; + + $sanity_item =~ s/\s//g; + $sanity_value =~ s/\s//g; + + if (defined $sanity{$sanity_item}) { + $insane = 1; + foreach my $check (split(/\|/,$sanity{$sanity_item})) { + if ($check =~ /-/) { + my ($from,$to) = split(/\-/,$check); + if (($sanity_value >= $from) and ($sanity_value <= $to)) {$insane = 0} + + } else { + if ($sanity_value eq $check) {$insane = 0} + } + } + $sanity{$sanity_item} =~ s/\|/ or /g; + } + return ($insane,$sanity{$sanity_item},$sanitydefault{$sanity_item}); +} +# end sanity +############################################################################### + +1; \ No newline at end of file diff --git a/src/redux/ConfigServer/Sendmail.pm b/src/redux/ConfigServer/Sendmail.pm new file mode 100644 index 000000000..e0956499f --- /dev/null +++ b/src/redux/ConfigServer/Sendmail.pm @@ -0,0 +1,166 @@ +############################################################################### +# Copyright 2006-2023, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +## no critic (RequireUseWarnings, ProhibitExplicitReturnUndef, ProhibitMixedBooleanOperators, RequireBriefOpen) +# start main +package ConfigServer::Sendmail; + +use strict; +use lib '/usr/local/csf/lib'; +use Carp; +use POSIX qw(strftime); +use Fcntl qw(:DEFAULT :flock); +use ConfigServer::Config; +use ConfigServer::CheckIP qw(checkip); + +use Exporter qw(import); +our $VERSION = 1.02; +our @ISA = qw(Exporter); +our @EXPORT_OK = qw(); + +my $config = ConfigServer::Config->loadconfig(); +my %config = $config->config(); +my $tz = strftime("%z", localtime); +my $hostname; +if (-e "/proc/sys/kernel/hostname") { + open (my $IN, "<", "/proc/sys/kernel/hostname"); + flock ($IN, LOCK_SH); + $hostname = <$IN>; + chomp $hostname; + close ($IN); +} else { + $hostname = "unknown"; +} + +if ($config{LF_ALERT_SMTP}) { + require Net::SMTP; + import Net::SMTP; +} + +# end main +############################################################################### +# start sendmail +sub relay { + my ($to, $from, @message) = @_; + my $time = localtime(time); + if ($to eq "") {$to = $config{LF_ALERT_TO}} else {$config{LF_ALERT_TO} = $to} + if ($from eq "") {$from = $config{LF_ALERT_FROM}} else {$config{LF_ALERT_FROM} = $from} + my $data; + + if ($from =~ /([\w\.\=\-\_]+\@[\w\.\-\_]+)/) {$from = $1} + if ($from eq "") {$from = "root"} + if ($to =~ /([\w\.\=\-\_]+\@[\w\.\-\_]+)/) {$to = $1} + if ($to eq "") {$to = "root"} + + my $header = 1; + foreach my $line (@message) { + $line =~ s/\r//; + if ($line eq "") {$header = 0} + $line =~ s/\[time\]/$time $tz/ig; + $line =~ s/\[hostname\]/$hostname/ig; + if ($header) { + if ($line =~ /^To:\s*(.*)\s*$/i) { + my $totxt = $1; + if ($config{LF_ALERT_TO} ne "") { + $line =~ s/^To:.*$/To: $config{LF_ALERT_TO}/i; + } else { + $to = $totxt; + } + } + if ($line =~ /^From:\s*(.*)\s*$/i) { + my $fromtxt = $1; + if ($config{LF_ALERT_FROM} ne "") { + $line =~ s/^From:.*$/From: $config{LF_ALERT_FROM}/i; + } else { + $from = $1; + } + } + } + $data .= $line."\n"; + } + + $data = &wraptext($data, 990); + + if ($config{LF_ALERT_SMTP}) { + if ($from !~ /\@/) {$from .= '@'.$hostname} + if ($to !~ /\@/) {$to .= '@'.$hostname} + my $smtp = Net::SMTP->new($config{LF_ALERT_SMTP}, Timeout => 10) or carp("Unable to send SMTP alert via [$config{LF_ALERT_SMTP}]: $!"); + if (defined $smtp) { + $smtp->mail($from); + $smtp->to($to); + $smtp->data(); + $smtp->datasend($data); + $smtp->dataend(); + $smtp->quit(); + } + } else { + local $SIG{CHLD} = 'DEFAULT'; + my $error = 0; + open (my $MAIL, "|-", "$config{SENDMAIL} -f $from -t") or carp("Unable to send SENDMAIL alert via [$config{SENDMAIL}]: $!"); + print $MAIL $data; + close ($MAIL) or $error = 1; + if ($error and $config{DEBUG}) { + logfile("Failed to send message via sendmail binary: $?"); + logfile("Failed message: [$data]"); + } + } + + return; +} +# end sendmail +############################################################################### +# start wraptext +sub wraptext { + my $text = shift; + my $column = shift; + my $original = $text; + my $return = ""; + my $hit = 1; + my $loop = 0; + while ($hit) { + $hit = 0; + $return = ""; + foreach my $line (split(/\n/, $text)) { + if (length($line) > $column) { + foreach ($line =~ /(.{1,$column})/g) { + my $chunk = $_; + my $newchunk = ""; + my $thishit = 0; + my @chars = split(//,$chunk); + for (my $x = length($chunk)-1;$x >= 0; $x--) { + if ($chars[$x] =~ /\s/) { + for (0..$x) {$newchunk .= $chars[$_]} + $newchunk .= "\n"; + for ($x+1..length($chunk)-1) {$newchunk .= $chars[$_]} + $thishit = 1; + last; + } + } + if ($thishit) { + $hit = 1; + $thishit = 0; + $return .= $newchunk; + } else { + $return .= $chunk."\n"; + } + } + } else { + $return .= $line."\n"; + } + } + $text = $return; + $loop++; + if ($loop > 1000) { + return $original; + last; + } + } + if (length($return) < length($original)) {$return = $original} + return $return; +} +# end wraptext +############################################################################### + +1; \ No newline at end of file diff --git a/src/redux/ConfigServer/ServerCheck.pm b/src/redux/ConfigServer/ServerCheck.pm new file mode 100644 index 000000000..df09f1718 --- /dev/null +++ b/src/redux/ConfigServer/ServerCheck.pm @@ -0,0 +1,1762 @@ +############################################################################### +# Copyright 2006-2023, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +## no critic (RequireUseWarnings, ProhibitExplicitReturnUndef, ProhibitMixedBooleanOperators, RequireBriefOpen) +# start main +package ConfigServer::ServerCheck; + +use strict; +use lib '/usr/local/csf/lib'; +use Fcntl qw(:DEFAULT :flock); +use File::Basename; +use IPC::Open3; +use ConfigServer::Slurp qw(slurp); +use ConfigServer::Sanity qw(sanity);; +use ConfigServer::Config; +use ConfigServer::GetIPs qw(getips); +use ConfigServer::CheckIP qw(checkip); +use ConfigServer::Service; +use ConfigServer::GetEthDev; + +use Exporter qw(import); +our $VERSION = 1.05; +our @ISA = qw(Exporter); +our @EXPORT_OK = qw(); + +my (%config, $cpconf, %daconfig, $cleanreg, $mypid, $childin, $childout, + $verbose, $cpurl, @processes, $total, $failures, $current, $DEBIAN, + $output, $sysinit, %g_ifaces, %g_ipv4, %g_ipv6); + +my $ipv4reg = ConfigServer::Config->ipv4reg; +my $ipv6reg = ConfigServer::Config->ipv6reg; + +use Exporter qw(import); +# end main +############################################################################### +# start report +sub report { + $verbose = shift; + my $config = ConfigServer::Config->loadconfig(); + %config = $config->config(); + $cleanreg = ConfigServer::Slurp->cleanreg; + $| = 1; + + if (defined $ENV{WEBMIN_VAR} and defined $ENV{WEBMIN_CONFIG}) { + $config{GENERIC} = 1; + $config{DIRECTADMIN} = 0; + } + elsif (-e "/usr/local/cpanel/version") { + use lib "/usr/local/cpanel"; + require Cpanel::Form; + import Cpanel::Form; + require Cpanel::Config; + import Cpanel::Config; + $cpconf = Cpanel::Config::loadcpconf(); + } + elsif (-e "/usr/local/directadmin/conf/directadmin.conf") { + my ($childin, $childout); + my $mypid = open3($childin, $childout, $childout, "/usr/local/directadmin/directadmin", "c"); + my @data = <$childout>; + waitpid ($mypid, 0); + chomp @data; + foreach my $line (@data) { + my ($name,$value) = split(/\=/,$line); + $daconfig{lc($name)} = $value; + } + $config{DIRECTADMIN} = 1; + } + elsif (-e "/etc/psa/psa.conf") { + $config{PLESK} = 1; + } + + $failures = 0; + $total = 0; + if ($ENV{cp_security_token}) {$cpurl = $ENV{cp_security_token}} + $DEBIAN = 0; + if (-e "/etc/lsb-release" or -e "/etc/debian_version") {$DEBIAN = 1} + + $sysinit = ConfigServer::Service::type(); + if ($sysinit ne "systemd") {$sysinit = "init"} + + opendir (PROCDIR, "/proc"); + while (my $pid = readdir(PROCDIR)) { + if ($pid !~ /^\d+$/) {next} + push @processes, readlink("/proc/$pid/exe"); + } + + my $ethdev = ConfigServer::GetEthDev->new(); + %g_ifaces = $ethdev->ifaces; + %g_ipv4 = $ethdev->ipv4; + %g_ipv6 = $ethdev->ipv6; + + &startoutput; + + &firewallcheck; + &servercheck; + &sshtelnetcheck; + unless ($config{DNSONLY} or $config{GENERIC}) {&mailcheck} + unless ($config{DNSONLY} or $config{GENERIC}) {&apachecheck} + unless ($config{DNSONLY} or $config{GENERIC}) {&phpcheck} + unless ($config{DNSONLY} or $config{GENERIC}) {&whmcheck} + if ($config{DIRECTADMIN}) { + &mailcheck; + &apachecheck; + &phpcheck; + &dacheck; + } + &servicescheck; + + &endoutput; + return $output; +} +# end report +############################################################################### +# start startoutput +sub startoutput { + if ($config{THIS_UI} and !$config{GENERIC}) { + $output .= "

Note: Internal WHM links will not work within the csf Integrated UI

\n"; + } + + return; +} +# end startoutput +############################################################################### +# start addline +sub addline { + my $status = shift; + my $check = shift; + my $comment = shift; + $total++; + + if ($status) { + $output .= "
\n"; + $output .= "
$check
\n"; + $output .= "
$comment
\n"; + $output .= "
\n"; + $failures ++; + $current++; + } + elsif ($verbose) { + $output .= "
\n"; + $output .= "
$check
\n"; + $output .= "
$comment
\n"; + $output .= "
\n"; + $current++; + } + return; +} +# end addline +############################################################################### +# start addtitle +sub addtitle { + my $title = shift; + if (defined $current and $current == 0) { + $output .= "
OK
\n"; + } + $current = 0; + $output .= "
$title
\n"; + return; +} +# end addtitle +############################################################################### +# start endoutput +sub endoutput { + if (defined $current and $current == 0) { + $output .= "
OK
\n"; + } + $output .= "
\n"; + + my $gap = int(($total-3)/4); + my $score = ($total - $failures); + my $width = int ((400 / $total) * $score) - 4; + $output .= "
\n\n
\n"; + $output .= "

Server Score: $score/$total*

\n"; + $output .= "
\n"; + $output .= "\n"; + $output .= "\n"; + $output .= "\n"; + $output .= "\n"; + $output .= "\n"; + $output .= "\n"; + $output .= "\n"; + $output .= "
    $total (max) 
\n"; + $output .= "
\n"; + $output .= "
\n"; + $output .= "\n"; + $output .= "\n"; + $output .= "\n"; + $output .= "\n"; + $output .= "\n"; + $output .= "\n"; + $output .= "
   $score (score)
\n"; + $output .= "
\n"; + $output .= "
* This scoring does not necessarily reflect the security of the server or the relative merits of each check
"; + $output .= "
"; + return; +} +# end endoutput +############################################################################### +# start firewallcheck +sub firewallcheck { + &addtitle("Firewall Check"); + my $status = 0; + open (my $IN, "<", "/etc/csf/csf.conf"); + flock ($IN, LOCK_SH); + my @config = <$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; + } + + $status = 0; + if (-e "/etc/csf/csf.disable") {$status = 1} + &addline($status,"csf enabled check","csf is currently disabled and should be enabled otherwise it is not functioning"); + + if (-x $config{IPTABLES}) { + my ($childin, $childout); + my $mypid = open3($childin, $childout, $childout, "$config{IPTABLES} $config{IPTABLESWAIT} -L INPUT -n"); + my @iptstatus = <$childout>; + waitpid ($mypid, 0); + chomp @iptstatus; + if ($iptstatus[0] =~ /# Warning: iptables-legacy tables present/) {shift @iptstatus} + $status = 0; + if ($iptstatus[0] =~ /policy ACCEPT/) {$status = 1} + &addline($status,"csf running check","iptables is not configured. You need to start csf"); + } + + $status = 0; + if ($config{TESTING}) {$status = 1} + &addline($status,"TESTING mode check","csf is in TESTING mode. If the firewall is working set TESTING to \"0\" in the Firewall Configuration otherwise it will continue to be stopped"); + + $status = 0; + unless ($config{RESTRICT_SYSLOG}) {$status = 1} + &addline($status,"RESTRICT_SYSLOG option check","Due to issues with syslog/rsyslog you should consider enabling this option. See the Firewall Configuration (/etc/csf/csf.conf) for more information"); + + $status = 0; + unless ($config{AUTO_UPDATES}) {$status = 1} + &addline($status,"AUTO_UPDATES option check","To keep csf up to date and secure you should enable AUTO_UPDATES. You should also monitor our blog"); + + $status = 0; + unless ($config{LF_DAEMON}) {$status = 1} + &addline($status,"lfd enabled check","lfd is disabled in the csf configuration which limits the affectiveness of this application"); + + $status = 0; + if ($config{TCP_IN} =~ /\b3306\b/) {$status = 1} + &addline($status,"Incoming MySQL port check","The TCP incoming MySQL port (3306) is open. This can pose both a security and server abuse threat since not only can hackers attempt to break into MySQL, any user can host their SQL database on your server and access it from another host and so (ab)use your server resources"); + + unless ($config{DNSONLY} or $config{GENERIC}) { + unless ($config{VPS}) { + $status = 0; + unless ($config{SMTP_BLOCK}) {$status = 1} + &addline($status,"SMTP_BLOCK option check","This option will help prevent the most common form of spam abuse on a server that bypasses exim and sends spam directly out through port 25. Enabling this option will prevent any web script from sending out using socket connection, such scripts should use the exim or sendmail binary instead"); + } + + $status = 0; + unless ($config{LF_SCRIPT_ALERT}) {$status = 1} + &addline($status,"LF_SCRIPT_ALERT option check","This option will notify you when a large amount of email is sent from a particular script on the server, helping track down spam scripts"); + } + + $status = 0; + my @options = ("LF_SSHD","LF_FTPD","LF_SMTPAUTH","LF_POP3D","LF_IMAPD","LF_HTACCESS","LF_MODSEC","LF_CPANEL","LF_CPANEL_ALERT","SYSLOG_CHECK","RESTRICT_UI"); + if ($config{GENERIC}) {@options = ("LF_SSHD","LF_FTPD","LF_SMTPAUTH","LF_POP3D","LF_IMAPD","LF_HTACCESS","LF_MODSEC","SYSLOG_CHECK","FASTSTART","RESTRICT_UI");} + if ($config{DNSONLY}) {@options = ("LF_SSHD","LF_CPANEL","SYSLOG_CHECK","FASTSTART","RESTRICT_UI")} + + foreach my $option (@options) { + $status = 0; + unless ($config{$option}) {$status = 1} + &addline($status,"$option option check","This option helps prevent brute force attacks on your server services or overall server stability"); + } + + $status = 0; + unless ($config{LF_DIRWATCH}) {$status = 1} + &addline($status,"LF_DIRWATCH option check","This option will notify when a suspicious file is found in one of the common temp directories on the server"); + + $status = 0; + unless ($config{LF_INTEGRITY}) {$status = 1} + &addline($status,"LF_INTEGRITY option check","This option will notify when an executable in one of the common directories on the server changes in some way. This helps alert you to potential rootkit installation or server compromise"); + + $status = 0; + unless ($config{FASTSTART}) {$status = 1} + &addline($status,"FASTSTART option check","This option can dramatically improve the startup time of csf and the rule loading speed of lfd"); + + $status = 0; + if ($config{URLGET} == 1) {$status = 1} + &addline($status,"URLGET option check","This option determines which perl module is used to upgrade csf. It is recommended to set this to use LWP rather than HTTP::Tiny so that upgrades are performed over an SSL connection"); + + $status = 0; + if ($config{PT_USERKILL} == 1) {$status = 1} + &addline($status,"PT_USERKILL option check","This option should not normally be enabled as it can easily lead to legitimate processes being terminated, use csf.pignore instead"); + + unless ($config{DNSONLY} or $config{GENERIC}) { + $status = 0; + if ($config{PT_SKIP_HTTP}) {$status = 1} + &addline($status,"PT_SKIP_HTTP option check","This option disables checking of processes running under apache and can limit false-positives but may then miss running exploits"); + } + + $status = 0; + if (!$config{LF_IPSET} and !$config{VPS} and ($config{CC_DENY} or $config{CC_ALLOW} or $config{CC_ALLOW_FILTER} or $config{CC_ALLOW_PORTS} or $config{CC_DENY_PORTS})) {$status = 1} + &addline($status,"LF_IPSET option check","If support by your OS, you should install ipset and enable LF_IPSET when using Country Code (CC_*) filters"); + + unless ($config{DNSONLY} or $config{GENERIC}) { + $status = 0; + unless ($config{PT_ALL_USERS}) {$status = 1} + &addline($status,"PT_ALL_USERS option check","This option ensures that almost all Linux accounts are checked with Process Tracking, not just the cPanel ones"); + } + + sysopen (my $CONF, "/etc/csf/csf.conf", O_RDWR | O_CREAT); + flock ($CONF, LOCK_SH); + my @confdata = <$CONF>; + close ($CONF); + chomp @confdata; + + foreach my $line (@confdata) { + if (($line !~ /^\#/) and ($line =~ /=/)) { + my ($start,$end) = split (/=/,$line,2); + my $name = $start; + $name =~ s/\s/\_/g; + if ($end =~ /\"(.*)\"/) {$end = $1} + my ($insane,$range,$default) = sanity($start,$end); + if ($insane) { + &addline(1,"$start sanity check","$start = $end. Recommended range: $range (Default: $default)"); + } + } + } + return; +} +# end firewallcheck +############################################################################### +# start servercheck +sub servercheck { + &addtitle("Server Check"); + my $status = 0; + + my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,$blksize,$blocks) = stat("/tmp"); + my $pmode = sprintf "%03o", $mode & oct("07777"); + + $status = 0; + if ($pmode != 1777) {$status = 1} + &addline($status,"Check /tmp permissions","/tmp should be chmod 1777"); + + $status = 0; + if (($uid != 0) or ($gid != 0)) {$status = 1} + &addline($status,"Check /tmp ownership","/tmp should be owned by root:root"); + + if (-d "/var/tmp") { + ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,$blksize,$blocks) = stat("/var/tmp"); + $pmode = sprintf "%04o", $mode & oct("07777"); + + $status = 0; + if ($pmode != 1777) {$status = 1} + &addline($status,"Check /var/tmp permissions","/var/tmp should be chmod 1777"); + + $status = 0; + if (($uid != 0) or ($gid != 0)) {$status = 1} + &addline($status,"Check /var/tmp ownership","/var/tmp should be owned by root:root"); + } + + if (-d "/usr/tmp") { + ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,$blksize,$blocks) = stat("/usr/tmp"); + $pmode = sprintf "%04o", $mode & oct("07777"); + + $status = 0; + if ($pmode != 1777) {$status = 1} + &addline($status,"Check /usr/tmp permissions","/usr/tmp should be chmod 1777"); + + $status = 0; + if (($uid != 0) or ($gid != 0)) {$status = 1} + &addline($status,"Check /usr/tmp ownership","/usr/tmp should be owned by root:root"); + } + + $status = 0; + if (&getportinfo(53)) { + my @files = ("/var/named/chroot/etc/named.conf","/etc/named.conf","/etc/bind/named.conf","/var/named/chroot/etc/bind/named.conf"); + my @namedconf; + my @morefiles; + my $hit; + foreach my $file (@files) { + if (-e $file) { + $hit = 1; + open (my $IN, "<", "$file"); + flock ($IN, LOCK_SH); + my @conf = <$IN>; + close ($IN); + chomp @conf; + if (my @ls = grep {$_ =~ /^\s*include\s+(.*)\;\s*$/i} @conf) { + foreach my $more (@ls) { + if ($more =~ /^\s*include\s+\"(.*)\"\s*\;\s*$/i) {push @morefiles, $1} + } + } + @namedconf = (@namedconf, @conf); + } + } + foreach my $file (@morefiles) { + if (-e $file) { + open (my $IN, "<", "$file"); + flock ($IN, LOCK_SH); + my @conf = <$IN>; + close ($IN); + chomp @conf; + @namedconf = (@namedconf, @conf); + } + } + + if ($hit) { +# if (my @ls = grep {$_ =~ /^\s*(recursion\s+no|allow-recursion)/} @namedconf) {$status = 0} else {$status = 1} +# &addline($status,"Check for DNS recursion restrictions","You have a local DNS server running but do not appear to have any recursion restrictions set. This is a security and performance risk and you should look at restricting recursive lookups to the local IP addresses only"); + + if (my @ls = grep {$_ =~ /^\s*(query-source\s[^\;]*53)/} @namedconf) {$status = 1} else {$status = 0} + &addline($status,"Check for DNS random query source port","ISC recommend that you do not configure BIND to use a static query port. You should remove/disable the query-source line that specifies port 53 from the named configuration files"); + } + } + + if (!$DEBIAN and $sysinit eq "init" and -x "/sbin/runlevel") { + $status = 0; + $mypid = open3($childin, $childout, $childout, "/sbin/runlevel"); + my @conf = <$childout>; + waitpid ($mypid, 0); + chomp @conf; + my (undef,$runlevel) = split(/\s/,$conf[0]); + if ($runlevel != 3) {$status = 1} + &addline($status,"Check server runlevel","The servers runlevel is currently set to $runlevel. For a secure server environment you should only run the server at runlevel 3. You can fix this by editing /etc/inittab and changing the initdefault line to:
id:3:initdefault:
and then rebooting the server"); + } + + $status = 0; + if ((-e "/var/spool/cron/nobody") and !(-z "/var/spool/cron/nobody")) {$status = 1} + &addline($status,"Check nobody cron","You have a nobody cron log file - you should check that this has not been created by an exploit"); + + $status = 0; + my ($isfedora, $isrh, $version, $conf) = 0; + if (-e "/etc/fedora-release") { + open (my $IN, "<", "/etc/fedora-release"); + flock ($IN, LOCK_SH); + $conf = <$IN>; + close ($IN); + $isfedora = 1; + if ($conf =~ /release (\d+)/i) {$version = $1} + } elsif (-e "/etc/redhat-release") { + open (my $IN, "<", "/etc/redhat-release"); + flock ($IN, LOCK_SH); + $conf = <$IN>; + close ($IN); + $isrh = 1; + if ($conf =~ /release (\d+)/i) {$version = $1} + } + chomp $conf; + + if ($isrh or $isfedora) { + if (($isfedora and $version < 30) or ($isrh and $version < 6)) {$status = 1} + &addline($status,"Check Operating System support","You are running an OS - $conf - that is no longer supported by the OS vendor, or is about to become obsolete. This means that you will be receiving no OS updates (i.e. application or security bug fixes) or kernel updates and should consider moving to an OS that is supported as soon as possible"); + } + + $status = 0; + if ($] < 5.008008) { + $status = 1; + } else {$status = 0} + &addline($status,"Check perl version","The version of perl (v$]) is out of date and you should upgrade it"); + + $status = 0; + while (my ($name,undef,$uid) = getpwent()) { + if (($uid == 0) and ($name ne "root")) {$status = 1} + } + &addline($status,"Check SUPERUSER accounts","You have accounts other than root set up with UID 0. This is a considerable security risk. You should use su, or best of all sudo for such access"); + + if (-e "/usr/local/cpanel/version" or $config{DIRECTADMIN}) { + $status = 0; + unless (-e "/etc/cxs/cxs.pl") { + $status = 1; + } + &addline($status,"Check for cxs","You should consider using cxs to scan web script uploads and user accounts for exploits uploaded to the server"); + $status = 0; + unless (-e "/etc/osm/osmd.pl") { + $status = 1; + } + &addline($status,"Check for osm","You should consider using osm to provide protection from spammers exploiting the server"); + } + + unless ($config{IPV6}) { + $status = 0; + my $ipv6 = ""; + foreach my $key (keys %g_ipv6) { + if ($ipv6) {$ipv6 .= ", "} + $ipv6 .= $key; + $status = 1; + } + if ($ipv6 eq "::1") {$ipv6 = ""; $status = 0} + &addline($status,"Check for IPv6","IPv6 appears to be enabled [$ipv6]. If ip6tables is installed, you should enable the csf IPv6 firewall (IPV6 in csf.conf)"); + } + + if ($sysinit eq "init") { + $status = 1; + my $syslog = 0; + if (grep {$_ =~ /\/syslogd\s*/} @processes) { + $syslog = 1; + if (grep {$_ =~ /\/klogd$/} @processes) {$status = 0} + &addline($status,"Check for kernel logger","syslogd appears to be running, but not klogd which logs kernel firewall messages to syslog. You should ensure that klogd is running"); + } + if (grep {$_ =~ /\/rsyslogd\s*/} @processes) { + $syslog = 1; + if (grep {$_ =~ /\/rklogd\s*/} @processes) { + $status = 0; + } else { + open (my $IN, "<", "/etc/rsyslog.conf"); + flock ($IN, LOCK_SH); + my @conf = <$IN>; + close ($IN); + chomp @conf; + if (grep {$_ =~ /^\$ModLoad imklog/} @conf) {$status = 0} + } + &addline($status,"Check for kernel logger","rsyslogd appears to be running, but klog may not be loaded which logs kernel firewall messages to rsyslog. You should modify /etc/rsyslogd to load the klog module with:
\$ModLoad imklog
Then restart rsyslog"); + } + unless ($syslog) { + $status = 1; + &addline($status,"Check for syslog or rsyslog","Neither syslog nor rsyslog appear to be running"); + } + } + + $status = 0; + if (grep {$_ =~ /\/dhclient\s*/} @processes) {$status = 1} + &addline($status,"Check for dhclient","dhclient appears to be running which suggests that the server is obtaining an IP address via DHCP. This can pose a security risk. You should configure static IP addresses for all ethernet controllers"); + + unless ($config{VPS}) { + $status = 1; + open (my $IN, "<", "/proc/swaps"); + flock ($IN, LOCK_SH); + my @swaps = <$IN>; + close ($IN); + if (scalar(@swaps) > 1) {$status = 0} + &addline($status,"Check for swap file","The server appears to have no swap file. This is usually considered a stability and performance risk. You should either add a swap partition, or create one via a normal file on an existing partition"); + + if (-e "/etc/redhat-release") { + open (my $IN, "<", "/etc/redhat-release"); + flock ($IN, LOCK_SH); + $conf = <$IN>; + close ($IN); + chomp $conf; + + if ($conf =~ /^CloudLinux/i) { + $status = 0; + if (-e "/usr/sbin/cagefsctl") { + } else {$status = 1} + &addline($status,"CloudLinux CageFS","CloudLinux CageFS is not installed. This CloudLinux option greatly improves server security on we servers by separating user accounts into their own environment"); + + unless ($status) { + $status = 0; + $mypid = open3($childin, $childout, $childout, "/usr/sbin/cagefsctl","--cagefs-status"); + my @conf = <$childout>; + waitpid ($mypid, 0); + chomp @conf; + if ($conf[0] !~ /^Enabled/) {$status = 1} + &addline($status,"CloudLinux CageFS Enabled","CloudLinux CageFS is not enabled. This CloudLinux option greatly improves server security on we servers by separating user accounts into their own environment"); + } + + $status = 0; + open (my $ENFORCE_SYMLINKSIFOWNER, "<", "/proc/sys/fs/enforce_symlinksifowner"); + flock ($ENFORCE_SYMLINKSIFOWNER, LOCK_SH); + $conf = <$ENFORCE_SYMLINKSIFOWNER>; + close ($ENFORCE_SYMLINKSIFOWNER); + chomp $conf; + if ($conf < 1) {$status = 1} + &addline($status,"CloudLinux Symlink Protection","CloudLinux Symlink Protection is not configured. You should configure it in /etc/sysctl.conf to prevent symlink attacks on web servers"); + + $status = 0; + open (my $PROC_CAN_SEE_OTHER_UID, "<", "/proc/sys/fs/proc_can_see_other_uid"); + flock ($PROC_CAN_SEE_OTHER_UID, LOCK_SH); + $conf = <$PROC_CAN_SEE_OTHER_UID>; + close ($PROC_CAN_SEE_OTHER_UID); + chomp $conf; + if ($conf > 0) {$status = 1} + &addline($status,"CloudLinux Virtualised /proc","CloudLinux Virtualised /proc is not configured. You should configure it in /etc/sysctl.conf to prevent users accessing server resources that they do not need on web servers"); + + $status = 0; + open (my $USER_PTRACE, "<", "/proc/sys/kernel/user_ptrace"); + flock ($USER_PTRACE, LOCK_SH); + $conf = <$USER_PTRACE>; + close ($USER_PTRACE); + chomp $conf; + if ($conf > 0) {$status = 1} + &addline($status,"CloudLinux Disable ptrace","CloudLinux Disable ptrace is not configured. You should configure it in /etc/sysctl.conf to prevent users accessing server resources that they do not need on web servers"); + } + } + } + return; +} +# end servercheck +############################################################################### +# start whmcheck +sub whmcheck { + my $status = 0; + &addtitle("WHM Settings Check"); + + $status = 0; + unless ($cpconf->{alwaysredirecttossl}) {$status = 1} + &addline($status,"Check cPanel login is SSL only","You should check WHM > Tweak Settings > Choose the closest matched domain for which that the system has a valid certificate when redirecting from non-SSL to SSL URLs"); + + $status = 0; + unless ($cpconf->{skipboxtrapper}) {$status = 1} + &addline($status,"Check boxtrapper is disabled","Having boxtrapper enabled can very easily lead to your server being listed in common RBLs and usually has the effect of increasing the overall spam load, not reducing it. You should disable it in WHM > Tweak Settings > BoxTrapper Spam Trap"); + + $status = 0; + if (-e "/var/cpanel/greylist/enabled") {$status = 1} + &addline($status,"Check GreyListing is disabled","Using GreyListing can and will lead to lost legitimate emails. It can also cause significant problems with \"password verification\" systems. See here for more information"); + + if (defined $cpconf->{popbeforesmtp}) { + $status = 0; + if ($cpconf->{popbeforesmtp}) {$status = 1} + &addline($status,"Check popbeforesmtp is disabled","Using pop before smtp is considered a security risk, SMTP AUTH should be used instead. You should disable it in WHM > Tweak Settings > Allow users to relay mail if they use an IP address through which someone has validated an IMAP or POP3 login"); + } + + $status = 0; + unless ($cpconf->{maxemailsperhour}) {$status = 1} + &addline($status,"Check max emails per hour is set","To limit the damage that can be caused by potential spammers on the server you should set a value for WHM > Tweak Settings > Max hourly emails per domain"); + + $status = 0; + if ($cpconf->{resetpass}) {$status = 1} + &addline($status,"Check Reset Password for cPanel accounts","This poses a potential security risk and should be disabled unless necessary in WHM > Tweak Settings > Reset Password for cPanel accounts"); + + $status = 0; + if ($cpconf->{resetpass_sub}) {$status = 1} + &addline($status,"Check Reset Password for Subaccounts","This poses a potential security risk and should be disabled unless necessary in WHM > Tweak Settings > Reset Password for Subaccounts "); + + foreach my $openid (glob "/var/cpanel/authn/openid_connect/*") { + open (my $IN, "<", $openid); + flock ($IN, LOCK_SH); + my $line = <$IN>; + close ($IN); + chomp $line; + + my ($file, $filedir) = fileparse($openid); + $status = 0; + if ($line =~ /\{"cpanelid"/) {$status = 1} + &addline($status,"Check cPanelID for $file","You should only enable this option if you are going to use it otherwise it is a potential security risk in WHM > Manage External Authentications > $file"); + } + + unless ($cpconf->{nativessl} eq undef) { + $status = 0; + unless ($cpconf->{nativessl}) {$status = 1} + &addline($status,"Check whether native cPanel SSL is enabled","You should enable this option so that lfd tracks SSL cpanel login attempts WHM > Tweak Settings > Use native SSL support if possible, negating need for Stunnel"); + } + + $status = 0; + my $cc = '/usr/bin/cc'; + while ( readlink($cc) ) { + $cc = readlink($cc); + } + if ( $cc !~ /^\// ) { $cc = '/usr/bin/' . $cc; } + my $mode = substr( sprintf( "%o", ( ( stat($cc) )[2] ) ), 2, 4 ); + if ( $mode > 750 ) {$status = 1} + &addline($status,"Check compilers","You should disable compilers WHM > Security Center > Compilers Access"); + + if (-e "/etc/pure-ftpd.conf" and ($cpconf->{ftpserver} eq "pure-ftpd") and !(-e "/etc/ftpddisable")) { + $status = 0; + open (my $IN, "<", "/etc/pure-ftpd.conf"); + flock ($IN, LOCK_SH); + my @conf = <$IN>; + close ($IN); + chomp @conf; + if (my @ls = grep {$_ =~ /^\s*NoAnonymous\s*(no|off)/i} @conf) {$status = 1} + &addline($status,"Check Anonymous FTP Logins","Used as an attack vector by hackers and should be disabled unless actively used WHM > FTP Server Configuration > Allow Anonymous Logins > No"); + $status = 0; + if (my @ls = grep {$_ =~ /^\s*AnonymousCantUpload\s*(no|off)/i} @conf) {$status = 1} + &addline($status,"Check Anonymous FTP Uploads","Used as an attack vector by hackers and should be disabled unless actively used WHM > FTP Server Configuration > Allow Anonymous Uploads > No"); + + $status = 0; + my $ciphers; + my $error; + if (my @ls = grep {$_ =~ /^\s*TLSCipherSuite/} @conf) { + if ($ls[0] =~ /TLSCipherSuite\s+(.*)$/) {$ciphers = $1} + $ciphers =~ s/\s*|\"|\'//g; + if ($ciphers eq "") { + $status = 1; + } + elsif ($ciphers !~ /SSL/) { + $status = 0 + } else { + if (-x "/usr/bin/openssl") { + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, "/usr/bin/openssl","ciphers","-v",$ciphers); + my @openssl = <$childout>; + waitpid ($cmdpid, 0); + chomp @openssl; + if (my @ls = grep {$_ =~ /error/i} @openssl) {$error = $openssl[0]; $status=2} + if (my @ls = grep {$_ =~ /SSLv2/} @openssl) {$status = 1} + } + } + } else {$status = 1} + if ($status == 2) { + &addline($status,"Check pure-ftpd weak SSL/TLS Ciphers (TLSCipherSuite)","Unable to determine cipher list for [$ciphers] from openssl:
[$error]"); + } + &addline($status,"Check pure-ftpd weak SSL/TLS Ciphers (TLSCipherSuite)","Cipher list [$ciphers]. Due to weaknesses in the SSLv2 cipher you should disable SSLv2 in WHM > FTP Server Configuration > TLS Cipher Suite > Remove +SSLv2 or Add -SSLv2"); + + $status = 0; + unless (-e "/var/cpanel/conf/pureftpd/root_password_disabled") {$status = 1} + &addline($status,"Check FTP Logins with Root Password","Allowing root login via FTP is a considerable security risk and should be disabled WHM > FTP Server Configuration > Allow Logins with Root Password > No"); + } + + if (-e "/var/cpanel/conf/proftpd/main" and ($cpconf->{ftpserver} eq "proftpd") and !(-e "/etc/ftpddisable")) { + $status = 0; + open (my $IN, "<", "/var/cpanel/conf/proftpd/main"); + flock ($IN, LOCK_SH); + my @conf = <$IN>; + close ($IN); + chomp @conf; + if (my @ls = grep {$_ =~ /^cPanelAnonymousAccessAllowed: 'yes'/i} @conf) {$status = 1} + &addline($status,"Check Anonymous FTP Logins","Used as an attack vector by hackers and should be disabled unless actively used WHM > FTP Server Configuration > Allow Anonymous Logins > No"); + + $status = 0; + my $ciphers; + my $error; + if (my @ls = grep {$_ =~ /^\s*TLSCipherSuite/} @conf) { + if ($ls[0] =~ /TLSCipherSuite\:\s+(.*)$/) {$ciphers = $1} + $ciphers =~ s/\s*|\"|\'//g; + if ($ciphers eq "") { + $status = 1; + } else { + if (-e "/usr/bin/openssl") { + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, "/usr/bin/openssl","ciphers","-v",$ciphers); + my @openssl = <$childout>; + waitpid ($cmdpid, 0); + chomp @openssl; + if (my @ls = grep {$_ =~ /error/i} @openssl) {$error = $openssl[0]; $status=2} + if (my @ls = grep {$_ =~ /SSLv2/} @openssl) {$status = 1} + } + } + } else {$status = 1} + if ($status == 2) { + &addline($status,"Check proftpd weak SSL/TLS Ciphers (TLSCipherSuite)","Unable to determine cipher list for [$ciphers] from openssl:
[$error]"); + } + &addline($status,"Check proftpd weak SSL/TLS Ciphers (TLSCipherSuite)","Cipher list [$ciphers]. Due to weaknesses in the SSLv2 cipher you should disable SSLv2 in WHM > FTP Server Configuration > TLS Cipher Suite > Remove +SSLv2 or Add -SSLv2"); + + if ($config{VPS}) { + $status = 0; + open (my $IN, "<", "/etc/proftpd.conf"); + flock ($IN, LOCK_SH); + my @conf = <$IN>; + close ($IN); + chomp @conf; + if (my @ls = grep {$_ =~ /^\s*PassivePorts\s+(\d+)\s+(\d+)/} @conf) { + if ($config{TCP_IN} !~ /\b$1:$2\b/) {$status = 1} + } else {$status = 1} + &addline($status,"Check VPS FTP PASV hole","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"); + } + } + + $status = 0; + if ($cpconf->{allowremotedomains}) {$status = 1} + &addline($status,"Check allow remote domains","User can park domains that resolve to other servers on this server. You should disable WHM > Tweak Settings > Allow Remote Domains"); + + $status = 0; + unless ($cpconf->{blockcommondomains}) {$status = 1} + &addline($status,"Check block common domains","User can park common domain names on this server. You should disable WHM > Tweak Settings > Prevent cPanel users from creating specific domains"); + + $status = 0; + if ($cpconf->{allowparkonothers}) {$status = 1} + &addline($status,"Check allow park domains","User can park/addon domains that belong to other users on this server. You should disable WHM > Tweak Settings > Allow cPanel users to create subdomains across accounts"); + + $status = 0; + if ($cpconf->{proxysubdomains}) {$status = 1} + &addline($status,"Check proxy subdomains","This option can mask a users real IP address and hinder security. You should disable WHM > Tweak Settings > Service subdomains"); + + $status = 1; + if ($cpconf->{cpaddons_notify_owner}) {$status = 0} + &addline($status,"Check cPAddons update email to resellers","You should have cPAddons email users if cPAddon installations require updating WHM > Tweak Settings > Notify reseller of cPAddons Site Software installations"); + + $status = 1; + if ($cpconf->{cpaddons_notify_root}) {$status = 0} + &addline($status,"Check cPAddons update email to root","You should have cPAddons email root if cPAddon installations require updating WHM > Tweak Settings > Notify root of cPAddons Site Software installations"); + + if (-e "/etc/cpupdate.conf") { + open (my $IN, "<", "/etc/cpupdate.conf"); + flock ($IN, LOCK_SH); + my @conf = <$IN>; + close ($IN); + chomp @conf; + + $status = 0; + if (my @ls = grep {$_ =~ /^CPANEL=(edge|beta|nightly)/i} @conf) {$status = 1} + &addline($status,"Check cPanel tree","Running EDGE/BETA on a production server could lead to server instability"); + + $status = 1; + if (my @ls = grep {$_ =~ /^UPDATES=daily/i} @conf) {$status = 0} + &addline($status,"Check cPanel updates","You have cPanel updating disabled, this can pose a security and stability risk. WHM > Update Preferences > Enabled Automatic Updates"); + +# $status = 0; +# if (grep {$_ =~ /^SYSUP=/i} @conf) {$status = 1} +# if (grep {$_ =~ /^SYSUP=daily/i} @conf) {$status = 0} +# &addline($status,"Check package updates","You have package updating disabled, this can pose a security and stability risk. WHM > Update Config >cPanel Package Updates > Automatic"); + +# $status = 1; +# if (my @ls = grep {$_ =~ /^RPMUP=daily/i} @conf) {$status = 0} +# &addline($status,"Check security updates","You have security updating disabled, this can pose a security and stability risk. WHM > Update Config >Operating System Package Updates > Automatic"); + } else {&addline(1,"Check cPanel updates","Unable to find /etc/cpupdate.conf");} + + $status = 1; + if ($cpconf->{account_login_access} eq "user") {$status = 0} + &addline($status,"Check accounts that can access a cPanel user","You should consider setting this option to \"user\" after use. WHM > Tweak Settings > Accounts that can access a cPanel user account"); + + unless ($status) { + $status = 0; + open (my $IN, "<", "/usr/local/cpanel/3rdparty/etc/php.ini"); + flock ($IN, LOCK_SH); + my @conf = <$IN>; + close ($IN); + chomp @conf; + if (my @ls = grep {$_ =~ /^\s*register_globals\s*=\s*on/i} @conf) {$status = 1} + &addline($status,"Check cPanel php.ini file for register_globals","PHP register_globals is considered a high security risk. It is currently enabled in /usr/local/cpanel/3rdparty/etc/php.ini and should be disabled (disabling may break 3rd party PHP cPanel apps)"); + } + + $status = 0; + if ($cpconf->{emailpasswords}) {$status = 1} + &addline($status,"Check cPanel passwords in email","You should not send passwords out in plain text emails. You should disable WHM > Tweak Settings > Send passwords when creating a new account"); + + $status = 0; + if ($cpconf->{coredump}) {$status = 1} + &addline($status,"Check core dumps","You should disable WHM > Tweak Settings > Allow WHM/Webmail/cPanel services to create core dumps for debugging purposes"); + + $status = 1; + if ($cpconf->{cookieipvalidation} eq "strict") {$status = 0} + &addline($status,"Check Cookie IP Validation","You should enable strict Cookie IP validation in WHM > Tweak Settings > Cookie IP validation"); + + $status = 1; + if ($cpconf->{use_apache_md5_for_htaccess}) {$status = 0} + &addline($status,"Check MD5 passwords with Apache","You should enable WHM > Tweak Settings > Use MD5 passwords with Apache"); + + $status = 1; + if ($cpconf->{referrerblanksafety}) {$status = 0} + &addline($status,"Check Referrer Blank Security","You should enable WHM > Tweak Settings > Blank referrer safety check"); + + $status = 1; + if ($cpconf->{referrersafety}) {$status = 0} + &addline($status,"Check Referrer Security","You should enable WHM > Tweak Settings > Referrer safety check"); + + $status = 1; + if ($cpconf->{skiphttpauth}) {$status = 0} + &addline($status,"Check HTTP Authentication","You should disable skiphttpauth in /var/cpanel/cpanel.config"); + + $status = 0; + if ($cpconf->{skipparentcheck}) {$status = 1} + &addline($status,"Check Parent Security","You should disable WHM > Tweak Settings > Allow other applications to run the cPanel and admin binaries"); + + $status = 0; + if ($cpconf->{"cpsrvd-domainlookup"}) {$status = 1} + &addline($status,"Check Domain Lookup Security","You should disable WHM > Tweak Settings > cpsrvd username domain lookup"); + + $status = 1; + if ($cpconf->{"cgihidepass"}) {$status = 0} + &addline($status,"Check Password ENV variable","You should enable WHM > Tweak Settings > Hide login password from cgi scripts "); + + $status = 0; + if (-e "/var/cpanel/smtpgidonlytweak") {$status = 1} + &addline($status,"Check SMTP Restrictions","This option in WHM will not function when running csf. You should disable WHM > Security Center > SMTP Restrictions and use the csf configuration option SMTP_BLOCK instead"); + + if (-e "/etc/wwwacct.conf") { + $status = 1; + open (my $IN, "<", "/etc/wwwacct.conf"); + flock ($IN, LOCK_SH); + my @conf = <$IN>; + close ($IN); + chomp @conf; + + my %ips; + foreach my $key (keys %g_ipv4) { + $ips{$key} = 1; + } + + my $nameservers; + my $local = 0; + my $allns = 0; + foreach my $line (@conf) { + if ($line =~ /^NS(\d)?\s+(.*)\s*$/) { + my $ns = $2; + $ns =~ s/\s//g; + if ($ns) { + $allns++; + $nameservers .= "$ns
\n"; + my $ip; + if (checkip(\$ns)) { + $ip = $ns; + if ($ips{$ip}) {$local++} + } else { + my @ips = getips($ns); + unless (scalar @ips) {&addline(1,"Check nameservers","Unable to resolve nameserver [$ns]")} + my $hit = 0; + foreach my $oip (@ips) { + if ($ips{$oip}) {$hit = 1} + } + if ($hit) {$local++} + } + } + } + } + if ($local < $allns) {$status = 0} + &addline($status,"Check nameservers","At least one of the configured nameservers:
\n$nameservers should be located in a topologically and geographically dispersed location on the Internet - See RFC 2182 (Section 3.1)"); + } + + if (-e "/usr/local/cpanel/bin/register_appconfig") { + $status = 0; + if ($cpconf->{permit_unregistered_apps_as_reseller}) {$status = 1} + &addline($status,"Check AppConfig Required","You should disable WHM > Tweak Settings > Allow apps that have not registered with AppConfig to be run when logged in as a reseller in WHM"); + + $status = 0; + if ($cpconf->{permit_unregistered_apps_as_root}) {$status = 1} + &addline($status,"Check AppConfig as root","You should disable WHM > Tweak Settings > Allow apps that have not registered with AppConfig to be run when logged in as root or a reseller with the \"all\" ACL in WHM"); + + $status = 0; + if ($cpconf->{permit_appconfig_entries_without_acls}) {$status = 1} + &addline($status,"Check AppConfig ACLs","You should disable WHM > Tweak Settings > Allow WHM apps registered with AppConfig to be executed even if a Required ACLs list has not been defined"); + + $status = 0; + if ($cpconf->{permit_appconfig_entries_without_features}) {$status = 1} + &addline($status,"Check AppConfig Feature List","You should disable WHM > Tweak Settings > Allow cPanel and Webmail apps registered with AppConfig to be executed even if a Required Features list has not been defined"); + } + + $status = 0; + if ($cpconf->{"disable-security-tokens"}) {$status = 1} + &addline($status,"Check Security Tokens","Security Tokens should not be disabled as without them security of WHM/cPanel is compromised. The setting disable-security-tokens=0 should be set in /var/cpanel/cpanel.config"); + return; +} +# end whmcheck +############################################################################### +# start dacheck +sub dacheck { + my $status = 0; + &addtitle("DirectAdmin Settings Check"); + + $status = 0; + unless ($daconfig{ssl}) {$status = 1} + &addline($status,"Check DirectAdmin login is SSL only","You should enable SSL only login to DirectAdmin"); + + if (($daconfig{ftpconfig} =~ /proftpd.conf/) and ($daconfig{pureftp} != 1)) { + $status = 0; + open (my $IN, "<", $daconfig{ftpconfig}); + flock ($IN, LOCK_SH); + my @conf = <$IN>; + close ($IN); + chomp @conf; + + my $ciphers; + my $error; + if (my @ls = grep {$_ =~ /^\s*TLSCipherSuite/} @conf) { + if ($ls[0] =~ /TLSCipherSuite\s+(.*)$/) {$ciphers = $1} + $ciphers =~ s/\s*|\"|\'//g; + if ($ciphers eq "") { + $status = 1; + } else { + if (-e "/usr/bin/openssl") { + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, "/usr/bin/openssl","ciphers","-v",$ciphers); + my @openssl = <$childout>; + waitpid ($cmdpid, 0); + chomp @openssl; + if (my @ls = grep {$_ =~ /error/i} @openssl) {$error = $openssl[0]; $status=2} + if (my @ls = grep {$_ =~ /SSLv2/} @openssl) {$status = 1} + } + } + } else {$status = 1} + if ($status == 2) { + &addline($status,"Check proftpd weak SSL/TLS Ciphers (TLSCipherSuite)","Unable to determine cipher list for [$ciphers] from openssl:
[$error]"); + } + &addline($status,"Check proftpd weak SSL/TLS Ciphers (TLSCipherSuite)","Cipher list [$ciphers]. Due to weaknesses in the SSLv2 cipher you should add a TLSCipherSuite with SSLv2 disabled in $daconfig{ftpconfig}. For example,
<IfModule mod_tls.c>
TLSCipherSuite HIGH
</IfModule> container
"); + + if ($config{VPS}) { + $status = 0; + if (my @ls = grep {$_ =~ /^\s*PassivePorts\s+(\d+)\s+(\d+)/} @conf) { + if ($config{TCP_IN} !~ /\b$1:$2\b/) {$status = 1} + } else {$status = 1} + &addline($status,"Check VPS FTP PASV hole","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"); + } + } + + $status = 1; + + my %ips; + foreach my $key (keys %g_ipv4) { + $ips{$key} = 1; + } + + my $nameservers; + for (my $x = 1; $x < 3; $x++) { + my $ns = $daconfig{"ns$x"}; + $ns =~ s/\s//g; + if ($ns) { + $nameservers .= "$ns
\n"; + my $ip; + if ($ns =~ /\d+\.\d+\.\d+\.d+/) { + $ip = $ns; + } else { + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die}; + alarm(5); + $ip = gethostbyname($ns); + $ip = inet_ntoa($ip); + alarm(0); + }; + alarm(0); + unless ($ip) {&addline(1,"Check nameservers","Unable to resolve nameserver [$ns] within 5 seconds")} + } + if ($ip) { + unless ($ips{$ip}) {$status = 0} + } + } + } + &addline($status,"Check nameservers","At least one of the configured nameservers:
\n$nameservers should be located in a topologically and geographically dispersed location on the Internet - See RFC 2182 (Section 3.1)"); + return; +} +# end dacheck +############################################################################### +# start mailcheck +sub mailcheck { + &addtitle("Mail Check"); + + my $status = 0; + unless ($config{DIRECTADMIN}) { + if (-e "/root/.forward") { + if (-z "/root/.forward") {$status = 1} + } else {$status = 1} + &addline($status,"Check root forwarder","The root account should have a forwarder set so that you receive essential email from your server"); + } + + if (-e "/etc/exim.conf" and -x "/usr/sbin/exim") { + $status = 0; + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, "/usr/sbin/exim","-bP"); + my @eximconf = <$childout>; + waitpid ($cmdpid, 0); + chomp @eximconf; + if (my @ls = grep {$_ =~ /^\s*log_selector/} @eximconf) { + if (($ls[0] !~ /\+all/) and ($ls[0] !~ /\+arguments/) and ($ls[0] !~ /\+arguments/)) {$status = 1} + } else {$status = 1} + if ($config{DIRECTADMIN}) { + &addline($status,"Check exim for extended logging (log_selector)","You should enable extended exim logging to enable easier tracking potential outgoing spam issues. Add:
log_selector = +arguments +subject +received_recipients
to /etc/exim.conf"); + } else { + &addline($status,"Check exim for extended logging (log_selector)","You should enable extended exim logging to enable easier tracking potential outgoing spam issues. Add:
log_selector = +arguments +subject +received_recipients
in WHM > Exim Configuration Manager > Advanced Editor > log_selector"); + } + + $status = 0; + my $ciphers; + my $error; + if (my @ls = grep {$_ =~ /^\s*tls_require_ciphers/} @eximconf) { + (undef,$ciphers) = split(/\=/,$ls[0]); + $ciphers =~ s/\s*|\"|\'//g; + if ($ciphers eq "") { + $status = 1; + } else { + if (-x "/usr/bin/openssl") { + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, "/usr/bin/openssl","ciphers","-v",$ciphers); + my @openssl = <$childout>; + waitpid ($cmdpid, 0); + chomp @openssl; + if (my @ls = grep {$_ =~ /error/i} @openssl) {$error = $openssl[0]; $status=2} + if (my @ls = grep {$_ =~ /SSLv2/} @openssl) {$status = 1} + } + } + } else {$status = 1} + if ($status == 2) { + &addline($status,"Check exim weak SSL/TLS Ciphers (tls_require_ciphers)","Unable to determine cipher list for [$ciphers] from openssl:
[$error]"); + } + if ($config{DIRECTADMIN}) { + &addline($status,"Check exim weak SSL/TLS Ciphers (tls_require_ciphers)","Cipher list [$ciphers]. Due to weaknesses in the SSLv2 cipher you should edit /etc/exim.conf and set tls_require_ciphers to explicitly exclude it. For example:
tls_require_ciphers=ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:-LOW:-SSLv2:-EXP"); + } else { + &addline($status,"Check exim weak SSL/TLS Ciphers (tls_require_ciphers)","Cipher list [$ciphers]. Due to weaknesses in the SSLv2 cipher you should disable WHM > Exim Configuration Manager > Allow weak ssl/tls ciphers to be used, and also ensure tls_require_ciphers in /etc/exim.conf does not allow SSLv2 as openssl currently shows that it does"); + } + } else {&addline(1,"Check exim configuration","Unable to find /etc/exim.conf and/or /usr/sbin/exim");} + + if (-e "/etc/exim.conf.localopts") { + $status = 0; + open (my $IN, "<", "/etc/exim.conf.localopts"); + flock ($IN, LOCK_SH); + my @conf = <$IN>; + close ($IN); + chomp @conf; + + if (my @ls = grep {$_ =~ /require_secure_auth=0/i} @conf) {$status = 1} + &addline($status,"Check exim for secure authentication","You should require clients to connect with SSL or issue the STARTTLS command before they are allowed to authenticate with the server, otherwise passwords may be sent in plain text
in WHM > Exim Configuration Manager"); + } + + if ($config{DIRECTADMIN}) { + if (-e "/etc/dovecot.conf" and ($daconfig{dovecot})) { + $status = 0; + open (my $IN, "<", "/etc/dovecot.conf"); + flock ($IN, LOCK_SH); + my @conf = <$IN>; + close ($IN); + chomp @conf; + + my @morefiles; + if (my @ls = grep {$_ =~ /^\s*\!\s*include(_try)?\s+(.*)\s*$/i} @conf) { + foreach my $more (@ls) { + if ($more =~ /^\s*\!\s*include(_try)?\s+(.*)\s*$/i) { + my $conf = $2; + if ($conf !~ /^\//) {$conf = "/etc/dovecot/".$conf} + push @morefiles, $conf; + } + } + } + foreach my $file (@morefiles) { + if (-e $file) { + open (my $IN, "<", "$file"); + flock ($IN, LOCK_SH); + my @moreconf = <$IN>; + close ($IN); + chomp @conf; + @conf = (@conf, @moreconf); + } + } + + my $ciphers; + my $error; + if (my @ls = grep {$_ =~ /^ssl_cipher_list/} @conf) { + (undef,$ciphers) = split(/\=/,$ls[0]); + $ciphers =~ s/\s*|\"|\'//g; + if ($ciphers eq "") { + $status = 1; + } else { + if (-x "/usr/bin/openssl") { + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, "/usr/bin/openssl","ciphers","-v",$ciphers); + my @openssl = <$childout>; + waitpid ($cmdpid, 0); + chomp @openssl; + if (my @ls = grep {$_ =~ /error/i} @openssl) {$error = $openssl[0]; $status=2} + if (my @ls = grep {$_ =~ /SSLv2/} @openssl) {$status = 1} + } + } + } else {$status = 1} + if ($status == 2) { + &addline($status,"Check dovecot weak SSL/TLS Ciphers (ssl_cipher_list)","Unable to determine cipher list for [$ciphers] from openssl:
[$error]"); + } + &addline($status,"Check dovecot weak SSL/TLS Ciphers (ssl_cipher_list)","Cipher list [$ciphers]. Due to weaknesses in the SSLv2 cipher you should /etc/dovecot.conf and set ssl_cipher_list to explicitly exclude it. For example:
ssl_cipher_list = ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:-LOW:-SSLv2:-EXP"); + } + } else { + if (-e "/etc/dovecot/dovecot.conf" and ($cpconf->{mailserver} eq "dovecot")) { + $status = 0; + open (my $IN, "<", "/etc/dovecot/dovecot.conf"); + flock ($IN, LOCK_SH); + my @conf = <$IN>; + close ($IN); + chomp @conf; + + my @morefiles; + if (my @ls = grep {$_ =~ /^\s*\!?include(_try)?\s+(.*)\s*$/i} @conf) { + foreach my $more (@ls) { + if ($more =~ /^\s*\!?include(_try)?\s+(.*)\s*$/i) {push @morefiles, $2} + } + } + foreach my $file (@morefiles) { + if (-e $file) { + open (my $IN, "<", "$file"); + flock ($IN, LOCK_SH); + my @moreconf = <$IN>; + close ($IN); + chomp @conf; + @conf = (@conf, @moreconf); + } + } + + $status = 0; + my $ciphers; + my $error; + if (my @ls = grep {$_ =~ /^ssl_cipher_list/} @conf) { + (undef,$ciphers) = split(/\=/,$ls[0]); + $ciphers =~ s/\s*|\"|\'//g; + if ($ciphers eq "") { + $status = 1; + } else { + if (-x "/usr/bin/openssl") { + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, "/usr/bin/openssl","ciphers","-v",$ciphers); + my @openssl = <$childout>; + waitpid ($cmdpid, 0); + chomp @openssl; + if (my @ls = grep {$_ =~ /error/i} @openssl) {$error = $openssl[0]; $status=2} + if (my @ls = grep {$_ =~ /SSLv2/} @openssl) {$status = 1} + } + } + } else {$status = 1} + if ($status == 2) { + &addline($status,"Check dovecot weak SSL/TLS Ciphers (ssl_cipher_list)","Unable to determine cipher list for [$ciphers] from openssl:
[$error]"); + } + &addline($status,"Check dovecot weak SSL/TLS Ciphers (ssl_cipher_list)","Cipher list [$ciphers]. Due to weaknesses in the SSLv2 cipher you should disable SSLv2 in WHM > Mailserver Configuration > SSL Cipher List > Remove +SSLv2 or Add -SSLv2"); + } + + if (-e "/usr/lib/courier-imap/etc/imapd-ssl" and ($cpconf->{mailserver} eq "courier")) { + $status = 0; + open (my $IN, "<", "/usr/lib/courier-imap/etc/imapd-ssl"); + flock ($IN, LOCK_SH); + my @conf = <$IN>; + close ($IN); + chomp @conf; + $status = 0; + my $ciphers; + my $error; + if (my @ls = grep {$_ =~ /^TLS_CIPHER_LIST/} @conf) { + (undef,$ciphers) = split(/\=/,$ls[0]); + $ciphers =~ s/\s*|\"|\'//g; + if ($ciphers eq "") { + $status = 1; + } else { + if (-x "/usr/bin/openssl") { + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, "/usr/bin/openssl","ciphers","-v",$ciphers); + my @openssl = <$childout>; + waitpid ($cmdpid, 0); + chomp @openssl; + if (my @ls = grep {$_ =~ /error/i} @openssl) {$error = $openssl[0]; $status=2} + if (my @ls = grep {$_ =~ /SSLv2/} @openssl) {$status = 1} + } + } + } else {$status = 1} + if ($status == 2) { + &addline($status,"Check Courier IMAP weak SSL/TLS Ciphers (TLS_CIPHER_LIST)","Unable to determine cipher list for [$ciphers] from openssl:
[$error]"); + } + &addline($status,"Check Courier IMAP weak SSL/TLS Ciphers (TLS_CIPHER_LIST)","Cipher list [$ciphers]. Due to weaknesses in the SSLv2 cipher you should disable SSLv2 in WHM > Mailserver Configuration > IMAP TLS/SSL Cipher List > Remove +SSLv2 or Add -SSLv2"); + } + + if (-e "/usr/lib/courier-imap/etc/pop3d-ssl" and ($cpconf->{mailserver} eq "courier")) { + $status = 0; + open (my $IN, "<", "/usr/lib/courier-imap/etc/pop3d-ssl"); + flock ($IN, LOCK_SH); + my @conf = <$IN>; + close ($IN); + chomp @conf; + $status = 0; + my $ciphers; + my $error; + if (my @ls = grep {$_ =~ /^TLS_CIPHER_LIST/} @conf) { + (undef,$ciphers) = split(/\=/,$ls[0]); + $ciphers =~ s/\s*|\"|\'//g; + if ($ciphers eq "") { + $status = 1; + } else { + if (-x "/usr/bin/openssl") { + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, "/usr/bin/openssl","ciphers","-v",$ciphers); + my @openssl = <$childout>; + waitpid ($cmdpid, 0); + chomp @openssl; + if (my @ls = grep {$_ =~ /error/i} @openssl) {$error = $openssl[0]; $status=2} + if (my @ls = grep {$_ =~ /SSLv2/} @openssl) {$status = 1} + } + } + } else {$status = 1} + if ($status == 2) { + &addline($status,"Check Courier POP3D weak SSL/TLS Ciphers (TLS_CIPHER_LIST)","Unable to determine cipher list for [$ciphers] from openssl:
[$error]"); + } + &addline($status,"Check Courier POP3D weak SSL/TLS Ciphers (TLS_CIPHER_LIST)","Cipher list [$ciphers]. Due to weaknesses in the SSLv2 cipher you should disable SSLv2 in WHM > Mailserver Configuration > POP3 TLS/SSL Cipher List > Remove +SSLv2 or Add -SSLv2"); + } + } + return; +} +# end mailcheck +############################################################################### +# start phpcheck +sub phpcheck { + &addtitle("PHP Check"); + my %phpbinaries; + my %phpinis; + + if (-e "/usr/local/cpanel/version" and -e "/etc/cpanel/ea4/is_ea4") { + foreach my $phpdir (glob("/opt/cpanel/ea-*")) { + if (-e "${phpdir}/root/usr/bin/php") {$phpbinaries{"${phpdir}/root/usr/bin/php"} = 1} + } + } + elsif ($config{DIRECTADMIN}) { + foreach my $phpdir (glob("/usr/local/php*")) { + if (-e "${phpdir}/bin/php") {$phpbinaries{"${phpdir}/bin/php"} = 1} + } + } + elsif (-e "/usr/local/bin/php") {$phpbinaries{"/usr/local/bin/php"} = 1} + elsif (-e "/usr/bin/php") {$phpbinaries{"/usr/bin/php"} = 1} + + if (-e "/opt/alt/alt-php-config") { + foreach my $phpdir (glob("/opt/alt/php*")) { + if (-e "${phpdir}/usr/bin/php") {$phpbinaries{"${phpdir}/usr/bin/php"} = 1} + } + } + + if (scalar(keys %phpbinaries) == 0) { + &addline(1,"PHP Binary","PHP binary not found or not executable"); + return; + } + + foreach my $phpbin (keys %phpbinaries) { + if ($phpbin =~ /php44/) {$phpinis{"/opt/alt/php44/etc/php.ini"} = $phpbin} + elsif ($phpbin =~ /php51/) {$phpinis{"/opt/alt/php51/etc/php.ini"} = $phpbin} + else { + my ($childin, $childout); + my $mypid = open3($childin, $childout, $childout, $phpbin,"-d","zlib.output_compression=Off","--ini"); + my @conf = <$childout>; + waitpid ($mypid, 0); + chomp @conf; + foreach my $line (@conf) { + if ($line =~ /^Loaded Configuration File:\s*(\S+)$/) {$phpinis{$1} = $phpbin} + } + } + } + my %phpconf; + foreach my $phpini (sort keys %phpinis) { + my $phpbin = $phpinis{$phpini}; + + my $status = 0; + my ($childin, $childout); + my $mypid; + if ($phpbin =~ /php44|php51/) { + $mypid = open3($childin, $childout, $childout, $phpbin,"-i"); + } else { + $mypid = open3($childin, $childout, $childout, $phpbin,"-d","zlib.output_compression=Off","-i"); + } + my @conf = <$childout>; + waitpid ($mypid, 0); + chomp @conf; + + if (my @ls = grep {$_ =~ /^PHP License/} @conf) { + my $version = 0; + my ($mas,$maj,$min); + if (my @ls = grep {$_ =~ /^PHP Version\s*=>\s*/i} @conf) { + my $line = $ls[0]; + $line =~ /^PHP Version\s*=>\s*(.*)/i; + ($mas,$maj,$min) = split(/\./,$1); + $version = "$mas.$maj.$min"; + if ($mas < 8) {$status = 1} + if ($mas == 8 and $maj < 1) {$status = 1} + } + open (my $IN, "<", "/usr/local/apache/conf/php.conf.yaml"); + flock ($IN, LOCK_SH); + my @phpyamlconf = <$IN>; + close ($IN); + chomp @phpyamlconf; + + if (my @ls = grep {$_ =~ /php4:/i} @phpyamlconf) { + if ($ls[0] !~ /none/) { + $status = 1; + $version = "4.*"; + } + } + unless ($phpbin =~ m[^/opt/alt/php]) { + if ($status) {$phpconf{version} .= "$version ($phpbin),"} + } + + $status = 1; + if (my @ls = grep {$_ =~ /^enable_dl\s*=>\s*Off/i} @conf) { + $status = 0; + } + if (my @ls = grep {$_ =~ /^disable_functions\s*=>.*dl.*/i} @conf) { + $status = 0; + } + + if ($status) {$phpconf{enable_dl} .= "$phpini ($phpbin),"} + + $status = 1; + if (my @ls = grep {$_ =~ /^disable_functions\s*=>.*\,/i} @conf) { + $status = 0; + } + if ($status) {$phpconf{disable_functions} .= "$phpini ($phpbin),"} + + $status = 1; + if (my @ls = grep {$_ =~ /^disable_functions\s*=>.*ini_set.*/i} @conf) { + $status = 0; + } + if ($status) {$phpconf{ini_set} .= "$phpini ($phpbin),"} + + my $oldver = "$mas.$maj"; + if ($oldver < 5.4) { + $status = 1; + if (my @ls = grep {$_ =~ /^register_globals\s*=>\s*Off/i} @conf) { + $status = 0; + } + if ($status) {$phpconf{register_globals} .= "$phpini ($phpbin),"} + + } + } else { + $status = 1; + &addline($status,"Check php
[$phpbin]","Unable to examine PHP settings due to an error in the output from: [$phpbin -i]"); + } + } + foreach my $key ("version","enable_dl","disable_functions","ini_set","register_globals") { + my $values; + foreach my $value (split(/\,/,$phpconf{$key})) { + if ($value eq "") {next} + $values .= "
$value\n"; + } + if ($key eq "version") { + my $status = 0; + if ($values ne "") {$status = 1} + &addline($status,"Check php version","Any version of PHP older than v8.1.* is now obsolete and should be considered a security threat. You should upgrade to at least PHP v8.1+:
Affected PHP versions:$values"); + } + if ($key eq "enable_dl") { + my $status = 0; + if ($values ne "") {$status = 1} + &addline($status,"Check php for enable_dl or disabled dl()","You should set:
enable_dl = Off
This prevents users from loading php modules that affect everyone on the server. Note that if use dynamic libraries, such as ioncube, you will have to load them directly in the PHP configuration:
Affected PHP versions:$values"); + } + if ($key eq "disable_functions") { + my $status = 0; + if ($values ne "") {$status = 1} + &addline($status,"Check php for disable_functions","You should consider disabling commonly abused php functions, e.g.:
disable_functions = show_source, system, shell_exec, passthru, exec, popen, proc_open
Some client web scripts may break with some of these functions disabled, so you may have to remove them from this list:
Affected PHP versions:$values"); + } + if ($key eq "register_globals") { + my $status = 0; + if ($values ne "") {$status = 1} + &addline($status,"Check php for register_globals","You should set:
register_globals = Off
unless it is absolutely necessary as it is seen as a significant security risk:
Affected PHP versions:$values"); + } + } + return; +} +# end phpcheck +############################################################################### +# start apachecheck +sub apachecheck { + &addtitle("Apache Check"); + + my $status = 0; + my $mypid; + my ($childin, $childout); + my %ea4; + + if (-e "/usr/local/cpanel/version" and -e "/etc/cpanel/ea4/is_ea4" and -e "/etc/cpanel/ea4/paths.conf") { + my @file = slurp("/etc/cpanel/ea4/paths.conf"); + $ea4{enabled} = 1; + foreach my $line (@file) { + $line =~ s/$cleanreg//g; + if ($line =~ /^(\s|\#|$)/) {next} + if ($line !~ /=/) {next} + my ($name,$value) = split (/=/,$line,2); + $value =~ s/^\s+//g; + $value =~ s/\s+$//g; + $ea4{$name} = $value; + } + } + + if ($ea4{enabled}) { + unless (-x $ea4{bin_httpd}) {&addline(1,"HTTP Binary","$ea4{bin_httpd} not found or not executable"); return} + } + elsif ($config{DIRECTADMIN}) { + unless (-x "/usr/sbin/httpd") {&addline(1,"HTTP Binary","/usr/sbin/httpd not found or not executable"); return} + } + else { + unless (-x "/usr/local/apache/bin/httpd") {&addline(1,"HTTP Binary","/usr/local/apache/bin/httpd not found or not executable"); return} + } + + if ($ea4{enabled}) { + $mypid = open3($childin, $childout, $childout, $ea4{bin_httpd},"-v"); + } + elsif ($config{DIRECTADMIN}) { + $mypid = open3($childin, $childout, $childout, "/usr/sbin/httpd","-v"); + } + else { + $mypid = open3($childin, $childout, $childout, "/usr/local/apache/bin/httpd","-v"); + } + my @version = <$childout>; + waitpid ($mypid, 0); + chomp @version; + $version[0] =~ /Apache\/(\d+)\.(\d+)\.(\d+)/; + my $mas = $1; + my $maj = $2; + my $min = $3; + if ("$mas.$maj" < 2.2) {$status = 1} + &addline($status,"Check apache version","You are running a legacy version of apache (v$mas.$maj.$min) and should consider upgrading to v2.2.* as recommended by the Apache developers"); + + unless ($config{DIRECTADMIN}) { + my $ruid2 = 0; + if ($ea4{enabled}) { + $mypid = open3($childin, $childout, $childout, $ea4{bin_httpd},"-M"); + } + else { + $mypid = open3($childin, $childout, $childout, "/usr/local/apache/bin/httpd","-M"); + } + my @modules = <$childout>; + waitpid ($mypid, 0); + chomp @modules; + if (my @ls = grep {$_ =~ /ruid2_module/} @modules) {$ruid2 = 1} + if (my @ls = grep {$_ =~ /mpm_itk_module/} @modules) {$ruid2 = 1} + + $status = 0; + if (my @ls = grep {$_ =~ /security2_module/} @modules) {$status = 0} else {$status = 1} + &addline($status,"Check apache for ModSecurity","You should install the ModSecurity apache module during the easyapache build process to help prevent exploitation of vulnerable web scripts, together with a set of rules"); + + $status = 0; + if (my @ls = grep {$_ =~ /cloudflare_module/} @modules) {$status = 1} else {$status = 0} + if ($config{CF_ENABLE}) {$status = 0} + &addline($status,"Check apache for mod_cloudflare","This module logs the real users IP address to Apache. If this is reported to lfd via ModSecurity, cxs or some other vector through Apache it will lead to that IP being blocked, but because the IP is coming through the CloudFlare service the IP will not be blocked as so far as iptables is concerned the originating IP address is CloudFlare itself and the abuse will continue. To block these IP's in the CloudFlare Firewall look at using CF_ENABLE in csf.conf"); + + $status = 0; + if (my @ls = grep {$_ =~ /frontpage_module/} @modules) {$status = 1} + &addline($status,"Check apache for FrontPage","Microsoft Frontpage Extensions were EOL in 2006 and there is no support for bugs or security issues. For this reason, it should be considered a security risk to continue using them. You should rebuild apache through easyapache and deselect the option to build them"); + + my @conf; + if (-e "/usr/local/apache/conf/httpd.conf") { + open (my $IN, "<", "/usr/local/apache/conf/httpd.conf"); + flock ($IN, LOCK_SH); + @conf = <$IN>; + close ($IN); + chomp @conf; + } + if (-e "$ea4{file_conf}") { + open (my $IN, "<", "$ea4{file_conf}"); + flock ($IN, LOCK_SH); + @conf = <$IN>; + close ($IN); + chomp @conf; + } + if (@conf) { + $status = 0; + my $ciphers; + my $error; + if (my @ls = grep {$_ =~ /^\s*SSLCipherSuite/} @conf) { + $ls[0] =~ s/^\s+//g; + (undef,$ciphers) = split(/\ /,$ls[0]); + $ciphers =~ s/\s*|\"|\'//g; + if ($ciphers eq "") { + $status = 1; + } else { + if (-x "/usr/bin/openssl") { + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, "/usr/bin/openssl","ciphers","-v",$ciphers); + my @openssl = <$childout>; + waitpid ($cmdpid, 0); + chomp @openssl; + if (my @ls = grep {$_ =~ /error/i} @openssl) {$error = $openssl[0]; $status=2} + if (my @ls = grep {$_ =~ /SSLv2/} @openssl) {$status = 1} + } + } + } else {$status = 1} + if ($status == 2) { + &addline($status,"Check Apache weak SSL/TLS Ciphers (SSLCipherSuite)","Unable to determine cipher list for [$ciphers] from openssl:
[$error]"); + } + &addline($status,"Check Apache weak SSL/TLS Ciphers (SSLCipherSuite)","Cipher list [$ciphers]. Due to weaknesses in the SSLv2 cipher you should disable SSLv2 in WHM > Apache Configuration > Global Configuration > SSLCipherSuite > Add -SSLv2 to SSLCipherSuite and/or remove +SSLv2. Do not forget to Save AND then Rebuild Configuration and Restart Apache, otherwise the changes will not take effect in httpd.conf"); + + $status = 0; + if (my @ls = grep {$_ =~ /^\s*TraceEnable Off/} @conf) { + $status = 0; + } else {$status = 1} + &addline($status,"Check apache for TraceEnable","You should set TraceEnable to Off in: WHM > Apache Configuration > Global Configuration > Trace Enable > Off. Do not forget to Save AND then Rebuild Configuration and Restart Apache, otherwise the changes will not take effect in httpd.conf"); + $status = 0; + if (my @ls = grep {$_ =~ /^\s*ServerSignature Off/} @conf) { + $status = 0; + } else {$status = 1} + &addline($status,"Check apache for ServerSignature","You should set ServerSignature to Off in: WHM > Apache Configuration > Global Configuration > Server Signature > Off. Do not forget to Save AND then Rebuild Configuration and Restart Apache, otherwise the changes will not take effect in httpd.conf"); + $status = 0; + if (my @ls = grep {$_ =~ /^\s*ServerTokens ProductOnly/} @conf) { + $status = 0; + } else {$status = 1} + &addline($status,"Check apache for ServerTokens","You should set ServerTokens to ProductOnly in: WHM > Apache Configuration > Global Configuration > Server Tokens > Product Only. Do not forget to Save AND then Rebuild Configuration and Restart Apache, otherwise the changes will not take effect in httpd.conf"); + $status = 0; + if (my @ls = grep {$_ =~ /^\s*FileETag None/} @conf) { + $status = 0; + } else {$status = 1} + &addline($status,"Check apache for FileETag","You should set FileETag to None in: WHM > Apache Configuration > Global Configuration > File ETag > None. Do not forget to Save AND then Rebuild Configuration and Restart Apache, otherwise the changes will not take effect in httpd.conf"); + } + + my @apacheconf; + if (-e "/usr/local/apache/conf/php.conf.yaml") { + open (my $IN, "<", "/usr/local/apache/conf/php.conf.yaml"); + flock ($IN, LOCK_SH); + @apacheconf = <$IN>; + close ($IN); + chomp @apacheconf; + } + if (-e "$ea4{dir_conf}/php.conf.yaml") { + open (my $IN, "<", "$ea4{dir_conf}/php.conf.yaml"); + flock ($IN, LOCK_SH); + @apacheconf = <$IN>; + close ($IN); + chomp @apacheconf; + } + if (@apacheconf) { + unless ($ruid2) { + $status = 0; + if (my @ls = grep {$_ =~ /suphp/} @apacheconf) { + $status = 0; + } else {$status = 1} + &addline($status,"Check suPHP","To reduce the risk of hackers accessing all sites on the server from a compromised PHP web script, you should enable suPHP when you build apache/php. Note that there are sideeffects when enabling suPHP on a server and you should be aware of these before enabling it.
Don\'t forget to enable it as the default PHP handler in WHM > PHP 5 Handler"); + + $status = 0; + unless ($cpconf->{userdirprotect}) {$status = 1} + &addline($status,"Check mod_userdir protection","To prevents users from stealing bandwidth or hackers hiding access to your servers, you should check WHM > Security Center > mod_userdir Tweak"); + + $status = 1; + if (my @ls = grep {$_ =~ /suexec_module/} @modules) {$status = 0} + &addline($status,"Check Suexec","To reduce the risk of hackers accessing all sites on the server from a compromised CGI web script, you should set WHM > Suexec on"); + } + } + } + return; +} +# end apachecheck +############################################################################### +# start sshtelnetcheck +sub sshtelnetcheck { + my $status = 0; + &addtitle("SSH/Telnet Check"); + + if (-e "/etc/ssh/sshd_config") { + open (my $IN, "<", "/etc/ssh/sshd_config"); + flock ($IN, LOCK_SH); + my @sshconf = <$IN>; + close ($IN); + chomp @sshconf; + if (my @ls = grep {$_ =~ /^\s*Protocol/i} @sshconf) { + if ($ls[0] =~ /1/) {$status = 1} + } else {$status = 0} + &addline($status,"Check SSHv1 is disabled","You should disable SSHv1 by editing /etc/ssh/sshd_config and setting:
Protocol 2"); + + $status = 0; + my $sshport = "22"; + if (my @ls = grep {$_ =~ /^\s*Port/i} @sshconf) { + if ($ls[0] =~ /^\s*Port\s+(\d*)/i) { + $sshport = $1; + if ($sshport eq "22") {$status = 1} + } else {$status = 1} + } else {$status = 1} + &addline($status,"Check SSH on non-standard port","You should consider moving SSH to a non-standard port [currently:$sshport] to evade basic SSH port scans. Don't forget to open the port in the firewall first if necessary"); + + $status = 0; + if (my @ls = grep {$_ =~ /^\s*PasswordAuthentication/i} @sshconf) { + if ($ls[0] =~ /\byes\b/i) {$status = 1} + } else {$status = 1} + &addline($status,"Check SSH PasswordAuthentication","You should disable PasswordAuthentication and only allow access using PubkeyAuthentication to improve brute-force SSH security"); + + $status = 0; + if (my @ls = grep {$_ =~ /^\s*UseDNS/i} @sshconf) { + if ($ls[0] !~ /\bno\b/i) {$status = 1} + } else {$status = 1} + &addline($status,"Check SSH UseDNS","You should disable UseDNS by editing /etc/ssh/sshd_config and setting:
UseDNS no
Otherwise, lfd will be unable to track SSHD login failures successfully as the log files will not report IP addresses"); + } else {&addline(1,"Check SSH configuration","Unable to find /etc/ssh/sshd_config");} + + $status = 0; + my $check = &getportinfo("23"); + if ($check) {$status = 1} + &addline($status,"Check telnet port 23 is not in use","It appears that something is listening on port 23 which is normally used for telnet. Telnet is an insecure protocol and you should disable the telnet daemon if it is running"); + + unless ($config{DNSONLY} or $config{GENERIC}) { + unless ($config{VPS}) { + if (-e "/etc/redhat-release") { + open (my $IN, "<", "/etc/redhat-release"); + flock ($IN, LOCK_SH); + my $conf = <$IN>; + close ($IN); + chomp $conf; + + unless ($conf =~ /^CloudLinux/i) { + if (-e "/etc/profile") { + $status = 0; + open (my $IN, "<", "/etc/profile"); + flock ($IN, LOCK_SH); + my @profile = <$IN>; + close ($IN); + chomp @profile; + if (grep {$_ =~ /^LIMITUSER=\$USER/} @profile) { + $status = 0; + } else {$status = 1} + &addline($status,"Check shell limits","You should enable shell resource limits to prevent shell users from consuming server resources - DOS exploits typically do this. A quick way to set this is to use WHM > Shell Fork Bomb Protection"); + } else { + &addline(1,"Check shell limits","Unable to find /etc/profile"); + } + } + } + } + + $status = 0; + if (-e "/var/cpanel/killproc.conf") { + open (my $IN, "<", "/var/cpanel/killproc.conf"); + flock ($IN, LOCK_SH); + my @proc = <$IN>; + close ($IN); + chomp @proc; + if (@proc < 9) {$status = 1} + &addline($status,"Check Background Process Killer","You should enable each item in the WHM > Background Process Killer"); + } else {&addline(1,"Check Background Process Killer","You should enable each item in the WHM > Background Process Killer")} + } + return; +} +# end sshtelnetcheck +############################################################################### +# start servicescheck +sub servicescheck { + my $systemctl = "/usr/bin/systemctl"; + my $chkconfig = "/sbin/chkconfig"; + my $servicebin = "/sbin/service"; + if (-e "/bin/systemctl") {$systemctl = "/bin/systemctl"} + if (-e "/usr/sbin/chkconfig") {$chkconfig = "/usr/sbin/chkconfig"} + if (-e "/usr/sbin/service") {$servicebin = "/usr/sbin/service"} + &addtitle("Server Services Check"); + my @services = ("abrt-xorg", "abrtd", "alsa-state", "anacron", "avahi-daemon", "avahi-dnsconfd", "bluetooth", "bolt", "canna", "colord", "cups", "cups-config-daemon", "cupsd", "firewalld", "FreeWnn", "gdm", "gpm", "gssproxy", "hidd", "iiim", "ksmtuned", "mDNSResponder", "ModemManager", "nfslock", "nifd", "packagekit", "pcscd", "portreserve", "pulseaudio", "qpidd", "rpcbind", "rpcidmapd", "saslauthd", "sbadm", "wpa_supplicant", "xfs", "xinetd"); + + my $disable; + my ($childin, $childout); + my $mypid; + if ($sysinit eq "init") { + $disable = "$servicebin [service] stop
$chkconfig [service] off"; + $mypid = open3($childin, $childout, $childout, $chkconfig,"--list"); + } else { + $disable = "$systemctl stop [service]
$systemctl disable [service]"; + $mypid = open3($childin, $childout, $childout, $systemctl,"list-unit-files","--state=enabled","--no-pager","--no-legend"); + } + my @chkconfig = <$childout>; + waitpid ($mypid, 0); + chomp @chkconfig; + + my @enabled; + foreach my $service (@services) { + if ($service eq "xinetd" and $config{PLESK}) {next} + if ($sysinit eq "init") { + if (my @ls = grep {$_ =~ /^$service\b/} @chkconfig) { + if ($ls[0] =~ /\:on/) {push @enabled, $service} + } + } else { + if (my @ls = grep {$_ =~ /^$service\.service/} @chkconfig) {push @enabled, $service} + } + } + if (scalar @enabled > 0) { + my $list; + foreach my $service (@enabled) { + if (length($list) == 0) { + $list = $service; + } else { + $list .= ",".$service; + } + } + &addline("1","Check server services","On most servers the following services are not needed and should be stopped and disabled from starting unless used:

$list

\nEach service can usually be disabled using:
$disable"); + } else { + &addline("0","Check server services","On most servers the following services are not needed and should be stopped and disabled from starting unless used:

none found

\nEach service can usually be disabled using:
$disable"); + } + return; +} +# end servicescheck +############################################################################### +# start getportinfo +sub getportinfo { + my $port = shift; + my $hit = 0; + + foreach my $proto ("udp","tcp","udp6","tcp6") { + open (my $IN, "<", "/proc/net/$proto"); + flock ($IN, LOCK_SH); + while (<$IN>) { + my @rec = split(); + if ($rec[9] =~ /uid/) {next} + my (undef,$sport) = split(/:/,$rec[1]); + if (hex($sport) == $port) {$hit = 1} + } + close ($IN); + } + + return $hit; +} +# end getportinfo +############################################################################### + +1; diff --git a/src/redux/ConfigServer/ServerStats.pm b/src/redux/ConfigServer/ServerStats.pm new file mode 100644 index 000000000..a42656bda --- /dev/null +++ b/src/redux/ConfigServer/ServerStats.pm @@ -0,0 +1,3547 @@ +############################################################################### +# Copyright 2006-2023, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +## no critic (RequireUseWarnings, ProhibitExplicitReturnUndef, ProhibitMixedBooleanOperators, RequireBriefOpen) +# start main +package ConfigServer::ServerStats; + +use strict; +use lib '/usr/local/csf/lib'; +use Fcntl qw(:DEFAULT :flock); + +use Exporter qw(import); +our $VERSION = 1.02; +our @ISA = qw(Exporter); +our @EXPORT_OK = qw(); + +my %minmaxavg; + +# end main +############################################################################### +# start init +sub init { + eval ('use GD::Graph::bars;'); ##no critic + if ($@) {return undef} + eval ('use GD::Graph::pie;'); ##no critic + if ($@) {return undef} + eval ('use GD::Graph::lines;'); ##no critic + if ($@) {return undef} +} +# end init +############################################################################### +# start graphs +sub graphs { + my $type = shift; + my $system_maxdays = shift; + my $imghddir = shift; + my $img; + $| = 1; + + require GD::Graph::bars; + import GD::Graph::bars; + require GD::Graph::pie; + import GD::Graph::pie; + require GD::Graph::lines; + import GD::Graph::lines; + + sysopen (my $STATS,"/var/lib/csf/stats/system", O_RDWR | O_CREAT); + flock ($STATS, LOCK_SH); + my @stats = <$STATS>; + chomp @stats; + close ($STATS); + + if (@stats > 1) { + local $SIG{__DIE__} = undef; + my $time = time; + my %stata; + foreach my $line (@stats) { + my ($thistime,undef) = split(/\,/,$line); + if (time - $thistime > (86400 * $system_maxdays)) {next} + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($thistime); + $stata{$year}{$mon}{$mday}{$hour}{$min} = $line; + } + + if ($type eq "cpu") { + my (@h,@p,@t); + my $cputotal_prev; + my $cpuidle_prev; + my $cpuiowait_prev; + for (my $mins = 0; $mins < 60;$mins++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($mins * 60)); + push @h,$min; + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$min}); + if ($time eq "" or $cputotal eq "") { + $cputotal_prev = 0; + $cpuidle_prev = 0; + $cpuiowait_prev = 0; + push @p,undef; + push @t,undef; + } else { + my $idle_diff = $cpuidle - $cpuidle_prev; + my $iowait_diff = $cpuiowait - $cpuiowait_prev; + my $total_diff = $cputotal - $cputotal_prev; + if ($total_diff == 0) { + $cputotal_prev = 0; + $cpuidle_prev = 0; + $cpuiowait_prev = 0; + push @p,undef; + push @t,undef; + next; + } + my $idle_use = 100 - 100 * ($total_diff - $idle_diff) / $total_diff; + my $iowait_use = 100 - 100 * ($total_diff - $iowait_diff) / $total_diff; + $cpuidle_prev = $cpuidle; + $cpuiowait_prev = $cpuiowait; + $cputotal_prev = $cputotal; + push @p,$idle_use; + push @t,$iowait_use; + + &minmaxavg("HOUR","1Idle",$idle_use); + &minmaxavg("HOUR","2IOWAIT",$iowait_use); + } + } + if ($minmaxavg{HOUR}{"1Idle"}{CNT} > 0) {$minmaxavg{HOUR}{"1Idle"}{AVG} /= $minmaxavg{HOUR}{"1Idle"}{CNT}} + if ($minmaxavg{HOUR}{"2IOWAIT"}{CNT} > 0) {$minmaxavg{HOUR}{"2IOWAIT"}{AVG} /= $minmaxavg{HOUR}{"2IOWAIT"}{CNT}} + my @data = ([reverse @h],[reverse @p],[reverse @t]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred) ] ); + $hour_graph->set( + x_label => 'Minute', + y_label => '% CPU', + x_label_skip => 3, + line_width => 2, + title => 'CPU Usage in last hour', + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend( qw(Idle IOWAIT)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemhour.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "cpu") { + my (@h,@p,@t); + my $cputotal_prev; + my $cpuidle_prev; + my $cpuiowait_prev; + for (my $mins = 0; $mins < 1440;$mins++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($mins * 60)); + push @h,$hour; + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$min}); + if ($time eq "" or $cputotal eq "") { + $cputotal_prev = 0; + $cpuidle_prev = 0; + $cpuiowait_prev = 0; + push @p,undef; + push @t,undef; + } else { + my $idle_diff = $cpuidle - $cpuidle_prev; + my $iowait_diff = $cpuiowait - $cpuiowait_prev; + my $total_diff = $cputotal - $cputotal_prev; + if ($total_diff == 0) { + $cputotal_prev = 0; + $cpuidle_prev = 0; + $cpuiowait_prev = 0; + push @p,undef; + push @t,undef; + next; + } + my $idle_use = 100 - 100 * ($total_diff - $idle_diff) / $total_diff; + my $iowait_use = 100 - 100 * ($total_diff - $iowait_diff) / $total_diff; + $cpuidle_prev = $cpuidle; + $cpuiowait_prev = $cpuiowait; + $cputotal_prev = $cputotal; + push @p,$idle_use; + push @t,$iowait_use; + + &minmaxavg("DAY","1Idle",$idle_use); + &minmaxavg("DAY","2IOWAIT",$iowait_use); + } + } + if ($minmaxavg{DAY}{"1Idle"}{CNT} > 0) {$minmaxavg{DAY}{"1Idle"}{AVG} /= $minmaxavg{DAY}{"1Idle"}{CNT}} + if ($minmaxavg{DAY}{"2IOWAIT"}{CNT} > 0) {$minmaxavg{DAY}{"2IOWAIT"}{AVG} /= $minmaxavg{DAY}{"2IOWAIT"}{CNT}} + my @data = ([reverse @h],[reverse @p],[reverse @t]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred) ] ); + $hour_graph->set( + x_label => 'Hour', + y_label => '% CPU', + x_label_skip => 60, + title => 'CPU Usage in last 24 hours', + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend( qw(Idle IOWAIT)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemday.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "cpu") { + my (@h,@p,@t); + my $cputotal_prev; + my $cpuidle_prev; + my $cpuiowait_prev; + $minmaxavg{WEEK}{"1Idle"}{MIN} = 100; + $minmaxavg{WEEK}{"1Idle"}{MAX} = 0; + $minmaxavg{WEEK}{"2IOWAIT"}{MIN} = 100; + $minmaxavg{WEEK}{"2IOWAIT"}{MAX} = 0; + for (my $hours = 0; $hours < 168;$hours++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($hours * 60 * 60)); + push @h,$mday; + my $idle_avg; + my $iowait_avg; + my $cnt_avg; + for (my $mins = 59; $mins >= 0;$mins--) { + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$mins}); + if ($time and $cputotal ne "") { + my $idle_diff = $cpuidle - $cpuidle_prev; + my $iowait_diff = $cpuiowait - $cpuiowait_prev; + my $total_diff = $cputotal - $cputotal_prev; + if ($total_diff == 0) { + $cputotal_prev = 0; + $cpuidle_prev = 0; + $cpuiowait_prev = 0; + next; + } + my $idle_use = 100 - 100 * ($total_diff - $idle_diff) / $total_diff; + my $iowait_use = 100 - 100 * ($total_diff - $iowait_diff) / $total_diff; + $cpuidle_prev = $cpuidle; + $cpuiowait_prev = $cpuiowait; + $cputotal_prev = $cputotal; + $idle_avg += $idle_use; + $iowait_avg += $iowait_use; + $cnt_avg++; + } else { + $cputotal_prev = 0; + $cpuidle_prev = 0; + $cpuiowait_prev = 0; + } + } + unless (defined $cnt_avg) { + push @p,undef; + push @t,undef; + } else { + if ($cnt_avg == 0) {$cnt_avg = 1} + push @p,$idle_avg/$cnt_avg; + push @t,$iowait_avg/$cnt_avg; + &minmaxavg("WEEK","1Idle",($idle_avg/$cnt_avg)); + &minmaxavg("WEEK","2IOWAIT",($iowait_avg/$cnt_avg)); + } + } + if ($minmaxavg{WEEK}{"1Idle"}{CNT} > 0) {$minmaxavg{WEEK}{"1Idle"}{AVG} /= $minmaxavg{WEEK}{"1Idle"}{CNT}} + if ($minmaxavg{WEEK}{"2IOWAIT"}{CNT} > 0) {$minmaxavg{WEEK}{"2IOWAIT"}{AVG} /= $minmaxavg{WEEK}{"2IOWAIT"}{CNT}} + my @data = ([reverse @h],[reverse @p],[reverse @t]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred) ] ); + $hour_graph->set( + x_label => 'Day (Hourly Average)', + y_label => '% CPU', + x_label_skip => 24, + title => 'CPU Usage in last 7 days', + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend( qw(Idle IOWAIT)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemweek.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "cpu") { + my (@h,@p,@t); + my $cputotal_prev; + my $cpuidle_prev; + my $cpuiowait_prev; + $minmaxavg{MONTH}{"1Idle"}{MIN} = 100; + $minmaxavg{MONTH}{"1Idle"}{MAX} = 0; + $minmaxavg{MONTH}{"2IOWAIT"}{MIN} = 100; + $minmaxavg{MONTH}{"2IOWAIT"}{MAX} = 0; + for (my $hours = 0; $hours < (24 * $system_maxdays);$hours++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($hours * 60 * 60)); + push @h,$mday; + my $idle_avg; + my $iowait_avg; + my $cnt_avg; + for (my $mins = 59; $mins >= 0;$mins--) { + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$mins}); + if ($time and $cputotal ne "") { + my $idle_diff = $cpuidle - $cpuidle_prev; + my $iowait_diff = $cpuiowait - $cpuiowait_prev; + my $total_diff = $cputotal - $cputotal_prev; + if ($total_diff == 0) { + $cputotal_prev = 0; + $cpuidle_prev = 0; + $cpuiowait_prev = 0; + next; + } + my $idle_use = 100 - 100 * ($total_diff - $idle_diff) / $total_diff; + my $iowait_use = 100 - 100 * ($total_diff - $iowait_diff) / $total_diff; + $cpuidle_prev = $cpuidle; + $cpuiowait_prev = $cpuiowait; + $cputotal_prev = $cputotal; + $idle_avg += $idle_use; + $iowait_avg += $iowait_use; + $cnt_avg++; + } else { + $cputotal_prev = 0; + $cpuidle_prev = 0; + $cpuiowait_prev = 0; + } + } + unless (defined $cnt_avg) { + push @p,undef; + push @t,undef; + } else { + if ($cnt_avg == 0) {$cnt_avg = 1} + push @p,$idle_avg/$cnt_avg; + push @t,$iowait_avg/$cnt_avg; + &minmaxavg("MONTH","1Idle",($idle_avg/$cnt_avg)); + &minmaxavg("MONTH","2IOWAIT",($iowait_avg/$cnt_avg)); + } + } + if ($minmaxavg{MONTH}{"1Idle"}{CNT} > 0) {$minmaxavg{MONTH}{"1Idle"}{AVG} /= $minmaxavg{MONTH}{"1Idle"}{CNT}} + if ($minmaxavg{MONTH}{"2IOWAIT"}{CNT} > 0) {$minmaxavg{MONTH}{"2IOWAIT"}{AVG} /= $minmaxavg{MONTH}{"2IOWAIT"}{CNT}} + my @data = ([reverse @h],[reverse @p],[reverse @t]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred) ] ); + $hour_graph->set( + x_label => 'Day (Hourly Average)', + y_label => '% CPU', + x_label_skip => 24, + title => "CPU Usage in last $system_maxdays days", + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend( qw(Idle IOWAIT)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemmonth.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "mem") { + my (@h,@p,@t,@c,@a,@b); + for (my $mins = 0; $mins < 60;$mins++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($mins * 60)); + push @h,$min; + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$min}); + if ($time eq "" or $memtotal eq "") { + push @p,undef; + push @t,undef; + push @c,undef; + push @a,undef; + push @b,undef; + } else { + $memfree = $memtotal - $memfree; + $memswapfree = $memswaptotal - $memswapfree; + push @p,$memtotal; + push @t,$memfree; + push @c,$memcached; + push @a,$memswaptotal; + push @b,$memswapfree; + + &minmaxavg("HOUR","1Used",$memfree); + &minmaxavg("HOUR","2Cached",$memcached); + &minmaxavg("HOUR","3SwapUsed",$memswapfree); + } + } + if ($minmaxavg{HOUR}{"1Used"}{CNT} > 0) {$minmaxavg{HOUR}{"1Used"}{AVG} /= $minmaxavg{HOUR}{"1Used"}{CNT}} + if ($minmaxavg{HOUR}{"2Cached"}{CNT} > 0) {$minmaxavg{HOUR}{"2Cached"}{AVG} /= $minmaxavg{HOUR}{"2Cached"}{CNT}} + if ($minmaxavg{HOUR}{"3SwapUsed"}{CNT} > 0) {$minmaxavg{HOUR}{"3SwapUsed"}{AVG} /= $minmaxavg{HOUR}{"3SwapUsed"}{CNT}} + my @data = ([reverse @h],[reverse @p],[reverse @t],[reverse @c],[reverse @a],[reverse @b]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred purple blue green) ] ); + $hour_graph->set( + x_label => 'Minute', + y_label => 'Memory (KB)', + x_label_skip => 3, + title => 'Memory Usage in last hour', + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend( qw(Total Used Cached SwapTotal SwapUsed)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemhour.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "mem") { + my (@h,@p,@c,@t,@a,@b); + for (my $mins = 0; $mins < 1440;$mins++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($mins * 60)); + push @h,$hour; + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$min}); + if ($time eq "" or $memtotal eq "") { + push @p,undef; + push @t,undef; + push @c,undef; + push @a,undef; + push @b,undef; + } else { + $memfree = $memtotal - $memfree; + $memswapfree = $memswaptotal - $memswapfree; + push @p,$memtotal; + push @t,$memfree; + push @c,$memcached; + push @a,$memswaptotal; + push @b,$memswapfree; + + &minmaxavg("DAY","1Used",$memfree); + &minmaxavg("DAY","2Cached",$memcached); + &minmaxavg("DAY","3SwapUsed",$memswapfree); + } + } + if ($minmaxavg{DAY}{"1Used"}{CNT} > 0) {$minmaxavg{DAY}{"1Used"}{AVG} /= $minmaxavg{DAY}{"1Used"}{CNT}} + if ($minmaxavg{DAY}{"2Cached"}{CNT} > 0) {$minmaxavg{DAY}{"2Cached"}{AVG} /= $minmaxavg{DAY}{"2Cached"}{CNT}} + if ($minmaxavg{DAY}{"3SwapUsed"}{CNT} > 0) {$minmaxavg{DAY}{"3SwapUsed"}{AVG} /= $minmaxavg{DAY}{"3SwapUsed"}{CNT}} + my @data = ([reverse @h],[reverse @p],[reverse @t],[reverse @c],[reverse @a],[reverse @b]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred purple blue green) ] ); + $hour_graph->set( + x_label => 'Hour', + y_label => 'Memory (KB)', + x_label_skip => 60, + title => 'Memory Usage in last 24 hours', + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend( qw(Total Used Cached SwapTotal SwapUsed)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemday.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "mem") { + my (@h,@p,@t,@c,@a,@b); + for (my $hours = 0; $hours < 168;$hours++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($hours * 60 * 60)); + push @h,$mday; + my $memtotal_avg; + my $memfree_avg; + my $memcached_avg; + my $memswaptotal_avg; + my $memswapfree_avg; + my $cnt_avg; + for (my $mins = 59; $mins >= 0;$mins--) { + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$mins}); + if ($time and $memtotal ne "") { + $memfree = $memtotal - $memfree; + $memswapfree = $memswaptotal - $memswapfree; + $memtotal_avg += $memtotal; + $memfree_avg += $memfree; + $memcached_avg += $memcached; + $memswaptotal_avg += $memswaptotal; + $memswapfree_avg += $memswapfree; + $cnt_avg++; + } + } + unless (defined $cnt_avg) { + push @p,undef; + push @t,undef; + push @c,undef; + push @a,undef; + push @b,undef; + } else { + if ($cnt_avg == 0) {$cnt_avg = 1} + push @p,$memtotal_avg/$cnt_avg; + push @t,$memfree_avg/$cnt_avg; + push @c,$memcached_avg/$cnt_avg; + push @a,$memswaptotal_avg/$cnt_avg; + push @b,$memswapfree_avg/$cnt_avg; + + &minmaxavg("WEEK","1Used",($memfree_avg/$cnt_avg)); + &minmaxavg("WEEK","2Cached",($memcached_avg/$cnt_avg)); + &minmaxavg("WEEK","3SwapUsed",($memswapfree_avg/$cnt_avg)); + } + } + if ($minmaxavg{WEEK}{"1Used"}{CNT} > 0) {$minmaxavg{WEEK}{"1Used"}{AVG} /= $minmaxavg{WEEK}{"1Used"}{CNT}} + if ($minmaxavg{WEEK}{"2Cached"}{CNT} > 0) {$minmaxavg{WEEK}{"2Cached"}{AVG} /= $minmaxavg{WEEK}{"2Cached"}{CNT}} + if ($minmaxavg{WEEK}{"3SwapUsed"}{CNT} > 0) {$minmaxavg{WEEK}{"3SwapUsed"}{AVG} /= $minmaxavg{WEEK}{"3SwapUsed"}{CNT}} + my @data = ([reverse @h],[reverse @p],[reverse @t],[reverse @c],[reverse @a],[reverse @b]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred purple blue green) ] ); + $hour_graph->set( + x_label => 'Day (Hourly Average)', + y_label => 'Memory (KB)', + x_label_skip => 24, + title => 'Memory Usage in last 7 days', + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend( qw(Total Used Cached SwapTotal SwapUsed)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemweek.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "mem") { + my (@h,@p,@t,@c,@a,@b); + for (my $hours = 0; $hours < (24 * $system_maxdays);$hours++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($hours * 60 * 60)); + push @h,$mday; + my $memtotal_avg; + my $memfree_avg; + my $memcached_avg; + my $memswaptotal_avg; + my $memswapfree_avg; + my $cnt_avg; + for (my $mins = 59; $mins >= 0;$mins--) { + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$mins}); + if ($time and $memtotal ne "") { + $memfree = $memtotal - $memfree; + $memswapfree = $memswaptotal - $memswapfree; + $memtotal_avg += $memtotal; + $memfree_avg += $memfree; + $memcached_avg += $memcached; + $memswaptotal_avg += $memswaptotal; + $memswapfree_avg += $memswapfree; + $cnt_avg++; + } + } + unless (defined $cnt_avg) { + push @p,undef; + push @t,undef; + push @c,undef; + push @a,undef; + push @b,undef; + } else { + if ($cnt_avg == 0) {$cnt_avg = 1} + push @p,$memtotal_avg/$cnt_avg; + push @t,$memfree_avg/$cnt_avg; + push @c,$memcached_avg/$cnt_avg; + push @a,$memswaptotal_avg/$cnt_avg; + push @b,$memswapfree_avg/$cnt_avg; + + &minmaxavg("MONTH","1Used",($memfree_avg/$cnt_avg)); + &minmaxavg("MONTH","2Cached",($memcached_avg/$cnt_avg)); + &minmaxavg("MONTH","3SwapUsed",($memswapfree_avg/$cnt_avg)); + } + } + if ($minmaxavg{MONTH}{"1Used"}{CNT} > 0) {$minmaxavg{MONTH}{"1Used"}{AVG} /= $minmaxavg{MONTH}{"1Used"}{CNT}} + if ($minmaxavg{MONTH}{"2Cached"}{CNT} > 0) {$minmaxavg{MONTH}{"2Cached"}{AVG} /= $minmaxavg{MONTH}{"2Cached"}{CNT}} + if ($minmaxavg{MONTH}{"3SwapUsed"}{CNT} > 0) {$minmaxavg{MONTH}{"3SwapUsed"}{AVG} /= $minmaxavg{MONTH}{"3SwapUsed"}{CNT}} + my @data = ([reverse @h],[reverse @p],[reverse @t],[reverse @c],[reverse @a],[reverse @b]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred purple blue green) ] ); + $hour_graph->set( + x_label => 'Day (Hourly Average)', + y_label => 'Memory (Bytes)', + x_label_skip => 24, + title => "Memory Usage in last $system_maxdays days", + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend( qw(Total Used Cached SwapTotal SwapUsed)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemmonth.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "load") { + my (@h,@p,@t,@a); + for (my $mins = 0; $mins < 60;$mins++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($mins * 60)); + push @h,$min; + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$min}); + if ($time eq "" or $load1 eq "") { + push @p,undef; + push @t,undef; + push @a,undef; + } else { + push @p,$load1; + push @t,$load5; + push @a,$load15; + + &minmaxavg("HOUR","1Load_1",$load1); + &minmaxavg("HOUR","2Load_5",$load5); + &minmaxavg("HOUR","3Load_15",$load15); + } + } + if ($minmaxavg{HOUR}{"1Load_1"}{CNT} > 0) {$minmaxavg{HOUR}{"1Load_1"}{AVG} /= $minmaxavg{HOUR}{"1Load_1"}{CNT}} + if ($minmaxavg{HOUR}{"2Load_5"}{CNT} > 0) {$minmaxavg{HOUR}{"2Load_5"}{AVG} /= $minmaxavg{HOUR}{"2Load_5"}{CNT}} + if ($minmaxavg{HOUR}{"3Load_15"}{CNT} > 0) {$minmaxavg{HOUR}{"3Load_15"}{AVG} /= $minmaxavg{HOUR}{"3Load_15"}{CNT}} + my @data = ([reverse @h],[reverse @p],[reverse @t],[reverse @a]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred purple) ] ); + $hour_graph->set( + x_label => 'Minute', + y_label => 'Load Average', + x_label_skip => 3, + title => 'Load Averages in last hour', + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend( qw(Load_1 Load_5 Load_15)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemhour.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "load") { + my (@h,@p,@t,@a); + for (my $mins = 0; $mins < 1440;$mins++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($mins * 60)); + push @h,$hour; + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$min}); + if ($time eq "" or $load1 eq "") { + push @p,undef; + push @t,undef; + push @a,undef; + } else { + push @p,$load1; + push @t,$load5; + push @a,$load15; + + &minmaxavg("DAY","1Load_1",$load1); + &minmaxavg("DAY","2Load_5",$load5); + &minmaxavg("DAY","3Load_15",$load15); + } + } + if ($minmaxavg{DAY}{"1Load_1"}{CNT} > 0) {$minmaxavg{DAY}{"1Load_1"}{AVG} /= $minmaxavg{DAY}{"1Load_1"}{CNT}} + if ($minmaxavg{DAY}{"2Load_5"}{CNT} > 0) {$minmaxavg{DAY}{"2Load_5"}{AVG} /= $minmaxavg{DAY}{"2Load_5"}{CNT}} + if ($minmaxavg{DAY}{"3Load_15"}{CNT} > 0) {$minmaxavg{DAY}{"3Load_15"}{AVG} /= $minmaxavg{DAY}{"3Load_15"}{CNT}} + my @data = ([reverse @h],[reverse @p],[reverse @t],[reverse @a]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred purple) ] ); + $hour_graph->set( + x_label => 'Hour', + y_label => 'Load Average', + x_label_skip => 60, + title => 'Load Averages in last 24 hours', + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend( qw(Load_1 Load_5 Load_15)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemday.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "load") { + my (@h,@p,@t,@a); + for (my $hours = 0; $hours < 168;$hours++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($hours * 60 * 60)); + push @h,$mday; + my $load1_avg; + my $load5_avg; + my $load15_avg; + my $cnt_avg = 0; + for (my $mins = 59; $mins >= 0;$mins--) { + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$mins}); + if ($time and $load1 ne "") { + $load1_avg += $load1; + $load5_avg += $load5; + $load15_avg += $load15; + $cnt_avg++; + } + } + unless (defined $cnt_avg) { + push @p,undef; + push @t,undef; + push @a,undef; + } else { + if ($cnt_avg == 0) {$cnt_avg = 1} + push @p,$load1_avg/$cnt_avg; + push @t,$load5_avg/$cnt_avg; + push @a,$load15_avg/$cnt_avg; + + &minmaxavg("WEEK","1Load_1",($load1_avg/$cnt_avg)); + &minmaxavg("WEEK","2Load_5",($load5_avg/$cnt_avg)); + &minmaxavg("WEEK","3Load_15",($load15_avg/$cnt_avg)); + } + } + if ($minmaxavg{WEEK}{"1Load_1"}{CNT} > 0) {$minmaxavg{WEEK}{"1Load_1"}{AVG} /= $minmaxavg{WEEK}{"1Load_1"}{CNT}} + if ($minmaxavg{WEEK}{"2Load_5"}{CNT} > 0) {$minmaxavg{WEEK}{"2Load_5"}{AVG} /= $minmaxavg{WEEK}{"2Load_5"}{CNT}} + if ($minmaxavg{WEEK}{"3Load_15"}{CNT} > 0) {$minmaxavg{WEEK}{"3Load_15"}{AVG} /= $minmaxavg{WEEK}{"3Load_15"}{CNT}} + my @data = ([reverse @h],[reverse @p],[reverse @t],[reverse @a]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred purple) ] ); + $hour_graph->set( + x_label => 'Day (Hourly Average)', + y_label => 'Load Average', + x_label_skip => 24, + title => 'Load Averages in last 7 days', + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend( qw(Load_1 Load_5 Load_15)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemweek.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "load") { + my (@h,@p,@t,@a); + for (my $hours = 0; $hours < (24 * $system_maxdays);$hours++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($hours * 60 * 60)); + push @h,$mday; + my $load1_avg; + my $load5_avg; + my $load15_avg; + my $cnt_avg = 0; + for (my $mins = 59; $mins >= 0;$mins--) { + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$mins}); + if ($time and $load1 ne "") { + $load1_avg += $load1; + $load5_avg += $load5; + $load15_avg += $load15; + $cnt_avg++; + } + } + unless (defined $cnt_avg) { + push @p,undef; + push @t,undef; + push @a,undef; + } else { + if ($cnt_avg == 0) {$cnt_avg = 1} + push @p,$load1_avg/$cnt_avg; + push @t,$load5_avg/$cnt_avg; + push @a,$load15_avg/$cnt_avg; + + &minmaxavg("MONTH","1Load_1",($load1_avg/$cnt_avg)); + &minmaxavg("MONTH","2Load_5",($load5_avg/$cnt_avg)); + &minmaxavg("MONTH","3Load_15",($load15_avg/$cnt_avg)); + } + } + if ($minmaxavg{MONTH}{"1Load_1"}{CNT} > 0) {$minmaxavg{MONTH}{"1Load_1"}{AVG} /= $minmaxavg{MONTH}{"1Load_1"}{CNT}} + if ($minmaxavg{MONTH}{"2Load_5"}{CNT} > 0) {$minmaxavg{MONTH}{"2Load_5"}{AVG} /= $minmaxavg{MONTH}{"2Load_5"}{CNT}} + if ($minmaxavg{MONTH}{"3Load_15"}{CNT} > 0) {$minmaxavg{MONTH}{"3Load_15"}{AVG} /= $minmaxavg{MONTH}{"3Load_15"}{CNT}} + my @data = ([reverse @h],[reverse @p],[reverse @t],[reverse @a]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred purple blue) ] ); + $hour_graph->set( + x_label => 'Day (Hourly Average)', + y_label => 'Load Average', + x_label_skip => 24, + title => "Load Averages in last $system_maxdays days", + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend( qw(Load_1 Load_5 Load_15)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemmonth.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "net") { + my (@h,@p,@t); + my $netin_prev; + my $netout_prev; + for (my $mins = 0; $mins < 60;$mins++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($mins * 60)); + push @h,$min; + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$min}); + if ($time eq "" or $netin eq "") { + $netin_prev = 0; + $netout_prev = 0; + push @p,undef; + push @t,undef; + } else { + if ($netin_prev < $netin or $netin eq "") { + push @p,undef; + $netin_prev = $netin; + } else { + my $netin_val = ($netin_prev - $netin) / 60; + push @p,$netin_val; + $netin_prev = $netin; + &minmaxavg("HOUR","1Inbound",$netin_val); + } + if ($netout_prev < $netout or $netout eq "") { + push @t,undef; + $netout_prev = $netout; + } else { + my $netout_val = ($netout_prev - $netout) / 60; + push @t,$netout_val; + $netout_prev = $netout; + &minmaxavg("HOUR","2Outbound",$netout_val); + } + } + } + if ($minmaxavg{HOUR}{"1Inbound"}{CNT} > 0) {$minmaxavg{HOUR}{"1Inbound"}{AVG} /= $minmaxavg{HOUR}{"1Inbound"}{CNT}} + if ($minmaxavg{HOUR}{"2Outbound"}{CNT} > 0) {$minmaxavg{HOUR}{"2Outbound"}{AVG} /= $minmaxavg{HOUR}{"2Outbound"}{CNT}} + my @data = ([reverse @h],[reverse @p],[reverse @t]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred) ] ); + $hour_graph->set( + x_label => 'Minute', + y_label => 'Bytes/Second', + x_label_skip => 3, + title => 'Network Usage in last hour', + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend( qw(Inbound Outbound)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemhour.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "net") { + my (@h,@p,@t); + my $netin_prev; + my $netout_prev; + for (my $mins = 0; $mins < 1440;$mins++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($mins * 60)); + push @h,$hour; + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$min}); + if ($time eq "" or $netin eq "") { + $netin_prev = 0; + $netout_prev = 0; + push @p,undef; + push @t,undef; + } else { + if ($netin_prev < $netin or $netin eq "") { + push @p,undef; + $netin_prev = $netin; + } else { + my $netin_val = ($netin_prev - $netin) / 60; + push @p,$netin_val; + $netin_prev = $netin; + &minmaxavg("DAY","1Inbound",$netin_val); + } + if ($netout_prev < $netout or $netout eq "") { + push @t,undef; + $netout_prev = $netout; + } else { + my $netout_val = ($netout_prev - $netout) / 60; + push @t,$netout_val; + $netout_prev = $netout; + &minmaxavg("DAY","2Outbound",$netout_val); + } + } + } + if ($minmaxavg{DAY}{"1Inbound"}{CNT} > 0) {$minmaxavg{DAY}{"1Inbound"}{AVG} /= $minmaxavg{DAY}{"1Inbound"}{CNT}} + if ($minmaxavg{DAY}{"2Outbound"}{CNT} > 0) {$minmaxavg{DAY}{"2Outbound"}{AVG} /= $minmaxavg{DAY}{"2Outbound"}{CNT}} + my @data = ([reverse @h],[reverse @p],[reverse @t]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred) ] ); + $hour_graph->set( + x_label => 'Hour', + y_label => 'Bytes/Second', + x_label_skip => 60, + title => 'Network Usage in last 24 hours', + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend( qw(Inbound Outbound)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemday.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "net") { + my (@h,@p,@t); + my $netin_prev; + my $netout_prev; + for (my $hours = 0; $hours < 168;$hours++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($hours * 60 * 60)); + push @h,$mday; + my $netin_avg; + my $netout_avg; + for (my $mins = 59; $mins >= 0;$mins--) { + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$mins}); + if ($time eq "" or $netin eq "") { + $netin_prev = 0; + $netout_prev = 0; + } else { + if ($netin_prev < $netin or $netin eq "") { + $netin_prev = $netin; + } else { + my $netin_val = ($netin_prev - $netin) / 60; + $netin_avg = $netin_avg + $netin_val; + $netin_prev = $netin; + } + if ($netout_prev < $netout or $netout eq "") { + $netout_prev = $netout; + } else { + my $netout_val = ($netout_prev - $netout) / 60; + $netout_avg = $netout_avg + $netout_val; + $netout_prev = $netout; + } + } + } + unless (defined $netin_avg) { + push @p,undef; + } else { + push @p,($netin_avg/60); + &minmaxavg("WEEK","1Inbound",($netin_avg/60)); + } + unless (defined $netout_avg) { + push @t,undef; + } else { + push @t,($netout_avg/60); + &minmaxavg("WEEK","2Outbound",($netout_avg/60)); + } + } + if ($minmaxavg{WEEK}{"1Inbound"}{CNT} > 0) {$minmaxavg{WEEK}{"1Inbound"}{AVG} /= $minmaxavg{WEEK}{"1Inbound"}{CNT}} + if ($minmaxavg{WEEK}{"2Outbound"}{CNT} > 0) {$minmaxavg{WEEK}{"2Outbound"}{AVG} /= $minmaxavg{WEEK}{"2Outbound"}{CNT}} + my @data = ([reverse @h],[reverse @p],[reverse @t]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred) ] ); + $hour_graph->set( + x_label => 'Day (Hourly Average)', + y_label => 'Bytes/Second', + x_label_skip => 24, + title => 'Network Usage in last 7 days', + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend( qw(Inbound Outbound)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemweek.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "net") { + my (@h,@p,@t); + my $netin_prev; + my $netout_prev; + for (my $hours = 0; $hours < (24 * $system_maxdays);$hours++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($hours * 60 * 60)); + push @h,$mday; + my $netin_avg; + my $netout_avg; + for (my $mins = 59; $mins >= 0;$mins--) { + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$mins}); + if ($time eq "" or $netin eq "") { + $netin_prev = 0; + $netout_prev = 0; + } else { + if ($netin_prev < $netin or $netin eq "") { + $netin_prev = $netin; + } else { + my $netin_val = ($netin_prev - $netin) / 60; + $netin_avg = $netin_avg + $netin_val; + $netin_prev = $netin; + } + if ($netout_prev < $netout or $netout eq "") { + $netout_prev = $netout; + } else { + my $netout_val = ($netout_prev - $netout) / 60; + $netout_avg = $netout_avg + $netout_val; + $netout_prev = $netout; + } + } + } + unless (defined $netin_avg) { + push @p,undef; + } else { + push @p,($netin_avg/60); + &minmaxavg("MONTH","1Inbound",($netin_avg/60)); + } + unless (defined $netout_avg) { + push @t,undef; + } else { + push @t,($netout_avg/60); + &minmaxavg("MONTH","2Outbound",($netout_avg/60)); + } + } + if ($minmaxavg{MONTH}{"1Inbound"}{CNT} > 0) {$minmaxavg{MONTH}{"1Inbound"}{AVG} /= $minmaxavg{MONTH}{"1Inbound"}{CNT}} + if ($minmaxavg{MONTH}{"2Outbound"}{CNT} > 0) {$minmaxavg{MONTH}{"2Outbound"}{AVG} /= $minmaxavg{MONTH}{"2Outbound"}{CNT}} + my @data = ([reverse @h],[reverse @p],[reverse @t]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred) ] ); + $hour_graph->set( + x_label => 'Day (Hourly Average)', + y_label => 'Bytes/Second', + x_label_skip => 24, + title => "Network Usage in last $system_maxdays days", + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend( qw(Inbound Outbound)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemmonth.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "disk") { + my (@h,@p,@t); + my $diskread_prev; + my $diskwrite_prev; + for (my $mins = 0; $mins < 60;$mins++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($mins * 60)); + push @h,$min; + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$min}); + if ($time eq "" or $diskread eq "") { + $diskread_prev = 0; + $diskwrite_prev = 0; + push @p,undef; + push @t,undef; + } else { + if ($diskread_prev < $diskread or $diskread eq "") { + push @p,undef; + $diskread_prev = $diskread; + } else { + my $diskread_val = ($diskread_prev - $diskread) / 60; + push @p,$diskread_val; + $diskread_prev = $diskread; + &minmaxavg("HOUR","1Reads",$diskread_val); + } + if ($diskwrite_prev < $diskwrite or $diskwrite eq "") { + push @t,undef; + $diskwrite_prev = $diskwrite; + } else { + my $diskwrite_val = ($diskwrite_prev - $diskwrite) / 60; + push @t,$diskwrite_val; + $diskwrite_prev = $diskwrite; + &minmaxavg("HOUR","2Writes",$diskwrite_val); + } + } + } + if ($minmaxavg{HOUR}{"1Reads"}{CNT} > 0) {$minmaxavg{HOUR}{"1Reads"}{AVG} /= $minmaxavg{HOUR}{"1Reads"}{CNT}} + if ($minmaxavg{HOUR}{"2Writes"}{CNT} > 0) {$minmaxavg{HOUR}{"2Writes"}{AVG} /= $minmaxavg{HOUR}{"2Writes"}{CNT}} + my @data = ([reverse @h],[reverse @p],[reverse @t]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred) ] ); + $hour_graph->set( + x_label => 'Minute', + y_label => 'IO/Second', + x_label_skip => 3, + title => 'Disk Usage in last hour', + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend( qw(Reads Writes)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemhour.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "disk") { + my (@h,@p,@t); + my $diskread_prev; + my $diskwrite_prev; + for (my $mins = 0; $mins < 1440;$mins++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($mins * 60)); + push @h,$hour; + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$min}); + if ($time eq "" or $diskread eq "") { + $diskread_prev = 0; + $diskwrite_prev = 0; + push @p,undef; + push @t,undef; + } else { + if ($diskread_prev < $diskread or $diskread eq "") { + push @p,undef; + $diskread_prev = $diskread; + } else { + my $diskread_val = ($diskread_prev - $diskread) / 60; + push @p,$diskread_val; + $diskread_prev = $diskread; + &minmaxavg("DAY","1Reads",$diskread_val); + } + if ($diskwrite_prev < $diskwrite or $diskwrite eq "") { + push @t,undef; + $diskwrite_prev = $diskwrite; + } else { + my $diskwrite_val = ($diskwrite_prev - $diskwrite) / 60; + push @t,$diskwrite_val; + $diskwrite_prev = $diskwrite; + &minmaxavg("DAY","2Writes",$diskwrite_val); + } + } + } + if ($minmaxavg{DAY}{"1Reads"}{CNT} > 0) {$minmaxavg{DAY}{"1Reads"}{AVG} /= $minmaxavg{DAY}{"1Reads"}{CNT}} + if ($minmaxavg{DAY}{"2Writes"}{CNT} > 0) {$minmaxavg{DAY}{"2Writes"}{AVG} /= $minmaxavg{DAY}{"2Writes"}{CNT}} + my @data = ([reverse @h],[reverse @p],[reverse @t]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred) ] ); + $hour_graph->set( + x_label => 'Hour', + y_label => 'IO/Second', + x_label_skip => 60, + title => 'Disk Usage in last 24 hours', + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend( qw(Reads Writes)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemday.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "disk") { + my (@h,@p,@t); + my $diskread_prev; + my $diskwrite_prev; + for (my $hours = 0; $hours < 168;$hours++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($hours * 60 * 60)); + push @h,$mday; + my $diskread_avg; + my $diskwrite_avg; + for (my $mins = 59; $mins >= 0;$mins--) { + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$mins}); + if ($time eq "" or $diskread eq "") { + $diskread_prev = 0; + $diskwrite_prev = 0; + } else { + if ($diskread_prev < $diskread or $diskread eq "") { + $diskread_prev = $diskread; + } else { + $diskread_avg = $diskread_avg + ($diskread_prev - $diskread)/60; + $diskread_prev = $diskread; + } + if ($diskwrite_prev < $diskwrite or $diskwrite eq "") { + $diskwrite_prev = $diskwrite; + } else { + $diskwrite_avg = $diskwrite_avg + ($diskwrite_prev - $diskwrite)/60; + $diskwrite_prev = $diskwrite; + } + } + } + unless (defined $diskread_avg) { + push @p,undef; + } else { + push @p,($diskread_avg/60); + &minmaxavg("WEEK","1Reads",($diskread_avg/60)); + } + unless (defined $diskwrite_avg) { + push @t,undef; + } else { + push @t,($diskwrite_avg/60); + &minmaxavg("WEEK","2Writes",($diskwrite_avg/60)); + } + } + if ($minmaxavg{WEEK}{"1Reads"}{CNT} > 0) {$minmaxavg{WEEK}{"1Reads"}{AVG} /= $minmaxavg{WEEK}{"1Reads"}{CNT}} + if ($minmaxavg{WEEK}{"2Writes"}{CNT} > 0) {$minmaxavg{WEEK}{"2Writes"}{AVG} /= $minmaxavg{WEEK}{"2Writes"}{CNT}} + my @data = ([reverse @h],[reverse @p],[reverse @t]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred) ] ); + $hour_graph->set( + x_label => 'Day (Hourly Average)', + y_label => 'IO/Second', + x_label_skip => 24, + title => 'Disk Usage in last 7 days', + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend( qw(Reads Writes)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemweek.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "disk") { + my (@h,@p,@t); + my $diskread_prev; + my $diskwrite_prev; + for (my $hours = 0; $hours < (24 * $system_maxdays);$hours++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($hours * 60 * 60)); + push @h,$mday; + my $diskread_avg; + my $diskwrite_avg; + for (my $mins = 59; $mins >= 0;$mins--) { + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$mins}); + if ($time eq "" or $diskread eq "") { + $diskread_prev = 0; + $diskwrite_prev = 0; + } else { + if ($diskread_prev < $diskread or $diskread eq "") { + $diskread_prev = $diskread; + } else { + $diskread_avg = $diskread_avg + ($diskread_prev - $diskread)/60; + $diskread_prev = $diskread; + } + if ($diskwrite_prev < $diskwrite or $diskwrite eq "") { + $diskwrite_prev = $diskwrite; + } else { + $diskwrite_avg = $diskwrite_avg + ($diskwrite_prev - $diskwrite)/60; + $diskwrite_prev = $diskwrite; + } + } + } + unless (defined $diskread_avg) { + push @p,undef; + } else { + push @p,($diskread_avg/60); + &minmaxavg("MONTH","1Reads",($diskread_avg/60)); + } + unless (defined $diskwrite_avg) { + push @t,undef; + } else { + push @t,($diskwrite_avg/60); + &minmaxavg("MONTH","2Writes",($diskwrite_avg/60)); + } + } + if ($minmaxavg{MONTH}{"1Reads"}{CNT} > 0) {$minmaxavg{MONTH}{"1Reads"}{AVG} /= $minmaxavg{MONTH}{"1Reads"}{CNT}} + if ($minmaxavg{MONTH}{"2Writes"}{CNT} > 0) {$minmaxavg{MONTH}{"2Writes"}{AVG} /= $minmaxavg{MONTH}{"2Writes"}{CNT}} + my @data = ([reverse @h],[reverse @p],[reverse @t]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred) ] ); + $hour_graph->set( + x_label => 'Day (Hourly Average)', + y_label => 'IO/Second', + x_label_skip => 24, + title => "Disk Usage in last $system_maxdays days", + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend( qw(Reads Writes)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemmonth.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "email") { + my (@h,@p,@t); + for (my $mins = 0; $mins < 60;$mins++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($mins * 60)); + push @h,$min; + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$min}); + if ($time eq "" or $mailin eq "") { + push @p,undef; + push @t,undef; + } else { + push @p,$mailin; + push @t,$mailout; + + &minmaxavg("HOUR","1Received",$mailin); + &minmaxavg("HOUR","2Sent",$mailout); + } + } + if ($minmaxavg{HOUR}{"1Received"}{CNT} > 0) {$minmaxavg{HOUR}{"1Received"}{AVG} /= $minmaxavg{HOUR}{"1Received"}{CNT}} + if ($minmaxavg{HOUR}{"2Sent"}{CNT} > 0) {$minmaxavg{HOUR}{"2Sent"}{AVG} /= $minmaxavg{HOUR}{"2Sent"}{CNT}} + my @data = ([reverse @h],[reverse @p],[reverse @t]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred) ] ); + $hour_graph->set( + x_label => 'Minute', + y_label => 'Emails', + x_label_skip => 3, + title => 'Email Usage in last hour', + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend( qw(Received Sent)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemhour.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "email") { + my (@h,@p,@t); + for (my $mins = 0; $mins < 1440;$mins++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($mins * 60)); + push @h,$hour; + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$min}); + if ($time eq "" or $mailin eq "") { + push @p,undef; + push @t,undef; + } else { + push @p,$mailin; + push @t,$mailout; + + &minmaxavg("DAY","1Received",$mailin); + &minmaxavg("DAY","2Sent",$mailout); + } + } + if ($minmaxavg{DAY}{"1Received"}{CNT} > 0) {$minmaxavg{DAY}{"1Received"}{AVG} /= $minmaxavg{DAY}{"1Received"}{CNT}} + if ($minmaxavg{DAY}{"2Sent"}{CNT} > 0) {$minmaxavg{DAY}{"2Sent"}{AVG} /= $minmaxavg{DAY}{"2Sent"}{CNT}} + my @data = ([reverse @h],[reverse @p],[reverse @t]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred purple) ] ); + $hour_graph->set( + x_label => 'Hour', + y_label => 'Emails', + x_label_skip => 60, + title => 'Email Usage in last 24 hours', + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend( qw(Received Sent)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemday.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "email") { + my (@h,@p,@t); + for (my $hours = 0; $hours < 168;$hours++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($hours * 60 * 60)); + push @h,$mday; + my $mailin_avg; + my $mailout_avg; + my $cnt_avg = 0; + for (my $mins = 59; $mins >= 0;$mins--) { + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$mins}); + if ($time and $mailin ne "") { + $mailin_avg += $mailin; + $mailout_avg += $mailout; + $cnt_avg++; + } + } + unless (defined $cnt_avg) { + push @p,undef; + push @t,undef; + } else { + if ($cnt_avg == 0) {$cnt_avg = 1} + push @p,$mailin_avg/$cnt_avg; + push @t,$mailout_avg/$cnt_avg; + + &minmaxavg("WEEK","1Received",($mailin_avg/$cnt_avg)); + &minmaxavg("WEEK","2Sent",($mailout_avg/$cnt_avg)); + } + } + if ($minmaxavg{WEEK}{"1Received"}{CNT} > 0) {$minmaxavg{WEEK}{"1Received"}{AVG} /= $minmaxavg{WEEK}{"1Received"}{CNT}} + if ($minmaxavg{WEEK}{"2Sent"}{CNT} > 0) {$minmaxavg{WEEK}{"2Sent"}{AVG} /= $minmaxavg{WEEK}{"2Sent"}{CNT}} + my @data = ([reverse @h],[reverse @p],[reverse @t]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred) ] ); + $hour_graph->set( + x_label => 'Day (Hourly Average)', + y_label => 'Emails', + x_label_skip => 24, + title => 'Email Usage in last 7 days', + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend( qw(Received Sent)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemweek.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "email") { + my (@h,@p,@t); + for (my $hours = 0; $hours < (24 * $system_maxdays);$hours++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($hours * 60 * 60)); + push @h,$mday; + my $mailin_avg; + my $mailout_avg; + my $cnt_avg = 0; + for (my $mins = 59; $mins >= 0;$mins--) { + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$mins}); + if ($time and $mailin ne "") { + $mailin_avg += $mailin; + $mailout_avg += $mailout; + $cnt_avg++; + } + } + unless (defined $cnt_avg) { + push @p,undef; + push @t,undef; + } else { + if ($cnt_avg == 0) {$cnt_avg = 1} + push @p,$mailin_avg/$cnt_avg; + push @t,$mailout_avg/$cnt_avg; + + &minmaxavg("MONTH","1Received",($mailin_avg/$cnt_avg)); + &minmaxavg("MONTH","2Sent",($mailout_avg/$cnt_avg)); + } + } + if ($minmaxavg{MONTH}{"1Received"}{CNT} > 0) {$minmaxavg{MONTH}{"1Received"}{AVG} /= $minmaxavg{MONTH}{"1Received"}{CNT}} + if ($minmaxavg{MONTH}{"2Sent"}{CNT} > 0) {$minmaxavg{MONTH}{"2Sent"}{AVG} /= $minmaxavg{MONTH}{"2Sent"}{CNT}} + my @data = ([reverse @h],[reverse @p],[reverse @t]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred) ] ); + $hour_graph->set( + x_label => 'Day (Hourly Average)', + y_label => 'Emails', + x_label_skip => 24, + title => "Email Usage in last $system_maxdays", + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend( qw(Received Sent)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemmonth.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "temp") { + my (@h,@p); + for (my $mins = 0; $mins < 60;$mins++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($mins * 60)); + push @h,$min; + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$min}); + if ($time eq "" or $cputemp eq "") { + push @p,undef; + } else { + push @p,$cputemp; + + &minmaxavg("HOUR","1CPU",$cputemp); + } + } + if ($minmaxavg{HOUR}{"1CPU"}{CNT} > 0) {$minmaxavg{HOUR}{"1CPU"}{AVG} /= $minmaxavg{HOUR}{"1CPU"}{CNT}} + my @data = ([reverse @h],[reverse @p]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred) ] ); + $hour_graph->set( + x_label => 'Minute', + y_label => 'Centigrade', + x_label_skip => 3, + title => 'CPU Temp in last hour', + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend("Highest Core Temperature"); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemhour.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "temp") { + my (@h,@p); + for (my $mins = 0; $mins < 1440;$mins++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($mins * 60)); + push @h,$hour; + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$min}); + if ($time eq "" or $cputemp eq "") { + push @p,undef; + } else { + push @p,$cputemp; + + &minmaxavg("DAY","1CPU",$cputemp); + } + } + if ($minmaxavg{DAY}{"1CPU"}{CNT} > 0) {$minmaxavg{DAY}{"1CPU"}{AVG} /= $minmaxavg{DAY}{"1CPU"}{CNT}} + my @data = ([reverse @h],[reverse @p]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred purple) ] ); + $hour_graph->set( + x_label => 'Hour', + y_label => 'Centigrade', + x_label_skip => 60, + title => 'CPU Temp in last 24 hours', + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend("Highest Core Temperature"); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemday.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "temp") { + my (@h,@p); + for (my $hours = 0; $hours < 168;$hours++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($hours * 60 * 60)); + push @h,$mday; + my $cputemp_avg; + my $cnt_avg = 0; + for (my $mins = 59; $mins >= 0;$mins--) { + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$mins}); + if ($time and $cputemp ne "") { + $cputemp_avg += $cputemp; + $cnt_avg++; + } + } + unless (defined $cnt_avg) { + push @p,undef; + } else { + if ($cnt_avg == 0) {$cnt_avg = 1} + push @p,$cputemp_avg/$cnt_avg; + + &minmaxavg("WEEK","1CPU",($cputemp_avg/$cnt_avg)); + } + } + if ($minmaxavg{WEEK}{"1CPU"}{CNT} > 0) {$minmaxavg{WEEK}{"1CPU"}{AVG} /= $minmaxavg{WEEK}{"1CPU"}{CNT}} + my @data = ([reverse @h],[reverse @p]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred) ] ); + $hour_graph->set( + x_label => 'Day (Hourly Average)', + y_label => 'Centigrade', + x_label_skip => 24, + title => 'CPU Temp in last 7 days', + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend("Highest Core Temperature"); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemweek.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "temp") { + my (@h,@p); + for (my $hours = 0; $hours < (24 * $system_maxdays);$hours++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($hours * 60 * 60)); + push @h,$mday; + my $cputemp_avg; + my $cnt_avg = 0; + for (my $mins = 59; $mins >= 0;$mins--) { + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$mins}); + if ($time and $cputemp ne "") { + $cputemp_avg += $cputemp; + $cnt_avg++; + } + } + unless (defined $cnt_avg) { + push @p,undef; + } else { + if ($cnt_avg == 0) {$cnt_avg = 1} + push @p,$cputemp_avg/$cnt_avg; + + &minmaxavg("MONTH","1CPU",($cputemp_avg/$cnt_avg)); + } + } + if ($minmaxavg{MONTH}{"1CPU"}{CNT} > 0) {$minmaxavg{MONTH}{"1CPU"}{AVG} /= $minmaxavg{MONTH}{"1CPU"}{CNT}} + my @data = ([reverse @h],[reverse @p]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred) ] ); + $hour_graph->set( + x_label => 'Day (Hourly Average)', + y_label => 'Centigrade', + x_label_skip => 24, + title => "CPU Temp in last $system_maxdays days", + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend("Highest Core Temperature"); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemmonth.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "mysqldata") { + my (@h,@p,@t); + my $mysqlin_prev; + my $mysqlout_prev; + for (my $mins = 0; $mins < 60;$mins++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($mins * 60)); + push @h,$min; + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$min}); + if ($time eq "" or $mysqlin eq "") { + $mysqlin_prev = 0; + $mysqlout_prev = 0; + push @p,undef; + push @t,undef; + } else { + if ($mysqlin_prev < $mysqlin or $mysqlin eq "") { + push @p,undef; + $mysqlin_prev = $mysqlin; + } else { + my $mysqlin_val = ($mysqlin_prev - $mysqlin) / 60; + push @p,$mysqlin_val; + $mysqlin_prev = $mysqlin; + &minmaxavg("HOUR","1Inbound",$mysqlin_val); + } + if ($mysqlout_prev < $mysqlout or $mysqlout eq "") { + push @t,undef; + $mysqlout_prev = $mysqlout; + } else { + my $mysqlout_val = ($mysqlout_prev - $mysqlout) / 60; + push @t,$mysqlout_val; + $mysqlout_prev = $mysqlout; + &minmaxavg("HOUR","2Outbound",$mysqlout_val); + } + } + } + if ($minmaxavg{HOUR}{"1Inbound"}{CNT} > 0) {$minmaxavg{HOUR}{"1Inbound"}{AVG} /= $minmaxavg{HOUR}{"1Inbound"}{CNT}} + if ($minmaxavg{HOUR}{"2Outbound"}{CNT} > 0) {$minmaxavg{HOUR}{"2Outbound"}{AVG} /= $minmaxavg{HOUR}{"2Outbound"}{CNT}} + my @data = ([reverse @h],[reverse @p],[reverse @t]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred) ] ); + $hour_graph->set( + x_label => 'Minute', + y_label => 'Bytes/Second', + x_label_skip => 3, + title => 'MySQL Data in last hour', + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend( qw(Inbound Outbound)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemhour.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "mysqldata") { + my (@h,@p,@t); + my $mysqlin_prev; + my $mysqlout_prev; + for (my $mins = 0; $mins < 1440;$mins++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($mins * 60)); + push @h,$hour; + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$min}); + if ($time eq "" or $mysqlin eq "") { + $mysqlin_prev = 0; + $mysqlout_prev = 0; + push @p,undef; + push @t,undef; + } else { + if ($mysqlin_prev < $mysqlin or $mysqlin eq "") { + push @p,undef; + $mysqlin_prev = $mysqlin; + } else { + my $mysqlin_val = ($mysqlin_prev - $mysqlin) / 60; + push @p,$mysqlin_val; + $mysqlin_prev = $mysqlin; + &minmaxavg("DAY","1Inbound",$mysqlin_val); + } + if ($mysqlout_prev < $mysqlout or $mysqlout eq "") { + push @t,undef; + $mysqlout_prev = $mysqlout; + } else { + my $mysqlout_val = ($mysqlout_prev - $mysqlout) / 60; + push @t,$mysqlout_val; + $mysqlout_prev = $mysqlout; + &minmaxavg("DAY","2Outbound",$mysqlout_val); + } + } + } + if ($minmaxavg{DAY}{"1Inbound"}{CNT} > 0) {$minmaxavg{DAY}{"1Inbound"}{AVG} /= $minmaxavg{DAY}{"1Inbound"}{CNT}} + if ($minmaxavg{DAY}{"2Outbound"}{CNT} > 0) {$minmaxavg{DAY}{"2Outbound"}{AVG} /= $minmaxavg{DAY}{"2Outbound"}{CNT}} + my @data = ([reverse @h],[reverse @p],[reverse @t]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred) ] ); + $hour_graph->set( + x_label => 'Hour', + y_label => 'Bytes/Second', + x_label_skip => 60, + title => 'MySQL Data in last 24 hours', + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend( qw(Inbound Outbound)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemday.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "mysqldata") { + my (@h,@p,@t); + my $mysqlin_prev; + my $mysqlout_prev; + for (my $hours = 0; $hours < 168;$hours++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($hours * 60 * 60)); + push @h,$mday; + my $mysqlin_avg; + my $mysqlout_avg; + for (my $mins = 59; $mins >= 0;$mins--) { + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$mins}); + if ($time eq "" or $mysqlin eq "") { + $mysqlin_prev = 0; + $mysqlout_prev = 0; + } else { + if ($mysqlin_prev < $mysqlin or $mysqlin eq "") { + $mysqlin_prev = $mysqlin; + } else { + my $mysqlin_val = ($mysqlin_prev - $mysqlin) / 60; + $mysqlin_avg = $mysqlin_avg + $mysqlin_val; + $mysqlin_prev = $mysqlin; + } + if ($mysqlout_prev < $mysqlout or $mysqlout eq "") { + $mysqlout_prev = $mysqlout; + } else { + my $mysqlout_val = ($mysqlout_prev - $mysqlout) / 60; + $mysqlout_avg = $mysqlout_avg + $mysqlout_val; + $mysqlout_prev = $mysqlout; + } + } + } + unless (defined $mysqlin_avg) { + push @p,undef; + } else { + push @p,($mysqlin_avg/60); + &minmaxavg("WEEK","1Inbound",($mysqlin_avg/60)); + } + unless (defined $mysqlout_avg) { + push @t,undef; + } else { + push @t,($mysqlout_avg/60); + &minmaxavg("WEEK","2Outbound",($mysqlout_avg/60)); + } + } + if ($minmaxavg{WEEK}{"1Inbound"}{CNT} > 0) {$minmaxavg{WEEK}{"1Inbound"}{AVG} /= $minmaxavg{WEEK}{"1Inbound"}{CNT}} + if ($minmaxavg{WEEK}{"2Outbound"}{CNT} > 0) {$minmaxavg{WEEK}{"2Outbound"}{AVG} /= $minmaxavg{WEEK}{"2Outbound"}{CNT}} + my @data = ([reverse @h],[reverse @p],[reverse @t]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred) ] ); + $hour_graph->set( + x_label => 'Day (Hourly Average)', + y_label => 'Bytes/Second', + x_label_skip => 24, + title => 'MySQL Data in last 7 days', + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend( qw(Inbound Outbound)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemweek.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "mysqldata") { + my (@h,@p,@t); + my $mysqlin_prev; + my $mysqlout_prev; + for (my $hours = 0; $hours < (24 * $system_maxdays);$hours++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($hours * 60 * 60)); + push @h,$mday; + my $mysqlin_avg; + my $mysqlout_avg; + for (my $mins = 59; $mins >= 0;$mins--) { + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$mins}); + if ($time eq "" or $mysqlin eq "") { + $mysqlin_prev = 0; + $mysqlout_prev = 0; + } else { + if ($mysqlin_prev < $mysqlin or $mysqlin eq "") { + $mysqlin_prev = $mysqlin; + } else { + my $mysqlin_val = ($mysqlin_prev - $mysqlin) / 60; + $mysqlin_avg = $mysqlin_avg + $mysqlin_val; + $mysqlin_prev = $mysqlin; + } + if ($mysqlout_prev < $mysqlout or $mysqlout eq "") { + $mysqlout_prev = $mysqlout; + } else { + my $mysqlout_val = ($mysqlout_prev - $mysqlout) / 60; + $mysqlout_avg = $mysqlout_avg + $mysqlout_val; + $mysqlout_prev = $mysqlout; + } + } + } + unless (defined $mysqlin_avg) { + push @p,undef; + } else { + push @p,($mysqlin_avg/60); + &minmaxavg("MONTH","1Inbound",($mysqlin_avg/60)); + } + unless (defined $mysqlout_avg) { + push @t,undef; + } else { + push @t,($mysqlout_avg/60); + &minmaxavg("MONTH","2Outbound",($mysqlout_avg/60)); + } + } + if ($minmaxavg{MONTH}{"1Inbound"}{CNT} > 0) {$minmaxavg{MONTH}{"1Inbound"}{AVG} /= $minmaxavg{MONTH}{"1Inbound"}{CNT}} + if ($minmaxavg{MONTH}{"2Outbound"}{CNT}) {$minmaxavg{MONTH}{"2Outbound"}{AVG} /= $minmaxavg{MONTH}{"2Outbound"}{CNT}} + my @data = ([reverse @h],[reverse @p],[reverse @t]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred) ] ); + $hour_graph->set( + x_label => 'Day (Hourly Average)', + y_label => 'Bytes/Second', + x_label_skip => 24, + title => "MySQL Data in last $system_maxdays days", + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend( qw(Inbound Outbound)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemmonth.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "mysqlqueries") { + my (@h,@p,@t); + my $mysqlq_prev; + my $mysqlsq_prev; + for (my $mins = 0; $mins < 60;$mins++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($mins * 60)); + push @h,$min; + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$min}); + if ($time eq "" or $mysqlq eq "") { + $mysqlq_prev = 0; + push @p,undef; + } else { + if ($mysqlq_prev < $mysqlq or $mysqlq eq "") { + push @p,undef; + $mysqlq_prev = $mysqlq; + } else { + my $mysqlq_val = ($mysqlq_prev - $mysqlq); + push @p,$mysqlq_val; + $mysqlq_prev = $mysqlq; + &minmaxavg("HOUR","1Queries",$mysqlq_val); + } + } + } + if ($minmaxavg{HOUR}{"1Queries"}{CNT} > 0) {$minmaxavg{HOUR}{"1Queries"}{AVG} /= $minmaxavg{HOUR}{"1Queries"}{CNT}} + my @data = ([reverse @h],[reverse @p]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred) ] ); + $hour_graph->set( + x_label => 'Minute', + y_label => 'Queries', + x_label_skip => 3, + title => 'MySQL Queries in last hour', + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend( qw(Queries)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemhour.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "mysqlqueries") { + my (@h,@p,@t); + my $mysqlq_prev; + my $mysqlsq_prev; + for (my $mins = 0; $mins < 1440;$mins++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($mins * 60)); + push @h,$hour; + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$min}); + if ($time eq "" or $mysqlq eq "") { + $mysqlq_prev = 0; + push @p,undef; + } else { + if ($mysqlq_prev < $mysqlq or $mysqlq eq "") { + push @p,undef; + $mysqlq_prev = $mysqlq; + } else { + my $mysqlq_val = ($mysqlq_prev - $mysqlq); + push @p,$mysqlq_val; + $mysqlq_prev = $mysqlq; + &minmaxavg("DAY","1Queries",$mysqlq_val); + } + } + } + if ($minmaxavg{DAY}{"1Queries"}{CNT} > 0) {$minmaxavg{DAY}{"1Queries"}{AVG} /= $minmaxavg{DAY}{"1Queries"}{CNT}} + my @data = ([reverse @h],[reverse @p]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred) ] ); + $hour_graph->set( + x_label => 'Hour', + y_label => 'Queries', + x_label_skip => 60, + title => 'MySQL Queries in last 24 hours', + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend( qw(Queries)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemday.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "mysqlqueries") { + my (@h,@p,@t); + my $mysqlq_prev; + for (my $hours = 0; $hours < 168;$hours++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($hours * 60 * 60)); + push @h,$mday; + my $mysqlq_avg; + for (my $mins = 59; $mins >= 0;$mins--) { + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$mins}); + if ($time eq "" or $mysqlq eq "") { + $mysqlq_prev = 0; + } else { + if ($mysqlq_prev < $mysqlq or $mysqlq eq "") { + $mysqlq_prev = $mysqlq; + } else { + my $mysqlq_val = ($mysqlq_prev - $mysqlq); + $mysqlq_avg = $mysqlq_avg + $mysqlq_val; + $mysqlq_prev = $mysqlq; + } + } + } + unless (defined $mysqlq_avg) { + push @p,undef; + } else { + push @p,($mysqlq_avg/60); + &minmaxavg("WEEK","1Queries",($mysqlq_avg/60)); + } + } + if ($minmaxavg{WEEK}{"1Queries"}{CNT} > 0) {$minmaxavg{WEEK}{"1Queries"}{AVG} /= $minmaxavg{WEEK}{"1Queries"}{CNT}} + my @data = ([reverse @h],[reverse @p]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred) ] ); + $hour_graph->set( + x_label => 'Day (Hourly Average)', + y_label => 'Queries', + x_label_skip => 24, + title => 'MySQL Queries in last 7 days', + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend( qw(Queries)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemweek.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "mysqlqueries") { + my (@h,@p,@t); + my $mysqlq_prev; + for (my $hours = 0; $hours < (24 * $system_maxdays);$hours++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($hours * 60 * 60)); + push @h,$mday; + my $mysqlq_avg; + for (my $mins = 59; $mins >= 0;$mins--) { + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$mins}); + if ($time eq "" or $mysqlq eq "") { + $mysqlq_prev = 0; + } else { + if ($mysqlq_prev < $mysqlq or $mysqlq eq "") { + $mysqlq_prev = $mysqlq; + } else { + my $mysqlq_val = ($mysqlq_prev - $mysqlq); + $mysqlq_avg = $mysqlq_avg + $mysqlq_val; + $mysqlq_prev = $mysqlq; + } + } + } + unless (defined $mysqlq_avg) { + push @p,undef; + } else { + push @p,($mysqlq_avg/60); + &minmaxavg("MONTH","1Queries",($mysqlq_avg/60)); + } + } + if ($minmaxavg{MONTH}{"1Queries"}{CNT} > 0) {$minmaxavg{MONTH}{"1Queries"}{AVG} /= $minmaxavg{MONTH}{"1Queries"}{CNT}} + my @data = ([reverse @h],[reverse @p]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred) ] ); + $hour_graph->set( + x_label => 'Day (Hourly Average)', + y_label => 'Queries', + x_label_skip => 24, + title => "MySQL Queries in last $system_maxdays", + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend( qw(Queries)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemmonth.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "mysqlslowqueries") { + my (@h,@p,@t); + my $mysqlsq_prev; + for (my $mins = 0; $mins < 60;$mins++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($mins * 60)); + push @h,$min; + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$min}); + if ($time eq "" or $mysqlq eq "") { + $mysqlsq_prev = 0; + push @t,undef; + } else { + if ($mysqlsq_prev < $mysqlsq or $mysqlsq eq "") { + push @t,undef; + $mysqlsq_prev = $mysqlsq; + } else { + my $mysqlsq_val = ($mysqlsq_prev - $mysqlsq); + push @t,$mysqlsq_val; + $mysqlsq_prev = $mysqlsq; + &minmaxavg("HOUR","1Slow_Queries",$mysqlsq_val); + } + } + } + if ($minmaxavg{HOUR}{"1Slow_Queries"}{CNT} > 0) {$minmaxavg{HOUR}{"1Slow_Queries"}{AVG} /= $minmaxavg{HOUR}{"1Slow_Queries"}{CNT}} + my @data = ([reverse @h],[reverse @t]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred) ] ); + $hour_graph->set( + x_label => 'Minute', + y_label => 'Slow Queries', + x_label_skip => 3, + title => 'MySQL Slow Queries in last hour', + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend( qw(Slow_Queries)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemhour.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "mysqlslowqueries") { + my (@h,@p,@t); + my $mysqlsq_prev; + for (my $mins = 0; $mins < 1440;$mins++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($mins * 60)); + push @h,$hour; + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$min}); + if ($time eq "" or $mysqlq eq "") { + $mysqlsq_prev = 0; + push @t,undef; + } else { + if ($mysqlsq_prev < $mysqlsq or $mysqlsq eq "") { + push @t,undef; + $mysqlsq_prev = $mysqlsq; + } else { + my $mysqlsq_val = ($mysqlsq_prev - $mysqlsq); + push @t,$mysqlsq_val; + $mysqlsq_prev = $mysqlsq; + &minmaxavg("DAY","1Slow_Queries",$mysqlsq_val); + } + } + } + if ($minmaxavg{DAY}{"1Slow_Queries"}{CNT} > 0) {$minmaxavg{DAY}{"1Slow_Queries"}{AVG} /= $minmaxavg{DAY}{"1Slow_Queries"}{CNT}} + my @data = ([reverse @h],[reverse @t]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred) ] ); + $hour_graph->set( + x_label => 'Hour', + y_label => 'Slow Queries', + x_label_skip => 60, + title => 'MySQL Slow Queries in last 24 hours', + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend( qw(Slow_Queries)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemday.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "mysqlslowqueries") { + my (@h,@p,@t); + my $mysqlsq_prev; + for (my $hours = 0; $hours < 168;$hours++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($hours * 60 * 60)); + push @h,$mday; + my $mysqlsq_avg; + for (my $mins = 59; $mins >= 0;$mins--) { + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$mins}); + if ($time eq "" or $mysqlsq eq "") { + $mysqlsq_prev = 0; + } else { + if ($mysqlsq_prev < $mysqlsq or $mysqlsq eq "") { + $mysqlsq_prev = $mysqlsq; + } else { + my $mysqlsq_val = ($mysqlsq_prev - $mysqlsq); + $mysqlsq_avg = $mysqlsq_avg + $mysqlsq_val; + $mysqlsq_prev = $mysqlsq; + } + } + } + unless (defined $mysqlsq_avg) { + push @t,undef; + } else { + push @t,($mysqlsq_avg/60); + &minmaxavg("WEEK","1Slow_Queries",($mysqlsq_avg/60)); + } + } + if ($minmaxavg{WEEK}{"1Slow_Queries"}{CNT} > 0) {$minmaxavg{WEEK}{"1Slow_Queries"}{AVG} /= $minmaxavg{WEEK}{"1Slow_Queries"}{CNT}} + my @data = ([reverse @h],[reverse @t]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred) ] ); + $hour_graph->set( + x_label => 'Day (Hourly Average)', + y_label => 'Slow Queries', + x_label_skip => 24, + title => 'MySQL Slow Queries in last 7 days', + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend( qw(Slow_Queries)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemweek.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "mysqlslowqueries") { + my (@h,@p,@t); + my $mysqlsq_prev; + for (my $hours = 0; $hours < (24 * $system_maxdays);$hours++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($hours * 60 * 60)); + push @h,$mday; + my $mysqlsq_avg; + for (my $mins = 59; $mins >= 0;$mins--) { + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$mins}); + if ($time eq "" or $mysqlsq eq "") { + $mysqlsq_prev = 0; + } else { + if ($mysqlsq_prev < $mysqlsq or $mysqlsq eq "") { + $mysqlsq_prev = $mysqlsq; + } else { + my $mysqlsq_val = ($mysqlsq_prev - $mysqlsq); + $mysqlsq_avg = $mysqlsq_avg + $mysqlsq_val; + $mysqlsq_prev = $mysqlsq; + } + } + } + unless (defined $mysqlsq_avg) { + push @t,undef; + } else { + push @t,($mysqlsq_avg/60); + &minmaxavg("MONTH","1Slow_Queries",($mysqlsq_avg/60)); + } + } + if ($minmaxavg{MONTH}{"1Slow_Queries"}{CNT} > 0) {$minmaxavg{MONTH}{"1Slow_Queries"}{AVG} /= $minmaxavg{MONTH}{"1Slow_Queries"}{CNT}} + my @data = ([reverse @h],[reverse @t]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred) ] ); + $hour_graph->set( + x_label => 'Day (Hourly Average)', + y_label => 'Slow Queries', + x_label_skip => 24, + title => "MySQL Slow Queries in last $system_maxdays", + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend( qw(Slow_Queries)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemmonth.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "mysqlconns") { + my (@h,@p,@t); + my $mysqlcn_prev; + for (my $mins = 0; $mins < 60;$mins++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($mins * 60)); + push @h,$min; + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$min}); + if ($time eq "" or $mysqlq eq "") { + $mysqlcn_prev = 0; + push @p,undef; + push @t,undef; + } else { + if ($mysqlcn_prev < $mysqlcn or $mysqlcn eq "") { + push @p,undef; + $mysqlcn_prev = $mysqlcn; + } else { + my $mysqlcn_val = ($mysqlcn_prev - $mysqlcn); + push @p,$mysqlcn_val; + $mysqlcn_prev = $mysqlcn; + &minmaxavg("HOUR","1Connections",$mysqlcn_val); + } + if ($mysqlth eq "") { + push @t,undef; + } else { + push @t,$mysqlth; + &minmaxavg("HOUR","2Threads",$mysqlth); + } + } + } + if ($minmaxavg{HOUR}{"1Connections"}{CNT} > 0) {$minmaxavg{HOUR}{"1Connections"}{AVG} /= $minmaxavg{HOUR}{"1Connections"}{CNT}} + if ($minmaxavg{HOUR}{"2Threads"}{CNT} > 0) {$minmaxavg{HOUR}{"2Threads"}{AVG} /= $minmaxavg{HOUR}{"2Threads"}{CNT}} + my @data = ([reverse @h],[reverse @p],[reverse @t]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred) ] ); + $hour_graph->set( + x_label => 'Minute', + y_label => '', + x_label_skip => 3, + title => 'MySQL Connections & Threads in last hour', + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend( qw(Connections Threads)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemhour.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "mysqlconns") { + my (@h,@p,@t); + my $mysqlcn_prev; + for (my $mins = 0; $mins < 1440;$mins++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($mins * 60)); + push @h,$hour; + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$min}); + if ($time eq "" or $mysqlq eq "") { + $mysqlcn_prev = 0; + push @p,undef; + push @t,undef; + } else { + if ($mysqlcn_prev < $mysqlcn or $mysqlcn eq "") { + push @p,undef; + $mysqlcn_prev = $mysqlcn; + } else { + my $mysqlcn_val = ($mysqlcn_prev - $mysqlcn); + push @p,$mysqlcn_val; + $mysqlcn_prev = $mysqlcn; + &minmaxavg("DAY","1Connections",$mysqlcn_val); + } + if ($mysqlth eq "") { + push @t,undef; + } else { + push @t,$mysqlth; + &minmaxavg("DAY","2Threads",$mysqlth); + } + } + } + if ($minmaxavg{DAY}{"1Connections"}{CNT} > 0) {$minmaxavg{DAY}{"1Connections"}{AVG} /= $minmaxavg{DAY}{"1Connections"}{CNT}} + if ($minmaxavg{DAY}{"2Threads"}{CNT} > 0) {$minmaxavg{DAY}{"2Threads"}{AVG} /= $minmaxavg{DAY}{"2Threads"}{CNT}} + my @data = ([reverse @h],[reverse @p],[reverse @t]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred) ] ); + $hour_graph->set( + x_label => 'Hour', + y_label => '', + x_label_skip => 60, + title => 'MySQL Connections & Threads in last 24 hours', + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend( qw(Connections Threads)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemday.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "mysqlconns") { + my (@h,@p,@t); + my $mysqlcn_prev; + for (my $hours = 0; $hours < 168;$hours++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($hours * 60 * 60)); + push @h,$mday; + my $mysqlcn_avg; + my $mysqlth_avg; + for (my $mins = 59; $mins >= 0;$mins--) { + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$mins}); + if ($time eq "" or $mysqlq eq "") { + $mysqlcn_prev = 0; + } else { + if ($mysqlcn_prev < $mysqlcn or $mysqlcn eq "") { + $mysqlcn_prev = $mysqlcn; + } else { + my $mysqlcn_val = ($mysqlcn_prev - $mysqlcn); + $mysqlcn_avg = $mysqlcn_avg + $mysqlcn_val; + $mysqlcn_prev = $mysqlcn; + } + $mysqlth_avg = $mysqlth_avg + $mysqlth; + } + } + unless (defined $mysqlcn_avg) { + push @p,undef; + } else { + push @p,($mysqlcn_avg/60); + &minmaxavg("WEEK","1Connections",($mysqlcn_avg/60)); + } + unless (defined $mysqlth_avg) { + push @t,undef; + } else { + push @t,($mysqlth_avg/60); + &minmaxavg("WEEK","2Threads",($mysqlth_avg/60)); + } + } + if ($minmaxavg{WEEK}{"1Connections"}{CNT} > 0) {$minmaxavg{WEEK}{"1Connections"}{AVG} /= $minmaxavg{WEEK}{"1Connections"}{CNT}} + if ($minmaxavg{WEEK}{"2Threads"}{CNT} > 0) {$minmaxavg{WEEK}{"2Threads"}{AVG} /= $minmaxavg{WEEK}{"2Threads"}{CNT}} + my @data = ([reverse @h],[reverse @p],[reverse @t]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred) ] ); + $hour_graph->set( + x_label => 'Day (Hourly Average)', + y_label => '', + x_label_skip => 24, + title => 'MySQL Connections & Threads in last 7 days', + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend( qw(Connections Threads)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemweek.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "mysqlconns") { + my (@h,@p,@t); + my $mysqlcn_prev; + for (my $hours = 0; $hours < (24 * $system_maxdays);$hours++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($hours * 60 * 60)); + push @h,$mday; + my $mysqlcn_avg; + my $mysqlth_avg; + for (my $mins = 59; $mins >= 0;$mins--) { + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$mins}); + if ($time eq "" or $mysqlq eq "") { + $mysqlcn_prev = 0; + } else { + if ($mysqlcn_prev < $mysqlcn or $mysqlcn eq "") { + $mysqlcn_prev = $mysqlcn; + } else { + my $mysqlcn_val = ($mysqlcn_prev - $mysqlcn); + $mysqlcn_avg = $mysqlcn_avg + $mysqlcn_val; + $mysqlcn_prev = $mysqlcn; + } + $mysqlth_avg = $mysqlth_avg + $mysqlth; + } + } + unless (defined $mysqlcn_avg) { + push @p,undef; + } else { + push @p,($mysqlcn_avg/60); + &minmaxavg("MONTH","1Connections",($mysqlcn_avg/60)); + } + unless (defined $mysqlth_avg) { + push @t,undef; + } else { + push @t,($mysqlth_avg/60); + &minmaxavg("MONTH","2Threads",($mysqlth_avg/60)); + } + } + if ($minmaxavg{MONTH}{"1Connections"}{CNT} > 0) {$minmaxavg{MONTH}{"1Connections"}{AVG} /= $minmaxavg{MONTH}{"1Connections"}{CNT}} + if ($minmaxavg{MONTH}{"2Threads"}{CNT} > 0) {$minmaxavg{MONTH}{"2Threads"}{AVG} /= $minmaxavg{MONTH}{"2Threads"}{CNT}} + my @data = ([reverse @h],[reverse @p],[reverse @t]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred) ] ); + $hour_graph->set( + x_label => 'Day (Hourly Average)', + y_label => '', + x_label_skip => 24, + title => "MySQL Connections & Threads in last $system_maxdays days", + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend( qw(Connections Threads)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemmonth.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "apachecpu") { + my (@h,@p); + for (my $mins = 0; $mins < 60;$mins++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($mins * 60)); + push @h,$min; + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$min}); + if ($time eq "" or $apachecpu eq "") { + push @p,undef; + } else { + push @p,$apachecpu; + + &minmaxavg("HOUR","1Apache_CPU",$apachecpu); + } + } + if ($minmaxavg{HOUR}{"1Apache_CPU"}{CNT} > 0) {$minmaxavg{HOUR}{"1Apache_CPU"}{AVG} /= $minmaxavg{HOUR}{"1Apache_CPU"}{CNT}} + my @data = ([reverse @h],[reverse @p]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred) ] ); + $hour_graph->set( + x_label => 'Minute', + y_label => 'Percentage', + x_label_skip => 3, + title => 'Apache CPU Usage in last hour', + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend("Apache CPU"); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemhour.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "apachecpu") { + my (@h,@p); + for (my $mins = 0; $mins < 1440;$mins++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($mins * 60)); + push @h,$hour; + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$min}); + if ($time eq "" or $apachecpu eq "") { + push @p,undef; + } else { + push @p,$apachecpu; + + &minmaxavg("DAY","1Apache_CPU",$apachecpu); + } + } + if ($minmaxavg{DAY}{"1Apache_CPU"}{CNT} > 0) {$minmaxavg{DAY}{"1Apache_CPU"}{AVG} /= $minmaxavg{DAY}{"1Apache_CPU"}{CNT}} + my @data = ([reverse @h],[reverse @p]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred purple) ] ); + $hour_graph->set( + x_label => 'Hour', + y_label => 'Percentage', + x_label_skip => 60, + title => 'Apache CPU Usage in last 24 hours', + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend("Apache CPU"); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemday.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "apachecpu") { + my (@h,@p); + for (my $hours = 0; $hours < 168;$hours++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($hours * 60 * 60)); + push @h,$mday; + my $apachecpu_avg; + my $cnt_avg = 0; + for (my $mins = 59; $mins >= 0;$mins--) { + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$mins}); + if ($time and $apachecpu ne "") { + $apachecpu_avg += $apachecpu; + $cnt_avg++; + } + } + unless (defined $cnt_avg) { + push @p,undef; + } else { + if ($cnt_avg == 0) {$cnt_avg = 1} + push @p,$apachecpu_avg/$cnt_avg; + + &minmaxavg("WEEK","1Apache_CPU",($apachecpu_avg/$cnt_avg)); + } + } + if ($minmaxavg{WEEK}{"1Apache_CPU"}{CNT} > 0) {$minmaxavg{WEEK}{"1Apache_CPU"}{AVG} /= $minmaxavg{WEEK}{"1Apache_CPU"}{CNT}} + my @data = ([reverse @h],[reverse @p]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred) ] ); + $hour_graph->set( + x_label => 'Day (Hourly Average)', + y_label => 'Percentage', + x_label_skip => 24, + title => 'Apache CPU Usage in last 7 days', + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend("Apache CPU"); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemweek.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "apachecpu") { + my (@h,@p); + for (my $hours = 0; $hours < (24 * $system_maxdays);$hours++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($hours * 60 * 60)); + push @h,$mday; + my $apachecpu_avg; + my $cnt_avg = 0; + for (my $mins = 59; $mins >= 0;$mins--) { + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$mins}); + if ($time and $apachecpu ne "") { + $apachecpu_avg += $apachecpu; + $cnt_avg++; + } + } + unless (defined $cnt_avg) { + push @p,undef; + } else { + if ($cnt_avg == 0) {$cnt_avg = 1} + push @p,$apachecpu_avg/$cnt_avg; + + &minmaxavg("MONTH","1Apache_CPU",($apachecpu_avg/$cnt_avg)); + } + } + if ($minmaxavg{MONTH}{"1Apache_CPU"}{CNT} > 0) {$minmaxavg{MONTH}{"1Apache_CPU"}{AVG} /= $minmaxavg{MONTH}{"1Apache_CPU"}{CNT}} + my @data = ([reverse @h],[reverse @p]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred) ] ); + $hour_graph->set( + x_label => 'Day (Hourly Average)', + y_label => 'Percentage', + x_label_skip => 24, + title => "Apache CPU Usage in last $system_maxdays", + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend("Apache CPU"); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemmonth.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "apacheconn") { + my (@h,@p); + my $apacheacc_prev; + for (my $mins = 0; $mins < 60;$mins++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($mins * 60)); + push @h,$min; + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$min}); + if ($time eq "" or $apacheacc eq "") { + $apacheacc_prev = 0; + push @p,undef; + } else { + if ($apacheacc_prev < $apacheacc or $apacheacc eq "") { + push @p,undef; + $apacheacc_prev = $apacheacc; + } else { + my $apacheacc_val = ($apacheacc_prev - $apacheacc); + push @p,$apacheacc_val; + $apacheacc_prev = $apacheacc; + &minmaxavg("HOUR","1Connections",$apacheacc_val); + } + } + } + if ($minmaxavg{HOUR}{"1Connections"}{CNT} > 0) {$minmaxavg{HOUR}{"1Connections"}{AVG} /= $minmaxavg{HOUR}{"1Connections"}{CNT}} + my @data = ([reverse @h],[reverse @p]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred) ] ); + $hour_graph->set( + x_label => 'Minute', + y_label => '', + x_label_skip => 3, + title => 'Apache Connections in last hour', + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend( qw(Connections)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemhour.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "apacheconn") { + my (@h,@p,@t); + my $apacheacc_prev; + for (my $mins = 0; $mins < 1440;$mins++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($mins * 60)); + push @h,$hour; + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$min}); + if ($time eq "" or $apacheacc eq "") { + $apacheacc_prev = 0; + push @p,undef; + } else { + if ($apacheacc_prev < $apacheacc or $apacheacc eq "") { + push @p,undef; + $apacheacc_prev = $apacheacc; + } else { + my $apacheacc_val = ($apacheacc_prev - $apacheacc); + push @p,$apacheacc_val; + $apacheacc_prev = $apacheacc; + &minmaxavg("DAY","1Connections",$apacheacc_val); + } + } + } + if ($minmaxavg{DAY}{"1Connections"}{CNT} > 0) {$minmaxavg{DAY}{"1Connections"}{AVG} /= $minmaxavg{DAY}{"1Connections"}{CNT}} + my @data = ([reverse @h],[reverse @p]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred) ] ); + $hour_graph->set( + x_label => 'Hour', + y_label => '', + x_label_skip => 60, + title => 'Apache Connections in last 24 hours', + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend( qw(Connections)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemday.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "apacheconn") { + my (@h,@p,@t); + my $apacheacc_prev; + for (my $hours = 0; $hours < 168;$hours++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($hours * 60 * 60)); + push @h,$mday; + my $apacheacc_avg; + for (my $mins = 59; $mins >= 0;$mins--) { + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$mins}); + if ($time eq "" or $apacheacc eq "") { + $apacheacc_prev = 0; + } else { + if ($apacheacc_prev < $apacheacc or $apacheacc eq "") { + $apacheacc_prev = $apacheacc; + } else { + my $apacheacc_val = ($apacheacc_prev - $apacheacc); + $apacheacc_avg = $apacheacc_avg + $apacheacc_val; + $apacheacc_prev = $apacheacc; + } + } + } + unless (defined $apacheacc_avg) { + push @p,undef; + } else { + push @p,($apacheacc_avg/60); + &minmaxavg("WEEK","1Connections",($apacheacc_avg/60)); + } + } + if ($minmaxavg{WEEK}{"1Connections"}{CNT} > 0) {$minmaxavg{WEEK}{"1Connections"}{AVG} /= $minmaxavg{WEEK}{"1Connections"}{CNT}} + my @data = ([reverse @h],[reverse @p]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred) ] ); + $hour_graph->set( + x_label => 'Day (Hourly Average)', + y_label => '', + x_label_skip => 24, + title => 'Apache Connections in last 7 days', + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend( qw(Connections Threads)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemweek.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "apacheconn") { + my (@h,@p,@t); + my $apacheacc_prev; + for (my $hours = 0; $hours < (24 * $system_maxdays);$hours++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($hours * 60 * 60)); + push @h,$mday; + my $apacheacc_avg; + for (my $mins = 59; $mins >= 0;$mins--) { + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$mins}); + if ($time eq "" or $apacheacc eq "") { + $apacheacc_prev = 0; + } else { + if ($apacheacc_prev < $apacheacc or $apacheacc eq "") { + $apacheacc_prev = $apacheacc; + } else { + my $apacheacc_val = ($apacheacc_prev - $apacheacc); + $apacheacc_avg = $apacheacc_avg + $apacheacc_val; + $apacheacc_prev = $apacheacc; + } + } + } + unless (defined $apacheacc_avg) { + push @p,undef; + } else { + push @p,($apacheacc_avg/60); + &minmaxavg("MONTH","1Connections",($apacheacc_avg/60)); + } + } + if ($minmaxavg{MONTH}{"1Connections"}{CNT} > 0) {$minmaxavg{MONTH}{"1Connections"}{AVG} /= $minmaxavg{MONTH}{"1Connections"}{CNT}} + my @data = ([reverse @h],[reverse @p]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred) ] ); + $hour_graph->set( + x_label => 'Day (Hourly Average)', + y_label => '', + x_label_skip => 24, + title => "Apache Connections in last $system_maxdays", + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend( qw(Connections Threads)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemmonth.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "apachework") { + my (@h,@p,@t); + for (my $mins = 0; $mins < 60;$mins++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($mins * 60)); + push @h,$min; + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$min}); + if ($time eq "" or $apachebwork eq "") { + push @p,undef; + push @t,undef; + } else { + push @p,$apachebwork; + push @t,$apacheiwork; + + &minmaxavg("HOUR","1Busy",$apachebwork); + &minmaxavg("HOUR","2Idle",$apacheiwork); + } + } + if ($minmaxavg{HOUR}{"1Busy"}{CNT} > 0) {$minmaxavg{HOUR}{"1Busy"}{AVG} /= $minmaxavg{HOUR}{"1Busy"}{CNT}} + if ($minmaxavg{HOUR}{"2Idle"}{CNT} > 0) {$minmaxavg{HOUR}{"2Idle"}{AVG} /= $minmaxavg{HOUR}{"2Idle"}{CNT}} + my @data = ([reverse @h],[reverse @p],[reverse @t]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred) ] ); + $hour_graph->set( + x_label => 'Minute', + y_label => 'Workers', + x_label_skip => 3, + title => 'Apache Workers in last hour', + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend( qw(Busy Idle)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemhour.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "apachework") { + my (@h,@p,@t); + for (my $mins = 0; $mins < 1440;$mins++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($mins * 60)); + push @h,$hour; + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$min}); + if ($time eq "" or $apachebwork eq "") { + push @p,undef; + push @t,undef; + } else { + push @p,$apachebwork; + push @t,$apacheiwork; + + &minmaxavg("DAY","1Busy",$apachebwork); + &minmaxavg("DAY","2Idle",$apacheiwork); + } + } + if ($minmaxavg{DAY}{"1Busy"}{CNT} > 0) {$minmaxavg{DAY}{"1Busy"}{AVG} /= $minmaxavg{DAY}{"1Busy"}{CNT}} + if ($minmaxavg{DAY}{"2Idle"}{CNT} > 0) {$minmaxavg{DAY}{"2Idle"}{AVG} /= $minmaxavg{DAY}{"2Idle"}{CNT}} + my @data = ([reverse @h],[reverse @p],[reverse @t]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred purple) ] ); + $hour_graph->set( + x_label => 'Hour', + y_label => 'Workers', + x_label_skip => 60, + title => 'Apache Workers in last 24 hours', + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend( qw(Busy Idle)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemday.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "apachework") { + my (@h,@p,@t); + for (my $hours = 0; $hours < 168;$hours++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($hours * 60 * 60)); + push @h,$mday; + my $apachebwork_avg; + my $apacheiwork_avg; + my $cnt_avg = 0; + for (my $mins = 59; $mins >= 0;$mins--) { + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$mins}); + if ($time and $apachebwork ne "") { + $apachebwork_avg += $apachebwork; + $apacheiwork_avg += $apacheiwork; + $cnt_avg++; + } + } + unless (defined $cnt_avg) { + push @p,undef; + push @t,undef; + } else { + if ($cnt_avg == 0) {$cnt_avg = 1} + push @p,$apachebwork_avg/$cnt_avg; + push @t,$apacheiwork_avg/$cnt_avg; + + &minmaxavg("WEEK","1Busy",($apachebwork_avg/$cnt_avg)); + &minmaxavg("WEEK","2Idle",($apacheiwork_avg/$cnt_avg)); + } + } + if ($minmaxavg{WEEK}{"1Busy"}{CNT} > 0) {$minmaxavg{WEEK}{"1Busy"}{AVG} /= $minmaxavg{WEEK}{"1Busy"}{CNT}} + if ($minmaxavg{WEEK}{"2Idle"}{CNT} > 0) {$minmaxavg{WEEK}{"2Idle"}{AVG} /= $minmaxavg{WEEK}{"2Idle"}{CNT}} + my @data = ([reverse @h],[reverse @p],[reverse @t]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred) ] ); + $hour_graph->set( + x_label => 'Day (Hourly Average)', + y_label => 'Workers', + x_label_skip => 24, + title => 'Apache Workers in last 7 days', + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend( qw(Busy Idle)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemweek.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "apachework") { + my (@h,@p,@t); + for (my $hours = 0; $hours < (24 * $system_maxdays);$hours++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($hours * 60 * 60)); + push @h,$mday; + my $apachebwork_avg; + my $apacheiwork_avg; + my $cnt_avg = 0; + for (my $mins = 59; $mins >= 0;$mins--) { + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$mins}); + if ($time and $apachebwork ne "") { + $apachebwork_avg += $apachebwork; + $apacheiwork_avg += $apacheiwork; + $cnt_avg++; + } + } + unless (defined $cnt_avg) { + push @p,undef; + push @t,undef; + } else { + if ($cnt_avg == 0) {$cnt_avg = 1} + push @p,$apachebwork_avg/$cnt_avg; + push @t,$apacheiwork_avg/$cnt_avg; + + &minmaxavg("MONTH","1Busy",($apachebwork_avg/$cnt_avg)); + &minmaxavg("MONTH","2Idle",($apacheiwork_avg/$cnt_avg)); + } + } + if ($minmaxavg{MONTH}{"1Busy"}{CNT} > 0) {$minmaxavg{MONTH}{"1Busy"}{AVG} /= $minmaxavg{MONTH}{"1Busy"}{CNT}} + if ($minmaxavg{MONTH}{"2Idle"}{CNT} > 0) {$minmaxavg{MONTH}{"2Idle"}{AVG} /= $minmaxavg{MONTH}{"2Idle"}{CNT}} + my @data = ([reverse @h],[reverse @p],[reverse @t]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred) ] ); + $hour_graph->set( + x_label => 'Day (Hourly Average)', + y_label => 'Workers', + x_label_skip => 24, + title => "Apache Workers in last $system_maxdays", + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend( qw(Busy Idle)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemmonth.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + if ($type eq "diskw") { + my (@h,@p); + for (my $mins = 0; $mins < 60;$mins++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($mins * 60)); + push @h,$min; + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$min}); + if ($time eq "" or $diskw eq "") { + push @p,undef; + } else { + push @p,$diskw; + + &minmaxavg("HOUR","1Disk_Write",$diskw); + } + } + if ($minmaxavg{HOUR}{"1Disk_Write"}{CNT} > 0) {$minmaxavg{HOUR}{"1Disk_Write"}{AVG} /= $minmaxavg{HOUR}{"1Disk_Write"}{CNT}} + my @data = ([reverse @h],[reverse @p]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred) ] ); + $hour_graph->set( + x_label => 'Minute', + y_label => 'MB/s', + x_label_skip => 3, + title => 'Disk Write Performance in last hour', + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend("Disk_Write"); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemhour.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "diskw") { + my (@h,@p); + for (my $mins = 0; $mins < 1440;$mins++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($mins * 60)); + push @h,$hour; + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$min}); + if ($time eq "" or $diskw eq "") { + push @p,undef; + } else { + push @p,$diskw; + + &minmaxavg("DAY","1Disk_Write",$diskw); + } + } + if ($minmaxavg{DAY}{"1Disk_Write"}{CNT} > 0) {$minmaxavg{DAY}{"1Disk_Write"}{AVG} /= $minmaxavg{DAY}{"1Disk_Write"}{CNT}} + my @data = ([reverse @h],[reverse @p]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred purple) ] ); + $hour_graph->set( + x_label => 'Hour', + y_label => 'MB/s', + x_label_skip => 60, + title => 'Disk Write Performance in last 24 hours', + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend("Disk_Write"); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemday.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "diskw") { + my (@h,@p); + for (my $hours = 0; $hours < 168;$hours++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($hours * 60 * 60)); + push @h,$mday; + my $diskw_avg; + my $cnt_avg = 0; + for (my $mins = 59; $mins >= 0;$mins--) { + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$mins}); + if ($time and $diskw ne "") { + $diskw_avg += $diskw; + $cnt_avg++; + } + } + unless (defined $cnt_avg) { + push @p,undef; + } else { + if ($cnt_avg == 0) {$cnt_avg = 1} + push @p,$diskw_avg/$cnt_avg; + + &minmaxavg("WEEK","1Disk_Write",($diskw_avg/$cnt_avg)); + } + } + if ($minmaxavg{WEEK}{"1Disk_Write"}{CNT} > 0) {$minmaxavg{WEEK}{"1Disk_Write"}{AVG} /= $minmaxavg{WEEK}{"1Disk_Write"}{CNT}} + my @data = ([reverse @h],[reverse @p]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred) ] ); + $hour_graph->set( + x_label => 'Day (Hourly Average)', + y_label => 'MB/s', + x_label_skip => 24, + title => 'Disk Write Performance in last 7 days', + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend("Disk_Write"); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemweek.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + + if ($type eq "diskw") { + my (@h,@p); + for (my $hours = 0; $hours < (24 * $system_maxdays);$hours++) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time - ($hours * 60 * 60)); + push @h,$mday; + my $diskw_avg; + my $cnt_avg = 0; + for (my $mins = 59; $mins >= 0;$mins--) { + my ($time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load1,$load5,$load15,$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached) = split(/\,/,$stata{$year}{$mon}{$mday}{$hour}{$mins}); + if ($time and $diskw ne "") { + $diskw_avg += $diskw; + $cnt_avg++; + } + } + unless (defined $cnt_avg) { + push @p,undef; + } else { + if ($cnt_avg == 0) {$cnt_avg = 1} + push @p,$diskw_avg/$cnt_avg; + + &minmaxavg("MONTH","1Disk_Write",($diskw_avg/$cnt_avg)); + } + } + if ($minmaxavg{MONTH}{"1Disk_Write"}{CNT} > 0) {$minmaxavg{MONTH}{"1Disk_Write"}{AVG} /= $minmaxavg{MONTH}{"1Disk_Write"}{CNT}} + my @data = ([reverse @h],[reverse @p]); + my $hour_graph = GD::Graph::lines->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred) ] ); + $hour_graph->set( + x_label => 'Day (Hourly Average)', + y_label => 'MB/s', + x_label_skip => 24, + title => "Disk Write Performance in last $system_maxdays", + borderclrs => $hour_graph->{dclrs}, + transparent => 0, + ); + $hour_graph->set_legend("Disk_Write"); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_systemmonth.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + } + } + + return; +} +# end graphs +############################################################################### +# start charts +sub charts { + my $cc_lookups = shift; + my $imghddir = shift; + my $img; + $| = 1; + + require GD::Graph::bars; + import GD::Graph::bars; + require GD::Graph::pie; + import GD::Graph::pie; + require GD::Graph::lines; + import GD::Graph::lines; + + sysopen (my $STATS,"/var/lib/csf/stats/lfdstats", O_RDWR | O_CREAT); + flock ($STATS, LOCK_SH); + my @stats = <$STATS>; + chomp @stats; + close ($STATS); + + if (@stats) { + my $time = time; + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time); + + # Blocks by lfd in the last 24 hours + my $cnt = $hour + 1; + if ($cnt > 23) {$cnt = 0} + my (@h,@p,@t,@hp,@cp); + my %triggers; + for (my $hours = 0; $hours < 24;$hours++) { + push @h,$cnt; + my ($permdate,$permcount,$tempdate,$tempcount) = split(/\,/,$stats[$cnt]); + if ($time - $permdate > (24 * 60 * 60)) {$permdate = 0; $permcount = 0} + if ($time - $tempdate > (24 * 60 * 60)) {$tempdate = 0; $tempcount = 0} + push @p,$permcount; + push @t,$tempcount; + my @line = split(/\,/,$stats[$cnt]); + for (my $loop = 4; $loop < @line; $loop+=2) { + if ($time - $line[$loop] > (24 * 60 * 60)) {next} + my ($triggerstat,$triggercount) = split(/\:/,$line[$loop+1]); + $triggers{$triggerstat} += $triggercount; + } + $cnt++; + if ($cnt > 23) {$cnt = 0} + } + my @data = ([@h],[@p],[@t]); + my $hour_graph = GD::Graph::bars->new(750,350); + $hour_graph->set( dclrs => [ qw(yellow dred) ] ); + $hour_graph->set( + x_label => 'Hour', + y_label => 'Total Blocks', + long_ticks => 1, + tick_length => 0, + x_ticks => 0, + title => 'Blocks by lfd in the last 24 hours', + cumulate => 1, + borderclrs => $hour_graph->{dclrs}, + bar_spacing => 4, + shadow_depth => 1, + transparent => 0, + x_label_position => 1/2, + ); + $hour_graph->set_legend( qw(Permanent Temporary)); + $hour_graph->plot(\@data); + $img = $imghddir."lfd_hour.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $hour_graph->gd->gif(); + close ($OUT); + + foreach my $key (keys %triggers) { + push @hp, "$key ($triggers{$key})"; + push @cp, $triggers{$key}; + } + my @piedata = ([@hp],[@cp]); + my $hour_pie_graph = GD::Graph::pie->new( 400, 300 ); + $hour_pie_graph->set( + title => 'Block triggers in the last 24 hours', + label => 'Trigger in csf.conf', + axislabelclr => 'black', + pie_height => 36, + l_margin => 15, + r_margin => 15, + start_angle => 235, + transparent => 0, + ); + $hour_pie_graph->plot(\@piedata); + $img = $imghddir."lfd_pie_hour.gif"; + open (my $OUT2, ">", "$img"); + flock ($OUT2, LOCK_EX); + binmode ($OUT2); + print $OUT2 $hour_pie_graph->gd->gif(); + close ($OUT2); + + + # Blocks by lfd in the last 30 Days + my $maxdays = 30; + my ($hsec,$hmin,$hhour,$hmday,$hmon,$hyear,$hwday,$hyday,$hisdst) = localtime($time - (29 * 24 * 60 * 60)); + my $hdim = (31,28,31,30,31,30,31,31,30,31,30,31)[$hmon]; + if ($hmon == 1 && (($hyear % 4 == 0) && ($hyear % 100 != 0) && ($hyear % 400 == 0))) {$hdim++} + if ($hmon == 1) { + $maxdays = $hdim; + ($hsec,$hmin,$hhour,$hmday,$hmon,$hyear,$hwday,$hyday,$hisdst) = localtime($time - (($maxdays - 1) * 24 * 60 * 60)); + } + $cnt = $hmday; + my (@hh,@ph,@th,@hhp,@hcp); + my %htriggers; + for (my $days = 1; $days <= $maxdays;$days++) { + push @hh,$cnt; + my ($permdate,$permcount,$tempdate,$tempcount) = split(/\,/,$stats[$cnt+24]); + if ($time - $permdate > (($maxdays - 1) * 24 * 60 * 60)) {$permdate = 0; $permcount = 0} + if ($time - $tempdate > (($maxdays - 1) * 24 * 60 * 60)) {$tempdate = 0; $tempcount = 0} + push @ph,$permcount; + push @th,$tempcount; + my @line = split(/\,/,$stats[$cnt+24]); + for (my $loop = 4; $loop < @line; $loop+=2) { + if ($time - $line[$loop] > (($maxdays - 1) * 24 * 60 * 60)) {next} + my ($triggerstat,$triggercount) = split(/\:/,$line[$loop+1]); + $htriggers{$triggerstat} += $triggercount; + } + $cnt++; + if ($cnt > $hdim) {$cnt = 1} + } + my @datah = ([@hh],[@ph],[@th]); + my $day_graph = GD::Graph::bars->new(750,350); + $day_graph->set( dclrs => [ qw(yellow dred) ] ); + $day_graph->set( + x_label => 'Day', + y_label => 'Total Blocks', + long_ticks => 1, + tick_length => 0, + x_ticks => 0, + title => "Blocks by lfd in the last $maxdays Days", + cumulate => 1, + borderclrs => $day_graph->{dclrs}, + bar_spacing => 4, + shadow_depth => 1, + transparent => 0, + x_label_position => 1/2, + ); + $day_graph->set_legend( qw(Permanent Temporary)); + $day_graph->plot(\@datah); + $img = $imghddir."lfd_month.gif"; + open (my $OUT3, ">", "$img"); + flock ($OUT3, LOCK_EX); + binmode ($OUT3); + print $OUT3 $day_graph->gd->gif(); + close ($OUT3); + + foreach my $key (keys %htriggers) { + push @hhp, "$key ($htriggers{$key})"; + push @hcp, $htriggers{$key}; + } + my @hpiedata = ([@hhp],[@hcp]); + my $day_pie_graph = GD::Graph::pie->new( 400, 300 ); + $day_pie_graph->set( + title => "Block triggers in the last $maxdays days", + label => 'Trigger in csf.conf', + axislabelclr => 'black', + pie_height => 36, + l_margin => 15, + r_margin => 15, + start_angle => 235, + transparent => 0, + ); + $day_pie_graph->plot(\@hpiedata); + $img = $imghddir."lfd_pie_day.gif"; + open (my $OUT4, ">", "$img"); + flock ($OUT4, LOCK_EX); + binmode ($OUT4); + print $OUT4 $day_pie_graph->gd->gif(); + close ($OUT4); + + # Blocks by lfd in the last 12 months + $cnt = $mon + 2; + if ($cnt > 12) {$cnt = 1} + my (@hy,@py,@ty,@yhp,@ycp); + my %ytriggers; + for (my $months = 1; $months < 13;$months++) { + push @hy,$cnt; + my ($permdate,$permcount,$tempdate,$tempcount) = split(/\,/,$stats[$cnt+55]); + if ($time - $permdate > (364 * 24 * 60 * 60)) {$permdate = 0; $permcount = 0} + if ($time - $tempdate > (364 * 24 * 60 * 60)) {$tempdate = 0; $tempcount = 0} + push @py,$permcount; + push @ty,$tempcount; + my @line = split(/\,/,$stats[$cnt+55]); + for (my $loop = 4; $loop < @line; $loop+=2) { + if ($time - $line[$loop] > (364 * 24 * 60 * 60)) {next} + my ($triggerstat,$triggercount) = split(/\:/,$line[$loop+1]); + $ytriggers{$triggerstat} += $triggercount; + } + $cnt++; + if ($cnt > 12) {$cnt = 1} + } + my @datay = ([@hy],[@py],[@ty]); + my $year_graph = GD::Graph::bars->new(750,350); + $year_graph->set( dclrs => [ qw(yellow dred) ] ); + $year_graph->set( + x_label => 'Month', + y_label => 'Total Blocks', + long_ticks => 1, + tick_length => 0, + x_ticks => 0, + title => 'Blocks by lfd in the last 12 months', + cumulate => 1, + borderclrs => $year_graph->{dclrs}, + bar_spacing => 4, + shadow_depth => 1, + transparent => 0, + x_label_position => 1/2, + ); + $year_graph->set_legend( qw(Permanent Temporary)); + $year_graph->plot(\@datay); + $img = $imghddir."lfd_year.gif"; + open (my $OUT5, ">", "$img"); + flock ($OUT5, LOCK_EX); + binmode ($OUT5); + print $OUT5 $year_graph->gd->gif(); + close ($OUT5); + + foreach my $key (keys %ytriggers) { + push @yhp, "$key ($ytriggers{$key})"; + push @ycp, $ytriggers{$key}; + } + my @ypiedata = ([@yhp],[@ycp]); + my $year_pie_graph = GD::Graph::pie->new( 400, 300 ); + $year_pie_graph->set( + title => 'Block triggers in the last 12 months', + label => 'Trigger in csf.conf', + axislabelclr => 'black', + pie_height => 36, + l_margin => 15, + r_margin => 15, + start_angle => 235, + transparent => 0, + ); + $year_pie_graph->plot(\@ypiedata); + $img = $imghddir."lfd_pie_year.gif"; + open (my $OUT6, ">", "$img"); + flock ($OUT6, LOCK_EX); + binmode ($OUT6); + print $OUT6 $year_pie_graph->gd->gif(); + close ($OUT6); + + if ($cc_lookups) { + # Total Top 30 Country Code blocks by lfd + my (@ccy,@ccx); + my %ccs; + my $cntcc; + my @line = split(/\,/,$stats[69]); + for (my $x = 0; $x < @line; $x+=2) {$ccs{$line[$x]} = $line[$x+1]} + foreach my $key (sort {$ccs{$b} <=> $ccs{$a}} keys %ccs) { + push @ccy,$key; + push @ccx,$ccs{$key}; + $cntcc++; + if ($cntcc > 29) {last} + } + my @datacc = ([@ccy],[@ccx]); + my $cc_graph = GD::Graph::bars->new(750,350); + $cc_graph->set( dclrs => [ qw(yellow) ] ); + $cc_graph->set( + x_label => 'Country Code', + y_label => 'Total Blocks', + long_ticks => 1, + tick_length => 0, + x_ticks => 0, + title => 'Total Top 30 Country Code blocks by lfd', + cumulate => 1, + borderclrs => $cc_graph->{dclrs}, + bar_spacing => 4, + shadow_depth => 1, + transparent => 0, + x_label_position => 1/2, + ); + $cc_graph->plot(\@datacc); + $img = $imghddir."lfd_cc.gif"; + open (my $OUT, ">", "$img"); + flock ($OUT, LOCK_EX); + binmode ($OUT); + print $OUT $cc_graph->gd->gif(); + close ($OUT); + } + } + + return; +} +# end charts +############################################################################### +# start minmaxavg +sub minmaxavg { + my $graph = shift; + my $name = shift; + my $value = shift; + + unless (defined $minmaxavg{$graph}{$name}{MIN}) {$minmaxavg{$graph}{$name}{MIN} = $value} + unless (defined $minmaxavg{$graph}{$name}{MAX}) {$minmaxavg{$graph}{$name}{MAX} = $value} + if ($minmaxavg{$graph}{$name}{MIN} > $value) {$minmaxavg{$graph}{$name}{MIN} = $value} + if ($minmaxavg{$graph}{$name}{MAX} < $value) {$minmaxavg{$graph}{$name}{MAX} = $value} + $minmaxavg{$graph}{$name}{AVG} += $value; + $minmaxavg{$graph}{$name}{CNT}++; + + return; +} +# end minmaxavg +############################################################################### +# start graphs_html +sub graphs_html { + my $imgdir = shift; + my $html; + + $html .= "\n"; + $html .= "\n
\n"; + $html .= "


\n"; + foreach my $key (sort keys %{$minmaxavg{HOUR}}) { + my $item = $key; + if ($key =~ /^\d(.*)$/) {$item = $1} + $html .= ""; + $html .= ""; + $html .= ""; + $html .= "\n"; + } + $html .= "
$itemMin:".sprintf("%.2f",$minmaxavg{HOUR}{$key}{MIN})."Max:".sprintf("%.2f",$minmaxavg{HOUR}{$key}{MAX})."Avg:".sprintf("%.2f",$minmaxavg{HOUR}{$key}{AVG})."

Note: This graph displays per minute statistics unless otherwise stated
\n"; + $html .= "


\n"; + foreach my $key (sort keys %{$minmaxavg{DAY}}) { + my $item = $key; + if ($key =~ /^\d(.*)$/) {$item = $1} + $html .= ""; + $html .= ""; + $html .= ""; + $html .= "\n"; + } + $html .= "
$itemMin:".sprintf("%.2f",$minmaxavg{DAY}{$key}{MIN})."Max:".sprintf("%.2f",$minmaxavg{DAY}{$key}{MAX})."Avg:".sprintf("%.2f",$minmaxavg{DAY}{$key}{AVG})."

Note: This graph displays per minute statistics unless otherwise stated
\n"; + $html .= "


\n"; + foreach my $key (sort keys %{$minmaxavg{WEEK}}) { + my $item = $key; + if ($key =~ /^\d(.*)$/) {$item = $1} + $html .= ""; + $html .= ""; + $html .= ""; + $html .= "\n"; + } + $html .= "
$itemMin:".sprintf("%.2f",$minmaxavg{WEEK}{$key}{MIN})."Max:".sprintf("%.2f",$minmaxavg{WEEK}{$key}{MAX})."Avg:".sprintf("%.2f",$minmaxavg{WEEK}{$key}{AVG})."

Note: This graph displays an hourly average of the per minute statistics, so you will not see the peak minute values
\n"; + $html .= "


\n"; + foreach my $key (sort keys %{$minmaxavg{MONTH}}) { + my $item = $key; + if ($key =~ /^\d(.*)$/) {$item = $1} + $html .= ""; + $html .= ""; + $html .= ""; + $html .= "\n"; + } + $html .= "
$itemMin:".sprintf("%.2f",$minmaxavg{MONTH}{$key}{MIN})."Max:".sprintf("%.2f",$minmaxavg{MONTH}{$key}{MAX})."Avg:".sprintf("%.2f",$minmaxavg{MONTH}{$key}{AVG})."

Note: This graph displays an hourly average of the per minute statistics, so you will not see the peak minute values
\n"; + return $html; +} +# end graphs_html +############################################################################### +# start charts_html +sub charts_html { + my $cc_lookups = shift; + my $imgdir = shift; + my $html; + + $html .= "\n"; + $html .= "\n\n\n
\n"; + $html .= "

 

\n"; + $html .= "

\n"; + $html .= "
\n"; + $html .= "

 

\n"; + $html .= "

\n"; + if ($cc_lookups) { + $html .= "
\n"; + $html .= "

 

\n"; + $html .= "

\n"; + $html .= "
\n"; + $html .= "

\n"; + } else { + $html .= "
\n"; + $html .= "

 

\n"; + $html .= "

\n"; + } + $html .= "
\n"; + + return $html; +} +# end charts_html +############################################################################### + +1; \ No newline at end of file diff --git a/src/redux/ConfigServer/Service.pm b/src/redux/ConfigServer/Service.pm new file mode 100644 index 000000000..e679c2921 --- /dev/null +++ b/src/redux/ConfigServer/Service.pm @@ -0,0 +1,118 @@ +############################################################################### +# Copyright 2006-2023, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +## no critic (RequireUseWarnings, ProhibitExplicitReturnUndef, ProhibitMixedBooleanOperators, RequireBriefOpen) +# start main +package ConfigServer::Service; + +use strict; +use lib '/usr/local/csf/lib'; +use Carp; +use IPC::Open3; +use Fcntl qw(:DEFAULT :flock); +use ConfigServer::Config; + +use Exporter qw(import); +our $VERSION = 1.01; +our @ISA = qw(Exporter); +our @EXPORT_OK = qw(); + +my $config = ConfigServer::Config->loadconfig(); +my %config = $config->config(); + +open (my $IN, "<", "/proc/1/comm"); +flock ($IN, LOCK_SH); +my $sysinit = <$IN>; +close ($IN); +chomp $sysinit; +if ($sysinit ne "systemd") {$sysinit = "init"} + +# end main +############################################################################### +# start type +sub type { + return $sysinit; +} +# end type +############################################################################### +# start startlfd +sub startlfd { + if ($sysinit eq "systemd") { + &printcmd($config{SYSTEMCTL},"start","lfd.service"); + &printcmd($config{SYSTEMCTL},"status","lfd.service"); + } else { + &printcmd("/etc/init.d/lfd","start"); + } + + return; +} +# end startlfd +############################################################################### +# start stoplfd +sub stoplfd { + if ($sysinit eq "systemd") { + &printcmd($config{SYSTEMCTL},"stop","lfd.service"); + } + else { + &printcmd("/etc/init.d/lfd","stop"); + } + + return; +} +# end stoplfd +############################################################################### +# start restartlfd +sub restartlfd { + if ($sysinit eq "systemd") { + &printcmd($config{SYSTEMCTL},"restart","lfd.service"); + &printcmd($config{SYSTEMCTL},"status","lfd.service"); + } + else { + &printcmd("/etc/init.d/lfd","restart"); + } + + return; +} +# end restartlfd +############################################################################### +# start restartlfd +sub statuslfd { + if ($sysinit eq "systemd") { + &printcmd($config{SYSTEMCTL},"status","lfd.service"); + } + else { + &printcmd("/etc/init.d/lfd","status"); + } + + return 0 +} +# end restartlfd +############################################################################### +# start printcmd +sub printcmd { + my @command = @_; + + if ($config{DIRECTADMIN}) { + my $doublepid = fork; + if ($doublepid == 0) { + my ($childin, $childout); + my $pid = open3($childin, $childout, $childout, @command); + while (<$childout>) {print $_} + waitpid ($pid, 0); + exit; + } + waitpid ($doublepid, 0); + } else { + my ($childin, $childout); + my $pid = open3($childin, $childout, $childout, @command); + while (<$childout>) {print $_} + waitpid ($pid, 0); + } + return; +} +# end printcmd +############################################################################### + +1; \ No newline at end of file diff --git a/src/redux/ConfigServer/Slurp.pm b/src/redux/ConfigServer/Slurp.pm new file mode 100644 index 000000000..0772997ee --- /dev/null +++ b/src/redux/ConfigServer/Slurp.pm @@ -0,0 +1,55 @@ +############################################################################### +# Copyright 2006-2023, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +## no critic (RequireUseWarnings, ProhibitExplicitReturnUndef, ProhibitMixedBooleanOperators, RequireBriefOpen) +# start main +package ConfigServer::Slurp; + +use strict; +use lib '/usr/local/csf/lib'; +use Fcntl qw(:DEFAULT :flock); +use Carp; + +use Exporter qw(import); +our $VERSION = 1.02; +our @ISA = qw(Exporter); +our @EXPORT_OK = qw(slurp); + +our $slurpreg = qr/(?>\x0D\x0A?|[\x0A-\x0C\x85\x{2028}\x{2029}])/; +our $cleanreg = qr/(\r)|(\n)|(^\s+)|(\s+$)/; + +# end main +############################################################################### +# start slurp +sub slurp { + my $file = shift; + if (-e $file) { + sysopen (my $FILE, $file, O_RDONLY) or carp "*Error* Unable to open [$file]: $!"; + flock ($FILE, LOCK_SH) or carp "*Error* Unable to lock [$file]: $!"; + my $text = do {local $/; <$FILE>}; + close ($FILE); + return split(/$slurpreg/,$text); + } else { + carp "*Error* File does not exist: [$file]"; + } + + return; +} +# end slurp +############################################################################### +# start slurpreg +sub slurpreg { + return $slurpreg; +} +# end slurpreg +############################################################################### +# start cleanreg +sub cleanreg { + return $cleanreg; +} +# end cleanreg +############################################################################### + +1; \ No newline at end of file diff --git a/src/redux/ConfigServer/URLGet.pm b/src/redux/ConfigServer/URLGet.pm new file mode 100644 index 000000000..892c84b9f --- /dev/null +++ b/src/redux/ConfigServer/URLGet.pm @@ -0,0 +1,292 @@ +############################################################################### +# Copyright 2006-2023, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +## no critic (RequireUseWarnings, ProhibitExplicitReturnUndef, ProhibitMixedBooleanOperators, RequireBriefOpen) +# start main +package ConfigServer::URLGet; + +use strict; +use lib '/usr/local/csf/lib'; +use Fcntl qw(:DEFAULT :flock); +use Carp; +use IPC::Open3; +use ConfigServer::Config; + +use Exporter qw(import); +our $VERSION = 2.00; +our @ISA = qw(Exporter); +our @EXPORT_OK = qw(); + +my $agent = "ConfigServer"; +my $option = 1; +my $proxy = ""; + +my $config = ConfigServer::Config->loadconfig(); +my %config = $config->config(); +$SIG{PIPE} = 'IGNORE'; + +# end main +############################################################################### +# start new +sub new { + my $class = shift; + $option = shift; + $agent = shift; + $proxy = shift; + my $self = {}; + bless $self,$class; + + if ($option == 3) { + return $self; + } + elsif ($option == 2) { + eval ('use LWP::UserAgent;'); ##no critic + if ($@) {return undef} + } + else { + eval { + local $SIG{__DIE__} = undef; + eval ('use HTTP::Tiny;'); ##no critic + }; + } + + return $self; +} +# end new +############################################################################### +# start urlget +sub urlget { + my $self = shift; + my $url = shift; + my $file = shift; + my $quiet = shift; + my $status; + my $text; + + if (!defined $url) {carp "url not specified"; return} + + if ($option == 3) { + ($status, $text) = &binget($url,$file,$quiet); + } + elsif ($option == 2) { + ($status, $text) = &urlgetLWP($url,$file,$quiet); + } + else { + ($status, $text) = &urlgetTINY($url,$file,$quiet); + } + return ($status, $text); +} +# end urlget +############################################################################### +# start urlgetTINY +sub urlgetTINY { + my $url = shift; + my $file = shift; + my $quiet = shift; + my $status = 0; + my $timeout = 1200; + if ($proxy eq "") {undef $proxy} + my $ua = HTTP::Tiny->new( + 'agent' => $agent, + 'timeout' => 300, + 'proxy' => $proxy + ); + 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); + $res = $ua->request('GET', $url, { + data_callback => sub { + my($chunk, $res) = @_; + $bytes_received += length($chunk); + unless (defined $expected_length) {$expected_length = $res->{headers}->{'content-length'} || 0} + if ($expected_length) { + my $per = int(100 * $bytes_received / $expected_length); + if ((int($per / 5) == $per / 5) and ($per != $oldper) and !$quiet) { + print "...$per\%\n"; + $oldper = $per; + } + } else { + unless ($quiet) {print "."} + } + print $OUT $chunk; + } + }); + close ($OUT); + unless ($quiet) {print "\n"} + } else { + $res = $ua->request('GET', $url); + } + alarm(0); + if ($res->{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 { + my $reason = $res->{reason}; + if ($res->{status} == 599) {$reason = $res->{content}} + ($status, $text) = &binget($url,$file,$quiet,$reason); + return ($status, $text); + } + }; + alarm(0); + if ($@) {return (1, $@)} + return ($status,$text); +} +# end urlgetTINY +############################################################################### +# start urlgetLWP +sub urlgetLWP { + my $url = shift; + my $file = shift; + my $quiet = shift; + my $status = 0; + my $timeout = 300; + my $ua = LWP::UserAgent->new; + $ua->agent($agent); + $ua->timeout(30); + if ($proxy ne "") {$ua->proxy([ 'http', 'https' ], $proxy)} +#use LWP::ConnCache; +#my $cache = LWP::ConnCache->new; +#$cache->total_capacity([1]); +#$ua->conn_cache($cache); + 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); + $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) and !$quiet) { + print "...$per\%\n"; + $oldper = $per; + } + } else { + unless ($quiet) {print "."} + } + print $OUT $chunk; + }); + close ($OUT); + unless ($quiet) {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 { + ($status, $text) = &binget($url,$file,$quiet,$res->message); + return ($status, $text); + } + }; + alarm(0); + if ($@) { + return (1, $@); + } + if ($text) { + return ($status,$text); + } else { + return (1, "Download timeout after $timeout seconds"); + } +} +# end urlget +############################################################################### +# start binget +sub binget { + my $url = shift; + my $file = shift; + my $quiet = shift; + my $errormsg = shift; + $url = "'$url'"; + + my $cmd; + if (-e $config{CURL}) { + $cmd = $config{CURL}." -skLf -m 120"; + if ($file) {$cmd = $config{CURL}." -kLf -m 120 -o";} + } + elsif (-e $config{WGET}) { + $cmd = $config{WGET}." -qT 120 -O-"; + if ($file) {$cmd = $config{WGET}." -T 120 -O"} + } + if ($cmd ne "") { + if ($file) { + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, $cmd." $file\.tmp $url"); + my @output = <$childout>; + waitpid ($cmdpid, 0); + unless ($quiet and $option != 3) { + print "Using fallback [$cmd]\n"; + print @output; + } + if (-e "$file\.tmp") { + rename ("$file\.tmp","$file") or return (1, "Unable to rename $file\.tmp to $file: $!"); + return (0, $file); + } else { + if ($option == 3) { + return (1, "Unable to download: ".$cmd." $file\.tmp $url".join("",@output)); + } else { + return (1, "Unable to download: ".$errormsg); + } + } + } else { + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, $cmd." $url"); + my @output = <$childout>; + waitpid ($cmdpid, 0); + if (scalar @output > 0) { + return (0, join("",@output)); + } else { + if ($option == 3) { + return (1, "Unable to download: [$cmd $url]".join("",@output)); + } else { + return (1, "Unable to download: ".$errormsg); + } + } + } + } + if ($option == 3) { + return (1, "Unable to download (CURL/WGET also not present, see csf.conf)"); + } else { + return (1, "Unable to download (CURL/WGET also not present, see csf.conf): ".$errormsg); + } +} +# end binget +############################################################################### +1; \ No newline at end of file diff --git a/src/redux/ConfigServer/cseUI.pm b/src/redux/ConfigServer/cseUI.pm new file mode 100644 index 000000000..d1249ebc3 --- /dev/null +++ b/src/redux/ConfigServer/cseUI.pm @@ -0,0 +1,1029 @@ +############################################################################### +# Copyright 2006-2023, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +## no critic (RequireUseWarnings, ProhibitExplicitReturnUndef, ProhibitMixedBooleanOperators, RequireBriefOpen) +package ConfigServer::cseUI; + +use strict; +use Fcntl qw(:DEFAULT :flock); +use File::Find; +use File::Copy; +use IPC::Open3; + +use Exporter qw(import); +our $VERSION = 2.03; +our @ISA = qw(Exporter); +our @EXPORT_OK = qw(); + +umask(0177); + +our ($chart, $ipscidr6, $ipv6reg, $ipv4reg, %config, %ips, $mobile, + %FORM, $script, $script_da, $images, $myv); + +our ($act, $destpath, $element, $extramessage, $fieldname, $fileinc, + $filetemp, $message, $name, $origpath, $storepath, $tgid, $thisdir, + $tuid, $value, $webpath, %ele, %header, @bits, @dirs, @filebodies, + @filenames, @files, @months, @parts, @passrecs, @thisdirs, @thisfiles, + $files); +# +############################################################################### +# start main +sub main { + my $FORM_ref = shift; + %FORM = %{$FORM_ref}; + $fileinc = shift; + $script = shift; + $script_da = shift; + $images = shift; + $myv = shift; + $| = 1; + + &loadconfig; + + $webpath = '/'; + + if ($FORM{do} eq "view") { + &view; + exit; + } + + print "Content-type: text/html\r\n\r\n"; + + my $bootstrapcss = ""; + my $jqueryjs = ""; + my $bootstrapjs = ""; + + print < + + + ConfigServer Explorer + + + $bootstrapcss + + $jqueryjs + $bootstrapjs + + +
+EOF + + unless ($FORM{do} eq "console") { + print "
\n"; + print "
\n"; + if ($config{UI_CXS} or $config{UI_CSE}) { + print "
\n"; + } + print " cse Logout\n"; + print "
\n"; + print < +

ConfigServer Explorer - cse

+
+EOF + } + + $message = ""; + + if ($fileinc) {&uploadfile} + elsif ($FORM{do} eq "") {&browse} + 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} + else {print "Invalid action"}; + + unless ($FORM{do} eq "console") { + print "

©2006-2023, ConfigServer Services (Way to the Web Limited)

\n"; + } + print < + + + +EOF + exit; +} +# end main +############################################################################### +# start browse +sub browse { + 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"; + 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"; + } + my $class = "tdshade2"; + foreach my $dir (@thisdirs) { + if ($dir =~/'|"|\||\`/) { + print ""; + 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 & oct("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 (my $PASSFILE, "<","$storepath/$passfile.htpasswd") or die $!; + flock ($PASSFILE, LOCK_SH); + @passrecs = <$PASSFILE>; + close ($PASSFILE); + chomp @passrecs; + if (@passrecs > 0) {$pp = "**"} + } + + print ""; + if ($FORM{do} eq "r" and ($FORM{f} eq $dir)) { + print "\n"; + print ""; + print "\n"; + } + elsif (-r "$webpath$FORM{p}/$dir") { + print ""; + } + else { + print ""; + } + print ""; + print ""; + if ($FORM{do} eq "o" and ($FORM{f} eq $dir)) { + print "\n"; + print ""; + print "\n"; + } + else { + print ""; + } + if ($FORM{do} eq "p" and ($FORM{f} eq $dir)) { + print "\n"; + print ""; + print "\n"; + } + else { + print ""; + } + print ""; + print ""; + print "\n"; + } + if ($FORM{do} eq "newd") { + print ""; + print "\n"; + print ""; + print "\n"; + print ""; + print ""; + print ""; + print ""; + print ""; + print "\n"; + } + if (($FORM{do} eq "c") and (-d "$webpath$FORM{c}")) { + my $newf = (split(/\//,$FORM{c}))[-1]; + print ""; + print "\n"; + print ""; + print "\n"; + print ""; + print ""; + print ""; + print ""; + print ""; + print "\n"; + } + if (($FORM{do} eq "m") and (-d "$webpath$FORM{m}")) { + my $newf = (split(/\//,$FORM{m}))[-1]; + print ""; + print "\n"; + print ""; + print "\n"; + print ""; + print ""; + print ""; + print ""; + print ""; + print "\n"; + } + + if (@thisfiles > 0) { + print "\n"; + print ""; + print ""; + print ""; + print ""; + print ""; + print ""; + print ""; + print "\n"; + } + $class = "tdshade2"; + foreach my $file (@thisfiles) { + if ($file =~/'|"|\||\`/) { + print ""; + 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 & oct("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 ""; + print "\n"; + } + else { + $act = "$script?do=view&p=$FORM{p}&f=$file$extra\#new"; + print ""; + } + print ""; + print ""; + if ($FORM{do} eq "o" and ($FORM{f} eq $file)) { + print "\n"; + print ""; + print "\n"; + } + else { + print ""; + } + if ($FORM{do} eq "p" and ($FORM{f} eq $file)) { + print "\n"; + print ""; + print "\n"; + } + else { + print ""; + } + my $ext = (split(/\./,$file))[-1]; + if (-T "$webpath$FORM{p}/$file") { + my $act = ""; + print ""; + } else { + print ""; + } + print ""; + print "\n"; + } + if ($FORM{do} eq "newf") { + print ""; + print "\n"; + print ""; + print "\n"; + print ""; + print ""; + print ""; + print ""; + print ""; + print "\n"; + } + if (($FORM{do} eq "c") and (-f "$webpath$FORM{c}")) { + my $newf = (split(/\//,$FORM{c}))[-1]; + print ""; + print "\n"; + print ""; + print "\n"; + print ""; + print ""; + print ""; + print ""; + print ""; + print "\n"; + } + if (($FORM{do} eq "m") and (-f "$webpath$FORM{m}")) { + my $newf = (split(/\//,$FORM{m}))[-1]; + print ""; + print "\n"; + print ""; + print "\n"; + print ""; + print ""; + print ""; + print ""; + print ""; + 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 "; + print " "; + print " "; + 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 "; + print " "; + print " "; + 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 "
Search for filenames or directories
"; + print " \n"; + print "
\n"; + print "
\n"; + print "\n"; + print "\n"; + print "\n\n"; + print "
Create New...
Create New DirectoryCreate Empty File
\n"; + print "
\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "
Upload Files...

\n"; + print "
Mode:
\n"; + print "
\n"; + print "
\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "\n"; + print "
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"; + 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/src/redux/Crypt/Blowfish_PP.pm b/src/redux/Crypt/Blowfish_PP.pm new file mode 100644 index 000000000..455e3fc1e --- /dev/null +++ b/src/redux/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/src/redux/Crypt/CBC.pm b/src/redux/Crypt/CBC.pm new file mode 100644 index 000000000..39ff251d4 --- /dev/null +++ b/src/redux/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/src/redux/HTTP/Tiny.pm b/src/redux/HTTP/Tiny.pm new file mode 100644 index 000000000..541befe90 --- /dev/null +++ b/src/redux/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/src/redux/JSON/Tiny.pm b/src/redux/JSON/Tiny.pm new file mode 100644 index 000000000..a713d56e5 --- /dev/null +++ b/src/redux/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/src/redux/Module/Installed/Tiny.pm b/src/redux/Module/Installed/Tiny.pm new file mode 100644 index 000000000..3aab2339e --- /dev/null +++ b/src/redux/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/src/redux/Net/CIDR/Lite.pm b/src/redux/Net/CIDR/Lite.pm new file mode 100644 index 000000000..fd6df7355 --- /dev/null +++ b/src/redux/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/src/redux/Net/IP.pm b/src/redux/Net/IP.pm new file mode 100644 index 000000000..0ff27ffeb --- /dev/null +++ b/src/redux/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/src/redux/accounttracking.txt b/src/redux/accounttracking.txt new file mode 100644 index 000000000..24c908059 --- /dev/null +++ b/src/redux/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/src/redux/alert.txt b/src/redux/alert.txt new file mode 100644 index 000000000..d27e1d75a --- /dev/null +++ b/src/redux/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/src/redux/apache.http.txt b/src/redux/apache.http.txt new file mode 100644 index 000000000..a0dcd50f1 --- /dev/null +++ b/src/redux/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/src/redux/apache.https.txt b/src/redux/apache.https.txt new file mode 100644 index 000000000..2cfc8a81b --- /dev/null +++ b/src/redux/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/src/redux/apache.main.txt b/src/redux/apache.main.txt new file mode 100644 index 000000000..e69de29bb diff --git a/src/redux/apf_stub.pl b/src/redux/apf_stub.pl new file mode 100644 index 000000000..73874f9f9 --- /dev/null +++ b/src/redux/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/src/redux/auto.cwp.pl b/src/redux/auto.cwp.pl new file mode 100644 index 000000000..807994918 --- /dev/null +++ b/src/redux/auto.cwp.pl @@ -0,0 +1,592 @@ +#!/usr/bin/perl +############################################################################### +# Copyright 2006-2023, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +## 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/src/redux/auto.cyberpanel.pl b/src/redux/auto.cyberpanel.pl new file mode 100644 index 000000000..ba4bf6f1d --- /dev/null +++ b/src/redux/auto.cyberpanel.pl @@ -0,0 +1,576 @@ +#!/usr/bin/perl +############################################################################### +# Copyright 2006-2023, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +## 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/src/redux/auto.directadmin.pl b/src/redux/auto.directadmin.pl new file mode 100644 index 000000000..09e3915c1 --- /dev/null +++ b/src/redux/auto.directadmin.pl @@ -0,0 +1,605 @@ +#!/usr/bin/perl +############################################################################### +# Copyright 2006-2023, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +## 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/src/redux/auto.generic.pl b/src/redux/auto.generic.pl new file mode 100644 index 000000000..39e5510f9 --- /dev/null +++ b/src/redux/auto.generic.pl @@ -0,0 +1,576 @@ +#!/usr/bin/perl +############################################################################### +# Copyright 2006-2023, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +## 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/src/redux/auto.interworx.pl b/src/redux/auto.interworx.pl new file mode 100644 index 000000000..a5d1b4031 --- /dev/null +++ b/src/redux/auto.interworx.pl @@ -0,0 +1,576 @@ +#!/usr/bin/perl +############################################################################### +# Copyright 2006-2023, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +## 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/src/redux/auto.pl b/src/redux/auto.pl new file mode 100644 index 000000000..629b79dc3 --- /dev/null +++ b/src/redux/auto.pl @@ -0,0 +1,1239 @@ +#!/usr/bin/perl +############################################################################### +# Copyright 2006-2023, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +## 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/src/redux/auto.vesta.pl b/src/redux/auto.vesta.pl new file mode 100644 index 000000000..681b61aa9 --- /dev/null +++ b/src/redux/auto.vesta.pl @@ -0,0 +1,592 @@ +#!/usr/bin/perl +############################################################################### +# Copyright 2006-2023, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +## 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/src/redux/changelog.txt b/src/redux/changelog.txt new file mode 100644 index 000000000..f7fd0497b --- /dev/null +++ b/src/redux/changelog.txt @@ -0,0 +1,6127 @@ +ChangeLog: + +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/src/redux/connectiontracking.txt b/src/redux/connectiontracking.txt new file mode 100644 index 000000000..5aa06a441 --- /dev/null +++ b/src/redux/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/src/redux/consolealert.txt b/src/redux/consolealert.txt new file mode 100644 index 000000000..ece9ad744 --- /dev/null +++ b/src/redux/consolealert.txt @@ -0,0 +1,5 @@ +From: root +To: root +Subject: lfd on [hostname]: console login alert + +[line] diff --git a/src/redux/cpanel.allow b/src/redux/cpanel.allow new file mode 100644 index 000000000..357910ffa --- /dev/null +++ b/src/redux/cpanel.allow @@ -0,0 +1,87 @@ +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# 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/src/redux/cpanel.comodo.allow b/src/redux/cpanel.comodo.allow new file mode 100644 index 000000000..702dc3eaf --- /dev/null +++ b/src/redux/cpanel.comodo.allow @@ -0,0 +1,43 @@ +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# 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/src/redux/cpanel.comodo.ignore b/src/redux/cpanel.comodo.ignore new file mode 100644 index 000000000..99aba9268 --- /dev/null +++ b/src/redux/cpanel.comodo.ignore @@ -0,0 +1,23 @@ +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# 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/src/redux/cpanel.ignore b/src/redux/cpanel.ignore new file mode 100644 index 000000000..fbd315f4c --- /dev/null +++ b/src/redux/cpanel.ignore @@ -0,0 +1,22 @@ +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# 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/src/redux/cpanel/Driver/ConfigServercsf.pm b/src/redux/cpanel/Driver/ConfigServercsf.pm new file mode 100644 index 000000000..961316415 --- /dev/null +++ b/src/redux/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/src/redux/cpanel/Driver/ConfigServercsf/META.pm b/src/redux/cpanel/Driver/ConfigServercsf/META.pm new file mode 100644 index 000000000..7cad38902 --- /dev/null +++ b/src/redux/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' => 'Way to the Web Limited', + '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/src/redux/cpanel/csf.cgi b/src/redux/cpanel/csf.cgi new file mode 100644 index 000000000..8b988df34 --- /dev/null +++ b/src/redux/cpanel/csf.cgi @@ -0,0 +1,327 @@ +#!/usr/bin/perl +#WHMADDON:csf:ConfigServer Security & Firewall +############################################################################### +# Copyright 2006-2023, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +## 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/src/redux/cpanel/csf.conf b/src/redux/cpanel/csf.conf new file mode 100644 index 000000000..8dbadc7ea --- /dev/null +++ b/src/redux/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/src/redux/cpanel/csf.tmpl b/src/redux/cpanel/csf.tmpl new file mode 100644 index 000000000..bbd908866 --- /dev/null +++ b/src/redux/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/src/redux/cpanel/upgrade.sh b/src/redux/cpanel/upgrade.sh new file mode 100644 index 000000000..d7f75b146 --- /dev/null +++ b/src/redux/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/src/redux/cpanelalert.txt b/src/redux/cpanelalert.txt new file mode 100644 index 000000000..507230e11 --- /dev/null +++ b/src/redux/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/src/redux/csf.1.txt b/src/redux/csf.1.txt new file mode 100644 index 000000000..72dc1eb39 --- /dev/null +++ b/src/redux/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, Way to the Web Limited (http://www.configserver.com) diff --git a/src/redux/csf.allow b/src/redux/csf.allow new file mode 100644 index 000000000..862133f79 --- /dev/null +++ b/src/redux/csf.allow @@ -0,0 +1,20 @@ +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# 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/src/redux/csf.blocklists b/src/redux/csf.blocklists new file mode 100644 index 000000000..13af4f9a5 --- /dev/null +++ b/src/redux/csf.blocklists @@ -0,0 +1,103 @@ +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# 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/src/redux/csf.c b/src/redux/csf.c new file mode 100644 index 000000000..1c81bbdc1 --- /dev/null +++ b/src/redux/csf.c @@ -0,0 +1,72 @@ +/* + * Copyright 2006-2023, Way to the Web Limited + * URL: http://www.configserver.com + * Email: sales@waytotheweb.com +*/ +#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/src/redux/csf.cloudflare b/src/redux/csf.cloudflare new file mode 100644 index 000000000..53f52e472 --- /dev/null +++ b/src/redux/csf.cloudflare @@ -0,0 +1,50 @@ +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# 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/src/redux/csf.conf b/src/redux/csf.conf new file mode 100644 index 000000000..ad57ac5fe --- /dev/null +++ b/src/redux/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/src/redux/csf.cwp.allow b/src/redux/csf.cwp.allow new file mode 100644 index 000000000..989a6dd45 --- /dev/null +++ b/src/redux/csf.cwp.allow @@ -0,0 +1,17 @@ +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# 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/src/redux/csf.cwp.conf b/src/redux/csf.cwp.conf new file mode 100644 index 000000000..feae1b99c --- /dev/null +++ b/src/redux/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/src/redux/csf.cwp.ignore b/src/redux/csf.cwp.ignore new file mode 100644 index 000000000..b5627a749 --- /dev/null +++ b/src/redux/csf.cwp.ignore @@ -0,0 +1,12 @@ +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# 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/src/redux/csf.cwp.pignore b/src/redux/csf.cwp.pignore new file mode 100644 index 000000000..b6b3dc941 --- /dev/null +++ b/src/redux/csf.cwp.pignore @@ -0,0 +1,103 @@ +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# 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/src/redux/csf.cyberpanel.allow b/src/redux/csf.cyberpanel.allow new file mode 100644 index 000000000..989a6dd45 --- /dev/null +++ b/src/redux/csf.cyberpanel.allow @@ -0,0 +1,17 @@ +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# 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/src/redux/csf.cyberpanel.conf b/src/redux/csf.cyberpanel.conf new file mode 100644 index 000000000..5c1853802 --- /dev/null +++ b/src/redux/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/src/redux/csf.cyberpanel.ignore b/src/redux/csf.cyberpanel.ignore new file mode 100644 index 000000000..b5627a749 --- /dev/null +++ b/src/redux/csf.cyberpanel.ignore @@ -0,0 +1,12 @@ +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# 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/src/redux/csf.cyberpanel.pignore b/src/redux/csf.cyberpanel.pignore new file mode 100644 index 000000000..71182f99f --- /dev/null +++ b/src/redux/csf.cyberpanel.pignore @@ -0,0 +1,95 @@ +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# 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/src/redux/csf.deny b/src/redux/csf.deny new file mode 100644 index 000000000..de32af6cc --- /dev/null +++ b/src/redux/csf.deny @@ -0,0 +1,18 @@ +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# 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/src/redux/csf.directadmin.allow b/src/redux/csf.directadmin.allow new file mode 100644 index 000000000..989a6dd45 --- /dev/null +++ b/src/redux/csf.directadmin.allow @@ -0,0 +1,17 @@ +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# 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/src/redux/csf.directadmin.conf b/src/redux/csf.directadmin.conf new file mode 100644 index 000000000..97ae202fa --- /dev/null +++ b/src/redux/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/src/redux/csf.directadmin.ignore b/src/redux/csf.directadmin.ignore new file mode 100644 index 000000000..b5627a749 --- /dev/null +++ b/src/redux/csf.directadmin.ignore @@ -0,0 +1,12 @@ +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# 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/src/redux/csf.directadmin.pignore b/src/redux/csf.directadmin.pignore new file mode 100644 index 000000000..1f3a24828 --- /dev/null +++ b/src/redux/csf.directadmin.pignore @@ -0,0 +1,82 @@ +############################################################################### +# Copyright 2006-2019, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# 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/src/redux/csf.dirwatch b/src/redux/csf.dirwatch new file mode 100644 index 000000000..ef9c5acdb --- /dev/null +++ b/src/redux/csf.dirwatch @@ -0,0 +1,14 @@ +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# 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/src/redux/csf.div b/src/redux/csf.div new file mode 100644 index 000000000..36ce84cb7 --- /dev/null +++ b/src/redux/csf.div @@ -0,0 +1,230 @@ + diff --git a/src/redux/csf.dyndns b/src/redux/csf.dyndns new file mode 100644 index 000000000..5f5d3c55d --- /dev/null +++ b/src/redux/csf.dyndns @@ -0,0 +1,18 @@ +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# 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/src/redux/csf.fignore b/src/redux/csf.fignore new file mode 100644 index 000000000..c7d119ad9 --- /dev/null +++ b/src/redux/csf.fignore @@ -0,0 +1,28 @@ +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# 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) diff --git a/src/redux/csf.generic.allow b/src/redux/csf.generic.allow new file mode 100644 index 000000000..989a6dd45 --- /dev/null +++ b/src/redux/csf.generic.allow @@ -0,0 +1,17 @@ +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# 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/src/redux/csf.generic.conf b/src/redux/csf.generic.conf new file mode 100644 index 000000000..7df13a40c --- /dev/null +++ b/src/redux/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/src/redux/csf.generic.ignore b/src/redux/csf.generic.ignore new file mode 100644 index 000000000..b5627a749 --- /dev/null +++ b/src/redux/csf.generic.ignore @@ -0,0 +1,12 @@ +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# 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/src/redux/csf.generic.pignore b/src/redux/csf.generic.pignore new file mode 100644 index 000000000..b4760d55f --- /dev/null +++ b/src/redux/csf.generic.pignore @@ -0,0 +1,68 @@ +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# 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/src/redux/csf.help b/src/redux/csf.help new file mode 100644 index 000000000..e6685bba5 --- /dev/null +++ b/src/redux/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, Way to the Web Limited (http://www.configserver.com) + + csf(1) diff --git a/src/redux/csf.ignore b/src/redux/csf.ignore new file mode 100644 index 000000000..f956d50bc --- /dev/null +++ b/src/redux/csf.ignore @@ -0,0 +1,15 @@ +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# 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/src/redux/csf.interworx.allow b/src/redux/csf.interworx.allow new file mode 100644 index 000000000..989a6dd45 --- /dev/null +++ b/src/redux/csf.interworx.allow @@ -0,0 +1,17 @@ +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# 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/src/redux/csf.interworx.conf b/src/redux/csf.interworx.conf new file mode 100644 index 000000000..60d4cec7c --- /dev/null +++ b/src/redux/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/src/redux/csf.interworx.ignore b/src/redux/csf.interworx.ignore new file mode 100644 index 000000000..b5627a749 --- /dev/null +++ b/src/redux/csf.interworx.ignore @@ -0,0 +1,12 @@ +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# 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/src/redux/csf.interworx.pignore b/src/redux/csf.interworx.pignore new file mode 100644 index 000000000..82f59c073 --- /dev/null +++ b/src/redux/csf.interworx.pignore @@ -0,0 +1,88 @@ +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# 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/src/redux/csf.logfiles b/src/redux/csf.logfiles new file mode 100644 index 000000000..82084c97b --- /dev/null +++ b/src/redux/csf.logfiles @@ -0,0 +1,36 @@ +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# 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/src/redux/csf.logignore b/src/redux/csf.logignore new file mode 100644 index 000000000..908ec1804 --- /dev/null +++ b/src/redux/csf.logignore @@ -0,0 +1,75 @@ +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# 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/src/redux/csf.mignore b/src/redux/csf.mignore new file mode 100644 index 000000000..070a7dadf --- /dev/null +++ b/src/redux/csf.mignore @@ -0,0 +1,9 @@ +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# 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/src/redux/csf.pignore b/src/redux/csf.pignore new file mode 100644 index 000000000..fbcca3c5a --- /dev/null +++ b/src/redux/csf.pignore @@ -0,0 +1,145 @@ +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# 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/src/redux/csf.pl b/src/redux/csf.pl new file mode 100644 index 000000000..bc1d20101 --- /dev/null +++ b/src/redux/csf.pl @@ -0,0 +1,5996 @@ +#!/usr/bin/perl +############################################################################### +# Copyright 2006-2023, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +## 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/src/redux/csf.rblconf b/src/redux/csf.rblconf new file mode 100644 index 000000000..48f1e3faa --- /dev/null +++ b/src/redux/csf.rblconf @@ -0,0 +1,22 @@ +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# 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/src/redux/csf.rbls b/src/redux/csf.rbls new file mode 100644 index 000000000..1949d19ef --- /dev/null +++ b/src/redux/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/src/redux/csf.redirect b/src/redux/csf.redirect new file mode 100644 index 000000000..391f8a838 --- /dev/null +++ b/src/redux/csf.redirect @@ -0,0 +1,34 @@ +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# 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/src/redux/csf.resellers b/src/redux/csf.resellers new file mode 100644 index 000000000..e76c8eb46 --- /dev/null +++ b/src/redux/csf.resellers @@ -0,0 +1,47 @@ +############################################################################### +# Copyright 2006-2019, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# 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/src/redux/csf.rignore b/src/redux/csf.rignore new file mode 100644 index 000000000..d9a6b6cc5 --- /dev/null +++ b/src/redux/csf.rignore @@ -0,0 +1,40 @@ +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# 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/src/redux/csf.service b/src/redux/csf.service new file mode 100644 index 000000000..e8dae8f0a --- /dev/null +++ b/src/redux/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/src/redux/csf.sh b/src/redux/csf.sh new file mode 100644 index 000000000..04df5e62c --- /dev/null +++ b/src/redux/csf.sh @@ -0,0 +1,90 @@ +#!/bin/bash +# +############################################################################### +# lfd +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# +# 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/src/redux/csf.signore b/src/redux/csf.signore new file mode 100644 index 000000000..51b2d662e --- /dev/null +++ b/src/redux/csf.signore @@ -0,0 +1,7 @@ +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# 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/src/redux/csf.sips b/src/redux/csf.sips new file mode 100644 index 000000000..136904879 --- /dev/null +++ b/src/redux/csf.sips @@ -0,0 +1,9 @@ +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# 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/src/redux/csf.smtpauth b/src/redux/csf.smtpauth new file mode 100644 index 000000000..e8e277eb0 --- /dev/null +++ b/src/redux/csf.smtpauth @@ -0,0 +1,12 @@ +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# 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/src/redux/csf.suignore b/src/redux/csf.suignore new file mode 100644 index 000000000..f87c8beeb --- /dev/null +++ b/src/redux/csf.suignore @@ -0,0 +1,7 @@ +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# The following is a list of usernames that are ignored during the LF_EXPLOIT +# SUPERUSER check diff --git a/src/redux/csf.syslogs b/src/redux/csf.syslogs new file mode 100644 index 000000000..11c655201 --- /dev/null +++ b/src/redux/csf.syslogs @@ -0,0 +1,90 @@ +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# 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/src/redux/csf.syslogusers b/src/redux/csf.syslogusers new file mode 100644 index 000000000..d386f89d2 --- /dev/null +++ b/src/redux/csf.syslogusers @@ -0,0 +1,66 @@ +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# 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/src/redux/csf.uidignore b/src/redux/csf.uidignore new file mode 100644 index 000000000..f92dc86ba --- /dev/null +++ b/src/redux/csf.uidignore @@ -0,0 +1,9 @@ +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# 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/src/redux/csf.vesta.allow b/src/redux/csf.vesta.allow new file mode 100644 index 000000000..989a6dd45 --- /dev/null +++ b/src/redux/csf.vesta.allow @@ -0,0 +1,17 @@ +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# 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/src/redux/csf.vesta.conf b/src/redux/csf.vesta.conf new file mode 100644 index 000000000..d30993cd5 --- /dev/null +++ b/src/redux/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/src/redux/csf.vesta.ignore b/src/redux/csf.vesta.ignore new file mode 100644 index 000000000..b5627a749 --- /dev/null +++ b/src/redux/csf.vesta.ignore @@ -0,0 +1,12 @@ +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# 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/src/redux/csf.vesta.pignore b/src/redux/csf.vesta.pignore new file mode 100644 index 000000000..04e4b297d --- /dev/null +++ b/src/redux/csf.vesta.pignore @@ -0,0 +1,105 @@ +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# 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/src/redux/csf/LICENSE.txt b/src/redux/csf/LICENSE.txt new file mode 100644 index 000000000..34da9d9ee --- /dev/null +++ b/src/redux/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/src/redux/csf/admin_icon.svg b/src/redux/csf/admin_icon.svg new file mode 100644 index 000000000..1c928ea0d --- /dev/null +++ b/src/redux/csf/admin_icon.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/redux/csf/bootstrap-chosen.css b/src/redux/csf/bootstrap-chosen.css new file mode 100644 index 000000000..54e6a1398 --- /dev/null +++ b/src/redux/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/src/redux/csf/bootstrap/css/bootstrap.min.css b/src/redux/csf/bootstrap/css/bootstrap.min.css new file mode 100644 index 000000000..b89ef7f3e --- /dev/null +++ b/src/redux/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/src/redux/csf/bootstrap/css/bootstrap.min.css.map b/src/redux/csf/bootstrap/css/bootstrap.min.css.map new file mode 100644 index 000000000..0c2c93492 --- /dev/null +++ b/src/redux/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,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A,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
    ,
      , or
      .\n\n.list-group {\n // No need to set list-style: none; since .list-group-item is block level\n margin-bottom: 20px;\n padding-left: 0; // reset padding because ul and ol\n}\n\n\n// Individual list items\n//\n// Use on `li`s or `div`s within the `.list-group` parent.\n\n.list-group-item {\n position: relative;\n display: block;\n padding: 10px 15px;\n // Place the border on the list items and negative margin up for better styling\n margin-bottom: -1px;\n background-color: @list-group-bg;\n border: 1px solid @list-group-border;\n\n // Round the first and last items\n &:first-child {\n .border-top-radius(@list-group-border-radius);\n }\n &:last-child {\n margin-bottom: 0;\n .border-bottom-radius(@list-group-border-radius);\n }\n}\n\n\n// Interactive list items\n//\n// Use anchor or button elements instead of `li`s or `div`s to create interactive items.\n// Includes an extra `.active` modifier class for showing selected items.\n\na.list-group-item,\nbutton.list-group-item {\n color: @list-group-link-color;\n\n .list-group-item-heading {\n color: @list-group-link-heading-color;\n }\n\n // Hover state\n &:hover,\n &:focus {\n text-decoration: none;\n color: @list-group-link-hover-color;\n background-color: @list-group-hover-bg;\n }\n}\n\nbutton.list-group-item {\n width: 100%;\n text-align: left;\n}\n\n.list-group-item {\n // Disabled state\n &.disabled,\n &.disabled:hover,\n &.disabled:focus {\n background-color: @list-group-disabled-bg;\n color: @list-group-disabled-color;\n cursor: @cursor-disabled;\n\n // Force color to inherit for custom content\n .list-group-item-heading {\n color: inherit;\n }\n .list-group-item-text {\n color: @list-group-disabled-text-color;\n }\n }\n\n // Active class on item itself, not parent\n &.active,\n &.active:hover,\n &.active:focus {\n z-index: 2; // Place active items above their siblings for proper border styling\n color: @list-group-active-color;\n background-color: @list-group-active-bg;\n border-color: @list-group-active-border;\n\n // Force color to inherit for custom content\n .list-group-item-heading,\n .list-group-item-heading > small,\n .list-group-item-heading > .small {\n color: inherit;\n }\n .list-group-item-text {\n color: @list-group-active-text-color;\n }\n }\n}\n\n\n// Contextual variants\n//\n// Add modifier classes to change text and background color on individual items.\n// Organizationally, this must come after the `:hover` states.\n\n.list-group-item-variant(success; @state-success-bg; @state-success-text);\n.list-group-item-variant(info; @state-info-bg; @state-info-text);\n.list-group-item-variant(warning; @state-warning-bg; @state-warning-text);\n.list-group-item-variant(danger; @state-danger-bg; @state-danger-text);\n\n\n// Custom content options\n//\n// Extra classes for creating well-formatted content within `.list-group-item`s.\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","// List Groups\n\n.list-group-item-variant(@state; @background; @color) {\n .list-group-item-@{state} {\n color: @color;\n background-color: @background;\n\n a&,\n button& {\n color: @color;\n\n .list-group-item-heading {\n color: inherit;\n }\n\n &:hover,\n &:focus {\n color: @color;\n background-color: darken(@background, 5%);\n }\n &.active,\n &.active:hover,\n &.active:focus {\n color: #fff;\n background-color: @color;\n border-color: @color;\n }\n }\n }\n}\n","//\n// Panels\n// --------------------------------------------------\n\n\n// Base class\n.panel {\n margin-bottom: @line-height-computed;\n background-color: @panel-bg;\n border: 1px solid transparent;\n border-radius: @panel-border-radius;\n .box-shadow(0 1px 1px rgba(0,0,0,.05));\n}\n\n// Panel contents\n.panel-body {\n padding: @panel-body-padding;\n &:extend(.clearfix all);\n}\n\n// Optional heading\n.panel-heading {\n padding: @panel-heading-padding;\n border-bottom: 1px solid transparent;\n .border-top-radius((@panel-border-radius - 1));\n\n > .dropdown .dropdown-toggle {\n color: inherit;\n }\n}\n\n// Within heading, strip any `h*` tag of its default margins for spacing.\n.panel-title {\n margin-top: 0;\n margin-bottom: 0;\n font-size: ceil((@font-size-base * 1.125));\n color: inherit;\n\n > a,\n > small,\n > .small,\n > small > a,\n > .small > a {\n color: inherit;\n }\n}\n\n// Optional footer (stays gray in every modifier class)\n.panel-footer {\n padding: @panel-footer-padding;\n background-color: @panel-footer-bg;\n border-top: 1px solid @panel-inner-border;\n .border-bottom-radius((@panel-border-radius - 1));\n}\n\n\n// List groups in panels\n//\n// By default, space out list group content from panel headings to account for\n// any kind of custom content between the two.\n\n.panel {\n > .list-group,\n > .panel-collapse > .list-group {\n margin-bottom: 0;\n\n .list-group-item {\n border-width: 1px 0;\n border-radius: 0;\n }\n\n // Add border top radius for first one\n &:first-child {\n .list-group-item:first-child {\n border-top: 0;\n .border-top-radius((@panel-border-radius - 1));\n }\n }\n\n // Add border bottom radius for last one\n &:last-child {\n .list-group-item:last-child {\n border-bottom: 0;\n .border-bottom-radius((@panel-border-radius - 1));\n }\n }\n }\n > .panel-heading + .panel-collapse > .list-group {\n .list-group-item:first-child {\n .border-top-radius(0);\n }\n }\n}\n// Collapse space between when there's no additional content.\n.panel-heading + .list-group {\n .list-group-item:first-child {\n border-top-width: 0;\n }\n}\n.list-group + .panel-footer {\n border-top-width: 0;\n}\n\n// Tables in panels\n//\n// Place a non-bordered `.table` within a panel (not within a `.panel-body`) and\n// watch it go full width.\n\n.panel {\n > .table,\n > .table-responsive > .table,\n > .panel-collapse > .table {\n margin-bottom: 0;\n\n caption {\n padding-left: @panel-body-padding;\n padding-right: @panel-body-padding;\n }\n }\n // Add border top radius for first one\n > .table:first-child,\n > .table-responsive:first-child > .table:first-child {\n .border-top-radius((@panel-border-radius - 1));\n\n > thead:first-child,\n > tbody:first-child {\n > tr:first-child {\n border-top-left-radius: (@panel-border-radius - 1);\n border-top-right-radius: (@panel-border-radius - 1);\n\n td:first-child,\n th:first-child {\n border-top-left-radius: (@panel-border-radius - 1);\n }\n td:last-child,\n th:last-child {\n border-top-right-radius: (@panel-border-radius - 1);\n }\n }\n }\n }\n // Add border bottom radius for last one\n > .table:last-child,\n > .table-responsive:last-child > .table:last-child {\n .border-bottom-radius((@panel-border-radius - 1));\n\n > tbody:last-child,\n > tfoot:last-child {\n > tr:last-child {\n border-bottom-left-radius: (@panel-border-radius - 1);\n border-bottom-right-radius: (@panel-border-radius - 1);\n\n td:first-child,\n th:first-child {\n border-bottom-left-radius: (@panel-border-radius - 1);\n }\n td:last-child,\n th:last-child {\n border-bottom-right-radius: (@panel-border-radius - 1);\n }\n }\n }\n }\n > .panel-body + .table,\n > .panel-body + .table-responsive,\n > .table + .panel-body,\n > .table-responsive + .panel-body {\n border-top: 1px solid @table-border-color;\n }\n > .table > tbody:first-child > tr:first-child th,\n > .table > tbody:first-child > tr:first-child td {\n border-top: 0;\n }\n > .table-bordered,\n > .table-responsive > .table-bordered {\n border: 0;\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 > thead,\n > tbody {\n > tr:first-child {\n > td,\n > th {\n border-bottom: 0;\n }\n }\n }\n > tbody,\n > tfoot {\n > tr:last-child {\n > td,\n > th {\n border-bottom: 0;\n }\n }\n }\n }\n > .table-responsive {\n border: 0;\n margin-bottom: 0;\n }\n}\n\n\n// Collapsible panels (aka, accordion)\n//\n// Wrap a series of panels in `.panel-group` to turn them into an accordion with\n// the help of our collapse JavaScript plugin.\n\n.panel-group {\n margin-bottom: @line-height-computed;\n\n // Tighten up margin so it's only between panels\n .panel {\n margin-bottom: 0;\n border-radius: @panel-border-radius;\n\n + .panel {\n margin-top: 5px;\n }\n }\n\n .panel-heading {\n border-bottom: 0;\n\n + .panel-collapse > .panel-body,\n + .panel-collapse > .list-group {\n border-top: 1px solid @panel-inner-border;\n }\n }\n\n .panel-footer {\n border-top: 0;\n + .panel-collapse .panel-body {\n border-bottom: 1px solid @panel-inner-border;\n }\n }\n}\n\n\n// Contextual variations\n.panel-default {\n .panel-variant(@panel-default-border; @panel-default-text; @panel-default-heading-bg; @panel-default-border);\n}\n.panel-primary {\n .panel-variant(@panel-primary-border; @panel-primary-text; @panel-primary-heading-bg; @panel-primary-border);\n}\n.panel-success {\n .panel-variant(@panel-success-border; @panel-success-text; @panel-success-heading-bg; @panel-success-border);\n}\n.panel-info {\n .panel-variant(@panel-info-border; @panel-info-text; @panel-info-heading-bg; @panel-info-border);\n}\n.panel-warning {\n .panel-variant(@panel-warning-border; @panel-warning-text; @panel-warning-heading-bg; @panel-warning-border);\n}\n.panel-danger {\n .panel-variant(@panel-danger-border; @panel-danger-text; @panel-danger-heading-bg; @panel-danger-border);\n}\n","// Panels\n\n.panel-variant(@border; @heading-text-color; @heading-bg-color; @heading-border) {\n border-color: @border;\n\n & > .panel-heading {\n color: @heading-text-color;\n background-color: @heading-bg-color;\n border-color: @heading-border;\n\n + .panel-collapse > .panel-body {\n border-top-color: @border;\n }\n .badge {\n color: @heading-bg-color;\n background-color: @heading-text-color;\n }\n }\n & > .panel-footer {\n + .panel-collapse > .panel-body {\n border-bottom-color: @border;\n }\n }\n}\n","// Embeds responsive\n//\n// Credit: Nicolas Gallagher and SUIT CSS.\n\n.embed-responsive {\n position: relative;\n display: block;\n height: 0;\n padding: 0;\n overflow: hidden;\n\n .embed-responsive-item,\n iframe,\n embed,\n object,\n video {\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n height: 100%;\n width: 100%;\n border: 0;\n }\n}\n\n// Modifier class for 16:9 aspect ratio\n.embed-responsive-16by9 {\n padding-bottom: 56.25%;\n}\n\n// Modifier class for 4:3 aspect ratio\n.embed-responsive-4by3 {\n padding-bottom: 75%;\n}\n","//\n// Wells\n// --------------------------------------------------\n\n\n// Base class\n.well {\n min-height: 20px;\n padding: 19px;\n margin-bottom: 20px;\n background-color: @well-bg;\n border: 1px solid @well-border;\n border-radius: @border-radius-base;\n .box-shadow(inset 0 1px 1px rgba(0,0,0,.05));\n blockquote {\n border-color: #ddd;\n border-color: rgba(0,0,0,.15);\n }\n}\n\n// Sizes\n.well-lg {\n padding: 24px;\n border-radius: @border-radius-large;\n}\n.well-sm {\n padding: 9px;\n border-radius: @border-radius-small;\n}\n","//\n// Close icons\n// --------------------------------------------------\n\n\n.close {\n float: right;\n font-size: (@font-size-base * 1.5);\n font-weight: @close-font-weight;\n line-height: 1;\n color: @close-color;\n text-shadow: @close-text-shadow;\n .opacity(.2);\n\n &:hover,\n &:focus {\n color: @close-color;\n text-decoration: none;\n cursor: pointer;\n .opacity(.5);\n }\n\n // Additional properties for button version\n // iOS requires the button element instead of an anchor tag.\n // If you want the anchor version, it requires `href=\"#\"`.\n // See https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile\n button& {\n padding: 0;\n cursor: pointer;\n background: transparent;\n border: 0;\n -webkit-appearance: none;\n }\n}\n","//\n// Modals\n// --------------------------------------------------\n\n// .modal-open - body class for killing the scroll\n// .modal - container to scroll within\n// .modal-dialog - positioning shell for the actual modal\n// .modal-content - actual modal w/ bg and corners and shit\n\n// Kill the scroll on the body\n.modal-open {\n overflow: hidden;\n}\n\n// Container that the modal scrolls within\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: @zindex-modal;\n -webkit-overflow-scrolling: touch;\n\n // Prevent Chrome on Windows from adding a focus outline. For details, see\n // https://github.com/twbs/bootstrap/pull/10951.\n outline: 0;\n\n // When fading in the modal, animate it to slide down\n &.fade .modal-dialog {\n .translate(0, -25%);\n .transition-transform(~\"0.3s ease-out\");\n }\n &.in .modal-dialog { .translate(0, 0) }\n}\n.modal-open .modal {\n overflow-x: hidden;\n overflow-y: auto;\n}\n\n// Shell div to position the modal with bottom padding\n.modal-dialog {\n position: relative;\n width: auto;\n margin: 10px;\n}\n\n// Actual modal\n.modal-content {\n position: relative;\n background-color: @modal-content-bg;\n border: 1px solid @modal-content-fallback-border-color; //old browsers fallback (ie8 etc)\n border: 1px solid @modal-content-border-color;\n border-radius: @border-radius-large;\n .box-shadow(0 3px 9px rgba(0,0,0,.5));\n background-clip: padding-box;\n // Remove focus outline from opened modal\n outline: 0;\n}\n\n// Modal background\n.modal-backdrop {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: @zindex-modal-background;\n background-color: @modal-backdrop-bg;\n // Fade for backdrop\n &.fade { .opacity(0); }\n &.in { .opacity(@modal-backdrop-opacity); }\n}\n\n// Modal header\n// Top section of the modal w/ title and dismiss\n.modal-header {\n padding: @modal-title-padding;\n border-bottom: 1px solid @modal-header-border-color;\n &:extend(.clearfix all);\n}\n// Close icon\n.modal-header .close {\n margin-top: -2px;\n}\n\n// Title text within header\n.modal-title {\n margin: 0;\n line-height: @modal-title-line-height;\n}\n\n// Modal body\n// Where all modal content resides (sibling of .modal-header and .modal-footer)\n.modal-body {\n position: relative;\n padding: @modal-inner-padding;\n}\n\n// Footer (for actions)\n.modal-footer {\n padding: @modal-inner-padding;\n text-align: right; // right align buttons\n border-top: 1px solid @modal-footer-border-color;\n &:extend(.clearfix all); // clear it in case folks use .pull-* classes on buttons\n\n // Properly space out buttons\n .btn + .btn {\n margin-left: 5px;\n margin-bottom: 0; // account for input[type=\"submit\"] which gets the bottom margin like all other inputs\n }\n // but override that for button groups\n .btn-group .btn + .btn {\n margin-left: -1px;\n }\n // and override it for block buttons as well\n .btn-block + .btn-block {\n margin-left: 0;\n }\n}\n\n// Measure scrollbar width for padding body during modal show/hide\n.modal-scrollbar-measure {\n position: absolute;\n top: -9999px;\n width: 50px;\n height: 50px;\n overflow: scroll;\n}\n\n// Scale up the modal\n@media (min-width: @screen-sm-min) {\n // Automatically set modal's width for larger viewports\n .modal-dialog {\n width: @modal-md;\n margin: 30px auto;\n }\n .modal-content {\n .box-shadow(0 5px 15px rgba(0,0,0,.5));\n }\n\n // Modal sizes\n .modal-sm { width: @modal-sm; }\n}\n\n@media (min-width: @screen-md-min) {\n .modal-lg { width: @modal-lg; }\n}\n","//\n// Tooltips\n// --------------------------------------------------\n\n\n// Base class\n.tooltip {\n position: absolute;\n z-index: @zindex-tooltip;\n display: block;\n // Our parent element can be arbitrary since tooltips are by default inserted as a sibling of their target element.\n // So reset our font and text properties to avoid inheriting weird values.\n .reset-text();\n font-size: @font-size-small;\n\n .opacity(0);\n\n &.in { .opacity(@tooltip-opacity); }\n &.top { margin-top: -3px; padding: @tooltip-arrow-width 0; }\n &.right { margin-left: 3px; padding: 0 @tooltip-arrow-width; }\n &.bottom { margin-top: 3px; padding: @tooltip-arrow-width 0; }\n &.left { margin-left: -3px; padding: 0 @tooltip-arrow-width; }\n}\n\n// Wrapper for the tooltip content\n.tooltip-inner {\n max-width: @tooltip-max-width;\n padding: 3px 8px;\n color: @tooltip-color;\n text-align: center;\n background-color: @tooltip-bg;\n border-radius: @border-radius-base;\n}\n\n// Arrows\n.tooltip-arrow {\n position: absolute;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n}\n// Note: Deprecated .top-left, .top-right, .bottom-left, and .bottom-right as of v3.3.1\n.tooltip {\n &.top .tooltip-arrow {\n bottom: 0;\n left: 50%;\n margin-left: -@tooltip-arrow-width;\n border-width: @tooltip-arrow-width @tooltip-arrow-width 0;\n border-top-color: @tooltip-arrow-color;\n }\n &.top-left .tooltip-arrow {\n bottom: 0;\n right: @tooltip-arrow-width;\n margin-bottom: -@tooltip-arrow-width;\n border-width: @tooltip-arrow-width @tooltip-arrow-width 0;\n border-top-color: @tooltip-arrow-color;\n }\n &.top-right .tooltip-arrow {\n bottom: 0;\n left: @tooltip-arrow-width;\n margin-bottom: -@tooltip-arrow-width;\n border-width: @tooltip-arrow-width @tooltip-arrow-width 0;\n border-top-color: @tooltip-arrow-color;\n }\n &.right .tooltip-arrow {\n top: 50%;\n left: 0;\n margin-top: -@tooltip-arrow-width;\n border-width: @tooltip-arrow-width @tooltip-arrow-width @tooltip-arrow-width 0;\n border-right-color: @tooltip-arrow-color;\n }\n &.left .tooltip-arrow {\n top: 50%;\n right: 0;\n margin-top: -@tooltip-arrow-width;\n border-width: @tooltip-arrow-width 0 @tooltip-arrow-width @tooltip-arrow-width;\n border-left-color: @tooltip-arrow-color;\n }\n &.bottom .tooltip-arrow {\n top: 0;\n left: 50%;\n margin-left: -@tooltip-arrow-width;\n border-width: 0 @tooltip-arrow-width @tooltip-arrow-width;\n border-bottom-color: @tooltip-arrow-color;\n }\n &.bottom-left .tooltip-arrow {\n top: 0;\n right: @tooltip-arrow-width;\n margin-top: -@tooltip-arrow-width;\n border-width: 0 @tooltip-arrow-width @tooltip-arrow-width;\n border-bottom-color: @tooltip-arrow-color;\n }\n &.bottom-right .tooltip-arrow {\n top: 0;\n left: @tooltip-arrow-width;\n margin-top: -@tooltip-arrow-width;\n border-width: 0 @tooltip-arrow-width @tooltip-arrow-width;\n border-bottom-color: @tooltip-arrow-color;\n }\n}\n",".reset-text() {\n font-family: @font-family-base;\n // We deliberately do NOT reset font-size.\n font-style: normal;\n font-weight: normal;\n letter-spacing: normal;\n line-break: auto;\n line-height: @line-height-base;\n text-align: left; // Fallback for where `start` is not supported\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}\n","//\n// Popovers\n// --------------------------------------------------\n\n\n.popover {\n position: absolute;\n top: 0;\n left: 0;\n z-index: @zindex-popover;\n display: none;\n max-width: @popover-max-width;\n padding: 1px;\n // Our parent element can be arbitrary since popovers are by default inserted as a sibling of their target element.\n // So reset our font and text properties to avoid inheriting weird values.\n .reset-text();\n font-size: @font-size-base;\n\n background-color: @popover-bg;\n background-clip: padding-box;\n border: 1px solid @popover-fallback-border-color;\n border: 1px solid @popover-border-color;\n border-radius: @border-radius-large;\n .box-shadow(0 5px 10px rgba(0,0,0,.2));\n\n // Offset the popover to account for the popover arrow\n &.top { margin-top: -@popover-arrow-width; }\n &.right { margin-left: @popover-arrow-width; }\n &.bottom { margin-top: @popover-arrow-width; }\n &.left { margin-left: -@popover-arrow-width; }\n}\n\n.popover-title {\n margin: 0; // reset heading margin\n padding: 8px 14px;\n font-size: @font-size-base;\n background-color: @popover-title-bg;\n border-bottom: 1px solid darken(@popover-title-bg, 5%);\n border-radius: (@border-radius-large - 1) (@border-radius-large - 1) 0 0;\n}\n\n.popover-content {\n padding: 9px 14px;\n}\n\n// Arrows\n//\n// .arrow is outer, .arrow:after is inner\n\n.popover > .arrow {\n &,\n &:after {\n position: absolute;\n display: block;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n }\n}\n.popover > .arrow {\n border-width: @popover-arrow-outer-width;\n}\n.popover > .arrow:after {\n border-width: @popover-arrow-width;\n content: \"\";\n}\n\n.popover {\n &.top > .arrow {\n left: 50%;\n margin-left: -@popover-arrow-outer-width;\n border-bottom-width: 0;\n border-top-color: @popover-arrow-outer-fallback-color; // IE8 fallback\n border-top-color: @popover-arrow-outer-color;\n bottom: -@popover-arrow-outer-width;\n &:after {\n content: \" \";\n bottom: 1px;\n margin-left: -@popover-arrow-width;\n border-bottom-width: 0;\n border-top-color: @popover-arrow-color;\n }\n }\n &.right > .arrow {\n top: 50%;\n left: -@popover-arrow-outer-width;\n margin-top: -@popover-arrow-outer-width;\n border-left-width: 0;\n border-right-color: @popover-arrow-outer-fallback-color; // IE8 fallback\n border-right-color: @popover-arrow-outer-color;\n &:after {\n content: \" \";\n left: 1px;\n bottom: -@popover-arrow-width;\n border-left-width: 0;\n border-right-color: @popover-arrow-color;\n }\n }\n &.bottom > .arrow {\n left: 50%;\n margin-left: -@popover-arrow-outer-width;\n border-top-width: 0;\n border-bottom-color: @popover-arrow-outer-fallback-color; // IE8 fallback\n border-bottom-color: @popover-arrow-outer-color;\n top: -@popover-arrow-outer-width;\n &:after {\n content: \" \";\n top: 1px;\n margin-left: -@popover-arrow-width;\n border-top-width: 0;\n border-bottom-color: @popover-arrow-color;\n }\n }\n\n &.left > .arrow {\n top: 50%;\n right: -@popover-arrow-outer-width;\n margin-top: -@popover-arrow-outer-width;\n border-right-width: 0;\n border-left-color: @popover-arrow-outer-fallback-color; // IE8 fallback\n border-left-color: @popover-arrow-outer-color;\n &:after {\n content: \" \";\n right: 1px;\n border-right-width: 0;\n border-left-color: @popover-arrow-color;\n bottom: -@popover-arrow-width;\n }\n }\n}\n","//\n// Carousel\n// --------------------------------------------------\n\n\n// Wrapper for the slide container and indicators\n.carousel {\n position: relative;\n}\n\n.carousel-inner {\n position: relative;\n overflow: hidden;\n width: 100%;\n\n > .item {\n display: none;\n position: relative;\n .transition(.6s ease-in-out left);\n\n // Account for jankitude on images\n > img,\n > a > img {\n &:extend(.img-responsive);\n line-height: 1;\n }\n\n // WebKit CSS3 transforms for supported devices\n @media all and (transform-3d), (-webkit-transform-3d) {\n .transition-transform(~'0.6s ease-in-out');\n .backface-visibility(~'hidden');\n .perspective(1000px);\n\n &.next,\n &.active.right {\n .translate3d(100%, 0, 0);\n left: 0;\n }\n &.prev,\n &.active.left {\n .translate3d(-100%, 0, 0);\n left: 0;\n }\n &.next.left,\n &.prev.right,\n &.active {\n .translate3d(0, 0, 0);\n left: 0;\n }\n }\n }\n\n > .active,\n > .next,\n > .prev {\n display: block;\n }\n\n > .active {\n left: 0;\n }\n\n > .next,\n > .prev {\n position: absolute;\n top: 0;\n width: 100%;\n }\n\n > .next {\n left: 100%;\n }\n > .prev {\n left: -100%;\n }\n > .next.left,\n > .prev.right {\n left: 0;\n }\n\n > .active.left {\n left: -100%;\n }\n > .active.right {\n left: 100%;\n }\n\n}\n\n// Left/right controls for nav\n// ---------------------------\n\n.carousel-control {\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n width: @carousel-control-width;\n .opacity(@carousel-control-opacity);\n font-size: @carousel-control-font-size;\n color: @carousel-control-color;\n text-align: center;\n text-shadow: @carousel-text-shadow;\n background-color: rgba(0, 0, 0, 0); // Fix IE9 click-thru bug\n // We can't have this transition here because WebKit cancels the carousel\n // animation if you trip this while in the middle of another animation.\n\n // Set gradients for backgrounds\n &.left {\n #gradient > .horizontal(@start-color: rgba(0,0,0,.5); @end-color: rgba(0,0,0,.0001));\n }\n &.right {\n left: auto;\n right: 0;\n #gradient > .horizontal(@start-color: rgba(0,0,0,.0001); @end-color: rgba(0,0,0,.5));\n }\n\n // Hover/focus state\n &:hover,\n &:focus {\n outline: 0;\n color: @carousel-control-color;\n text-decoration: none;\n .opacity(.9);\n }\n\n // Toggles\n .icon-prev,\n .icon-next,\n .glyphicon-chevron-left,\n .glyphicon-chevron-right {\n position: absolute;\n top: 50%;\n margin-top: -10px;\n z-index: 5;\n display: inline-block;\n }\n .icon-prev,\n .glyphicon-chevron-left {\n left: 50%;\n margin-left: -10px;\n }\n .icon-next,\n .glyphicon-chevron-right {\n right: 50%;\n margin-right: -10px;\n }\n .icon-prev,\n .icon-next {\n width: 20px;\n height: 20px;\n line-height: 1;\n font-family: serif;\n }\n\n\n .icon-prev {\n &:before {\n content: '\\2039';// SINGLE LEFT-POINTING ANGLE QUOTATION MARK (U+2039)\n }\n }\n .icon-next {\n &:before {\n content: '\\203a';// SINGLE RIGHT-POINTING ANGLE QUOTATION MARK (U+203A)\n }\n }\n}\n\n// Optional indicator pips\n//\n// Add an unordered list with the following class and add a list item for each\n// slide your carousel holds.\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 li {\n display: inline-block;\n width: 10px;\n height: 10px;\n margin: 1px;\n text-indent: -999px;\n border: 1px solid @carousel-indicator-border-color;\n border-radius: 10px;\n cursor: pointer;\n\n // IE8-9 hack for event handling\n //\n // Internet Explorer 8-9 does not support clicks on elements without a set\n // `background-color`. We cannot use `filter` since that's not viewed as a\n // background color by the browser. Thus, a hack is needed.\n // See https://developer.mozilla.org/en-US/docs/Web/Events/click#Internet_Explorer\n //\n // For IE8, we set solid black as it doesn't support `rgba()`. For IE9, we\n // set alpha transparency for the best results possible.\n background-color: #000 \\9; // IE8\n background-color: rgba(0,0,0,0); // IE9\n }\n .active {\n margin: 0;\n width: 12px;\n height: 12px;\n background-color: @carousel-indicator-active-bg;\n }\n}\n\n// Optional captions\n// -----------------------------\n// Hidden by default for smaller viewports\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: @carousel-caption-color;\n text-align: center;\n text-shadow: @carousel-text-shadow;\n & .btn {\n text-shadow: none; // No shadow for button elements in carousel-caption\n }\n}\n\n\n// Scale up controls for tablets and up\n@media screen and (min-width: @screen-sm-min) {\n\n // Scale up the controls a smidge\n .carousel-control {\n .glyphicon-chevron-left,\n .glyphicon-chevron-right,\n .icon-prev,\n .icon-next {\n width: (@carousel-control-font-size * 1.5);\n height: (@carousel-control-font-size * 1.5);\n margin-top: (@carousel-control-font-size / -2);\n font-size: (@carousel-control-font-size * 1.5);\n }\n .glyphicon-chevron-left,\n .icon-prev {\n margin-left: (@carousel-control-font-size / -2);\n }\n .glyphicon-chevron-right,\n .icon-next {\n margin-right: (@carousel-control-font-size / -2);\n }\n }\n\n // Show and left align the captions\n .carousel-caption {\n left: 20%;\n right: 20%;\n padding-bottom: 30px;\n }\n\n // Move up the indicators\n .carousel-indicators {\n bottom: 20px;\n }\n}\n","// Clearfix\n//\n// For modern browsers\n// 1. The space content is one way to avoid an Opera bug when the\n// contenteditable attribute is included anywhere else in the document.\n// Otherwise it causes space to appear at the top and bottom of elements\n// that are clearfixed.\n// 2. The use of `table` rather than `block` is only necessary if using\n// `:before` to contain the top-margins of child elements.\n//\n// Source: http://nicolasgallagher.com/micro-clearfix-hack/\n\n.clearfix() {\n &:before,\n &:after {\n content: \" \"; // 1\n display: table; // 2\n }\n &:after {\n clear: both;\n }\n}\n","// Center-align a block level element\n\n.center-block() {\n display: block;\n margin-left: auto;\n margin-right: auto;\n}\n","// CSS image replacement\n//\n// Heads up! v3 launched with only `.hide-text()`, but per our pattern for\n// mixins being reused as classes with the same name, this doesn't hold up. As\n// of v3.0.1 we have added `.text-hide()` and deprecated `.hide-text()`.\n//\n// Source: https://github.com/h5bp/html5-boilerplate/commit/aa0396eae757\n\n// Deprecated as of v3.0.1 (has been removed in v4)\n.hide-text() {\n font: ~\"0/0\" a;\n color: transparent;\n text-shadow: none;\n background-color: transparent;\n border: 0;\n}\n\n// New mixin to use as of v3.0.1\n.text-hide() {\n .hide-text();\n}\n","//\n// Responsive: Utility classes\n// --------------------------------------------------\n\n\n// IE10 in Windows (Phone) 8\n//\n// Support for responsive views via media queries is kind of borked in IE10, for\n// Surface/desktop in split view and for Windows Phone 8. This particular fix\n// must be accompanied by a snippet of JavaScript to sniff the user agent and\n// apply some conditional CSS to *only* the Surface/desktop Windows 8. Look at\n// our Getting Started page for more information on this bug.\n//\n// For more information, see the following:\n//\n// Issue: https://github.com/twbs/bootstrap/issues/10497\n// Docs: http://getbootstrap.com/getting-started/#support-ie10-width\n// Source: http://timkadlec.com/2013/01/windows-phone-8-and-device-width/\n// Source: http://timkadlec.com/2012/10/ie10-snap-mode-and-responsive-design/\n\n@-ms-viewport {\n width: device-width;\n}\n\n\n// Visibility utilities\n// Note: Deprecated .visible-xs, .visible-sm, .visible-md, and .visible-lg as of v3.2.0\n.visible-xs,\n.visible-sm,\n.visible-md,\n.visible-lg {\n .responsive-invisibility();\n}\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\n.visible-xs {\n @media (max-width: @screen-xs-max) {\n .responsive-visibility();\n }\n}\n.visible-xs-block {\n @media (max-width: @screen-xs-max) {\n display: block !important;\n }\n}\n.visible-xs-inline {\n @media (max-width: @screen-xs-max) {\n display: inline !important;\n }\n}\n.visible-xs-inline-block {\n @media (max-width: @screen-xs-max) {\n display: inline-block !important;\n }\n}\n\n.visible-sm {\n @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n .responsive-visibility();\n }\n}\n.visible-sm-block {\n @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n display: block !important;\n }\n}\n.visible-sm-inline {\n @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n display: inline !important;\n }\n}\n.visible-sm-inline-block {\n @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n display: inline-block !important;\n }\n}\n\n.visible-md {\n @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n .responsive-visibility();\n }\n}\n.visible-md-block {\n @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n display: block !important;\n }\n}\n.visible-md-inline {\n @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n display: inline !important;\n }\n}\n.visible-md-inline-block {\n @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n display: inline-block !important;\n }\n}\n\n.visible-lg {\n @media (min-width: @screen-lg-min) {\n .responsive-visibility();\n }\n}\n.visible-lg-block {\n @media (min-width: @screen-lg-min) {\n display: block !important;\n }\n}\n.visible-lg-inline {\n @media (min-width: @screen-lg-min) {\n display: inline !important;\n }\n}\n.visible-lg-inline-block {\n @media (min-width: @screen-lg-min) {\n display: inline-block !important;\n }\n}\n\n.hidden-xs {\n @media (max-width: @screen-xs-max) {\n .responsive-invisibility();\n }\n}\n.hidden-sm {\n @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n .responsive-invisibility();\n }\n}\n.hidden-md {\n @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n .responsive-invisibility();\n }\n}\n.hidden-lg {\n @media (min-width: @screen-lg-min) {\n .responsive-invisibility();\n }\n}\n\n\n// Print utilities\n//\n// Media queries are placed on the inside to be mixin-friendly.\n\n// Note: Deprecated .visible-print as of v3.2.0\n.visible-print {\n .responsive-invisibility();\n\n @media print {\n .responsive-visibility();\n }\n}\n.visible-print-block {\n display: none !important;\n\n @media print {\n display: block !important;\n }\n}\n.visible-print-inline {\n display: none !important;\n\n @media print {\n display: inline !important;\n }\n}\n.visible-print-inline-block {\n display: none !important;\n\n @media print {\n display: inline-block !important;\n }\n}\n\n.hidden-print {\n @media print {\n .responsive-invisibility();\n }\n}\n","// Responsive utilities\n\n//\n// More easily include all the states for responsive-utilities.less.\n.responsive-visibility() {\n display: block !important;\n table& { display: table !important; }\n tr& { display: table-row !important; }\n th&,\n td& { display: table-cell !important; }\n}\n\n.responsive-invisibility() {\n display: none !important;\n}\n"]} \ No newline at end of file diff --git a/src/redux/csf/bootstrap/fonts/glyphicons-halflings-regular.eot b/src/redux/csf/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/src/redux/csf/bootstrap/fonts/glyphicons-halflings-regular.ttf b/src/redux/csf/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/src/redux/csf/bootstrap/fonts/glyphicons-halflings-regular.woff2 b/src/redux/csf/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/src/redux/csf/bootstrap/js/bootstrap.min.js b/src/redux/csf/bootstrap/js/bootstrap.min.js new file mode 100644 index 000000000..07cf295be --- /dev/null +++ b/src/redux/csf/bootstrap/js/bootstrap.min.js @@ -0,0 +1,7 @@ +/*! + * Bootstrap v3.3.7 (http://getbootstrap.com) + * Copyright 2011-2017 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/src/redux/csf/chosen-sprite.png b/src/redux/csf/chosen-sprite.png new file mode 100644 index 0000000000000000000000000000000000000000..3611ae4ace1c4b1cbeacd6145b5a79cbc72e0bdc GIT binary patch literal 646 zcmV;10(t$3P)0006_Nkl&pbAC0n?)s%2x5M$#UgGxI1~gymp~v; zh<`zGaTJP5BybQY4tlRo;SIcmE0t>ueW3>*u6N;@_u;;|BoL8PuhZ#FWY9$(flan1oVvxDBL8~}0Q5z;^2p>Ov z7}Q$E7=l>$BZLUt1*uKMCaQwKYf$lsJCyerWMd+%BeGH6f_f&Vpy%=$BN%uK%Ahxi zF+%Jj=Pc-WXF;djSiJw|m4>cN%^Fi|FBZ!E{_yJLS?RI<3U696XLkQSs z{{&kQJ$K(#5CgC1;GbA>mjm56zJZ^-Hg2_ASKI_K@CybPh7Rq}8ud``)NM~eZx}qT z)oK?Lf>t!B;%Uh}*P+)Ef?jbx#w|BNEVb(l{2LK}m#fw4xx>ddF;&j}!S{N-e!<&Q z?kvzyI_AT@H-u4tUz1h&GCh8>?TnA~?BZ7WGP<9`r gQ6DuZO!_~60ju@{TzXF%TmS$707*qoM6N<$g2#CqL;wH) literal 0 HcmV?d00001 diff --git a/src/redux/csf/chosen-sprite@2x.png b/src/redux/csf/chosen-sprite@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..ffe4d7d1121ca45cd35783696940050c690a8676 GIT binary patch literal 872 zcmeAS@N?(olHy`uVBq!ia0vp^89?mC!3-o5mOWetq|OBRgt-3y{~yTgfB`oc01C8& zL0el}Lqh|Q1oD8A5J8A6G6@lfkU;ftMr&&;+$f+RkloVK0wm!8C|FWb0x`e2xj8g6 z6i7l;BAWwL4-tfu5G@ccP!{MmqnYOy06pVW666=m!0_*bfx(A_gav;C1PU5HKT!C5 z;g7@l4POuZ{>hQBP{j4uqq`I2WP9&Sn{}I8xJi*&v*QL&+Dw-Bf-CQLyLk0Ht2-;T zynum$iPO`?F{C2y?bYjfj|~J`6Xz~`vM4Ef+U{Vpli%)D%kKSey_RG0Bi9Xw4jtOb z@!)?~_%DVelO793W#Pl3vjdNCDTnGGb(^YY+BbF2;mJK!nq}@nBGoHxCn#7X*gdxr z+~ZQF6rpL6;MDP)JzehcJBL53AM-QU?@65Plc4-}1EW@`H@EEGrnFmTubZ~5iUzVn zrZYyBIm|RmW$3F@+wkq2)c>|mGh5Rv3%(p~zjStyruBl(TP2_51LpTH2noN*e&}J; z1;$+4EpJ(Mb+^1}Fv>ms%b`r}+KYy~zf5x(4?8l28%eNnEHzx({;NGP)_hX&tEw9t zSKv=Qjt(d#~b;F7hbDdUu$OUK8iumkkl&-=~$APCd2zdqHg6@=Z#Pt*5RY_s@Hw*YS9+ z^u)7AmzM6Ux!dus_!gJY)Vtf?+t>a3wO2S)_Vct=T}#@RuG(h!d8WYZS9Tst+VfKv zt~zntPsvfyqLY`klZSPslCz_dlcSRJLa$Px)_+W2Y&u!?oJrIMCNTz2S3j3^P6"+t.group_label+""+t.html:t.html},t.prototype.mouse_enter=function(){return this.mouse_on_container=!0},t.prototype.mouse_leave=function(){return this.mouse_on_container=!1},t.prototype.input_focus=function(t){if(this.is_multiple){if(!this.active_field)return setTimeout(function(t){return function(){return t.container_mousedown()}}(this),50)}else if(!this.active_field)return this.activate_field()},t.prototype.input_blur=function(t){if(!this.mouse_on_container)return this.active_field=!1,setTimeout(function(t){return function(){return t.blur_test()}}(this),100)},t.prototype.label_click_handler=function(t){return this.is_multiple?this.container_mousedown(t):this.activate_field()},t.prototype.results_option_build=function(t){var e,s,i,n,r,o,h;for(e="",h=0,n=0,r=(o=this.results_data).length;n=this.max_shown_results));n++);return e},t.prototype.result_add_option=function(t){var e,s;return t.search_match&&this.include_option_in_results(t)?(e=[],t.disabled||t.selected&&this.is_multiple||e.push("active-result"),!t.disabled||t.selected&&this.is_multiple||e.push("disabled-result"),t.selected&&e.push("result-selected"),null!=t.group_array_index&&e.push("group-option"),""!==t.classes&&e.push(t.classes),s=document.createElement("li"),s.className=e.join(" "),s.style.cssText=t.style,s.setAttribute("data-option-array-index",t.array_index),s.innerHTML=t.highlighted_html||t.html,t.title&&(s.title=t.title),this.outerHTML(s)):""},t.prototype.result_add_group=function(t){var e,s;return(t.search_match||t.group_match)&&t.active_options>0?((e=[]).push("group-result"),t.classes&&e.push(t.classes),s=document.createElement("li"),s.className=e.join(" "),s.innerHTML=t.highlighted_html||this.escape_html(t.label),t.title&&(s.title=t.title),this.outerHTML(s)):""},t.prototype.results_update_field=function(){if(this.set_default_text(),this.is_multiple||this.results_reset_cleanup(),this.result_clear_highlight(),this.results_build(),this.results_showing)return this.winnow_results()},t.prototype.reset_single_select_options=function(){var t,e,s,i,n;for(n=[],t=0,e=(s=this.results_data).length;t"+this.escape_html(e)+""+this.escape_html(d)),null!=_&&(_.group_match=!0)):null!=n.group_array_index&&this.results_data[n.group_array_index].search_match&&(n.search_match=!0)));return this.result_clear_highlight(),c<1&&o.length?(this.update_results_content(""),this.no_results(o)):(this.update_results_content(this.results_option_build()),this.winnow_results_set_highlight())},t.prototype.get_search_regex=function(t){var e,s;return s=this.search_contains?t:"(^|\\s|\\b)"+t+"[^\\s]*",this.enable_split_word_search||this.search_contains||(s="^"+s),e=this.case_sensitive_search?"":"i",new RegExp(s,e)},t.prototype.search_string_match=function(t,e){var s;return s=e.exec(t),!this.search_contains&&(null!=s?s[1]:void 0)&&(s.index+=1),s},t.prototype.choices_count=function(){var t,e,s;if(null!=this.selected_option_count)return this.selected_option_count;for(this.selected_option_count=0,t=0,e=(s=this.form_field.options).length;t0?this.keydown_backstroke():this.pending_backstroke||(this.result_clear_highlight(),this.results_search());break;case 13:t.preventDefault(),this.results_showing&&this.result_select(t);break;case 27:this.results_showing&&this.results_hide();break;case 9:case 16:case 17:case 18:case 38:case 40:case 91:break;default:this.results_search()}},t.prototype.clipboard_event_checker=function(t){if(!this.is_disabled)return setTimeout(function(t){return function(){return t.results_search()}}(this),50)},t.prototype.container_width=function(){return null!=this.options.width?this.options.width:this.form_field.offsetWidth+"px"},t.prototype.include_option_in_results=function(t){return!(this.is_multiple&&!this.display_selected_options&&t.selected)&&(!(!this.display_disabled_options&&t.disabled)&&!t.empty)},t.prototype.search_results_touchstart=function(t){return this.touch_started=!0,this.search_results_mouseover(t)},t.prototype.search_results_touchmove=function(t){return this.touch_started=!1,this.search_results_mouseout(t)},t.prototype.search_results_touchend=function(t){if(this.touch_started)return this.search_results_mouseup(t)},t.prototype.outerHTML=function(t){var e;return t.outerHTML?t.outerHTML:((e=document.createElement("div")).appendChild(t),e.innerHTML)},t.prototype.get_single_html=function(){return'
      \n '+this.default_text+'\n
      \n
      \n
      \n \n
        \n
        '},t.prototype.get_multi_html=function(){return'
          \n
        • \n \n
        • \n
        \n
        \n
          \n
          '},t.prototype.get_no_results_html=function(t){return'
        • \n '+this.results_none_found+" "+this.escape_html(t)+"\n
        • "},t.browser_is_supported=function(){return"Microsoft Internet Explorer"===window.navigator.appName?document.documentMode>=8:!(/iP(od|hone)/i.test(window.navigator.userAgent)||/IEMobile/i.test(window.navigator.userAgent)||/Windows Phone/i.test(window.navigator.userAgent)||/BlackBerry/i.test(window.navigator.userAgent)||/BB10/i.test(window.navigator.userAgent)||/Android.*Mobile/i.test(window.navigator.userAgent))},t.default_multiple_text="Select Some Options",t.default_single_text="Select an Option",t.default_no_result_text="No results match",t}(),(t=jQuery).fn.extend({chosen:function(i){return e.browser_is_supported()?this.each(function(e){var n,r;r=(n=t(this)).data("chosen"),"destroy"!==i?r instanceof s||n.data("chosen",new s(this,i)):r instanceof s&&r.destroy()}):this}}),s=function(s){function n(){return n.__super__.constructor.apply(this,arguments)}return r(n,e),n.prototype.setup=function(){return this.form_field_jq=t(this.form_field),this.current_selectedIndex=this.form_field.selectedIndex},n.prototype.set_up_html=function(){var e,s;return(e=["chosen-container"]).push("chosen-container-"+(this.is_multiple?"multi":"single")),this.inherit_select_classes&&this.form_field.className&&e.push(this.form_field.className),this.is_rtl&&e.push("chosen-rtl"),s={"class":e.join(" "),title:this.form_field.title},this.form_field.id.length&&(s.id=this.form_field.id.replace(/[^\w]/g,"_")+"_chosen"),this.container=t("
          ",s),this.container.width(this.container_width()),this.is_multiple?this.container.html(this.get_multi_html()):this.container.html(this.get_single_html()),this.form_field_jq.hide().after(this.container),this.dropdown=this.container.find("div.chosen-drop").first(),this.search_field=this.container.find("input").first(),this.search_results=this.container.find("ul.chosen-results").first(),this.search_field_scale(),this.search_no_results=this.container.find("li.no-results").first(),this.is_multiple?(this.search_choices=this.container.find("ul.chosen-choices").first(),this.search_container=this.container.find("li.search-field").first()):(this.search_container=this.container.find("div.chosen-search").first(),this.selected_item=this.container.find(".chosen-single").first()),this.results_build(),this.set_tab_index(),this.set_label_behavior()},n.prototype.on_ready=function(){return this.form_field_jq.trigger("chosen:ready",{chosen:this})},n.prototype.register_observers=function(){return this.container.on("touchstart.chosen",function(t){return function(e){t.container_mousedown(e)}}(this)),this.container.on("touchend.chosen",function(t){return function(e){t.container_mouseup(e)}}(this)),this.container.on("mousedown.chosen",function(t){return function(e){t.container_mousedown(e)}}(this)),this.container.on("mouseup.chosen",function(t){return function(e){t.container_mouseup(e)}}(this)),this.container.on("mouseenter.chosen",function(t){return function(e){t.mouse_enter(e)}}(this)),this.container.on("mouseleave.chosen",function(t){return function(e){t.mouse_leave(e)}}(this)),this.search_results.on("mouseup.chosen",function(t){return function(e){t.search_results_mouseup(e)}}(this)),this.search_results.on("mouseover.chosen",function(t){return function(e){t.search_results_mouseover(e)}}(this)),this.search_results.on("mouseout.chosen",function(t){return function(e){t.search_results_mouseout(e)}}(this)),this.search_results.on("mousewheel.chosen DOMMouseScroll.chosen",function(t){return function(e){t.search_results_mousewheel(e)}}(this)),this.search_results.on("touchstart.chosen",function(t){return function(e){t.search_results_touchstart(e)}}(this)),this.search_results.on("touchmove.chosen",function(t){return function(e){t.search_results_touchmove(e)}}(this)),this.search_results.on("touchend.chosen",function(t){return function(e){t.search_results_touchend(e)}}(this)),this.form_field_jq.on("chosen:updated.chosen",function(t){return function(e){t.results_update_field(e)}}(this)),this.form_field_jq.on("chosen:activate.chosen",function(t){return function(e){t.activate_field(e)}}(this)),this.form_field_jq.on("chosen:open.chosen",function(t){return function(e){t.container_mousedown(e)}}(this)),this.form_field_jq.on("chosen:close.chosen",function(t){return function(e){t.close_field(e)}}(this)),this.search_field.on("blur.chosen",function(t){return function(e){t.input_blur(e)}}(this)),this.search_field.on("keyup.chosen",function(t){return function(e){t.keyup_checker(e)}}(this)),this.search_field.on("keydown.chosen",function(t){return function(e){t.keydown_checker(e)}}(this)),this.search_field.on("focus.chosen",function(t){return function(e){t.input_focus(e)}}(this)),this.search_field.on("cut.chosen",function(t){return function(e){t.clipboard_event_checker(e)}}(this)),this.search_field.on("paste.chosen",function(t){return function(e){t.clipboard_event_checker(e)}}(this)),this.is_multiple?this.search_choices.on("click.chosen",function(t){return function(e){t.choices_click(e)}}(this)):this.container.on("click.chosen",function(t){t.preventDefault()})},n.prototype.destroy=function(){return t(this.container[0].ownerDocument).off("click.chosen",this.click_test_action),this.form_field_label.length>0&&this.form_field_label.off("click.chosen"),this.search_field[0].tabIndex&&(this.form_field_jq[0].tabIndex=this.search_field[0].tabIndex),this.container.remove(),this.form_field_jq.removeData("chosen"),this.form_field_jq.show()},n.prototype.search_field_disabled=function(){return this.is_disabled=this.form_field.disabled||this.form_field_jq.parents("fieldset").is(":disabled"),this.container.toggleClass("chosen-disabled",this.is_disabled),this.search_field[0].disabled=this.is_disabled,this.is_multiple||this.selected_item.off("focus.chosen",this.activate_field),this.is_disabled?this.close_field():this.is_multiple?void 0:this.selected_item.on("focus.chosen",this.activate_field)},n.prototype.container_mousedown=function(e){var s;if(!this.is_disabled)return!e||"mousedown"!==(s=e.type)&&"touchstart"!==s||this.results_showing||e.preventDefault(),null!=e&&t(e.target).hasClass("search-choice-close")?void 0:(this.active_field?this.is_multiple||!e||t(e.target)[0]!==this.selected_item[0]&&!t(e.target).parents("a.chosen-single").length||(e.preventDefault(),this.results_toggle()):(this.is_multiple&&this.search_field.val(""),t(this.container[0].ownerDocument).on("click.chosen",this.click_test_action),this.results_show()),this.activate_field())},n.prototype.container_mouseup=function(t){if("ABBR"===t.target.nodeName&&!this.is_disabled)return this.results_reset(t)},n.prototype.search_results_mousewheel=function(t){var e;if(t.originalEvent&&(e=t.originalEvent.deltaY||-t.originalEvent.wheelDelta||t.originalEvent.detail),null!=e)return t.preventDefault(),"DOMMouseScroll"===t.type&&(e*=40),this.search_results.scrollTop(e+this.search_results.scrollTop())},n.prototype.blur_test=function(t){if(!this.active_field&&this.container.hasClass("chosen-container-active"))return this.close_field()},n.prototype.close_field=function(){return t(this.container[0].ownerDocument).off("click.chosen",this.click_test_action),this.active_field=!1,this.results_hide(),this.container.removeClass("chosen-container-active"),this.clear_backstroke(),this.show_search_field_default(),this.search_field_scale(),this.search_field.blur()},n.prototype.activate_field=function(){if(!this.is_disabled)return this.container.addClass("chosen-container-active"),this.active_field=!0,this.search_field.val(this.search_field.val()),this.search_field.focus()},n.prototype.test_active_click=function(e){var s;return(s=t(e.target).closest(".chosen-container")).length&&this.container[0]===s[0]?this.active_field=!0:this.close_field()},n.prototype.results_build=function(){return this.parsing=!0,this.selected_option_count=null,this.results_data=i.select_to_array(this.form_field),this.is_multiple?this.search_choices.find("li.search-choice").remove():this.is_multiple||(this.single_set_selected_text(),this.disable_search||this.form_field.options.length<=this.disable_search_threshold?(this.search_field[0].readOnly=!0,this.container.addClass("chosen-container-single-nosearch")):(this.search_field[0].readOnly=!1,this.container.removeClass("chosen-container-single-nosearch"))),this.update_results_content(this.results_option_build({first:!0})),this.search_field_disabled(),this.show_search_field_default(),this.search_field_scale(),this.parsing=!1},n.prototype.result_do_highlight=function(t){var e,s,i,n,r;if(t.length){if(this.result_clear_highlight(),this.result_highlight=t,this.result_highlight.addClass("highlighted"),i=parseInt(this.search_results.css("maxHeight"),10),r=this.search_results.scrollTop(),n=i+r,s=this.result_highlight.position().top+this.search_results.scrollTop(),(e=s+this.result_highlight.outerHeight())>=n)return this.search_results.scrollTop(e-i>0?e-i:0);if(s0)return this.form_field_label.on("click.chosen",this.label_click_handler)},n.prototype.show_search_field_default=function(){return this.is_multiple&&this.choices_count()<1&&!this.active_field?(this.search_field.val(this.default_text),this.search_field.addClass("default")):(this.search_field.val(""),this.search_field.removeClass("default"))},n.prototype.search_results_mouseup=function(e){var s;if((s=t(e.target).hasClass("active-result")?t(e.target):t(e.target).parents(".active-result").first()).length)return this.result_highlight=s,this.result_select(e),this.search_field.focus()},n.prototype.search_results_mouseover=function(e){var s;if(s=t(e.target).hasClass("active-result")?t(e.target):t(e.target).parents(".active-result").first())return this.result_do_highlight(s)},n.prototype.search_results_mouseout=function(e){if(t(e.target).hasClass("active-result")||t(e.target).parents(".active-result").first())return this.result_clear_highlight()},n.prototype.choice_build=function(e){var s,i;return s=t("
        • ",{"class":"search-choice"}).html(""+this.choice_label(e)+""),e.disabled?s.addClass("search-choice-disabled"):((i=t("",{"class":"search-choice-close","data-option-array-index":e.array_index})).on("click.chosen",function(t){return function(e){return t.choice_destroy_link_click(e)}}(this)),s.append(i)),this.search_container.before(s)},n.prototype.choice_destroy_link_click=function(e){if(e.preventDefault(),e.stopPropagation(),!this.is_disabled)return this.choice_destroy(t(e.target))},n.prototype.choice_destroy=function(t){if(this.result_deselect(t[0].getAttribute("data-option-array-index")))return this.active_field?this.search_field.focus():this.show_search_field_default(),this.is_multiple&&this.choices_count()>0&&this.get_search_field_value().length<1&&this.results_hide(),t.parents("li").first().remove(),this.search_field_scale()},n.prototype.results_reset=function(){if(this.reset_single_select_options(),this.form_field.options[0].selected=!0,this.single_set_selected_text(),this.show_search_field_default(),this.results_reset_cleanup(),this.trigger_form_field_change(),this.active_field)return this.results_hide()},n.prototype.results_reset_cleanup=function(){return this.current_selectedIndex=this.form_field.selectedIndex,this.selected_item.find("abbr").remove()},n.prototype.result_select=function(t){var e,s;if(this.result_highlight)return e=this.result_highlight,this.result_clear_highlight(),this.is_multiple&&this.max_selected_options<=this.choices_count()?(this.form_field_jq.trigger("chosen:maxselected",{chosen:this}),!1):(this.is_multiple?e.removeClass("active-result"):this.reset_single_select_options(),e.addClass("result-selected"),s=this.results_data[e[0].getAttribute("data-option-array-index")],s.selected=!0,this.form_field.options[s.options_index].selected=!0,this.selected_option_count=null,this.search_field.val(""),this.is_multiple?this.choice_build(s):this.single_set_selected_text(this.choice_label(s)),this.is_multiple&&(!this.hide_results_on_select||t.metaKey||t.ctrlKey)?this.winnow_results():(this.results_hide(),this.show_search_field_default()),(this.is_multiple||this.form_field.selectedIndex!==this.current_selectedIndex)&&this.trigger_form_field_change({selected:this.form_field.options[s.options_index].value}),this.current_selectedIndex=this.form_field.selectedIndex,t.preventDefault(),this.search_field_scale())},n.prototype.single_set_selected_text=function(t){return null==t&&(t=this.default_text),t===this.default_text?this.selected_item.addClass("chosen-default"):(this.single_deselect_control_build(),this.selected_item.removeClass("chosen-default")),this.selected_item.find("span").html(t)},n.prototype.result_deselect=function(t){var e;return e=this.results_data[t],!this.form_field.options[e.options_index].disabled&&(e.selected=!1,this.form_field.options[e.options_index].selected=!1,this.selected_option_count=null,this.result_clear_highlight(),this.results_showing&&this.winnow_results(),this.trigger_form_field_change({deselected:this.form_field.options[e.options_index].value}),this.search_field_scale(),!0)},n.prototype.single_deselect_control_build=function(){if(this.allow_single_deselect)return this.selected_item.find("abbr").length||this.selected_item.find("span").first().after(''),this.selected_item.addClass("chosen-single-with-deselect")},n.prototype.get_search_field_value=function(){return this.search_field.val()},n.prototype.get_search_text=function(){return t.trim(this.get_search_field_value())},n.prototype.escape_html=function(e){return t("
          ").text(e).html()},n.prototype.winnow_results_set_highlight=function(){var t,e;if(e=this.is_multiple?[]:this.search_results.find(".result-selected.active-result"),null!=(t=e.length?e.first():this.search_results.find(".active-result").first()))return this.result_do_highlight(t)},n.prototype.no_results=function(t){var e;return e=this.get_no_results_html(t),this.search_results.append(e),this.form_field_jq.trigger("chosen:no_results",{chosen:this})},n.prototype.no_results_clear=function(){return this.search_results.find(".no-results").remove()},n.prototype.keydown_arrow=function(){var t;return this.results_showing&&this.result_highlight?(t=this.result_highlight.nextAll("li.active-result").first())?this.result_do_highlight(t):void 0:this.results_show()},n.prototype.keyup_arrow=function(){var t;return this.results_showing||this.is_multiple?this.result_highlight?(t=this.result_highlight.prevAll("li.active-result")).length?this.result_do_highlight(t.first()):(this.choices_count()>0&&this.results_hide(),this.result_clear_highlight()):void 0:this.results_show()},n.prototype.keydown_backstroke=function(){var t;return this.pending_backstroke?(this.choice_destroy(this.pending_backstroke.find("a").first()),this.clear_backstroke()):(t=this.search_container.siblings("li.search-choice").last()).length&&!t.hasClass("search-choice-disabled")?(this.pending_backstroke=t,this.single_backstroke_delete?this.keydown_backstroke():this.pending_backstroke.addClass("search-choice-focus")):void 0},n.prototype.clear_backstroke=function(){return this.pending_backstroke&&this.pending_backstroke.removeClass("search-choice-focus"),this.pending_backstroke=null},n.prototype.search_field_scale=function(){var e,s,i,n,r,o,h;if(this.is_multiple){for(r={position:"absolute",left:"-1000px",top:"-1000px",display:"none",whiteSpace:"pre"},s=0,i=(o=["fontSize","fontStyle","fontWeight","fontFamily","lineHeight","textTransform","letterSpacing"]).length;s").css(r)).text(this.get_search_field_value()),t("body").append(e),h=e.width()+25,e.remove(),this.container.is(":visible")&&(h=Math.min(this.container.outerWidth()-10,h)),this.search_field.width(h)}},n.prototype.trigger_form_field_change=function(t){return this.form_field_jq.trigger("input",t),this.form_field_jq.trigger("change",t)},n}()}).call(this); \ No newline at end of file diff --git a/src/redux/csf/configserver.css b/src/redux/csf/configserver.css new file mode 100644 index 000000000..8b02267ac --- /dev/null +++ b/src/redux/csf/configserver.css @@ -0,0 +1,193 @@ +.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; +} +.btn-csf-config:focus, +.btn-csf-config:hover, +.btn-csf-config:active, +.btn-csf-config.active { + background-color:#BDECB6 !important; + -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; +} +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; +} +.comment { + border-radius:5px; + border: 1px solid #DDDDDD; + padding: 10px; + font-family: Courier New, Courier; + font-size: 14px; +} +.value-default { + background:#F5F5F5; + padding:2px; + border-radius:5px; +} +.value-other { + background:#F4F4EA; + padding:2px; + border-radius:5px; +} +.value-disabled { + background:#F5F5F5; + padding:2px; + border-radius:5px; +} +.value-warning { + background:#FFC0CB; + padding:2px; + border-radius:5px; +} +.section { + border-radius:5px; + border: 2px solid #990000; + padding: 10px; + font-size:16px; + font-weight:bold; +} +.toplink { + cursor: pointer; + position: fixed; + top: 20px; + right: 20px; + z-index: 9999 !important; + font-size: 36px; + opacity: 0.5; + display:none; +} +.botlink { + cursor: pointer; + position:fixed; + bottom:20px; + right:20px; + z-index: 9999 !important; + font-size: 36px; + opacity: 0.5; + display:none; +} diff --git a/src/redux/csf/csf-loader.gif b/src/redux/csf/csf-loader.gif new file mode 100644 index 0000000000000000000000000000000000000000..dd1828fc576d4a07f72af65debc91f5dff3894c4 GIT binary patch literal 3951 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 literal 0 HcmV?d00001 diff --git a/src/redux/csf/csf.svg b/src/redux/csf/csf.svg new file mode 100644 index 000000000..1c928ea0d --- /dev/null +++ b/src/redux/csf/csf.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/redux/csf/csf_small.png b/src/redux/csf/csf_small.png new file mode 100644 index 0000000000000000000000000000000000000000..82b9642813b6dd489dc337a90485858218e7d584 GIT binary patch literal 2211 zcmV;U2weAxP);j8UX6p=h z=9|5H_MCJ7@0|bp&VQG~ZGLh74q%#qzXO;i;O_vY3HUpJX#%%8fz4(kSSN&aa1eqZ zxPfQj`H?oW)FznCuvx7`^Lm5yo5SIl8UZIg%-(a(t!-f71~lm(p&~XCRSB`DObp)eA`!T9<@O?A>*|t% z|25%P|6c^oPe#CT?HUEW2>n4E_>^Gif5O4m-R+)Q0*~_5;XY|#Yz~)3t`aqnHN~;R z<1b980TM00B}H6)Zu#bSYltkGmLp;KK7tx^H)5v2z-SsBnO zvY}Neq&~yQ%|=J*adbCpp~*fZejf`qR+IU$=U8P9nhAXuFG>U)*S>_)U~r3nu(n1F zUcVqvTzz402#ia=iQcE4#fi9B92XIT6Y+5X!_4YU&75Qc#|<8CQm~fpdKMU+@X>6yzS*iIuazpK^YY zMBry~@cZr;cfhnJ7zS=88mK+Xi}j5~HleNXQxt{0=3%3gfu%@8>P9qY9`tIn9yU5y zQ;q8^;3w~aVexO#KZ8Smpd5ymWDpL18~lL>z;6$R@g+IFm>YnC8Fx-9T=u)JxBw+@ zEko`UMal>_rlq1KE8VNe*?bpuqeRREtAFBq(EpU&=2Z%Qjtu?x2EwpN4&j4P@JAko z@b~**N(_P_M24Q=d!W3-KLprZ`2id*x3<{qfK?JP)gH#T{wSu6X)OgAHjnO!z{^Bn zR|xn|9s!^E9SA!qjh4{Pd`pIA**7M%z!3s(-ZX*c@d(H{TxxB$SshM`M8Ix`@$D6o z>nxiGen$xOFH)dCmy1F3s)xaU`Y7q-KFLxaqa6yBp<>S6Vy=&`fnz9o{r5Mifel_Y zz~(wixYVMxS)Jn$V6MY&qSanZ_dAF{&V%5K7J$!~Pdh?dSTPU!*#WpZhl1R_9l9(k z%np2rc2y4Am4_wdW|3DnqpPGqymz&W$c9dl1zmO~jmZ|jyFqaX=T4U6e8VZ|G7g}f z%|8U)A^JR=j^2wGoGklA0<6+Byz;Uug@oNiU?*WK1@9v8h?q*ukyyL_2^kD??!x8e zZ=gHs&u9!^jvA^uYpD7hMs-XCYSu)%wTbOiy=v1B;6K$>sHT&=CNbUv)oY_sO?_)= zCu&oYN3b~wb*ahd>lsyzGAq@8|1s!)a5wnB21|L*2<#d{9_4?@QxJ+C2Y>JZNejP` zlhEb3{xuHQh+K zvwehsz4vpeX!}FJNcs#DP=vyAY9$c}1Apv(0*QHlD3usPPW1~pj0@$cpE=v-V7>wZ zy^?@e21q&XT74PJ$6tU=vw;XKrQpeh3Ku{)G#|!Di2xI{X~{e^a(*P>G#O!d{skES z#ElSO_Nk=RuMLMyyAgv8v7~_~i2xmH%vRqcH(E)SyN&w28I1a&62s?eG$x7)zT7ES zqh2+@s!vmVym$(WDa2NPUl7bC&%xTX4z{KwaThE#;ou8M2l?bkbSALA!tP+07IQee zeLGImifWX(E;Qxkq3H;M9c_e$S`nnsTjDG5fDiv<3`ylluA?|eHbeCV+8cC&PDATVJIit ztoX|+5#w^w|gnDAoBkC7_5&JgJuM*L%T3o7eTu~DYRcAV5U?1((?fx zr>*NGUK-}Jy}F&m+qOWvf3H`YW%GG`r4)9&4^s^7!cIDYl|Q7Q*N!1T_oove6hA{d z5G0-lH@1eLY5vze#CXfa-1}*0{^ti?MLzB;C37R=@~3GRh=k(1ur|iI6A(Yw!(6-& z{O&-QN$_91Bd6Nr4v!$eY69cF)LXS0n4;-D_+yS7=xvt! zXN~)iTdGEHW(Qoalr`lrZRTJudWI}i3f!hi67AG-av51IhtH$P%kSh|FZAQSk-fI$ z<}{F&0`0y%UjH!g>5nbj*-n^M2^cuB7}okILL>%`|Bl4_BN(!G;9S8`=#CvlC!wvl z5UnM}?x42w9UbVXtUzl~f%x55w2=6_8|uksHE1a+L>rCopyv#ulb(IOuXkbs(tj%s z*sor&+j{D3w(e67+ZnCJ-hUm=vEAq#u~FZ#uzP9q6?TVHgm~|CjvM0i-|POqrV04_ lnkL}yYnp(+uiKu${{V%K8uiA@uHFCu002ovPDHLkV1kYBBG&)_ literal 0 HcmV?d00001 diff --git a/src/redux/csf/jquery.min.js b/src/redux/csf/jquery.min.js new file mode 100644 index 000000000..e83647587 --- /dev/null +++ b/src/redux/csf/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(" + diff --git a/src/redux/cyberpanel/configservercsf/__init__.py b/src/redux/cyberpanel/configservercsf/__init__.py new file mode 100644 index 000000000..7002da052 --- /dev/null +++ b/src/redux/cyberpanel/configservercsf/__init__.py @@ -0,0 +1 @@ +#default_app_config = 'configservercsf.apps.configservercsfConfig' diff --git a/src/redux/cyberpanel/configservercsf/admin.py b/src/redux/cyberpanel/configservercsf/admin.py new file mode 100644 index 000000000..13be29d96 --- /dev/null +++ b/src/redux/cyberpanel/configservercsf/admin.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.contrib import admin + +# Register your models here. diff --git a/src/redux/cyberpanel/configservercsf/apps.py b/src/redux/cyberpanel/configservercsf/apps.py new file mode 100644 index 000000000..cbae2c824 --- /dev/null +++ b/src/redux/cyberpanel/configservercsf/apps.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.apps import AppConfig + +class configservercsfConfig(AppConfig): + name = 'configservercsf' + + def ready(self): + import signals diff --git a/src/redux/cyberpanel/configservercsf/config b/src/redux/cyberpanel/configservercsf/config new file mode 100644 index 000000000..e69de29bb diff --git a/src/redux/cyberpanel/configservercsf/meta.xml b/src/redux/cyberpanel/configservercsf/meta.xml new file mode 100644 index 000000000..4515593e9 --- /dev/null +++ b/src/redux/cyberpanel/configservercsf/meta.xml @@ -0,0 +1,7 @@ + + + ConfigServer Security and Firewall + plugin + ConfigServer Security and Firewall + 1.0 + diff --git a/src/redux/cyberpanel/configservercsf/migrations/__init__.py b/src/redux/cyberpanel/configservercsf/migrations/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/redux/cyberpanel/configservercsf/models.py b/src/redux/cyberpanel/configservercsf/models.py new file mode 100644 index 000000000..1dfab7604 --- /dev/null +++ b/src/redux/cyberpanel/configservercsf/models.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models + +# Create your models here. diff --git a/src/redux/cyberpanel/configservercsf/signals.py b/src/redux/cyberpanel/configservercsf/signals.py new file mode 100644 index 000000000..3db8f8c4a --- /dev/null +++ b/src/redux/cyberpanel/configservercsf/signals.py @@ -0,0 +1,13 @@ +from django.dispatch import receiver +from django.shortcuts import redirect +from firewall.signals import preFirewallHome, preCSF + +@receiver(preFirewallHome) +def csfFirewallHome(sender, **kwargs): + request = kwargs['request'] + return redirect('/configservercsf/') + +@receiver(preCSF) +def csfCSF(sender, **kwargs): + request = kwargs['request'] + return redirect('/configservercsf/') diff --git a/src/redux/cyberpanel/configservercsf/templates/configservercsf/index.html b/src/redux/cyberpanel/configservercsf/templates/configservercsf/index.html new file mode 100644 index 000000000..fcae8b1a0 --- /dev/null +++ b/src/redux/cyberpanel/configservercsf/templates/configservercsf/index.html @@ -0,0 +1,17 @@ +{% extends "baseTemplate/index.html" %} +{% load i18n %} +{% block title %}ConfigServer Security and Firewall{% endblock %} +{% block content %} + +{% load static %} + + + + +{% endblock %} diff --git a/src/redux/cyberpanel/configservercsf/templates/configservercsf/menu.html b/src/redux/cyberpanel/configservercsf/templates/configservercsf/menu.html new file mode 100644 index 000000000..d2888156f --- /dev/null +++ b/src/redux/cyberpanel/configservercsf/templates/configservercsf/menu.html @@ -0,0 +1,25 @@ + + + ConfigServer Services + + + + +
        • diff --git a/src/redux/cyberpanel/configservercsf/tests.py b/src/redux/cyberpanel/configservercsf/tests.py new file mode 100644 index 000000000..5982e6bcd --- /dev/null +++ b/src/redux/cyberpanel/configservercsf/tests.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.test import TestCase + +# Create your tests here. diff --git a/src/redux/cyberpanel/configservercsf/urls.py b/src/redux/cyberpanel/configservercsf/urls.py new file mode 100644 index 000000000..c4cdb005b --- /dev/null +++ b/src/redux/cyberpanel/configservercsf/urls.py @@ -0,0 +1,8 @@ +from django.conf.urls import url +from . import views + +urlpatterns = [ + + url(r'^$', views.configservercsf, name='configservercsf'), + url(r'^iframe/$', views.configservercsfiframe, name='configservercsfiframe'), +] diff --git a/src/redux/cyberpanel/configservercsf/views.py b/src/redux/cyberpanel/configservercsf/views.py new file mode 100644 index 000000000..c5235544e --- /dev/null +++ b/src/redux/cyberpanel/configservercsf/views.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +import os +import os.path +import sys +import django +sys.path.append('/usr/local/CyberCP') +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "CyberCP.settings") +django.setup() +import json +from plogical.acl import ACLManager +import plogical.CyberCPLogFileWriter as logging +import subprocess +from django.shortcuts import HttpResponse, render +from plogical.processUtilities import ProcessUtilities +from django.views.decorators.csrf import csrf_exempt +import tempfile +from django.http import HttpResponse +from django.views.decorators.clickjacking import xframe_options_exempt + +def configservercsf(request): + userID = request.session['userID'] + currentACL = ACLManager.loadedACL(userID) + + if currentACL['admin'] == 1: + pass + else: + return ACLManager.loadError() + + return render(request,'configservercsf/index.html') + +@csrf_exempt +@xframe_options_exempt +def configservercsfiframe(request): + userID = request.session['userID'] + currentACL = ACLManager.loadedACL(userID) + + if currentACL['admin'] == 1: + pass + else: + return ACLManager.loadError() + + if request.method == 'GET': + qs = request.GET.urlencode() + elif request.method == 'POST': + qs = request.POST.urlencode() + + try: + tmp = tempfile.NamedTemporaryFile(mode = "w", delete=False) + tmp.write(qs) + tmp.close() + command = "/usr/local/csf/bin/cyberpanel.pl '" + tmp.name + "'" + + try: + output = ProcessUtilities.outputExecutioner(command) + except: + output = "Output Error from csf UI script" + + os.unlink(tmp.name) + except: + output = "Unable to create csf UI temp file" + + return HttpResponse(output) diff --git a/src/redux/cyberpanel/cyberpanel.pl b/src/redux/cyberpanel/cyberpanel.pl new file mode 100644 index 000000000..bbd213a65 --- /dev/null +++ b/src/redux/cyberpanel/cyberpanel.pl @@ -0,0 +1,205 @@ +#!/usr/bin/perl +############################################################################### +# Copyright 2006-2023, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# start main +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::Config; + +our ($script, $images, $myv, %FORM, %in); + +my $config = ConfigServer::Config->loadconfig(); +my %config = $config->config; + +open (my $IN, "<", "/etc/csf/version.txt"); +$myv = <$IN>; +close ($IN); +chomp $myv; + +$script = "/configservercsf/iframe/"; +$images = "/static/configservercsf"; + +my $file = $ARGV[0]; +unless (-e $file) {die "Cannot find tempfile [$file]"} +my (undef,undef,$uuid,$ugid) = getpwnam("cyberpanel"); +my $uid = (stat($file))[4]; +my $gid = (stat($file))[5]; +if ($uid != $uuid or $gid != $ugid) {die "Invalid tempfile ownership [$file]"} + +open (my $DATA, "<", $file); +my $buffer = <$DATA>; +close ($DATA); +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; +} + +#print "
          $ARGV[0]:$ARGV[1]:[[$buffer]]
          \n"; +#foreach my $key (keys %ENV) { +# print "$key = [$ENV{$key}]
          \n"; +#} + +my $bootstrapcss = ""; +my $jqueryjs = ""; +my $bootstrapjs = ""; + +unless ($FORM{action} eq "tailcmd" or $FORM{action} =~ /^cf/ or $FORM{action} eq "logtailcmd" or $FORM{action} eq "loggrepcmd") { + print < + + + ConfigServer Security & Firewall + + + $bootstrapcss + + $jqueryjs + $bootstrapjs + +\n"; + print < + +
          + +
          +
          +
          +

          ConfigServer Security & Firewall - csf v$myv

          +
          +EOF +} + +#my $templatehtml; +#open (my $SCRIPTOUT, '>', \$templatehtml); +#select $SCRIPTOUT; + +ConfigServer::DisplayUI::main(\%FORM, $script, $script, $images, $myv); + +#close ($SCRIPTOUT); +#select STDOUT; +#open (OUT, ">/tmp/out.html"); +#print OUT $templatehtml; +#close (OUT); +#print $templatehtml; + +unless ($FORM{action} eq "tailcmd" or $FORM{action} =~ /^cf/ or $FORM{action} eq "logtailcmd" or $FORM{action} eq "loggrepcmd") { + print < +\n"; + print "\n"; + print "\n"; +} + +1; + diff --git a/src/redux/da/admin/index.html b/src/redux/da/admin/index.html new file mode 100644 index 000000000..9509d4210 --- /dev/null +++ b/src/redux/da/admin/index.html @@ -0,0 +1,31 @@ +#!/usr/bin/perl + +print "\n"; +print "\n"; diff --git a/src/redux/da/admin/index.raw b/src/redux/da/admin/index.raw new file mode 100644 index 000000000..92f429023 --- /dev/null +++ b/src/redux/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/csf/exec/csf"); diff --git a/src/redux/da/exec/da_csf.cgi b/src/redux/da/exec/da_csf.cgi new file mode 100644 index 000000000..2a563c183 --- /dev/null +++ b/src/redux/da/exec/da_csf.cgi @@ -0,0 +1,309 @@ +#!/usr/bin/perl +#WHMADDON:addonupdates:ConfigServer Security&Firewall +############################################################################### +# Copyright 2006-2023, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +## no critic (RequireUseWarnings, ProhibitExplicitReturnUndef, ProhibitMixedBooleanOperators, RequireBriefOpen) +# start main +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::Config; +use ConfigServer::Slurp qw(slurp); + +our ($script, $script_da, $images, $myv, %FORM, %daconfig); + +my $config = ConfigServer::Config->loadconfig(); +my %config = $config->config; +my $slurpreg = ConfigServer::Slurp->slurpreg; +my $cleanreg = ConfigServer::Slurp->cleanreg; + +our %session; +our @sessiondata; +unless (-e "/var/lib/csf/csf.da.skip") { + if ($ENV{SESSION_ID} =~ /^\w+$/) { + open (my $SESSION, "<", "/usr/local/directadmin/data/sessions/da_sess_".$ENV{SESSION_ID}) or &loginfail("Security Error: No valid session key for [$ENV{SESSION_ID}]"); + flock ($SESSION, LOCK_SH); + @sessiondata = <$SESSION>; + close ($SESSION); + chomp @sessiondata; + foreach my $line (@sessiondata) { + my ($name, $value) = split(/\=/,$line); + $session{$name} = $value; + } + } + if (($session{key} eq "") or ($session{ip} eq "") or ($session{ip} ne $ENV{REMOTE_ADDR}) or ($session{key} ne $ENV{SESSION_KEY})) { + &loginfail("Security Error: No valid session key"); + exit; + } +## &loginfail("Security Error: test error"); +} + +my ($ppid, $pexe) = &getexe(getppid()); +if ($pexe ne "/usr/local/directadmin/directadmin") { + &loginfail("Security Error: Invalid parent"); + exit; +} + +open (my $IN, "<", "/etc/csf/version.txt") or die $!; +$myv = <$IN>; +close ($IN); +chomp $myv; + +$script = "/CMD_PLUGINS_ADMIN/csf/index.raw"; +$script_da = "/CMD_PLUGINS_ADMIN/csf/index.raw"; +$images = "/CMD_PLUGINS_ADMIN/csf/images"; + +my $buffer = $ENV{'QUERY_STRING'}; +if ($buffer eq "") {$buffer = $ENV{POST}} +if ($ENV{POST} eq "stdin=true") { + $buffer = ""; + while (<>) { + s/\0//; + $buffer .= $_; + } + chomp $buffer; +} +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; +} + +open (my $DIRECTADMIN, "<", "/usr/local/directadmin/conf/directadmin.conf"); +my @data = <$DIRECTADMIN>; +close ($DIRECTADMIN); +chomp @data; +foreach my $line (@data) { + my ($name,$value) = split(/\=/,$line); + $daconfig{$name} = $value; +} + +my $bootstrapcss = ""; +my $jqueryjs = ""; +my $bootstrapjs = ""; + +my @header; +my @footer; +my $bodytag; +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); +} +if (-e "/etc/csf/csf.htmltag") { + open (my $HTMLTAG, "<", "/etc/csf/csf.htmltag"); + flock ($HTMLTAG, LOCK_SH); + $htmltag .= <$HTMLTAG>; + chomp $htmltag; + close ($HTMLTAG); +} +if (-e "/etc/csf/csf.bodytag") { + open (my $BODYTAG, "<", "/etc/csf/csf.bodytag"); + flock ($BODYTAG, LOCK_SH); + $bodytag = <$BODYTAG>; + chomp $bodytag; + close ($BODYTAG); +} +unless ($config{STYLE_CUSTOM}) { + undef @header; + undef @footer; + $htmltag = ""; + $bodytag = ""; +} + +unless ($FORM{action} eq "tailcmd" or $FORM{action} =~ /^cf/ or $FORM{action} eq "logtailcmd" or $FORM{action} eq "loggrepcmd") { + print < + + + ConfigServer Security & Firewall + + + $bootstrapcss + + $jqueryjs + $bootstrapjs + +\n"; + print @header; + print < + +
          + +
          +
          +
          +

          ConfigServer Security & Firewall - csf v$myv

          +
          +EOF +} + +ConfigServer::DisplayUI::main(\%FORM, $script, $script_da, $images, $myv); + +unless ($FORM{action} eq "tailcmd" or $FORM{action} =~ /^cf/ or $FORM{action} eq "logtailcmd" or $FORM{action} eq "loggrepcmd") { + print < +\n"; + print @footer; + print "\n"; + print "\n"; +} +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); +} +sub loginfail { + my $message = shift; + my $file = "/var/lib/csf/da".time.".error"; + print $message."

          Information saved to [$file]\n"; + sysopen (my $FILE, $file, O_WRONLY | O_CREAT | O_TRUNC); + flock ($FILE, LOCK_EX); + print $FILE "To disable DirectAdmin session checks, create a touch file called /var/lib/csf/csf.da.skip\n\n"; + print $FILE $message."\n\n"; + print $FILE "Session ID = [$ENV{SESSION_ID}]\n"; + print $FILE "Session File [/usr/local/directadmin/data/sessions/da_sess_".$ENV{SESSION_ID}."]..."; + if (-e "/usr/local/directadmin/data/sessions/da_sess_".$ENV{SESSION_ID}) { + print $FILE "exists.\n\n"; + } else { + print $FILE "does not exist\n\n"; + close ($FILE); + exit; + } + print $FILE "Environment data:\n"; + print $FILE "REMOTE_ADDR = [$ENV{REMOTE_ADDR}]\n"; + print $FILE "SESSION_KEY = [$ENV{SESSION_KEY}]\n"; + print $FILE "SESSION_ID = [$ENV{SESSION_ID}]\n\n"; + print $FILE "Session data:\n"; + print $FILE "ip = [$session{ip}]\n"; + print $FILE "key = [$session{key}]\n\n"; + print $FILE "Session file contents:\n"; + print $FILE join("\n",@sessiondata); + close ($FILE); + exit; +} +1; diff --git a/src/redux/da/exec/da_csf_reseller.cgi b/src/redux/da/exec/da_csf_reseller.cgi new file mode 100644 index 000000000..85c4e725f --- /dev/null +++ b/src/redux/da/exec/da_csf_reseller.cgi @@ -0,0 +1,302 @@ +#!/usr/bin/perl +#WHMADDON:addonupdates:ConfigServer Security&Firewall +############################################################################### +# Copyright 2006-2023, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +## no critic (RequireUseWarnings, ProhibitExplicitReturnUndef, ProhibitMixedBooleanOperators, RequireBriefOpen) +# start main +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); + +our ($reseller, $script, $script_da, $images, %rprivs, $myv, %FORM, %daconfig); + +my $config = ConfigServer::Config->loadconfig(); +my %config = $config->config; +my $slurpreg = ConfigServer::Slurp->slurpreg; +my $cleanreg = ConfigServer::Slurp->cleanreg; + +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; +} + +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{ip} ne $ENV{REMOTE_ADDR}) or ($session{key} ne $ENV{SESSION_KEY})) { + print "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; +} + +delete $ENV{REMOTE_USER}; + +#print "content-type: text/html\n\n"; +#foreach my $key (keys %ENV) { +# print "ENV $key = [$ENV{$key}]
          \n"; +#} +#foreach my $key (keys %session) { +# print "session $key = [$session{$key}]
          \n"; +#} + +if (($session{key} ne "" and ($ENV{SESSION_KEY} eq $session{key})) and + ($session{ip} ne "" and ($ENV{REMOTE_ADDR} eq $session{ip}))) { + my @usernames = split(/\|/,$session{username}); + $ENV{REMOTE_USER} = $usernames[-1]; +} + +$reseller = 0; +if ($ENV{REMOTE_USER} ne "" and $ENV{REMOTE_USER} eq $ENV{CSF_RESELLER} and $rprivs{$ENV{REMOTE_USER}}{USE}) { + $reseller = 1; +} else { + 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; + +$script = "/CMD_PLUGINS_RESELLER/csf/index.raw"; +$script_da = "/CMD_PLUGINS_RESELLER/csf/index.raw"; +$images = "/CMD_PLUGINS_RESELLER/csf/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; +} + +open (my $DIRECTADMIN, "<", "/usr/local/directadmin/conf/directadmin.conf"); +my @data = <$DIRECTADMIN>; +close ($DIRECTADMIN); +chomp @data; +foreach my $line (@data) { + my ($name,$value) = split(/\=/,$line); + $daconfig{$name} = $value; +} + +my $bootstrapcss = ""; +my $jqueryjs = ""; +my $bootstrapjs = ""; + +my @header; +my @footer; +my $bodytag; +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); +} +if (-e "/etc/csf/csf.htmltag") { + open (my $HTMLTAG, "<", "/etc/csf/csf.htmltag"); + flock ($HTMLTAG, LOCK_SH); + $htmltag .= <$HTMLTAG>; + chomp $htmltag; + close ($HTMLTAG); +} +if (-e "/etc/csf/csf.bodytag") { + open (my $BODYTAG, "<", "/etc/csf/csf.bodytag"); + flock ($BODYTAG, LOCK_SH); + $bodytag = <$BODYTAG>; + chomp $bodytag; + close ($BODYTAG); +} +unless ($config{STYLE_CUSTOM}) { + undef @header; + undef @footer; + $htmltag = ""; + $bodytag = ""; +} + +unless ($FORM{action} eq "tailcmd" or $FORM{action} =~ /^cf/ or $FORM{action} eq "logtailcmd" or $FORM{action} eq "loggrepcmd") { + print < + + + ConfigServer Security & Firewall + + + $bootstrapcss + + $jqueryjs + $bootstrapjs + +\n"; + print @header; + print < + +

          + +
          +
          +
          +

          ConfigServer Security & Firewall - csf v$myv

          +
          +EOF +} + +ConfigServer::DisplayResellerUI::main(\%FORM, $script, 0, $images, $myv); + +unless ($FORM{action} eq "tailcmd" or $FORM{action} =~ /^cf/ or $FORM{action} eq "logtailcmd" or $FORM{action} eq "loggrepcmd") { + print < +\n"; + print @footer; + print "\n"; + print "\n"; +} +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/src/redux/da/hooks/admin_img.html b/src/redux/da/hooks/admin_img.html new file mode 100644 index 000000000..cb8e2582a --- /dev/null +++ b/src/redux/da/hooks/admin_img.html @@ -0,0 +1,4 @@ + +
          + ConfigServer Security & Firewall +
          diff --git a/src/redux/da/hooks/admin_txt.html b/src/redux/da/hooks/admin_txt.html new file mode 100644 index 000000000..c2e9699d6 --- /dev/null +++ b/src/redux/da/hooks/admin_txt.html @@ -0,0 +1 @@ +ConfigServer Security & Firewall \ No newline at end of file diff --git a/src/redux/da/hooks/reseller_img.html b/src/redux/da/hooks/reseller_img.html new file mode 100644 index 000000000..8edf1a665 --- /dev/null +++ b/src/redux/da/hooks/reseller_img.html @@ -0,0 +1,4 @@ + +
          + ConfigServer Security & Firewall +
          diff --git a/src/redux/da/hooks/reseller_txt.html b/src/redux/da/hooks/reseller_txt.html new file mode 100644 index 000000000..a33f184e0 --- /dev/null +++ b/src/redux/da/hooks/reseller_txt.html @@ -0,0 +1 @@ +ConfigServer Security & Firewall \ No newline at end of file diff --git a/src/redux/da/images/LICENSE.txt b/src/redux/da/images/LICENSE.txt new file mode 100644 index 000000000..34da9d9ee --- /dev/null +++ b/src/redux/da/images/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/src/redux/da/images/admin_icon.svg b/src/redux/da/images/admin_icon.svg new file mode 100644 index 000000000..1c928ea0d --- /dev/null +++ b/src/redux/da/images/admin_icon.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/redux/da/images/bootstrap-chosen.css b/src/redux/da/images/bootstrap-chosen.css new file mode 100644 index 000000000..54e6a1398 --- /dev/null +++ b/src/redux/da/images/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/src/redux/da/images/bootstrap/css/bootstrap.min.css b/src/redux/da/images/bootstrap/css/bootstrap.min.css new file mode 100644 index 000000000..b89ef7f3e --- /dev/null +++ b/src/redux/da/images/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/src/redux/da/images/bootstrap/css/bootstrap.min.css.map b/src/redux/da/images/bootstrap/css/bootstrap.min.css.map new file mode 100644 index 000000000..0c2c93492 --- /dev/null +++ b/src/redux/da/images/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,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A,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
        • 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/src/redux/da/reseller/index.raw b/src/redux/da/reseller/index.raw new file mode 100644 index 000000000..92f429023 --- /dev/null +++ b/src/redux/da/reseller/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/csf/exec/csf"); diff --git a/src/redux/da/scripts/install.sh b/src/redux/da/scripts/install.sh new file mode 100644 index 000000000..ede7059ff --- /dev/null +++ b/src/redux/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/src/redux/da/scripts/uninstall.sh b/src/redux/da/scripts/uninstall.sh new file mode 100644 index 000000000..35cd4f5a5 --- /dev/null +++ b/src/redux/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/src/redux/da/scripts/update.sh b/src/redux/da/scripts/update.sh new file mode 100644 index 000000000..2fbca4475 --- /dev/null +++ b/src/redux/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/src/redux/downloadservers b/src/redux/downloadservers new file mode 100644 index 000000000..ef8376d6d --- /dev/null +++ b/src/redux/downloadservers @@ -0,0 +1,2 @@ +download.configserver.com +download2.configserver.com diff --git a/src/redux/exploitalert.txt b/src/redux/exploitalert.txt new file mode 100644 index 000000000..22ce06451 --- /dev/null +++ b/src/redux/exploitalert.txt @@ -0,0 +1,7 @@ +From: root +To: root +Subject: lfd on [hostname]: System Exploit checking detected a possible compromise + +Time: [time] + +[text] diff --git a/src/redux/filealert.txt b/src/redux/filealert.txt new file mode 100644 index 000000000..c9c4f47aa --- /dev/null +++ b/src/redux/filealert.txt @@ -0,0 +1,9 @@ +From: root +To: root +Subject: lfd on [hostname]: Suspicious File Alert + +Time: [time] +File: [file] +Reason: [reason] +Owner: [owner] +Action: [action] diff --git a/src/redux/forkbombalert.txt b/src/redux/forkbombalert.txt new file mode 100644 index 000000000..4ea099416 --- /dev/null +++ b/src/redux/forkbombalert.txt @@ -0,0 +1,10 @@ +From: root +To: root +Subject: lfd on [hostname]: Fork Bomb detected and killed + +Time: [time] +Trigger: [level] + +Processes: + +[text] diff --git a/src/redux/install.cpanel.sh b/src/redux/install.cpanel.sh new file mode 100644 index 000000000..7dcc7acd1 --- /dev/null +++ b/src/redux/install.cpanel.sh @@ -0,0 +1,567 @@ +#!/bin/sh +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### + +umask 0177 + +echo "Installing csf and lfd" +echo + +echo "Check we're running as root" +if [ ! `id -u` = 0 ]; then + echo + echo "FAILED: You have to be logged in as root (UID:0) to install csf" + echo + exit +fi +echo + +if [ ! -e "install.sh" ]; then + echo "You must cd to the package directory that you expanded" + exit +fi + +#First replace: +if [ -e "/usr/local/cpanel/3rdparty/bin/perl" ]; then + sed -i 's%^#\!/usr/bin/perl%#\!/usr/local/cpanel/3rdparty/bin/perl%' auto.pl + sed -i 's%^#\!/usr/bin/perl%#\!/usr/local/cpanel/3rdparty/bin/perl%' cpanel/csf.cgi + sed -i 's%^#\!/usr/bin/perl%#\!/usr/local/cpanel/3rdparty/bin/perl%' csf.pl + sed -i 's%^#\!/usr/bin/perl%#\!/usr/local/cpanel/3rdparty/bin/perl%' csftest.pl + sed -i 's%^#\!/usr/bin/perl%#\!/usr/local/cpanel/3rdparty/bin/perl%' lfd.pl + sed -i 's%^#\!/usr/bin/perl%#\!/usr/local/cpanel/3rdparty/bin/perl%' os.pl + sed -i 's%^#\!/usr/bin/perl%#\!/usr/local/cpanel/3rdparty/bin/perl%' pt_deleted_action.pl + sed -i 's%^#\!/usr/bin/perl%#\!/usr/local/cpanel/3rdparty/bin/perl%' regex.custom.pm + sed -i 's%^#\!/usr/bin/perl%#\!/usr/local/cpanel/3rdparty/bin/perl%' webmin/csf/index.cgi +fi + +mkdir -v -m 0600 /etc/csf +cp -avf install.txt /etc/csf/ + +echo +echo "Checking Perl modules..." +chmod 700 os.pl +RETURN=`./os.pl` +if [ "$RETURN" = 1 ]; then + echo + echo "FAILED: You MUST install the missing perl modules above before you can install csf. See /etc/csf/install.txt for installation details." + exit +else + echo "...Perl modules OK" +fi + +mkdir -v -m 0600 /var/lib/csf +mkdir -v -m 0600 /var/lib/csf/backup +mkdir -v -m 0600 /var/lib/csf/Geo +mkdir -v -m 0600 /var/lib/csf/ui +mkdir -v -m 0600 /var/lib/csf/stats +mkdir -v -m 0600 /var/lib/csf/lock +mkdir -v -m 0600 /var/lib/csf/webmin +mkdir -v -m 0600 /var/lib/csf/zone +mkdir -v -m 0600 /usr/local/csf +mkdir -v -m 0600 /usr/local/csf/bin +mkdir -v -m 0600 /usr/local/csf/lib +mkdir -v -m 0600 /usr/local/csf/tpl + +if [ -e "/etc/csf/alert.txt" ]; then + sh migratedata.sh +fi + +if [ ! -e "/etc/csf/csf.conf" ]; then + cp -avf csf.conf /etc/csf/. +fi + +if [ ! -e "/etc/csf/csf.allow" ]; then + cp -avf csf.allow /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.deny" ]; then + cp -avf csf.deny /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.redirect" ]; then + cp -avf csf.redirect /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.resellers" ]; then + cp -avf csf.resellers /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.dirwatch" ]; then + cp -avf csf.dirwatch /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.syslogs" ]; then + cp -avf csf.syslogs /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.logfiles" ]; then + cp -avf csf.logfiles /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.logignore" ]; then + cp -avf csf.logignore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.blocklists" ]; then + cp -avf csf.blocklists /etc/csf/. +else + cp -avf csf.blocklists /etc/csf/csf.blocklists.new +fi +if [ ! -e "/etc/csf/csf.ignore" ]; then + cp -avf csf.ignore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.pignore" ]; then + cp -avf csf.pignore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.rignore" ]; then + cp -avf csf.rignore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.fignore" ]; then + cp -avf csf.fignore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.signore" ]; then + cp -avf csf.signore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.suignore" ]; then + cp -avf csf.suignore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.uidignore" ]; then + cp -avf csf.uidignore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.mignore" ]; then + cp -avf csf.mignore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.sips" ]; then + cp -avf csf.sips /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.dyndns" ]; then + cp -avf csf.dyndns /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.syslogusers" ]; then + cp -avf csf.syslogusers /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.smtpauth" ]; then + cp -avf csf.smtpauth /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.rblconf" ]; then + cp -avf csf.rblconf /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.cloudflare" ]; then + cp -avf csf.cloudflare /etc/csf/. +fi + +if [ ! -e "/usr/local/csf/tpl/alert.txt" ]; then + cp -avf alert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/reselleralert.txt" ]; then + cp -avf reselleralert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/logalert.txt" ]; then + cp -avf logalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/logfloodalert.txt" ]; then + cp -avf logfloodalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/syslogalert.txt" ]; then + cp -avf syslogalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/integrityalert.txt" ]; then + cp -avf integrityalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/exploitalert.txt" ]; then + cp -avf exploitalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/queuealert.txt" ]; then + cp -avf queuealert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/modsecipdbalert.txt" ]; then + cp -avf modsecipdbalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/tracking.txt" ]; then + cp -avf tracking.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/connectiontracking.txt" ]; then + cp -avf connectiontracking.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/processtracking.txt" ]; then + cp -avf processtracking.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/accounttracking.txt" ]; then + cp -avf accounttracking.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/usertracking.txt" ]; then + cp -avf usertracking.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/sshalert.txt" ]; then + cp -avf sshalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/webminalert.txt" ]; then + cp -avf webminalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/sualert.txt" ]; then + cp -avf sualert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/sudoalert.txt" ]; then + cp -avf sudoalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/consolealert.txt" ]; then + cp -avf consolealert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/uialert.txt" ]; then + cp -avf uialert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/cpanelalert.txt" ]; then + cp -avf cpanelalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/scriptalert.txt" ]; then + cp -avf scriptalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/relayalert.txt" ]; then + cp -avf relayalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/filealert.txt" ]; then + cp -avf filealert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/watchalert.txt" ]; then + cp -avf watchalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/loadalert.txt" ]; then + cp -avf loadalert.txt /usr/local/csf/tpl/. +else + cp -avf loadalert.txt /usr/local/csf/tpl/loadalert.txt.new +fi +if [ ! -e "/usr/local/csf/tpl/resalert.txt" ]; then + cp -avf resalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/portscan.txt" ]; then + cp -avf portscan.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/uidscan.txt" ]; then + cp -avf uidscan.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/permblock.txt" ]; then + cp -avf permblock.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/netblock.txt" ]; then + cp -avf netblock.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/portknocking.txt" ]; then + cp -avf portknocking.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/forkbombalert.txt" ]; then + cp -avf forkbombalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/recaptcha.txt" ]; then + cp -avf recaptcha.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/apache.main.txt" ]; then + cp -avf apache.main.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/apache.http.txt" ]; then + cp -avf apache.http.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/apache.https.txt" ]; then + cp -avf apache.https.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/litespeed.main.txt" ]; then + cp -avf litespeed.main.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/litespeed.http.txt" ]; then + cp -avf litespeed.http.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/litespeed.https.txt" ]; then + cp -avf litespeed.https.txt /usr/local/csf/tpl/. +fi +cp -avf x-arf.txt /usr/local/csf/tpl/. + +if [ ! -e "/usr/local/csf/bin/regex.custom.pm" ]; then + cp -avf regex.custom.pm /usr/local/csf/bin/. +fi +if [ ! -e "/usr/local/csf/bin/pt_deleted_action.pl" ]; then + cp -avf pt_deleted_action.pl /usr/local/csf/bin/. +fi +if [ ! -e "/etc/csf/messenger" ]; then + cp -avf messenger /etc/csf/. +fi +if [ ! -e "/etc/csf/messenger/index.recaptcha.html" ]; then + cp -avf messenger/index.recaptcha.html /etc/csf/messenger/. +fi +if [ ! -e "/etc/csf/ui" ]; then + cp -avf ui /etc/csf/. +fi +if [ -e "/etc/cron.d/csfcron.sh" ]; then + mv -fv /etc/cron.d/csfcron.sh /etc/cron.d/csf-cron +fi +if [ ! -e "/etc/cron.d/csf-cron" ]; then + cp -avf csfcron.sh /etc/cron.d/csf-cron +fi +if [ -e "/etc/cron.d/lfdcron.sh" ]; then + mv -fv /etc/cron.d/lfdcron.sh /etc/cron.d/lfd-cron +fi +if [ ! -e "/etc/cron.d/lfd-cron" ]; then + cp -avf lfdcron.sh /etc/cron.d/lfd-cron +fi +sed -i "s%/etc/init.d/lfd restart%/usr/sbin/csf --lfd restart%" /etc/cron.d/lfd-cron +if [ -e "/usr/local/csf/bin/servercheck.pm" ]; then + rm -f /usr/local/csf/bin/servercheck.pm +fi +if [ -e "/etc/csf/cseui.pl" ]; then + rm -f /etc/csf/cseui.pl +fi +if [ -e "/etc/csf/csfui.pl" ]; then + rm -f /etc/csf/csfui.pl +fi +if [ -e "/etc/csf/csfuir.pl" ]; then + rm -f /etc/csf/csfuir.pl +fi +if [ -e "/usr/local/csf/bin/cseui.pl" ]; then + rm -f /usr/local/csf/bin/cseui.pl +fi +if [ -e "/usr/local/csf/bin/csfui.pl" ]; then + rm -f /usr/local/csf/bin/csfui.pl +fi +if [ -e "/usr/local/csf/bin/csfuir.pl" ]; then + rm -f /usr/local/csf/bin/csfuir.pl +fi +if [ -e "/usr/local/csf/bin/regex.pm" ]; then + rm -f /usr/local/csf/bin/regex.pm +fi + +OLDVERSION=0 +if [ -e "/etc/csf/version.txt" ]; then + OLDVERSION=`head -n 1 /etc/csf/version.txt` +fi + +rm -f /etc/csf/csf.pl /usr/sbin/csf /etc/csf/lfd.pl /usr/sbin/lfd +chmod 700 csf.pl lfd.pl +cp -avf csf.pl /usr/sbin/csf +cp -avf lfd.pl /usr/sbin/lfd +chmod 700 /usr/sbin/csf /usr/sbin/lfd +ln -svf /usr/sbin/csf /etc/csf/csf.pl +ln -svf /usr/sbin/lfd /etc/csf/lfd.pl +ln -svf /usr/local/csf/bin/csftest.pl /etc/csf/ +ln -svf /usr/local/csf/bin/pt_deleted_action.pl /etc/csf/ +ln -svf /usr/local/csf/bin/remove_apf_bfd.sh /etc/csf/ +ln -svf /usr/local/csf/bin/uninstall.sh /etc/csf/ +ln -svf /usr/local/csf/bin/regex.custom.pm /etc/csf/ +ln -svf /usr/local/csf/lib/webmin /etc/csf/ +if [ ! -e "/etc/csf/alerts" ]; then + ln -svf /usr/local/csf/tpl /etc/csf/alerts +fi +chcon -h system_u:object_r:bin_t:s0 /usr/sbin/lfd +chcon -h system_u:object_r:bin_t:s0 /usr/sbin/csf + +mkdir webmin/csf/images +mkdir ui/images +mkdir da/images +mkdir interworx/images + +cp -avf csf/* webmin/csf/images/ +cp -avf csf/* ui/images/ +cp -avf csf/* da/images/ +cp -avf csf/* interworx/images/ + +cp -avf messenger/*.php /etc/csf/messenger/ +cp -avf csf/csf_small.png /usr/local/cpanel/whostmgr/docroot/addon_plugins/ +cp -avf uninstall.sh /usr/local/csf/bin/ +cp -avf csftest.pl /usr/local/csf/bin/ +cp -avf remove_apf_bfd.sh /usr/local/csf/bin/ +cp -avf readme.txt /etc/csf/ +cp -avf sanity.txt /usr/local/csf/lib/ +cp -avf csf.rbls /usr/local/csf/lib/ +cp -avf restricted.txt /usr/local/csf/lib/ +cp -avf changelog.txt /etc/csf/ +cp -avf downloadservers /etc/csf/ +cp -avf install.txt /etc/csf/ +cp -avf version.txt /etc/csf/ +cp -avf license.txt /etc/csf/ +cp -avf webmin /usr/local/csf/lib/ +cp -avf ConfigServer /usr/local/csf/lib/ +cp -avf Net /usr/local/csf/lib/ +cp -avf Geo /usr/local/csf/lib/ +cp -avf Crypt /usr/local/csf/lib/ +cp -avf HTTP /usr/local/csf/lib/ +cp -avf JSON /usr/local/csf/lib/ +cp -avf version/* /usr/local/csf/lib/ +cp -avf csf.div /usr/local/csf/lib/ +cp -avf csfajaxtail.js /usr/local/csf/lib/ +cp -avf ui/images /etc/csf/ui/. +cp -avf profiles /usr/local/csf/ +cp -avf csf.conf /usr/local/csf/profiles/reset_to_defaults.conf +cp -avf cpanel.comodo.ignore /etc/csf/ +cp -avf cpanel.comodo.allow /etc/csf/ +cp -avf cpanel.ignore /etc/csf/ +cp -avf cpanel.allow /etc/csf/ +cp -avf messenger/*.php /etc/csf/messenger/. +cp -avf lfd.logrotate /etc/logrotate.d/lfd + +rm -fv /etc/csf/csf.spamhaus /etc/csf/csf.dshield /etc/csf/csf.tor /etc/csf/csf.bogon + +mkdir -p /usr/local/man/man1/ +cp -avf csf.1.txt /usr/local/man/man1/csf.1 +man csf | col -b > csf.help +cp -avf csf.help /usr/local/csf/lib/ +chmod 755 /usr/local/man/ +chmod 755 /usr/local/man/man1/ +chmod 644 /usr/local/man/man1/csf.1 + +chmod -R 600 /etc/csf +chmod -R 600 /var/lib/csf +chmod -R 600 /usr/local/csf/bin +chmod -R 600 /usr/local/csf/lib +chmod -R 600 /usr/local/csf/tpl +chmod -R 600 /usr/local/csf/profiles +chmod 600 /var/log/lfd.log* + +chmod -v 700 /usr/local/csf/bin/*.pl /usr/local/csf/bin/*.sh /usr/local/csf/bin/*.pm +chmod -v 700 /etc/csf/*.pl /etc/csf/*.cgi /etc/csf/*.sh /etc/csf/*.php /etc/csf/*.py +chmod -v 700 /etc/csf/webmin/csf/index.cgi +chmod -v 644 /etc/cron.d/lfd-cron +chmod -v 644 /etc/cron.d/csf-cron + +cp -avf csget.pl /etc/cron.daily/csget +chmod 700 /etc/cron.daily/csget +/etc/cron.daily/csget --nosleep + +chmod -v 700 auto.pl +./auto.pl $OLDVERSION + +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/csf +chmod 700 /usr/local/cpanel/whostmgr/docroot/cgi/configserver/csf + +cp -avf cpanel/csf.cgi /usr/local/cpanel/whostmgr/docroot/cgi/configserver/csf.cgi +chmod -v 700 /usr/local/cpanel/whostmgr/docroot/cgi/configserver/csf.cgi + +cp -avf csf/ /usr/local/cpanel/whostmgr/docroot/cgi/configserver/ +cp -avf cpanel/Driver /usr/local/cpanel/whostmgr/docroot/cgi/configserver/csf/ +cp -avf ui/images/icon.gif /usr/local/cpanel/whostmgr/docroot/themes/x/icons/csf.gif +cp -avf cpanel/csf.tmpl /usr/local/cpanel/whostmgr/docroot/templates/ + +VERSION=`cat /usr/local/cpanel/version | cut -d '.' -f2` +if [ "$VERSION" -lt "65" ]; then + sed -i "s/^target=.*$/target=mainFrame/" cpanel/csf.conf + echo "cPanel v$VERSION, target set to mainFrame" +else + sed -i "s/^target=.*$/target=_self/" cpanel/csf.conf + echo "cPanel v$VERSION, target set to _self" +fi + +cp -avf cpanel/csf.conf /usr/local/cpanel/whostmgr/docroot/cgi/configserver/csf/csf.conf +cp -avf cpanel/upgrade.sh /usr/local/cpanel/whostmgr/docroot/cgi/configserver/csf/upgrade.sh +chmod 700 /usr/local/cpanel/whostmgr/docroot/cgi/configserver/csf/upgrade.sh + +if [ -e "/usr/local/cpanel/bin/register_appconfig" ]; 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 +else + cp -avf cpanel/csf.cgi /usr/local/cpanel/whostmgr/docroot/cgi/addon_csf.cgi + chmod -v 700 /usr/local/cpanel/whostmgr/docroot/cgi/addon_csf.cgi + cp -avf csf/ /usr/local/cpanel/whostmgr/docroot/cgi/ + if [ ! -d "/var/cpanel/apps" ]; then + mkdir /var/cpanel/apps + chmod 755 /var/cpanel/apps + fi + /bin/cp -avf cpanel/csf.conf.old /var/cpanel/apps/csf.conf + chmod 600 /var/cpanel/apps/csf.conf +fi + +if test `cat /proc/1/comm` = "systemd" +then + if [ -e /etc/init.d/lfd ]; then + if [ -f /etc/redhat-release ]; then + /sbin/chkconfig csf off + /sbin/chkconfig lfd off + /sbin/chkconfig csf --del + /sbin/chkconfig lfd --del + elif [ -f /etc/debian_version ] || [ -f /etc/lsb-release ]; then + update-rc.d -f lfd remove + update-rc.d -f csf remove + elif [ -f /etc/gentoo-release ]; then + rc-update del lfd default + rc-update del csf default + elif [ -f /etc/slackware-version ]; then + rm -vf /etc/rc.d/rc3.d/S80csf + rm -vf /etc/rc.d/rc4.d/S80csf + rm -vf /etc/rc.d/rc5.d/S80csf + rm -vf /etc/rc.d/rc3.d/S85lfd + rm -vf /etc/rc.d/rc4.d/S85lfd + rm -vf /etc/rc.d/rc5.d/S85lfd + else + /sbin/chkconfig csf off + /sbin/chkconfig lfd off + /sbin/chkconfig csf --del + /sbin/chkconfig lfd --del + fi + rm -fv /etc/init.d/csf + rm -fv /etc/init.d/lfd + fi + + mkdir -p /etc/systemd/system/ + mkdir -p /usr/lib/systemd/system/ + cp -avf lfd.service /usr/lib/systemd/system/ + cp -avf csf.service /usr/lib/systemd/system/ + + chcon -h system_u:object_r:systemd_unit_file_t:s0 /usr/lib/systemd/system/lfd.service + chcon -h system_u:object_r:systemd_unit_file_t:s0 /usr/lib/systemd/system/csf.service + + systemctl daemon-reload + + systemctl enable csf.service + systemctl enable lfd.service + + systemctl disable firewalld + systemctl stop firewalld + systemctl mask firewalld +else + cp -avf lfd.sh /etc/init.d/lfd + cp -avf csf.sh /etc/init.d/csf + chmod -v 755 /etc/init.d/lfd + chmod -v 755 /etc/init.d/csf + + if [ -f /etc/redhat-release ]; then + /sbin/chkconfig lfd on + /sbin/chkconfig csf on + elif [ -f /etc/debian_version ] || [ -f /etc/lsb-release ]; then + update-rc.d -f lfd remove + update-rc.d -f csf remove + update-rc.d lfd defaults 80 20 + update-rc.d csf defaults 20 80 + elif [ -f /etc/gentoo-release ]; then + rc-update add lfd default + rc-update add csf default + elif [ -f /etc/slackware-version ]; then + ln -svf /etc/init.d/csf /etc/rc.d/rc3.d/S80csf + ln -svf /etc/init.d/csf /etc/rc.d/rc4.d/S80csf + ln -svf /etc/init.d/csf /etc/rc.d/rc5.d/S80csf + ln -svf /etc/init.d/lfd /etc/rc.d/rc3.d/S85lfd + ln -svf /etc/init.d/lfd /etc/rc.d/rc4.d/S85lfd + ln -svf /etc/init.d/lfd /etc/rc.d/rc5.d/S85lfd + else + /sbin/chkconfig lfd on + /sbin/chkconfig csf on + fi +fi + +#Second replace +if [ -e "/usr/local/cpanel/3rdparty/bin/perl" ]; then + sed -i 's%^#\!/usr/local/cpanel/3rdparty/bin/perl%#\!/usr/bin/perl%' auto.pl + sed -i 's%^#\!/usr/local/cpanel/3rdparty/bin/perl%#\!/usr/bin/perl%' cpanel/csf.cgi + sed -i 's%^#\!/usr/local/cpanel/3rdparty/bin/perl%#\!/usr/bin/perl%' csf.pl + sed -i 's%^#\!/usr/local/cpanel/3rdparty/bin/perl%#\!/usr/bin/perl%' csftest.pl + sed -i 's%^#\!/usr/local/cpanel/3rdparty/bin/perl%#\!/usr/bin/perl%' lfd.pl + sed -i 's%^#\!/usr/local/cpanel/3rdparty/bin/perl%#\!/usr/bin/perl%' os.pl + sed -i 's%^#\!/usr/local/cpanel/3rdparty/bin/perl%#\!/usr/bin/perl%' pt_deleted_action.pl + sed -i 's%^#\!/usr/local/cpanel/3rdparty/bin/perl%#\!/usr/bin/perl%' regex.custom.pm + sed -i 's%^#\!/usr/local/cpanel/3rdparty/bin/perl%#\!/usr/bin/perl%' webmin/csf/index.cgi +fi + +chown -Rf root:root /etc/csf /var/lib/csf /usr/local/csf +chown -f root:root /usr/sbin/csf /usr/sbin/lfd /etc/logrotate.d/lfd /etc/cron.d/csf-cron /etc/cron.d/lfd-cron /usr/local/man/man1/csf.1 /usr/lib/systemd/system/lfd.service /usr/lib/systemd/system/csf.service /etc/init.d/lfd /etc/init.d/csf + +cd webmin ; tar -czf /usr/local/csf/csfwebmin.tgz ./* +ln -svf /usr/local/csf/csfwebmin.tgz /etc/csf/ + +echo +echo "Installation Completed" +echo diff --git a/src/redux/install.cwp.sh b/src/redux/install.cwp.sh new file mode 100644 index 000000000..0f4d334f1 --- /dev/null +++ b/src/redux/install.cwp.sh @@ -0,0 +1,543 @@ +#!/bin/sh +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### + +umask 0177 + +if [ -e "/usr/local/cpanel/version" ]; then + echo "Running csf cPanel installer" + echo + sh install.cpanel.sh + exit 0 +elif [ -e "/usr/local/directadmin/directadmin" ]; then + echo "Running csf DirectAdmin installer" + echo + sh install.directadmin.sh + exit 0 +fi + +echo "Installing csf and lfd" +echo + +echo "Check we're running as root" +if [ ! `id -u` = 0 ]; then + echo + echo "FAILED: You have to be logged in as root (UID:0) to install csf" + exit +fi +echo + +mkdir -v -m 0600 /etc/csf +cp -avf install.txt /etc/csf/ + +echo "Checking Perl modules..." +chmod 700 os.pl +RETURN=`./os.pl` +if [ "$RETURN" = 1 ]; then + echo + echo "FAILED: You MUST install the missing perl modules above before you can install csf. See /etc/csf/install.txt for installation details." + echo + exit +else + echo "...Perl modules OK" + echo +fi + +mkdir -v -m 0600 /etc/csf +mkdir -v -m 0600 /var/lib/csf +mkdir -v -m 0600 /var/lib/csf/backup +mkdir -v -m 0600 /var/lib/csf/Geo +mkdir -v -m 0600 /var/lib/csf/ui +mkdir -v -m 0600 /var/lib/csf/stats +mkdir -v -m 0600 /var/lib/csf/lock +mkdir -v -m 0600 /var/lib/csf/webmin +mkdir -v -m 0600 /var/lib/csf/zone +mkdir -v -m 0600 /usr/local/csf +mkdir -v -m 0600 /usr/local/csf/bin +mkdir -v -m 0600 /usr/local/csf/lib +mkdir -v -m 0600 /usr/local/csf/tpl + +if [ -e "/etc/csf/alert.txt" ]; then + sh migratedata.sh +fi + +if [ ! -e "/etc/csf/csf.conf" ]; then + cp -avf csf.cwp.conf /etc/csf/csf.conf +fi + +if [ ! -d /var/lib/csf ]; then + mkdir -v -p -m 0600 /var/lib/csf +fi +if [ ! -d /usr/local/csf/lib ]; then + mkdir -v -p -m 0600 /usr/local/csf/lib +fi +if [ ! -d /usr/local/csf/bin ]; then + mkdir -v -p -m 0600 /usr/local/csf/bin +fi +if [ ! -d /usr/local/csf/tpl ]; then + mkdir -v -p -m 0600 /usr/local/csf/tpl +fi + +if [ ! -e "/etc/csf/csf.allow" ]; then + cp -avf csf.cwp.allow /etc/csf/csf.allow +fi +if [ ! -e "/etc/csf/csf.deny" ]; then + cp -avf csf.deny /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.redirect" ]; then + cp -avf csf.redirect /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.resellers" ]; then + cp -avf csf.resellers /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.dirwatch" ]; then + cp -avf csf.dirwatch /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.syslogs" ]; then + cp -avf csf.syslogs /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.logfiles" ]; then + cp -avf csf.logfiles /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.logignore" ]; then + cp -avf csf.logignore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.blocklists" ]; then + cp -avf csf.blocklists /etc/csf/. +else + cp -avf csf.blocklists /etc/csf/csf.blocklists.new +fi +if [ ! -e "/etc/csf/csf.ignore" ]; then + cp -avf csf.cwp.ignore /etc/csf/csf.ignore +fi +if [ ! -e "/etc/csf/csf.pignore" ]; then + cp -avf csf.cwp.pignore /etc/csf/csf.pignore +fi +if [ ! -e "/etc/csf/csf.rignore" ]; then + cp -avf csf.rignore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.fignore" ]; then + cp -avf csf.fignore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.signore" ]; then + cp -avf csf.signore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.suignore" ]; then + cp -avf csf.suignore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.uidignore" ]; then + cp -avf csf.uidignore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.mignore" ]; then + cp -avf csf.mignore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.sips" ]; then + cp -avf csf.sips /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.dyndns" ]; then + cp -avf csf.dyndns /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.syslogusers" ]; then + cp -avf csf.syslogusers /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.smtpauth" ]; then + cp -avf csf.smtpauth /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.rblconf" ]; then + cp -avf csf.rblconf /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.cloudflare" ]; then + cp -avf csf.cloudflare /etc/csf/. +fi + +if [ ! -e "/usr/local/csf/tpl/alert.txt" ]; then + cp -avf alert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/reselleralert.txt" ]; then + cp -avf reselleralert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/logalert.txt" ]; then + cp -avf logalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/logfloodalert.txt" ]; then + cp -avf logfloodalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/syslogalert.txt" ]; then + cp -avf syslogalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/integrityalert.txt" ]; then + cp -avf integrityalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/exploitalert.txt" ]; then + cp -avf exploitalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/queuealert.txt" ]; then + cp -avf queuealert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/modsecipdbalert.txt" ]; then + cp -avf modsecipdbalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/tracking.txt" ]; then + cp -avf tracking.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/connectiontracking.txt" ]; then + cp -avf connectiontracking.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/processtracking.txt" ]; then + cp -avf processtracking.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/accounttracking.txt" ]; then + cp -avf accounttracking.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/usertracking.txt" ]; then + cp -avf usertracking.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/sshalert.txt" ]; then + cp -avf sshalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/webminalert.txt" ]; then + cp -avf webminalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/sualert.txt" ]; then + cp -avf sualert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/sudoalert.txt" ]; then + cp -avf sudoalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/consolealert.txt" ]; then + cp -avf consolealert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/uialert.txt" ]; then + cp -avf uialert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/cpanelalert.txt" ]; then + cp -avf cpanelalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/scriptalert.txt" ]; then + cp -avf scriptalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/relayalert.txt" ]; then + cp -avf relayalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/filealert.txt" ]; then + cp -avf filealert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/watchalert.txt" ]; then + cp -avf watchalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/loadalert.txt" ]; then + cp -avf loadalert.txt /usr/local/csf/tpl/. +else + cp -avf loadalert.txt /usr/local/csf/tpl/loadalert.txt.new +fi +if [ ! -e "/usr/local/csf/tpl/resalert.txt" ]; then + cp -avf resalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/portscan.txt" ]; then + cp -avf portscan.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/uidscan.txt" ]; then + cp -avf uidscan.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/permblock.txt" ]; then + cp -avf permblock.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/netblock.txt" ]; then + cp -avf netblock.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/portknocking.txt" ]; then + cp -avf portknocking.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/forkbombalert.txt" ]; then + cp -avf forkbombalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/recaptcha.txt" ]; then + cp -avf recaptcha.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/apache.main.txt" ]; then + cp -avf apache.main.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/apache.http.txt" ]; then + cp -avf apache.http.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/apache.https.txt" ]; then + cp -avf apache.https.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/litespeed.main.txt" ]; then + cp -avf litespeed.main.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/litespeed.http.txt" ]; then + cp -avf litespeed.http.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/litespeed.https.txt" ]; then + cp -avf litespeed.https.txt /usr/local/csf/tpl/. +fi +cp -avf x-arf.txt /usr/local/csf/tpl/. + +if [ ! -e "/usr/local/csf/bin/regex.custom.pm" ]; then + cp -avf regex.custom.pm /usr/local/csf/bin/. +fi +if [ ! -e "/usr/local/csf/bin/pt_deleted_action.pl" ]; then + cp -avf pt_deleted_action.pl /usr/local/csf/bin/. +fi +if [ ! -e "/etc/csf/messenger" ]; then + cp -avf messenger /etc/csf/. +fi +if [ ! -e "/etc/csf/messenger/index.recaptcha.html" ]; then + cp -avf messenger/index.recaptcha.html /etc/csf/messenger/. +fi +if [ ! -e "/etc/csf/ui" ]; then + cp -avf ui /etc/csf/. +fi +if [ -e "/etc/cron.d/csfcron.sh" ]; then + mv -fv /etc/cron.d/csfcron.sh /etc/cron.d/csf-cron +fi +if [ ! -e "/etc/cron.d/csf-cron" ]; then + cp -avf csfcron.sh /etc/cron.d/csf-cron +fi +if [ -e "/etc/cron.d/lfdcron.sh" ]; then + mv -fv /etc/cron.d/lfdcron.sh /etc/cron.d/lfd-cron +fi +if [ ! -e "/etc/cron.d/lfd-cron" ]; then + cp -avf lfdcron.sh /etc/cron.d/lfd-cron +fi +sed -i "s%/etc/init.d/lfd restart%/usr/sbin/csf --lfd restart%" /etc/cron.d/lfd-cron +if [ -e "/usr/local/csf/bin/servercheck.pm" ]; then + rm -f /usr/local/csf/bin/servercheck.pm +fi +if [ -e "/etc/csf/cseui.pl" ]; then + rm -f /etc/csf/cseui.pl +fi +if [ -e "/etc/csf/csfui.pl" ]; then + rm -f /etc/csf/csfui.pl +fi +if [ -e "/etc/csf/csfuir.pl" ]; then + rm -f /etc/csf/csfuir.pl +fi +if [ -e "/usr/local/csf/bin/cseui.pl" ]; then + rm -f /usr/local/csf/bin/cseui.pl +fi +if [ -e "/usr/local/csf/bin/csfui.pl" ]; then + rm -f /usr/local/csf/bin/csfui.pl +fi +if [ -e "/usr/local/csf/bin/csfuir.pl" ]; then + rm -f /usr/local/csf/bin/csfuir.pl +fi +if [ -e "/usr/local/csf/bin/regex.pm" ]; then + rm -f /usr/local/csf/bin/regex.pm +fi + +OLDVERSION=0 +if [ -e "/etc/csf/version.txt" ]; then + OLDVERSION=`head -n 1 /etc/csf/version.txt` +fi + +rm -f /etc/csf/csf.pl /usr/sbin/csf /etc/csf/lfd.pl /usr/sbin/lfd +chmod 700 csf.pl lfd.pl +cp -avf csf.pl /usr/sbin/csf +cp -avf lfd.pl /usr/sbin/lfd +chmod 700 /usr/sbin/csf /usr/sbin/lfd +ln -svf /usr/sbin/csf /etc/csf/csf.pl +ln -svf /usr/sbin/lfd /etc/csf/lfd.pl +ln -svf /usr/local/csf/bin/csftest.pl /etc/csf/ +ln -svf /usr/local/csf/bin/pt_deleted_action.pl /etc/csf/ +ln -svf /usr/local/csf/bin/remove_apf_bfd.sh /etc/csf/ +ln -svf /usr/local/csf/bin/uninstall.sh /etc/csf/ +ln -svf /usr/local/csf/bin/regex.custom.pm /etc/csf/ +ln -svf /usr/local/csf/lib/webmin /etc/csf/ +if [ ! -e "/etc/csf/alerts" ]; then + ln -svf /usr/local/csf/tpl /etc/csf/alerts +fi +chcon -h system_u:object_r:bin_t:s0 /usr/sbin/lfd +chcon -h system_u:object_r:bin_t:s0 /usr/sbin/csf + +mkdir webmin/csf/images +mkdir ui/images +mkdir da/images +mkdir interworx/images + +cp -avf csf/* webmin/csf/images/ +cp -avf csf/* ui/images/ +cp -avf csf/* da/images/ +cp -avf csf/* interworx/images/ + +cp -avf messenger/*.php /etc/csf/messenger/ +cp -avf uninstall.cwp.sh /usr/local/csf/bin/uninstall.sh +cp -avf csftest.pl /usr/local/csf/bin/ +cp -avf remove_apf_bfd.sh /usr/local/csf/bin/ +cp -avf readme.txt /etc/csf/ +cp -avf sanity.txt /usr/local/csf/lib/ +cp -avf csf.rbls /usr/local/csf/lib/ +cp -avf restricted.txt /usr/local/csf/lib/ +cp -avf changelog.txt /etc/csf/ +cp -avf downloadservers /etc/csf/ +cp -avf install.txt /etc/csf/ +cp -avf version.txt /etc/csf/ +cp -avf license.txt /etc/csf/ +cp -avf webmin /usr/local/csf/lib/ +cp -avf ConfigServer /usr/local/csf/lib/ +cp -avf Net /usr/local/csf/lib/ +cp -avf Geo /usr/local/csf/lib/ +cp -avf Crypt /usr/local/csf/lib/ +cp -avf HTTP /usr/local/csf/lib/ +cp -avf JSON /usr/local/csf/lib/ +cp -avf version/* /usr/local/csf/lib/ +cp -avf csf.div /usr/local/csf/lib/ +cp -avf csfajaxtail.js /usr/local/csf/lib/ +cp -avf ui/images /etc/csf/ui/. +cp -avf profiles /usr/local/csf/ +cp -avf csf.conf /usr/local/csf/profiles/reset_to_defaults.conf +cp -avf lfd.logrotate /etc/logrotate.d/lfd +chcon --reference /etc/logrotate.d /etc/logrotate.d/lfd + +if [ -e "/usr/local/cwpsrv/" ]; then + if [ -e "/usr/local/cwpsrv/htdocs/resources/admin/modules/csf.orig.php" ]; then + mv -fv /usr/local/cwpsrv/htdocs/resources/admin/modules/csf.orig.php /usr/local/cwpsrv/htdocs/resources/admin/modules/csf.php + fi +fi + +#if [ -e "/usr/local/cwpsrv/" ]; then +# if [ ! -e "/etc/csf/cwp.disable" ]; then +# cp -avf cwp /usr/local/csf/lib/ +## chattr -i /usr/local/cwpsrv/htdocs/admin/ +## ln -svf /usr/local/csf/lib/cwp/ /usr/local/cwpsrv/htdocs/admin/csf +## chattr +i /usr/local/cwpsrv/htdocs/admin/ +# if [ ! -e "/usr/local/cwpsrv/htdocs/resources/admin/modules/csf.orig.php" ]; then +# mv -fv /usr/local/cwpsrv/htdocs/resources/admin/modules/csf.php /usr/local/cwpsrv/htdocs/resources/admin/modules/csf.orig.php +# fi +# rm -fv /usr/local/cwpsrv/htdocs/resources/admin/modules/csf.php +# ln -svf /usr/local/csf/lib/cwp/cwp_csf_r.php /usr/local/cwpsrv/htdocs/resources/admin/modules/csf.php +# fi +#fi + +if [ -e "/usr/local/ispconfig/interface/web/csf/ispconfig_csf" ]; then + rm -Rfv /usr/local/ispconfig/interface/web/csf/ +fi + +rm -fv /etc/csf/csf.spamhaus /etc/csf/csf.dshield /etc/csf/csf.tor /etc/csf/csf.bogon + +mkdir -p /usr/local/man/man1/ +cp -avf csf.1.txt /usr/local/man/man1/csf.1 +cp -avf csf.help /usr/local/csf/lib/ +chmod 755 /usr/local/man/ +chmod 755 /usr/local/man/man1/ +chmod 644 /usr/local/man/man1/csf.1 + +chmod -R 600 /etc/csf +chmod -R 600 /var/lib/csf +chmod -R 600 /usr/local/csf/bin +chmod -R 600 /usr/local/csf/lib +chmod -R 600 /usr/local/csf/tpl +chmod -R 600 /usr/local/csf/profiles +chmod 600 /var/log/lfd.log* + +chmod -v 700 /usr/local/csf/bin/*.pl /usr/local/csf/bin/*.sh /usr/local/csf/bin/*.pm +chmod -v 700 /etc/csf/*.pl /etc/csf/*.cgi /etc/csf/*.sh /etc/csf/*.php /etc/csf/*.py +chmod -v 700 /etc/csf/webmin/csf/index.cgi +chmod -v 644 /etc/cron.d/lfd-cron +chmod -v 644 /etc/cron.d/csf-cron + +cp -avf csget.pl /etc/cron.daily/csget +chmod 700 /etc/cron.daily/csget +/etc/cron.daily/csget --nosleep + +chmod -v 700 auto.cwp.pl +./auto.cwp.pl $OLDVERSION + +if test `cat /proc/1/comm` = "systemd" +then + if [ -e /etc/init.d/lfd ]; then + if [ -f /etc/redhat-release ]; then + /sbin/chkconfig csf off + /sbin/chkconfig lfd off + /sbin/chkconfig csf --del + /sbin/chkconfig lfd --del + elif [ -f /etc/debian_version ] || [ -f /etc/lsb-release ]; then + update-rc.d -f lfd remove + update-rc.d -f csf remove + elif [ -f /etc/gentoo-release ]; then + rc-update del lfd default + rc-update del csf default + elif [ -f /etc/slackware-version ]; then + rm -vf /etc/rc.d/rc3.d/S80csf + rm -vf /etc/rc.d/rc4.d/S80csf + rm -vf /etc/rc.d/rc5.d/S80csf + rm -vf /etc/rc.d/rc3.d/S85lfd + rm -vf /etc/rc.d/rc4.d/S85lfd + rm -vf /etc/rc.d/rc5.d/S85lfd + else + /sbin/chkconfig csf off + /sbin/chkconfig lfd off + /sbin/chkconfig csf --del + /sbin/chkconfig lfd --del + fi + rm -fv /etc/init.d/csf + rm -fv /etc/init.d/lfd + fi + + mkdir -p /etc/systemd/system/ + mkdir -p /usr/lib/systemd/system/ + cp -avf lfd.service /usr/lib/systemd/system/ + cp -avf csf.service /usr/lib/systemd/system/ + + chcon -h system_u:object_r:systemd_unit_file_t:s0 /usr/lib/systemd/system/lfd.service + chcon -h system_u:object_r:systemd_unit_file_t:s0 /usr/lib/systemd/system/csf.service + + systemctl daemon-reload + + systemctl enable csf.service + systemctl enable lfd.service + + systemctl disable firewalld + systemctl stop firewalld + systemctl mask firewalld +else + cp -avf lfd.sh /etc/init.d/lfd + cp -avf csf.sh /etc/init.d/csf + chmod -v 755 /etc/init.d/lfd + chmod -v 755 /etc/init.d/csf + + if [ -f /etc/redhat-release ]; then + /sbin/chkconfig lfd on + /sbin/chkconfig csf on + elif [ -f /etc/debian_version ] || [ -f /etc/lsb-release ]; then + update-rc.d -f lfd remove + update-rc.d -f csf remove + update-rc.d lfd defaults 80 20 + update-rc.d csf defaults 20 80 + elif [ -f /etc/gentoo-release ]; then + rc-update add lfd default + rc-update add csf default + elif [ -f /etc/slackware-version ]; then + ln -svf /etc/init.d/csf /etc/rc.d/rc3.d/S80csf + ln -svf /etc/init.d/csf /etc/rc.d/rc4.d/S80csf + ln -svf /etc/init.d/csf /etc/rc.d/rc5.d/S80csf + ln -svf /etc/init.d/lfd /etc/rc.d/rc3.d/S85lfd + ln -svf /etc/init.d/lfd /etc/rc.d/rc4.d/S85lfd + ln -svf /etc/init.d/lfd /etc/rc.d/rc5.d/S85lfd + else + /sbin/chkconfig lfd on + /sbin/chkconfig csf on + fi +fi + +chown -Rf root:root /etc/csf /var/lib/csf /usr/local/csf +chown -f root:root /usr/sbin/csf /usr/sbin/lfd /etc/logrotate.d/lfd /etc/cron.d/csf-cron /etc/cron.d/lfd-cron /usr/local/man/man1/csf.1 /usr/lib/systemd/system/lfd.service /usr/lib/systemd/system/csf.service /etc/init.d/lfd /etc/init.d/csf + +cp -av cwp/csfofficial.php /usr/local/cwpsrv/htdocs/resources/admin/modules/ +cp -av cwp/csf.pl /usr/local/cwpsrv/htdocs/resources/admin/modules/ +chmod 700 /usr/local/cwpsrv/htdocs/resources/admin/modules/csf.pl +cp -av cwp/ajax_csfframe.php /usr/local/cwpsrv/htdocs/resources/admin/addons/ajax/ +cp -av cwp/configserver.php /usr/local/cwpsrv/htdocs/resources/admin/include/ +mkdir -v -m 0600 /usr/local/cwpsrv/htdocs/admin/design/csf/ +cp -avf csf/* /usr/local/cwpsrv/htdocs/admin/design/csf/ + +cd webmin ; tar -czf /usr/local/csf/csfwebmin.tgz ./* +ln -svf /usr/local/csf/csfwebmin.tgz /etc/csf/ + +echo +echo "Installation Completed" +echo diff --git a/src/redux/install.cyberpanel.sh b/src/redux/install.cyberpanel.sh new file mode 100644 index 000000000..04b30e4be --- /dev/null +++ b/src/redux/install.cyberpanel.sh @@ -0,0 +1,536 @@ +#!/bin/sh +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### + +umask 0177 + +if [ -e "/usr/local/cpanel/version" ]; then + echo "Running csf cPanel installer" + echo + sh install.cpanel.sh + exit 0 +elif [ -e "/usr/local/directadmin/directadmin" ]; then + echo "Running csf DirectAdmin installer" + echo + sh install.directadmin.sh + exit 0 +fi + +echo "Installing csf and lfd" +echo + +echo "Check we're running as root" +if [ ! `id -u` = 0 ]; then + echo + echo "FAILED: You have to be logged in as root (UID:0) to install csf" + exit +fi +echo + +mkdir -v -m 0600 /etc/csf +cp -avf install.txt /etc/csf/ + +echo "Checking Perl modules..." +chmod 700 os.pl +RETURN=`./os.pl` +if [ "$RETURN" = 1 ]; then + echo + echo "FAILED: You MUST install the missing perl modules above before you can install csf. See /etc/csf/install.txt for installation details." + echo + exit +else + echo "...Perl modules OK" + echo +fi + +mkdir -v -m 0600 /etc/csf +mkdir -v -m 0600 /var/lib/csf +mkdir -v -m 0600 /var/lib/csf/backup +mkdir -v -m 0600 /var/lib/csf/Geo +mkdir -v -m 0600 /var/lib/csf/ui +mkdir -v -m 0600 /var/lib/csf/stats +mkdir -v -m 0600 /var/lib/csf/lock +mkdir -v -m 0600 /var/lib/csf/webmin +mkdir -v -m 0600 /var/lib/csf/zone +mkdir -v -m 0600 /usr/local/csf +mkdir -v -m 0600 /usr/local/csf/bin +mkdir -v -m 0600 /usr/local/csf/lib +mkdir -v -m 0600 /usr/local/csf/tpl + +if [ -e "/etc/csf/alert.txt" ]; then + sh migratedata.sh +fi + +if [ ! -e "/etc/csf/csf.conf" ]; then + cp -avf csf.cyberpanel.conf /etc/csf/csf.conf +fi + +if [ ! -d /var/lib/csf ]; then + mkdir -v -p -m 0600 /var/lib/csf +fi +if [ ! -d /usr/local/csf/lib ]; then + mkdir -v -p -m 0600 /usr/local/csf/lib +fi +if [ ! -d /usr/local/csf/bin ]; then + mkdir -v -p -m 0600 /usr/local/csf/bin +fi +if [ ! -d /usr/local/csf/tpl ]; then + mkdir -v -p -m 0600 /usr/local/csf/tpl +fi + +if [ ! -e "/etc/csf/csf.allow" ]; then + cp -avf csf.cyberpanel.allow /etc/csf/csf.allow +fi +if [ ! -e "/etc/csf/csf.deny" ]; then + cp -avf csf.deny /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.redirect" ]; then + cp -avf csf.redirect /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.resellers" ]; then + cp -avf csf.resellers /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.dirwatch" ]; then + cp -avf csf.dirwatch /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.syslogs" ]; then + cp -avf csf.syslogs /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.logfiles" ]; then + cp -avf csf.logfiles /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.logignore" ]; then + cp -avf csf.logignore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.blocklists" ]; then + cp -avf csf.blocklists /etc/csf/. +else + cp -avf csf.blocklists /etc/csf/csf.blocklists.new +fi +if [ ! -e "/etc/csf/csf.ignore" ]; then + cp -avf csf.cyberpanel.ignore /etc/csf/csf.ignore +fi +if [ ! -e "/etc/csf/csf.pignore" ]; then + cp -avf csf.cyberpanel.pignore /etc/csf/csf.pignore +fi +if [ ! -e "/etc/csf/csf.rignore" ]; then + cp -avf csf.rignore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.fignore" ]; then + cp -avf csf.fignore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.signore" ]; then + cp -avf csf.signore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.suignore" ]; then + cp -avf csf.suignore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.uidignore" ]; then + cp -avf csf.uidignore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.mignore" ]; then + cp -avf csf.mignore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.sips" ]; then + cp -avf csf.sips /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.dyndns" ]; then + cp -avf csf.dyndns /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.syslogusers" ]; then + cp -avf csf.syslogusers /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.smtpauth" ]; then + cp -avf csf.smtpauth /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.rblconf" ]; then + cp -avf csf.rblconf /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.cloudflare" ]; then + cp -avf csf.cloudflare /etc/csf/. +fi + +if [ ! -e "/usr/local/csf/tpl/alert.txt" ]; then + cp -avf alert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/reselleralert.txt" ]; then + cp -avf reselleralert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/logalert.txt" ]; then + cp -avf logalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/logfloodalert.txt" ]; then + cp -avf logfloodalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/syslogalert.txt" ]; then + cp -avf syslogalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/integrityalert.txt" ]; then + cp -avf integrityalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/exploitalert.txt" ]; then + cp -avf exploitalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/queuealert.txt" ]; then + cp -avf queuealert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/modsecipdbalert.txt" ]; then + cp -avf modsecipdbalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/tracking.txt" ]; then + cp -avf tracking.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/connectiontracking.txt" ]; then + cp -avf connectiontracking.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/processtracking.txt" ]; then + cp -avf processtracking.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/accounttracking.txt" ]; then + cp -avf accounttracking.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/usertracking.txt" ]; then + cp -avf usertracking.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/sshalert.txt" ]; then + cp -avf sshalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/webminalert.txt" ]; then + cp -avf webminalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/sualert.txt" ]; then + cp -avf sualert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/sudoalert.txt" ]; then + cp -avf sudoalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/consolealert.txt" ]; then + cp -avf consolealert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/uialert.txt" ]; then + cp -avf uialert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/cpanelalert.txt" ]; then + cp -avf cpanelalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/scriptalert.txt" ]; then + cp -avf scriptalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/relayalert.txt" ]; then + cp -avf relayalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/filealert.txt" ]; then + cp -avf filealert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/watchalert.txt" ]; then + cp -avf watchalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/loadalert.txt" ]; then + cp -avf loadalert.txt /usr/local/csf/tpl/. +else + cp -avf loadalert.txt /usr/local/csf/tpl/loadalert.txt.new +fi +if [ ! -e "/usr/local/csf/tpl/resalert.txt" ]; then + cp -avf resalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/portscan.txt" ]; then + cp -avf portscan.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/uidscan.txt" ]; then + cp -avf uidscan.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/permblock.txt" ]; then + cp -avf permblock.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/netblock.txt" ]; then + cp -avf netblock.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/portknocking.txt" ]; then + cp -avf portknocking.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/forkbombalert.txt" ]; then + cp -avf forkbombalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/recaptcha.txt" ]; then + cp -avf recaptcha.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/apache.main.txt" ]; then + cp -avf apache.main.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/apache.http.txt" ]; then + cp -avf apache.http.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/apache.https.txt" ]; then + cp -avf apache.https.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/litespeed.main.txt" ]; then + cp -avf litespeed.main.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/litespeed.http.txt" ]; then + cp -avf litespeed.http.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/litespeed.https.txt" ]; then + cp -avf litespeed.https.txt /usr/local/csf/tpl/. +fi +cp -avf x-arf.txt /usr/local/csf/tpl/. + +if [ ! -e "/usr/local/csf/bin/regex.custom.pm" ]; then + cp -avf regex.custom.pm /usr/local/csf/bin/. +fi +if [ ! -e "/usr/local/csf/bin/pt_deleted_action.pl" ]; then + cp -avf pt_deleted_action.pl /usr/local/csf/bin/. +fi +if [ ! -e "/etc/csf/messenger" ]; then + cp -avf messenger /etc/csf/. +fi +if [ ! -e "/etc/csf/messenger/index.recaptcha.html" ]; then + cp -avf messenger/index.recaptcha.html /etc/csf/messenger/. +fi +if [ ! -e "/etc/csf/ui" ]; then + cp -avf ui /etc/csf/. +fi +if [ -e "/etc/cron.d/csfcron.sh" ]; then + mv -fv /etc/cron.d/csfcron.sh /etc/cron.d/csf-cron +fi +if [ ! -e "/etc/cron.d/csf-cron" ]; then + cp -avf csfcron.sh /etc/cron.d/csf-cron +fi +if [ -e "/etc/cron.d/lfdcron.sh" ]; then + mv -fv /etc/cron.d/lfdcron.sh /etc/cron.d/lfd-cron +fi +if [ ! -e "/etc/cron.d/lfd-cron" ]; then + cp -avf lfdcron.sh /etc/cron.d/lfd-cron +fi +sed -i "s%/etc/init.d/lfd restart%/usr/sbin/csf --lfd restart%" /etc/cron.d/lfd-cron +if [ -e "/usr/local/csf/bin/servercheck.pm" ]; then + rm -f /usr/local/csf/bin/servercheck.pm +fi +if [ -e "/etc/csf/cseui.pl" ]; then + rm -f /etc/csf/cseui.pl +fi +if [ -e "/etc/csf/csfui.pl" ]; then + rm -f /etc/csf/csfui.pl +fi +if [ -e "/etc/csf/csfuir.pl" ]; then + rm -f /etc/csf/csfuir.pl +fi +if [ -e "/usr/local/csf/bin/cseui.pl" ]; then + rm -f /usr/local/csf/bin/cseui.pl +fi +if [ -e "/usr/local/csf/bin/csfui.pl" ]; then + rm -f /usr/local/csf/bin/csfui.pl +fi +if [ -e "/usr/local/csf/bin/csfuir.pl" ]; then + rm -f /usr/local/csf/bin/csfuir.pl +fi +if [ -e "/usr/local/csf/bin/regex.pm" ]; then + rm -f /usr/local/csf/bin/regex.pm +fi + +OLDVERSION=0 +if [ -e "/etc/csf/version.txt" ]; then + OLDVERSION=`head -n 1 /etc/csf/version.txt` +fi + +rm -f /etc/csf/csf.pl /usr/sbin/csf /etc/csf/lfd.pl /usr/sbin/lfd +chmod 700 csf.pl lfd.pl +cp -avf csf.pl /usr/sbin/csf +cp -avf lfd.pl /usr/sbin/lfd +chmod 700 /usr/sbin/csf /usr/sbin/lfd +ln -svf /usr/sbin/csf /etc/csf/csf.pl +ln -svf /usr/sbin/lfd /etc/csf/lfd.pl +ln -svf /usr/local/csf/bin/csftest.pl /etc/csf/ +ln -svf /usr/local/csf/bin/pt_deleted_action.pl /etc/csf/ +ln -svf /usr/local/csf/bin/remove_apf_bfd.sh /etc/csf/ +ln -svf /usr/local/csf/bin/uninstall.sh /etc/csf/ +ln -svf /usr/local/csf/bin/regex.custom.pm /etc/csf/ +ln -svf /usr/local/csf/lib/webmin /etc/csf/ +if [ ! -e "/etc/csf/alerts" ]; then + ln -svf /usr/local/csf/tpl /etc/csf/alerts +fi +chcon -h system_u:object_r:bin_t:s0 /usr/sbin/lfd +chcon -h system_u:object_r:bin_t:s0 /usr/sbin/csf + +mkdir webmin/csf/images +mkdir ui/images +mkdir da/images +mkdir interworx/images + +cp -avf csf/* webmin/csf/images/ +cp -avf csf/* ui/images/ +cp -avf csf/* da/images/ +cp -avf csf/* interworx/images/ + +cp -avf messenger/*.php /etc/csf/messenger/ +cp -avf uninstall.cyberpanel.sh /usr/local/csf/bin/uninstall.sh +cp -avf csftest.pl /usr/local/csf/bin/ +cp -avf remove_apf_bfd.sh /usr/local/csf/bin/ +cp -avf readme.txt /etc/csf/ +cp -avf sanity.txt /usr/local/csf/lib/ +cp -avf csf.rbls /usr/local/csf/lib/ +cp -avf restricted.txt /usr/local/csf/lib/ +cp -avf changelog.txt /etc/csf/ +cp -avf downloadservers /etc/csf/ +cp -avf install.txt /etc/csf/ +cp -avf version.txt /etc/csf/ +cp -avf license.txt /etc/csf/ +cp -avf webmin /usr/local/csf/lib/ +cp -avf ConfigServer /usr/local/csf/lib/ +cp -avf Net /usr/local/csf/lib/ +cp -avf Geo /usr/local/csf/lib/ +cp -avf Crypt /usr/local/csf/lib/ +cp -avf HTTP /usr/local/csf/lib/ +cp -avf JSON /usr/local/csf/lib/ +cp -avf version/* /usr/local/csf/lib/ +cp -avf csf.div /usr/local/csf/lib/ +cp -avf csfajaxtail.js /usr/local/csf/lib/ +cp -avf ui/images /etc/csf/ui/. +cp -avf profiles /usr/local/csf/ +cp -avf csf.conf /usr/local/csf/profiles/reset_to_defaults.conf +cp -avf lfd.logrotate /etc/logrotate.d/lfd +chcon --reference /etc/logrotate.d /etc/logrotate.d/lfd +cp -avf apf_stub.pl /etc/csf/ + +rm -fv /etc/csf/csf.spamhaus /etc/csf/csf.dshield /etc/csf/csf.tor /etc/csf/csf.bogon + +mkdir -p /usr/local/man/man1/ +cp -avf csf.1.txt /usr/local/man/man1/csf.1 +cp -avf csf.help /usr/local/csf/lib/ +chmod 755 /usr/local/man/ +chmod 755 /usr/local/man/man1/ +chmod 644 /usr/local/man/man1/csf.1 + +chmod -R 600 /etc/csf +chmod -R 600 /var/lib/csf +chmod -R 600 /usr/local/csf/bin +chmod -R 600 /usr/local/csf/lib +chmod -R 600 /usr/local/csf/tpl +chmod -R 600 /usr/local/csf/profiles +chmod 600 /var/log/lfd.log* + +chmod -v 700 /usr/local/csf/bin/*.pl /usr/local/csf/bin/*.sh /usr/local/csf/bin/*.pm +chmod -v 700 /etc/csf/*.pl /etc/csf/*.cgi /etc/csf/*.sh /etc/csf/*.php /etc/csf/*.py +chmod -v 700 /etc/csf/webmin/csf/index.cgi +chmod -v 644 /etc/cron.d/lfd-cron +chmod -v 644 /etc/cron.d/csf-cron + +cp -avf csget.pl /etc/cron.daily/csget +chmod 700 /etc/cron.daily/csget +/etc/cron.daily/csget --nosleep + +chmod -v 700 auto.cyberpanel.pl +./auto.cyberpanel.pl $OLDVERSION + +if test `cat /proc/1/comm` = "systemd" +then + if [ -e /etc/init.d/lfd ]; then + if [ -f /etc/redhat-release ]; then + /sbin/chkconfig csf off + /sbin/chkconfig lfd off + /sbin/chkconfig csf --del + /sbin/chkconfig lfd --del + elif [ -f /etc/debian_version ] || [ -f /etc/lsb-release ]; then + update-rc.d -f lfd remove + update-rc.d -f csf remove + elif [ -f /etc/gentoo-release ]; then + rc-update del lfd default + rc-update del csf default + elif [ -f /etc/slackware-version ]; then + rm -vf /etc/rc.d/rc3.d/S80csf + rm -vf /etc/rc.d/rc4.d/S80csf + rm -vf /etc/rc.d/rc5.d/S80csf + rm -vf /etc/rc.d/rc3.d/S85lfd + rm -vf /etc/rc.d/rc4.d/S85lfd + rm -vf /etc/rc.d/rc5.d/S85lfd + else + /sbin/chkconfig csf off + /sbin/chkconfig lfd off + /sbin/chkconfig csf --del + /sbin/chkconfig lfd --del + fi + rm -fv /etc/init.d/csf + rm -fv /etc/init.d/lfd + fi + + mkdir -p /etc/systemd/system/ + mkdir -p /usr/lib/systemd/system/ + cp -avf lfd.service /usr/lib/systemd/system/ + cp -avf csf.service /usr/lib/systemd/system/ + + chcon -h system_u:object_r:systemd_unit_file_t:s0 /usr/lib/systemd/system/lfd.service + chcon -h system_u:object_r:systemd_unit_file_t:s0 /usr/lib/systemd/system/csf.service + + systemctl daemon-reload + + systemctl enable csf.service + systemctl enable lfd.service + + systemctl disable firewalld + systemctl stop firewalld + systemctl mask firewalld +else + cp -avf lfd.sh /etc/init.d/lfd + cp -avf csf.sh /etc/init.d/csf + chmod -v 755 /etc/init.d/lfd + chmod -v 755 /etc/init.d/csf + + if [ -f /etc/redhat-release ]; then + /sbin/chkconfig lfd on + /sbin/chkconfig csf on + elif [ -f /etc/debian_version ] || [ -f /etc/lsb-release ]; then + update-rc.d -f lfd remove + update-rc.d -f csf remove + update-rc.d lfd defaults 80 20 + update-rc.d csf defaults 20 80 + elif [ -f /etc/gentoo-release ]; then + rc-update add lfd default + rc-update add csf default + elif [ -f /etc/slackware-version ]; then + ln -svf /etc/init.d/csf /etc/rc.d/rc3.d/S80csf + ln -svf /etc/init.d/csf /etc/rc.d/rc4.d/S80csf + ln -svf /etc/init.d/csf /etc/rc.d/rc5.d/S80csf + ln -svf /etc/init.d/lfd /etc/rc.d/rc3.d/S85lfd + ln -svf /etc/init.d/lfd /etc/rc.d/rc4.d/S85lfd + ln -svf /etc/init.d/lfd /etc/rc.d/rc5.d/S85lfd + else + /sbin/chkconfig lfd on + /sbin/chkconfig csf on + fi +fi + +chown -Rf root:root /etc/csf /var/lib/csf /usr/local/csf +chown -f root:root /usr/sbin/csf /usr/sbin/lfd /etc/logrotate.d/lfd /etc/cron.d/csf-cron /etc/cron.d/lfd-cron /usr/local/man/man1/csf.1 /usr/lib/systemd/system/lfd.service /usr/lib/systemd/system/csf.service /etc/init.d/lfd /etc/init.d/csf + +mkdir -vp /usr/local/CyberCP/public/static/configservercsf/ +cp -avf csf/* /usr/local/CyberCP/public/static/configservercsf/ +cp -avf csf/* cyberpanel/configservercsf/static/configservercsf/ +chmod 755 /usr/local/CyberCP/public/static/configservercsf/ + +cp cyberpanel/cyberpanel.pl /usr/local/csf/bin/ +chmod 700 /usr/local/csf/bin/cyberpanel.pl +cp -avf cyberpanel/configservercsf /usr/local/CyberCP/ + +mkdir /home/cyberpanel/plugins +touch /home/cyberpanel/plugins/configservercsf + +if ! cat /usr/local/CyberCP/CyberCP/settings.py | grep -q configservercsf; then + sed -i "/pluginHolder/ i \ \ \ \ 'configservercsf'," /usr/local/CyberCP/CyberCP/settings.py +fi +if ! cat /usr/local/CyberCP/CyberCP/urls.py | grep -q configservercsf; then + sed -i "/pluginHolder/ i \ \ \ \ url(r'^configservercsf/',include('configservercsf.urls'))," /usr/local/CyberCP/CyberCP/urls.py +fi +#if ! cat /usr/local/CyberCP/baseTemplate/templates/baseTemplate/index.html | grep -q configservercsf; then +# sed -i "/url 'csf'/ i
        • ConfigServer Security \& Firewall
        • " /usr/local/CyberCP/baseTemplate/templates/baseTemplate/index.html +#fi +if ! cat /usr/local/CyberCP/baseTemplate/templates/baseTemplate/index.html | grep -q configserver; then + sed -i "/trans 'Plugins'/ i \{\% include \"/usr/local/CyberCP/configservercsf/templates/configservercsf/menu.html\" \%\}" /usr/local/CyberCP/baseTemplate/templates/baseTemplate/index.html +fi + +service lscpd restart + +echo +echo "Installation Completed" +echo diff --git a/src/redux/install.directadmin.sh b/src/redux/install.directadmin.sh new file mode 100644 index 000000000..e4d6cf4f6 --- /dev/null +++ b/src/redux/install.directadmin.sh @@ -0,0 +1,521 @@ +#!/bin/sh +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### + +umask 0177 + +echo "Installing csf and lfd" +echo + +echo "Check we're running as root" +if [ ! `id -u` = 0 ]; then + echo + echo "FAILED: You have to be logged in as root (UID:0) to install csf" + exit +fi +echo + +mkdir -v -m 0600 /etc/csf +cp -avf install.txt /etc/csf/ + +echo "Checking Perl modules..." +chmod 700 os.pl +RETURN=`./os.pl` +if [ "$RETURN" = 1 ]; then + echo + echo "FAILED: You MUST install the missing perl modules above before you can install csf. See /etc/csf/install.txt for installation details." + echo + exit +else + echo "...Perl modules OK" + echo +fi + +mkdir -v -m 0600 /var/lib/csf +mkdir -v -m 0600 /var/lib/csf/backup +mkdir -v -m 0600 /var/lib/csf/Geo +mkdir -v -m 0600 /var/lib/csf/ui +mkdir -v -m 0600 /var/lib/csf/stats +mkdir -v -m 0600 /var/lib/csf/lock +mkdir -v -m 0600 /var/lib/csf/webmin +mkdir -v -m 0600 /var/lib/csf/zone +mkdir -v -m 0600 /usr/local/csf +mkdir -v -m 0600 /usr/local/csf/bin +mkdir -v -m 0600 /usr/local/csf/lib +mkdir -v -m 0600 /usr/local/csf/tpl + +if [ -e "/etc/csf/alert.txt" ]; then + sh migratedata.sh +fi + +if [ ! -e "/etc/csf/csf.conf" ]; then + cp -avf csf.directadmin.conf /etc/csf/csf.conf +fi + +if [ ! -d /var/lib/csf ]; then + mkdir -v -p -m 0600 /var/lib/csf +fi +if [ ! -d /usr/local/csf/lib ]; then + mkdir -v -p -m 0600 /usr/local/csf/lib +fi +if [ ! -d /usr/local/csf/bin ]; then + mkdir -v -p -m 0600 /usr/local/csf/bin +fi +if [ ! -d /usr/local/csf/tpl ]; then + mkdir -v -p -m 0600 /usr/local/csf/tpl +fi + +if [ ! -e "/etc/csf/csf.allow" ]; then + cp -avf csf.directadmin.allow /etc/csf/csf.allow +fi +if [ ! -e "/etc/csf/csf.deny" ]; then + cp -avf csf.deny /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.redirect" ]; then + cp -avf csf.redirect /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.resellers" ]; then + cp -avf csf.resellers /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.dirwatch" ]; then + cp -avf csf.dirwatch /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.syslogs" ]; then + cp -avf csf.syslogs /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.logfiles" ]; then + cp -avf csf.logfiles /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.logignore" ]; then + cp -avf csf.logignore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.blocklists" ]; then + cp -avf csf.blocklists /etc/csf/. +else + cp -avf csf.blocklists /etc/csf/csf.blocklists.new +fi +if [ ! -e "/etc/csf/csf.ignore" ]; then + cp -avf csf.directadmin.ignore /etc/csf/csf.ignore +fi +if [ ! -e "/etc/csf/csf.pignore" ]; then + cp -avf csf.directadmin.pignore /etc/csf/csf.pignore +fi +if [ ! -e "/etc/csf/csf.rignore" ]; then + cp -avf csf.rignore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.fignore" ]; then + cp -avf csf.fignore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.signore" ]; then + cp -avf csf.signore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.suignore" ]; then + cp -avf csf.suignore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.uidignore" ]; then + cp -avf csf.uidignore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.mignore" ]; then + cp -avf csf.mignore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.sips" ]; then + cp -avf csf.sips /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.dyndns" ]; then + cp -avf csf.dyndns /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.syslogusers" ]; then + cp -avf csf.syslogusers /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.smtpauth" ]; then + cp -avf csf.smtpauth /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.rblconf" ]; then + cp -avf csf.rblconf /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.cloudflare" ]; then + cp -avf csf.cloudflare /etc/csf/. +fi + +if [ ! -e "/usr/local/csf/tpl/alert.txt" ]; then + cp -avf alert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/reselleralert.txt" ]; then + cp -avf reselleralert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/logalert.txt" ]; then + cp -avf logalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/logfloodalert.txt" ]; then + cp -avf logfloodalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/syslogalert.txt" ]; then + cp -avf syslogalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/integrityalert.txt" ]; then + cp -avf integrityalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/exploitalert.txt" ]; then + cp -avf exploitalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/queuealert.txt" ]; then + cp -avf queuealert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/modsecipdbalert.txt" ]; then + cp -avf modsecipdbalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/tracking.txt" ]; then + cp -avf tracking.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/connectiontracking.txt" ]; then + cp -avf connectiontracking.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/processtracking.txt" ]; then + cp -avf processtracking.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/accounttracking.txt" ]; then + cp -avf accounttracking.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/usertracking.txt" ]; then + cp -avf usertracking.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/sshalert.txt" ]; then + cp -avf sshalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/webminalert.txt" ]; then + cp -avf webminalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/sualert.txt" ]; then + cp -avf sualert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/sudoalert.txt" ]; then + cp -avf sudoalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/consolealert.txt" ]; then + cp -avf consolealert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/uialert.txt" ]; then + cp -avf uialert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/cpanelalert.txt" ]; then + cp -avf cpanelalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/scriptalert.txt" ]; then + cp -avf scriptalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/relayalert.txt" ]; then + cp -avf relayalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/filealert.txt" ]; then + cp -avf filealert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/watchalert.txt" ]; then + cp -avf watchalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/loadalert.txt" ]; then + cp -avf loadalert.txt /usr/local/csf/tpl/. +else + cp -avf loadalert.txt /usr/local/csf/tpl/loadalert.txt.new +fi +if [ ! -e "/usr/local/csf/tpl/resalert.txt" ]; then + cp -avf resalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/portscan.txt" ]; then + cp -avf portscan.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/uidscan.txt" ]; then + cp -avf uidscan.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/permblock.txt" ]; then + cp -avf permblock.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/netblock.txt" ]; then + cp -avf netblock.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/portknocking.txt" ]; then + cp -avf portknocking.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/forkbombalert.txt" ]; then + cp -avf forkbombalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/recaptcha.txt" ]; then + cp -avf recaptcha.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/apache.main.txt" ]; then + cp -avf apache.main.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/apache.http.txt" ]; then + cp -avf apache.http.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/apache.https.txt" ]; then + cp -avf apache.https.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/litespeed.main.txt" ]; then + cp -avf litespeed.main.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/litespeed.http.txt" ]; then + cp -avf litespeed.http.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/litespeed.https.txt" ]; then + cp -avf litespeed.https.txt /usr/local/csf/tpl/. +fi +cp -avf x-arf.txt /usr/local/csf/tpl/. + +if [ ! -e "/usr/local/csf/bin/regex.custom.pm" ]; then + cp -avf regex.custom.pm /usr/local/csf/bin/. +fi +if [ ! -e "/usr/local/csf/bin/pt_deleted_action.pl" ]; then + cp -avf pt_deleted_action.pl /usr/local/csf/bin/. +fi +if [ ! -e "/etc/csf/messenger" ]; then + cp -avf messenger /etc/csf/. +fi +if [ ! -e "/etc/csf/messenger/index.recaptcha.html" ]; then + cp -avf messenger/index.recaptcha.html /etc/csf/messenger/. +fi +if [ ! -e "/etc/csf/ui" ]; then + cp -avf ui /etc/csf/. +fi +if [ -e "/etc/cron.d/csfcron.sh" ]; then + mv -fv /etc/cron.d/csfcron.sh /etc/cron.d/csf-cron +fi +if [ ! -e "/etc/cron.d/csf-cron" ]; then + cp -avf csfcron.sh /etc/cron.d/csf-cron +fi +if [ -e "/etc/cron.d/lfdcron.sh" ]; then + mv -fv /etc/cron.d/lfdcron.sh /etc/cron.d/lfd-cron +fi +if [ ! -e "/etc/cron.d/lfd-cron" ]; then + cp -avf lfdcron.sh /etc/cron.d/lfd-cron +fi +sed -i "s%/etc/init.d/lfd restart%/usr/sbin/csf --lfd restart%" /etc/cron.d/lfd-cron +if [ -e "/usr/local/csf/bin/servercheck.pm" ]; then + rm -f /usr/local/csf/bin/servercheck.pm +fi +if [ -e "/etc/csf/cseui.pl" ]; then + rm -f /etc/csf/cseui.pl +fi +if [ -e "/etc/csf/csfui.pl" ]; then + rm -f /etc/csf/csfui.pl +fi +if [ -e "/etc/csf/csfuir.pl" ]; then + rm -f /etc/csf/csfuir.pl +fi +if [ -e "/usr/local/csf/bin/cseui.pl" ]; then + rm -f /usr/local/csf/bin/cseui.pl +fi +if [ -e "/usr/local/csf/bin/csfui.pl" ]; then + rm -f /usr/local/csf/bin/csfui.pl +fi +if [ -e "/usr/local/csf/bin/csfuir.pl" ]; then + rm -f /usr/local/csf/bin/csfuir.pl +fi +if [ -e "/usr/local/csf/bin/regex.pm" ]; then + rm -f /usr/local/csf/bin/regex.pm +fi + +OLDVERSION=0 +if [ -e "/etc/csf/version.txt" ]; then + OLDVERSION=`head -n 1 /etc/csf/version.txt` +fi + +rm -f /etc/csf/csf.pl /usr/sbin/csf /etc/csf/lfd.pl /usr/sbin/lfd +chmod 700 csf.pl lfd.pl +cp -avf csf.pl /usr/sbin/csf +cp -avf lfd.pl /usr/sbin/lfd +chmod 700 /usr/sbin/csf /usr/sbin/lfd +ln -svf /usr/sbin/csf /etc/csf/csf.pl +ln -svf /usr/sbin/lfd /etc/csf/lfd.pl +ln -svf /usr/local/csf/bin/csftest.pl /etc/csf/ +ln -svf /usr/local/csf/bin/pt_deleted_action.pl /etc/csf/ +ln -svf /usr/local/csf/bin/remove_apf_bfd.sh /etc/csf/ +ln -svf /usr/local/csf/bin/uninstall.sh /etc/csf/ +ln -svf /usr/local/csf/bin/regex.custom.pm /etc/csf/ +ln -svf /usr/local/csf/lib/webmin /etc/csf/ +if [ ! -e "/etc/csf/alerts" ]; then + ln -svf /usr/local/csf/tpl /etc/csf/alerts +fi +chcon -h system_u:object_r:bin_t:s0 /usr/sbin/lfd +chcon -h system_u:object_r:bin_t:s0 /usr/sbin/csf + +mkdir webmin/csf/images +mkdir ui/images +mkdir da/images +mkdir interworx/images + +cp -avf csf/* webmin/csf/images/ +cp -avf csf/* ui/images/ +cp -avf csf/* da/images/ +cp -avf csf/* interworx/images/ + +cp -avf messenger/*.php /etc/csf/messenger/ +cp -avf uninstall.directadmin.sh /usr/local/csf/bin/uninstall.sh +cp -avf csftest.pl /usr/local/csf/bin/ +cp -avf remove_apf_bfd.sh /usr/local/csf/bin/ +cp -avf readme.txt /etc/csf/ +cp -avf sanity.txt /usr/local/csf/lib/ +cp -avf csf.rbls /usr/local/csf/lib/ +cp -avf restricted.txt /usr/local/csf/lib/ +cp -avf changelog.txt /etc/csf/ +cp -avf downloadservers /etc/csf/ +cp -avf install.txt /etc/csf/ +cp -avf version.txt /etc/csf/ +cp -avf license.txt /etc/csf/ +cp -avf webmin /usr/local/csf/lib/ +cp -avf ConfigServer /usr/local/csf/lib/ +cp -avf Net /usr/local/csf/lib/ +cp -avf Geo /usr/local/csf/lib/ +cp -avf Crypt /usr/local/csf/lib/ +cp -avf HTTP /usr/local/csf/lib/ +cp -avf JSON /usr/local/csf/lib/ +cp -avf version/* /usr/local/csf/lib/ +cp -avf csf.div /usr/local/csf/lib/ +cp -avf csfajaxtail.js /usr/local/csf/lib/ +cp -avf ui/images /etc/csf/ui/. +cp -avf profiles /usr/local/csf/ +cp -avf csf.conf /usr/local/csf/profiles/reset_to_defaults.conf +cp -avf lfd.logrotate /etc/logrotate.d/lfd + +rm -fv /etc/csf/csf.spamhaus /etc/csf/csf.dshield /etc/csf/csf.tor /etc/csf/csf.bogon + +mkdir -p /usr/local/man/man1/ +cp -avf csf.1.txt /usr/local/man/man1/csf.1 +cp -avf csf.help /usr/local/csf/lib/ +chmod 755 /usr/local/man/ +chmod 755 /usr/local/man/man1/ +chmod 644 /usr/local/man/man1/csf.1 + +chmod -R 600 /etc/csf +chmod -R 600 /var/lib/csf +chmod -R 600 /usr/local/csf/bin +chmod -R 600 /usr/local/csf/lib +chmod -R 600 /usr/local/csf/tpl +chmod -R 600 /usr/local/csf/profiles +chmod 600 /var/log/lfd.log* + +chmod -v 700 /usr/local/csf/bin/*.pl /usr/local/csf/bin/*.sh /usr/local/csf/bin/*.pm +chmod -v 700 /etc/csf/*.pl /etc/csf/*.cgi /etc/csf/*.sh /etc/csf/*.php /etc/csf/*.py +chmod -v 700 /etc/csf/webmin/csf/index.cgi +chmod -v 644 /etc/cron.d/lfd-cron +chmod -v 644 /etc/cron.d/csf-cron + +cp -avf csget.pl /etc/cron.daily/csget +chmod 700 /etc/cron.daily/csget +/etc/cron.daily/csget --nosleep + +chmod -v 700 auto.directadmin.pl +./auto.directadmin.pl $OLDVERSION + +mkdir -p /usr/local/directadmin/plugins/csf/ +chmod 711 /usr/local/directadmin/plugins/csf +chown diradmin:diradmin /usr/local/directadmin/plugins/csf +cp -avf da/* /usr/local/directadmin/plugins/csf/ +cp -avf csf/* /usr/local/directadmin/plugins/csf/images/ +find /usr/local/directadmin/plugins/csf/ -type d -exec chmod -v 755 {} \; +find /usr/local/directadmin/plugins/csf/ -type f -exec chmod -v 644 {} \; + +if [ -e "/usr/local/directadmin/plugins/csf/exec/csf" ]; then + rm -f /usr/local/directadmin/plugins/csf/exec/csf +fi +export PATH=$PATH; +gcc -o /usr/local/directadmin/plugins/csf/exec/csf csf.c +chown -Rv diradmin:diradmin /usr/local/directadmin/plugins/csf +chmod -v 755 /usr/local/directadmin/plugins/csf/admin/index.html +chmod -v 755 /usr/local/directadmin/plugins/csf/admin/index.raw +chmod -v 755 /usr/local/directadmin/plugins/csf/exec/da_csf.cgi +chmod -v 755 /usr/local/directadmin/plugins/csf/reseller/index.html +chmod -v 755 /usr/local/directadmin/plugins/csf/reseller/index.raw +chmod -v 755 /usr/local/directadmin/plugins/csf/exec/da_csf_reseller.cgi +chmod -v 755 /usr/local/directadmin/plugins/csf/scripts/* +chown -v root:root /usr/local/directadmin/plugins/csf/exec/csf +chmod -v 4755 /usr/local/directadmin/plugins/csf/exec/csf + +if test `cat /proc/1/comm` = "systemd" +then + if [ -e /etc/init.d/lfd ]; then + if [ -f /etc/redhat-release ]; then + /sbin/chkconfig csf off + /sbin/chkconfig lfd off + /sbin/chkconfig csf --del + /sbin/chkconfig lfd --del + elif [ -f /etc/debian_version ] || [ -f /etc/lsb-release ]; then + update-rc.d -f lfd remove + update-rc.d -f csf remove + elif [ -f /etc/gentoo-release ]; then + rc-update del lfd default + rc-update del csf default + elif [ -f /etc/slackware-version ]; then + rm -vf /etc/rc.d/rc3.d/S80csf + rm -vf /etc/rc.d/rc4.d/S80csf + rm -vf /etc/rc.d/rc5.d/S80csf + rm -vf /etc/rc.d/rc3.d/S85lfd + rm -vf /etc/rc.d/rc4.d/S85lfd + rm -vf /etc/rc.d/rc5.d/S85lfd + else + /sbin/chkconfig csf off + /sbin/chkconfig lfd off + /sbin/chkconfig csf --del + /sbin/chkconfig lfd --del + fi + rm -fv /etc/init.d/csf + rm -fv /etc/init.d/lfd + fi + + mkdir -p /etc/systemd/system/ + mkdir -p /usr/lib/systemd/system/ + cp -avf lfd.service /usr/lib/systemd/system/ + cp -avf csf.service /usr/lib/systemd/system/ + + chcon -h system_u:object_r:systemd_unit_file_t:s0 /usr/lib/systemd/system/lfd.service + chcon -h system_u:object_r:systemd_unit_file_t:s0 /usr/lib/systemd/system/csf.service + + systemctl daemon-reload + + systemctl enable csf.service + systemctl enable lfd.service + + systemctl disable firewalld + systemctl stop firewalld + systemctl mask firewalld +else + cp -avf lfd.sh /etc/init.d/lfd + cp -avf csf.sh /etc/init.d/csf + chmod -v 755 /etc/init.d/lfd + chmod -v 755 /etc/init.d/csf + + if [ -f /etc/redhat-release ]; then + /sbin/chkconfig lfd on + /sbin/chkconfig csf on + elif [ -f /etc/debian_version ] || [ -f /etc/lsb-release ]; then + update-rc.d -f lfd remove + update-rc.d -f csf remove + update-rc.d lfd defaults 80 20 + update-rc.d csf defaults 20 80 + elif [ -f /etc/gentoo-release ]; then + rc-update add lfd default + rc-update add csf default + elif [ -f /etc/slackware-version ]; then + ln -svf /etc/init.d/csf /etc/rc.d/rc3.d/S80csf + ln -svf /etc/init.d/csf /etc/rc.d/rc4.d/S80csf + ln -svf /etc/init.d/csf /etc/rc.d/rc5.d/S80csf + ln -svf /etc/init.d/lfd /etc/rc.d/rc3.d/S85lfd + ln -svf /etc/init.d/lfd /etc/rc.d/rc4.d/S85lfd + ln -svf /etc/init.d/lfd /etc/rc.d/rc5.d/S85lfd + else + /sbin/chkconfig lfd on + /sbin/chkconfig csf on + fi +fi + +chown -Rf root:root /etc/csf /var/lib/csf /usr/local/csf +chown -f root:root /usr/sbin/csf /usr/sbin/lfd /etc/logrotate.d/lfd /etc/cron.d/csf-cron /etc/cron.d/lfd-cron /usr/local/man/man1/csf.1 /usr/lib/systemd/system/lfd.service /usr/lib/systemd/system/csf.service /etc/init.d/lfd /etc/init.d/csf + +cd webmin ; tar -czf /usr/local/csf/csfwebmin.tgz ./* +ln -svf /usr/local/csf/csfwebmin.tgz /etc/csf/ + +echo +echo "Installation Completed" +echo diff --git a/src/redux/install.generic.sh b/src/redux/install.generic.sh new file mode 100644 index 000000000..6c04de476 --- /dev/null +++ b/src/redux/install.generic.sh @@ -0,0 +1,515 @@ +#!/bin/sh +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### + +umask 0177 + +if [ -e "/usr/local/cpanel/version" ]; then + echo "Running csf cPanel installer" + echo + sh install.cpanel.sh + exit 0 +elif [ -e "/usr/local/directadmin/directadmin" ]; then + echo "Running csf DirectAdmin installer" + echo + sh install.directadmin.sh + exit 0 +fi + +echo "Installing generic csf and lfd" +echo + +echo "Check we're running as root" +if [ ! `id -u` = 0 ]; then + echo + echo "FAILED: You have to be logged in as root (UID:0) to install csf" + exit +fi +echo + +mkdir -v -m 0600 /etc/csf +cp -avf install.txt /etc/csf/ + +echo "Checking Perl modules..." +chmod 700 os.pl +RETURN=`./os.pl` +if [ "$RETURN" = 1 ]; then + echo + echo "FAILED: You MUST install the missing perl modules above before you can install csf. See /etc/csf/install.txt for installation details." + echo + exit +else + echo "...Perl modules OK" + echo +fi + +mkdir -v -m 0600 /etc/csf +mkdir -v -m 0600 /var/lib/csf +mkdir -v -m 0600 /var/lib/csf/backup +mkdir -v -m 0600 /var/lib/csf/Geo +mkdir -v -m 0600 /var/lib/csf/ui +mkdir -v -m 0600 /var/lib/csf/stats +mkdir -v -m 0600 /var/lib/csf/lock +mkdir -v -m 0600 /var/lib/csf/webmin +mkdir -v -m 0600 /var/lib/csf/zone +mkdir -v -m 0600 /usr/local/csf +mkdir -v -m 0600 /usr/local/csf/bin +mkdir -v -m 0600 /usr/local/csf/lib +mkdir -v -m 0600 /usr/local/csf/tpl + +if [ -e "/etc/csf/alert.txt" ]; then + sh migratedata.sh +fi + +if [ ! -e "/etc/csf/csf.conf" ]; then + cp -avf csf.generic.conf /etc/csf/csf.conf +fi + +if [ ! -d /var/lib/csf ]; then + mkdir -v -p -m 0600 /var/lib/csf +fi +if [ ! -d /usr/local/csf/lib ]; then + mkdir -v -p -m 0600 /usr/local/csf/lib +fi +if [ ! -d /usr/local/csf/bin ]; then + mkdir -v -p -m 0600 /usr/local/csf/bin +fi +if [ ! -d /usr/local/csf/tpl ]; then + mkdir -v -p -m 0600 /usr/local/csf/tpl +fi + +if [ ! -e "/etc/csf/csf.allow" ]; then + cp -avf csf.generic.allow /etc/csf/csf.allow +fi +if [ ! -e "/etc/csf/csf.deny" ]; then + cp -avf csf.deny /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.redirect" ]; then + cp -avf csf.redirect /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.resellers" ]; then + cp -avf csf.resellers /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.dirwatch" ]; then + cp -avf csf.dirwatch /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.syslogs" ]; then + cp -avf csf.syslogs /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.logfiles" ]; then + cp -avf csf.logfiles /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.logignore" ]; then + cp -avf csf.logignore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.blocklists" ]; then + cp -avf csf.blocklists /etc/csf/. +else + cp -avf csf.blocklists /etc/csf/csf.blocklists.new +fi +if [ ! -e "/etc/csf/csf.ignore" ]; then + cp -avf csf.generic.ignore /etc/csf/csf.ignore +fi +if [ ! -e "/etc/csf/csf.pignore" ]; then + cp -avf csf.generic.pignore /etc/csf/csf.pignore +fi +if [ ! -e "/etc/csf/csf.rignore" ]; then + cp -avf csf.rignore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.fignore" ]; then + cp -avf csf.fignore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.signore" ]; then + cp -avf csf.signore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.suignore" ]; then + cp -avf csf.suignore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.uidignore" ]; then + cp -avf csf.uidignore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.mignore" ]; then + cp -avf csf.mignore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.sips" ]; then + cp -avf csf.sips /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.dyndns" ]; then + cp -avf csf.dyndns /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.syslogusers" ]; then + cp -avf csf.syslogusers /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.smtpauth" ]; then + cp -avf csf.smtpauth /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.rblconf" ]; then + cp -avf csf.rblconf /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.cloudflare" ]; then + cp -avf csf.cloudflare /etc/csf/. +fi + +if [ ! -e "/usr/local/csf/tpl/alert.txt" ]; then + cp -avf alert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/reselleralert.txt" ]; then + cp -avf reselleralert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/logalert.txt" ]; then + cp -avf logalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/logfloodalert.txt" ]; then + cp -avf logfloodalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/syslogalert.txt" ]; then + cp -avf syslogalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/integrityalert.txt" ]; then + cp -avf integrityalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/exploitalert.txt" ]; then + cp -avf exploitalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/queuealert.txt" ]; then + cp -avf queuealert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/modsecipdbalert.txt" ]; then + cp -avf modsecipdbalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/tracking.txt" ]; then + cp -avf tracking.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/connectiontracking.txt" ]; then + cp -avf connectiontracking.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/processtracking.txt" ]; then + cp -avf processtracking.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/accounttracking.txt" ]; then + cp -avf accounttracking.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/usertracking.txt" ]; then + cp -avf usertracking.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/sshalert.txt" ]; then + cp -avf sshalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/webminalert.txt" ]; then + cp -avf webminalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/sualert.txt" ]; then + cp -avf sualert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/sudoalert.txt" ]; then + cp -avf sudoalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/consolealert.txt" ]; then + cp -avf consolealert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/uialert.txt" ]; then + cp -avf uialert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/cpanelalert.txt" ]; then + cp -avf cpanelalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/scriptalert.txt" ]; then + cp -avf scriptalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/relayalert.txt" ]; then + cp -avf relayalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/filealert.txt" ]; then + cp -avf filealert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/watchalert.txt" ]; then + cp -avf watchalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/loadalert.txt" ]; then + cp -avf loadalert.txt /usr/local/csf/tpl/. +else + cp -avf loadalert.txt /usr/local/csf/tpl/loadalert.txt.new +fi +if [ ! -e "/usr/local/csf/tpl/resalert.txt" ]; then + cp -avf resalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/portscan.txt" ]; then + cp -avf portscan.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/uidscan.txt" ]; then + cp -avf uidscan.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/permblock.txt" ]; then + cp -avf permblock.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/netblock.txt" ]; then + cp -avf netblock.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/portknocking.txt" ]; then + cp -avf portknocking.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/forkbombalert.txt" ]; then + cp -avf forkbombalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/recaptcha.txt" ]; then + cp -avf recaptcha.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/apache.main.txt" ]; then + cp -avf apache.main.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/apache.http.txt" ]; then + cp -avf apache.http.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/apache.https.txt" ]; then + cp -avf apache.https.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/litespeed.main.txt" ]; then + cp -avf litespeed.main.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/litespeed.http.txt" ]; then + cp -avf litespeed.http.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/litespeed.https.txt" ]; then + cp -avf litespeed.https.txt /usr/local/csf/tpl/. +fi +cp -avf x-arf.txt /usr/local/csf/tpl/. + +if [ ! -e "/usr/local/csf/bin/regex.custom.pm" ]; then + cp -avf regex.custom.pm /usr/local/csf/bin/. +fi +if [ ! -e "/usr/local/csf/bin/pt_deleted_action.pl" ]; then + cp -avf pt_deleted_action.pl /usr/local/csf/bin/. +fi +if [ ! -e "/etc/csf/messenger" ]; then + cp -avf messenger /etc/csf/. +fi +if [ ! -e "/etc/csf/messenger/index.recaptcha.html" ]; then + cp -avf messenger/index.recaptcha.html /etc/csf/messenger/. +fi +if [ ! -e "/etc/csf/ui" ]; then + cp -avf ui /etc/csf/. +fi +if [ -e "/etc/cron.d/csfcron.sh" ]; then + mv -fv /etc/cron.d/csfcron.sh /etc/cron.d/csf-cron +fi +if [ ! -e "/etc/cron.d/csf-cron" ]; then + cp -avf csfcron.sh /etc/cron.d/csf-cron +fi +if [ -e "/etc/cron.d/lfdcron.sh" ]; then + mv -fv /etc/cron.d/lfdcron.sh /etc/cron.d/lfd-cron +fi +if [ ! -e "/etc/cron.d/lfd-cron" ]; then + cp -avf lfdcron.sh /etc/cron.d/lfd-cron +fi +sed -i "s%/etc/init.d/lfd restart%/usr/sbin/csf --lfd restart%" /etc/cron.d/lfd-cron +if [ -e "/usr/local/csf/bin/servercheck.pm" ]; then + rm -f /usr/local/csf/bin/servercheck.pm +fi +if [ -e "/etc/csf/cseui.pl" ]; then + rm -f /etc/csf/cseui.pl +fi +if [ -e "/etc/csf/csfui.pl" ]; then + rm -f /etc/csf/csfui.pl +fi +if [ -e "/etc/csf/csfuir.pl" ]; then + rm -f /etc/csf/csfuir.pl +fi +if [ -e "/usr/local/csf/bin/cseui.pl" ]; then + rm -f /usr/local/csf/bin/cseui.pl +fi +if [ -e "/usr/local/csf/bin/csfui.pl" ]; then + rm -f /usr/local/csf/bin/csfui.pl +fi +if [ -e "/usr/local/csf/bin/csfuir.pl" ]; then + rm -f /usr/local/csf/bin/csfuir.pl +fi +if [ -e "/usr/local/csf/bin/regex.pm" ]; then + rm -f /usr/local/csf/bin/regex.pm +fi + +OLDVERSION=0 +if [ -e "/etc/csf/version.txt" ]; then + OLDVERSION=`head -n 1 /etc/csf/version.txt` +fi + +rm -f /etc/csf/csf.pl /usr/sbin/csf /etc/csf/lfd.pl /usr/sbin/lfd +chmod 700 csf.pl lfd.pl +cp -avf csf.pl /usr/sbin/csf +cp -avf lfd.pl /usr/sbin/lfd +chmod 700 /usr/sbin/csf /usr/sbin/lfd +ln -svf /usr/sbin/csf /etc/csf/csf.pl +ln -svf /usr/sbin/lfd /etc/csf/lfd.pl +ln -svf /usr/local/csf/bin/csftest.pl /etc/csf/ +ln -svf /usr/local/csf/bin/pt_deleted_action.pl /etc/csf/ +ln -svf /usr/local/csf/bin/remove_apf_bfd.sh /etc/csf/ +ln -svf /usr/local/csf/bin/uninstall.sh /etc/csf/ +ln -svf /usr/local/csf/bin/regex.custom.pm /etc/csf/ +ln -svf /usr/local/csf/lib/webmin /etc/csf/ +if [ ! -e "/etc/csf/alerts" ]; then + ln -svf /usr/local/csf/tpl /etc/csf/alerts +fi +chcon -h system_u:object_r:bin_t:s0 /usr/sbin/lfd +chcon -h system_u:object_r:bin_t:s0 /usr/sbin/csf + +mkdir webmin/csf/images +mkdir ui/images +mkdir da/images +mkdir interworx/images + +cp -avf csf/* webmin/csf/images/ +cp -avf csf/* ui/images/ +cp -avf csf/* da/images/ +cp -avf csf/* interworx/images/ + +cp -avf messenger/*.php /etc/csf/messenger/ +cp -avf uninstall.generic.sh /usr/local/csf/bin/uninstall.sh +cp -avf csftest.pl /usr/local/csf/bin/ +cp -avf remove_apf_bfd.sh /usr/local/csf/bin/ +cp -avf readme.txt /etc/csf/ +cp -avf sanity.txt /usr/local/csf/lib/ +cp -avf csf.rbls /usr/local/csf/lib/ +cp -avf restricted.txt /usr/local/csf/lib/ +cp -avf changelog.txt /etc/csf/ +cp -avf downloadservers /etc/csf/ +cp -avf install.txt /etc/csf/ +cp -avf version.txt /etc/csf/ +cp -avf license.txt /etc/csf/ +cp -avf webmin /usr/local/csf/lib/ +cp -avf ConfigServer /usr/local/csf/lib/ +cp -avf Net /usr/local/csf/lib/ +cp -avf Geo /usr/local/csf/lib/ +cp -avf Crypt /usr/local/csf/lib/ +cp -avf HTTP /usr/local/csf/lib/ +cp -avf JSON /usr/local/csf/lib/ +cp -avf version/* /usr/local/csf/lib/ +cp -avf csf.div /usr/local/csf/lib/ +cp -avf csfajaxtail.js /usr/local/csf/lib/ +cp -avf ui/images /etc/csf/ui/. +cp -avf profiles /usr/local/csf/ +cp -avf csf.conf /usr/local/csf/profiles/reset_to_defaults.conf +cp -avf lfd.logrotate /etc/logrotate.d/lfd +chcon --reference /etc/logrotate.d /etc/logrotate.d/lfd + +if [ -e "/usr/local/ispconfig/interface/web/csf/ispconfig_csf" ]; then + rm -Rfv /usr/local/ispconfig/interface/web/csf/ +fi + +rm -fv /etc/csf/csf.spamhaus /etc/csf/csf.dshield /etc/csf/csf.tor /etc/csf/csf.bogon + +mkdir -p /usr/local/man/man1/ +cp -avf csf.1.txt /usr/local/man/man1/csf.1 +cp -avf csf.help /usr/local/csf/lib/ +chmod 755 /usr/local/man/ +chmod 755 /usr/local/man/man1/ +chmod 644 /usr/local/man/man1/csf.1 + +chmod -R 600 /etc/csf +chmod -R 600 /var/lib/csf +chmod -R 600 /usr/local/csf/bin +chmod -R 600 /usr/local/csf/lib +chmod -R 600 /usr/local/csf/tpl +chmod -R 600 /usr/local/csf/profiles +chmod 600 /var/log/lfd.log* + +chmod -v 700 /usr/local/csf/bin/*.pl /usr/local/csf/bin/*.sh /usr/local/csf/bin/*.pm +chmod -v 700 /etc/csf/*.pl /etc/csf/*.cgi /etc/csf/*.sh /etc/csf/*.php /etc/csf/*.py +chmod -v 700 /etc/csf/webmin/csf/index.cgi +chmod -v 644 /etc/cron.d/lfd-cron +chmod -v 644 /etc/cron.d/csf-cron + +cp -avf csget.pl /etc/cron.daily/csget +chmod 700 /etc/cron.daily/csget +/etc/cron.daily/csget --nosleep + +chmod -v 700 auto.generic.pl +./auto.generic.pl $OLDVERSION + +if test `cat /proc/1/comm` = "systemd" +then + if [ -e /etc/init.d/lfd ]; then + if [ -f /etc/redhat-release ]; then + /sbin/chkconfig csf off + /sbin/chkconfig lfd off + /sbin/chkconfig csf --del + /sbin/chkconfig lfd --del + elif [ -f /etc/debian_version ] || [ -f /etc/lsb-release ]; then + update-rc.d -f lfd remove + update-rc.d -f csf remove + elif [ -f /etc/gentoo-release ]; then + rc-update del lfd default + rc-update del csf default + elif [ -f /etc/slackware-version ]; then + rm -vf /etc/rc.d/rc3.d/S80csf + rm -vf /etc/rc.d/rc4.d/S80csf + rm -vf /etc/rc.d/rc5.d/S80csf + rm -vf /etc/rc.d/rc3.d/S85lfd + rm -vf /etc/rc.d/rc4.d/S85lfd + rm -vf /etc/rc.d/rc5.d/S85lfd + else + /sbin/chkconfig csf off + /sbin/chkconfig lfd off + /sbin/chkconfig csf --del + /sbin/chkconfig lfd --del + fi + rm -fv /etc/init.d/csf + rm -fv /etc/init.d/lfd + fi + + mkdir -p /etc/systemd/system/ + mkdir -p /usr/lib/systemd/system/ + cp -avf lfd.service /usr/lib/systemd/system/ + cp -avf csf.service /usr/lib/systemd/system/ + + chcon -h system_u:object_r:systemd_unit_file_t:s0 /usr/lib/systemd/system/lfd.service + chcon -h system_u:object_r:systemd_unit_file_t:s0 /usr/lib/systemd/system/csf.service + + systemctl daemon-reload + + systemctl enable csf.service + systemctl enable lfd.service + + systemctl disable firewalld + systemctl stop firewalld + systemctl mask firewalld +else + cp -avf lfd.sh /etc/init.d/lfd + cp -avf csf.sh /etc/init.d/csf + chmod -v 755 /etc/init.d/lfd + chmod -v 755 /etc/init.d/csf + + if [ -f /etc/redhat-release ]; then + /sbin/chkconfig lfd on + /sbin/chkconfig csf on + elif [ -f /etc/debian_version ] || [ -f /etc/lsb-release ]; then + update-rc.d -f lfd remove + update-rc.d -f csf remove + update-rc.d lfd defaults 80 20 + update-rc.d csf defaults 20 80 + elif [ -f /etc/gentoo-release ]; then + rc-update add lfd default + rc-update add csf default + elif [ -f /etc/slackware-version ]; then + ln -svf /etc/init.d/csf /etc/rc.d/rc3.d/S80csf + ln -svf /etc/init.d/csf /etc/rc.d/rc4.d/S80csf + ln -svf /etc/init.d/csf /etc/rc.d/rc5.d/S80csf + ln -svf /etc/init.d/lfd /etc/rc.d/rc3.d/S85lfd + ln -svf /etc/init.d/lfd /etc/rc.d/rc4.d/S85lfd + ln -svf /etc/init.d/lfd /etc/rc.d/rc5.d/S85lfd + else + /sbin/chkconfig lfd on + /sbin/chkconfig csf on + fi +fi + +chown -Rf root:root /etc/csf /var/lib/csf /usr/local/csf +chown -f root:root /usr/sbin/csf /usr/sbin/lfd /etc/logrotate.d/lfd /etc/cron.d/csf-cron /etc/cron.d/lfd-cron /usr/local/man/man1/csf.1 /usr/lib/systemd/system/lfd.service /usr/lib/systemd/system/csf.service /etc/init.d/lfd /etc/init.d/csf + +cd webmin ; tar -czf /usr/local/csf/csfwebmin.tgz ./* +ln -svf /usr/local/csf/csfwebmin.tgz /etc/csf/ + +echo +echo "Installation Completed" +echo diff --git a/src/redux/install.interworx.sh b/src/redux/install.interworx.sh new file mode 100644 index 000000000..9ca71c55b --- /dev/null +++ b/src/redux/install.interworx.sh @@ -0,0 +1,540 @@ +#!/bin/sh +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### + +umask 0177 + +if [ -e "/usr/local/cpanel/version" ]; then + echo "Running csf cPanel installer" + echo + sh install.cpanel.sh + exit 0 +elif [ -e "/usr/local/directadmin/directadmin" ]; then + echo "Running csf DirectAdmin installer" + echo + sh install.directadmin.sh + exit 0 +fi + +echo "Installing csf and lfd" +echo + +echo "Check we're running as root" +if [ ! `id -u` = 0 ]; then + echo + echo "FAILED: You have to be logged in as root (UID:0) to install csf" + exit +fi +echo + +mkdir -v -m 0600 /etc/csf +cp -avf install.txt /etc/csf/ + +echo "Checking Perl modules..." +chmod 700 os.pl +RETURN=`./os.pl` +if [ "$RETURN" = 1 ]; then + echo + echo "FAILED: You MUST install the missing perl modules above before you can install csf. See /etc/csf/install.txt for installation details." + echo + exit +else + echo "...Perl modules OK" + echo +fi + +mkdir -v -m 0600 /etc/csf +mkdir -v -m 0600 /var/lib/csf +mkdir -v -m 0600 /var/lib/csf/backup +mkdir -v -m 0600 /var/lib/csf/Geo +mkdir -v -m 0600 /var/lib/csf/ui +mkdir -v -m 0600 /var/lib/csf/stats +mkdir -v -m 0600 /var/lib/csf/lock +mkdir -v -m 0600 /var/lib/csf/webmin +mkdir -v -m 0600 /var/lib/csf/zone +mkdir -v -m 0600 /usr/local/csf +mkdir -v -m 0600 /usr/local/csf/bin +mkdir -v -m 0600 /usr/local/csf/lib +mkdir -v -m 0600 /usr/local/csf/tpl + +if [ -e "/etc/csf/alert.txt" ]; then + sh migratedata.sh +fi + +if [ ! -e "/etc/csf/csf.conf" ]; then + cp -avf csf.interworx.conf /etc/csf/csf.conf +fi + +if [ ! -d /var/lib/csf ]; then + mkdir -v -p -m 0600 /var/lib/csf +fi +if [ ! -d /usr/local/csf/lib ]; then + mkdir -v -p -m 0600 /usr/local/csf/lib +fi +if [ ! -d /usr/local/csf/bin ]; then + mkdir -v -p -m 0600 /usr/local/csf/bin +fi +if [ ! -d /usr/local/csf/tpl ]; then + mkdir -v -p -m 0600 /usr/local/csf/tpl +fi + +if [ ! -e "/etc/csf/csf.allow" ]; then + cp -avf csf.interworx.allow /etc/csf/csf.allow +fi +if [ ! -e "/etc/csf/csf.deny" ]; then + cp -avf csf.deny /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.redirect" ]; then + cp -avf csf.redirect /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.resellers" ]; then + cp -avf csf.resellers /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.dirwatch" ]; then + cp -avf csf.dirwatch /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.syslogs" ]; then + cp -avf csf.syslogs /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.logfiles" ]; then + cp -avf csf.logfiles /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.logignore" ]; then + cp -avf csf.logignore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.blocklists" ]; then + cp -avf csf.blocklists /etc/csf/. +else + cp -avf csf.blocklists /etc/csf/csf.blocklists.new +fi +if [ ! -e "/etc/csf/csf.ignore" ]; then + cp -avf csf.interworx.ignore /etc/csf/csf.ignore +fi +if [ ! -e "/etc/csf/csf.pignore" ]; then + cp -avf csf.interworx.pignore /etc/csf/csf.pignore +fi +if [ ! -e "/etc/csf/csf.rignore" ]; then + cp -avf csf.rignore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.fignore" ]; then + cp -avf csf.fignore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.signore" ]; then + cp -avf csf.signore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.suignore" ]; then + cp -avf csf.suignore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.uidignore" ]; then + cp -avf csf.uidignore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.mignore" ]; then + cp -avf csf.mignore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.sips" ]; then + cp -avf csf.sips /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.dyndns" ]; then + cp -avf csf.dyndns /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.syslogusers" ]; then + cp -avf csf.syslogusers /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.smtpauth" ]; then + cp -avf csf.smtpauth /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.rblconf" ]; then + cp -avf csf.rblconf /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.cloudflare" ]; then + cp -avf csf.cloudflare /etc/csf/. +fi + +if [ ! -e "/usr/local/csf/tpl/alert.txt" ]; then + cp -avf alert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/reselleralert.txt" ]; then + cp -avf reselleralert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/logalert.txt" ]; then + cp -avf logalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/logfloodalert.txt" ]; then + cp -avf logfloodalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/syslogalert.txt" ]; then + cp -avf syslogalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/integrityalert.txt" ]; then + cp -avf integrityalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/exploitalert.txt" ]; then + cp -avf exploitalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/queuealert.txt" ]; then + cp -avf queuealert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/modsecipdbalert.txt" ]; then + cp -avf modsecipdbalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/tracking.txt" ]; then + cp -avf tracking.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/connectiontracking.txt" ]; then + cp -avf connectiontracking.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/processtracking.txt" ]; then + cp -avf processtracking.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/accounttracking.txt" ]; then + cp -avf accounttracking.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/usertracking.txt" ]; then + cp -avf usertracking.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/sshalert.txt" ]; then + cp -avf sshalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/webminalert.txt" ]; then + cp -avf webminalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/sualert.txt" ]; then + cp -avf sualert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/sudoalert.txt" ]; then + cp -avf sudoalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/consolealert.txt" ]; then + cp -avf consolealert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/uialert.txt" ]; then + cp -avf uialert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/cpanelalert.txt" ]; then + cp -avf cpanelalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/scriptalert.txt" ]; then + cp -avf scriptalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/relayalert.txt" ]; then + cp -avf relayalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/filealert.txt" ]; then + cp -avf filealert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/watchalert.txt" ]; then + cp -avf watchalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/loadalert.txt" ]; then + cp -avf loadalert.txt /usr/local/csf/tpl/. +else + cp -avf loadalert.txt /usr/local/csf/tpl/loadalert.txt.new +fi +if [ ! -e "/usr/local/csf/tpl/resalert.txt" ]; then + cp -avf resalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/portscan.txt" ]; then + cp -avf portscan.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/uidscan.txt" ]; then + cp -avf uidscan.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/permblock.txt" ]; then + cp -avf permblock.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/netblock.txt" ]; then + cp -avf netblock.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/portknocking.txt" ]; then + cp -avf portknocking.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/forkbombalert.txt" ]; then + cp -avf forkbombalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/recaptcha.txt" ]; then + cp -avf recaptcha.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/apache.main.txt" ]; then + cp -avf apache.main.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/apache.http.txt" ]; then + cp -avf apache.http.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/apache.https.txt" ]; then + cp -avf apache.https.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/litespeed.main.txt" ]; then + cp -avf litespeed.main.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/litespeed.http.txt" ]; then + cp -avf litespeed.http.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/litespeed.https.txt" ]; then + cp -avf litespeed.https.txt /usr/local/csf/tpl/. +fi +cp -avf x-arf.txt /usr/local/csf/tpl/. + +if [ ! -e "/usr/local/csf/bin/regex.custom.pm" ]; then + cp -avf regex.custom.pm /usr/local/csf/bin/. +fi +if [ ! -e "/usr/local/csf/bin/pt_deleted_action.pl" ]; then + cp -avf pt_deleted_action.pl /usr/local/csf/bin/. +fi +if [ ! -e "/etc/csf/messenger" ]; then + cp -avf messenger /etc/csf/. +fi +if [ ! -e "/etc/csf/messenger/index.recaptcha.html" ]; then + cp -avf messenger/index.recaptcha.html /etc/csf/messenger/. +fi +if [ ! -e "/etc/csf/ui" ]; then + cp -avf ui /etc/csf/. +fi +if [ -e "/etc/cron.d/csfcron.sh" ]; then + mv -fv /etc/cron.d/csfcron.sh /etc/cron.d/csf-cron +fi +if [ ! -e "/etc/cron.d/csf-cron" ]; then + cp -avf csfcron.sh /etc/cron.d/csf-cron +fi +if [ -e "/etc/cron.d/lfdcron.sh" ]; then + mv -fv /etc/cron.d/lfdcron.sh /etc/cron.d/lfd-cron +fi +if [ ! -e "/etc/cron.d/lfd-cron" ]; then + cp -avf lfdcron.sh /etc/cron.d/lfd-cron +fi +sed -i "s%/etc/init.d/lfd restart%/usr/sbin/csf --lfd restart%" /etc/cron.d/lfd-cron +if [ -e "/usr/local/csf/bin/servercheck.pm" ]; then + rm -f /usr/local/csf/bin/servercheck.pm +fi +if [ -e "/etc/csf/cseui.pl" ]; then + rm -f /etc/csf/cseui.pl +fi +if [ -e "/etc/csf/csfui.pl" ]; then + rm -f /etc/csf/csfui.pl +fi +if [ -e "/etc/csf/csfuir.pl" ]; then + rm -f /etc/csf/csfuir.pl +fi +if [ -e "/usr/local/csf/bin/cseui.pl" ]; then + rm -f /usr/local/csf/bin/cseui.pl +fi +if [ -e "/usr/local/csf/bin/csfui.pl" ]; then + rm -f /usr/local/csf/bin/csfui.pl +fi +if [ -e "/usr/local/csf/bin/csfuir.pl" ]; then + rm -f /usr/local/csf/bin/csfuir.pl +fi +if [ -e "/usr/local/csf/bin/regex.pm" ]; then + rm -f /usr/local/csf/bin/regex.pm +fi + +OLDVERSION=0 +if [ -e "/etc/csf/version.txt" ]; then + OLDVERSION=`head -n 1 /etc/csf/version.txt` +fi + +rm -f /etc/csf/csf.pl /usr/sbin/csf /etc/csf/lfd.pl /usr/sbin/lfd +chmod 700 csf.pl lfd.pl +cp -avf csf.pl /usr/sbin/csf +cp -avf lfd.pl /usr/sbin/lfd +chmod 700 /usr/sbin/csf /usr/sbin/lfd +ln -svf /usr/sbin/csf /etc/csf/csf.pl +ln -svf /usr/sbin/lfd /etc/csf/lfd.pl +ln -svf /usr/local/csf/bin/csftest.pl /etc/csf/ +ln -svf /usr/local/csf/bin/pt_deleted_action.pl /etc/csf/ +ln -svf /usr/local/csf/bin/remove_apf_bfd.sh /etc/csf/ +ln -svf /usr/local/csf/bin/uninstall.sh /etc/csf/ +ln -svf /usr/local/csf/bin/regex.custom.pm /etc/csf/ +ln -svf /usr/local/csf/lib/webmin /etc/csf/ +if [ ! -e "/etc/csf/alerts" ]; then + ln -svf /usr/local/csf/tpl /etc/csf/alerts +fi +chcon -h system_u:object_r:bin_t:s0 /usr/sbin/lfd +chcon -h system_u:object_r:bin_t:s0 /usr/sbin/csf + +mkdir webmin/csf/images +mkdir ui/images +mkdir da/images +mkdir interworx/images + +cp -avf csf/* webmin/csf/images/ +cp -avf csf/* ui/images/ +cp -avf csf/* da/images/ +cp -avf csf/* interworx/images/ + +cp -avf messenger/*.php /etc/csf/messenger/ +cp -avf uninstall.interworx.sh /usr/local/csf/bin/uninstall.sh +cp -avf csftest.pl /usr/local/csf/bin/ +cp -avf remove_apf_bfd.sh /usr/local/csf/bin/ +cp -avf readme.txt /etc/csf/ +cp -avf sanity.txt /usr/local/csf/lib/ +cp -avf csf.rbls /usr/local/csf/lib/ +cp -avf restricted.txt /usr/local/csf/lib/ +cp -avf changelog.txt /etc/csf/ +cp -avf downloadservers /etc/csf/ +cp -avf install.txt /etc/csf/ +cp -avf version.txt /etc/csf/ +cp -avf license.txt /etc/csf/ +cp -avf webmin /usr/local/csf/lib/ +cp -avf ConfigServer /usr/local/csf/lib/ +cp -avf Net /usr/local/csf/lib/ +cp -avf Geo /usr/local/csf/lib/ +cp -avf Crypt /usr/local/csf/lib/ +cp -avf HTTP /usr/local/csf/lib/ +cp -avf JSON /usr/local/csf/lib/ +cp -avf version/* /usr/local/csf/lib/ +cp -avf csf.div /usr/local/csf/lib/ +cp -avf csfajaxtail.js /usr/local/csf/lib/ +cp -avf ui/images /etc/csf/ui/. +cp -avf profiles /usr/local/csf/ +cp -avf csf.conf /usr/local/csf/profiles/reset_to_defaults.conf +cp -avf lfd.logrotate /etc/logrotate.d/lfd +chcon --reference /etc/logrotate.d /etc/logrotate.d/lfd +cp -avf apf_stub.pl /etc/csf/ + +if [ -e "/usr/local/ispconfig/interface/web/csf/ispconfig_csf" ]; then + rm -Rfv /usr/local/ispconfig/interface/web/csf/ +fi + +rm -fv /etc/csf/csf.spamhaus /etc/csf/csf.dshield /etc/csf/csf.tor /etc/csf/csf.bogon + +mkdir -p /usr/local/man/man1/ +cp -avf csf.1.txt /usr/local/man/man1/csf.1 +cp -avf csf.help /usr/local/csf/lib/ +chmod 755 /usr/local/man/ +chmod 755 /usr/local/man/man1/ +chmod 644 /usr/local/man/man1/csf.1 + +chmod -R 600 /etc/csf +chmod -R 600 /var/lib/csf +chmod -R 600 /usr/local/csf/bin +chmod -R 600 /usr/local/csf/lib +chmod -R 600 /usr/local/csf/tpl +chmod -R 600 /usr/local/csf/profiles +chmod 600 /var/log/lfd.log* + +chmod -v 700 /usr/local/csf/bin/*.pl /usr/local/csf/bin/*.sh /usr/local/csf/bin/*.pm +chmod -v 700 /etc/csf/*.pl /etc/csf/*.cgi /etc/csf/*.sh /etc/csf/*.php /etc/csf/*.py +chmod -v 700 /etc/csf/webmin/csf/index.cgi +chmod -v 644 /etc/cron.d/lfd-cron +chmod -v 644 /etc/cron.d/csf-cron + +cp -avf csget.pl /etc/cron.daily/csget +chmod 700 /etc/cron.daily/csget +/etc/cron.daily/csget --nosleep + +chmod -v 700 auto.interworx.pl +./auto.interworx.pl $OLDVERSION + +if test `cat /proc/1/comm` = "systemd" +then + if [ -e /etc/init.d/lfd ]; then + if [ -f /etc/redhat-release ]; then + /sbin/chkconfig csf off + /sbin/chkconfig lfd off + /sbin/chkconfig csf --del + /sbin/chkconfig lfd --del + elif [ -f /etc/debian_version ] || [ -f /etc/lsb-release ]; then + update-rc.d -f lfd remove + update-rc.d -f csf remove + elif [ -f /etc/gentoo-release ]; then + rc-update del lfd default + rc-update del csf default + elif [ -f /etc/slackware-version ]; then + rm -vf /etc/rc.d/rc3.d/S80csf + rm -vf /etc/rc.d/rc4.d/S80csf + rm -vf /etc/rc.d/rc5.d/S80csf + rm -vf /etc/rc.d/rc3.d/S85lfd + rm -vf /etc/rc.d/rc4.d/S85lfd + rm -vf /etc/rc.d/rc5.d/S85lfd + else + /sbin/chkconfig csf off + /sbin/chkconfig lfd off + /sbin/chkconfig csf --del + /sbin/chkconfig lfd --del + fi + rm -fv /etc/init.d/csf + rm -fv /etc/init.d/lfd + fi + + mkdir -p /etc/systemd/system/ + mkdir -p /usr/lib/systemd/system/ + cp -avf lfd.service /usr/lib/systemd/system/ + cp -avf csf.service /usr/lib/systemd/system/ + + chcon -h system_u:object_r:systemd_unit_file_t:s0 /usr/lib/systemd/system/lfd.service + chcon -h system_u:object_r:systemd_unit_file_t:s0 /usr/lib/systemd/system/csf.service + + systemctl daemon-reload + + systemctl enable csf.service + systemctl enable lfd.service + + systemctl disable firewalld + systemctl stop firewalld + systemctl mask firewalld +else + cp -avf lfd.sh /etc/init.d/lfd + cp -avf csf.sh /etc/init.d/csf + chmod -v 755 /etc/init.d/lfd + chmod -v 755 /etc/init.d/csf + + if [ -f /etc/redhat-release ]; then + /sbin/chkconfig lfd on + /sbin/chkconfig csf on + elif [ -f /etc/debian_version ] || [ -f /etc/lsb-release ]; then + update-rc.d -f lfd remove + update-rc.d -f csf remove + update-rc.d lfd defaults 80 20 + update-rc.d csf defaults 20 80 + elif [ -f /etc/gentoo-release ]; then + rc-update add lfd default + rc-update add csf default + elif [ -f /etc/slackware-version ]; then + ln -svf /etc/init.d/csf /etc/rc.d/rc3.d/S80csf + ln -svf /etc/init.d/csf /etc/rc.d/rc4.d/S80csf + ln -svf /etc/init.d/csf /etc/rc.d/rc5.d/S80csf + ln -svf /etc/init.d/lfd /etc/rc.d/rc3.d/S85lfd + ln -svf /etc/init.d/lfd /etc/rc.d/rc4.d/S85lfd + ln -svf /etc/init.d/lfd /etc/rc.d/rc5.d/S85lfd + else + /sbin/chkconfig lfd on + /sbin/chkconfig csf on + fi +fi + +chown -Rf root:root /etc/csf /var/lib/csf /usr/local/csf +chown -f root:root /usr/sbin/csf /usr/sbin/lfd /etc/logrotate.d/lfd /etc/cron.d/csf-cron /etc/cron.d/lfd-cron /usr/local/man/man1/csf.1 /usr/lib/systemd/system/lfd.service /usr/lib/systemd/system/csf.service /etc/init.d/lfd /etc/init.d/csf + +mkdir -v -m 0600 /usr/local/interworx/plugins/configservercsf /usr/local/interworx/html/configserver +chmod -v 0711 /usr/local/interworx/html/configserver +cp -avf interworx/* /usr/local/interworx/plugins/configservercsf +cp -avf csf /usr/local/interworx/html/configserver/ +chown -R iworx:iworx /usr/local/interworx/plugins/configservercsf /usr/local/interworx/html/configserver +find /usr/local/interworx/plugins/configservercsf -type d -exec chmod -v 700 {} \; +find /usr/local/interworx/plugins/configservercsf -type f -exec chmod -v 600 {} \; +/usr/local/interworx/bin/nodeworx.pex -u --controller Plugins --action edit --plugin_name configservercsf --status 1 -n + +if [ -e "/usr/local/interworx/include/Ctrl/Nodeworx/Firewall.php.orig" ]; then + mv /usr/local/interworx/include/Ctrl/Nodeworx/Firewall.php.orig /usr/local/interworx/include/Ctrl/Nodeworx/Firewall.php + chown iworx:iworx /usr/local/interworx/include/Ctrl/Nodeworx/Firewall.php + chmod 600 /usr/local/interworx/include/Ctrl/Nodeworx/Firewall.php +fi + +chattr -ia /etc/apf/apf +if [ -e "/etc/apf/apf.old" ]; then + cp -avf apf_stub.pl /etc/apf/apf +else + mv /etc/apf/apf /etc/apf/apf.old + cp -avf apf_stub.pl /etc/apf/apf +fi +chmod 750 /etc/apf/apf + +cd webmin ; tar -czf /usr/local/csf/csfwebmin.tgz ./* +ln -svf /usr/local/csf/csfwebmin.tgz /etc/csf/ + +echo +echo "Installation Completed" +echo diff --git a/src/redux/install.sh b/src/redux/install.sh new file mode 100644 index 000000000..0aceb0f3f --- /dev/null +++ b/src/redux/install.sh @@ -0,0 +1,40 @@ +#!/bin/sh +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### + +echo +echo "Selecting installer..." +echo + +if [ -e "/usr/local/cpanel/version" ]; then + echo "Running csf cPanel installer" + echo + sh install.cpanel.sh +elif [ -e "/usr/local/directadmin/directadmin" ]; then + echo "Running csf DirectAdmin installer" + echo + sh install.directadmin.sh +elif [ -e "/usr/local/interworx" ]; then + echo "Running csf InterWorx installer" + echo + sh install.interworx.sh +elif [ -e "/usr/local/cwpsrv" ]; then + echo "Running csf CentOS Web Panel installer" + echo + sh install.cwp.sh +elif [ -e "/usr/local/vesta" ]; then + echo "Running csf VestaCP installer" + echo + sh install.vesta.sh +elif [ -e "/usr/local/CyberCP" ]; then + echo "Running csf CyberPanel installer" + echo + sh install.cyberpanel.sh +else + echo "Running csf generic installer" + echo + sh install.generic.sh +fi diff --git a/src/redux/install.txt b/src/redux/install.txt new file mode 100644 index 000000000..cb02b243c --- /dev/null +++ b/src/redux/install.txt @@ -0,0 +1,93 @@ +############################################################################### +# Copyright 2006-2023, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### + + +Installation +============ +Installation is quite straightforward: + +cd /usr/src +rm -fv csf.tgz +wget https://download.configserver.com/csf.tgz +tar -xzf csf.tgz +cd csf +sh install.sh + +Next, test whether you have the required iptables modules: + +perl /usr/local/csf/bin/csftest.pl + +Don't worry if you cannot run all the features, so long as the script doesn't +report any FATAL errors + +You should not run any other iptables firewall configuration script. For +example, if you previously used APF+BFD you can remove the combination (which +you will need to do if you have them installed otherwise they will conflict): + +sh /usr/local/csf/bin/remove_apf_bfd.sh + +That's it. You can then configure csf and lfd by reading the documentation and +configuration files in /etc/csf/csf.conf and /etc/csf/readme.txt directly or +through the csf User Interface. + +csf installation for cPanel and DirectAdmin is preconfigured to work on those +servers with all the standard ports open. + +csf auto-configures your SSH port on installation where it's running on a non- +standard port. + +csf auto-whitelists your connected IP address where possible on installation. + +You should ensure that kernel logging daemon (klogd) is enabled. Typically, VPS +servers running RedHat/CentOS v5 have this disabled and you should check +/etc/init.d/syslog and make sure that any klogd lines are not commented out. If +you change the file, remember to restart syslog. + +See the csf.conf and readme.txt files for more information. + +Perl Modules +============ + +While most should be installed on a standard perl installation the following +may need to be installed manually: + +# On rpm based systems: +yum install perl-libwww-perl.noarch perl-LWP-Protocol-https.noarch perl-GDGraph perl-Math-BigInt.noarch + +# On APT based systems: +apt-get install libwww-perl liblwp-protocol-https-perl libgd-graph-perl + +# Via cpan: +perl -MCPAN -eshell +cpan> install LWP LWP::Protocol::https GD::Graph + + + +InterWorx +========= + +1. Enable csf in InterWorx > NodeWorx > Plugins > csf + +2. See the InterWorx section in /etc/csf/readme.txt + + +Webmin Module Installation/Upgrade +================================== + +To install or upgrade the csf webmin module: + +Install csf as above +Install the csf webmin module in: + Webmin > Webmin Configuration > Webmin Modules > + From local file > /usr/local/csf/csfwebmin.tgz > Install Module + + +Uninstallation +============== +Removing csf and lfd is even more simple: + +cd /etc/csf +sh uninstall.sh diff --git a/src/redux/install.vesta.sh b/src/redux/install.vesta.sh new file mode 100644 index 000000000..98e55837f --- /dev/null +++ b/src/redux/install.vesta.sh @@ -0,0 +1,523 @@ +#!/bin/sh +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### + +umask 0177 + +if [ -e "/usr/local/cpanel/version" ]; then + echo "Running csf cPanel installer" + echo + sh install.cpanel.sh + exit 0 +elif [ -e "/usr/local/directadmin/directadmin" ]; then + echo "Running csf DirectAdmin installer" + echo + sh install.directadmin.sh + exit 0 +fi + +echo "Installing csf and lfd" +echo + +echo "Check we're running as root" +if [ ! `id -u` = 0 ]; then + echo + echo "FAILED: You have to be logged in as root (UID:0) to install csf" + exit +fi +echo + +mkdir -v -m 0600 /etc/csf +cp -avf install.txt /etc/csf/ + +echo "Checking Perl modules..." +chmod 700 os.pl +RETURN=`./os.pl` +if [ "$RETURN" = 1 ]; then + echo + echo "FAILED: You MUST install the missing perl modules above before you can install csf. See /etc/csf/install.txt for installation details." + echo + exit +else + echo "...Perl modules OK" + echo +fi + +mkdir -v -m 0600 /etc/csf +mkdir -v -m 0600 /var/lib/csf +mkdir -v -m 0600 /var/lib/csf/backup +mkdir -v -m 0600 /var/lib/csf/Geo +mkdir -v -m 0600 /var/lib/csf/ui +mkdir -v -m 0600 /var/lib/csf/stats +mkdir -v -m 0600 /var/lib/csf/lock +mkdir -v -m 0600 /var/lib/csf/webmin +mkdir -v -m 0600 /var/lib/csf/zone +mkdir -v -m 0600 /usr/local/csf +mkdir -v -m 0600 /usr/local/csf/bin +mkdir -v -m 0600 /usr/local/csf/lib +mkdir -v -m 0600 /usr/local/csf/tpl + +if [ -e "/etc/csf/alert.txt" ]; then + sh migratedata.sh +fi + +if [ ! -e "/etc/csf/csf.conf" ]; then + cp -avf csf.vesta.conf /etc/csf/csf.conf +fi + +if [ ! -d /var/lib/csf ]; then + mkdir -v -p -m 0600 /var/lib/csf +fi +if [ ! -d /usr/local/csf/lib ]; then + mkdir -v -p -m 0600 /usr/local/csf/lib +fi +if [ ! -d /usr/local/csf/bin ]; then + mkdir -v -p -m 0600 /usr/local/csf/bin +fi +if [ ! -d /usr/local/csf/tpl ]; then + mkdir -v -p -m 0600 /usr/local/csf/tpl +fi + +if [ ! -e "/etc/csf/csf.allow" ]; then + cp -avf csf.vesta.allow /etc/csf/csf.allow +fi +if [ ! -e "/etc/csf/csf.deny" ]; then + cp -avf csf.deny /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.redirect" ]; then + cp -avf csf.redirect /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.resellers" ]; then + cp -avf csf.resellers /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.dirwatch" ]; then + cp -avf csf.dirwatch /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.syslogs" ]; then + cp -avf csf.syslogs /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.logfiles" ]; then + cp -avf csf.logfiles /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.logignore" ]; then + cp -avf csf.logignore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.blocklists" ]; then + cp -avf csf.blocklists /etc/csf/. +else + cp -avf csf.blocklists /etc/csf/csf.blocklists.new +fi +if [ ! -e "/etc/csf/csf.ignore" ]; then + cp -avf csf.vesta.ignore /etc/csf/csf.ignore +fi +if [ ! -e "/etc/csf/csf.pignore" ]; then + cp -avf csf.vesta.pignore /etc/csf/csf.pignore +fi +if [ ! -e "/etc/csf/csf.rignore" ]; then + cp -avf csf.rignore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.fignore" ]; then + cp -avf csf.fignore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.signore" ]; then + cp -avf csf.signore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.suignore" ]; then + cp -avf csf.suignore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.uidignore" ]; then + cp -avf csf.uidignore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.mignore" ]; then + cp -avf csf.mignore /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.sips" ]; then + cp -avf csf.sips /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.dyndns" ]; then + cp -avf csf.dyndns /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.syslogusers" ]; then + cp -avf csf.syslogusers /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.smtpauth" ]; then + cp -avf csf.smtpauth /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.rblconf" ]; then + cp -avf csf.rblconf /etc/csf/. +fi +if [ ! -e "/etc/csf/csf.cloudflare" ]; then + cp -avf csf.cloudflare /etc/csf/. +fi + +if [ ! -e "/usr/local/csf/tpl/alert.txt" ]; then + cp -avf alert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/reselleralert.txt" ]; then + cp -avf reselleralert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/logalert.txt" ]; then + cp -avf logalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/logfloodalert.txt" ]; then + cp -avf logfloodalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/syslogalert.txt" ]; then + cp -avf syslogalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/integrityalert.txt" ]; then + cp -avf integrityalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/exploitalert.txt" ]; then + cp -avf exploitalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/queuealert.txt" ]; then + cp -avf queuealert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/modsecipdbalert.txt" ]; then + cp -avf modsecipdbalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/tracking.txt" ]; then + cp -avf tracking.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/connectiontracking.txt" ]; then + cp -avf connectiontracking.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/processtracking.txt" ]; then + cp -avf processtracking.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/accounttracking.txt" ]; then + cp -avf accounttracking.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/usertracking.txt" ]; then + cp -avf usertracking.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/sshalert.txt" ]; then + cp -avf sshalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/webminalert.txt" ]; then + cp -avf webminalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/sualert.txt" ]; then + cp -avf sualert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/sudoalert.txt" ]; then + cp -avf sudoalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/consolealert.txt" ]; then + cp -avf consolealert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/uialert.txt" ]; then + cp -avf uialert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/cpanelalert.txt" ]; then + cp -avf cpanelalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/scriptalert.txt" ]; then + cp -avf scriptalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/relayalert.txt" ]; then + cp -avf relayalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/filealert.txt" ]; then + cp -avf filealert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/watchalert.txt" ]; then + cp -avf watchalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/loadalert.txt" ]; then + cp -avf loadalert.txt /usr/local/csf/tpl/. +else + cp -avf loadalert.txt /usr/local/csf/tpl/loadalert.txt.new +fi +if [ ! -e "/usr/local/csf/tpl/resalert.txt" ]; then + cp -avf resalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/portscan.txt" ]; then + cp -avf portscan.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/uidscan.txt" ]; then + cp -avf uidscan.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/permblock.txt" ]; then + cp -avf permblock.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/netblock.txt" ]; then + cp -avf netblock.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/portknocking.txt" ]; then + cp -avf portknocking.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/forkbombalert.txt" ]; then + cp -avf forkbombalert.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/recaptcha.txt" ]; then + cp -avf recaptcha.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/apache.main.txt" ]; then + cp -avf apache.main.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/apache.http.txt" ]; then + cp -avf apache.http.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/apache.https.txt" ]; then + cp -avf apache.https.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/litespeed.main.txt" ]; then + cp -avf litespeed.main.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/litespeed.http.txt" ]; then + cp -avf litespeed.http.txt /usr/local/csf/tpl/. +fi +if [ ! -e "/usr/local/csf/tpl/litespeed.https.txt" ]; then + cp -avf litespeed.https.txt /usr/local/csf/tpl/. +fi +cp -avf x-arf.txt /usr/local/csf/tpl/. + +if [ ! -e "/usr/local/csf/bin/regex.custom.pm" ]; then + cp -avf regex.custom.pm /usr/local/csf/bin/. +fi +if [ ! -e "/usr/local/csf/bin/pt_deleted_action.pl" ]; then + cp -avf pt_deleted_action.pl /usr/local/csf/bin/. +fi +if [ ! -e "/etc/csf/messenger" ]; then + cp -avf messenger /etc/csf/. +fi +if [ ! -e "/etc/csf/messenger/index.recaptcha.html" ]; then + cp -avf messenger/index.recaptcha.html /etc/csf/messenger/. +fi +if [ ! -e "/etc/csf/ui" ]; then + cp -avf ui /etc/csf/. +fi +if [ -e "/etc/cron.d/csfcron.sh" ]; then + mv -fv /etc/cron.d/csfcron.sh /etc/cron.d/csf-cron +fi +if [ ! -e "/etc/cron.d/csf-cron" ]; then + cp -avf csfcron.sh /etc/cron.d/csf-cron +fi +if [ -e "/etc/cron.d/lfdcron.sh" ]; then + mv -fv /etc/cron.d/lfdcron.sh /etc/cron.d/lfd-cron +fi +if [ ! -e "/etc/cron.d/lfd-cron" ]; then + cp -avf lfdcron.sh /etc/cron.d/lfd-cron +fi +sed -i "s%/etc/init.d/lfd restart%/usr/sbin/csf --lfd restart%" /etc/cron.d/lfd-cron +if [ -e "/usr/local/csf/bin/servercheck.pm" ]; then + rm -f /usr/local/csf/bin/servercheck.pm +fi +if [ -e "/etc/csf/cseui.pl" ]; then + rm -f /etc/csf/cseui.pl +fi +if [ -e "/etc/csf/csfui.pl" ]; then + rm -f /etc/csf/csfui.pl +fi +if [ -e "/etc/csf/csfuir.pl" ]; then + rm -f /etc/csf/csfuir.pl +fi +if [ -e "/usr/local/csf/bin/cseui.pl" ]; then + rm -f /usr/local/csf/bin/cseui.pl +fi +if [ -e "/usr/local/csf/bin/csfui.pl" ]; then + rm -f /usr/local/csf/bin/csfui.pl +fi +if [ -e "/usr/local/csf/bin/csfuir.pl" ]; then + rm -f /usr/local/csf/bin/csfuir.pl +fi +if [ -e "/usr/local/csf/bin/regex.pm" ]; then + rm -f /usr/local/csf/bin/regex.pm +fi + +OLDVERSION=0 +if [ -e "/etc/csf/version.txt" ]; then + OLDVERSION=`head -n 1 /etc/csf/version.txt` +fi + +rm -f /etc/csf/csf.pl /usr/sbin/csf /etc/csf/lfd.pl /usr/sbin/lfd +chmod 700 csf.pl lfd.pl +cp -avf csf.pl /usr/sbin/csf +cp -avf lfd.pl /usr/sbin/lfd +chmod 700 /usr/sbin/csf /usr/sbin/lfd +ln -svf /usr/sbin/csf /etc/csf/csf.pl +ln -svf /usr/sbin/lfd /etc/csf/lfd.pl +ln -svf /usr/local/csf/bin/csftest.pl /etc/csf/ +ln -svf /usr/local/csf/bin/pt_deleted_action.pl /etc/csf/ +ln -svf /usr/local/csf/bin/remove_apf_bfd.sh /etc/csf/ +ln -svf /usr/local/csf/bin/uninstall.sh /etc/csf/ +ln -svf /usr/local/csf/bin/regex.custom.pm /etc/csf/ +ln -svf /usr/local/csf/lib/webmin /etc/csf/ +if [ ! -e "/etc/csf/alerts" ]; then + ln -svf /usr/local/csf/tpl /etc/csf/alerts +fi +chcon -h system_u:object_r:bin_t:s0 /usr/sbin/lfd +chcon -h system_u:object_r:bin_t:s0 /usr/sbin/csf + +mkdir webmin/csf/images +mkdir ui/images +mkdir da/images +mkdir interworx/images + +cp -avf csf/* webmin/csf/images/ +cp -avf csf/* ui/images/ +cp -avf csf/* da/images/ +cp -avf csf/* interworx/images/ + +cp -avf messenger/*.php /etc/csf/messenger/ +cp -avf uninstall.vesta.sh /usr/local/csf/bin/uninstall.sh +cp -avf csftest.pl /usr/local/csf/bin/ +cp -avf remove_apf_bfd.sh /usr/local/csf/bin/ +cp -avf readme.txt /etc/csf/ +cp -avf sanity.txt /usr/local/csf/lib/ +cp -avf csf.rbls /usr/local/csf/lib/ +cp -avf restricted.txt /usr/local/csf/lib/ +cp -avf changelog.txt /etc/csf/ +cp -avf downloadservers /etc/csf/ +cp -avf install.txt /etc/csf/ +cp -avf version.txt /etc/csf/ +cp -avf license.txt /etc/csf/ +cp -avf webmin /usr/local/csf/lib/ +cp -avf ConfigServer /usr/local/csf/lib/ +cp -avf Net /usr/local/csf/lib/ +cp -avf Geo /usr/local/csf/lib/ +cp -avf Crypt /usr/local/csf/lib/ +cp -avf HTTP /usr/local/csf/lib/ +cp -avf JSON /usr/local/csf/lib/ +cp -avf version/* /usr/local/csf/lib/ +cp -avf csf.div /usr/local/csf/lib/ +cp -avf csfajaxtail.js /usr/local/csf/lib/ +cp -avf ui/images /etc/csf/ui/. +cp -avf profiles /usr/local/csf/ +cp -avf csf.conf /usr/local/csf/profiles/reset_to_defaults.conf +cp -avf lfd.logrotate /etc/logrotate.d/lfd +chcon --reference /etc/logrotate.d /etc/logrotate.d/lfd + +if [ -e "/usr/local/ispconfig/interface/web/csf/ispconfig_csf" ]; then + rm -Rfv /usr/local/ispconfig/interface/web/csf/ +fi + +rm -fv /etc/csf/csf.spamhaus /etc/csf/csf.dshield /etc/csf/csf.tor /etc/csf/csf.bogon + +mkdir -p /usr/local/man/man1/ +cp -avf csf.1.txt /usr/local/man/man1/csf.1 +cp -avf csf.help /usr/local/csf/lib/ +chmod 755 /usr/local/man/ +chmod 755 /usr/local/man/man1/ +chmod 644 /usr/local/man/man1/csf.1 + +chmod -R 600 /etc/csf +chmod -R 600 /var/lib/csf +chmod -R 600 /usr/local/csf/bin +chmod -R 600 /usr/local/csf/lib +chmod -R 600 /usr/local/csf/tpl +chmod -R 600 /usr/local/csf/profiles +chmod 600 /var/log/lfd.log* + +chmod -v 700 /usr/local/csf/bin/*.pl /usr/local/csf/bin/*.sh /usr/local/csf/bin/*.pm +chmod -v 700 /etc/csf/*.pl /etc/csf/*.cgi /etc/csf/*.sh /etc/csf/*.php /etc/csf/*.py +chmod -v 700 /etc/csf/webmin/csf/index.cgi +chmod -v 644 /etc/cron.d/lfd-cron +chmod -v 644 /etc/cron.d/csf-cron + +cp -avf csget.pl /etc/cron.daily/csget +chmod 700 /etc/cron.daily/csget +/etc/cron.daily/csget --nosleep + +chmod -v 700 auto.vesta.pl +./auto.vesta.pl $OLDVERSION + +if test `cat /proc/1/comm` = "systemd" +then + if [ -e /etc/init.d/lfd ]; then + if [ -f /etc/redhat-release ]; then + /sbin/chkconfig csf off + /sbin/chkconfig lfd off + /sbin/chkconfig csf --del + /sbin/chkconfig lfd --del + elif [ -f /etc/debian_version ] || [ -f /etc/lsb-release ]; then + update-rc.d -f lfd remove + update-rc.d -f csf remove + elif [ -f /etc/gentoo-release ]; then + rc-update del lfd default + rc-update del csf default + elif [ -f /etc/slackware-version ]; then + rm -vf /etc/rc.d/rc3.d/S80csf + rm -vf /etc/rc.d/rc4.d/S80csf + rm -vf /etc/rc.d/rc5.d/S80csf + rm -vf /etc/rc.d/rc3.d/S85lfd + rm -vf /etc/rc.d/rc4.d/S85lfd + rm -vf /etc/rc.d/rc5.d/S85lfd + else + /sbin/chkconfig csf off + /sbin/chkconfig lfd off + /sbin/chkconfig csf --del + /sbin/chkconfig lfd --del + fi + rm -fv /etc/init.d/csf + rm -fv /etc/init.d/lfd + fi + + mkdir -p /etc/systemd/system/ + mkdir -p /usr/lib/systemd/system/ + cp -avf lfd.service /usr/lib/systemd/system/ + cp -avf csf.service /usr/lib/systemd/system/ + + chcon -h system_u:object_r:systemd_unit_file_t:s0 /usr/lib/systemd/system/lfd.service + chcon -h system_u:object_r:systemd_unit_file_t:s0 /usr/lib/systemd/system/csf.service + + systemctl daemon-reload + + systemctl enable csf.service + systemctl enable lfd.service + + systemctl disable firewalld + systemctl stop firewalld + systemctl mask firewalld +else + cp -avf lfd.sh /etc/init.d/lfd + cp -avf csf.sh /etc/init.d/csf + chmod -v 755 /etc/init.d/lfd + chmod -v 755 /etc/init.d/csf + + if [ -f /etc/redhat-release ]; then + /sbin/chkconfig lfd on + /sbin/chkconfig csf on + elif [ -f /etc/debian_version ] || [ -f /etc/lsb-release ]; then + update-rc.d -f lfd remove + update-rc.d -f csf remove + update-rc.d lfd defaults 80 20 + update-rc.d csf defaults 20 80 + elif [ -f /etc/gentoo-release ]; then + rc-update add lfd default + rc-update add csf default + elif [ -f /etc/slackware-version ]; then + ln -svf /etc/init.d/csf /etc/rc.d/rc3.d/S80csf + ln -svf /etc/init.d/csf /etc/rc.d/rc4.d/S80csf + ln -svf /etc/init.d/csf /etc/rc.d/rc5.d/S80csf + ln -svf /etc/init.d/lfd /etc/rc.d/rc3.d/S85lfd + ln -svf /etc/init.d/lfd /etc/rc.d/rc4.d/S85lfd + ln -svf /etc/init.d/lfd /etc/rc.d/rc5.d/S85lfd + else + /sbin/chkconfig lfd on + /sbin/chkconfig csf on + fi +fi + +chown -Rf root:root /etc/csf /var/lib/csf /usr/local/csf +chown -f root:root /usr/sbin/csf /usr/sbin/lfd /etc/logrotate.d/lfd /etc/cron.d/csf-cron /etc/cron.d/lfd-cron /usr/local/man/man1/csf.1 /usr/lib/systemd/system/lfd.service /usr/lib/systemd/system/csf.service /etc/init.d/lfd /etc/init.d/csf + +mkdir -v -m 0600 /usr/local/vesta/web/list/csf/ +cp -avf vestacp/* /usr/local/vesta/web/list/csf/ +cp -avf csf /usr/local/vesta/web/list/csf/images/ +find /usr/local/vesta/web/list/csf -type d -exec chmod -v 755 {} \; +find /usr/local/vesta/web/list/csf -type f -exec chmod -v 644 {} \; +mv /usr/local/vesta/web/list/csf/csf.pl /usr/local/vesta/bin/ +chmod 700 /usr/local/vesta/bin/csf.pl + +cd webmin ; tar -czf /usr/local/csf/csfwebmin.tgz ./* +ln -svf /usr/local/csf/csfwebmin.tgz /etc/csf/ + +echo +echo "Installation Completed" +echo diff --git a/src/redux/integrityalert.txt b/src/redux/integrityalert.txt new file mode 100644 index 000000000..1ff21cf81 --- /dev/null +++ b/src/redux/integrityalert.txt @@ -0,0 +1,9 @@ +From: root +To: root +Subject: lfd on [hostname]: System Integrity checking detected a modified system file + +Time: [time] + +The following list of files have FAILED the md5sum comparison test. This means that the file has been changed in some way. This could be a result of an OS update or application upgrade. If the change is unexpected it should be investigated: + +[text] diff --git a/src/redux/interworx/Ctrl/Nodeworx/Configservercsf.php b/src/redux/interworx/Ctrl/Nodeworx/Configservercsf.php new file mode 100644 index 000000000..636e6834a --- /dev/null +++ b/src/redux/interworx/Ctrl/Nodeworx/Configservercsf.php @@ -0,0 +1,36 @@ +getView()->assign('title', 'Configservercsf Services'); + $this->getView()->assign('template', 'admin'); + } + + public function indexAction() + { + if (IW::NW()->isReseller()) { + $this->_getPlugin()->runReseller(); + } else { + $this->_getPlugin()->runAdmin(); + } + exit; + } +} diff --git a/src/redux/interworx/Plugin/Configservercsf.php b/src/redux/interworx/Plugin/Configservercsf.php new file mode 100644 index 000000000..3e6f2d4e2 --- /dev/null +++ b/src/redux/interworx/Plugin/Configservercsf.php @@ -0,0 +1,134 @@ + Security & Firewall, has replaced this item'); + } + elseif (strpos($ctrl_act, 'Ctrl_Nodeworx_Firewall') === 0) { + throw new IWorx_Exception_ActionBlocked('N/A'); + } + } + + public function getCategory() + { + return Plugin_Category::ADVANCED; + } + + public function getPriority() + { + return 40; + } + + public function runReseller() + { + putenv('IWORX_SESSION_ID=' . session_id()); + session_write_close(); + + $cmd = Ini::get(Ini::IWORX_BIN, 'runasuser'); + + $user = 'root'; + $cmd .= " {$user} custom /usr/local/interworx/plugins/configservercsf/lib/reseller.pl 2>&1"; + + $InterWorx = IW::Env()->getActiveSession()->getInterWorx(); + $WorkingUser = $InterWorx->getWorkingUser(); + putenv('REMOTE_USER=' . $WorkingUser->getNickname()); + + putenv('QUERY_STRING=' . http_build_query($_GET)); + putenv('REQUEST_METHOD=' . $_SERVER['REQUEST_METHOD']); + + putenv('REMOTE_ADDR=' . $_SERVER['REMOTE_ADDR']); + putenv('HTTP_USER_AGENT=' . $_SERVER['HTTP_USER_AGENT']); + + if ($_SERVER['REQUEST_METHOD'] === 'POST') { + putenv('CONTENT_LENGTH=' . $_SERVER['CONTENT_LENGTH']); + putenv('POST=' . http_build_query($_POST)); + putenv('HTTP_RAW_POST_DATA=' . http_build_query($_POST)); + } + + IWorxExec::exec($cmd, $result, $retval, IWorxExec::STDERR_2_STDOUT); + $header = 1; + foreach ($result as $line) { + if ($header) { + header ("$line\n"); + } else { + print "$line\n"; + } + if ($header && $line == "") { + $header = 0; + } + } + } + + public function runAdmin() + { + putenv('IWORX_SESSION_ID=' . session_id()); + session_write_close(); + + $cmd = Ini::get(Ini::IWORX_BIN, 'runasuser'); + + $user = 'root'; + $cmd .= " {$user} custom /usr/local/interworx/plugins/configservercsf/lib/index.pl 2>&1"; + + putenv('QUERY_STRING=' . http_build_query($_GET)); + putenv('REQUEST_METHOD=' . $_SERVER['REQUEST_METHOD']); + + putenv('REMOTE_ADDR=' . $_SERVER['REMOTE_ADDR']); + putenv('HTTP_USER_AGENT=' . $_SERVER['HTTP_USER_AGENT']); + + if ($_SERVER['REQUEST_METHOD'] === 'POST') { + putenv('CONTENT_LENGTH=' . $_SERVER['CONTENT_LENGTH']); + putenv('POST=' . http_build_query($_POST)); + putenv('HTTP_RAW_POST_DATA=' . http_build_query($_POST)); + } + + IWorxExec::exec($cmd, $result, $retval, IWorxExec::STDERR_2_STDOUT); + $header = 1; + foreach ($result as $line) { + if ($header) { + header ("$line\n"); + } else { + print "$line\n"; + } + if ($header && $line == "") { + $header = 0; + } + } + } + + public function updateNodeworxMenu(IWorxMenuManager $MenuMan) + { + $new_data = array( 'text' => 'ConfigServer Plugins', + 'class' => 'iw-i-plugin', + 'disabled_for_reseller' => '0' ); + + $MenuMan->addMenuItemAfter( + 'iw-menu-svc', + 'menu-configserver', + $new_data + ); + + $new_data = array( 'text' => 'Security & Firewall', + 'url' => '/nodeworx/configservercsf?action=launch', + 'parent' => 'menu-configserver', + 'class' => 'iw-i-plugin', + 'disabled_for_reseller' => '0' ); + + $MenuMan->addMenuItemAfter( + 'menu-configserver', + 'menu-configservercsf', + $new_data + ); + } + +} diff --git a/src/redux/interworx/images/LICENSE.txt b/src/redux/interworx/images/LICENSE.txt new file mode 100644 index 000000000..34da9d9ee --- /dev/null +++ b/src/redux/interworx/images/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/src/redux/interworx/images/admin_icon.svg b/src/redux/interworx/images/admin_icon.svg new file mode 100644 index 000000000..1c928ea0d --- /dev/null +++ b/src/redux/interworx/images/admin_icon.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/redux/interworx/images/bootstrap-chosen.css b/src/redux/interworx/images/bootstrap-chosen.css new file mode 100644 index 000000000..54e6a1398 --- /dev/null +++ b/src/redux/interworx/images/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/src/redux/interworx/images/bootstrap/css/bootstrap.min.css b/src/redux/interworx/images/bootstrap/css/bootstrap.min.css new file mode 100644 index 000000000..b89ef7f3e --- /dev/null +++ b/src/redux/interworx/images/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/src/redux/interworx/images/bootstrap/css/bootstrap.min.css.map b/src/redux/interworx/images/bootstrap/css/bootstrap.min.css.map new file mode 100644 index 000000000..0c2c93492 --- /dev/null +++ b/src/redux/interworx/images/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,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A,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
          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(" +{literal} + +{/literal} diff --git a/src/redux/interworx/templates/reseller.tpl b/src/redux/interworx/templates/reseller.tpl new file mode 100644 index 000000000..b7f6c8611 --- /dev/null +++ b/src/redux/interworx/templates/reseller.tpl @@ -0,0 +1,10 @@ + +{literal} + +{/literal} diff --git a/src/redux/lfd.logrotate b/src/redux/lfd.logrotate new file mode 100644 index 000000000..86ea16021 --- /dev/null +++ b/src/redux/lfd.logrotate @@ -0,0 +1,12 @@ +/var/log/lfd.log { + weekly + rotate 1 + compress + missingok +} +/var/log/lfd_messenger.log { + weekly + rotate 1 + compress + missingok +} diff --git a/src/redux/lfd.pl b/src/redux/lfd.pl new file mode 100644 index 000000000..dd5ddc1c1 --- /dev/null +++ b/src/redux/lfd.pl @@ -0,0 +1,11370 @@ +#!/usr/bin/perl +############################################################################### +# Copyright 2006-2023, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +## no critic (RequireUseWarnings, ProhibitExplicitReturnUndef, ProhibitMixedBooleanOperators, RequireBriefOpen, RequireLocalizedPunctuationVars) +# start main +use strict; +use lib '/usr/local/csf/lib'; +use Fcntl qw(:DEFAULT :flock); +use IO::Handle; +use IPC::Open3; +use Net::CIDR::Lite; +use POSIX qw(:sys_wait_h sysconf strftime setsid); +use Socket; +use ConfigServer::Config; +use ConfigServer::Slurp qw(slurp); +use ConfigServer::CheckIP qw(checkip cccheckip); +use ConfigServer::URLGet; +use ConfigServer::GetIPs qw(getips); +use ConfigServer::Service; +use ConfigServer::AbuseIP qw(abuseip); +use ConfigServer::GetEthDev; +use ConfigServer::Sendmail; +use ConfigServer::Logger qw(logfile); +use ConfigServer::KillSSH; +use ConfigServer::LookUpIP qw(iplookup); + +umask(0177); + +our ($abuseip, $accept, $apache401timeout, $apache403timeout, + $apache404timeout, $attimeout, $blocklisttimeout, $ccltimeout, $cctimeout, + $childcnt, $childpid, $childproc, $cidr, $cidr6, $cleanreg, $clock_ticks, + $clusterip, $count, $csftimeout, $cttimeout, $cxsreputation, + $dirwatchfiletimeout, $dirwatchtimeout, $dyndnstimeout, $eth6devin, + $eth6devout, $ethdevin, $ethdevout, $exploittimeout, $faststart, $gcidr, + $gcidr6, $gdyndnstimeout, $globaltimeout, $hostname, $hostshort, + $integritytimeout, $ipscidr, $ipscidr6, $ipv4reg, $ipv6reg, $loadtimeout, + $locktimeout, $loginterval, $masterpid, $modsecipdbchecktimeout, $pid, + $pidfile, $pidino, $pstimeout, $ptchildpid, $pttimeout, $queuetimeout, + $relaytimeout, $scripttimeout, $slurpreg, $smtptimeout, $sys_syslog, + $syslogcheckcode, $syslogchecktimeout, $sysloggid, $syslogpid, + $systemstatstimeout, $tar, $toomanymatches, $tz, $uidtimeout, $uiip, + $urlget, $version, $messenger1, $messenger2, $messenger3); + +our ($LISTLOCK, $IPTABLESLOCK, $PIDFILE); + +our (%accounttracking, %adb, %adf, %ads, %apache401, %apache403, %apache404, + %blockedips, %blocklists, %cfblocks, %config, %cpanelalert, + %cpanelalertusers, %cpconfig, %cxsports, %db, %dirwatchfile, %forks, + %gignoreips, %globlogs, %ifaces, %ignoreips, %ips, %logfiles, %loginproto, + %logins, %logintimeout, %logscannerfiles, %messengerips, %messengerports, + %newaccounttracking, %nofiles, %ports, %portscans, %psips, %pskip, + %relayip, %relays, %rtignore, %scripts, %sfile, %skip, %skipfile, + %skipscript, %skipuser, %suignore, %uidignore, %uidscans); + +our (@cccidrs, @cidrs, @faststart4, @faststart4nat, @faststart6, + @faststart6nat, @faststartipset, @gcidrs, @ipset, @lfbuf, @lffd, @lfino, + @lfsize, @logignore, @matchfile, @rdns, @suspicious); + +$pidfile = "/var/run/lfd.pid"; + +if (-e "/etc/csf/csf.disable") { + print "csf and lfd have been disabled\n"; + exit 1; +} + +if (-e "/etc/csf/csf.error") { + print "\nError: You have an unresolved error when starting csf. You need to restart csf successfully before starting lfd (see /etc/csf/csf.error)\n"; + exit 1; +} + +my $config = ConfigServer::Config->loadconfig(); +%config = $config->config(); +my %configsetting = $config->configsetting(); +$ipv4reg = $config->ipv4reg; +$ipv6reg = $config->ipv6reg; +$slurpreg = ConfigServer::Slurp->slurpreg; +$cleanreg = ConfigServer::Slurp->cleanreg; + +unless ($config{LF_DAEMON}) {&cleanup(__LINE__,"*Error* LF_DAEMON not enabled in /etc/csf/csf.conf")} +if ($config{TESTING}) {&cleanup(__LINE__,"*Error* lfd will not run with TESTING enabled in /etc/csf/csf.conf")} + +if ($config{UI}) { + require ConfigServer::DisplayUI; + import ConfigServer::DisplayUI; + require ConfigServer::cseUI; + import ConfigServer::cseUI; + eval { + local $SIG{__DIE__} = undef; + require IO::Socket::SSL; + import IO::Socket::SSL; + }; +} +if ($config{LF_DIRWATCH}) { + require File::Find; + import File::Find; +} +if ($config{UI} or $config{LF_DIRWATCH_FILE}) { + require Digest::MD5; + import Digest::MD5; +} +if ($config{SYSLOG} or $config{SYSLOG_CHECK}) { + eval('use Sys::Syslog;'); ##no critic + unless ($@) {$sys_syslog = 1} +} +if ($config{DEBUG}) { + require Time::HiRes; + import Time::HiRes; +} +if ($config{CLUSTER_SENDTO} or $config{CLUSTER_RECVFROM}) { + require Crypt::CBC; + import Crypt::CBC; + require File::Basename; + import File::Basename; +} +if ($config{CLUSTER_SENDTO} or $config{CLUSTER_RECVFROM}) { + require IO::Socket::INET; + import IO::Socket::INET; +} +if ($config{MESSENGER}) { + require ConfigServer::Messenger; + import ConfigServer::Messenger; +} +if ($config{CF_ENABLE}) { + require ConfigServer::CloudFlare; + import ConfigServer::CloudFlare; +} +if (-e "/etc/cxs/cxs.reputation" and -e "/usr/local/csf/lib/ConfigServer/cxs.pm") { + require ConfigServer::cxs; + import ConfigServer::cxs; + $cxsreputation = 1; + %cxsports = ConfigServer::cxs::Rports(); +} +$SIG{CHLD} = 'IGNORE'; + +if ($pid = fork) { + exit 0; +} elsif (defined($pid)) { + $pid = $$; +} else { + die "*Error* Unable to fork: $!"; +} + +chdir("/etc/csf"); + +close(STDIN); +close(STDOUT); +close(STDERR); +open STDIN, "<","/dev/null"; +open STDOUT, ">","/dev/null"; +open STDERR, ">","/dev/null"; +setsid(); + +my $oldfh = select STDERR; ##no critic +$| = 1; +select $oldfh; ##no critic + +if ($config{DEBUG}) { + open (STDERR, ">>", "/var/log/lfd.log"); +} + +if (-e "/proc/sys/kernel/hostname") { + open (my $IN, "<", "/proc/sys/kernel/hostname"); + flock ($IN, LOCK_SH); + $hostname = <$IN>; + chomp $hostname; + close ($IN); +} else { + $hostname = "unknown"; +} +$hostshort = (split(/\./,$hostname))[0]; +$clock_ticks = sysconf( &POSIX::_SC_CLK_TCK ) || 100; +$tz = strftime("%z", localtime); + +sysopen ($PIDFILE, $pidfile, O_RDWR | O_CREAT) or &childcleanup(__LINE__,"*Error* unable to create lfd PID file [$pidfile] $!"); +flock ($PIDFILE, LOCK_EX | LOCK_NB) or &childcleanup(__LINE__,"*Error* attempt to start lfd when it is already running"); +autoflush $PIDFILE 1; +seek ($PIDFILE, 0, 0); +truncate ($PIDFILE, 0); +print $PIDFILE "$pid\n"; +$pidino = (stat($pidfile))[1]; +$masterpid = $pid; + +$0 = "lfd - starting"; + +$SIG{INT} = \&cleanup; +$SIG{TERM} = \&cleanup; +$SIG{HUP} = \&cleanup; +$SIG{__DIE__} = sub {&cleanup(@_);}; +$SIG{CHLD} = 'IGNORE'; +$SIG{PIPE} = 'IGNORE'; + +$ipscidr = Net::CIDR::Lite->new; +$ipscidr6 = Net::CIDR::Lite->new; +$cidr = Net::CIDR::Lite->new; +$cidr6 = Net::CIDR::Lite->new; +$gcidr = Net::CIDR::Lite->new; +$gcidr6 = 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")}; + +$faststart = 0; + +eval { + local $SIG{__DIE__} = undef; + $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}); + logfile("*WARNING* URLGET set to use LWP but perl module is not installed, fallback to using CURL/WGET"); + } else { + $config{URLGET} = 1; + $urlget = ConfigServer::URLGet->new($config{URLGET}, "csf/$version", $config{URLPROXY}); + logfile("*WARNING* URLGET set to use LWP but perl module is not installed, CURL and WGET not installed - reverting to HTTP::Tiny"); + } +} + +if (-e "/etc/wwwacct.conf") { + foreach my $line (slurp("/etc/wwwacct.conf")) { + $line =~ s/$cleanreg//g; + if ($line =~ /^(\s|\#|$)/) {next} + my ($name,$value) = split (/ /,$line,2); + $cpconfig{$name} = $value; + } +} +if (-e "/usr/local/cpanel/version") { + foreach my $line (slurp("/usr/local/cpanel/version")) { + $line =~ s/$cleanreg//g; + if ($line =~ /\d/) {$cpconfig{version} = $line} + } +} + +if (-e "/var/lib/csf/csf.tempconf") {unlink ("/var/lib/csf/csf.tempconf")} +if (-e "/var/lib/csf/lfd.enable") {unlink "/var/lib/csf/lfd.enable"} +if (-e "/var/lib/csf/lfd.start") {unlink "/var/lib/csf/lfd.start"} +if (-e "/var/lib/csf/lfd.restart") {unlink "/var/lib/csf/lfd.restart"} +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 (-e "/var/lib/csf/csf.dnscache") {unlink "/var/lib/csf/csf.dnscache"} +if (-e "/var/lib/csf/csf.gignore") {unlink "/var/lib/csf/csf.gignore"} + +&getethdev; + +open (my $IN, "<", "/etc/csf/version.txt") or &cleanup(__LINE__,"Unable to open version.txt: $!"); +flock ($IN, LOCK_SH); +$version = <$IN>; +close ($IN); +chomp $version; +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)"} +logfile("daemon started on $hostname - csf v$version$generic"); +if ($config{DEBUG} >= 1) {logfile("Clock Ticks: $clock_ticks")} +if ($config{DEBUG} >= 1) {logfile("debug: **** DEBUG LEVEL $config{DEBUG} ENABLED ****")} + +unless (-e $config{SENDMAIL}) { + logfile("*WARNING* Unable to send email reports - [$config{SENDMAIL}] not found"); +} + +if (ConfigServer::Service::type() eq "systemd") { + my @reply = &syscommand(__LINE__,$config{SYSTEMCTL},"is-active","firewalld"); + chomp @reply; + if ($reply[0] eq "active" or $reply[0] eq "activating") { + &cleanup(__LINE__,"*Error* firewalld found to be running. You must stop and disable firewalld when using csf"); + exit 1; + } +} + +require ConfigServer::RegexMain; +import ConfigServer::RegexMain; + +if ($config{RESTRICT_SYSLOG} == 1) { + logfile("Restricted log file access (RESTRICT_SYSLOG)"); + foreach (qw{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}) { + if ($config{$_} != 0) { + $config{$_} = 0; + logfile("RESTRICT_SYSLOG: Option $_ *Disabled*"); + } + } +} +elsif ($config{RESTRICT_SYSLOG} == 3) { + logfile("Restricting syslog/rsyslog socket acccess to group [$config{RESTRICT_SYSLOG_GROUP}]..."); + &syslog_init; +} + +if ($config{SYSLOG} or $config{SYSLOG_CHECK}) { + unless ($sys_syslog) { + logfile("*Error* Cannot log to SYSLOG - Perl module Sys::Syslog required"); + } +} + +if (-e "/etc/csf/csf.blocklists") { + 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 ($cxsreputation and -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); + $url =~ s/download\.configserver\.com/$config{DOWNLOADSERVER}/g; + 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; + } + } +} + +if (-e "/etc/csf/csf.ignore") { + 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 ($first,undef) = split(/\s/,$line); + my ($ip,$iscidr) = split(/\//,$first); + if (checkip(\$first)) { + if ($iscidr) {push @cidrs,$first} else {$ignoreips{$ip} = 1} + } + elsif ($ip ne "127.0.0.1") {logfile("Invalid entry in csf.ignore: [$first]")} + } + foreach my $entry (@cidrs) { + if (checkip(\$entry) == 6) { + eval {local $SIG{__DIE__} = undef; $cidr6->add($entry)}; + } else { + eval {local $SIG{__DIE__} = undef; $cidr->add($entry)}; + } + if ($@) {logfile("Invalid entry in csf.ignore: $entry")} + } +} +if (-e "/etc/csf/csf.rignore") { + my @entries = slurp("/etc/csf/csf.rignore"); + 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} + if ($line =~ /^(\.|\w)/) { + my ($host,undef) = split (/\s/,$line); + if ($host ne "") {push @rdns,$host} + } + } +} +if ($config{IGNORE_ALLOW} and -e "/etc/csf/csf.allow") { + my @ignore = slurp("/etc/csf/csf.allow"); + 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 ($first,undef) = split(/\s/,$line); + my ($ip,$iscidr) = split(/\//,$first); + if (checkip(\$first)) { + if ($iscidr) {push @cidrs,$first} else {$ignoreips{$ip} = 1} + } + } + foreach my $entry (@cidrs) { + if (checkip(\$entry) == 6) { + eval {local $SIG{__DIE__} = undef; $cidr6->add($entry)}; + } else { + eval {local $SIG{__DIE__} = undef; $cidr->add($entry)}; + } + if ($@) {logfile("Invalid CIDR in csf.allow: $entry")} + } +} + +if ($config{LF_HTACCESS} or $config{LF_APACHE_404} or $config{LF_APACHE_403} or $config{LF_APACHE_401} or $config{LF_QOS} or $config{LF_SYMLINK}) {&globlog("HTACCESS_LOG")} +if ($config{LF_MODSEC} or $config{LF_CXS}) {&globlog("MODSEC_LOG")} +if ($config{LF_SUHOSIN}) {&globlog("SUHOSIN_LOG}")} +if ($config{LF_SMTPAUTH} or $config{LF_EXIMSYNTAX}) {&globlog("SMTPAUTH_LOG")} +if ($config{LF_POP3D} or $config{LT_POP3D}) {&globlog("POP3D_LOG")} +if ($config{LF_IMAPD} or $config{LT_IMAPD}) {&globlog("IMAPD_LOG")} +if ($config{LF_CPANEL}) {&globlog("CPANEL_LOG")} +if ($config{LF_DIRECTADMIN}) { + &globlog("DIRECTADMIN_LOG"); + &globlog("DIRECTADMIN_LOG_R"); + &globlog("DIRECTADMIN_LOG_S"); + &globlog("DIRECTADMIN_LOG_P"); +} +if ($config{LF_INTERWORX}) {&globlog("INTERWORX_LOG")} +if ($config{LF_CYBERPANEL}) {&globlog("CYBERPANEL_LOG")} +if ($config{LF_CWP}) {&globlog("CWP_LOG")} +if ($config{LF_VESTA}) {&globlog("VESTA_LOG")} +if ($config{LF_WEBMIN} or $config{LF_WEBMIN_EMAIL_ALERT}) {&globlog("WEBMIN_LOG")} +if ($config{LF_SSHD} or $config{LF_SSH_EMAIL_ALERT} or $config{LF_CONSOLE_EMAIL_ALERT}) {&globlog("SSHD_LOG")} +if ($config{LF_FTPD}) {&globlog("FTPD_LOG")} +if ($config{LF_BIND}) {&globlog("BIND_LOG")} +if ($config{LF_CPANEL_ALERT}) {&globlog("CPANEL_ACCESSLOG")} +if ($config{SYSLOG_CHECK} and $sys_syslog) {&globlog("SYSLOG_LOG")} + +if ($config{PS_INTERVAL} or $config{ST_ENABLE} or $config{UID_INTERVAL}) {&globlog("IPTABLES_LOG")} +if ($config{LF_SU_EMAIL_ALERT}) {&globlog("SU_LOG")} +if ($config{LF_SUDO_EMAIL_ALERT}) {&globlog("SUDO_LOG")} +if ($config{LF_SCRIPT_ALERT}) {&globlog("SCRIPT_LOG")} +if ($config{RT_RELAY_ALERT} or $config{RT_AUTHRELAY_ALERT} or $config{RT_POPRELAY_ALERT}) {&globlog("SMTPRELAY_LOG")} + +if ($config{LT_IMAPD}) {$loginproto{imapd} = $config{LT_IMAPD}} +if ($config{LT_POP3D}) {$loginproto{pop3d} = $config{LT_POP3D}} + +for (my $x = 1;$x < 10;$x++) {&globlog("CUSTOM${x}_LOG")} + +if (-e "/usr/local/cpanel/version" and -e "/etc/cpanel/ea4/is_ea4" and -e "/etc/cpanel/ea4/paths.conf") { + my @file = slurp("/etc/cpanel/ea4/paths.conf"); + foreach my $line (@file) { + $line =~ s/$cleanreg//g; + 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_logs") { + if ($config{LF_HTACCESS} or $config{LF_APACHE_404} or $config{LF_APACHE_403} or $config{LF_APACHE_401} or $config{LF_QOS} or $config{LF_SYMLINK}) { + delete $globlogs{HTACCESS_LOG}{$config{HTACCESS_LOG}}; + delete $logfiles{$config{HTACCESS_LOG}}; + $globlogs{HTACCESS_LOG}{"$value/error_log"} = 1; + $logfiles{"$value/error_log"} = 1; + logfile("EasyApache4, using $value/error_log instead of $config{HTACCESS_LOG} (Web Server)"); + } + if ($config{LF_MODSEC} or $config{LF_CXS}) { + delete $globlogs{MODSEC_LOG}{$config{MODSEC_LOG}}; + delete $logfiles{$config{MODSEC_LOG}}; + $globlogs{MODSEC_LOG}{"$value/error_log"} = 1; + $logfiles{"$value/error_log"} = 1; + logfile("EasyApache4, using $value/error_log instead of $config{MODSEC_LOG} {ModSecurity}"); + } + } + } +} + +if ($config{LOGSCANNER}) { + my @entries = slurp("/etc/csf/csf.logfiles"); + foreach my $line (@entries) { + if ($line =~ /^Include\s*(.*)$/) { + my @incfile = slurp($1); + push @entries,@incfile; + } + } + foreach my $file (@entries) { + $file =~ s/$cleanreg//g; + if ($file eq "") {next} + if ($file =~ /^\s*\#|Include/) {next} + if ($file =~ /\*|\?|\[/) { + foreach my $log (glob $file) { + if (-e $log) { + $logfiles{$log} = 1; + $logscannerfiles{$log} = 1; + } + } + } else { + if (-e $file) { + $logfiles{$file} = 1; + $logscannerfiles{$file} = 1; + } + } + } + my @entries2 = slurp("/etc/csf/csf.logignore"); + foreach my $line (@entries2) { + if ($line =~ /^Include\s*(.*)$/) { + my @incfile = slurp($1); + push @entries2,@incfile; + } + } + foreach my $line (@entries2) { + $line =~ s/$cleanreg//g; + if ($line eq "") {next} + if ($line =~ /^\s*\#|Include/) {next} + if (&testregex($line)) {push @logignore, $line} + else {logfile("*Error* Invalid regex [$line] in csf.logignore")} + } + logfile("Log Scanner..."); +} + +unless (-d "/var/spool/exim") {$config{LF_QUEUE_ALERT} = 0} + +$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"; + logfile("WATCH_MODE enabled..."); +} + +if (-e "/var/lib/csf/csf.restart") { + unlink "/var/lib/csf/csf.restart"; + &csfrestart; +} + +if ($config{LF_CSF}) { + if (-e "/var/lib/csf/cpanel.new") {unlink "/var/lib/csf/cpanel.new"} + logfile("CSF Tracking..."); + &csfcheck; + $csftimeout = 0; +} + +if ($config{IPV6}) { + logfile("IPv6 Enabled..."); +} + +if ($cxsreputation) { + logfile("cxs Reputation Enabled..."); +} + +if ($config{PT_LOAD}) { + logfile("LOAD Tracking..."); + &loadcheck; + $loadtimeout = 0; +} + +if ($config{CF_ENABLE} and -e "/etc/csf/csf.cloudflare") { + logfile("CloudFlare Firewall..."); + $cfblocks{LF_MODSEC} = 1; + $cfblocks{LF_CXS} = 1; +# $cfblocks{LF_CPANEL} = 1; +# $cfblocks{LF_DIRECTADMIN} = 1; +# $cfblocks{LF_WEBMIN} = 1; +} + +if ($config{MESSENGER}) { + unless (-e "/var/log/lfd_messenger.log") { + open (my $OUT, ">", "/var/log/lfd_messenger.log"); + close ($OUT); + } + system("chown","$config{MESSENGER_USER}:$config{MESSENGER_USER}","/var/log/lfd_messenger.log"); + + if (!$config{MESSENGERV2}) { + &messengerstop(2); + } + if (!$config{MESSENGERV3}) { + &messengerstop(3); + } + my (undef,undef,$uid,$gid) = getpwnam($config{MESSENGER_USER}); + if (($config{MESSENGER_USER} ne "") and ($config{MESSENGER_USER} ne "root") and ($uid > 0) and ($gid > 0)) { + if ($config{MESSENGER_HTTPS_DISABLED} ne "") { + logfile($config{MESSENGER_HTTPS_DISABLED}); + } + if ($config{MESSENGERV3}) { + $messenger3 = ConfigServer::Messenger->init(3); + if (-e "/var/cpanel/users/$config{MESSENGER_USER}") { + logfile("*MESSENGERV3* - Cannot run service using a cPanel account:[$config{MESSENGER_USER}], MESSENGER service disabled"); + $config{MESSENGER} = 0; + $config{MESSENGERV3} = 0; + &messengerstop(3); + } else { + if ($config{MESSENGER_HTTPS_IN} ne "") { + foreach my $port (split(/\,/,$config{MESSENGER_HTTPS_IN})) {$messengerports{$port} = 1} + logfile("Messenger HTTPS Service starting..."); + } + if ($config{MESSENGER_HTML_IN} ne "") { + foreach my $port (split(/\,/,$config{MESSENGER_HTML_IN})) {$messengerports{$port} = 1} + logfile("Messenger HTML Service starting..."); + } + &messengerv3; + } + } + elsif ($config{MESSENGERV2}) { + $messenger2 = ConfigServer::Messenger->init(2); + if (-e "/var/cpanel/users/$config{MESSENGER_USER}") { + logfile("*MESSENGERV2* - Cannot run service using a cPanel account:[$config{MESSENGER_USER}], MESSENGER service disabled"); + $config{MESSENGER} = 0; + $config{MESSENGERV2} = 0; + &messengerstop(2); + } else { + if ($config{MESSENGER_HTTPS_IN} ne "") { + foreach my $port (split(/\,/,$config{MESSENGER_HTTPS_IN})) {$messengerports{$port} = 1} + logfile("Messenger HTTPS Service starting..."); + } + if ($config{MESSENGER_HTML_IN} ne "") { + foreach my $port (split(/\,/,$config{MESSENGER_HTML_IN})) {$messengerports{$port} = 1} + logfile("Messenger HTML Service starting..."); + } + &messengerv2; + } + } + else { + $messenger1 = ConfigServer::Messenger->init(1); + if ($config{MESSENGER_HTTPS_IN} ne "") { + foreach my $port (split(/\,/,$config{MESSENGER_HTTPS_IN})) {$messengerports{$port} = 1} + logfile("Messenger HTTPS Service starting..."); + &messenger($config{MESSENGER_HTTPS},$config{MESSENGER_USER},"HTTPS"); + } + if ($config{MESSENGER_HTML_IN} ne "") { + foreach my $port (split(/\,/,$config{MESSENGER_HTML_IN})) {$messengerports{$port} = 1} + logfile("Messenger HTML Service starting..."); + &messenger($config{MESSENGER_HTML},$config{MESSENGER_USER},"HTML"); + } + } + if ($config{MESSENGER_TEXT_IN} ne "") { + unless (defined $messenger1) { + $messenger1 = ConfigServer::Messenger->init(1); + } + foreach my $port (split(/\,/,$config{MESSENGER_TEXT_IN})) {$messengerports{$port} = 1} + logfile("Messenger TEXT Service starting..."); + &messenger($config{MESSENGER_TEXT},$config{MESSENGER_USER},"TEXT"); + } + } else { + logfile("Messenger account [$config{MESSENGER_USER}] invalid, MESSENGER service *disabled*"); + $config{MESSENGER} = 0; + } +} else { + &messengerstop(2); + &messengerstop(3); +} + +if ($config{UI}) { + if ($config{UI_CXS}) { + use lib '/etc/cxs'; + require ConfigServer::cxsUI; + } + if ($config{UI_USER} eq "" or $config{UI_USER} eq "username") { + logfile("*Error* Cannot run csf Integrated UI - UI_USER must set"); + $config{UI} = 0; + } + elsif ($config{UI_PASS} eq "" or $config{UI_PASS} eq "password") { + logfile("*Error* Cannot run Integrated csf UI - UI_PASS must set"); + $config{UI} = 0; + } + else { + logfile("csf Integrated UI running up on port $config{UI_PORT}..."); + &ui; + } +} + +if ($config{CLUSTER_RECVFROM}) { + logfile("Cluster Service starting..."); + if (length $config{CLUSTER_KEY} < 8) { + logfile("Failed: Cluster Service - CLUSTER_KEY too short"); + $config{CLUSTER_RECVFROM} = 0; + } else { + if (length $config{CLUSTER_KEY} < 20) {logfile("Cluster Service - CLUSTER_KEY should really be longer than 20 characters")} + &lfdserver; + } +} + +if ($config{DYNDNS}) { + logfile("DynDNS Tracking..."); + &dyndns; + $dyndnstimeout = 0; + if ($config{DYNDNS} < 60) { + logfile("DYNDNS refresh increased to 300 to prevent looping (csf.conf setting: $config{DYNDNS})"); + $config{DYNDNS} = 300; + } +} + +if ($config{LF_GLOBAL}) { + if ($config{GLOBAL_IGNORE}) {logfile("Global Ignore Tracking...")} + if ($config{GLOBAL_ALLOW}) {logfile("Global Allow Tracking...")} + if ($config{GLOBAL_DENY}) {logfile("Global Deny Tracking...")} + if ($config{GLOBAL_DYNDNS}) {logfile("Global DynDNS Tracking...")} + &global; + $globaltimeout = 0; + if ($config{LF_GLOBAL} < 60) { + logfile("LF_GLOBAL refresh increased to 300 to prevent looping (csf.conf setting: $config{LF_GLOBAL})"); + $config{LF_GLOBAL} = 300; + } + if ($config{GLOBAL_DYNDNS_INTERVAL} < 60) { + logfile("GLOBAL_DYNDNS_INTERVAL refresh increased to 300 to prevent looping (csf.conf setting: $config{GLOBAL_DYNDNS_INTERVAL})"); + $config{GLOBAL_DYNDNS_INTERVAL} = 300; + } +} + +if (scalar(keys %blocklists) > 0) { + logfile("Blocklist Tracking..."); + &blocklist; + $blocklisttimeout = 0; +} + +if ($config{CC_LOOKUPS}) { + if ($config{CC_LOOKUPS} != 4 and $config{MM_LICENSE_KEY} eq "" and $config{CC_SRC} eq "1") { + logfile("*ERROR*: Country Code Lookups setting MM_LICENSE_KEY must be set in /etc/csf/csf.conf to continue updating the MaxMind databases"); + } + logfile("Country Code Lookups..."); + &countrycodelookups; + $ccltimeout = 0; +} + +if ($config{CC_DENY} or $config{CC_ALLOW} or $config{CC_ALLOW_FILTER} or $config{CC_ALLOW_PORTS} or $config{CC_DENY_PORTS} or $config{CC_ALLOW_SMTPAUTH}) { + if ($config{MM_LICENSE_KEY} eq "" and $config{CC_SRC} eq "1") { + logfile("*ERROR*: Country Code Filters setting MM_LICENSE_KEY must be set in /etc/csf/csf.conf to continue updating the MaxMind databases"); + } + logfile("Country Code Filters..."); + &countrycode; + $cctimeout = 0; +} + +if ($config{CC_IGNORE}) { + if ($config{CC_LOOKUPS}) { + logfile("Country Code Ignores..."); + } else { + logfile("Country Code Ignores requires CC_LOOKUPS to be enabled - disabled CC_IGNORE"); + $config{CC_IGNORE} = ""; + } +} + +if ($config{LF_INTEGRITY}) { + logfile("System Integrity Tracking..."); + &integrity; + $integritytimeout = 0; + if ($config{LF_INTEGRITY} < 120) { + logfile("LF_INTEGRITY refresh increased to 300 to prevent looping (csf.conf setting: $config{LF_INTEGRITY})"); + $config{LF_INTEGRITY} = 300; + } +} + +if ($config{LF_EXPLOIT}) { + if (-e "/var/lib/csf/csf.tempexploit") {unlink ("/var/lib/csf/csf.tempexploit")} + if (-e "/etc/csf/csf.suignore") { + my @entries = slurp("/etc/csf/csf.suignore"); + 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} + $suignore{$line} = 1; + } + } + logfile("Exploit Tracking..."); + &exploit; + $exploittimeout = 0; + if ($config{LF_EXPLOIT} < 60) { + logfile("LF_EXPLOIT refresh increased to 60 to prevent looping (csf.conf setting: $config{LF_EXPLOIT})"); + $config{LF_EXPLOIT} = 60; + } +} +if ($config{X_ARF}) { + if (-e $config{HOST}) {$abuseip = 1} + else {logfile("Binary location of HOST is incorrect in csf.conf")} +} + +if ($config{LF_DIRWATCH}) { + if (-e "/etc/csf/csf.fignore") { + my @entries = slurp("/etc/csf/csf.fignore"); + 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} + if ($line =~ /\*|\\/) { + if (&testregex($line)) {push @matchfile, $line} + else {logfile("*Error* Invalid regex [$line] in csf.fignore")} + } + elsif ($line =~ /^user:(.*)/) { + $skipuser{$1} = 1; + } + else { + $skipfile{$line} = 1; + } + } + } + if (-e "/var/lib/csf/csf.tempfiles") {unlink ("/var/lib/csf/csf.tempfiles")} + if (-e "/var/lib/csf/csf.dwdisable") {unlink ("/var/lib/csf/csf.dwdisable")} + logfile("Directory Watching..."); + $dirwatchtimeout = 0; +} + +if ($config{LF_DIRWATCH_FILE}) { + if (-e "/etc/csf/csf.dirwatch") { + logfile("Directory File Watching..."); + my @entries = slurp("/etc/csf/csf.dirwatch"); + 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} + if (-e $line) { + $dirwatchfile{$line} = 1; + } else { + logfile("Directory File Watching [$line] not found - ignoring"); + } + } + &dirwatchfile; + $dirwatchfiletimeout = 0; + } +} + +if ($config{LF_SCRIPT_ALERT}) { + logfile("Email Script Tracking..."); + if (-e "/etc/csf/csf.signore") { + my @entries = slurp("/etc/csf/csf.signore"); + 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} + $skipscript{$line} = 1; + } + } +} + +if ($config{LF_QUEUE_ALERT}) { + logfile("Email Queue Tracking..."); + &queuecheck; + $queuetimeout = 0; + if ($config{LF_QUEUE_INTERVAL} < 30) { + logfile("LF_QUEUE_INTERVAL refresh increased to 300 to prevent looping (csf.conf setting: $config{LF_QUEUE_INTERVAL})"); + $config{LF_QUEUE_INTERVAL} = 300; + } +} + +if ($config{LF_MODSECIPDB_ALERT}) { + logfile("ModSecurity IP D/B Tracking..."); + &modsecipdbcheck; + $modsecipdbchecktimeout = 0; +} + +if ($config{RT_RELAY_ALERT} or $config{RT_AUTHRELAY_ALERT} or $config{RT_POPRELAY_ALERT} or $config{RT_LOCALRELAY_ALERT} or $config{RT_LOCALHOSTRELAY_ALERT}) { + logfile("Email Relay Tracking..."); + if ($config{RT_LOCALRELAY_ALERT}) { + if (-e "/etc/csf/csf.mignore") { + my @entries = slurp("/etc/csf/csf.mignore"); + 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} + $rtignore{$line} = 1; + } + } + } +} + +if ($config{LF_PERMBLOCK}) { + logfile("Temp to Perm Block Tracking..."); +} + +if ($config{LF_NETBLOCK}) { + logfile("Netblock Tracking..."); +} + +if ($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 $old = 1; + my ($oip,$operm,$otime,$omessage) = split(/\|/,$line,4); + my $interval = time - $otime; + if ($config{LF_PERMBLOCK} and $interval < ($config{LF_PERMBLOCK_INTERVAL} * $config{LF_PERMBLOCK_COUNT})) {$old = 0} + if ($config{LF_NETBLOCK} and $interval < ($config{LF_NETBLOCK_INTERVAL} * $config{LF_NETBLOCK_COUNT})) {$old = 0} + unless ($old) {print $TEMPIP "$line\n"} + } + close ($TEMPIP); +} + +if ($config{ST_SYSTEM}) { + logfile("System Statistics..."); + my $time = time; + sysopen (my $SYSSTATNEW,"/var/lib/csf/stats/system.new", O_RDWR | O_CREAT); + flock ($SYSSTATNEW, LOCK_EX); + seek ($SYSSTATNEW, 0, 0); + truncate ($SYSSTATNEW, 0); + + sysopen (my $SYSSTAT,"/var/lib/csf/stats/system", O_RDWR | O_CREAT); + flock ($SYSSTAT, LOCK_EX); + while (my $line = <$SYSSTAT>) { + chomp $line; + my ($thistime,undef) = split(/\,/,$line); + if ($time - $thistime > (86400 * $config{ST_SYSTEM_MAXDAYS})) {next} + print $SYSSTATNEW $line."\n"; + } + close ($SYSSTAT); + close ($SYSSTATNEW); + rename "/var/lib/csf/stats/system.new", "/var/lib/csf/stats/system"; + &systemstats; +} +if ($config{PS_INTERVAL}) { + logfile("Port Scan Tracking..."); + if ($config{PS_INTERVAL} < 60) { + logfile("PS_INTERVAL refresh increased to 60 to prevent looping (csf.conf setting: $config{PS_INTERVAL})"); + $config{PS_INTERVAL} = 60; + } + $pstimeout = 0; +} +if ($config{UID_INTERVAL}) { + logfile("User ID Tracking..."); + if ($config{UID_INTERVAL} < 60) { + logfile("UID_INTERVAL refresh increased to 60 to prevent looping (csf.conf setting: $config{UID_INTERVAL})"); + $config{UID_INTERVAL} = 60; + } + $uidtimeout = 0; + my @entries = slurp("/etc/csf/csf.uidignore"); + 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} + $uidignore{$line} = 1; + } +} + +if ($config{CT_LIMIT}) { + if ($config{CT_STATES}) { + logfile("Connection Tracking ($config{CT_STATES})..."); + } else { + logfile("Connection Tracking..."); + } + &connectiontracking; + $cttimeout = 0; + if ($config{CT_INTERVAL} < 10) { + logfile("CT_INTERVAL refresh increased to 30 to prevent looping (csf.conf setting: $config{CT_INTERVAL})"); + $config{CT_INTERVAL} = 30; + } +} + +if ($config{PT_LIMIT}) { + if (-e "/etc/csf/csf.pignore") { + my @entries = slurp("/etc/csf/csf.pignore"); + 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 ($item,$rule) = split(/:/,$line,2); + $rule =~ s/\r|\n//g; + $rule =~ s/\s*$//g; + $item =~ s/\s//g; + $item = lc $item; + if ($item =~ /^(cmd|exe|user)$/) { + $skip{$item}{$rule} = 1; + } + elsif ($item =~ /^(pcmd|pexe|puser)$/) { + if (&testregex($rule)) {$pskip{$item}{$rule} = 1} + else {logfile("*Error* Invalid regex [$line] in csf.pignore")} + } + } + } + if (-e "/var/lib/csf/csf.temppids") {unlink ("/var/lib/csf/csf.temppids")} + if (-e "/var/lib/csf/csf.tempusers") {unlink ("/var/lib/csf/csf.tempusers")} + logfile("Process Tracking..."); + &processtracking; + $pttimeout = 0; + if ($config{PT_INTERVAL} < 10) { + logfile("PT_INTERVAL refresh increased to 60 to prevent looping (csf.conf setting: $config{PT_INTERVAL})"); + $config{PT_INTERVAL} = 60; + } + + if ($config{PT_SSHDHUNG}) { + logfile("SSHD Hung Session Tracking..."); + } +} + +if ($config{AT_ALERT}) { + if ($config{AT_ALERT} == 3) { + my ($user,$passwd,$uid,$gid,$quota,$comment,$gcos,$dir,$shell) = getpwnam("root"); + $accounttracking{$user}{account} = 1; + $accounttracking{$user}{passwd} = $passwd; + $accounttracking{$user}{uid} = $uid; + $accounttracking{$user}{gid} = $gid; + $accounttracking{$user}{dir} = $dir; + $accounttracking{$user}{shell} = $shell; + } else { + while (my ($user,$passwd,$uid,$gid,$quota,$comment,$gcos,$dir,$shell) = getpwent()) { + if (($config{AT_ALERT} eq "2") and ($uid ne "0")) {next} + $accounttracking{$user}{account} = 1; + $accounttracking{$user}{passwd} = $passwd; + $accounttracking{$user}{uid} = $uid; + $accounttracking{$user}{gid} = $gid; + $accounttracking{$user}{dir} = $dir; + $accounttracking{$user}{shell} = $shell; + } + endpwent(); + } + logfile("Account Tracking..."); + $attimeout = 0; + if ($config{AT_INTERVAL} < 10) { + logfile("AT_INTERVAL refresh increased to 60 to prevent looping (csf.conf setting: $config{AT_INTERVAL})"); + $config{AT_INTERVAL} = 60; + } +} + +if ($config{LF_SSH_EMAIL_ALERT}) { + logfile("SSH Tracking..."); +} +if ($config{LF_WEBMIN_EMAIL_ALERT}) { + logfile("Webmin Tracking..."); +} +if ($config{LF_SU_EMAIL_ALERT}) { + logfile("SU Tracking..."); +} +if ($config{LF_SUDO_EMAIL_ALERT}) { + logfile("SUDO Tracking..."); +} +if ($config{LF_CONSOLE_EMAIL_ALERT}) { + logfile("Console Tracking..."); +} + +if ($config{LF_CPANEL_ALERT}) { + $config{LF_CPANEL_ALERT_USERS} =~ s/\s//g; + foreach my $user (split(/\,/,$config{LF_CPANEL_ALERT_USERS})) { + $cpanelalertusers{$user} = 1; + } + logfile("WHM Tracking..."); +} + +if ($config{PORTKNOCKING} and $config{PORTKNOCKING_ALERT}) { + logfile("Port Knocking Tracking..."); +} + +my $sshdef = $config{PORTS_sshd}; +$ports{pop3d} = $config{PORTS_pop3d}; +$ports{imapd} = $config{PORTS_imapd}; +$ports{htpasswd} = $config{PORTS_htpasswd}; +$ports{mod_security} = $config{PORTS_mod_security}; +$ports{mod_qos} = $config{PORTS_mod_qos}; +$ports{symlink} = $config{PORTS_symlink}; +$ports{cxs} = $config{PORTS_cxs}; +$ports{bind} = $config{PORTS_bind}; +$ports{suhosin} = $config{PORTS_suhosin}; +$ports{cpanel} = $config{PORTS_cpanel}; +$ports{ftpd} = $config{PORTS_ftpd}; +$ports{smtpauth} = $config{PORTS_smtpauth}; +$ports{eximsyntax} = $config{PORTS_eximsyntax}; +$ports{webmin} = $config{PORTS_webmin}; +$ports{directadmin} = $config{PORTS_directadmin}; + +opendir (DIR, "/etc/chkserv.d"); +while (my $file = readdir (DIR)) { + if ($file =~ /exim-(\d+)/) { + $ports{smtpauth} .= ",$1"; + $ports{eximsyntax} .= ",$1"; + } +} +closedir (DIR); + +if (-e "/etc/ssh/sshd_config") { + foreach my $line (slurp("/etc/ssh/sshd_config")) { + $line =~ s/$cleanreg//g; + if ($line =~ /^(\s|\#|$)/) {next} + if ($line =~ /^Port\s+(\d+)/i) { + my $port = $1; + if ($ports{sshd}) { + $ports{sshd} .= ",$port"; + } else { + $ports{sshd} = $port; + } + } + } +} +unless ($ports{sshd}) {$ports{sshd} = $sshdef} + +if ($config{LF_INTERVAL} < 60) { + logfile("LF_INTERVAL refresh increased to 300 to prevent looping (csf.conf setting: $config{LF_INTERVAL})"); + $config{LT_INTERVAL} = 300; +} + +if ($config{LF_PARSE} < 5 or $config{LF_PARSE} > 20) { + logfile("LF_PARSE refresh reset to 5 to prevent looping (csf.conf setting: $config{LF_PARSE})"); + $config{LF_PARSE} = 5; +} + +my $lastline = ""; +$scripttimeout = 0; +my $duration = 0; +my $maintimer = 0; +while (1) { + $0 = "lfd - processing"; + $maintimer = time; + + seek ($PIDFILE, 0, 0); + my @piddata = <$PIDFILE>; + chomp @piddata; + if (($pid ne $piddata[0]) or ($pidino ne (stat($pidfile))[1])) { + &cleanup(__LINE__,"*Error* pid mismatch or missing"); + } + + if (-e "/etc/csf/csf.error") { + &cleanup(__LINE__,"*Error* You have an unresolved error when starting csf. You need to restart csf successfully before restarting lfd (see /etc/csf/csf.error). *lfd stopped*"); + } + my $perms = sprintf "%04o", (stat("/etc/csf"))[2] & oct("07777"); + if ($perms != "0600") { + chmod (0600,"/etc/csf"); + logfile("*Permissions* on /etc/csf reset to 0600 [currently: $perms]"); + } + $perms = sprintf "%04o", (stat("/var/lib/csf"))[2] & oct("07777"); + if ($perms != "0600") { + chmod (0600,"/var/lib/csf"); + logfile("*Permissions* on /var/lib/csf reset to 0600 [currently: $perms]"); + } + $perms = sprintf "%04o", (stat("/usr/local/csf"))[2] & oct("07777"); + if ($perms != "0600") { + chmod (0600,"/usr/local/csf"); + logfile("*Permissions* on /usr/local/csf reset to 0600 [currently: $perms]"); + } + + $locktimeout+=$duration; + if ($locktimeout >= 60) { + $locktimeout = 0; + &lockhang; + } + + if (scalar(keys %forks) > 200) { + my $forkcnt = 0; + foreach my $key (keys %forks) { + if ($key =~ /\d+/ and $key > 1 and kill(0,$key)) { + $forkcnt++; + if ($config{DEBUG} >= 3) {logfile("debug: fork:[$key]")} + } else { + delete $forks{$key}; + } + } + if ($config{DEBUG} >= 2) {logfile("debug: Forks:[$forkcnt]")} + if ($forkcnt > 200) { + logfile("*Error* Excessive number of children ($forkcnt), restarting lfd..."); + &lfdrestart; + exit; + } + } + + if (-e "/var/lib/csf/lfd.restart") { + unlink "/var/lib/csf/lfd.restart"; + &lfdrestart; + exit; + } + + if (-e "/var/lib/csf/csf.restart") { + unlink "/var/lib/csf/csf.restart"; + &csfrestart; + } + + if ($config{LF_CSF}) { + $csftimeout+=$duration; + if ($csftimeout >= 300) { + $csftimeout = 0; + &csfcheck; + } + } + + if ($config{SYSLOG_CHECK} and $sys_syslog) { + $syslogchecktimeout+=$duration; + if ($syslogchecktimeout >= $config{SYSLOG_CHECK}) { + $syslogchecktimeout = 0; + if ($syslogcheckcode eq "") { + my @chars = ('0'..'9','a'..'z','A'..'Z'); + $syslogcheckcode = join '', map {$chars[rand(@chars)]} (1..(15 + int(rand(15)))); + eval { + local $SIG{__DIE__} = undef; + openlog('lfd', 'ndelay,pid', 'user'); + syslog('info', "SYSLOG check [$syslogcheckcode]"); + closelog(); + } + } else { + &syslogcheck; + $syslogcheckcode = ""; + } + } + } + + if ($config{ST_SYSTEM}) { + $systemstatstimeout+=$duration; + if ($systemstatstimeout >= 60) { + $systemstatstimeout = 0; + &systemstats; + } + } + + if ($config{LT_POP3D}) { + $logintimeout{pop3d}+=$duration; + if ($logintimeout{pop3d} >= 3600) { + delete $logintimeout{pop3d}; + delete $logins{pop3d}; + } + } + if ($config{LT_IMAPD}) { + $logintimeout{imapd}+=$duration; + if ($logintimeout{imapd} >= 3600) { + delete $logintimeout{imapd}; + delete $logins{imapd}; + } + } + if ($config{PS_INTERVAL}) { + $pstimeout+=$duration; + if ($pstimeout >= $config{PS_INTERVAL}) { + $pstimeout = 0; + undef %portscans; + } + } + if ($config{UID_INTERVAL}) { + $uidtimeout+=$duration; + if ($uidtimeout >= $config{UID_INTERVAL}) { + $uidtimeout = 0; + undef %uidscans; + } + } + if ($config{LF_SCRIPT_ALERT}) { + $scripttimeout+=$duration; + if ($scripttimeout >= 3600) { + $scripttimeout = 0; + undef %scripts; + } + } + if ($config{LF_APACHE_404}) { + $apache404timeout+=$duration; + if ($apache404timeout >= $config{LF_INTERVAL}) { + $apache404timeout = 0; + undef %apache404; + } + } + if ($config{LF_APACHE_403}) { + $apache403timeout+=$duration; + if ($apache403timeout >= $config{LF_INTERVAL}) { + $apache403timeout = 0; + undef %apache403; + } + } + if ($config{LF_APACHE_401}) { + $apache401timeout+=$duration; + if ($apache401timeout >= $config{LF_INTERVAL}) { + $apache401timeout = 0; + undef %apache401; + } + } + if ($config{RT_RELAY_ALERT} or $config{RT_AUTHRELAY_ALERT} or $config{RT_POPRELAY_ALERT} or $config{RT_LOCALRELAY_ALERT} or $config{RT_LOCALHOSTRELAY_ALERT}) { + $relaytimeout+=$duration; + if ($relaytimeout >= 3600) { + $relaytimeout = 0; + undef %relays; + } + } + + if (-e "/var/lib/csf/csf.tempconf") { + open (my $IN, "<", "/var/lib/csf/csf.tempconf"); + flock ($IN, LOCK_SH); + while (my $line = <$IN>) { + chomp $line; + if ($line =~ /^\#/) {next} + if ($line !~ /=/) {next} + my ($name,$value) = split (/=/,$line,2); + $name =~ s/\s//g; + if ($value =~ /\"(.*)\"/) { + $value = $1; + } else { + &cleanup(__LINE__,"*Error* Invalid configuration line in csf.tempconf"); + } + $config{$name} = $value; + } + close ($IN); + } + + if ($config{GLOBAL_IGNORE} and -e "/var/lib/csf/csf.gignore") { + undef @gcidrs; + undef %gignoreips; + undef $gcidr; + undef $gcidr6; + $gcidr = Net::CIDR::Lite->new; + $gcidr6 = Net::CIDR::Lite->new; + open (my $IN, "<", "/var/lib/csf/csf.gignore"); + flock ($IN, LOCK_SH); + while (my $line = <$IN>) { + chomp $line; + if ($line =~ /^(\#|\n|\r|\s)/ or $line eq "") {next} + my ($ip,undef) = split(/\s/,$line); + my (undef,$iscidr) = split(/\//,$ip); + my $v = checkip(\$ip); + if ($v) { + if ($iscidr) { + push @gcidrs,$ip; + undef $@; + if ($v == 6) { + eval {local $SIG{__DIE__} = undef; $gcidr6->add($ip)}; + } else { + eval {local $SIG{__DIE__} = undef; $gcidr->add($ip)}; + } + if ($@) {logfile("Invalid entry in GLOBAL_IGNORE: $ip")} + } else {$gignoreips{$ip} = 1} + } + elsif ($ip ne "127.0.0.1") {logfile("Invalid entry in GLOBAL_IGNORE: [$ip]")} + } + close ($IN); + unlink "/var/lib/csf/csf.gignore"; + } + + $count = 0; + $0 = "lfd - scanning log files"; + undef %relayip; + if ($config{RELAYHOSTS}) { + open (my $IN, "<", "/etc/relayhosts"); + flock ($IN, LOCK_SH); + while (my $ip = <$IN>) { + chomp $ip; + if (checkip(\$ip)) {$relayip{$ip} = 1} + } + close ($IN); + } + if ($config{DYNDNS} and $config{DYNDNS_IGNORE}) { + open (my $IN, "<", "/var/lib/csf/csf.tempdyn"); + flock ($IN, LOCK_SH); + while (my $ip = <$IN>) { + chomp $ip; + if (checkip(\$ip)) {$relayip{$ip} = 1} + } + close ($IN); + } + if ($config{GLOBAL_DYNDNS} and $config{GLOBAL_DYNDNS_IGNORE}) { + open (my $IN, "<", "/var/lib/csf/csf.tempgdyn"); + flock ($IN, LOCK_SH); + while (my $ip = <$IN>) { + chomp $ip; + if (checkip(\$ip)) {$relayip{$ip} = 1} + } + close ($IN); + } + + if ($config{RESTRICT_SYSLOG} == 3) {&syslog_perms} + foreach my $lgfile (keys %logfiles) { + if ($lgfile eq "") {next} + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start",$lgfile,$timer)} + my $totlines = 0; + my @data; + while (my $line = &getlogfile($lgfile,$count,$totlines)) { + if ($line eq "reopen") { + undef @data; + last; + } else { + $totlines ++; + push @data, $line; + } + } + if ($config{DEBUG} >= 2) {logfile("debug: Parsing $lgfile ($totlines lines)")} + foreach my $line (@data) { + if (($lastline ne "") and ($line =~ /^\S+\s+\d+\s+\S+ \S+ last message repeated (\d+) times/)) { + my $hits = $1; + if ($hits > 100) {$hits = 100} + for (my $x = 0;$x <$hits ;$x++) { + &dochecks($lastline,$lgfile); + } + } else { + &dochecks($line,$lgfile); + $lastline = $line; + } + } + $lastline = ""; + $count++; + undef %psips; + undef %blockedips; + if ($config{DEBUG} >= 3) {$timer = &timer("stop",$lgfile,$timer)} + } + + $0 = "lfd - processing"; + if ($config{CT_LIMIT}) { + $cttimeout+=$duration; + if ($cttimeout >= $config{CT_INTERVAL}) { + $cttimeout = 0; + &connectiontracking; + } + } + + if ($config{DYNDNS}) { + $dyndnstimeout+=$duration; + if ($dyndnstimeout >= $config{DYNDNS}) { + $dyndnstimeout = 0; + &dyndns; + } + } + + if ($config{GLOBAL_DYNDNS}) { + $gdyndnstimeout+=$duration; + if ($gdyndnstimeout >= $config{GLOBAL_DYNDNS_INTERVAL}) { + $gdyndnstimeout = 0; + &globaldyndns; + } + } + + if ($config{LF_GLOBAL}) { + $globaltimeout+=$duration; + if ($globaltimeout >= $config{LF_GLOBAL}) { + $globaltimeout = 0; + &global; + } + } + + if (scalar(keys %blocklists)) { + $blocklisttimeout+=$duration; + if ($blocklisttimeout >= 300) { + $blocklisttimeout = 0; + &blocklist; + } + } + + if ($config{CC_DENY} or $config{CC_ALLOW} or $config{CC_ALLOW_FILTER} or $config{CC_ALLOW_PORTS} or $config{CC_DENY_PORTS} or $config{CC_ALLOW_SMTPAUTH}) { + $cctimeout+=$duration; + if ($cctimeout >= 3600) { + $cctimeout = 0; + &countrycode; + } + } + + if ($config{CC_LOOKUPS}) { + $ccltimeout+=$duration; + if ($ccltimeout >= 3600) { + $ccltimeout = 0; + &countrycodelookups; + } + } + + if ($config{LOGSCANNER}) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); + my $lastrun; + + if (-e "/var/lib/csf/csf.lastlogrun") { + my @data = slurp("/var/lib/csf/csf.lastlogrun"); + $loginterval = $lastrun = $data[0]; + } + if ($loginterval eq "") { + if ($config{LOGSCANNER_INTERVAL} eq "hourly") {$loginterval = $hour} + if ($config{LOGSCANNER_INTERVAL} eq "daily") {$loginterval = $mday} + } + if (-e "/var/lib/csf/csf.logrun") { + unlink "/var/lib/csf/csf.logrun"; + &logscanner($hour); + } + elsif ($config{LOGSCANNER_INTERVAL} eq "hourly" and $loginterval ne $hour) { + $loginterval = $hour; + &logscanner($hour); + } + elsif ($config{LOGSCANNER_INTERVAL} eq "daily" and $loginterval ne $mday) { + $loginterval = $mday; + &logscanner($hour); + } + + if ($lastrun ne $loginterval) { + $lastrun = $loginterval; + sysopen (my $LOGRUN, "/var/lib/csf/csf.lastlogrun", O_WRONLY | O_CREAT | O_TRUNC); + flock ($LOGRUN, LOCK_EX); + print $LOGRUN $loginterval; + close ($LOGRUN); + } + } + + if ($config{LF_INTEGRITY}) { + $integritytimeout+=$duration; + if ($integritytimeout >= $config{LF_INTEGRITY}) { + $integritytimeout = 0; + &integrity; + } + } + + if ($config{LF_QUEUE_ALERT}) { + $queuetimeout+=$duration; + if ($queuetimeout >= $config{LF_QUEUE_INTERVAL}) { + $queuetimeout = 0; + &queuecheck; + } + } + + if ($config{LF_MODSECIPDB_ALERT}) { + $modsecipdbchecktimeout+=$duration; + if ($modsecipdbchecktimeout >= 3600) { + $modsecipdbchecktimeout = 0; + &modsecipdbcheck; + } + } + + if ($config{LF_EXPLOIT}) { + $exploittimeout+=$duration; + if ($exploittimeout >= $config{LF_EXPLOIT}) { + $exploittimeout = 0; + &exploit; + } + } + + if ($config{LF_DIRWATCH}) { + $dirwatchtimeout+=$duration; + if (not -e "/var/lib/csf/csf.dwdisable") { + if ($dirwatchtimeout >= $config{LF_DIRWATCH}) { + $dirwatchtimeout = 0; + &dirwatch; + } + } + } + + if ($config{LF_DIRWATCH_FILE}) { + $dirwatchfiletimeout+=$duration; + if ($dirwatchfiletimeout >= $config{LF_DIRWATCH_FILE}) { + &dirwatchfile; + $dirwatchfiletimeout = 0; + } + } + + if ($config{PT_LOAD}) { + $loadtimeout+=$duration; + if ($loadtimeout >= $config{PT_LOAD}) { + $loadtimeout = 0; + &loadcheck; + } + } + + if ($config{PT_LIMIT}) { + $pttimeout+=$duration; + if ($pttimeout >= $config{PT_INTERVAL}) { + $pttimeout = 0; + &processtracking; + } + } + + if ($config{MESSENGER}) { + unless (-e "/var/log/lfd_messenger.log") { + open (my $OUT, ">", "/var/log/lfd_messenger.log"); + close ($OUT); + } + system("chown","$config{MESSENGER_USER}:$config{MESSENGER_USER}","/var/log/lfd_messenger.log"); + foreach my $key (keys %messengerips) { + if ($messengerips{$key} > 1 and $config{"MESSENGER_${key}_IN"} ne "") { + unless (kill(0,$messengerips{$key})) { + &messenger($config{"MESSENGER_${key}"},$config{MESSENGER_USER},$key); + logfile("Messenger $key Service died, restarted"); + } + } + } + &messengerrecaptcha; + } + if ($config{UI}) { + if ($uiip > 1 and !(kill(0,$uiip))) { + &ui; + logfile("Integrated UI Service died, restarted"); + } + } + if ($config{CLUSTER_RECVFROM}) { + if ($clusterip > 1 and !(kill(0,$clusterip))) { + &lfdserver; + logfile("Cluster Service died, restarted"); + } + } + + if ($config{AT_ALERT}) { + $attimeout+=$duration; + if ($attimeout >= $config{AT_INTERVAL}) { + $attimeout = 0; + undef %newaccounttracking; + if ($config{AT_ALERT} == 3) { + my ($user,$passwd,$uid,$gid,$quota,$comment,$gcos,$dir,$shell) = getpwnam("root"); + $newaccounttracking{$user}{account} = 1; + $newaccounttracking{$user}{passwd} = $passwd; + $newaccounttracking{$user}{uid} = $uid; + $newaccounttracking{$user}{gid} = $gid; + $newaccounttracking{$user}{dir} = $dir; + $newaccounttracking{$user}{shell} = $shell; + } else { + while (my ($user,$passwd,$uid,$gid,$quota,$comment,$gcos,$dir,$shell) = getpwent()) { + if (($config{AT_ALERT} eq "2") and ($uid ne "0")) {next} + $newaccounttracking{$user}{account} = 1; + $newaccounttracking{$user}{passwd} = $passwd; + $newaccounttracking{$user}{uid} = $uid; + $newaccounttracking{$user}{gid} = $gid; + $newaccounttracking{$user}{dir} = $dir; + $newaccounttracking{$user}{shell} = $shell; + } + endpwent(); + } + &accounttracking; + %accounttracking = %newaccounttracking; + } + } + + if ($config{INTERWORX}) { + if (slurp("/etc/csf/apf_stub.pl") ne slurp("/etc/apf/apf")) { + &syscommand(__LINE__,"cp -af /etc/csf/apf_stub.pl /etc/apf/apf"); + &syscommand(__LINE__,"chmod 750 /etc/apf/apf"); + logfile ("InterWorx: Reapplied apf stub"); + } + } + + &ipunblock; + + $0 = "lfd - sleeping"; + sleep ($config{LF_PARSE}); + + $duration = time - $maintimer; + if (($config{DEBUG} >= 1) and ($duration > ($config{LF_PARSE} * 10))) { + logfile ("debug: *Performance* log parsing taking $duration seconds"); + } + if ($config{DEBUG} >= 2) {logfile("debug: Tick: $duration [$config{LF_PARSE}]")} +} + +exit; + +# end main +############################################################################### +# start dochecks +sub dochecks { + my $line = shift; + my $lgfile = shift; + my $timenow = time; + my $logscanner_skip = 0; + + my ($reason, $ip, $app, $customtrigger, $customports, $customperm, $customcf) = ConfigServer::RegexMain::processline ($line,$lgfile,\%globlogs); + + my ($gip,$account,$domain) = split (/\|/,$ip,3); + unless ($account =~ /^[a-zA-Z0-9\-\_\.\@\%\+]+$/) { + if ($account and $config{DEBUG} >= 1) {logfile("debug: (processline) Account name [$account] is invalid")} + $account = ""; + } + $ip = $gip; + if (($ip) and ($ip !~ /^127\./) and ($ip ne "::1")) { + if (&ignoreip($ip)) { + logfile("$reason $ip - ignored"); + } else { + if ($blockedips{$ip}{block} or ($blockedips{$ip}{apps} =~ /\b$app\b/)) { + if ($config{DEBUG} >= 1) {logfile("debug: $ip already blocked")} + } else { + if (($app eq "pop3d" or $app eq "imapd") and $line =~ /\(auth failed, (\d+) attempts/) { + $db{$ip}{text} .= "$line\n"; + for (1..$1) { + $db{$ip}{count}++; + $db{$ip}{apps} .= $app." "; + $db{$ip}{appscount}{$app}++; + $db{$ip}{mytime} .= "$timenow,"; + $db{$ip}{appstime}{$app} .= "$timenow,"; + $db{$ip}{domains} .= $domain." "; + } + } else { + $db{$ip}{count}++; + $db{$ip}{text} .= "$line\n"; + $db{$ip}{apps} .= $app." "; + $db{$ip}{appscount}{$app}++; + $db{$ip}{mytime} .= "$timenow,"; + $db{$ip}{appstime}{$app} .= "$timenow,"; + $db{$ip}{domains} .= $domain." "; + } + + my $hits; + my $trigger; + my $setting; + my @times; + if ($customtrigger) { + $trigger = "LF_CUSTOMTRIGGER"; + $config{$trigger} = $customtrigger; + $config{"$trigger\_PERM"} = $customperm; + $ports{$app} = $customports; + $cfblocks{LF_CUSTOMTRIGGER} = $customcf; + } + if ($config{LF_TRIGGER}) { + @times = split(/\,/,$db{$ip}{mytime}); + $trigger = "LF_TRIGGER"; + } else { + @times = split(/\,/,$db{$ip}{appstime}{$app}); + if ($app eq "sshd") {$trigger = "LF_SSHD"} + elsif ($app eq "pop3d") {$trigger = "LF_POP3D"} + elsif ($app eq "imapd") {$trigger = "LF_IMAPD"} + elsif ($app eq "ftpd") {$trigger = "LF_FTPD"} + elsif ($app eq "smtpauth") {$trigger = "LF_SMTPAUTH"} + elsif ($app eq "eximsyntax") {$trigger = "LF_EXIMSYNTAX"} + elsif ($app eq "htpasswd") {$trigger = "LF_HTACCESS"} + elsif ($app eq "mod_security") {$trigger = "LF_MODSEC"} + elsif ($app eq "bind") {$trigger = "LF_BIND"} + elsif ($app eq "suhosin") {$trigger = "LF_SUHOSIN"} + elsif ($app eq "cpanel") {$trigger = "LF_CPANEL"} + elsif ($app eq "directadmin") {$trigger = "LF_DIRECTADMIN"} + elsif ($app eq "interworx") {$trigger = "LF_INTERWORX"} + elsif ($app eq "cyberpanel") {$trigger = "LF_CYBERPANEL"} + elsif ($app eq "cwp") {$trigger = "LF_CWP"} + elsif ($app eq "vesta") {$trigger = "LF_VESTA"} + elsif ($app eq "webmin") {$trigger = "LF_WEBMIN"} + elsif ($app eq "whm") {$trigger = "LF_CPANEL"} + elsif ($app eq "webmail") {$trigger = "LF_CPANEL"} + elsif ($app eq "mod_qos") {$trigger = "LF_QOS"} + elsif ($app eq "symlink") {$trigger = "LF_SYMLINK"} + elsif ($app eq "cxs") {$trigger = "LF_CXS"} + } + + my $newtimes; + my $newcnt = 0; + foreach my $time (@times) { + if ($timenow - $time <= $config{LF_INTERVAL}) { + $newtimes .= "$time,"; + $newcnt++; + } + } + if ($config{LF_TRIGGER}) { + $db{$ip}{count} = $newcnt; + $db{$ip}{mytime} = $newtimes; + $hits = $db{$ip}{count}; + } else { + $db{$ip}{appscount}{$app} = $newcnt; + $db{$ip}{appstime}{$app} = $newtimes; + $hits = $db{$ip}{appscount}{$app}; + } + + if ($config{DEBUG} >= 1) {logfile("debug: $reason $ip - $hits failure(s) in the last $config{LF_INTERVAL} secs")} + + if ($hits >= $config{$trigger}) { + my @text = split(/\n/,$db{$ip}{text}); + $db{$ip}{text} = ""; + for (-$hits..-1) {$db{$ip}{text} .= "$text[$_]\n"} + $0 = "lfd - blocking $ip"; + &block($ip,$hits,$app,$config{"$trigger\_PERM"},$trigger,$reason); + if ($config{LF_SELECT} and !$config{LF_TRIGGER}) { + $db{$ip}{appscount}{$app} = 0; + $db{$ip}{appstime}{$app} = ""; + } else { + delete $db{$ip}; + } + if ($cxsreputation) { + ConfigServer::cxs::Rreport($trigger,$ip,"$reason $ip - $hits failure(s) in the last $config{LF_INTERVAL} secs",$trigger); + } + $0 = "lfd - scanning $lgfile"; + } + + if ($config{LF_DISTATTACK} and $account) { + $adb{$app}{$account}{$timenow}{ip} .= "$ip,"; + $adb{$app}{$account}{$timenow}{text} .= "$line\n"; + my @accountips; + my $text; + foreach my $key (keys %{$adb{$app}{$account}}) { + if ($timenow - $key <= $config{LF_INTERVAL}) { + push @accountips, (split(/\,/,$adb{$app}{$account}{$key}{ip})); + $text .= $adb{$app}{$account}{$key}{text}; + } else { + delete $adb{$app}{$account}{$key}; + } + } + my %seen; + my @uniqueips = grep { ! $seen{ $_ }++ } @accountips; + if ($config{DEBUG} >= 1) {logfile("debug: $reason ".@uniqueips." ip(s) to account [$account] ".@accountips." in the last $config{LF_INTERVAL} secs")} + if ((@accountips >= $config{$trigger}) and (@uniqueips >= $config{LF_DISTATTACK_UNIQ})) { + delete $adb{$app}{$account}; + &blockaccount(\@uniqueips,$account,$#accountips+1,$app,$text,$config{"$trigger\_PERM"},$trigger); + } + } + } + } + } + + if ($config{LF_DISTFTP} and ($globlogs{FTPD_LOG}{$lgfile})) { + my ($ip, $account) = ConfigServer::RegexMain::processdistftpline ($line); + unless ($account =~ /^[a-zA-Z0-9\-\_\.\@\%\+]+$/) { + if ($account and $config{DEBUG} >= 1) {logfile("debug: (processdistftpline) Account name [$account] is invalid")} + $account = ""; + } + if ($ip and $account and ($ip !~ /^127\./) and ($ip ne "::1")) { + if (&ignoreip($ip)) { + if ($config{DEBUG} >= 1) {logfile("debug: Distributed FTP $ip - ignored")} + } else { + $adf{$account}{$timenow}{ip} .= "$ip,"; + $adf{$account}{$timenow}{text} .= "$line\n"; + my @accountips; + my $text; + foreach my $key (keys %{$adf{$account}}) { + if ($timenow - $key <= $config{LF_DIST_INTERVAL}) { + push @accountips, (split(/\,/,$adf{$account}{$key}{ip})); + $text .= $adf{$account}{$key}{text}; + } else { + delete $adf{$account}{$key}; + } + } + my %seen; + my @uniqueips = grep { ! $seen{ $_ }++ } @accountips; + if ($config{DEBUG} >= 1) {logfile("debug: FTP logins from ".@uniqueips." ip(s) to account [$account] ".@accountips." in the last $config{LF_INTERVAL} secs")} + if ((@accountips >= $config{LF_DISTFTP}) and (@uniqueips >= $config{LF_DISTFTP_UNIQ})) { + delete $adf{$account}; + &blockdistftp(\@uniqueips,$account,$#accountips+1,$text,$config{LF_DISTFTP_PERM}); + } + } + } + } + + if ($config{LF_DISTSMTP} and ($globlogs{SMTPAUTH_LOG}{$lgfile})) { + my ($ip, $account) = ConfigServer::RegexMain::processdistsmtpline ($line); + unless ($account =~ /^[a-zA-Z0-9\-\_\.\@\%\+]+$/) { + if ($account and $config{DEBUG} >= 1) {logfile("debug: (processdistsmtpline) Account name [$account] is invalid")} + $account = ""; + } + if ($ip and $account and ($ip !~ /^127\./) and ($ip ne "::1")) { + if (&ignoreip($ip)) { + if ($config{DEBUG} >= 1) {logfile("debug: Distributed SMTP $ip - ignored")} + } else { + $ads{$account}{$timenow}{ip} .= "$ip,"; + $ads{$account}{$timenow}{text} .= "$line\n"; + my @accountips; + my $text; + foreach my $key (keys %{$ads{$account}}) { + if ($timenow - $key <= $config{LF_DIST_INTERVAL}) { + push @accountips, (split(/\,/,$ads{$account}{$key}{ip})); + $text .= $ads{$account}{$key}{text}; + } else { + delete $ads{$account}{$key}; + } + } + my %seen; + my @uniqueips = grep { ! $seen{ $_ }++ } @accountips; + if ($config{DEBUG} >= 1) {logfile("debug: SMTP logins from ".@uniqueips." ip(s) to account [$account] ".@accountips." in the last $config{LF_INTERVAL} secs")} + if ((@accountips >= $config{LF_DISTSMTP}) and (@uniqueips >= $config{LF_DISTSMTP_UNIQ})) { + delete $ads{$account}; + &blockdistsmtp(\@uniqueips,$account,$#accountips+1,$text,$config{LF_DISTSMTP_PERM}); + } + } + } + } + + if ($config{LF_APACHE_404} and ($globlogs{HTACCESS_LOG}{$lgfile})) { + my ($ip) = ConfigServer::RegexMain::loginline404($line); + if ($ip and !&ignoreip($ip)) { + $apache404{$ip}{count}++; + $apache404{$ip}{text} .= "$line\n"; + if ($apache404{$ip}{count} > $config{LF_APACHE_404}) { + &disable404($ip,$apache404{$ip}{text}); + delete $apache404{$ip}; + } + } + } + + if ($config{LF_APACHE_403} and ($globlogs{HTACCESS_LOG}{$lgfile})) { + my ($ip) = ConfigServer::RegexMain::loginline403($line); + if ($ip and !&ignoreip($ip)) { + $apache403{$ip}{count}++; + $apache403{$ip}{text} .= "$line\n"; + if ($apache403{$ip}{count} > $config{LF_APACHE_403}) { + &disable403($ip,$apache403{$ip}{text}); + delete $apache403{$ip}; + } + } + } + + if ($config{LF_APACHE_401} and ($globlogs{HTACCESS_LOG}{$lgfile})) { + my ($ip) = ConfigServer::RegexMain::loginline401($line); + if ($ip and !&ignoreip($ip)) { + $apache401{$ip}{count}++; + $apache401{$ip}{text} .= "$line\n"; + if ($apache401{$ip}{count} > $config{LF_APACHE_401}) { + &disable401($ip,$apache401{$ip}{text}); + delete $apache401{$ip}; + } + } + } + + if (($config{LT_POP3D} or $config{LT_IMAPD}) and (($globlogs{POP3D_LOG}{$lgfile}) or ($globlogs{IMAPD_LOG}{$lgfile}))) { + my ($app, $account, $ip) = ConfigServer::RegexMain::processloginline ($line); + unless ($account =~ /^[a-zA-Z0-9\-\_\.\@\%\+]+$/) { + if ($account and $config{DEBUG} >= 1) {logfile("debug: (processloginline) Account name [$account] is invalid")} + $account = ""; + } + if ($account and $loginproto{$app} and !&ignoreip($ip,1)) { + $logins{$app}{$account}{$ip}++; + if ($account and $config{DEBUG} >= 1) {logfile("debug: (processloginline) Account name [$account] [$ip] [$logins{$app}{$account}{$ip}]")} + if ($logins{$app}{$account}{$ip} > $loginproto{$app}) { + $0 = "lfd - disabling $app logins for $account"; + &logindisable($app,$ip,$logins{$app}{$account}{$ip},$account); + delete $logins{$app}{$account}{$ip}; + $0 = "lfd - scanning $lgfile"; + } + } + } + + if ($config{LF_SSH_EMAIL_ALERT} and (($lgfile eq "/var/log/messages") or ($lgfile eq "/var/log/secure") or ($lgfile eq "/var/log/auth.log") or ($globlogs{SSHD_LOG}{$lgfile}))) { + my ($account, $ip, $method) = ConfigServer::RegexMain::processsshline ($line); + unless ($account =~ /^[a-zA-Z0-9\-\_\.\@\%\+]+$/) { + if ($account and $config{DEBUG} >= 1) {logfile("debug: (processsshline) Account name [$account] is invalid")} + $account = ""; + } + if ($account and $ip and !&ignoreip($ip)) { + &sshalert($account, $ip, $method, $line); + } + elsif (&ignoreip($ip)) {logfile("*SSH login* from $ip into the $account account using $method authentication - ignored")} + } + + if ($config{LF_SU_EMAIL_ALERT} and (($lgfile eq "/var/log/messages") or ($lgfile eq "/var/log/secure") or ($lgfile eq "/var/log/auth.log") or ($globlogs{SU_LOG}{$lgfile}))) { + my ($to, $from, $status) = ConfigServer::RegexMain::processsuline ($line); + if (($to and $from) and ($from ne "root") and ($from ne 'root(uid=0)') and ($from ne '(uid=0)')) { + &sualert($to, $from, $status, $line); + } + } + + if ($config{LF_SUDO_EMAIL_ALERT} and (($lgfile eq "/var/log/messages") or ($lgfile eq "/var/log/secure") or ($lgfile eq "/var/log/auth.log") or ($globlogs{SUDO_LOG}{$lgfile}))) { + my ($to, $from, $status) = ConfigServer::RegexMain::processsudoline ($line); + if (($to and $from) and ($from ne "root") and ($from ne 'root(uid=0)') and ($from ne '(uid=0)')) { + &sudoalert($to, $from, $status, $line); + } + } + + if ($config{LF_CONSOLE_EMAIL_ALERT} and (($lgfile eq "/var/log/messages") or ($lgfile eq "/var/log/secure") or ($lgfile eq "/var/log/auth.log") or ($globlogs{SU_LOG}{$lgfile}))) { + my ($status) = ConfigServer::RegexMain::processconsoleline ($line); + if ($status) { + &consolealert($line); + } + } + + if ($config{LF_CPANEL_ALERT} and ($globlogs{CPANEL_ACCESSLOG}{$lgfile})) { + my ($ip,$user) = ConfigServer::RegexMain::processcpanelline ($line); + unless ($user =~ /^[a-zA-Z0-9\-\_\.\@\%\+]+$/) { + if ($user and $config{DEBUG} >= 1) {logfile("debug: (processcpanelline) Account name [$user] is invalid")} + $user = ""; + } + if ($ip and !&ignoreip($ip) and $user and ($cpanelalertusers{$user} or $cpanelalertusers{all})) { + if ($cpanelalert{$ip}{$user} and (time - $cpanelalert{$ip}{$user} < 3600)) { + $cpanelalert{$ip}{$user} = time; + } else { + $cpanelalert{$ip}{$user} = time; + &cpanelalert($ip,$user, $line); + } + } + } + + if ($config{LF_WEBMIN_EMAIL_ALERT} and ($globlogs{WEBMIN_LOG}{$lgfile})) { + my ($account, $ip) = ConfigServer::RegexMain::processwebminline ($line); + if ($account) { + &webminalert($account,$ip, $line); + } + } + + if ($config{LF_SCRIPT_ALERT} and ($globlogs{SCRIPT_LOG}{$lgfile})) { + my $path = ConfigServer::RegexMain::scriptlinecheck($line); + if ($path ne "") { + $scripts{$path}{cnt}++; + if ($scripts{$path}{cnt} <= 10) { + $scripts{$path}{mails} .= "$line\n"; + } + if ($scripts{$path}{cnt} > $config{LF_SCRIPT_LIMIT}) { + &scriptalert($path,$scripts{$path}{cnt},$scripts{$path}{mails}); + delete $scripts{$path}; + } + } + } + + if ($config{PS_INTERVAL} and ($globlogs{IPTABLES_LOG}{$lgfile})) { + my ($ip, $port) = ConfigServer::RegexMain::pslinecheck($line); + if ($port and $ip and !&ignoreip($ip)) { + my $hit = 0; + foreach my $ports (split(/\,/,$config{PS_PORTS})) { + if ($ports =~ /\:/) { + my ($start,$end) = split(/\:/,$ports); + if ($port >= $start and $port <= $end) {$hit = 1} + } + elsif ($port == $ports) {$hit = 1} + if ($hit) {last} + } + if ($hit) { + $portscans{$ip}{count}++; + $portscans{$ip}{blocks} .= "$line\n"; + $portscans{$ip}{ports}{$port} = 1; + if ($portscans{$ip}{count} > $config{PS_LIMIT}) { + if ($config{PS_DIVERSITY} > 1 and ($config{PS_DIVERSITY} > scalar (keys %{$portscans{$ip}{ports}}))) { + if ($config{DEBUG} >= 1) {logfile("debug: *Port Scan* detected from $ip - but denied by PS_DIVERSITY")} + } else { + if ($psips{$ip}) { + if ($config{DEBUG} >= 1) {logfile("debug: *Port Scan* detected from $ip - already blocked")} + delete $portscans{$ip}; + } else { + &portscans($ip,$portscans{$ip}{count},$portscans{$ip}{blocks}); + $psips{$ip} = 1; + delete $portscans{$ip}; + } + } + } + } + } + elsif (($config{DEBUG} >= 1) and $port and $ip and &ignoreip($ip)) { + logfile("debug: PS count for $ip - ignored"); + } + } + + if ($config{UID_INTERVAL} and ($globlogs{IPTABLES_LOG}{$lgfile})) { + my ($port, $uid) = ConfigServer::RegexMain::uidlinecheck($line); + if ($port and $uid and !$uidignore{$uid}) { + my $hit = 0; + foreach my $ports (split(/\,/,$config{UID_PORTS})) { + if ($ports =~ /\:/) { + my ($start,$end) = split(/\:/,$ports); + if ($port >= $start and $port <= $end) {$hit = 1} + } + elsif ($port == $ports) {$hit = 1} + if ($hit) {last} + } + if ($hit) { + $uidscans{$uid}{count}++; + $uidscans{$uid}{blocks} .= "$line\n"; + if ($uidscans{$uid}{count} > $config{UID_LIMIT}) { + &uidscans($uid,$uidscans{$uid}{count},$uidscans{$uid}{blocks}); + delete $uidscans{$uid}; + } + } + } + elsif (($config{DEBUG} >= 1) and $port and $uid and $uidignore{$uid}) { + logfile("debug: UID count for $uid - ignored"); + } + } + + if ($config{ST_ENABLE} and ($globlogs{IPTABLES_LOG}{$lgfile})) { + if (ConfigServer::RegexMain::statscheck($line)) { + &stats($line,"iptables"); + } + } + + if ($config{SYSLOG_CHECK} and $sys_syslog and $syslogcheckcode and ($globlogs{SYSLOG_LOG}{$lgfile})) { + if (ConfigServer::RegexMain::syslogcheckline($line,$syslogcheckcode)) { + if ($config{DEBUG} >= 2) {logfile("debug: SYSLOG_CHECK match [$syslogcheckcode]")} + $syslogcheckcode = ""; + $logscanner_skip = 1; + } + } + + if ($config{PORTKNOCKING} and $config{PORTKNOCKING_ALERT} and ($globlogs{IPTABLES_LOG}{$lgfile})) { + my ($ip, $port) = ConfigServer::RegexMain::portknockingcheck($line); + if ($port and $ip and !&ignoreip($ip)) { + &portknocking($ip, $port); + } + } + + if ($config{LOGSCANNER} and $logscannerfiles{$lgfile} and !$logscanner_skip) { + my $hit = 1; + foreach my $regex (@logignore) { + if ($line =~ /$regex/) { + $hit = 0; + last; + } + } + if ($hit) { + unless (-e "/var/lib/csf/csf.logmax") { + sysopen (my $LOGTEMP,"/var/lib/csf/csf.logtemp", O_RDWR | O_CREAT); + flock ($LOGTEMP, LOCK_EX); + my @data = <$LOGTEMP>; + close ($LOGTEMP); + if (@data > $config{LOGSCANNER_LINES}) { + open (my $OUT,">","/var/lib/csf/csf.logmax"); + close ($OUT); + } else { + sysopen (my $LOGTEMP,"/var/lib/csf/csf.logtemp", O_WRONLY | O_APPEND | O_CREAT); + flock ($LOGTEMP, LOCK_EX); + print $LOGTEMP "$lgfile|$line\n"; + close ($LOGTEMP); + } + } + } + } + + if ((($config{RT_RELAY_ALERT} or $config{RT_AUTHRELAY_ALERT} or $config{RT_POPRELAY_ALERT} or $config{RT_LOCALRELAY_ALERT} or $config{RT_LOCALHOSTRELAY_ALERT})) and ($globlogs{SMTPRELAY_LOG}{$lgfile})) { + my ($ip,$check) = ConfigServer::RegexMain::relaycheck($line); + if ($ip) { + if ($check eq "RELAY" and !$relays{$ip}{check}) { + open (my $RELAYHOSTS, "<", "/etc/relayhosts"); + flock ($RELAYHOSTS, LOCK_SH); + my @relayhosts = <$RELAYHOSTS>; + close ($RELAYHOSTS); + chomp @relayhosts; + if (grep {$_ =~ /^$ip$/} @relayhosts) {$check = "POPRELAY"} + + open (my $ALWAYSRELAY, "<", "/etc/alwaysrelay"); + flock ($ALWAYSRELAY, LOCK_SH); + @relayhosts = <$ALWAYSRELAY>; + close ($ALWAYSRELAY); + chomp @relayhosts; + if (grep {$_ =~ /^$ip$/} @relayhosts) {$check = "POPRELAY"} + } + if ($ips{$ip} or $ipscidr->find($ip) or $ipscidr6->find($ip)) {$check = "LOCALHOSTRELAY"} + if ($config{ST_SYSTEM}) { + sysopen (my $EMAIL, "/var/lib/csf/stats/email", O_RDWR | O_CREAT); + flock ($EMAIL, LOCK_EX); + my $stats = <$EMAIL>; + chomp $stats; + my ($sent,$recv) = split(/\:/,$stats); + if ($check eq "RELAY") {$recv++} else {$sent++} + seek ($EMAIL, 0, 0); + truncate ($EMAIL, 0); + print $EMAIL "$sent:$recv"; + close ($EMAIL); + } + } + if ($ip and ($ip ne "mailnull") and ($ip ne "root") and (!$rtignore{$ip})) { + my $tline = $line; + $tline =~ s/".*"/""/g; + my $start = 0; + my $cnt = 0; + foreach my $item (split(/\s+/,$tline)) { + if ($item eq "for") {$start = 1 ; next} + if ($start and ($item =~ /\@/)) {$cnt++} else {$start = 0} + } + if ($cnt > 0) { + $relays{$ip}{cnt}+=$cnt; + } else { + $relays{$ip}{cnt}++; + } + if ($config{DEBUG} >= 1) {logfile("debug: RT\_$check\_LIMIT detected from $ip, count = $relays{$ip}{cnt}")} + + unless ($relays{$ip}{check}) {$relays{$ip}{check} = $check} + + my $mailcnt = 0; + foreach my $mail (split(/\n/,$relays{$ip}{mails})) {$mailcnt++} + if ($mailcnt < 10) { + $relays{$ip}{mails} .= "$line\n"; + } + + if (($relays{$ip}{cnt} > $config{"RT\_$check\_LIMIT"}) and ($config{"RT\_$check\_ALERT"})) { + if (($check eq "LOCALHOSTRELAY") or (!&ignoreip($ip))) { + &relayalert($ip,$relays{$ip}{cnt},$relays{$ip}{check},$relays{$ip}{mails}); + delete $relays{$ip}; + } + } + } + elsif (($config{DEBUG} >= 1) and $ip and $rtignore{$ip}) { + logfile("debug: RT\_$check\_LIMIT detected from $ip - ignored"); + } + } + return; +} +# end dochecks +############################################################################### +# start getlogfile +sub getlogfile { + my $logfile = shift; + my $lfn = shift; + my $totlines = shift; + my $ino; + my $size; + my $line; + my $count; + + if (!defined($lffd[$lfn])) { + if (&openlogfile($logfile,$lfn)) {return undef} + } + + (undef, $ino, undef, undef, undef, undef, undef, $size, undef) = stat($logfile); + + if ($ino != $lfino[$lfn]) { + logfile("$logfile rotated. Reopening log file"); + if (&openlogfile($logfile,$lfn)) {return undef} + return "reopen"; + } + + if ($size < $lfsize[$lfn]) { + logfile("$logfile has been reset. Reopening log file"); + if (&openlogfile($logfile,$lfn)) {return undef} + return "reopen"; + } + + $lffd[$lfn]->clearerr(); + $line = readline($lffd[$lfn]); + + if ($totlines > ($config{LF_PARSE} * 1000)) { + my $text = "*Error* Log line flooding/looping in $logfile. Reopening log file"; + logfile("$text"); + if ($config{LOGFLOOD_ALERT}) { + my @alert = slurp("/usr/local/csf/tpl/logfloodalert.txt"); + my @message; + foreach my $line (@alert) { + $line =~ s/\[text\]/$text/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + } + if (&openlogfile($logfile,$lfn)) {return undef} + return "reopen"; + } + + chomp $line; + if ($line) { + $lfsize[$lfn] = $size; + return $line; + } + + return undef; +} +# end getlogfile +############################################################################### +# start openlogfile +sub openlogfile { + my $logfile = shift; + my $lfn = shift; + + if (defined($lffd[$lfn])) { + close($lffd[$lfn]); + delete($lffd[$lfn]); + } + + sysopen ($lffd[$lfn], $logfile, O_RDONLY | O_NONBLOCK); + if (!defined($lffd[$lfn])) { + logfile("*Error* Cannot open $logfile"); + return 1; + } + if (seek($lffd[$lfn], 0, 2) == -1) { + logfile("*Error* Cannot seek to end of $logfile"); + return 1; + } + + logfile("Watching $logfile..."); + (undef, $lfino[$lfn], undef, undef, undef, undef, undef, $lfsize[$lfn], undef) = stat($lffd[$lfn]); + + return 0; +} +# end openlogfile +############################################################################### +# start globlog +sub globlog { + my $setting = shift; + if ($config{$setting} =~ /\*|\?|\[/) { + foreach my $log (glob $config{$setting}) { + $globlogs{$setting}{$log} = 1; + $logfiles{$log} = 1; + } + } else { + $globlogs{$setting}{$config{$setting}} = 1; + $logfiles{$config{$setting}} = 1; + } + return; +} +# end globlog +############################################################################### +# start lockhang +sub lockhang { + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","lockhang",$timer)} + $0 = "lfd - (child) checking for lock hang"; + + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die}; + alarm(10); + sysopen (my $COMMANDLOCK, "/var/lib/csf/lock/command.lock", O_RDWR | O_CREAT) or logfile("open: $!"); + flock ($COMMANDLOCK, LOCK_EX) or logfile("lock: $!"); + close ($COMMANDLOCK); + alarm(0); + }; + alarm(0); + if ($@) { + sysopen (my $COMMANDLOCK, "/var/lib/csf/lock/command.lock", O_RDWR | O_CREAT); + flock ($COMMANDLOCK, LOCK_SH); + my $pid = <$COMMANDLOCK>; + chomp $pid; + close ($COMMANDLOCK); + if ($pid == $$) { + logfile("*Hanging Lock* by main lfd process found for /var/lib/csf/lock/command.lock - restarting lfd"); + open (my $LFDOUT, ">", "/var/lib/csf/lfd.restart"); + close ($LFDOUT); + } else { + kill (9, $pid); + logfile("*Hanging Lock* by $pid found for /var/lib/csf/lock/command.lock - terminated"); + } + } + + if ($config{DEBUG} >= 3) {$timer = &timer("stop","lockhang",$timer)} + $0 = "lfd - child closing"; + exit; + } + return; +} +# end lockhang +############################################################################### +# start syslog_init +sub syslog_init { + local $SIG{CHLD} = 'DEFAULT'; + my %syslogusers; + my @entries = slurp("/etc/csf/csf.syslogusers"); + 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} + if ($line =~ /^[a-zA-Z0-9]+([\_\s\-\.]?[a-zA-Z0-9])*$/) {$syslogusers{$line} = 1} + } + + $sysloggid = getgrnam($config{RESTRICT_SYSLOG_GROUP}); + unless ($sysloggid) {&syscommand(__LINE__,"/usr/sbin/groupadd","-r",$config{RESTRICT_SYSLOG_GROUP})} + $sysloggid = getgrnam($config{RESTRICT_SYSLOG_GROUP}); + unless ($sysloggid) { + logfile("RESTRICT_SYSLOG: *Error* Failed to create group: [$config{RESTRICT_SYSLOG_GROUP}], RESTRICT_SYSLOG disabled"); + $config{RESTRICT_SYSLOG} = 0; + return; + } + + my (undef,undef,$gid,$members) = getgrgid($sysloggid); + foreach my $name (split(/\s+/,$members)) {$syslogusers{$name} = 0} + foreach my $name (keys %syslogusers) { + if ($syslogusers{$name} and getpwnam($name) ne "") { + &syscommand(__LINE__,"/usr/sbin/usermod","-a","-G",$config{RESTRICT_SYSLOG_GROUP},$name); + if ($config{DEBUG} >= 1) {logfile("debug: RESTRICT_SYSLOG: User $name added to group $config{RESTRICT_SYSLOG_GROUP}")} + } + } + return; +} +# end syslog_init +############################################################################### +# start syslog_perms +sub syslog_perms { + my $newpid = 1; + my @socketids; + my @sockets; + if (-S "/dev/log") {push @sockets, "/dev/log"} + if (-S "/usr/share/cagefs-skeleton/dev/log") {push @sockets, "/usr/share/cagefs-skeleton/dev/log"} + + if ($syslogpid) { + if (readlink("/proc/$syslogpid/exe") =~ m[^(/sbin/syslog)|(/sbin/rsyslog)|(/usr/sbin/syslog)|(/usr/sbin/rsyslog)]) {$newpid = 0} + } + + if ($newpid) { + opendir (PROCDIR, "/proc"); + while (my $pid = readdir(PROCDIR)) { + if ($pid !~ /^\d+$/) {next} + my $exe = readlink("/proc/$pid/exe"); + if ($exe =~ m[^(/sbin/syslog)|(/sbin/rsyslog)|(/usr/sbin/syslog)|(/usr/sbin/rsyslog)]) { + $syslogpid = $pid; + last; + } + } + closedir (PROCDIR); + } + + if ($syslogpid) { + opendir (DIR, "/proc/$syslogpid/fd/"); + while (my $file = readdir(DIR)) { + if (readlink("/proc/$syslogpid/fd/$file") =~/^socket:\[(\d*)\]$/) {push @socketids,$1} + } + closedir (DIR); + if (@socketids) { + open (my $IN, "<", "/proc/net/unix"); + flock ($IN, LOCK_SH); + while (my $line = <$IN>) { + chomp $line; + my @data = split(/\s+/,$line,8); + foreach my $socket (@socketids) { + if (($socket == $data[6]) and ($data[7] ne "/dev/log") and ($data[7] ne "/usr/share/cagefs-skeleton/dev/log")) {push @sockets,$data[7]} + } + } + close ($IN); + } else { + if ($config{DEBUG} >= 2) {logfile("debug: RESTRICT_SYSLOG: *Error* No additional unix sockets found")} + } + } else { + if ($config{DEBUG} >= 1) {logfile("debug: RESTRICT_SYSLOG: *Error* syslog/rsyslog process not found")} + } + + if (@sockets) { + my $fixme = 0; + foreach my $socket (@sockets) { + if (-S $socket) { + my (undef,undef,$mode,undef,$uid,$gid,undef) = stat($socket); + $mode = sprintf("%04o",$mode & oct("07777")); + if ($gid != $sysloggid or $mode ne "0660") { + $fixme = 1; + last; + } + } + } + if ($fixme) { + chown (-1,$sysloggid,@sockets); + chmod (0660, @sockets); + my $count = 0; + logfile("RESTRICT_SYSLOG: Unix socket permissions reapplied. Reopening log files..."); + foreach my $lgfile (keys %logfiles) { + &openlogfile($lgfile,$count); + $count++; + } + if ($config{DEBUG} >= 1) {logfile("debug: RESTRICT_SYSLOG: Fixed socket ownership/permissions")} + } + } else { + logfile("RESTRICT_SYSLOG: *Error* No matching unix sockets found"); + return; + } + return; +} +# end syslog_perms +############################################################################### +# start block +sub block { + my $ip = shift; + my $ipcount = shift; + my $app = shift; + my $temp = shift; + my $active = shift; + my $reason = shift; + my $ipc = $ipcount; + + my $text = $db{$ip}{text}; + my $apps = $db{$ip}{apps}; + my $domains = $db{$ip}{domains}; + unless ($config{LF_TRIGGER}) {$apps = $app} + + $blockedips{$ip}{block} = 1; + $blockedips{$ip}{apps} .= "$app\,"; + $text =~ s/\n+/\n/g; + + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","block",$timer)} + my %logapps; + my $apptext; + foreach my $app (split(/ /,$apps)) {$logapps{$app} = 1} + foreach my $key (keys %logapps) { + if ($apptext eq "") {$apptext = $key} else {$apptext .= ",$key"} + } + my $perm = 1; + if ($temp > 1) {$perm = 0} + + $0 = "lfd - (child) blocking $ip"; + + my $tip = iplookup($ip); + my $failtext = "Login failure/trigger from"; + if (keys %logapps == 1) {$failtext = $reason} + + my $cfid; + if ($config{CF_ENABLE} and $cfblocks{$active}) { + $perm = 0; + $temp = $config{CF_TEMP}; + &cloudflare("deny",$ip,$config{CF_BLOCK},$domains); + $cfid = " (CF_ENABLE)"; + } + if ($config{PT_SSHDKILL} and $logapps{sshd}) {ConfigServer::KillSSH::find($ip,$ports{sshd})} + + my $blocked = 0; + if ($config{LF_SELECT} and !$config{LF_TRIGGER}) { + if (&ipblock($perm,"($apptext) $failtext $tip: $ipcount in the last $config{LF_INTERVAL} secs$cfid",$ip,$ports{$app},"in",$temp,0,$text,$active)) { + if ($config{DEBUG} >= 1) {logfile("debug: $ip already blocked")} + } else {$blocked = 1} + } else { + if (&ipblock($perm,"($apptext) $failtext $tip: $ipcount in the last $config{LF_INTERVAL} secs$cfid",$ip,"","inout",$temp,0,$text,$active)) { + if ($config{DEBUG} >= 1) {logfile("debug: $ip already blocked")} + } else {$blocked = 1} + } + + if ($blocked) { + if ($config{LF_EMAIL_ALERT} and ($perm or (!$perm and $config{LF_TEMP_EMAIL_ALERT}))) { + $0 = "lfd - (child) sending alert email for $ip"; + + my @alert = slurp("/usr/local/csf/tpl/alert.txt"); + my $block = "Temporary Block for $temp seconds [$active]"; + if ($perm) {$block = "Permanent Block [$active]"} + + my $allowip = &allowip($ip); + if ($allowip == 1) {$block .= " (IP match in csf.allow, block may not work)"} + if ($allowip == 2) {$block .= " (IP match in GLOBAL_ALLOW, block may not work)"} + + my @message; + foreach my $line (@alert) { + $line =~ s/\[ip\]/$tip/ig; + $line =~ s/\[ipcount\]/$ipcount \($apptext\)/ig; + $line =~ s/\[iptick\]/$config{LF_INTERVAL}/ig; + $line =~ s/\[block\]/$block/ig; + $line =~ s/\[text\]/$text/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + + if ($config{DEBUG} >= 1) {logfile("debug: alert email sent for $ip")} + } + + if ($config{X_ARF}) { + $0 = "lfd - (child) sending X-ARF email for $ip"; + + my @alert = slurp("/usr/local/csf/tpl/x-arf.txt"); + my @message; + my $rfc3339 = strftime('%Y-%m-%dT%H:%M:%S%z',localtime); + my $boundary = time; + my $reportedfrom = "root\@$hostname"; + if ($config{X_ARF_TO}) {$config{LF_ALERT_TO} = $config{X_ARF_TO}} + if ($config{X_ARF_FROM}) {$config{LF_ALERT_FROM} = $config{X_ARF_FROM}; $reportedfrom = $config{X_ARF_FROM}} + my $iptype = "ipv".checkip(\$ip); + my $abuseto = ""; + my $abusemsg = ""; + + if ($abuseip) { + ($abuseto, $abusemsg) = abuseip($ip); + if ($abuseto eq "") { + $abusemsg = ""; + } + elsif ($config{X_ARF_ABUSE} and $config{X_ARF_FROM}) { + if ($config{LF_ALERT_TO}) { + $config{LF_ALERT_TO} .= ",".$abuseto; + } else { + $config{LF_ALERT_TO} = "root,".$abuseto; + } + } + } + + foreach my $line (@alert) { + $line =~ s/\[ip\]/$ip/ig; + $line =~ s/\[abuseip\]/$abusemsg/ig; + $line =~ s/\[iptype\]/$iptype/ig; + $line =~ s/\[tip\]/$tip/ig; + $line =~ s/\[ipcount\]/$ipc/ig; + $line =~ s/\[iptick\]/$config{LF_INTERVAL}/ig; + $line =~ s/\[service\]/$app/ig; + $line =~ s/\[csfversion\]/$version/ig; + $line =~ s/\[reportedfrom\]/$reportedfrom/ig; + $line =~ s/\[reportedid\]/$boundary\@$hostname/ig; + $line =~ s/\[boundary\]/$boundary/ig; + $line =~ s/\[text\]/$text/ig; + $line =~ s/\[RFC3339\]/$rfc3339/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay($config{LF_ALERT_TO}, $config{LF_ALERT_FROM}, @message); + + if ($config{DEBUG} >= 1) {logfile("debug: X-ARF email sent for $ip")} + } + } + + if ($config{DEBUG} >= 3) {$timer = &timer("stop","block",$timer)} + $0 = "lfd - child closing"; + exit; + } + return; +} +# end block +############################################################################### +# start blockaccount +sub blockaccount { + my $ipa = shift; + my @ips = @$ipa; + my $account = shift; + my $ipcount = shift; + my $app = shift; + my $text = shift; + my $temp = shift; + my $trigger = shift; + + foreach my $ip (@ips) { + $blockedips{$ip}{block} = 1; + $blockedips{$ip}{apps} .= "$app\,"; + } + + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","blockaccount",$timer)} + my $perm = 1; + if ($temp > 1) {$perm = 0} + + $text .= "\nIP Addresses Blocked:\n\n"; + foreach my $ip (@ips) { + $0 = "lfd - (child) blocking $ip"; + + if ($config{PT_SSHDKILL} and $app eq "sshd") {ConfigServer::KillSSH::find($ip,$ports{sshd})} + + my $tip = iplookup($ip); + if ($config{LF_SELECT} and !$config{LF_TRIGGER}) { + if (&ipblock($perm,"$tip, $ipcount distributed $app attacks on account [$account] in the last $config{LF_INTERVAL} secs",$ip,$ports{$app},"in",$temp,0,$text,"LF_DISTATTACK")) { + if ($config{DEBUG} >= 1) {logfile("debug: $ip already blocked")} + } + } else { + if (&ipblock($perm,"$tip, $ipcount distributed $app attacks on account [$account] in the last $config{LF_INTERVAL} secs",$ip,"","inout",$temp,0,$text,"LF_DISTATTACK")) { + if ($config{DEBUG} >= 1) {logfile("debug: $ip already blocked")} + } + } + $text .= "$tip\n"; + if ($cxsreputation) { + ConfigServer::cxs::Rreport($trigger,$ip,"$ipcount distributed $trigger attacks in the last $config{LF_INTERVAL} secs",$trigger); + } + } + + if ($config{LF_EMAIL_ALERT}) { + my @alert = slurp("/usr/local/csf/tpl/alert.txt"); + my $block = "Temporary Block for $temp seconds [LF_DISTATTACK]"; + if ($perm) {$block = "Permanent Block [LF_DISTATTACK]"} + + my @message; + foreach my $line (@alert) { + $line =~ s/\[ip\]/distributed $app attack on account [$account]/ig; + $line =~ s/\[ipcount\]/$ipcount/ig; + $line =~ s/\[iptick\]/$config{LF_INTERVAL}/ig; + $line =~ s/\[block\]/$block/ig; + $line =~ s/\[text\]/$text/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + } + + if ($config{DEBUG} >= 3) {$timer = &timer("stop","blockaccount",$timer)} + $0 = "lfd - child closing"; + exit; + } + return; +} +# end blockaccount +############################################################################### +# start blockdistftp +sub blockdistftp { + my $ipa = shift; + my @ips = @$ipa; + my $account = shift; + my $ipcount = shift; + my $text = shift; + my $temp = shift; + + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","blockdistftp",$timer)} + my $perm = 1; + if ($temp > 1) {$perm = 0} + + $text .= "\nIP Addresses Blocked:\n\n"; + foreach my $ip (@ips) { + $0 = "lfd - (child) blocking $ip"; + my $tip = iplookup($ip); + if (&ipblock($perm,"$tip, $ipcount distributed FTP Logins on account [$account] in the last $config{LF_DIST_INTERVAL} secs",$ip,"","inout",$temp,0,$text,"LF_DISTFTP")) { + if ($config{DEBUG} >= 1) {logfile("debug: $ip already blocked")} + } + $text .= "$tip\n"; + } + + if ($config{LF_DISTFTP_ALERT}) { + my @alert = slurp("/usr/local/csf/tpl/alert.txt"); + my $block = "Temporary Block for $temp seconds [LF_DISTFTP]"; + if ($perm) {$block = "Permanent Block [LF_DISTFTP]"} + + my @message; + foreach my $line (@alert) { + $line =~ s/\[ip\]/distributed FTP Logins on account [$account]/ig; + $line =~ s/\[ipcount\]/$ipcount/ig; + $line =~ s/\[iptick\]/$config{LF_INTERVAL}/ig; + $line =~ s/\[block\]/$block/ig; + $line =~ s/\[text\]/$text/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + } + + if ($config{LF_DIST_ACTION} and -e $config{LF_DIST_ACTION} and -x $config{LF_DIST_ACTION}) { + $0 = "lfd - (child) running LF_DIST_ACTION"; + system($config{LF_DIST_ACTION},"LF_DISTFTP",$account,$text); + } + + if ($config{DEBUG} >= 3) {$timer = &timer("stop","blockdistftp",$timer)} + $0 = "lfd - child closing"; + exit; + } + return; +} +# end blockdistftp +############################################################################### +# start blockdistsmtp +sub blockdistsmtp { + my $ipa = shift; + my @ips = @$ipa; + my $account = shift; + my $ipcount = shift; + my $text = shift; + my $temp = shift; + + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","blockdistsmtp",$timer)} + my $perm = 1; + if ($temp > 1) {$perm = 0} + + $text .= "\nIP Addresses Blocked:\n\n"; + foreach my $ip (@ips) { + $0 = "lfd - (child) blocking $ip"; + my $tip = iplookup($ip); + if (&ipblock($perm,"$tip, $ipcount distributed SMTP Logins on account [$account] in the last $config{LF_DIST_INTERVAL} secs",$ip,"","inout",$temp,0,$text,"LF_DISTSMTP")) { + if ($config{DEBUG} >= 1) {logfile("debug: $ip already blocked")} + } + $text .= "$tip\n"; + } + + if ($config{LF_DISTSMTP_ALERT}) { + my @alert = slurp("/usr/local/csf/tpl/alert.txt"); + my $block = "Temporary Block for $temp seconds [LF_DISTSMTP]"; + if ($perm) {$block = "Permanent Block [LF_DISTSMTP]"} + + my @message; + foreach my $line (@alert) { + $line =~ s/\[ip\]/distributed SMTP Logins on account [$account]/ig; + $line =~ s/\[ipcount\]/$ipcount/ig; + $line =~ s/\[iptick\]/$config{LF_INTERVAL}/ig; + $line =~ s/\[block\]/$block/ig; + $line =~ s/\[text\]/$text/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + } + + if ($config{LF_DIST_ACTION} and -e $config{LF_DIST_ACTION} and -x $config{LF_DIST_ACTION}) { + $0 = "lfd - (child) running LF_DIST_ACTION"; + system($config{LF_DIST_ACTION},"LF_DISTSMTP",$account,$text); + } + + if ($config{DEBUG} >= 3) {$timer = &timer("stop","blockdistsmtp",$timer)} + $0 = "lfd - child closing"; + exit; + } + return; +} +# end blockdistsmtp +############################################################################### +# start disable404 +sub disable404 { + my $ip = shift; + my $text = shift; + + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","disable404",$timer)} + + my $tip = iplookup($ip); + my $perm = 1; + if ($config{LF_APACHE_404_PERM} > 1) {$perm = 0} + if (&ipblock($perm,"$tip, more than $config{LF_APACHE_404} Apache 404 hits in the last $config{LF_INTERVAL} secs",$ip,$ports{mod_security},"in",$config{LF_APACHE_404_PERM},0,"","LF_APACHE_404")) { + if ($config{DEBUG} >= 1) {logfile("debug: $ip already blocked")} + } else { + if ($config{LT_EMAIL_ALERT}) { + $0 = "lfd - (child) sending alert email for $ip"; + + my @alert = slurp("/usr/local/csf/tpl/alert.txt"); + my $block = "Temporary Block for $config{LF_APACHE_404_PERM} seconds [LF_APACHE_404]"; + if ($perm) {$block = "Permanent Block [LF_APACHE_404]"} + my @message; + foreach my $line (@alert) { + $line =~ s/\[ip\]/$tip/ig; + $line =~ s/\[ipcount\]/$config{LF_APACHE_404}/ig; + $line =~ s/\[iptick\]/$config{LF_INTERVAL}/ig; + $line =~ s/\[block\]/$block/ig; + $line =~ s/\[text\]/$text/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + } + } + + if ($config{DEBUG} >= 3) {$timer = &timer("stop","disable404",$timer)} + $0 = "lfd - child closing"; + exit; + } + return; +} +# end disable404 +############################################################################### +# start disable403 +sub disable403 { + my $ip = shift; + my $text = shift; + + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","disable403",$timer)} + + my $tip = iplookup($ip); + my $perm = 1; + if ($config{LF_APACHE_403_PERM} > 1) {$perm = 0} + if (&ipblock($perm,"$tip, more than $config{LF_APACHE_403} Apache 403 hits in the last $config{LF_INTERVAL} secs",$ip,$ports{mod_security},"in",$config{LF_APACHE_403_PERM},0,"","LF_APACHE_403")) { + if ($config{DEBUG} >= 1) {logfile("debug: $ip already blocked")} + } else { + if ($config{LT_EMAIL_ALERT}) { + $0 = "lfd - (child) sending alert email for $ip"; + + my @alert = slurp("/usr/local/csf/tpl/alert.txt"); + my $block = "Temporary Block for $config{LF_APACHE_403_PERM} seconds [LF_APACHE_403]"; + if ($perm) {$block = "Permanent Block [LF_APACHE_403]"} + my @message; + foreach my $line (@alert) { + $line =~ s/\[ip\]/$tip/ig; + $line =~ s/\[ipcount\]/$config{LF_APACHE_403}/ig; + $line =~ s/\[iptick\]/$config{LF_INTERVAL}/ig; + $line =~ s/\[block\]/$block/ig; + $line =~ s/\[text\]/$text/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + } + } + + if ($config{DEBUG} >= 3) {$timer = &timer("stop","disable403",$timer)} + $0 = "lfd - child closing"; + exit; + } + return; +} +# end disable403 +############################################################################### +# start disable401 +sub disable401 { + my $ip = shift; + my $text = shift; + + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","disable401",$timer)} + + my $tip = iplookup($ip); + my $perm = 1; + if ($config{LF_APACHE_401_PERM} > 1) {$perm = 0} + if (&ipblock($perm,"$tip, more than $config{LF_APACHE_401} Apache 401 hits in the last $config{LF_INTERVAL} secs",$ip,$ports{mod_security},"in",$config{LF_APACHE_401_PERM},0,"","LF_APACHE_401")) { + if ($config{DEBUG} >= 1) {logfile("debug: $ip already blocked")} + } else { + if ($config{LT_EMAIL_ALERT}) { + $0 = "lfd - (child) sending alert email for $ip"; + + my @alert = slurp("/usr/local/csf/tpl/alert.txt"); + my $block = "Temporary Block for $config{LF_APACHE_401_PERM} seconds [LF_APACHE_401]"; + if ($perm) {$block = "Permanent Block [LF_APACHE_401]"} + my @message; + foreach my $line (@alert) { + $line =~ s/\[ip\]/$tip/ig; + $line =~ s/\[ipcount\]/$config{LF_APACHE_401}/ig; + $line =~ s/\[iptick\]/$config{LF_INTERVAL}/ig; + $line =~ s/\[block\]/$block/ig; + $line =~ s/\[text\]/$text/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + } + } + + if ($config{DEBUG} >= 3) {$timer = &timer("stop","disable401",$timer)} + $0 = "lfd - child closing"; + exit; + } + return; +} +# end disable401 +############################################################################### +# start logindisable +sub logindisable { + my $app = shift; + my $ip = shift; + my $logins = shift; + my $account = shift; + my $trigger = "LT_".uc($app); + + my $port = "110"; + my $sport = "995"; + if ($app eq "imapd") {$port = "143"; $sport = "993"} + + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","logindisable",$timer)} + my $flush = (3600-$logintimeout{$app}); + + my $tip = iplookup($ip); + if ($config{LT_SKIPPERMBLOCK}) {$config{LF_PERMBLOCK} = 0} + if (&ipblock(0,"$app - $logins logins in $logintimeout{$app} secs from $tip for $account exceeds $loginproto{$app}/hour",$ip,"$port,$sport","in",$flush,0,"",$trigger)) { + if ($config{DEBUG} >= 1) {logfile("debug: $ip already blocked")} + } else { + if ($config{LT_EMAIL_ALERT}) { + $0 = "lfd - (child) sending alert email for $account"; + + my @alert = slurp("/usr/local/csf/tpl/tracking.txt"); + my @message; + foreach my $line (@alert) { + $line =~ s/\[ip\]/$tip/ig; + $line =~ s/\[app\]/$app/ig; + $line =~ s/\[logins\]/$logins/ig; + $line =~ s/\[account\]/$account/ig; + $line =~ s/\[timeout\]/$logintimeout{$app}/ig; + $line =~ s/\[flush\]/$flush/ig; + $line =~ s/\[rate\]/$loginproto{$app}/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + + logfile("tracking email sent for $account"); + } + } + + if ($config{DEBUG} >= 3) {$timer = &timer("stop","logindisable",$timer)} + $0 = "lfd - child closing"; + exit; + } + return; +} +# end logindisable +############################################################################### +# start portscans +sub portscans { + my $ip = shift; + my $count = shift; + my $blocks = shift; + + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","portscans",$timer)} + + my $tip = iplookup($ip); + if (&ipblock($config{PS_PERMANENT},"*Port Scan* detected from $tip. $count hits in the last $pstimeout seconds",$ip,"","in",$config{PS_BLOCK_TIME},0,$blocks,"PS_LIMIT")) { + if ($config{DEBUG} >= 1) {logfile("debug: $ip already blocked")} + } else { + if ($config{PS_EMAIL_ALERT}) { + $0 = "lfd - (child) sending alert email for $ip"; + + my @alert = slurp("/usr/local/csf/tpl/portscan.txt"); + my $block = "Temporary Block for $config{PS_BLOCK_TIME} seconds [PS_LIMIT]"; + if ($config{PS_PERMANENT}) {$block = "Permanent Block [PS_LIMIT]"} + + my $allowip = &allowip($ip); + if ($allowip == 1) {$block .= " (IP match in csf.allow, block may not work)"} + if ($allowip == 2) {$block .= " (IP match in GLOBAL_ALLOW, block may not work)"} + + my @message; + foreach my $line (@alert) { + $line =~ s/\[ip\]/$tip/ig; + $line =~ s/\[count\]/$count/ig; + $line =~ s/\[blocks\]/$blocks/ig; + $line =~ s/\[temp\]/$block/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + if ($config{DEBUG} >= 1) {logfile("debug: alert email sent for $ip")} + + if ($config{X_ARF}) { + $0 = "lfd - (child) sending X-ARF email for $ip"; + + my @alert = slurp("/usr/local/csf/tpl/x-arf.txt"); + my @message; + my $rfc3339 = strftime('%Y-%m-%dT%H:%M:%S%z',localtime); + my $boundary = time; + my $reportedfrom = "root\@$hostname"; + if ($config{X_ARF_TO}) {$config{LF_ALERT_TO} = $config{X_ARF_TO}} + if ($config{X_ARF_FROM}) {$config{LF_ALERT_FROM} = $config{X_ARF_FROM}; $reportedfrom = $config{X_ARF_FROM}} + my $iptype = "ipv".checkip(\$ip); + + my $abuseto = ""; + my $abusemsg = ""; + if ($iptype eq "ipv4" and $abuseip) { + ($abuseto, $abusemsg) = abuseip($ip); + if ($abuseto eq "") { + $abusemsg = ""; + } + elsif ($config{X_ARF_ABUSE} and $config{X_ARF_FROM}) { + if ($config{LF_ALERT_TO}) { + $config{LF_ALERT_TO} .= ",".$abuseto; + } else { + $config{LF_ALERT_TO} = "root,".$abuseto; + } + } + } + + foreach my $line (@alert) { + $line =~ s/\[ip\]/$ip/ig; + $line =~ s/\[abuseip\]/$abusemsg/ig; + $line =~ s/\[iptype\]/$iptype/ig; + $line =~ s/\[tip\]/$tip/ig; + $line =~ s/\[ipcount\]/$count/ig; + $line =~ s/\[iptick\]/$config{LF_INTERVAL}/ig; + $line =~ s/\[service\]/firewall/ig; + $line =~ s/\[csfversion\]/$version/ig; + $line =~ s/\[reportedfrom\]/$reportedfrom/ig; + $line =~ s/\[reportedid\]/$boundary\@$hostname/ig; + $line =~ s/\[boundary\]/$boundary/ig; + $line =~ s/\[text\]/$blocks/ig; + $line =~ s/\[RFC3339\]/$rfc3339/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay($config{LF_ALERT_TO}, $config{LF_ALERT_FROM}, @message); + + if ($config{DEBUG} >= 1) {logfile("debug: X-ARF email sent for $ip")} + } + } + } + + if ($config{DEBUG} >= 3) {$timer = &timer("stop","portscans",$timer)} + $0 = "lfd - child closing"; + exit; + } + return; +} +# end portscans +############################################################################### +# start uidscans +sub uidscans { + my $uid = shift; + my $count = shift; + my $blocks = shift; + + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","uidscans",$timer)} + + $0 = "lfd - (child) sending alert email for UID $uid"; + + my $user = getpwuid($uid); + if ($user eq "") {$user = $uid} + logfile("*UID Tracking* $count blocks for UID $uid ($user)"); + + my @alert = slurp("/usr/local/csf/tpl/uidscan.txt"); + my @message; + foreach my $line (@alert) { + $line =~ s/\[uid\]/$uid ($user)/ig; + $line =~ s/\[count\]/$count/ig; + $line =~ s/\[ports\]/$blocks/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + if ($config{DEBUG} >= 1) {logfile("debug: alert email sent for UID $uid ($user)")} + + if ($config{DEBUG} >= 3) {$timer = &timer("stop","uidscans",$timer)} + $0 = "lfd - child closing"; + exit; + } + return; +} +# end uidscans +############################################################################### +# start csfrestart +sub csfrestart { + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","csfrestart",$timer)} + $0 = "lfd - (re)starting csf..."; + + logfile("csf (re)start requested - running *csf startup*..."); + &syscommand(__LINE__,"/usr/sbin/csf","-sf"); + logfile("csf (re)start completed"); + + if ($config{DEBUG} >= 3) {$timer = &timer("stop","csfrestart",$timer)} + $0 = "lfd - processing"; + return; +} +# end csfrestart +############################################################################### +# start lfdrestart +sub lfdrestart { + $SIG{INT} = 'IGNORE'; + $SIG{TERM} = 'IGNORE'; + $SIG{CHLD} = 'IGNORE'; + $0 = "lfd - stopping"; + + logfile("daemon restart requested"); + + close($PIDFILE); + unlink $pidfile; + + $SIG{HUP} = 'IGNORE'; + kill HUP => -$$; + exec("/usr/sbin/lfd"); + + exit 0; +} +# end lfdrestart +############################################################################### +# start csfcheck +sub csfcheck { + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","csfcheck",$timer)} + + my @ipdata = &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -L LOCALINPUT -n"); + chomp @ipdata; + if ($ipdata[0] =~ /# Warning: iptables-legacy tables present/) {shift @ipdata} + + if ($ipdata[0] =~ /xtables lock/) { + logfile("*Error*: Unable to check csf due to xtables lock, enable WAITLOCK in csf.conf"); + } else { + if ($ipdata[0] !~ /^Chain LOCALINPUT/) { + $0 = "lfd - starting csf..."; + logfile("iptables appears to have been flushed - running *csf startup*..."); + &syscommand(__LINE__,"/usr/sbin/csf","-sf"); + logfile("csf startup completed"); + $0 = "lfd - processing"; + } + + if ($config{INTERWORX}) { + &syscommand(__LINE__,"cp -af /etc/csf/apf_stub.pl /etc/apf/apf"); + &syscommand(__LINE__,"chmod 750 /etc/apf/apf"); + } + + if (-e "/usr/local/cpanel/version") { + my $skip; + + if (-e "/var/run/upcp.pid") { + open (my $IN, "<", "/var/run/upcp.pid"); + flock ($IN, LOCK_SH); + my $upcp = <$IN>; + close ($IN); + chomp ($upcp); + + if (-d "/proc/$upcp") { + if ($config{DEBUG} >= 1) {logfile("cPanel upcp is running, skipped version check")} + $skip = 1; + } + } + + if (-e "/var/lib/csf/cpanel.new") { + my $mtime = (stat("/var/lib/csf/cpanel.new"))[9]; + if (time - $mtime < 3600) {$skip = 1} + } + + unless ($skip) { + my $current; + foreach my $line (slurp("/usr/local/cpanel/version")) { + $line =~ s/$cleanreg//g; + if ($line =~ /\d/) {$current = $line} + } + if ($current ne $cpconfig{version}) { + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + local $SIG{CHLD} = 'DEFAULT'; + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","cpanelcheck",$timer)} + $0 = "lfd - (child) cPanel upgraded..."; + + my $lockstr = "LF_CSF"; + sysopen (my $THISLOCK, "/var/lib/csf/lock/$lockstr.lock", O_RDWR | O_CREAT) or &childcleanup("*Error* Unable to open /var/lib/csf/lock/$lockstr.lock"); + flock ($THISLOCK, LOCK_EX | LOCK_NB) or &childcleanup("*Lock Error* [$lockstr] still active - section skipped"); + print $THISLOCK time; + + logfile("cPanel upgrade detected, restarting ConfigServer services..."); + + if (-e "/var/lib/csf/cpanel.new") {unlink "/var/lib/csf/cpanel.new"} + open (my $CPANELNEW, ">", "/var/lib/csf/cpanel.new"); + flock ($CPANELNEW, LOCK_EX); + print $CPANELNEW time; + close ($CPANELNEW); + + if (-e "/etc/cxs/cxs.pl") { + logfile("cPanel upgrade detected, restarting cxs Watch (if running)"); + open (my $OUT, ">", "/etc/cxs/newusers/cxswatchrestart"); + close ($OUT); + logfile("cPanel upgrade detected, restarting cxs pure-uploadscript (if running)"); + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die}; + alarm(30); + &syscommand(__LINE__,"/sbin/service","pure-uploadscript","restart"); + &syscommand(__LINE__,"/scripts/restartsrv_ftpserver"); + alarm(0); + }; + alarm(0); + } + + if (-e "/etc/osm/osmd.pl") { + logfile("cPanel upgrade detected, restarting osmd"); + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die}; + alarm(30); + &syscommand(__LINE__,"/sbin/service","osmd","restart"); + alarm(0); + }; + alarm(0); + } + + if (-e "/etc/exim_outgoing.conf" and (-e "/etc/init.d/MailScanner" or -e "/etc/systemd/system/multi-user.target.wants/MailScanner.service")) { + logfile("cPanel upgrade detected, restarting MailScanner"); + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die}; + alarm(30); + &syscommand(__LINE__,"/sbin/service","MailScanner","restart"); + alarm(0); + }; + alarm(0); + } + + logfile("cPanel upgrade detected, restarting lfd"); + open (my $LFDOUT, ">", "/var/lib/csf/lfd.restart"); + close ($LFDOUT); + + close ($THISLOCK ); + if ($config{DEBUG} >= 3) {$timer = &timer("stop","cpanelcheck",$timer)} + $0 = "lfd - child closing"; + exit; + } + } + } + } + } + + if ($config{DEBUG} >= 3) {$timer = &timer("stop","csfcheck",$timer)} + return; +} +# end csfcheck +############################################################################### +# start loadcheck +sub loadcheck { + if (-e "/var/lib/csf/csf.load") { + open (my $IN, "<", "/var/lib/csf/csf.load"); + flock ($IN, LOCK_SH); + my $start = <$IN>; + close ($IN); + chomp $start; + if (time - $start < $config{PT_LOAD_SKIP}) { + return; + } else { + unlink ("/var/lib/csf/csf.load"); + } + } + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","loadcheck",$timer)} + $0 = "lfd - (child) checking load..."; + + my $lockstr = "PT_LOAD"; + sysopen (my $THISLOCK, "/var/lib/csf/lock/$lockstr.lock", O_RDWR | O_CREAT) or &childcleanup("*Error* Unable to open /var/lib/csf/lock/$lockstr.lock"); + flock ($THISLOCK, LOCK_EX | LOCK_NB) or &childcleanup("*Lock Error* [$lockstr] still active - section skipped"); + print $THISLOCK time; + + open (my $IN, "<", "/proc/loadavg"); + flock ($IN, LOCK_SH); + my $loadavg = <$IN>; + close ($IN); + chomp $loadavg; + my @load = split(/\s+/,$loadavg); + + my $reportload = $load[1]; + if ($config{PT_LOAD_AVG} == 1) {$reportload = $load[0]} + elsif ($config{PT_LOAD_AVG} == 15) {$reportload = $load[2]} + else {$config{PT_LOAD_AVG} = 5} + + if ($reportload >= $config{PT_LOAD_LEVEL}) { + logfile("*LOAD* $config{PT_LOAD_AVG} minute load average is $reportload, threshold is $config{PT_LOAD_LEVEL} - email sent"); + sysopen (my $LOAD, "/var/lib/csf/csf.load", O_WRONLY | O_CREAT) or &childcleanup(__LINE__,"*Error* Cannot write to file: $!"); + flock ($LOAD, LOCK_EX); + seek ($LOAD, 0, 0); + truncate ($LOAD, 0); + print $LOAD time; + close ($LOAD); + + if ($config{PT_LOAD_ACTION} and -e "$config{PT_LOAD_ACTION}" and -x "$config{PT_LOAD_ACTION}") { + $SIG{CHLD} = 'IGNORE'; + unless (defined ($ptchildpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + unless ($ptchildpid) { + system($config{PT_LOAD_ACTION}); + exit; + } + } + + my @proclist; + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die}; + alarm(15); + @proclist = &syscommand(__LINE__,$config{PS},"axuf"); + alarm(0); + }; + alarm(0); + if ($@) {push @proclist, "Unable to obtain process output within 15 seconds - Timed out"} + + my @vmstat; + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die}; + alarm(10); + @vmstat = &syscommand(__LINE__,$config{VMSTAT}); + alarm(0); + }; + alarm(0); + if ($@) {push @vmstat, "Unable to obtain vmstat output within 10 seconds - Timed out"} + + my @netstat; + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die}; + alarm(10); + @netstat = &syscommand(__LINE__,$config{NETSTAT}, "-autpn"); + alarm(0); + }; + alarm(0); + if ($@) {push @netstat, "Unable to obtain netstat output within 10 seconds - Timed out"} + + my $url = $config{PT_APACHESTATUS}; + my ($status, $apache) = $urlget->urlget($url); + if ($status) {$apache = "Unable to retrieve Apache Server Status [$url] - $apache"} + + my @alert = slurp("/usr/local/csf/tpl/loadalert.txt"); + my $boundary = "csf".time; + my @message; + foreach my $line (@alert) { + $line =~ s/\[loadavg1\]/$load[0]/ig; + $line =~ s/\[loadavg5\]/$load[1]/ig; + $line =~ s/\[loadavg15\]/$load[2]/ig; + $line =~ s/\[loadavg\]/$config{PT_LOAD_AVG}/ig; + $line =~ s/\[reportload\]/$reportload/ig; + $line =~ s/\[totprocs\]/$load[3]/ig; + $line =~ s/\[processlist\]/@proclist/ig; + $line =~ s/\[vmstat\]/@vmstat/ig; + $line =~ s/\[netstat\]/@netstat/ig; + $line =~ s/\[apache\]/$apache/ig; + $line =~ s/\[boundary\]/$boundary/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + } + + close ($THISLOCK ); + if ($config{DEBUG} >= 3) {$timer = &timer("stop","loadcheck",$timer)} + $0 = "lfd - child closing"; + exit; + } + return; +} +# end loadcheck +############################################################################### +# start denycheck +sub denycheck { + my $ip = shift; + my $port = shift; + my $perm = shift; + my $ipstring = quotemeta($ip); + my $skip = 0; + + my @deny = slurp("/etc/csf/csf.deny"); + foreach my $line (@deny) { + if ($line =~ /^Include\s*(.*)$/) { + my @incfile = slurp($1); + push @deny,@incfile; + } + } + my $denymatches = scalar(grep {$_ =~ /^$ipstring\b/i} @deny); + if ($config{LF_REPEATBLOCK} and $denymatches < $config{LF_REPEATBLOCK}) {$denymatches = 0} + unless ($denymatches == 0) {$skip = 1} + + open (my $IN, "<", "/var/lib/csf/csf.tempban"); + flock ($IN, LOCK_SH); + @deny = <$IN>; + close ($IN); + chomp @deny; + if (grep {$_ =~ /^\d+\|$ipstring\|$port\|/i} @deny) { + unless ($perm) {$skip = 1} + } + + return $skip; +} +# end denycheck +############################################################################### +# start queuecheck +sub queuecheck { + if (-e "/var/lib/csf/csf.queue") { + open (my $IN, "<", "/var/lib/csf/csf.queue"); + flock ($IN, LOCK_SH); + my $start = <$IN>; + close ($IN); + chomp $start; + if (time - $start < $config{LF_FLUSH}) { + return; + } else { + unlink ("/var/lib/csf/csf.queue"); + } + } + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","queuecheck",$timer)} + $0 = "lfd - (child) checking mail queue..."; + + my $lockstr = "LF_QUEUE_INTERVAL"; + sysopen (my $THISLOCK, "/var/lib/csf/lock/$lockstr.lock", O_RDWR | O_CREAT) or &childcleanup("*Error* Unable to open /var/lib/csf/lock/$lockstr.lock"); + flock ($THISLOCK, LOCK_EX | LOCK_NB) or &childcleanup("*Lock Error* [$lockstr] still active - section skipped"); + print $THISLOCK time; + + my $queue; + my $msqueue; + my $timeout = ""; + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die}; + alarm(30); + $queue = (&syscommand(__LINE__,"/usr/sbin/exim","-bpc"))[0]; + alarm(0); + }; + alarm(0); + if ($@) {$timeout = "Unable to obtain exim queue length within 30 seconds - Timed out"} + chomp $queue; + + if (-e "/etc/exim_outgoing.conf") { + $msqueue = $queue; + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die}; + alarm(30); + $queue = (&syscommand(__LINE__,"/usr/sbin/exim","-C","/etc/exim_outgoing.conf","-bpc"))[0]; + alarm(0); + }; + alarm(0); + if ($@) {$timeout = "Unable to obtain exim_outgoing.conf queue length within 30 seconds - Timed out"} + chomp $queue; + } + + if (($queue > $config{LF_QUEUE_ALERT}) or ($msqueue > $config{LF_QUEUE_ALERT}) or ($timeout ne "")) { + my $report = "The exim delivery queue size is $queue"; + if ($msqueue) {$report .= ", the MailScanner pending queue size is $msqueue"} + if ($timeout) {$report = $timeout} + logfile("*Email Queue* $report"); + + sysopen (my $QUEUE, "/var/lib/csf/csf.queue", O_WRONLY | O_CREAT) or &childcleanup(__LINE__,"*Error* Cannot write to file: $!"); + flock ($QUEUE, LOCK_EX); + seek ($QUEUE, 0, 0); + truncate ($QUEUE, 0); + print $QUEUE time; + close ($QUEUE); + + my @alert = slurp("/usr/local/csf/tpl/queuealert.txt"); + my @message; + foreach my $line (@alert) { + $line =~ s/\[text\]/$report/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + } + + close ($THISLOCK ); + if ($config{DEBUG} >= 3) {$timer = &timer("stop","queuecheck",$timer)} + $0 = "lfd - child closing"; + exit; + } + return; +} +# end queuecheck +############################################################################### +# start modsecipdbcheck +sub modsecipdbcheck { + if (-e "/var/lib/csf/csf.modsecipdbcheck") { + open (my $IN, "<", "/var/lib/csf/csf.modsecipdbcheck"); + flock ($IN, LOCK_SH); + my $start = <$IN>; + close ($IN); + chomp $start; + if (time - $start < $config{LF_FLUSH}) { + return; + } else { + unlink ("/var/lib/csf/csf.modsecipdbcheck"); + } + } + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","modsecipdbcheck",$timer)} + $0 = "lfd - (child) checking modsec ip db..."; + + my $lockstr = "LF_MODSECIPDB_ALERT"; + sysopen (my $THISLOCK, "/var/lib/csf/lock/$lockstr.lock", O_RDWR | O_CREAT) or &childcleanup("*Error* Unable to open /var/lib/csf/lock/$lockstr.lock"); + flock ($THISLOCK, LOCK_EX | LOCK_NB) or &childcleanup("*Lock Error* [$lockstr] still active - section skipped"); + print $THISLOCK time; + + my $size = (stat $config{LF_MODSECIPDB_FILE})[7]/(1024*1024*1024); + + if ($size > $config{LF_MODSECIPDB_ALERT}) { + $size = sprintf("%.2f", $size); + my $report = "ModSecurity persistent IP database ($config{LF_MODSECIPDB_FILE}) size is ${size}GB"; + + sysopen (my $QUEUE, "/var/lib/csf/csf.modsecipdbcheck", O_WRONLY | O_CREAT) or &childcleanup(__LINE__,"*Error* Cannot write to file: $!"); + flock ($QUEUE, LOCK_EX); + seek ($QUEUE, 0, 0); + truncate ($QUEUE, 0); + print $QUEUE time; + close ($QUEUE); + + my @alert = slurp("/usr/local/csf/tpl/modsecipdbalert.txt"); + my @message; + foreach my $line (@alert) { + $line =~ s/\[text\]/$report/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + } + + close ($THISLOCK ); + if ($config{DEBUG} >= 3) {$timer = &timer("stop","modsecipdbcheck",$timer)} + $0 = "lfd - child closing"; + exit; + } + return; +} +# end modsecipdbcheck +############################################################################### +# start connectiontracking +sub connectiontracking { + + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","connectiontracking",$timer)} + $0 = "lfd - (child) connection tracking..."; + + my $lockstr = "CT_INTERVAL"; + sysopen (my $THISLOCK, "/var/lib/csf/lock/$lockstr.lock", O_RDWR | O_CREAT) or &childcleanup("*Error* Unable to open /var/lib/csf/lock/$lockstr.lock"); + flock ($THISLOCK, LOCK_EX | LOCK_NB) or &childcleanup("*Lock Error* [$lockstr] still active - section skipped"); + print $THISLOCK time; + + my @connections; + my %ipcnt; + my %iptext; + my %subcnt; + my %subtext; + my $alarm = int($config{CT_INTERVAL}/10) + 10; + my $start = time; + my $tfail = 0; + my %states; + if ($config{CT_STATES}) { + foreach my $state (split(/\,/,$config{CT_STATES})) { + $states{$state} = 1; + } + } + my %countports; + if ($config{CT_PORTS}) { + foreach my $port (split(/\,/,$config{CT_PORTS})) { + $countports{$port} = 1; + } + } + + my %net; + my %tcpstates = ("01" => "ESTABLISHED", + "02" => "SYN_SENT", + "03" => "SYN_RECV", + "04" => "FIN_WAIT1", + "05" => "FIN_WAIT2", + "06" => "TIME_WAIT", + "07" => "CLOSE", + "08" => "CLOSE_WAIT", + "09" => "LAST_ACK", + "0A" => "LISTEN", + "0B" => "CLOSING"); + foreach my $proto ("tcp","udp","tcp6","udp6") { + open (my $IN, "<", "/proc/net/$proto"); + flock ($IN, LOCK_SH); + while (<$IN>) { + my @rec = split(); + if ($rec[9] =~ /uid/) {next} + + my ($dip,$dport) = split(/:/,$rec[1]); + $dport = hex($dport); + + my ($sip,$sport) = split(/:/,$rec[2]); + $sport = hex($sport); + + $dip = &hex2ip($dip); + if ($dip =~ /^0:0:0:0:0:ffff:(.*)$/) { + my $embed = ipv4in6($dip); + if ($embed =~ /^$ipv4reg$/) {$dip = $embed} + } + + $sip = &hex2ip($sip); + if ($sip =~ /^0:0:0:0:0:ffff:(.*)$/) { + my $embed = ipv4in6($sip); + if ($embed =~ /^$ipv4reg$/) {$sip = $embed} + } + + my $state = $tcpstates{$rec[3]}; + + if ($config{DEBUG} >= 4) {logfile("debug: CT $proto: $sip:$sport -> $dip:$dport state:[$state]")} + + if ($config{CT_SKIP_TIME_WAIT} and ($state eq "TIME_WAIT")) {next} + if ($config{CT_STATES} and ($states{$state} != 1)) {next} + if ($config{CT_PORTS} and ($countports{$dport} != 1)) {next} + if ($state eq "LISTEN") {next} + if ($dip =~ /^127\./) {next} + if ($dip =~ /^0\.0\.0\.1/) {next} + + checkip(\$sip); + $ipcnt{$sip}++; + $iptext{$sip} .= "$proto: $sip:$sport -> $dip:$dport ($state)\n"; + + if ($config{CT_SUBNET_LIMIT} > 0) { + my $subnet; + if ($sip =~ /^(\d+\.\d+\.\d+)\.\d+$/) { + $subnet = $1; + if ($subnet ne "0.0.0" and $subnet ne "255.255.255") { + $subcnt{$subnet}++; + $subtext{$subnet} .= "$proto: $sip:$sport -> $dip:$dport ($state)\n"; + if ($config{DEBUG} >= 2) {logfile("debug: CT $proto: $sip:$sport -> $dip:$dport state:[$state] count:[$ipcnt{$sip}] subnet:[$subnet] subnet count:[$subcnt{$subnet}]")} + } + } + } else { + if ($config{DEBUG} >= 2) {logfile("debug: CT $proto: $sip:$sport -> $dip:$dport state:[$state] count:[$ipcnt{$sip}]")} + } + } + close ($IN); + } + + foreach my $ip (keys %ipcnt) { + if (($ipcnt{$ip} > $config{CT_LIMIT}) and !&ignoreip($ip)) { + my $tip = iplookup($ip); + if (&ipblock($config{CT_PERMANENT},"(CT) IP $tip found to have $ipcnt{$ip} connections",$ip,"","inout",$config{CT_BLOCK_TIME},0,$iptext{$ip},"CT_LIMIT")) { + if ($config{DEBUG} >= 1) {logfile("debug: CT $ip already blocked")} + } else { + if ($config{CT_EMAIL_ALERT}) { + $0 = "lfd - (child) (CT) sending alert email for $ip"; + + my @alert = slurp("/usr/local/csf/tpl/connectiontracking.txt"); + my $block = "Temporary Block for $config{CT_BLOCK_TIME} seconds [CT_LIMIT]"; + if ($config{CT_PERMANENT}) {$block = "Permanent Block [CT_LIMIT]"} + + my $allowip = &allowip($ip); + if ($allowip == 1) {$block .= " (IP match in csf.allow, block may not work)"} + if ($allowip == 2) {$block .= " (IP match in GLOBAL_ALLOW, block may not work)"} + + my @message; + foreach my $line (@alert) { + $line =~ s/\[ip\]/$tip/ig; + $line =~ s/\[ipcount\]/$ipcnt{$ip}/ig; + $line =~ s/\[iptext\]/$iptext{$ip}/ig; + $line =~ s/\[temp\]/$block/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + + if ($config{X_ARF}) { + $0 = "lfd - (child) sending X-ARF email for $ip"; + + my @alert = slurp("/usr/local/csf/tpl/x-arf.txt"); + my @message; + my $rfc3339 = strftime('%Y-%m-%dT%H:%M:%S%z',localtime); + my $boundary = time; + my $reportedfrom = "root\@$hostname"; + if ($config{X_ARF_TO}) {$config{LF_ALERT_TO} = $config{X_ARF_TO}} + if ($config{X_ARF_FROM}) {$config{LF_ALERT_FROM} = $config{X_ARF_FROM}; $reportedfrom = $config{X_ARF_FROM}} + my $iptype = "ipv".checkip(\$ip); + + my $abuseto = ""; + my $abusemsg = ""; + if ($iptype eq "ipv4" and $abuseip) { + ($abuseto, $abusemsg) = abuseip($ip); + if ($abuseto eq "") { + $abusemsg = ""; + } + elsif ($config{X_ARF_ABUSE} and $config{X_ARF_FROM}) { + if ($config{LF_ALERT_TO}) { + $config{LF_ALERT_TO} .= ",".$abuseto; + } else { + $config{LF_ALERT_TO} = "root,".$abuseto; + } + } + } + + foreach my $line (@alert) { + $line =~ s/\[ip\]/$ip/ig; + $line =~ s/\[abuseip\]/$abusemsg/ig; + $line =~ s/\[iptype\]/$iptype/ig; + $line =~ s/\[tip\]/$tip/ig; + $line =~ s/\[ipcount\]/$ipcnt{$ip}/ig; + $line =~ s/\[iptick\]/$config{LF_INTERVAL}/ig; + $line =~ s/\[service\]/port-flood/ig; + $line =~ s/\[csfversion\]/$version/ig; + $line =~ s/\[reportedfrom\]/$reportedfrom/ig; + $line =~ s/\[reportedid\]/$boundary\@$hostname/ig; + $line =~ s/\[boundary\]/$boundary/ig; + $line =~ s/\[text\]/$iptext{$ip}/ig; + $line =~ s/\[RFC3339\]/$rfc3339/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay($config{LF_ALERT_TO}, $config{LF_ALERT_FROM}, @message); + + if ($config{DEBUG} >= 1) {logfile("debug: CT X-ARF email sent for $ip")} + } + + if ($config{DEBUG} >= 1) {logfile("debug: CT alert email sent for $ip")} + } + } + } + } + + foreach my $subnet (keys %subcnt) { + if ($config{DEBUG} >= 2) {logfile("debug: CT $subnet processing $subcnt{$subnet} entries")} + my $fullsubnet = $subnet.".0/24"; + if (($subcnt{$subnet} > $config{CT_SUBNET_LIMIT}) and !&ignoreip($fullsubnet)) { + my $tip = iplookup($fullsubnet); + if (&ipblock($config{CT_PERMANENT},"(CT) subnet $tip found to have $subcnt{$subnet} connections",$fullsubnet,"","inout",$config{CT_BLOCK_TIME},0,$subtext{$subnet},"CT_SUBNET_LIMIT")) { + if ($config{DEBUG} >= 1) {logfile("debug: CT $subnet already blocked")} + } else { + if ($config{CT_EMAIL_ALERT}) { + $0 = "lfd - (child) (CT) sending alert email for $subnet"; + + my @alert = slurp("/usr/local/csf/tpl/connectiontracking.txt"); + my $block = "Temporary Block for $config{CT_BLOCK_TIME} seconds [CT_LIMIT]"; + if ($config{CT_PERMANENT}) {$block = "Permanent Block [CT_LIMIT]"} + + my $allowip = &allowip($fullsubnet); + if ($allowip == 1) {$block .= " (subnet match in csf.allow, block may not work)"} + if ($allowip == 2) {$block .= " (subnet match in GLOBAL_ALLOW, block may not work)"} + + my @message; + foreach my $line (@alert) { + $line =~ s/\[ip\]/$tip/ig; + $line =~ s/\[ipcount\]/$subcnt{$subnet}/ig; + $line =~ s/\[iptext\]/$subtext{$subnet}/ig; + $line =~ s/\[temp\]/$block/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + + if ($config{DEBUG} >= 1) {logfile("debug: CT alert email sent for $fullsubnet")} + } + } + } + } + + if ($tfail) { + $config{CT_INTERVAL} = $config{CT_INTERVAL} * 1.5; + sysopen (my $TEMPCONF, "/var/lib/csf/csf.tempconf", O_WRONLY | O_APPEND | O_CREAT) or &childcleanup(__LINE__,"*Error* Cannot append out file: $!"); + flock ($TEMPCONF, LOCK_EX); + print $TEMPCONF "CT_INTERVAL = \"$config{CT_INTERVAL}\"\n"; + close ($TEMPCONF); + logfile("CT_INTERVAL taking $alarm seconds, temporarily throttled to run every $config{CT_INTERVAL} seconds"); + } + + close ($THISLOCK ); + if ($config{DEBUG} >= 3) {$timer = &timer("stop","connectiontracking",$timer)} + $0 = "lfd - (child) closing"; + exit; + } + return; +} +# end connectiontracking +############################################################################### +# start accounttracking +sub accounttracking { + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","accounttracking",$timer)} + $0 = "lfd - (child) account tracking..."; + + my $lockstr = "AT_INTERVAL"; + sysopen (my $THISLOCK, "/var/lib/csf/lock/$lockstr.lock", O_RDWR | O_CREAT) or &childcleanup("*Error* Unable to open /var/lib/csf/lock/$lockstr.lock"); + flock ($THISLOCK, LOCK_EX | LOCK_NB) or &childcleanup("*Lock Error* [$lockstr] still active - section skipped"); + print $THISLOCK time; + + my $report = ""; + foreach my $user (keys %newaccounttracking) { + if (($config{AT_ALERT} eq "2") and ($newaccounttracking{$user}{uid} ne "0")) {next} + if ($accounttracking{$user}{account} != 1) { + if ($config{AT_NEW}) { + $report .= "New account [$user] has been created with uid:[$newaccounttracking{$user}{uid}] gid:[$newaccounttracking{$user}{gid}] login:[$newaccounttracking{$user}{dir}] shell:[$newaccounttracking{$user}{shell}]\n"; + } + } else { + if ($config{AT_PASSWD} and ($newaccounttracking{$user}{passwd} ne $accounttracking{$user}{passwd})) { + $report .= "Account [$user] password has changed\n"; + } + if ($config{AT_UID} and ($newaccounttracking{$user}{uid} ne $accounttracking{$user}{uid})) { + $report .= "Account [$user] uid has changed from [$accounttracking{$user}{uid}] to [$newaccounttracking{$user}{uid}]\n"; + } + if ($config{AT_GID} and ($newaccounttracking{$user}{gid} ne $accounttracking{$user}{gid})) { + $report .= "Account [$user] gid has changed from [$accounttracking{$user}{gid}] to [$newaccounttracking{$user}{gid}]\n"; + } + if ($config{AT_DIR} and ($newaccounttracking{$user}{dir} ne $accounttracking{$user}{dir})) { + $report .= "Account [$user] login directory has changed from [$accounttracking{$user}{dir}] to [$newaccounttracking{$user}{dir}]\n"; + } + if ($config{AT_SHELL} and ($newaccounttracking{$user}{shell} ne $accounttracking{$user}{shell})) { + $report .= "Account [$user] login shell has changed from [$accounttracking{$user}{shell}] to [$newaccounttracking{$user}{shell}]\n"; + } + } + } + foreach my $user (keys %accounttracking) { + if (($config{AT_ALERT} eq "2") and ($accounttracking{$user}{uid} ne "0")) {next} + if ($config{AT_OLD} and ($newaccounttracking{$user}{account} != 1)) { + $report .= "Existing account [$user] has been removed. Old settings uid:[$accounttracking{$user}{uid}] gid:[$accounttracking{$user}{gid}] login:[$accounttracking{$user}{dir}] shell:[$accounttracking{$user}{shell}]\n"; + } + } + if ($report ne "") { + logfile("*Account Modification* Email sent"); + + my @alert = slurp("/usr/local/csf/tpl/accounttracking.txt"); + my @message; + foreach my $line (@alert) { + $line =~ s/\[report\]/$report/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + } + + close ($THISLOCK ); + if ($config{DEBUG} >= 3) {$timer = &timer("stop","accounttracking",$timer)} + $0 = "lfd - (child) closing"; + exit; + } + return; +} +# end accounttracking +############################################################################### +# start syslogcheck +sub syslogcheck { + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","syslogcheck",$timer)} + $0 = "lfd - (child) SYSLOG check..."; + + my $lockstr = "SYSLOG_CHECK"; + sysopen (my $THISLOCK, "/var/lib/csf/lock/$lockstr.lock", O_RDWR | O_CREAT) or &childcleanup("*Error* Unable to open /var/lib/csf/lock/$lockstr.lock"); + flock ($THISLOCK, LOCK_EX | LOCK_NB) or &childcleanup("*Lock Error* [$lockstr] still active - section skipped"); + print $THISLOCK time; + + logfile("*SYSLOG CHECK* Failed to detect check line [$syslogcheckcode] sent to SYSLOG"); + + my @alert = slurp("/usr/local/csf/tpl/syslogalert.txt"); + my @message; + foreach my $line (@alert) { + $line =~ s/\[code\]/$syslogcheckcode/ig; + $line =~ s/\[log\]/$config{SYSLOG_LOG}/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + + close ($THISLOCK ); + if ($config{DEBUG} >= 3) {$timer = &timer("stop","syslogcheck",$timer)} + $0 = "lfd - (child) closing"; + exit; + } + return; +} +# end syslogcheck +############################################################################### +# start processtracking +sub processtracking { + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","processtracking",$timer)} + $0 = "lfd - (child) process tracking..."; + + my $lockstr = "PT_INTERVAL"; + sysopen (my $THISLOCK, "/var/lib/csf/lock/$lockstr.lock", O_RDWR | O_CREAT) or &childcleanup("*Error* Unable to open /var/lib/csf/lock/$lockstr.lock"); + flock ($THISLOCK, LOCK_EX | LOCK_NB) or &childcleanup("*Lock Error* [$lockstr] still active - section skipped"); + print $THISLOCK time; + + my %users; + my %net; + + unless ($config{GENERIC}) { + opendir (DIR, "/var/cpanel/users"); + while (my $user = readdir (DIR)) { + if ($user =~ /^\./) {next} + $users{$user} = 1; + } + closedir (DIR); + $users{nobody} = 1; + } + + foreach my $proto ("udp","tcp","udp6","tcp6") { + open (my $IN, "<", "/proc/net/$proto"); + flock ($IN, LOCK_SH); + while (<$IN>) { + my @rec = split(); + if ($rec[9] =~ /uid/) {next} + + my ($dip,$dport) = split(/:/,$rec[2]); + $dport = hex($dport); + + my ($sip,$sport) = split(/:/,$rec[1]); + $sport = hex($sport); + + if ($dip == 0 or $sip == 0) {next} + + $dip = &hex2ip($dip); + if ($dip =~ /^0:0:0:0:0:ffff:(.*)$/) { + my $embed = ipv4in6($dip); + if ($embed =~ /^$ipv4reg$/) {$dip = $embed} + } + + $sip = &hex2ip($sip); + if ($sip =~ /^0:0:0:0:0:ffff:(.*)$/) { + my $embed = ipv4in6($sip); + if ($embed =~ /^$ipv4reg$/) {$sip = $embed} + } + + if ($sip eq '0.0.0.1') {next} + + $net{$rec[9]}{proto} = $proto; + $net{$rec[9]}{sport} = $sport; + $net{$rec[9]}{sip} = $sip; + $net{$rec[9]}{dport} = $dport; + $net{$rec[9]}{dip} = $dip; + if ($config{DEBUG} >= 4) {logfile("debug: PT $proto: $sip:$sport -> $dip:$dport")} + } + close ($IN); + } + + open (my $IN,"<", "/proc/uptime"); + flock ($IN, LOCK_SH); + my @up = <$IN>; + close ($IN); + chomp @up; + my ($upsecs,undef) = split (/\s/,$up[0]); + + my %pids; + if (! -z "/var/lib/csf/csf.temppids") { + open (my $IN, "<", "/var/lib/csf/csf.temppids"); + flock ($IN, LOCK_SH); + my @data = <$IN>; + close ($IN); + chomp @data; + + foreach my $line (@data) { + my ($itemttl,$item) = split(/:/,$line); + if (time - $itemttl < $config{LF_FLUSH}) { + $pids{$item} = 1; + } + } + } + my %ignoreusers; + if (! -z "/var/lib/csf/csf.tempusers") { + open (my $IN, "<", "/var/lib/csf/csf.tempusers"); + flock ($IN, LOCK_SH); + my @data = <$IN>; + close ($IN); + chomp @data; + + foreach my $line (@data) { + my ($itemttl,$item) = split(/:/,$line); + if (time - $itemttl < $config{LF_FLUSH}) { + $ignoreusers{$item} = 1; + } + } + } + + my %totproc; + my %procres; + my %sessions; + opendir (PROCDIR, "/proc"); + while (my $pid = readdir(PROCDIR)) { + if ($pid !~ /^\d+$/) {next} + open (my $IN,"<", "/proc/$pid/status") or next; + flock ($IN, LOCK_SH); + my @status = <$IN>; + close ($IN); + chomp @status; + my $user; + my $uid; + my $vmsize = 0; + my $vmrss = 0; + my $ppid = $pid; + foreach my $line (@status) { + if ($line =~ /^Uid:(.*)/) { + my $uidline = $1; + my @uids; + foreach my $bit (split(/\s/,$uidline)) { + if ($bit =~ /^(\d*)$/) {push @uids, $1} + } + $uid = $uids[-1]; + $user = getpwuid($uid); + } + if ($line =~ /^VmSize:\s+(\d+) kB$/) {$vmsize = $1} + if ($line =~ /^VmRSS:\s+(\d+) kB$/) {$vmrss = $1} + if ($line =~ /^PPid:\s+(\d+)$/) { + $ppid = $1; + if ($ppid == 1) {$ppid = $pid} + } + } + + if ($users{$user} or $config{GENERIC} or $config{PT_ALL_USERS}) { + if ($pids{$pid}) {next} + if ($skip{user}{$user}) {next} + my $pmatch = 0; + foreach my $item (keys %{$pskip{puser}}) { + if ($user =~ /^$item$/) { + $pmatch = 1; + last; + } + } + if ($pmatch) {next} + + my %printable = ( ( map { chr($_), unpack('H2', chr($_)) } (0..255) ), "\\"=>'\\', "\r"=>'r', "\n"=>'n', "\t"=>'t', "\""=>'"' ); ##no critic + + my $exe = readlink("/proc/$pid/exe"); + my $cwd = readlink("/proc/$pid/cwd"); + $exe =~ s/([\r\n\t\"\\\x00-\x1f\x7F-\xFF])/\\$printable{$1}/sg; + $cwd =~ s/([\r\n\t\"\\\x00-\x1f\x7F-\xFF])/\\$printable{$1}/sg; + if ($exe eq "") {next} + + if ($config{DEBUG} >= 4) {logfile("debug: PT exe = $exe")} + my $exet = $exe; + my $deleted = 0; + if ($exe =~ /\(deleted\)/) { + if ($ppid and ($ppid != $pid) and $pids{$ppid}) { + my $pexe = readlink("/proc/$ppid/exe"); + $pexe =~ s/([\r\n\t\"\\\x00-\x1f\x7F-\xFF])/\\$printable{$1}/sg; + if ($pexe =~ /\(deleted\)/) { + if ($config{DEBUG} >= 2) {logfile("Process Tracking - Parent PID $ppid already reported for deleted $pid - ignored")} + next; + } + } + $deleted = 1; + if ($config{PT_DELETED}) { + $exet .= "\n\nThe file system shows this process is running an executable file that has been deleted. This typically happens when the original file has been replaced by a new file when the application is updated. To prevent this being reported again, restart the process that runs this excecutable file. See csf.conf and the PT_DELETED text for more information about the security implications of processes running deleted executable files."; + } else {next} + } + + open (my $CMDLINE,"<", "/proc/$pid/cmdline"); + flock ($CMDLINE, LOCK_SH); + my $cmdline = <$CMDLINE>; + close ($CMDLINE); + chomp $cmdline; + $cmdline =~ s/\0$//g; + $cmdline =~ s/\0/ /g; + $cmdline =~ s/\s+$//g; + $cmdline =~ s/([\r\n\t\"\\\x00-\x1f\x7F-\xFF])/\\$printable{$1}/sg; + + open (my $STAT,"<", "/proc/$pid/stat") or next; + flock ($STAT, LOCK_SH); + my $pstatline = <$STAT>; + close ($STAT); + chomp $pstatline; + my @pstat; + if ($pstatline =~ /^\d+\s\(.*\)\s(.*)$/) { + @pstat = split(/\s/,$1); + } else {next} + + my $jiffsecs = $pstat[19] / $clock_ticks; + my $uptime = int($upsecs - $jiffsecs); + + if ($config{PT_SSHDHUNG}) { + if ($cmdline =~ /^sshd:\s+unknown\s+\[net|priv\]\s*$/) { + if ($uptime > 60) { + kill (9, $pid); + logfile("*PT_SSHDHUNG* process pid:[$pid] cmd:[$cmdline] Uptime:[$uptime], killed"); + next; + } + } + } + + if ($skip{exe}{$exe}) {next} + + $pmatch = 0; + foreach my $item (keys %{$pskip{pexe}}) { + if ($exe =~ /^$item$/) { + $pmatch = 1; + last; + } + } + if ($pmatch) {next} + + if ($skip{cmd}{$cmdline}) {next} + $pmatch = 0; + foreach my $item (keys %{$pskip{pcmd}}) { + if ($cmdline =~ /^$item$/) { + $pmatch = 1; + last; + } + } + if ($pmatch) {next} + + if (($config{MESSENGER} and $user eq $config{MESSENGER_USER}) and ($cmdline =~ /^lfd (HTML|TEXT|HTTPS) messenger/)) {next} + + if ($config{PT_FORKBOMB}) { + my $sid = $pstat[3]; + if ($sid > 1) { + $sessions{$sid}{count}++; + $sessions{$sid}{text} .= "PID:$pid PPID:$ppid SID:$sid User:$user EXE:$exe CMD:$cmdline\n"; + if ($sessions{$sid}{count} >= $config{PT_FORKBOMB}) { + logfile("*PT_FORKBOMB* PID:$pid SID:$sid User:$user EXE:$exe CMD:$cmdline"); + my $text = $sessions{$sid}{text}; + delete $sessions{$sid}; + kill 9, "-$sid"; + + my @alert = slurp("/usr/local/csf/tpl/forkbombalert.txt"); + my @message; + foreach my $line (@alert) { + $line =~ s/\[level\]/$config{PT_FORKBOMB}/ig; + $line =~ s/\[text\]/$text/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + next; + } + } + } + if ($user eq "root") {next} + + if ($config{PT_SKIP_HTTP}) { + my $pgrp = $pstat[2]; + my $pgrpexe = readlink("/proc/$pgrp/exe"); + if (($pid ne $pgrp) and ($pgrpexe eq "/usr/local/apache/bin/httpd")) {next} + if (($pid ne $pgrp) and ($pgrpexe eq "/usr/local/bin/httpd")) {next} + if (($pid ne $pgrp) and ($pgrpexe eq "/usr/bin/httpd")) {next} + } + + if ($user ne "nobody") { + unless ($deleted) { + $totproc{$user}{count}++; + if ($totproc{$user}{pids} eq "") { + $totproc{$user}{pids} = $pid; + } else { + $totproc{$user}{pids} .= ",$pid"; + } + $totproc{$user}{text} .= "User:$user PID:$pid PPID:$ppid Run Time:$uptime(secs) Memory:$vmsize(kb) RSS:$vmrss(kb) exe:$exe cmd:$cmdline\n"; + $procres{$pid}{vmsize} = $vmsize; + $procres{$pid}{vmrss} = $vmrss; + $procres{$pid}{uptime} = $uptime; + $procres{$pid}{user} = $user; + $procres{$pid}{exe} = $exe; + $procres{$pid}{exet} = $exet; + $procres{$pid}{cmd} = $cmdline; + $procres{$pid}{ppid} = $ppid; + } + } + + if ($uptime > $config{PT_LIMIT}) { + my $suspect = 0; + + my @fd; + opendir (DIR, "/proc/$pid/fd") or next; + while (my $file = readdir (DIR)) { + if ($file =~ /^\./) {next} + push (@fd, readlink("/proc/$pid/fd/$file")); + } + closedir (DIR); + + my $files; + my $sockets; + foreach my $file (@fd) { + if ($file =~ /^socket:\[?([0-9]+)\]?$/) { + my $ino = $1; + if ($net{$ino}) { + $sockets .= "$net{$ino}{proto}: $net{$ino}{sip}:$net{$ino}{sport} -> $net{$ino}{dip}:$net{$ino}{dport}\n"; + if ($suspect != 2) {$suspect = 1} + if ($config{PT_SKIP_HTTP} and $net{$ino}{sport} =~ /^(80|443)$/) {$suspect = 2} + } + } + if ($file =~ /^socket|pipe/) {next} + $files .= $file."\n"; + } + if ($suspect == 2) {$suspect = 0} + + if ($suspect or $deleted) { + my $sexe = readlink("/proc/$pid/exe"); + if ($sexe eq "") {next} + + logfile("*Suspicious Process* PID:$pid PPID:$ppid User:$user Uptime:$uptime secs EXE:$exe CMD:$cmdline"); + + sysopen (my $TEMPPIDS, "/var/lib/csf/csf.temppids", O_WRONLY | O_APPEND | O_CREAT) or &childcleanup(__LINE__,"*Error* Cannot append out file: $!"); + flock ($TEMPPIDS, LOCK_EX); + print $TEMPPIDS time.":$pid\n"; + if ($deleted and $ppid and ($ppid != $pid)) { + my $pexe = readlink("/proc/$ppid/exe"); + $pexe =~ s/([\r\n\t\"\\\x00-\x1f\x7F-\xFF])/\\$printable{$1}/sg; + if ($pexe =~ /\(deleted\)/) { + print $TEMPPIDS time.":$ppid\n"; + $pids{$ppid} = 1; + } + } + close ($TEMPPIDS); + + $0 = "lfd - (child) (PT) sending alert email for process $pid"; + + open (my $IN,"<", "/proc/$pid/maps"); + flock ($IN, LOCK_SH); + my @maps = <$IN>; + close ($IN); + chomp @maps; + my $maps; + foreach my $line (@maps) {$maps .= $line."\n"} + + my @alert = slurp("/usr/local/csf/tpl/processtracking.txt"); + my @message; + foreach my $line (@alert) { + $line =~ s/\[pid\]/$pid (Parent PID:$ppid)/ig; + $line =~ s/\[user\]/$user/ig; + $line =~ s/\[uptime\]/$uptime/ig; + $line =~ s/\[sockets\]/$sockets/ig; + $line =~ s/\[files\]/$files/ig; + $line =~ s/\[maps\]/$maps/ig; + $line =~ s/\[exe\]/$exet/ig; + $line =~ s/\[cmdline\]/$cmdline/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + + if ($deleted and $config{PT_DELETED_ACTION} and -e "$config{PT_DELETED_ACTION}" and -x "$config{PT_DELETED_ACTION}") { + $SIG{CHLD} = 'IGNORE'; + unless (defined ($ptchildpid = fork)) { + &childcleanup(__LINE__,"*Error* cannot fork: $!"); + } + unless ($ptchildpid) { + system($config{PT_DELETED_ACTION},$exe,$pid,$user,$ppid); + logfile("Executed PT_DELETED_ACTION for PID:$pid"); + exit; + } + } + + } + } + } + } + if ($config{PT_USERPROC}) { + $0 = "lfd - (child) (PT) checking user processes"; + foreach my $user (keys %totproc) { + if ($ignoreusers{$user}) {next} + if ($totproc{$user}{count} > $config{PT_USERPROC}) { + my $kill = "Not killed"; + if ($config{PT_USERKILL}) { + foreach my $pid (split(/\,/,$totproc{$user}{pids})) { + kill (9, $pid); + } + $kill = "Killed"; + } else { + sysopen (my $TEMPUSERS, "/var/lib/csf/csf.tempusers", O_WRONLY | O_APPEND | O_CREAT) or &childcleanup(__LINE__,"*Error* Cannot append out file: $!"); + flock ($TEMPUSERS, LOCK_EX); + print $TEMPUSERS time.":$user\n"; + close ($TEMPUSERS); + } + + logfile("*Excessive Processes* User:$user Kill:$config{PT_USERKILL} Process Count:$totproc{$user}{count}"); + + if (!$config{PT_USERKILL} or ($config{PT_USERKILL} and $config{PT_USERKILL_ALERT})) { + my @alert = slurp("/usr/local/csf/tpl/usertracking.txt"); + my @message; + foreach my $line (@alert) { + $line =~ s/\[user\]/$user/ig; + $line =~ s/\[count\]/$totproc{$user}{count} \($kill\)/ig; + $line =~ s/\[text\]/$totproc{$user}{text}/ig; + $line =~ s/\[kill\]/$kill/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + } + if ($config{PT_USER_ACTION} and -e "$config{PT_USER_ACTION}" and -x "$config{PT_USER_ACTION}") { + $SIG{CHLD} = 'IGNORE'; + unless (defined ($ptchildpid = fork)) { + &childcleanup(__LINE__,"*Error* cannot fork: $!"); + } + unless ($ptchildpid) { + system($config{PT_USER_ACTION},$totproc{$user}{pids}); + exit; + } + } + } + } + } + + if ($config{PT_USERMEM} or $config{PT_USERRSS} or $config{PT_USERTIME}) { + foreach my $pid (keys %procres) { + my $report = 0; + my $resource; + my $level; + if ($config{PT_USERMEM} and ($procres{$pid}{vmsize} > ($config{PT_USERMEM} * 1024))) { + $report = 1; + $resource = "Virtual Memory Size"; + my $memsize = int($procres{$pid}{vmsize} / 1024); + $level = "$memsize > $config{PT_USERMEM} (MB)"; + logfile("*User Processing* PID:$pid Kill:$config{PT_USERKILL} User:$procres{$pid}{user} VM:$memsize(MB) EXE:$procres{$pid}{exe} CMD:$procres{$pid}{cmd}"); + } + if ($config{PT_USERRSS} and ($procres{$pid}{vmrss} > ($config{PT_USERRSS} * 1024))) { + $report = 1; + $resource = "RSS Memory Size"; + my $memsize = int($procres{$pid}{vmrss} / 1024); + $level = "$memsize > $config{PT_USERRSS} (MB)"; + logfile("*User Processing* PID:$pid Kill:$config{PT_USERKILL} User:$procres{$pid}{user} RSS:$memsize(MB) EXE:$procres{$pid}{exe} CMD:$procres{$pid}{cmd}"); + } + if ($config{PT_USERTIME} and ($procres{$pid}{uptime} > $config{PT_USERTIME})) { + $report = 1; + $resource = "Process Time"; + $level = "$procres{$pid}{uptime} > $config{PT_USERTIME} (seconds)"; + logfile("*User Processing* PID:$pid Kill:$config{PT_USERKILL} User:$procres{$pid}{user} Time:$procres{$pid}{uptime} EXE:$procres{$pid}{exe} CMD:$procres{$pid}{cmd}"); + } + if ($report) { + my $kill = "No"; + if ($config{PT_USERKILL}) { + kill (9, $pid); + $kill = "Yes"; + } else { + sysopen (my $TEMPPIDS, "/var/lib/csf/csf.temppids", O_WRONLY | O_APPEND | O_CREAT) or &childcleanup(__LINE__,"*Error* Cannot append out file: $!"); + flock ($TEMPPIDS, LOCK_EX); + print $TEMPPIDS time.":$pid\n"; + close ($TEMPPIDS); + } + + if (!$config{PT_USERKILL} or ($config{PT_USERKILL} and $config{PT_USERKILL_ALERT})) { + my @alert = slurp("/usr/local/csf/tpl/resalert.txt"); + my @message; + foreach my $line (@alert) { + $line =~ s/\[user\]/$procres{$pid}{user}/ig; + $line =~ s/\[cmd\]/$procres{$pid}{cmd}/ig; + $line =~ s/\[exe\]/$procres{$pid}{exet}/ig; + $line =~ s/\[resource\]/$resource/ig; + $line =~ s/\[level\]/$level/ig; + $line =~ s/\[kill\]/$kill/ig; + $line =~ s/\[pid\]/$pid (Parent PID:$procres{$pid}{ppid})/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + } + + if ($config{PT_USER_ACTION} and -e "$config{PT_USER_ACTION}" and -x "$config{PT_USER_ACTION}") { + $SIG{CHLD} = 'IGNORE'; + unless (defined ($ptchildpid = fork)) { + &childcleanup(__LINE__,"*Error* cannot fork: $!"); + } + unless ($ptchildpid) { + system($config{PT_USER_ACTION},$pid); + exit; + } + } + } + } + } + + close ($THISLOCK ); + if ($config{DEBUG} >= 3) {$timer = &timer("stop","processtracking",$timer)} + $0 = "lfd - (child) closing"; + exit; + } + return; +} +# end processtracking +############################################################################### +# start sshalert +sub sshalert { + my $account = shift; + my $ip = shift; + my $method = shift; + my $text = shift; + + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","sshalert",$timer)} + logfile("*SSH login* from $ip into the $account account using $method authentication"); + + $0 = "lfd - (child) sending SSH login alert email for $ip"; + + my @alert = slurp("/usr/local/csf/tpl/sshalert.txt"); + my $tip = iplookup($ip); + my @message; + foreach my $line (@alert) { + $line =~ s/\[ip\]/$tip/ig; + $line =~ s/\[account\]/$account/ig; + $line =~ s/\[method\]/$method/ig; + $line =~ s/\[text\]/$text/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + + if ($config{DEBUG} >= 3) {$timer = &timer("stop","sshalert",$timer)} + $0 = "lfd - child closing"; + exit; + } + return; +} +# end sshalert +############################################################################### +# start sualert +sub sualert { + my $suto = shift; + my $sufrom = shift; + my $status = shift; + my $text = shift; + + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","sualert",$timer)} + logfile("*SU login* from account $sufrom to account $suto: $status"); + + $0 = "lfd - (child) sending SU login alert email from $sufrom to $suto"; + + my @alert = slurp("/usr/local/csf/tpl/sualert.txt"); + my @message; + foreach my $line (@alert) { + $line =~ s/\[to\]/$suto/ig; + $line =~ s/\[from\]/$sufrom/ig; + $line =~ s/\[status\]/$status/ig; + $line =~ s/\[text\]/$text/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + + if ($config{DEBUG} >= 3) {$timer = &timer("stop","sualert",$timer)} + $0 = "lfd - child closing"; + exit; + } + return; +} +# end sualert +############################################################################### +# start sudoalert +sub sudoalert { + my $suto = shift; + my $sufrom = shift; + my $status = shift; + my $text = shift; + + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","sudoalert",$timer)} + logfile("*SUDO login* from account $sufrom to account $suto: $status"); + + $0 = "lfd - (child) sending SU login alert email from $sufrom to $suto"; + + my @alert = slurp("/usr/local/csf/tpl/sudoalert.txt"); + my @message; + foreach my $line (@alert) { + $line =~ s/\[to\]/$suto/ig; + $line =~ s/\[from\]/$sufrom/ig; + $line =~ s/\[status\]/$status/ig; + $line =~ s/\[text\]/$text/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + + if ($config{DEBUG} >= 3) {$timer = &timer("stop","sudoalert",$timer)} + $0 = "lfd - child closing"; + exit; + } + return; +} +# end sudoalert +############################################################################### +# start webminalert +sub webminalert { + my $account = shift; + my $ip = shift; + my $text = shift; + + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","webminalert",$timer)} + logfile("*Webmin login* from $ip into the $account account"); + + $0 = "lfd - (child) sending Webmin login alert email for $ip"; + + my @alert = slurp("/usr/local/csf/tpl/webminalert.txt"); + my $tip = iplookup($ip); + my @message; + foreach my $line (@alert) { + $line =~ s/\[ip\]/$tip/ig; + $line =~ s/\[account\]/$account/ig; + $line =~ s/\[text\]/$text/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + + if ($config{DEBUG} >= 3) {$timer = &timer("stop","webminalert",$timer)} + $0 = "lfd - child closing"; + exit; + } + return; +} +# end webminalert +############################################################################### +# start consolealert +sub consolealert { + my $logline = shift; + + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","consolealert",$timer)} + logfile("*CONSOLE login* to root"); + + $0 = "lfd - (child) sending console login alert email"; + + my @alert = slurp("/usr/local/csf/tpl/consolealert.txt"); + my @message; + foreach my $line (@alert) { + $line =~ s/\[line\]/$logline/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + + if ($config{DEBUG} >= 3) {$timer = &timer("stop","consolealert",$timer)} + $0 = "lfd - child closing"; + exit; + } + return; +} +# end consolealert +############################################################################### +# start cpanelalert +sub cpanelalert { + my $ip = shift; + my $user = shift; + my $text = shift; + + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","cpanelalert",$timer)} + logfile("*WHM/cPanel $user access* from $ip"); + + $0 = "lfd - (child) sending WHM/cPanel access alert email for $ip"; + + my @alert = slurp("/usr/local/csf/tpl/cpanelalert.txt"); + my $tip = iplookup($ip); + my @message; + foreach my $line (@alert) { + $line =~ s/\[ip\]/$tip/ig; + $line =~ s/\[user\]/$user/ig; + $line =~ s/\[text\]/$text/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + + if ($config{LF_CPANEL_ALERT_ACTION} and -e "$config{LF_CPANEL_ALERT_ACTION}" and -x "$config{LF_CPANEL_ALERT_ACTION}") { + $0 = "lfd - (child) running LF_CPANEL_ALERT_ACTION"; + system($config{LF_CPANEL_ALERT_ACTION},$ip,$user,$tip); + } + + if ($config{DEBUG} >= 3) {$timer = &timer("stop","cpanelalert",$timer)} + $0 = "lfd - child closing"; + exit; + } + return; +} +# end cpanelalert +############################################################################### +# start scriptalert +sub scriptalert { + my $path = shift; + my $count = shift; + my $mails = shift; + my $text; + my $files; + + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","scriptalert",$timer)} + if ($skipscript{$path}) { + logfile("*Script Alert* - A script in '$path' has sent an email $count times within the last hour - ignored"); + exit; + } + logfile("*Script Alert* - A script in '$path' has sent an email $count times within the last hour"); + + $0 = "lfd - (child) identifying possible email scripts"; + + opendir (DIR, "$path"); + while (my $file = readdir (DIR)) { + if ($file =~ /\.(php([\ds]?)|phtml|cgi|pl|pm|sh|py)$/) { + open (my $IN, "<", "$path/$file"); + flock ($IN, LOCK_SH); + while (my $line = <$IN>) { + chomp $line; + if ($line =~ /mail\s*\(/) {$files .= "'$path/$file'\n"; last;} + if ($line =~ /sendmail/) {$files .= "'$path/$file'\n"; last;} + if ($line =~ /exim/) {$files .= "'$path/$file'\n"; last;} + } + close ($IN); + } + } + closedir (DIR); + + if ($config{LF_SCRIPT_PERM}) { + if (-l $path) { + logfile("'$path' is a symlink - *not* disabled by LF_SCRIPT_PERM"); + $files .= "\nDirectory '$path' is a symlink - *not* disabled\n"; + } else { + my $perms = sprintf "%04o", (stat($path))[2] & oct("00777"); + $files .= "\nDirectory '$path' has been disabled with 000 permissions.\n\nTo restore the permissions use:\nchattr -i $path\nchmod $perms $path\n"; + chmod (0000,$path); + system($config{CHATTR},"+i",$path); + logfile("'$path' has been disabled"); + } + } + + $0 = "lfd - (child) sending script alert"; + + my @alert = slurp("/usr/local/csf/tpl/scriptalert.txt"); + my @message; + foreach my $line (@alert) { + $line =~ s/\[path\]/\'$path\'/ig; + $line =~ s/\[count\]/$count/ig; + $line =~ s/\[emails\]/$mails/ig; + $line =~ s/\[scripts\]/$files/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + + if ($config{LF_SCRIPT_ACTION} and -e $config{LF_SCRIPT_ACTION} and -x $config{LF_SCRIPT_ACTION}) { + $0 = "lfd - (child) running LF_SCRIPT_ACTION"; + system($config{LF_SCRIPT_ACTION},$path,$count,$mails,$files); + } + + if ($config{DEBUG} >= 3) {$timer = &timer("stop","scriptalert",$timer)} + $0 = "lfd - child closing"; + exit; + } + return; +} +# end scriptalert +############################################################################### +# start relayalert +sub relayalert { + my $ip = shift; + my $cnt = shift; + my $check = shift; + my $mails = shift; + + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","relayalert",$timer)} + + logfile("*Exceeded $check limit* from $ip ($cnt in the last hour)"); + + $0 = "lfd - (child) reporting exceeded $check limit"; + + my $tip = $ip; + my $type = "$check, Local Account"; + if ($ip =~ /^127\./) { + $type = "$check, IPv4 localhost"; + } + elsif ($ip eq "::1") { + $type = "$check, IPv6 localhost"; + } + elsif (checkip(\$ip)) { + $tip = iplookup($ip); + $type = "$check, Remote IP"; + } + + if ($config{"RT\_$check\_BLOCK"}) { + if (checkip(\$ip) and !&ignoreip($ip)) { + my $perm = 0; + if ($config{"RT\_$check\_BLOCK"} == 1) {$perm = 1} + if (&ipblock($perm,"$tip $check limit exceeded",$ip,$ports{smtpauth},"in",$config{"RT\_$check\_BLOCK"},0,$mails,"RT\_$check\_LIMIT")) { + if ($config{DEBUG} >= 1) {logfile("debug: $ip already blocked")} + } + } + } + + my @alert = slurp("/usr/local/csf/tpl/relayalert.txt"); + my $block = "No"; + if ($config{"RT\_$check\_BLOCK"} == 1) {$block = "Permanent Block [RT\_$check\_LIMIT]"} + if ($config{"RT\_$check\_BLOCK"} > 1) {$block = "Temporary Block for ".$config{"RT\_$check\_BLOCK"}." seconds [RT\_$check\_LIMIT]"} + + my $allowip = &allowip($ip); + if ($allowip == 1 and $block ne "No") {$block .= " (IP match in csf.allow, block may not work)"} + if ($allowip == 2 and $block ne "No") {$block .= " (IP match in GLOBAL_ALLOW, block may not work)"} + + my @message; + foreach my $line (@alert) { + $line =~ s/\[ip\]/$tip/ig; + $line =~ s/\[block\]/$block/ig; + $line =~ s/\[check\]/$check/ig; + $line =~ s/\[type\]/$type/ig; + $line =~ s/\[count\]/$cnt/ig; + $line =~ s/\[emails\]/$mails/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + + if ($config{RT_ACTION} and -e "$config{RT_ACTION}" and -x "$config{RT_ACTION}") { + $0 = "lfd - (child) running RT_ACTION"; + system($config{RT_ACTION},$ip,$check,$block,$cnt,$mails); + } + + if ($config{DEBUG} >= 3) {$timer = &timer("stop","relayalert",$timer)} + $0 = "lfd - child closing"; + exit; + } + return; +} +# end relayalert +############################################################################### +# start portknocking +sub portknocking { + my $ip = shift; + my $port = shift; + + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","portknocking",$timer)} + logfile("*Port Knocking* port $port opened by $ip"); + + $0 = "lfd - (child) sending Port Knocking alert email for $ip"; + + my @alert = slurp("/usr/local/csf/tpl/portknocking.txt"); + my $tip = iplookup($ip); + my @message; + foreach my $line (@alert) { + $line =~ s/\[ip\]/$tip/ig; + $line =~ s/\[port\]/$port/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + + if ($config{DEBUG} >= 3) {$timer = &timer("stop","portknocking",$timer)} + $0 = "lfd - child closing"; + exit; + } + return; +} +# end portknocking +############################################################################### +# start blocklist +sub blocklist { + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","blocklist",$timer)} + $0 = "lfd - retrieving blocklists"; + + my $lockstr = "BLOCKLISTS"; + sysopen (my $THISLOCK, "/var/lib/csf/lock/$lockstr.lock", O_RDWR | O_CREAT) or &childcleanup("*Error* Unable to open /var/lib/csf/lock/$lockstr.lock"); + flock ($THISLOCK, LOCK_EX | LOCK_NB) or &childcleanup("*Lock Error* [$lockstr] still active - section skipped"); + print $THISLOCK time; + + $0 = "lfd - retrieving blocklists (waiting for list lock)"; + &listlock("lock"); + + my $skipcxs; + foreach my $name (keys %blocklists) { + if ($skipcxs) {next} + my $getlist = 0; + my $verbose = 1; + + if ($name =~ /^CXS_/ and $blocklists{$name}{url} =~ /download\.configserver\.com/) { + $blocklists{$name}{interval} = 600; + $verbose = 0; + } + if (-e "/var/lib/csf/csf.block.$name") { + my $mtime = (stat("/var/lib/csf/csf.block.$name"))[9]; + my $listtime = (time - $mtime); + if ($listtime >= $blocklists{$name}{interval}) {$getlist = 1} + } else {$getlist = 1} + + if ($getlist and ($name eq "SPAMDROP" or $name eq "SPAMEDROP")) { + my $tmpfile = "/var/lib/csf/$name.tmp"; + if (-e $tmpfile) { + my $mtime = (stat($tmpfile))[9]; + my $listtime = (time - $mtime); + if ($listtime < 7200) { + logfile("Unable to retrieve blocklist $name for the next ".(7200 - $listtime)." secs"); + $getlist = 0; + } else {unlink $tmpfile} + } else { + sysopen (my $OUT, $tmpfile, O_WRONLY | O_CREAT); + flock ($OUT, LOCK_EX); + print $OUT time; + close ($OUT); + } + } + + if ($getlist) { + $0 = "lfd - retrieving blocklist $name"; + my ($status, $text) = $urlget->urlget($blocklists{$name}{url}); + if ($status) { + logfile("Unable to retrieve blocklist $name - $text"); + if ($name =~ /^CXS_/ and $text =~ /Forbidden/) { + logfile("CXS Reputation service disabled [$text]"); + $skipcxs = 1; + unlink "/etc/cxs/cxs.reputation"; + } + next; + } + + my $blcidr = Net::CIDR::Lite->new; + eval {local $SIG{__DIE__} = undef; $blcidr->add_any("127.0.0.1")}; + my $blcidr6 = Net::CIDR::Lite->new; + eval {local $SIG{__DIE__} = undef; $blcidr6->add("::1/128")}; + foreach my $bl (keys %blocklists) { + if ($bl eq $name) {next} + if (-e "/var/lib/csf/csf.block.$bl") { + sysopen (my $BLOCK, "/var/lib/csf/csf.block.$bl", O_RDWR | O_CREAT) or &childcleanup(__LINE__,"*Error* Cannot open out file: $!"); + flock ($BLOCK, LOCK_SH); + while (my $ipstr = <$BLOCK>) { + chomp $ipstr; + my $iptype = checkip(\$ipstr); + if ($iptype == 4) { + eval {local $SIG{__DIE__} = undef; $blcidr->add_any($ipstr)}; + } + elsif ($iptype == 6 and $config{IPV6}) { + eval {local $SIG{__DIE__} = undef; $blcidr6->add_any($ipstr)}; + } + } + close ($BLOCK); + } + } + + if (&csflock) {&lockfail("BLOCKLIST")} + if ($verbose) {logfile("Retrieved and blocking blocklist $name IP address ranges")} + my $drop = $config{DROP}; + if ($config{DROP_IP_LOGGING}) {$drop = "BLOCKDROP"} + + if ($text =~ m[^PK\x03\x04] or $text =~ m[^PK\x05\x06] or $text =~ m[^PK\x07\x08]) { + sysopen (my $BLOCK, "/var/lib/csf/csf.block.${name}.zip", O_WRONLY | O_CREAT) or &childcleanup(__LINE__,"*Error* Cannot open out file: $!"); + flock ($BLOCK, LOCK_EX); + print $BLOCK $text; + close ($BLOCK); + my @data; + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die}; + alarm(180); + @data = &syscommand(__LINE__,$config{UNZIP},"-p","/var/lib/csf/csf.block.${name}.zip"); + alarm(0); + }; + alarm(0); + if ($@) { + logfile("CC Error: Unable to unzip Blocklist $name [/var/lib/csf/csf.block.${name}.zip] - timeout"); + $text = ""; + } else { + logfile("CC: Unzipped Blocklist $name [/var/lib/csf/csf.block.${name}.zip]"); + $text = join("\n",@data); + } + } + + sysopen (my $BLOCK, "/var/lib/csf/csf.block.$name", O_WRONLY | O_CREAT) or &childcleanup(__LINE__,"*Error* Cannot open out file: $!"); + flock ($BLOCK, LOCK_EX); + seek ($BLOCK, 0, 0); + truncate ($BLOCK, 0); + my $count = 0; + my @blocklist = split (/\n/,$text); + my %seen; + my @uniqueips = grep { ! $seen{ $_ }++ } @blocklist; + if ($config{FASTSTART}) {$faststart = 1} + foreach my $line (@uniqueips) { + if ($line =~ /^\#/) {next} + if ($line =~ /($ipv4reg(\/\d+)?)/) { + my $iprange = $1; + if ($name eq "DSHIELD" and $iprange !~/\/24/) {$iprange .= "/24"} + if (checkip(\$iprange)) { + my $skip = 0; + eval {local $SIG{__DIE__} = undef; $skip = $blcidr->find($iprange)}; + if ($skip) { + if ($config{DEBUG} >= 1) {logfile("debug: BLOCKLIST [$name] duplicate skipped: [$iprange]")} + next; + } + $count++; + if ($blocklists{$name}{max} > 0 and $count > $blocklists{$name}{max}) {last} + print $BLOCK "$iprange\n"; + } + } + elsif ($line =~ /($ipv6reg(\/\d+)?)/) { + my $iprange = $1; + if (checkip(\$iprange)) { + my $skip = 0; + eval {local $SIG{__DIE__} = undef; $skip = $blcidr6->find($iprange)}; + if ($skip) { + if ($config{DEBUG} >= 1) {logfile("debug: BLOCKLIST [$name] duplicate skipped: [$iprange]")} + next; + } + $count++; + if ($blocklists{$name}{max} > 0 and $count > $blocklists{$name}{max}) {last} + print $BLOCK "$iprange\n"; + } + } + } + close ($BLOCK); + + if ($config{LF_IPSET}) { + open (my $BLOCK, "<", "/var/lib/csf/csf.block.$name"); + flock ($BLOCK, LOCK_SH); + my @ipset6; + while (my $line = <$BLOCK>) { + chomp $line; + if ($line =~ /^\#/) {next} + if ($line =~ /($ipv4reg(\/\d+)?)/) { + my $iprange = $1; + push @ipset,"add new_$name $iprange\n"; + } + elsif ($line =~ /($ipv6reg(\/\d+)?)/) { + my $iprange = $1; + push @ipset6,"add new_6_$name $iprange\n"; + } + } + close ($BLOCK); + &ipsetrestore("new_$name"); + &ipsetswap("new_$name","bl_$name"); + if ($config{IPV6}) { + @ipset = @ipset6; + &ipsetrestore("new_6_$name"); + &ipsetswap("new_6_$name","bl_6_$name"); + } + } else { + if ($config{SAFECHAINUPDATE}) { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -N NEW$name"); + } else { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -F $name"); + } + if ($config{IPV6}) { + if ($config{SAFECHAINUPDATE}) { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -N NEW$name"); + } else { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -F $name"); + } + } + open (my $BLOCK, "<", "/var/lib/csf/csf.block.$name"); + flock ($BLOCK, LOCK_SH); + while (my $line = <$BLOCK>) { + chomp $line; + if ($line =~ /^\#/) {next} + if ($line =~ /($ipv4reg(\/\d+)?)/) { + my $iprange = $1; + if ($config{SAFECHAINUPDATE}) { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -A NEW$name -s $iprange -j $drop"); + } else { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -A $name -s $iprange -j $drop"); + } + } + elsif ($line =~ /($ipv6reg(\/\d+)?)/) { + my $iprange = $1; + if ($config{SAFECHAINUPDATE}) { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -A NEW$name -s $iprange -j $drop"); + } else { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -A $name -s $iprange -j $drop"); + } + } + } + close ($BLOCK); + 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})) { + if ($config{SAFECHAINUPDATE}) { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -I NEWBOGON -i $device -j RETURN"); + } else { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -I BOGON -i $device -j RETURN"); + } + } + } + if ($config{SAFECHAINUPDATE}) { + if ($cxsreputation and $name =~ /^CXS_/ and $name ne "CXS_ALL" and $cxsports{$name} ne "") { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -A LOCALINPUT -p tcp -m multiport --dport $cxsports{$name} $ethdevin -j NEW$name"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -D LOCALINPUT -p tcp -m multiport --dport $cxsports{$name} $ethdevin -j $name"); + } else { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -A LOCALINPUT $ethdevin -j NEW$name"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -D LOCALINPUT $ethdevin -j $name"); + } + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -F $name"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -X $name"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -E NEW$name $name"); + if ($config{IPV6}) { + if ($cxsreputation and $name =~ /^CXS_/ and $name ne "CXS_ALL" and $cxsports{$name} ne "") { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -A LOCALINPUT -p tcp -m multiport --dport $cxsports{$name} $ethdevin -j NEW$name"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -D LOCALINPUT -p tcp -m multiport --dport $cxsports{$name} $ethdevin -j $name"); + } else { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -A LOCALINPUT $ethdevin -j NEW$name"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -D LOCALINPUT $ethdevin -j $name"); + } + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -F $name"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -X $name"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -E NEW$name $name"); + } + } + } + } + } + + &listlock("unlock"); + close ($THISLOCK ); + if ($config{DEBUG} >= 3) {$timer = &timer("stop","blocklist",$timer)} + $0 = "lfd - child closing"; + exit; + } + return; +} +# end blocklist +############################################################################### +# start countrycode +sub countrycode { + my $force = shift; + + if ($config{MM_LICENSE_KEY} eq "" and $config{CC_SRC} eq "1") { + logfile("CC Error: Country Code Lookups setting MM_LICENSE_KEY must be set in /etc/csf/csf.conf to continue using the MaxMind databases"); + return; + } + + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","countrycode",$timer)} + $0 = "lfd - retrieving countrycode lists"; + + my $lockstr = "COUNTRYCODE"; + sysopen (my $THISLOCK, "/var/lib/csf/lock/$lockstr.lock", O_RDWR | O_CREAT) or &childcleanup("*Error* Unable to open /var/lib/csf/lock/$lockstr.lock"); + flock ($THISLOCK, LOCK_EX | LOCK_NB) or &childcleanup("*Lock Error* [$lockstr] still active - section skipped"); + print $THISLOCK time; + + $0 = "lfd - retrieving countrycode lists (waiting for list lock)"; + &listlock("lock"); + $0 = "lfd - retrieving countrycode lists"; + + my $drop = $config{DROP}; + if ($config{DROP_IP_LOGGING}) {$drop = "CCDROP"} + + my $redo_deny = 0; + my $redo_allow = 0; + my $redo_allow_filter = 0; + my $redo_allow_ports = 0; + my $redo_deny_ports = 0; + my $redo_allow_smtpauth = 0; + $config{CC_DENY} =~ s/\s//g; + $config{CC_ALLOW} =~ s/\s//g; + $config{CC_ALLOW_FILTER} =~ s/\s//g; + $config{CC_ALLOW_PORTS} =~ s/\s//g; + $config{CC_DENY_PORTS} =~ s/\s//g; + $config{CC_ALLOW_SMTPAUTH} =~ s/\s//g; + my $getgeo = 0; + my %cclist; + + if ($config{CC_SRC} eq "" or $config{CC_SRC} eq "1") { + unless (-e "/var/lib/csf/Geo/GeoLite2-Country-Blocks-IPv4.csv") {$getgeo = 1} + if (-z "/var/lib/csf/Geo/GeoLite2-Country-Blocks-IPv4.csv") {$getgeo = 1} + unless (-e "/var/lib/csf/Geo/GeoLite2-ASN-Blocks-IPv4.csv") {$getgeo = 1} + if (-z "/var/lib/csf/Geo/GeoLite2-ASN-Blocks-IPv4.csv") {$getgeo = 1} + + if (-e "/var/lib/csf/Geo/GeoLite2-Country-Blocks-IPv4.csv") { + my $mtime = (stat("/var/lib/csf/Geo/GeoLite2-Country-Blocks-IPv4.csv"))[9]; + my $days = int((time - $mtime) / 86400); + if ($days >= $config{CC_INTERVAL}) {$getgeo = 1} + } else {$getgeo = 1} + if ($getgeo) { + unless (-e $config{UNZIP}) { + logfile("Error: unzip binary ($config{UNZIP}) does not exist"); + exit; + } + logfile("CC: Retrieving $config{cc_src} Country database [$config{cc_country}]"); + my ($status, $text) = $urlget->urlget("$config{cc_country}","/var/lib/csf/Geo/GeoLite2-Country-CSV.zip"); + if ($status) { + logfile("CC Error: Unable to retrieve $config{cc_src} Country database [$config{cc_country}] - $text"); + } else { + if (-e "/var/lib/csf/Geo/GeoLite2-Country-Blocks-IPv4.csv") {unlink "/var/lib/csf/Geo/GeoLite2-Country-Blocks-IPv4.csv"} + my @data; + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die}; + alarm(180); + @data = &syscommand(__LINE__,$config{UNZIP},"-DDjod","/var/lib/csf/Geo/","/var/lib/csf/Geo/GeoLite2-Country-CSV.zip"); + alarm(0); + }; + alarm(0); + if ($@) { + logfile("CC Error: Unable to unzip $config{cc_src} Country database /var/lib/csf/Geo/GeoLite2-Country-CSV.zip - timeout"); + } + if (-z "/var/lib/csf/Geo/GeoLite2-Country-Blocks-IPv4.csv" or !(-e "/var/lib/csf/Geo/GeoLite2-Country-Blocks-IPv4.csv")) { + logfile("CC Error: GeoLite2-Country-Blocks-IPv4.csv empty or missing"); + } + foreach my $cc (split(/\,/,"$config{CC_DENY},$config{CC_ALLOW},$config{CC_ALLOW_FILTER},$config{CC_ALLOW_PORTS},$config{CC_DENY_PORTS},$config{CC_ALLOW_SMTPAUTH}")) { + if ($cc and length($cc) == 2) { + $cc = lc $cc; + $cclist{$cc} = 1; + } + } + } + logfile("CC: Retrieving $config{asn_src} ASN database [$config{cc_asn}]"); + ($status, $text) = $urlget->urlget("$config{cc_asn}","/var/lib/csf/Geo/GeoLite2-ASN-CSV.zip"); + if ($status) { + logfile("CC Error: Unable to retrieve $config{asn_src} ASN database [$config{cc_asn}] - $text"); + } else { + if (-e "/var/lib/csf/Geo/GeoLite2-ASN-Blocks-IPv4.csv") {unlink "/var/lib/csf/Geo/GeoLite2-ASN-Blocks-IPv4.csv"} + my @data; + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die}; + alarm(180); + @data = &syscommand(__LINE__,$config{UNZIP},"-DDjod","/var/lib/csf/Geo/","/var/lib/csf/Geo/GeoLite2-ASN-CSV.zip"); + alarm(0); + }; + alarm(0); + if ($@) { + logfile("CC Error: Unable to unzip $config{cc_src} Country database /var/lib/csf/Geo/GeoLite2-ASN-CSV.zip - timeout"); + } + if (-z "/var/lib/csf/Geo/GeoLite2-ASN-Blocks-IPv4.csv" or !(-e "/var/lib/csf/Geo/GeoLite2-ASN-Blocks-IPv4.csv")) { + logfile("CC Error: GeoLite2-ASN-Blocks-IPv4.csv empty or missing"); + } + foreach my $cc (split(/\,/,"$config{CC_DENY},$config{CC_ALLOW},$config{CC_ALLOW_FILTER},$config{CC_ALLOW_PORTS},$config{CC_DENY_PORTS},$config{CC_ALLOW_SMTPAUTH}")) { + if ($cc and length($cc) > 2) { + $cc = lc $cc; + $cclist{$cc} = 1; + } + } + } + unlink glob "/var/lib/csf/Geo/*.zip"; + unlink glob "/var/lib/csf/Geo/*-Locations-de.csv"; + unlink glob "/var/lib/csf/Geo/*-Locations-es.csv"; + unlink glob "/var/lib/csf/Geo/*-Locations-fr.csv"; + unlink glob "/var/lib/csf/Geo/*-Locations-ja.csv"; + unlink glob "/var/lib/csf/Geo/*-Locations-pt-BR.csv"; + unlink glob "/var/lib/csf/Geo/*-Locations-ru.csv"; + unlink glob "/var/lib/csf/Geo/*-Locations-zh-CN.csv"; + unlink glob "/var/lib/csf/Geo/*.dat"; + unlink glob "/var/lib/csf/zone/*.zip"; + unlink glob "/var/lib/csf/zone/*.csv"; + unlink "/var/lib/csf/Geo/GeoIPv6.csv"; + } + + $0 = "lfd - processing countrycode lists"; + foreach my $cc (split(/\,/,"$config{CC_DENY},$config{CC_ALLOW},$config{CC_ALLOW_FILTER},$config{CC_ALLOW_PORTS},$config{CC_DENY_PORTS},$config{CC_ALLOW_SMTPAUTH}")) { + if ($cc) { + $cc = lc $cc; + if (-e "/var/lib/csf/zone/$cc.zone") { + my $mtime = (stat("/var/lib/csf/zone/$cc.zone"))[9]; + my $days = int((time - $mtime) / 86400); + if ($days >= $config{CC_INTERVAL}) {$getgeo = 1; $cclist{$cc} = 1} + } else {$getgeo = 1; $cclist{$cc} = 1} + if (-z "/var/lib/csf/zone/$cc.zone") {$getgeo = 1; $cclist{$cc} = 1} + + if ($cclist{$cc}) { + if ($config{CC_DENY} =~ /\b$cc\b/i) {$redo_deny = 1} + if ($config{CC_ALLOW} =~ /\b$cc\b/i) {$redo_allow = 1} + if ($config{CC_ALLOW_FILTER} =~ /\b$cc\b/i) {$redo_allow_filter = 1} + if ($config{CC_ALLOW_PORTS} =~ /\b$cc\b/i) {$redo_allow_ports = 1} + if ($config{CC_DENY_PORTS} =~ /\b$cc\b/i) {$redo_deny_ports = 1} + if ($config{CC_ALLOW_SMTPAUTH} =~ /\b$cc\b/i) {$redo_allow_smtpauth = 1} + } + } + } + + if ($getgeo) { + logfile("CC: Processing $config{cc_src} Country/ASN database"); + my %dcidr; + my %geoid; + open (my $GEO, "<", "/var/lib/csf/Geo/GeoLite2-Country-Locations-en.csv"); + flock ($GEO, LOCK_SH); + while (my $record = <$GEO>) { + chomp $record; + $record =~ s/\"//g; + my ($geoname_id,undef,undef,undef,$country_iso_code,undef) = split (/\,/,$record); + foreach my $cc (keys %cclist) { + if (uc $cc eq uc $country_iso_code) { + $geoid{$cc}{$geoname_id} = 1; + } + } + } + close ($GEO); + open (my $IN, "<", "/var/lib/csf/Geo/GeoLite2-Country-Blocks-IPv4.csv"); + flock ($IN, LOCK_SH); + while (my $record = <$IN>) { + chomp $record; + $record =~ s/\"//g; + my ($range,$geoname_id,undef) = split (/\,/,$record); + foreach my $cc (keys %cclist) { + if ($geoid{$cc}{$geoname_id}) { + $dcidr{$cc}{$range} = 1; + } + } + } + close ($IN); + open ($IN, "<", "/var/lib/csf/Geo/GeoLite2-ASN-Blocks-IPv4.csv"); + flock ($IN, LOCK_SH); + while (my $record = <$IN>) { + chomp $record; + $record =~ s/\"//g; + my ($range,$asn,undef) = split (/\,/,$record); + foreach my $cc (keys %cclist) { + if (uc($cc) =~ /AS(\d+)/) { + if ($1 eq $asn) { + $dcidr{$cc}{$range} = 1; + } + } + } + } + close ($IN); + foreach my $cc (keys %cclist) { + logfile("CC: Extracting zone from $config{cc_src} Country/ASN database for [".uc($cc)."]"); + if (keys %{$dcidr{$cc}} eq 0) { + if (length($cc) == 2) { + logfile("CC: No entries found for [".uc($cc)."] in /var/lib/csf/Geo/GeoLite2-Country-Blocks-IPv4.csv"); + } else { + logfile("CC: No entries found for [".uc($cc)."] in /var/lib/csf/Geo/GeoLite2-ASN-Blocks-IPv4.csv"); + } + } else { + sysopen (my $CIDROUT, "/var/lib/csf/zone/$cc.zone", O_WRONLY | O_CREAT); + flock ($CIDROUT, LOCK_EX); + seek ($CIDROUT, 0, 0); + truncate ($CIDROUT, 0); + foreach my $key (keys %{$dcidr{$cc}}) {print $CIDROUT "$key\n"} + close ($CIDROUT); + } + } + } + } elsif ($config{CC_SRC} eq "2") { + unless (-e "/var/lib/csf/Geo/ip2asn-combined.tsv") {$getgeo = 1} + if (-z "/var/lib/csf/Geo/ip2asn-combined.tsv") {$getgeo = 1} + + if ($getgeo) { + unless (-e $config{UNZIP}) { + logfile("Error: unzip binary ($config{UNZIP}) does not exist"); + exit; + } + logfile("CC: Retrieving $config{asn_src} ASN database [$config{cc_asn}]"); + my ($status, $text) = $urlget->urlget("$config{cc_asn}","/var/lib/csf/Geo/ip2asn-combined.tsv.gz"); + if ($status) { + logfile("CC Error: Unable to retrieve $config{asn_src} ASN database [$config{cc_asn}] - $text"); + } else { + if (-e "/var/lib/csf/Geo/ip2asn-combined.tsv") {unlink "/var/lib/csf/Geo/ip2asn-combined.tsv"} + my @data; + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die}; + alarm(180); + @data = &syscommand(__LINE__,$config{GUNZIP},"/var/lib/csf/Geo/ip2asn-combined.tsv.gz"); + alarm(0); + }; + alarm(0); + if ($@) { + logfile("CC Error: Unable to unzip $config{cc_src} Country database /var/lib/csf/Geo/ip2asn-combined.tsv.gz - timeout"); + } + if (-z "/var/lib/csf/Geo/ip2asn-combined.tsv" or !(-e "/var/lib/csf/Geo/ip2asn-combined.tsv")) { + logfile("CC Error: ip2asn-combined.tsv empty or missing"); + } + foreach my $cc (split(/\,/,"$config{CC_DENY},$config{CC_ALLOW},$config{CC_ALLOW_FILTER},$config{CC_ALLOW_PORTS},$config{CC_DENY_PORTS},$config{CC_ALLOW_SMTPAUTH}")) { + if ($cc and length($cc) > 2) { + $cc = lc $cc; + $cclist{$cc} = 1; + } + } + } + } + + $0 = "lfd - processing countrycode lists"; + foreach my $cc (split(/\,/,"$config{CC_DENY},$config{CC_ALLOW},$config{CC_ALLOW_FILTER},$config{CC_ALLOW_PORTS},$config{CC_DENY_PORTS},$config{CC_ALLOW_SMTPAUTH}")) { + if ($cc) { + $cc = lc $cc; + if (-e "/var/lib/csf/zone/$cc.zone") { + my $mtime = (stat("/var/lib/csf/zone/$cc.zone"))[9]; + my $days = int((time - $mtime) / 86400); + if ($days >= $config{CC_INTERVAL}) {$getgeo = 1; $cclist{$cc} = 1} + } else {$getgeo = 1; $cclist{$cc} = 1} + if (-z "/var/lib/csf/zone/$cc.zone") {$getgeo = 1; $cclist{$cc} = 1} + + if ($cclist{$cc}) { + if ($config{CC_DENY} =~ /\b$cc\b/i) {$redo_deny = 1} + if ($config{CC_ALLOW} =~ /\b$cc\b/i) {$redo_allow = 1} + if ($config{CC_ALLOW_FILTER} =~ /\b$cc\b/i) {$redo_allow_filter = 1} + if ($config{CC_ALLOW_PORTS} =~ /\b$cc\b/i) {$redo_allow_ports = 1} + if ($config{CC_DENY_PORTS} =~ /\b$cc\b/i) {$redo_deny_ports = 1} + if ($config{CC_ALLOW_SMTPAUTH} =~ /\b$cc\b/i) {$redo_allow_smtpauth = 1} + } + } + } + + if ($getgeo) { + logfile("CC: Processing $config{asn_src} ASN database"); + my %dcidr; + open ($IN, "<", "/var/lib/csf/Geo/ip2asn-combined.tsv"); + flock ($IN, LOCK_SH); + while (my $record = <$IN>) { + chomp $record; + $record =~ s/\"//g; + my ($start,$end,$asn,undef) = split (/\t/,$record); + if (checkip($start) == 6) {last} + foreach my $cc (keys %cclist) { + if (uc($cc) =~ /AS(\d+)/) { + if ($1 eq $asn) { + my $ipscidr = Net::CIDR::Lite->new; + eval {local $SIG{__DIE__} = undef; $ipscidr->add_range("$start-$end")}; + my @cidr_list = $ipscidr->list; + foreach my $list (@cidr_list) { + $dcidr{$cc}{$list} = 1; + } + } + } + } + } + close ($IN); + foreach my $cc (keys %cclist) { + if (length($cc) > 2) { + logfile("CC: Extracting zone from $config{asn_src} ASN database for [".uc($cc)."]"); + if (keys %{$dcidr{$cc}} eq 0) { + logfile("CC: No entries found for [".uc($cc)."] in /var/lib/csf/Geo/ip2asn-combined.tsv"); + } else { + sysopen (my $CIDROUT, "/var/lib/csf/zone/$cc.zone", O_WRONLY | O_CREAT); + flock ($CIDROUT, LOCK_EX); + seek ($CIDROUT, 0, 0); + truncate ($CIDROUT, 0); + foreach my $key (keys %{$dcidr{$cc}}) {print $CIDROUT "$key\n"} + close ($CIDROUT); + } + } + elsif (length($cc) == 2) { + logfile("CC: Retrieving $config{ccl_src} Country Code Zone [".uc($cc)."] from https://www.ipdeny.com"); + my ($status, $text) = $urlget->urlget("https://www.ipdeny.com/ipblocks/data/aggregated/${cc}-aggregated.zone","/var/lib/csf/zone/$cc.zone"); + if ($status) { + logfile("CC Error: Unable to retrieve $config{ccl_src} Country Code Zone [".uc($cc)."] from https://www.ipdeny.com/ - $text"); + } else { + logfile("CC: Country Code Zone [".uc($cc)."] retrieved"); + } + sleep 1; + } + } + } + } + + if ($force) { + $redo_deny = 1; + $redo_allow = 1; + $redo_allow_filter = 1; + $redo_allow_ports = 1; + $redo_deny_ports = 1; + $redo_allow_smtpauth = 1; + } + + if ($config{LF_IPSET}) { + my $cclist; + my $cnt = 0; + if ($redo_deny) {$cclist .= $config{CC_DENY}.","} + if ($redo_allow) {$cclist .= $config{CC_ALLOW}.","} + if ($redo_allow_filter) {$cclist .= $config{CC_ALLOW_FILTER}.","} + if ($redo_allow_ports) {$cclist .= $config{CC_ALLOW_PORTS}.","} + if ($redo_deny_ports) {$cclist .= $config{CC_DENY_PORTS}} + if ($config{CC_ALLOW_FILTER} and $redo_allow_filter) {&iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -F CC_ALLOWF")} + foreach my $cc (split(/\,/,$cclist)) { + if ($cc eq "") {next} + undef @ipset; + $cc = lc $cc; + if ($config{CC_ALLOW_FILTER} and $redo_allow_filter) { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -A CC_ALLOWF -m set --match-set cc_$cc src -j RETURN");} + if (-e "/var/lib/csf/zone/$cc.zone") { + logfile("CC: Repopulating ipset cc_$cc with IP addresses from [".uc($cc)."]"); + open (my $IN, "<", "/var/lib/csf/zone/$cc.zone"); + flock ($IN, LOCK_SH); + while (my $line = <$IN>) { + chomp $line; + 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 new_$cc $ip"; + $cnt++; + } + } + &ipsetrestore("new_$cc"); + &ipsetswap("new_$cc","cc_$cc"); + } + } + if ($config{CC_ALLOW_FILTER} and $redo_allow_filter and $cnt > 0) { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -A CC_ALLOWF -j $drop"); + if ($config{LF_SPI}) { + my $statemodule = "-m state --state"; + if ($config{USE_CONNTRACK}) {$statemodule = "-m conntrack --ctstate"} + if ($config{USE_FTPHELPER}) { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -I CC_ALLOWF $ethdevin $statemodule RELATED -m helper --helper ftp -j $accept"); + + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -I CC_ALLOWF $ethdevin $statemodule ESTABLISHED -j $accept"); + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -I CC_ALLOWF $ethdevin $statemodule ESTABLISHED,RELATED -j $accept"); + } + } + } + } else { + if ($config{CC_DENY} and $redo_deny) { + if (&csflock) {&lockfail("CC_DENY")} + if ($config{SAFECHAINUPDATE}) { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -N NEWCC_DENY"); + } else { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -F CC_DENY"); + } + foreach my $cc (split(/\,/,$config{CC_DENY})) { + $cc = lc $cc; + if (-e "/var/lib/csf/zone/$cc.zone") { + if ($config{FASTSTART}) {$faststart = 1} + logfile("CC: Repopulating CC_DENY with IP addresses from [".uc($cc)."]"); + open (my $IN, "<", "/var/lib/csf/zone/$cc.zone"); + flock ($IN, LOCK_SH); + while (my $line = <$IN>) { + chomp $line; + 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} + } + if ($config{SAFECHAINUPDATE}) { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -A NEWCC_DENY -s $ip -j $drop"); + } else { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -A CC_DENY -s $ip -j $drop"); + } + } + } + close ($IN); + if ($config{FASTSTART}) {&faststart("CC_DENY [".uc($cc)."]")} + logfile("CC: Finished repopulating CC_DENY with IP addresses from [".uc($cc)."]"); + } + } + if ($config{SAFECHAINUPDATE}) { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -A LOCALINPUT $ethdevin -j NEWCC_DENY"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -D LOCALINPUT $ethdevin -j CC_DENY"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -F CC_DENY"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -X CC_DENY"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -E NEWCC_DENY CC_DENY"); + } + } + + if ($config{CC_ALLOW} and $redo_allow) { + if (&csflock) {&lockfail("CC_ALLOW")} + if ($config{SAFECHAINUPDATE}) { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -N NEWCC_ALLOW"); + } else { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -F CC_ALLOW"); + } + foreach my $cc (split(/\,/,$config{CC_ALLOW})) { + $cc = lc $cc; + if (-e "/var/lib/csf/zone/$cc.zone") { + if ($config{FASTSTART}) {$faststart = 1} + logfile("CC: Repopulating CC_ALLOW with IP addresses from [".uc($cc)."]"); + open (my $IN, "<", "/var/lib/csf/zone/$cc.zone"); + flock ($IN, LOCK_SH); + while (my $line = <$IN>) { + chomp $line; + 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} + } + if ($config{SAFECHAINUPDATE}) { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -A NEWCC_ALLOW -s $ip -j $accept"); + } else { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -A CC_ALLOW -s $ip -j $accept"); + } + } + } + close ($IN); + if ($config{FASTSTART}) {&faststart("CC_ALLOW [".uc($cc)."]")} + logfile("CC: Finished repopulating CC_ALLOW with IP addresses from [".uc($cc)."]"); + } + } + if ($config{SAFECHAINUPDATE}) { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -I LOCALINPUT $ethdevin -j NEWCC_ALLOW"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -D LOCALINPUT $ethdevin -j CC_ALLOW"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -F CC_ALLOW"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -X CC_ALLOW"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -E NEWCC_ALLOW CC_ALLOW"); + } + } + + if ($config{CC_ALLOW_FILTER} and $redo_allow_filter) { + my $cnt = 0; + if (&csflock) {&lockfail("CC_ALLOW_FILTER")} + if ($config{SAFECHAINUPDATE}) { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -N NCC_ALLOWF"); + } else { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -F CC_ALLOWF"); + } + foreach my $cc (split(/\,/,$config{CC_ALLOW_FILTER})) { + $cc = lc $cc; + if (-e "/var/lib/csf/zone/$cc.zone") { + if ($config{FASTSTART}) {$faststart = 1} + logfile("CC: Repopulating CC_ALLOWF with IP addresses from [".uc($cc)."]"); + open (my $IN, "<", "/var/lib/csf/zone/$cc.zone"); + flock ($IN, LOCK_SH); + while (my $line = <$IN>) { + chomp $line; + 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} + } + $cnt++; + if ($config{SAFECHAINUPDATE}) { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -A NCC_ALLOWF -s $ip -j RETURN"); + } else { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -A CC_ALLOWF -s $ip -j RETURN"); + } + } + } + close ($IN); + if ($config{FASTSTART}) {&faststart("CC_ALLOW_FILTER [".uc($cc)."]")} + logfile("CC: Finished repopulating CC_ALLOWF with IP addresses from [".uc($cc)."]"); + } + } + if ($config{SAFECHAINUPDATE}) { + if ($cnt > 0) {&iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -A NCC_ALLOWF -j $drop")} + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -A LOCALINPUT $ethdevin -j NCC_ALLOWF"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -D LOCALINPUT $ethdevin -j CC_ALLOWF"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -F CC_ALLOWF"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -X CC_ALLOWF"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -E NCC_ALLOWF CC_ALLOWF"); + } else { + if ($cnt > 0) { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -A CC_ALLOWF -j $drop"); + if ($config{LF_SPI}) { + my $statemodule = "-m state --state"; + if ($config{USE_CONNTRACK}) {$statemodule = "-m conntrack --ctstate"} + if ($config{USE_FTPHELPER}) { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -I CC_ALLOWF $ethdevin $statemodule RELATED -m helper --helper ftp -j $accept"); + + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -I CC_ALLOWF $ethdevin $statemodule ESTABLISHED -j $accept"); + } else { + &syscommand(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -I CC_ALLOWF $ethdevin $statemodule ESTABLISHED,RELATED -j $accept"); + } + } + } + } + } + + if ($config{CC_ALLOW_PORTS} and $redo_allow_ports) { + my $cnt = 0; + if (&csflock) {&lockfail("CC_ALLOW_PORTS")} + if ($config{SAFECHAINUPDATE}) { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -N NCC_ALLOWP"); + } else { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -F CC_ALLOWP"); + } + foreach my $cc (split(/\,/,$config{CC_ALLOW_PORTS})) { + $cc = lc $cc; + if (-e "/var/lib/csf/zone/$cc.zone") { + if ($config{FASTSTART}) {$faststart = 1} + logfile("CC: Repopulating CC_ALLOWP with IP addresses from [".uc($cc)."]"); + open (my $IN, "<", "/var/lib/csf/zone/$cc.zone"); + flock ($IN, LOCK_SH); + while (my $line = <$IN>) { + chomp $line; + 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} + } + $cnt++; + if ($config{SAFECHAINUPDATE}) { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -A NCC_ALLOWP -s $ip -j CC_ALLOWPORTS"); + } else { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -A CC_ALLOWP -s $ip -j CC_ALLOWPORTS"); + } + } + } + close ($IN); + if ($config{FASTSTART}) {&faststart("CC_ALLOW_PORTS [".uc($cc)."]")} + logfile("CC: Finished repopulating CC_ALLOWP with IP addresses from [".uc($cc)."]"); + } + } + if ($config{SAFECHAINUPDATE}) { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -A LOCALINPUT $ethdevin -j NCC_ALLOWP"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -D LOCALINPUT $ethdevin -j CC_ALLOWP"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -F CC_ALLOWP"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -X CC_ALLOWP"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -E NCC_ALLOWP CC_ALLOWP"); + } + } + + if ($config{CC_DENY_PORTS} and $redo_deny_ports) { + my $cnt = 0; + if (&csflock) {&lockfail("CC_DENY_PORTS")} + if ($config{SAFECHAINUPDATE}) { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -N NCC_DENYP"); + } else { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -F CC_DENYP"); + } + foreach my $cc (split(/\,/,$config{CC_DENY_PORTS})) { + $cc = lc $cc; + if (-e "/var/lib/csf/zone/$cc.zone") { + if ($config{FASTSTART}) {$faststart = 1} + logfile("CC: Repopulating CC_DENYP with IP addresses from [".uc($cc)."]"); + open (my $IN, "<", "/var/lib/csf/zone/$cc.zone"); + flock ($IN, LOCK_SH); + while (my $line = <$IN>) { + chomp $line; + 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} + } + $cnt++; + if ($config{SAFECHAINUPDATE}) { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -A NCC_DENYP -s $ip -j CC_DENYPORTS"); + } else { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -A CC_DENYP -s $ip -j CC_DENYPORTS"); + } + } + } + close ($IN); + if ($config{FASTSTART}) {&faststart("CC_DENY_PORTS [".uc($cc)."]")} + logfile("CC: Finished repopulating CC_DENYP with IP addresses from [".uc($cc)."]"); + } + } + if ($config{SAFECHAINUPDATE}) { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -A LOCALINPUT $ethdevin -j NCC_DENYP"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -D LOCALINPUT $ethdevin -j CC_DENYP"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -F CC_DENYP"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -X CC_DENYP"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -E NCC_DENYP CC_DENYP"); + } + } + } + if ($config{CC6_LOOKUPS} and $config{IPV6}) { + &countrycode6($force); + } + + if ($config{CC_ALLOW_SMTPAUTH} and $config{SMTPAUTH_RESTRICT} and $redo_allow_smtpauth) { + 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"} + } + logfile("CC: Finished repopulating /etc/exim.smtpauth with IPv4 addresses from [".uc($cc)."]"); + } + 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); + 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"} + } + logfile("CC: Finished repopulating /etc/exim.smtpauth with IPv6 addresses from [".uc($cc)."]"); + } + } + close ($SMTPAUTH); + chmod (0644,"/etc/exim.smtpauth"); + } + + &listlock("unlock"); + close ($THISLOCK ); + if ($config{DEBUG} >= 3) {$timer = &timer("stop","countrycode",$timer)} + $0 = "lfd - child closing"; + exit; + } + return; +} +# end countrycode +############################################################################### +# start countrycodelookups +sub countrycodelookups { + my $force = shift; + if ($config{CC_LOOKUPS} == 4) {return} + + if ($config{MM_LICENSE_KEY} eq "" and $config{CC_SRC} eq "1") { + logfile("CC Error: Country Code Filters setting MM_LICENSE_KEY must be set in /etc/csf/csf.conf to continue using the MaxMind databases"); + return; + } + + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","countrycodelookups",$timer)} + $0 = "lfd - retrieving countrycode lookups"; + + my $lockstr = "CC_LOOKUPS"; + sysopen (my $THISLOCK, "/var/lib/csf/lock/$lockstr.lock", O_RDWR | O_CREAT) or &childcleanup("*Error* Unable to open /var/lib/csf/lock/$lockstr.lock"); + flock ($THISLOCK, LOCK_EX | LOCK_NB) or &childcleanup("*Lock Error* [$lockstr] still active - section skipped"); + print $THISLOCK time; + + $0 = "lfd - retrieving countrycodelookups lists (waiting for list lock)"; + &listlock("lock"); + $0 = "lfd - retrieving countrycodelookups lists"; + + if ($config{CC_SRC} eq "" or $config{CC_SRC} eq "1") { + my $getgeo = 0; + my $geofile = "/var/lib/csf/Geo/GeoLite2-Country-Blocks-IPv4.csv"; + if ($config{CC_LOOKUPS} == 2 or $config{CC_LOOKUPS} == 3) {$geofile = "/var/lib/csf/Geo/GeoLite2-City-Blocks-IPv4.csv"} + if (-e $geofile) { + if (-z $geofile) {$getgeo = 1} + my $mtime = (stat($geofile))[9]; + my $days = int((time - $mtime) / 86400); + if ($days >= $config{CC_INTERVAL}) {$getgeo = 1} + + if ($config{CC_LOOKUPS} == 3) { + my $geofile = "/var/lib/csf/Geo/GeoLite2-ASN-Blocks-IPv4.csv"; + if (-z $geofile) {$getgeo = 1} + my $mtime = (stat($geofile))[9]; + my $days = int((time - $mtime) / 86400); + if ($days >= $config{CC_INTERVAL}) {$getgeo = 1} + } + } else {$getgeo = 1} + if ($getgeo) { + my $status; + my $text; + if ($config{CC_LOOKUPS} == 3) { + logfile("CCL: Retrieving $config{asn_src} ASN database [$config{cc_asn}]"); + ($status, $text) = $urlget->urlget("$config{cc_asn}","/var/lib/csf/Geo/GeoLite2-ASN-CSV.zip"); + logfile("CCL: Retrieving $config{cc_src} City database [$config{cc_city}]"); + ($status, $text) = $urlget->urlget("$config{cc_city}","/var/lib/csf/Geo/GeoLite2-City-CSV.zip"); + } + elsif ($config{CC_LOOKUPS} == 2) { + logfile("CCL: Retrieving $config{cc_src} City database [$config{cc_city}]"); + ($status, $text) = $urlget->urlget("$config{cc_city}","/var/lib/csf/Geo/GeoLite2-City-CSV.zip"); + } + else { + logfile("CCL: Retrieving $config{cc_src} Country database [$config{cc_country}]"); + ($status, $text) = $urlget->urlget("$config{cc_country}","/var/lib/csf/Geo/GeoLite2-Country-CSV.zip"); + } + if ($status) { + if ($config{CC_LOOKUPS} == 2 or $config{CC_LOOKUPS} == 3) { + logfile("CCL Error: Unable to retrieve $config{cc_src} City database [$config{cc_city}] - $text"); + } else { + logfile("CCL Error: Unable to retrieve $config{cc_src} Country database [$config{cc_country}] - $text"); + } + } else { + my @data; + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die}; + alarm(180); + my ($childin, $childout, $cmdpid); + if ($config{CC_LOOKUPS} == 3) { + @data = &syscommand(__LINE__,$config{UNZIP},"-DDjod","/var/lib/csf/Geo/","/var/lib/csf/Geo/GeoLite2-ASN-CSV.zip"); + @data = &syscommand(__LINE__,$config{UNZIP},"-DDjod","/var/lib/csf/Geo/","/var/lib/csf/Geo/GeoLite2-City-CSV.zip"); + } + elsif ($config{CC_LOOKUPS} == 2) { + @data = &syscommand(__LINE__,$config{UNZIP},"-DDjod","/var/lib/csf/Geo/","/var/lib/csf/Geo/GeoLite2-City-CSV.zip"); + } + else { + @data = &syscommand(__LINE__,$config{UNZIP},"-DDjod","/var/lib/csf/Geo/","/var/lib/csf/Geo/GeoLite2-Country-CSV.zip"); + } + alarm(0); + }; + alarm(0); + if ($@) { + if ($config{CC_LOOKUPS} == 2 or $config{CC_LOOKUPS} == 3) { + logfile("CCL Error: Unable to unzip $config{cc_src} City database /var/lib/csf/Geo/GeoLite2-City-CSV.zip - timeout"); + } else { + logfile("CCL Error: Unable to unzip $config{cc_src} Country database /var/lib/csf/Geo/GeoLite2-Country-CSV.zip - timeout"); + } + } + if (!(-e $geofile) or -z $geofile) { + logfile("CCL Error: $geofile empty or missing"); + } else { + my $now = time; + utime ($now,$now,$geofile); + logfile("CCL: Retrieved $config{cc_src} IP database"); + open (my $OUT, ">", "/var/lib/csf/csf.cclookup"); + close ($OUT); + } + } + unlink glob "/var/lib/csf/Geo/*.zip"; + unlink glob "/var/lib/csf/Geo/*-Locations-de.csv"; + unlink glob "/var/lib/csf/Geo/*-Locations-es.csv"; + unlink glob "/var/lib/csf/Geo/*-Locations-fr.csv"; + unlink glob "/var/lib/csf/Geo/*-Locations-ja.csv"; + unlink glob "/var/lib/csf/Geo/*-Locations-pt-BR.csv"; + unlink glob "/var/lib/csf/Geo/*-Locations-ru.csv"; + unlink glob "/var/lib/csf/Geo/*-Locations-zh-CN.csv"; + unlink glob "/var/lib/csf/Geo/*.dat"; + unlink glob "/var/lib/csf/zone/*.zip"; + unlink glob "/var/lib/csf/zone/*.csv"; + unlink "/var/lib/csf/Geo/GeoIPv6.csv"; + } + } elsif ($config{CC_SRC} eq "2") { + my $getgeo = 0; + my $geofile = "/var/lib/csf/Geo/dbip-country-lite.csv"; + if ($config{CC_LOOKUPS} == 2 or $config{CC_LOOKUPS} == 3) {$geofile = "/var/lib/csf/Geo/dbip-city-lite.csv"} + if (-e $geofile) { + if (-z $geofile) {$getgeo = 1} + my $mtime = (stat($geofile))[9]; + my $days = int((time - $mtime) / 86400); + if ($days >= $config{CC_INTERVAL}) {$getgeo = 1} + + if ($config{CC_LOOKUPS} == 3) { + my $geofile = "/var/lib/csf/Geo/ip2asn-combined.tsv"; + if (-z $geofile) {$getgeo = 1} + my $mtime = (stat($geofile))[9]; + my $days = int((time - $mtime) / 86400); + if ($days >= $config{CC_INTERVAL}) {$getgeo = 1} + } + } else {$getgeo = 1} + if ($getgeo) { + unless (-e $config{GUNZIP}) { + logfile("Error: gunzip binary ($config{GUNZIP}) does not exist"); + exit; + } + logfile("CCL: Retrieving CC Lookup database [$config{cc_cc}]"); + my ($status, $text) = $urlget->urlget("$config{cc_cc}","/var/lib/csf/Geo/countryInfo.txt"); + if ($status) { + logfile("CCL Error: Unable to retrieve $config{cc_src} CC Lookup database [$config{cc_cc}] - $text"); + } else { + if (-z "/var/lib/csf/Geo/countryInfo.txt" or !(-e "/var/lib/csf/Geo/countryInfo.txt")) { + logfile("CC Error: countryInfo.txt empty or missing"); + } + } + if ($config{CC_LOOKUPS} == 2 or $config{CC_LOOKUPS} == 3) { + logfile("CCL: Retrieving $config{cc_src} City database [$config{cc_city}]"); + my ($status, $text) = $urlget->urlget("$config{cc_city}","/var/lib/csf/Geo/dbip-city-lite.csv.gz"); + if ($status) { + logfile("CCL Error: Unable to retrieve $config{cc_src} City database [$config{cc_city}] - $text"); + } else { + if (-e "/var/lib/csf/Geo/dbip-city-lite.csv") {unlink "/var/lib/csf/Geo/dbip-city-lite.csv"} + my @data; + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die}; + alarm(180); + @data = &syscommand(__LINE__,$config{GUNZIP},"/var/lib/csf/Geo/dbip-city-lite.csv.gz"); + alarm(0); + }; + alarm(0); + if ($@) { + logfile("CCL Error: Unable to gunzip $config{cc_src} City database /var/lib/csf/Geo/dbip-city-lite.csv.gz - timeout"); + } + if (-z "/var/lib/csf/Geo/dbip-city-lite.csv" or !(-e "/var/lib/csf/Geo/dbip-city-lite.csv")) { + logfile("CCL Error: dbip-city-lite.csv empty or missing"); + } + } + if ($config{CC_LOOKUPS} == 3) { + logfile("CCL: Retrieving $config{asn_src} ASN database [$config{cc_asn}]"); + ($status, $text) = $urlget->urlget("$config{cc_asn}","/var/lib/csf/Geo/ip2asn-combined.tsv.gz"); + if ($status) { + logfile("CCL Error: Unable to retrieve $config{asn_src} ASN database [$config{cc_asn}] - $text"); + } else { + if (-e "/var/lib/csf/Geo/ip2asn-combined.tsv") {unlink "/var/lib/csf/Geo/ip2asn-combined.tsv"} + my @data; + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die}; + alarm(180); + @data = &syscommand(__LINE__,$config{GUNZIP},"/var/lib/csf/Geo/ip2asn-combined.tsv.gz"); + alarm(0); + }; + alarm(0); + if ($@) { + logfile("CCL Error: Unable to unzip $config{cc_src} Country database /var/lib/csf/Geo/ip2asn-combined.tsv.gz - timeout"); + } + if (-z "/var/lib/csf/Geo/ip2asn-combined.tsv" or !(-e "/var/lib/csf/Geo/ip2asn-combined.tsv")) { + logfile("CCL Error: ip2asn-combined.tsv empty or missing"); + } + } + } + } else { + logfile("CC: Retrieving $config{cc_src} Country database [$config{cc_country}]"); + my ($status, $text) = $urlget->urlget("$config{cc_country}","/var/lib/csf/Geo/dbip-country-lite.csv.gz"); + if ($status) { + logfile("CCL Error: Unable to retrieve $config{cc_src} Country database [$config{cc_country}] - $text"); + } else { + if (-e "/var/lib/csf/Geo/dbip-country-lite.csv") {unlink "/var/lib/csf/Geo/dbip-country-lite.csv"} + my @data; + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die}; + alarm(180); + @data = &syscommand(__LINE__,$config{GUNZIP},"/var/lib/csf/Geo/dbip-country-lite.csv.gz"); + alarm(0); + }; + alarm(0); + if ($@) { + logfile("CC Error: Unable to gunzip $config{cc_src} Country database /var/lib/csf/Geo/dbip-country-lite.csv.gz - timeout"); + } + if (-z "/var/lib/csf/Geo/dbip-country-lite.csv" or !(-e "/var/lib/csf/Geo/dbip-country-lite.csv")) { + logfile("CC Error: dbip-country-lite.csv empty or missing"); + } + } + } + } + } + + &listlock("unlock"); + close ($THISLOCK ); + if ($config{DEBUG} >= 3) {$timer = &timer("stop","countrycodelookups",$timer)} + $0 = "lfd - child closing"; + exit; + } + return; +} +# end countrycodelookups +############################################################################### +# start countrycode6 +sub countrycode6 { + my $force = shift; + my $getgeo; + my %cclist; + my $redo_deny = 0; + my $redo_allow = 0; + my $redo_allow_filter = 0; + my $redo_allow_ports = 0; + my $redo_deny_ports = 0; + my $redo_allow_smtpauth = 0; + my $drop = $config{DROP}; + if ($config{DROP_IP_LOGGING}) {$drop = "CCDROP"} + + $config{CC_DENY} =~ s/\s//g; + $config{CC_ALLOW} =~ s/\s//g; + $config{CC_ALLOW_FILTER} =~ s/\s//g; + $config{CC_ALLOW_PORTS} =~ s/\s//g; + $config{CC_DENY_PORTS} =~ s/\s//g; + $config{CC_ALLOW_SMTPAUTH} =~ s/\s//g; + + if ($force) { + $redo_deny = 1; + $redo_allow = 1; + $redo_allow_filter = 1; + $redo_allow_ports = 1; + $redo_deny_ports = 1; + $redo_allow_smtpauth = 1; + } + + $0 = "lfd - processing countrycode6 lists"; + foreach my $cc (split(/\,/,"$config{CC_DENY},$config{CC_ALLOW},$config{CC_ALLOW_FILTER},$config{CC_ALLOW_PORTS},$config{CC_DENY_PORTS},$config{CC_ALLOW_SMTPAUTH}")) { + if ($cc eq "") {next} + $cc = lc $cc; + if (-e "/var/lib/csf/zone/$cc.zone6") { + my $mtime = (stat("/var/lib/csf/zone/$cc.zone6"))[9]; + my $days = int((time - $mtime) / 86400); + if ($days >= $config{CC_INTERVAL}) {$getgeo = 1; $cclist{$cc} = 1} + } else {$getgeo = 1; $cclist{$cc} = 1} + if (-z "/var/lib/csf/zone/$cc.zone6") {$getgeo = 1; $cclist{$cc} = 1} + + if ($cclist{$cc}) { + if ($config{CC_DENY} =~ /\b$cc\b/i) {$redo_deny = 1} + if ($config{CC_ALLOW} =~ /\b$cc\b/i) {$redo_allow = 1} + if ($config{CC_ALLOW_FILTER} =~ /\b$cc\b/i) {$redo_allow_filter = 1} + if ($config{CC_ALLOW_PORTS} =~ /\b$cc\b/i) {$redo_allow_ports = 1} + if ($config{CC_DENY_PORTS} =~ /\b$cc\b/i) {$redo_deny_ports = 1} + if ($config{CC_ALLOW_SMTPAUTH} =~ /\b$cc\b/i) {$redo_allow_smtpauth = 1} + } + } + + if ($config{CC_SRC} eq "" or $config{CC_SRC} eq "1") { + if ($getgeo) { + logfile("CC: Processing $config{cc_src} Country/ASN IPv6 database"); + my %dcidr; + my %geoid; + open (my $GEO, "<", "/var/lib/csf/Geo/GeoLite2-Country-Locations-en.csv"); + flock ($GEO, LOCK_SH); + while (my $record = <$GEO>) { + chomp $record; + $record =~ s/\"//g; + my ($geoname_id,undef,undef,undef,$country_iso_code,undef) = split (/\,/,$record); + foreach my $cc (keys %cclist) { + if (uc $cc eq uc $country_iso_code) { + $geoid{$cc}{$geoname_id} = 1; + } + } + } + close ($GEO); + open (my $IN, "<", "/var/lib/csf/Geo/GeoLite2-Country-Blocks-IPv6.csv"); + flock ($IN, LOCK_SH); + while (my $record = <$IN>) { + chomp $record; + $record =~ s/\"//g; + my ($range,$geoname_id,undef) = split (/\,/,$record); + foreach my $cc (keys %cclist) { + if ($geoid{$cc}{$geoname_id}) { + $dcidr{$cc}{$range} = 1; + } + } + } + close ($IN); + open ($IN, "<", "/var/lib/csf/Geo/GeoLite2-ASN-Blocks-IPv6.csv"); + flock ($IN, LOCK_SH); + while (my $record = <$IN>) { + chomp $record; + $record =~ s/\"//g; + my ($range,$asn,undef) = split (/\,/,$record); + foreach my $cc (keys %cclist) { + if (uc($cc) =~ /AS(\d+)/) { + if ($1 eq $asn) { + $dcidr{$cc}{$range} = 1; + } + } + } + } + close ($IN); + foreach my $cc (keys %cclist) { + logfile("CC: Extracting zone from $config{cc_src} Country/ASN IPv6 database for [".uc($cc)."]"); + if (keys %{$dcidr{$cc}} eq 0) { + if (length($cc) == 2) { + logfile("CC: No IPv6 entries found for [".uc($cc)."] in /var/lib/csf/Geo/GeoLite2-Country-Blocks-IPv6.csv"); + } else { + logfile("CC: No IPv6 entries found for [".uc($cc)."] in /var/lib/csf/Geo/GeoLite2-ASN-Blocks-IPv6.csv"); + } + } else { + sysopen (my $CIDROUT, "/var/lib/csf/zone/$cc.zone6", O_WRONLY | O_CREAT); + flock ($CIDROUT, LOCK_EX); + seek ($CIDROUT, 0, 0); + truncate ($CIDROUT, 0); + foreach my $key (keys %{$dcidr{$cc}}) {print $CIDROUT "$key\n"} + close ($CIDROUT); + } + } + } + } elsif ($config{CC_SRC} eq "2") { + if ($getgeo) { + logfile("CC: Processing $config{cc_src} Country/ASN IPv6 database"); + my %dcidr; + open ($IN, "<", "/var/lib/csf/Geo/ip2asn-combined.tsv"); + flock ($IN, LOCK_SH); + while (my $record = <$IN>) { + chomp $record; + $record =~ s/\"//g; + my ($start,$end,$asn,undef) = split (/\t/,$record); + if (checkip($start) == 4) {next} + foreach my $cc (keys %cclist) { + if (uc($cc) =~ /AS(\d+)/) { + if ($1 eq $asn) { + my $ipscidr = Net::CIDR::Lite->new; + eval {local $SIG{__DIE__} = undef; $ipscidr->add_range("$start-$end")}; + my @cidr_list = $ipscidr->list; + foreach my $list (@cidr_list) { + $dcidr{$cc}{$list} = 1; + } + } + } + } + } + close ($IN); + foreach my $cc (keys %cclist) { + if (length($cc) > 2) { + logfile("CC: Extracting IPv6 zone from $config{asn_src} ASN database for [".uc($cc)."]"); + if (keys %{$dcidr{$cc}} eq 0) { + logfile("CC: No entries found for [".uc($cc)."] in /var/lib/csf/Geo/ip2asn-combined.tsv"); + } else { + sysopen (my $CIDROUT, "/var/lib/csf/zone/$cc.zone6", O_WRONLY | O_CREAT); + flock ($CIDROUT, LOCK_EX); + seek ($CIDROUT, 0, 0); + truncate ($CIDROUT, 0); + foreach my $key (keys %{$dcidr{$cc}}) {print $CIDROUT "$key\n"} + close ($CIDROUT); + } + } + elsif (length($cc) == 2) { + logfile("CC: Retrieving $config{ccl_src} Country Code IPv6 Zone [".uc($cc)."] from https://www.ipdeny.com"); + my ($status, $text) = $urlget->urlget("https://www.ipdeny.com/ipv6/ipaddresses/aggregated/${cc}-aggregated.zone","/var/lib/csf/zone/$cc.zone6"); + if ($status) { + logfile("CC Error: Unable to retrieve $config{ccl_src} Country Code IPv6 Zone [".uc($cc)."] from https://www.ipdeny.com - $text"); + } else { + logfile("CC: Country Code IPv6 Zone [".uc($cc)."] retrieved"); + } + sleep 1; + } + } + } + } + + if ($config{LF_IPSET}) { + my $cclist; + my $cnt = 0; + if ($redo_deny) {$cclist .= $config{CC_DENY}.","} + if ($redo_allow) {$cclist .= $config{CC_ALLOW}.","} + if ($redo_allow_filter) {$cclist .= $config{CC_ALLOW_FILTER}.","} + if ($redo_allow_ports) {$cclist .= $config{CC_ALLOW_PORTS}.","} + if ($redo_deny_ports) {$cclist .= $config{CC_DENY_PORTS}} + if ($config{CC_ALLOW_FILTER} and $redo_allow_filter) {&iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -F CC_ALLOWF")} + foreach my $cc (split(/\,/,$cclist)) { + if ($cc eq "") {next} + undef @ipset; + $cc = lc $cc; + if ($config{CC_ALLOW_FILTER} and $redo_allow_filter) {&iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -A CC_ALLOWF -m set --match-set cc_6_$cc src -j RETURN")} + if (-e "/var/lib/csf/zone/$cc.zone6") { + logfile("CC: Repopulating ipset cc_6_$cc with IP addresses from [".uc($cc)."]"); + open (my $IN, "<", "/var/lib/csf/zone/$cc.zone6"); + flock ($IN, LOCK_SH); + while (my $line = <$IN>) { + chomp $line; + 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 new_6_$cc $ip"; + $cnt++; + } + } + &ipsetrestore("new_6_$cc"); + &ipsetswap("new_6_$cc","cc_6_$cc"); + } + } + if ($config{CC_ALLOW_FILTER} and $redo_allow_filter and $cnt > 0) { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -A CC_ALLOWF -j $drop"); + if ($config{IPV6_SPI}) { + my $statemodule = "-m state --state"; + if ($config{USE_FTPHELPER}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -I CC_ALLOWF $ethdevin $statemodule RELATED -m helper --helper ftp -j $accept"); + + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -I CC_ALLOWF $ethdevin $statemodule ESTABLISHED -j $accept"); + } else { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -I CC_ALLOWF $ethdevin $statemodule ESTABLISHED,RELATED -j $accept"); + } + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -I CC_ALLOWF $eth6devin -p icmpv6 -j $accept"); + } + } + } else { + if ($config{CC_DENY} and $redo_deny) { + if (&csflock) {&lockfail("CC_DENY")} + if ($config{SAFECHAINUPDATE}) { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -N NEWCC_DENY"); + } else { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -F CC_DENY"); + } + foreach my $cc (split(/\,/,$config{CC_DENY})) { + $cc = lc $cc; + if (-e "/var/lib/csf/zone/$cc.zone6") { + if ($config{FASTSTART}) {$faststart = 1} + logfile("CC: Repopulating CC_DENY with IP addresses from [".uc($cc)."]"); + open (my $IN, "<", "/var/lib/csf/zone/$cc.zone6"); + flock ($IN, LOCK_SH); + while (my $line = <$IN>) { + chomp $line; + my ($ip,undef) = split (/\s/,$line,2); + if (cccheckip(\$ip)) { + if ($config{SAFECHAINUPDATE}) { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -A NEWCC_DENY -s $ip -j $drop"); + } else { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -A CC_DENY -s $ip -j $drop"); + } + } + } + close ($IN); + if ($config{FASTSTART}) {&faststart("CC_DENY [".uc($cc)."]")} + logfile("CC: Finished repopulating CC_DENY with IP addresses from [".uc($cc)."]"); + } + } + if ($config{SAFECHAINUPDATE}) { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -A LOCALINPUT $ethdevin -j NEWCC_DENY"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -D LOCALINPUT $ethdevin -j CC_DENY"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -F CC_DENY"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -X CC_DENY"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -E NEWCC_DENY CC_DENY"); + } + } + + if ($config{CC_ALLOW} and $redo_allow) { + if (&csflock) {&lockfail("CC_ALLOW")} + if ($config{SAFECHAINUPDATE}) { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -N NEWCC_ALLOW"); + } else { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -F CC_ALLOW"); + } + foreach my $cc (split(/\,/,$config{CC_ALLOW})) { + $cc = lc $cc; + if (-e "/var/lib/csf/zone/$cc.zone6") { + if ($config{FASTSTART}) {$faststart = 1} + logfile("CC: Repopulating CC_ALLOW with IP addresses from [".uc($cc)."]"); + open (my $IN, "<", "/var/lib/csf/zone/$cc.zone6"); + flock ($IN, LOCK_SH); + while (my $line = <$IN>) { + chomp $line; + my ($ip,undef) = split (/\s/,$line,2); + if (cccheckip(\$ip)) { + if ($config{SAFECHAINUPDATE}) { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -A NEWCC_ALLOW -s $ip -j $accept"); + } else { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -A CC_ALLOW -s $ip -j $accept"); + } + } + } + close ($IN); + if ($config{FASTSTART}) {&faststart("CC_ALLOW [".uc($cc)."]")} + logfile("CC: Finished repopulating CC_ALLOW with IP addresses from [".uc($cc)."]"); + } + } + if ($config{SAFECHAINUPDATE}) { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -I LOCALINPUT $ethdevin -j NEWCC_ALLOW"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -D LOCALINPUT $ethdevin -j CC_ALLOW"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -F CC_ALLOW"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -X CC_ALLOW"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -E NEWCC_ALLOW CC_ALLOW"); + } + } + + if ($config{CC_ALLOW_FILTER} and $redo_allow_filter) { + my $cnt = 0; + if (&csflock) {&lockfail("CC_ALLOW_FILTER")} + if ($config{SAFECHAINUPDATE}) { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -N NCC_ALLOWF"); + } else { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -F CC_ALLOWF"); + } + foreach my $cc (split(/\,/,$config{CC_ALLOW_FILTER})) { + $cc = lc $cc; + if (-e "/var/lib/csf/zone/$cc.zone6") { + if ($config{FASTSTART}) {$faststart = 1} + logfile("CC: Repopulating CC_ALLOWF with IP addresses from [".uc($cc)."]"); + open (my $IN, "<", "/var/lib/csf/zone/$cc.zone6"); + flock ($IN, LOCK_SH); + while (my $line = <$IN>) { + chomp $line; + my ($ip,undef) = split (/\s/,$line,2); + if (cccheckip(\$ip)) { + $cnt++; + if ($config{SAFECHAINUPDATE}) { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -A NCC_ALLOWF -s $ip -j RETURN"); + } else { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -A CC_ALLOWF -s $ip -j RETURN"); + } + } + } + close ($IN); + if ($config{FASTSTART}) {&faststart("CC_ALLOW_FILTER [".uc($cc)."]")} + logfile("CC: Finished repopulating CC_ALLOWF with IP addresses from [".uc($cc)."]"); + } + } + if ($config{SAFECHAINUPDATE}) { + if ($cnt > 0) {&iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -A NCC_ALLOWF -j $drop")} + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -A LOCALINPUT $ethdevin -j NCC_ALLOWF"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -D LOCALINPUT $ethdevin -j CC_ALLOWF"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -F CC_ALLOWF"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -X CC_ALLOWF"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -E NCC_ALLOWF CC_ALLOWF"); + } else { + if ($cnt > 0) { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -A CC_ALLOWF -j $drop"); + if ($config{IPV6_SPI}) { + my $statemodule = "-m state --state"; + if ($config{USE_FTPHELPER}) { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -I CC_ALLOWF $ethdevin $statemodule RELATED -m helper --helper ftp -j $accept"); + + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -I CC_ALLOWF $ethdevin $statemodule ESTABLISHED -j $accept"); + } else { + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -I CC_ALLOWF $ethdevin $statemodule ESTABLISHED,RELATED -j $accept"); + } + &syscommand(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -I CC_ALLOWF $eth6devin -p icmpv6 -j $accept"); + } + } + } + } + + if ($config{CC_ALLOW_PORTS} and $redo_allow_ports) { + my $cnt = 0; + if (&csflock) {&lockfail("CC_ALLOW_PORTS")} + if ($config{SAFECHAINUPDATE}) { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -N NCC_ALLOWP"); + } else { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -F CC_ALLOWP"); + } + foreach my $cc (split(/\,/,$config{CC_ALLOW_PORTS})) { + $cc = lc $cc; + if (-e "/var/lib/csf/zone/$cc.zone6") { + if ($config{FASTSTART}) {$faststart = 1} + logfile("CC: Repopulating CC_ALLOWP with IP addresses from [".uc($cc)."]"); + open (my $IN, "<", "/var/lib/csf/zone/$cc.zone6"); + flock ($IN, LOCK_SH); + while (my $line = <$IN>) { + chomp $line; + my ($ip,undef) = split (/\s/,$line,2); + if (cccheckip(\$ip)) { + $cnt++; + if ($config{SAFECHAINUPDATE}) { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -A NCC_ALLOWP -s $ip -j CC_ALLOWPORTS"); + } else { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -A CC_ALLOWP -s $ip -j CC_ALLOWPORTS"); + } + } + } + close ($IN); + if ($config{FASTSTART}) {&faststart("CC_ALLOW_PORTS [".uc($cc)."]")} + logfile("CC: Finished repopulating CC_ALLOWP with IP addresses from [".uc($cc)."]"); + } + } + if ($config{SAFECHAINUPDATE}) { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -A LOCALINPUT $ethdevin -j NCC_ALLOWP"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -D LOCALINPUT $ethdevin -j CC_ALLOWP"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -F CC_ALLOWP"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -X CC_ALLOWP"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -E NCC_ALLOWP CC_ALLOWP"); + } + } + + if ($config{CC_DENY_PORTS} and $redo_deny_ports) { + my $cnt = 0; + if (&csflock) {&lockfail("CC_DENY_PORTS")} + if ($config{SAFECHAINUPDATE}) { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -N NCC_DENYP"); + } else { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -F CC_DENYP"); + } + foreach my $cc (split(/\,/,$config{CC_DENY_PORTS})) { + $cc = lc $cc; + if (-e "/var/lib/csf/zone/$cc.zone6") { + if ($config{FASTSTART}) {$faststart = 1} + logfile("CC: Repopulating CC_DENYP with IP addresses from [".uc($cc)."]"); + open (my $IN, "<", "/var/lib/csf/zone/$cc.zone6"); + flock ($IN, LOCK_SH); + while (my $line = <$IN>) { + chomp $line; + my ($ip,undef) = split (/\s/,$line,2); + if (cccheckip(\$ip)) { + $cnt++; + if ($config{SAFECHAINUPDATE}) { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -A NCC_DENYP -s $ip -j CC_DENYPORTS"); + } else { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -A CC_DENYP -s $ip -j CC_DENYPORTS"); + } + } + } + close ($IN); + if ($config{FASTSTART}) {&faststart("CC_DENY_PORTS [".uc($cc)."]")} + logfile("CC: Finished repopulating CC_DENYP with IP addresses from [".uc($cc)."]"); + } + } + if ($config{SAFECHAINUPDATE}) { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -A LOCALINPUT $ethdevin -j NCC_DENYP"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -D LOCALINPUT $ethdevin -j CC_DENYP"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -F CC_DENYP"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -X CC_DENYP"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -E NCC_DENYP CC_DENYP"); + } + } + } + return; +} +# end countrycode6 +############################################################################### +# start global +sub global { + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","global",$timer)} + $0 = "lfd - retrieving global lists"; + + my $lockstr = "LF_GLOBAL"; + sysopen (my $THISLOCK, "/var/lib/csf/lock/$lockstr.lock", O_RDWR | O_CREAT) or &childcleanup("*Error* Unable to open /var/lib/csf/lock/$lockstr.lock"); + flock ($THISLOCK, LOCK_EX | LOCK_NB) or &childcleanup("*Lock Error* [$lockstr] still active - section skipped"); + print $THISLOCK time; + + $0 = "lfd - retrieving global lists (waiting for list lock)"; + &listlock("lock"); + $0 = "lfd - retrieving global lists"; + + if ($config{GLOBAL_ALLOW}) { + my ($status, $text) = $urlget->urlget($config{GLOBAL_ALLOW}); + if ($status) { + logfile("Unable to retrieve global allow list - $text"); + } else { + if (&csflock) {&lockfail("GLOBAL_ALLOW")} + logfile("Global Allow - retrieved and allowing IP address ranges"); + + if ($config{SAFECHAINUPDATE}) { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -N NEWGALLOWIN"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -N NEWGALLOWOUT"); + if ($config{LF_IPSET}) { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -A NEWGALLOWIN -m set --match-set chain_GALLOW src -j $accept"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -A NEWGALLOWOUT -m set --match-set chain_GALLOW dst -j $accept"); + &ipsetcreate("chain_NEWGALLOW"); + } + if ($config{IPV6}) { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -N NEWGALLOWIN"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -N NEWGALLOWOUT"); + if ($config{LF_IPSET}) { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -A NEWGALLOWIN -m set --match-set chain_6_GALLOW src -j $accept"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -A NEWGALLOWOUT -m set --match-set chain_6_GALLOW dst -j $accept"); + &ipsetcreate("chain_6_NEWGALLOW"); + } + } + } else { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -F GALLOWIN"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -F GALLOWOUT"); + if ($config{LF_IPSET}) { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -A GALLOWIN -m set --match-set chain_GALLOW src -j $accept"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -A GALLOWOUT -m set --match-set chain_GALLOW dst -j $accept"); + &ipsetflush("chain_GALLOW"); + } + if ($config{IPV6}) { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -F GALLOWIN"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -F GALLOWOUT"); + if ($config{LF_IPSET}) { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -A GALLOWIN -m set --match-set chain_6_GALLOW src -j $accept"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -A GALLOWOUT -m set --match-set chain_6_GALLOW dst -j $accept"); + &ipsetflush("chain_6_GALLOW"); + } + } + } + sysopen (my $GALLOW, "/var/lib/csf/csf.gallow", O_WRONLY | O_CREAT) or &childcleanup(__LINE__,"*Error* Cannot open out file: $!"); + flock ($GALLOW, LOCK_EX); + seek ($GALLOW, 0, 0); + truncate ($GALLOW, 0); + if ($config{FASTSTART}) {$faststart = 1} + foreach my $line (split (/\n/,$text)) { + if ($line =~ /^\#/) {next} + my ($ip,$comment) = split (/\s/,$line,2); + print $GALLOW "$ip\n"; + if ($config{SAFECHAINUPDATE}) { + &linefilter($ip, "allow","NEWGALLOW"); + } else { + &linefilter($ip, "allow","GALLOW"); + } + } + if ($config{FASTSTART}) {&faststart("GLOBAL_ALLOW")} + close ($GALLOW); + if ($config{SAFECHAINUPDATE}) { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -I LOCALINPUT $ethdevin -j NEWGALLOWIN"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -I LOCALOUTPUT $ethdevout -j NEWGALLOWOUT"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -D LOCALINPUT $ethdevin -j GALLOWIN"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -D LOCALOUTPUT $ethdevout -j GALLOWOUT"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -F GALLOWIN"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -F GALLOWOUT"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -X GALLOWIN"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -X GALLOWOUT"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -E NEWGALLOWIN GALLOWIN"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -E NEWGALLOWOUT GALLOWOUT"); + if ($config{IPV6}) { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -I LOCALINPUT $eth6devin -j NEWGALLOWIN"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -I LOCALOUTPUT $eth6devout -j NEWGALLOWOUT"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -D LOCALINPUT $eth6devin -j GALLOWIN"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -D LOCALOUTPUT $eth6devout -j GALLOWOUT"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -F GALLOWIN"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -F GALLOWOUT"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -X GALLOWIN"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -X GALLOWOUT"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -E NEWGALLOWIN GALLOWIN"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -E NEWGALLOWOUT GALLOWOUT"); + } + if ($config{LF_IPSET}) { + &ipsetswap("chain_NEWGALLOW","chain_GALLOW"); + if ($config{IPV6}) { + &ipsetswap("chain_6_NEWGALLOW","chain_6_GALLOW"); + } + } + } + } + } + + if ($config{GLOBAL_DENY}) { + my ($status, $text) = $urlget->urlget($config{GLOBAL_DENY}); + if ($status) { + logfile("Unable to retrieve global deny list - $text"); + } else { + if (&csflock) {&lockfail("GLOBAL_DENY")} + logfile("Global Deny - retrieved and blocking IP address ranges"); + my $drop = $config{DROP}; + if ($config{DROP_IP_LOGGING}) {$drop = "BLOCKDROP"} + + if ($config{SAFECHAINUPDATE}) { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -N NEWGDENYIN"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -N NEWGDENYOUT"); + 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"} + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -A NEWGDENYIN -m set --match-set chain_GDENY src -j $pktin"); + unless ($config{LF_BLOCKINONLY}) {&iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -A NEWGDENYOUT -m set --match-set chain_GDENY dst -j $pktout")} + &ipsetcreate("chain_NEWGDENY"); + } + if ($config{IPV6}) { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -N NEWGDENYIN"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -N NEWGDENYOUT"); + 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"} + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -A NEWGDENYIN -m set --match-set chain_6_GDENY src -j $pktin"); + unless ($config{LF_BLOCKINONLY}) {&iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -A NEWGDENYOUT -m set --match-set chain_6_GDENY dst -j $pktout")} + &ipsetcreate("chain_6_NEWGDENY"); + } + } + } else { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -F GDENYIN"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -F GDENYOUT"); + 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"} + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -A GDENYIN -m set --match-set chain_GDENY src -j $pktin"); + unless ($config{LF_BLOCKINONLY}) {&iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -A GDENYOUT -m set --match-set chain_GDENY dst -j $pktout")} + &ipsetflush("chain_GDENY"); + } + if ($config{IPV6}) { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -F GDENYIN"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -F GDENYOUT"); + 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"} + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -A GDENYIN -m set --match-set chain_6_GDENY src -j $pktin"); + unless ($config{LF_BLOCKINONLY}) {&iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -A GDENYOUT -m set --match-set chain_6_GDENY dst -j $pktout")} + &ipsetflush("chain_6_GDENY"); + } + } + } + sysopen (my $GDENY, "/var/lib/csf/csf.gdeny", O_WRONLY | O_CREAT) or &childcleanup(__LINE__,"*Error* Cannot open out file: $!"); + flock ($GDENY, LOCK_EX); + seek ($GDENY, 0, 0); + truncate ($GDENY, 0); + if ($config{FASTSTART}) {$faststart = 1} + foreach my $line (split (/\n/,$text)) { + if ($line =~ /^\#/) {next} + my ($ip,$comment) = split (/\s/,$line,2); + print $GDENY "$ip\n"; + if ($config{SAFECHAINUPDATE}) { + &linefilter($ip, "deny","NEWGDENY"); + } else { + &linefilter($ip, "deny","GDENY"); + } + } + if ($config{FASTSTART}) {&faststart("GLOBAL_DENY")} + close ($GDENY); + if ($config{SAFECHAINUPDATE}) { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -A LOCALINPUT $ethdevin -j NEWGDENYIN"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -A LOCALOUTPUT $ethdevout -j NEWGDENYOUT"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -D LOCALINPUT $ethdevin -j GDENYIN"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -D LOCALOUTPUT $ethdevout -j GDENYOUT"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -F GDENYIN"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -F GDENYOUT"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -X GDENYIN"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -X GDENYOUT"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -E NEWGDENYIN GDENYIN"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -E NEWGDENYOUT GDENYOUT"); + if ($config{IPV6}) { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -A LOCALINPUT $eth6devin -j NEWGDENYIN"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -A LOCALOUTPUT $eth6devout -j NEWGDENYOUT"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -D LOCALINPUT $eth6devin -j GDENYIN"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -D LOCALOUTPUT $eth6devout -j GDENYOUT"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -F GDENYIN"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -F GDENYOUT"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -X GDENYIN"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -X GDENYOUT"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -E NEWGDENYIN GDENYIN"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -E NEWGDENYOUT GDENYOUT"); + } + if ($config{LF_IPSET}) { + &ipsetswap("chain_NEWGDENY","chain_GDENY"); + if ($config{IPV6}) { + &ipsetswap("chain_6_NEWGDENY","chain_6_GDENY"); + } + } + } + } + } + + if ($config{GLOBAL_IGNORE}) { + my ($status, $text) = $urlget->urlget($config{GLOBAL_IGNORE}); + if ($status) { + logfile("Unable to retrieve global ignore list - $text"); + } else { + logfile("Global Ignore - retrieved and ignoring"); + + sysopen (my $GIGNORE, "/var/lib/csf/csf.gignore", O_WRONLY | O_CREAT) or &childcleanup(__LINE__,"*Error* Cannot open out file: $!"); + flock ($GIGNORE, LOCK_EX); + seek ($GIGNORE, 0, 0); + truncate ($GIGNORE, 0); + foreach my $line (split (/\n/,$text)) { + if ($line =~ /^\#/) {next} + my ($ip,$comment) = split (/\s/,$line,2); + print $GIGNORE "$ip\n"; + } + close ($GIGNORE); + } + } + + if ($config{GLOBAL_DYNDNS}) { + my ($status, $text) = $urlget->urlget($config{GLOBAL_DYNDNS}); + if ($status) { + logfile("Unable to retrieve global dyndns list - $text"); + } else { + logfile("Global DynDNS - retrieved and allowing IP addresses"); + + sysopen (my $GDYNDNS, "/var/lib/csf/csf.gdyndns", O_WRONLY | O_CREAT) or &childcleanup(__LINE__,"*Error* Cannot open out file: $!"); + flock ($GDYNDNS, LOCK_EX); + seek ($GDYNDNS, 0, 0); + truncate ($GDYNDNS, 0); + foreach my $line (split (/\n/,$text)) { + if ($line =~ /^\#/) {next} + my ($ip,$comment) = split (/\s/,$line,2); + print $GDYNDNS "$ip\n"; + } + close ($GDYNDNS); + &globaldyndns; + } + } + + &listlock("unlock"); + close ($THISLOCK ); + if ($config{DEBUG} >= 3) {$timer = &timer("stop","global",$timer)} + $0 = "lfd - child closing"; + exit; + } + return; +} +# end global +############################################################################### +# start dyndns +sub dyndns { + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","dyndns",$timer)} + $0 = "lfd - resolving dyndns IP addresses"; + + my $lockstr = "DYNDNS"; + sysopen (my $THISLOCK, "/var/lib/csf/lock/$lockstr.lock", O_RDWR | O_CREAT) or &childcleanup("*Error* Unable to open /var/lib/csf/lock/$lockstr.lock"); + flock ($THISLOCK, LOCK_EX | LOCK_NB) or &childcleanup("*Lock Error* [$lockstr] still active - section skipped"); + print $THISLOCK time; + + $0 = "lfd - resolving dyndns IP addresses (waiting for list lock)"; + &listlock("lock"); + $0 = "lfd - resolving dyndns IP addresses"; + + my @dyndns; + my @entries = slurp("/etc/csf/csf.dyndns"); + 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} + push @dyndns, $line; + } + + if (&csflock) {&lockfail("DYNDNS")} + if ($config{DEBUG} >= 1) {logfile("DynDNS - update IP addresses")} + if ($config{SAFECHAINUPDATE}) { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -N NEWALLOWDYNIN"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -N NEWALLOWDYNOUT"); + if ($config{LF_IPSET}) { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -A NEWALLOWDYNIN -m set --match-set chain_ALLOWDYN src -j $accept"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -A NEWALLOWDYNOUT -m set --match-set chain_ALLOWDYN dst -j $accept"); + } + } else { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -F ALLOWDYNIN"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -F ALLOWDYNOUT"); + if ($config{LF_IPSET}) { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -A ALLOWDYNIN -m set --match-set chain_ALLOWDYN src -j $accept"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -A ALLOWDYNOUT -m set --match-set chain_ALLOWDYN dst -j $accept"); + } + } + if ($config{IPV6}) { + if ($config{SAFECHAINUPDATE}) { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -N NEWALLOWDYNIN"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -N NEWALLOWDYNOUT"); + } else { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -F ALLOWDYNIN"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -F ALLOWDYNOUT"); + } + } + sysopen (my $TEMPDYN, "/var/lib/csf/csf.tempdyn", O_WRONLY | O_CREAT) or &childcleanup(__LINE__,"*Error* Cannot open out file: $!"); + flock ($TEMPDYN, LOCK_EX); + seek ($TEMPDYN, 0, 0); + truncate ($TEMPDYN, 0); + foreach my $line (@dyndns) { + my $adport; + my ($fqdn,undef) = split(/\s/,$line,2); + if ($fqdn =~ /^(.*(s|d)=)(.*)$/) {$adport = $1; $fqdn = $3} + my @results = getips($fqdn); + if (@results) { + foreach my $ip (@results) { + if ($adport) {$ip = $adport.$ip} + if ($config{SAFECHAINUPDATE}) { + &linefilter($ip, "allow","NEWALLOWDYN"); + } else { + &linefilter($ip, "allow","ALLOWDYN"); + } + print $TEMPDYN "$ip\n"; + } + } else { + logfile ("DynDNS: Lookup for [$fqdn] failed"); + } + } + close ($TEMPDYN); + if ($config{SAFECHAINUPDATE}) { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -I LOCALINPUT $ethdevin -j NEWALLOWDYNIN"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -I LOCALOUTPUT $ethdevout -j NEWALLOWDYNOUT"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -D LOCALINPUT $ethdevin -j ALLOWDYNIN"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -D LOCALOUTPUT $ethdevout -j ALLOWDYNOUT"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -F ALLOWDYNIN"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -F ALLOWDYNOUT"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -X ALLOWDYNIN"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -X ALLOWDYNOUT"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -E NEWALLOWDYNIN ALLOWDYNIN"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -E NEWALLOWDYNOUT ALLOWDYNOUT"); + } + if ($config{IPV6}) { + if ($config{SAFECHAINUPDATE}) { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -I LOCALINPUT $ethdevin -j NEWALLOWDYNIN"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -I LOCALOUTPUT $ethdevout -j NEWALLOWDYNOUT"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -D LOCALINPUT $ethdevin -j ALLOWDYNIN"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -D LOCALOUTPUT $ethdevout -j ALLOWDYNOUT"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -F ALLOWDYNIN"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -F ALLOWDYNOUT"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -X ALLOWDYNIN"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -X ALLOWDYNOUT"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -E NEWALLOWDYNIN ALLOWDYNIN"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -E NEWALLOWDYNOUT ALLOWDYNOUT"); + } + } + + &listlock("unlock"); + close ($THISLOCK ); + if ($config{DEBUG} >= 3) {$timer = &timer("stop","dyndns",$timer)} + $0 = "lfd - child closing"; + exit; + } + return; +} +# end dyndns +############################################################################### +# start globaldyndns +sub globaldyndns { + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","globaldyndns",$timer)} + $0 = "lfd - resolving global dyndns IP addresses"; + + my $lockstr = "GLOBAL_DYNDNS_INTERVAL"; + sysopen (my $THISLOCK, "/var/lib/csf/lock/$lockstr.lock", O_RDWR | O_CREAT) or &childcleanup("*Error* Unable to open /var/lib/csf/lock/$lockstr.lock"); + flock ($THISLOCK, LOCK_EX | LOCK_NB) or &childcleanup("*Lock Error* [$lockstr] still active - section skipped"); + print $THISLOCK time; + + $0 = "lfd - resolving global dyndns IP addresses (waiting for list lock)"; + &listlock("lock"); + $0 = "lfd - resolving global dyndns IP addresses"; + + open (my $IN, "<", "/var/lib/csf/csf.gdyndns"); + flock ($IN, LOCK_SH); + my @dyndns = <$IN>; + close ($IN); + chomp @dyndns; + + if (&csflock) {&lockfail("GLOBAL_DYNDNS_INTERVAL")} + logfile("Global DynDNS - update IP addresses"); + if ($config{SAFECHAINUPDATE}) { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -N NEWGDYNIN"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -N NEWGDYNOUT"); + if ($config{LF_IPSET}) { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -A NEWGDYNIN -m set --match-set chain_GDYN src -j $accept"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -A NEWGDYNOUT -m set --match-set chain_GDYN dst -j $accept"); + } + } else { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -F GDYNIN"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -F GDYNOUT"); + if ($config{LF_IPSET}) { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -A GDYNIN -m set --match-set chain_GDYN src -j $accept"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -A GDYNOUT -m set --match-set chain_GDYN dst -j $accept"); + } + } + if ($config{IPV6}) { + if ($config{SAFECHAINUPDATE}) { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -N NEWGDYNIN"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -N NEWGDYNOUT"); + if ($config{LF_IPSET}) { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -A NEWGDYNIN -m set --match-set chain_6_GDYN src -j $accept"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -A NEWGDYNOUT -m set --match-set chain_6_GDYN dst -j $accept"); + } + } else { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -F GDYNIN"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -F GDYNOUT"); + if ($config{LF_IPSET}) { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -A GDYNIN -m set --match-set chain_6_GDYN src -j $accept"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -A GDYNOUT -m set --match-set chain_6_GDYN dst -j $accept"); + } + } + } + sysopen (my $TEMPDYN, "/var/lib/csf/csf.tempgdyn", O_WRONLY | O_CREAT) or &childcleanup(__LINE__,"*Error* Cannot open out file: $!"); + flock ($TEMPDYN, LOCK_EX); + seek ($TEMPDYN, 0, 0); + truncate ($TEMPDYN, 0); + foreach my $line (@dyndns) { + if ($line =~ /^\#/) {next} + if ($line eq "") {next} + if ($line =~ /^\n/) {next} + if ($line =~ /^\r/) {next} + if ($line =~ /^\s/) {next} + my $ip; + my $adport; + my ($fqdn,undef) = split(/\s/,$line,2); + if ($fqdn =~ /(.*:(s|d)=)(.*)$/) {$adport = $1; $fqdn = $3} + my @results = getips($fqdn); + if (@results) { + foreach my $ip (@results) { + if ($adport) {$ip = $adport.$ip} + if ($config{SAFECHAINUPDATE}) { + &linefilter($ip, "allow","NEWGDYN"); + } else { + &linefilter($ip, "allow","GDYN"); + } + print $TEMPDYN "$ip\n"; + } + } else { + logfile ("Global DynDNS: Lookup for [$fqdn] failed"); + } + } + close ($TEMPDYN); + if ($config{SAFECHAINUPDATE}) { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -I LOCALINPUT $ethdevin -j NEWGDYNIN"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -I LOCALOUTPUT $ethdevout -j NEWGDYNOUT"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -D LOCALINPUT $ethdevin -j GDYNIN"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -D LOCALOUTPUT $ethdevout -j GDYNOUT"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -F GDYNIN"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -F GDYNOUT"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -X GDYNIN"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -X GDYNOUT"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -E NEWGDYNIN GDYNIN"); + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -E NEWGDYNOUT GDYNOUT"); + } + if ($config{IPV6}) { + if ($config{SAFECHAINUPDATE}) { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -I LOCALINPUT $ethdevin -j NEWGDYNIN"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -I LOCALOUTPUT $ethdevout -j NEWGDYNOUT"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -D LOCALINPUT $ethdevin -j GDYNIN"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -D LOCALOUTPUT $ethdevout -j GDYNOUT"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -F GDYNIN"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -F GDYNOUT"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -X GDYNIN"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -X GDYNOUT"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -E NEWGDYNIN GDYNIN"); + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -E NEWGDYNOUT GDYNOUT"); + } + } + + &listlock("unlock"); + close ($THISLOCK ); + if ($config{DEBUG} >= 3) {$timer = &timer("stop","globaldyndns",$timer)} + $0 = "lfd - child closing"; + exit; + } + return; +} +# end globaldyndns +############################################################################### +# start listlock +sub listlock { + my $state = shift; + if ($state eq "lock") { + sysopen ($LISTLOCK, "/var/lib/csf/lock/list.lock", O_RDWR | O_CREAT) or &childcleanup("*Error* Unable to open /var/lib/csf/lock/list.lock"); + flock ($LISTLOCK, LOCK_EX) or &childcleanup("*Lock Error* [listlock] unable to lock"); + print $LISTLOCK time; + } else { + close ($LISTLOCK); + } + return; +} +# end listlock +############################################################################### +# start dirwatch +sub dirwatch { + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","dirwatch",$timer)} + $0 = "lfd - checking directories"; + + my $lockstr = "LF_DIRWATCH"; + sysopen (my $THISLOCK, "/var/lib/csf/lock/$lockstr.lock", O_RDWR | O_CREAT) or &childcleanup("*Error* Unable to open /var/lib/csf/lock/$lockstr.lock"); + flock ($THISLOCK, LOCK_EX | LOCK_NB) or &childcleanup("*Lock Error* [$lockstr] still active - section skipped"); + print $THISLOCK time; + + my $alarm = int($config{LF_DIRWATCH}/10) + 10; + my $start = time; + my $tfail = 0; + undef %nofiles; + if (! -z "/var/lib/csf/csf.tempfiles") { + open (my $IN, "<", "/var/lib/csf/csf.tempfiles"); + flock ($IN, LOCK_SH); + my @data = <$IN>; + close ($IN); + chomp @data; + + foreach my $line (@data) { + my ($itemttl,$item) = split(/:/,$line); + if (time - $itemttl < $config{LF_FLUSH}) { + $nofiles{$item} = 1; + } + } + } + + undef @suspicious; + my @dirs = ('/tmp','/dev/shm','/usr/local/apache/proxy','/etc/cron.d','/etc/cron.daily','/etc/cron.hourly','/etc/cron.weekly'); + my $tmpino = (stat("/tmp"))[1]; + my $ino = (lstat("/var/tmp"))[1]; + if ($ino ne $tmpino) {push @dirs, '/var/tmp'} + $ino = (lstat("/usr/tmp"))[1]; + if ($ino ne $tmpino) {push @dirs, '/usr/tmp'} + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die}; + alarm($alarm); + find(\&dirfiles, @dirs); + alarm(0); + }; + alarm(0); + if ($@) { + logfile("Directory Watching terminated after $alarm seconds"); + $tfail = 1; + } else { + if (@suspicious) { + $0 = "lfd - reporting directory watch results"; + + my @alert = slurp("/usr/local/csf/tpl/filealert.txt"); + my $matches = 0; + foreach my $file (@suspicious) { + if ($nofiles{$file}) {next} + unless (-e $file) {next} + $nofiles{$file} = 1; + + my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,$blksize,$blocks) = stat($file); + if (-l $file) {($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,$blksize,$blocks) = lstat($file)} + + if ($file !~/\/core\./) { + if ($uid eq "0") {next} + } + + my $tuid = getpwuid($uid); + my $tgid = getgrgid($gid); + if ($file !~ /\/core\./) { + if (($uid eq "postgres") and ($gid eq "postgres")) {next} + if ($skipuser{$uid}) {next} + } + + $matches++; + if ($matches > 10) { + logfile("Too many hits for *LF_DIRWATCH* - Directory Watching disabled"); + sysopen (my $DWDISABLE, "/var/lib/csf/csf.dwdisable", O_WRONLY | O_APPEND | O_CREAT) or &childcleanup(__LINE__,"*Error* Cannot append out file: $!"); + flock ($DWDISABLE, LOCK_EX); + print $DWDISABLE "disabled\n"; + close ($DWDISABLE); + + my @newalert = @alert; + my @message; + foreach my $line (@newalert) { + $line =~ s/\[file\]//ig; + $line =~ s/\[reason\]//ig; + $line =~ s/\[owner\]//ig; + $line =~ s/\[action\]/Too many hits for \*LF_DIRWATCH\* - Directory Watching disabled/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + + exit; + } + + my $owner = "$tuid:$tgid ($uid:$gid)"; + my $line = "*Suspicious File* $file [$owner] - $sfile{$file}{reason}"; + my $action = "No action taken"; + + if ($config{LF_DIRWATCH_DISABLE}) { + if (-l $file) { + unlink ($file); + $action = "Symlink removed"; + $line .= " - symlink removed"; + delete $nofiles{$file}; + } + elsif (-f $file) { + system($config{TAR},"-rf","/var/lib/csf/suspicious.tar",$file); + unlink ($file); + $line .= " - removed"; + $action = "Moved into /var/lib/csf/suspicious.tar"; + delete $nofiles{$file}; + } + } + logfile($line); + $0 = "lfd - (child) suspicious file alert for $file"; + + my @newalert = @alert; + my @message; + foreach my $line (@newalert) { + $line =~ s/\[file\]/$file/ig; + $line =~ s/\[reason\]/$sfile{$file}{reason}/ig; + $line =~ s/\[owner\]/$owner/ig; + $line =~ s/\[action\]/$action/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + + if (! $config{LF_DIRWATCH_DISABLE}) { + sysopen (my $TEMPFILES, "/var/lib/csf/csf.tempfiles", O_WRONLY | O_APPEND | O_CREAT) or &childcleanup(__LINE__,"*Error* Cannot append out file: $!"); + flock ($TEMPFILES, LOCK_EX); + print $TEMPFILES time.":$file\n"; + close ($TEMPFILES); + } + } + } + } + + if ($tfail) { + $config{LF_DIRWATCH} = $config{LF_DIRWATCH} * 3; + sysopen (my $TEMPCONF, "/var/lib/csf/csf.tempconf", O_WRONLY | O_APPEND | O_CREAT) or &childcleanup(__LINE__,"*Error* Cannot append out file: $!"); + flock ($TEMPCONF, LOCK_EX); + print $TEMPCONF "LF_DIRWATCH = \"$config{LF_DIRWATCH}\"\n"; + close ($TEMPCONF); + logfile("LF_DIRWATCH taking $alarm seconds, temporarily throttled to run every $config{LF_DIRWATCH} seconds"); + } + + close ($THISLOCK ); + if ($config{DEBUG} >= 3) {$timer = &timer("stop","dirwatch",$timer)} + $0 = "lfd - child closing"; + exit; + } + return; +} +# end dirwatch +############################################################################### +# start dirfiles +sub dirfiles { + if ($skipfile{$File::Find::name}) {return} + if ($nofiles{$File::Find::name}) {return} + if ((-d $File::Find::name) and ($_ =~ /^(\.|\.\.)$/)) {return} + + my $skip = 0; + foreach my $match (@matchfile) { + if ($File::Find::name =~ /$match/) { + $skip = 1; + last; + } + } + if ($skip) {return} + + if (-l $File::Find::name) { + push @suspicious, $File::Find::name; + $sfile{$File::Find::name}{reason} = "Suspicious symlink (->".readlink($File::Find::name).")"; + return; + } + elsif ((-d $File::Find::name) and ($_ =~ /^(\.|\s)/)) { + push @suspicious, $File::Find::name; + $sfile{$File::Find::name}{reason} = "Suspicious directory"; + return; + } + elsif (-f $File::Find::name) { + if ($File::Find::name =~ /^\/etc\/cron/) { + if ($_ =~ /^core\./) { + push @suspicious, $File::Find::name; + $sfile{$File::Find::name}{reason} = "Core dump found - possible root exploit attack"; + return; + } else {return} + } + if ($File::Find::name =~ /[\;\|\`\\]/) { + push @suspicious, $File::Find::name; + $sfile{$File::Find::name}{reason} = "Suspicious file name"; + return; + } + if ($File::Find::name =~ /^\-/) { + push @suspicious, $File::Find::name; + $sfile{$File::Find::name}{reason} = "Suspicious file name"; + return; + } + if ($_ =~ /\.(pl|cgi|ph.*|py|sh|bash)$/) { + push @suspicious, $File::Find::name; + $sfile{$File::Find::name}{reason} = "Script, file extension"; + return; + } + if ($_ =~ /^(udp\.pl|r0nin|dc\.pl|bind|bindz|inetd|z|httpd|sshd|ssh|cron|crond|su)$/) { + push @suspicious, $File::Find::name; + $sfile{$File::Find::name}{reason} = "Known exploit"; + return; + } + + open (my $FILETYPE, "<", $File::Find::name); + flock ($FILETYPE, LOCK_SH); + read ($FILETYPE, my $filedata, 1024); + close ($FILETYPE); + if ($filedata =~ m[^\177ELF]) { + push @suspicious, $File::Find::name; + $sfile{$File::Find::name}{reason} = "Linux Binary"; + return; + } + if ($filedata =~ m[^\#\!]) { + push @suspicious, $File::Find::name; + $sfile{$File::Find::name}{reason} = "Script, starts with \#\!"; + return; + } + } + return; +} +# end dirfiles +############################################################################### +# start dirwatchfile +sub dirwatchfile { + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","dirwatchfile",$timer)} + + my $lockstr = "LF_DIRWATCH_FILE"; + sysopen (my $THISLOCK, "/var/lib/csf/lock/$lockstr.lock", O_RDWR | O_CREAT) or &childcleanup("*Error* Unable to open /var/lib/csf/lock/$lockstr.lock"); + flock ($THISLOCK, LOCK_EX | LOCK_NB) or &childcleanup("*Lock Error* [$lockstr] still active - section skipped"); + print $THISLOCK time; + + $0 = "lfd - checking files and directories"; + + undef %nofiles; + if (-e "/var/lib/csf/csf.tempwatch") { + open (my $IN, "<", "/var/lib/csf/csf.tempwatch"); + flock ($IN, LOCK_SH); + my @data = <$IN>; + close ($IN); + chomp @data; + + foreach my $line (@data) { + my ($file,$md5sum) = split(/:/,$line); + if ($dirwatchfile{$file}) {$dirwatchfile{$file} = $md5sum} + } + } + + my @alert = slurp("/usr/local/csf/tpl/watchalert.txt"); + foreach my $file (keys %dirwatchfile) { + unless (-e $file) { + logfile("Directory *File Watching* [$file] does not exist"); + next; + } + my @data; + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die}; + alarm(10); + @data = &syscommand(__LINE__,$config{LS},"--full-time","-lARt",$file); + alarm(0); + }; + alarm(0); + if ($@) { + logfile("Directory File Watching terminated after 10 seconds for $file: ".$@); + exit; + } + chomp @data; + my $md5current = Digest::MD5->new; + my $output; + foreach my $line (@data) { + $md5current->add($line); + $output .= $line."\n"; + } + my $md5sum = $md5current->b64digest; + + if ($dirwatchfile{$file} ne "1") { + if ($md5sum ne $dirwatchfile{$file}) { + $0 = "lfd - (child) suspicious file alert for $file"; + logfile("Directory *File Watching* has detected a change in $file"); + $dirwatchfile{$file} = $md5sum; + + my @newalert = @alert; + my @message; + foreach my $line (@newalert) { + $line =~ s/\[file\]/$file/ig; + $line =~ s/\[output\]/$output/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + } + } else { + $dirwatchfile{$file} = $md5sum; + } + } + + sysopen (my $TEMPWATCH, "/var/lib/csf/csf.tempwatch", O_WRONLY | O_CREAT) or &childcleanup(__LINE__,"*Error* Cannot write out file: $!"); + flock ($TEMPWATCH, LOCK_EX); + seek ($TEMPWATCH, 0, 0); + truncate ($TEMPWATCH, 0); + foreach my $file (keys %dirwatchfile) { + print $TEMPWATCH "$file:$dirwatchfile{$file}\n"; + } + close ($TEMPWATCH); + + close ($THISLOCK ); + if ($config{DEBUG} >= 3) {$timer = &timer("stop","dirwatchfile",$timer)} + $0 = "lfd - child closing"; + exit; + } + return; +} +# end dirwatchfile +############################################################################### +# start integrity +sub integrity { + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","integrity",$timer)} + + my $lockstr = "LF_INTEGRITY"; + sysopen (my $THISLOCK, "/var/lib/csf/lock/$lockstr.lock", O_RDWR | O_CREAT) or &childcleanup("*Error* Unable to open /var/lib/csf/lock/$lockstr.lock"); + flock ($THISLOCK, LOCK_EX | LOCK_NB) or &childcleanup("*Lock Error* [$lockstr] still active - section skipped"); + print $THISLOCK time; + + $0 = "lfd - checking system integrity"; + + my $integrity = '/usr/bin/* /usr/sbin/* /bin/* /sbin/* /usr/local/bin/* /usr/local/sbin/* /etc/init.d/* /etc/xinetd.d/* /etc/rc.local'; + my $alarm = int($config{LF_INTEGRITY}/10) + 10; + my $start = time; + my $tfail = 0; + + my $action; + if (-z "/var/lib/csf/csf.tempint") {$action = "start"} + unless (-e "/var/lib/csf/csf.tempint") {$action = "start"} + if ($action eq "start") { + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die}; + alarm($alarm); + &syscommand(__LINE__,"$config{MD5SUM} $integrity > /var/lib/csf/csf.tempint"); + alarm(0); + }; + alarm(0); + if ($@) { + logfile("System Integrity start terminated after $alarm seconds"); + $tfail = 1; + } + } else { + my @data; + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die}; + alarm($alarm); + @data = &syscommand(__LINE__,"$config{MD5SUM} --check /var/lib/csf/csf.tempint"); + alarm(0); + }; + alarm(0); + if ($@) { + logfile("System Integrity check terminated after $alarm seconds"); + $tfail = 1; + } else { + chomp @data; + my $report; + my $files; + foreach my $line (@data) { + my ($file,$text) = split(/:/,$line); + if ($text =~ /FAILED/) { + $report .= "$line\n"; + $files .= " $file"; + } + } + + if ($report) { + logfile("*System Integrity* has detected modified file(s):$files"); + $0 = "lfd - (child) system integrity alert"; + + my @alert = slurp("/usr/local/csf/tpl/integrityalert.txt"); + my @message; + foreach my $line (@alert) { + $line =~ s/\r//; + $line =~ s/\[text\]/$report/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + unlink "/var/lib/csf/csf.tempint"; + + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die}; + alarm($alarm); + &syscommand(__LINE__,"$config{MD5SUM} $integrity > /var/lib/csf/csf.tempint"); + alarm(0); + }; + alarm(0); + if ($@) { + logfile("System Integrity start terminated after $alarm seconds"); + $tfail = 1; + } + } + } + } + + if ($tfail) { + $config{LF_INTEGRITY} = $config{LF_INTEGRITY} * 1.5; + sysopen (my $TEMPCONF, "/var/lib/csf/csf.tempconf", O_WRONLY | O_APPEND | O_CREAT) or &childcleanup(__LINE__,"*Error* Cannot append out file: $!"); + flock ($TEMPCONF, LOCK_EX); + print $TEMPCONF "LF_INTEGRITY = \"$config{LF_INTEGRITY}\"\n"; + close ($TEMPCONF); + logfile("LF_INTEGRITY taking $alarm seconds, temporarily throttled to run every $config{LF_INTEGRITY} seconds"); + } + + close ($THISLOCK ); + if ($config{DEBUG} >= 3) {$timer = &timer("stop","integrity",$timer)} + $0 = "lfd - child closing"; + exit; + } + return; +} +# end integrity +############################################################################### +# start logscanner +sub logscanner { + my $hour = shift; + if (length $hour == 1) {$hour = "0$hour:00"} else {$hour = "$hour:00"} + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","logscanner",$timer)} + + my $lockstr = "LOGSCANNER"; + sysopen (my $THISLOCK, "/var/lib/csf/lock/$lockstr.lock", O_RDWR | O_CREAT) or &childcleanup("*Error* Unable to open /var/lib/csf/lock/$lockstr.lock"); + flock ($THISLOCK, LOCK_EX | LOCK_NB) or &childcleanup("*Lock Error* [$lockstr] still active - section skipped"); + print $THISLOCK time; + + $0 = "lfd - log scanner"; + + unless (-z "/var/lib/csf/csf.logtemp" and $config{LOGSCANNER_EMPTY} == 0) { + my $text; + my %loglines; + my $total = 0; + my $max = 0; + + sysopen (my $LOGTEMP,"/var/lib/csf/csf.logtemp", O_RDWR | O_CREAT); + flock ($LOGTEMP, LOCK_EX); + my @data = <$LOGTEMP>; + seek ($LOGTEMP, 0, 0); + truncate ($LOGTEMP, 0); + if (-e "/var/lib/csf/csf.logmax") { + unlink "/var/lib/csf/csf.logmax"; + $max = 1; + } + close ($LOGTEMP); + chomp @data; + + if ($config{LOGSCANNER_STYLE} == "1") { + foreach my $line (@data) { + my ($logfile,$logline) = split(/\|/,$line); + $loglines{$logfile} .= "$logline\n"; + $total++; + } + foreach my $logfile (keys %loglines) { + $text .= "$logfile:\n$loglines{$logfile}\n"; + } + } else { + foreach my $line (@data) { + my ($logfile,$logline) = split(/\|/,$line); + $text .= "$logline\n"; + $total++; + } + } + + if ($max) {$text .= "\n...Report truncated as it exceeded $config{LOGSCANNER_LINES} of log lines...\n"} + + if ($text eq "") {$text = "...No log lines to report..."} + + my @alert = slurp("/usr/local/csf/tpl/logalert.txt"); + my @message; + foreach my $line (@alert) { + $line =~ s/\r//; + $line =~ s/\[text\]/$text/ig; + $line =~ s/\[lines\]/$total/ig; + $line =~ s/\[hour\]/$hour/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + + if ($config{DEBUG} >= 1) {logfile("LOGSCANNER report sent")} + } + + close ($THISLOCK ); + if ($config{DEBUG} >= 3) {$timer = &timer("stop","logscanner",$timer)} + $0 = "lfd - child closing"; + exit; + } + return; +} +# end logscanner +############################################################################### +# start exploit +sub exploit { + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","exploit",$timer)} + + my $lockstr = "LF_EXPLOIT"; + sysopen (my $THISLOCK, "/var/lib/csf/lock/$lockstr.lock", O_RDWR | O_CREAT) or &childcleanup("*Error* Unable to open /var/lib/csf/lock/$lockstr.lock"); + flock ($THISLOCK, LOCK_EX | LOCK_NB) or &childcleanup("*Lock Error* [$lockstr] still active - section skipped"); + print $THISLOCK time; + + $0 = "lfd - checking system exploit"; + + my %exploit_tests; + foreach my $test (split(/\,/,$config{LF_EXPLOIT_IGNORE})) {$exploit_tests{$test} = 1} + my $report = ""; + + unless ($exploit_tests{SUPERUSER}) { + while (my ($name,undef,$uid) = getpwent()) { + if (($uid == 0) and ($name ne "root") and ($suignore{$name} != 1)) { + $report .= "Possible root compromise: User account $name is a superuser (UID 0)\n"; + logfile("*System Exploit* has detected a possible root compromise ($name = UID 0)"); + } + } + endpwent(); + } + + if ($report) { + $0 = "lfd - (child) system exploit alert"; + sysopen (my $TEMPEXPLOIT, "/var/lib/csf/csf.tempexploit", O_WRONLY | O_CREAT) or &childcleanup(__LINE__,"*Error* Cannot open out file: $!"); + flock ($TEMPEXPLOIT, LOCK_EX); + print $TEMPEXPLOIT time; + close ($TEMPEXPLOIT); + + my @alert = slurp("/usr/local/csf/tpl/exploitalert.txt"); + my @message; + foreach my $line (@alert) { + $line =~ s/\[text\]/$report/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + unlink "/var/lib/csf/csf.tempexp"; + } + + close ($THISLOCK ); + if ($config{DEBUG} >= 3) {$timer = &timer("stop","exploit",$timer)} + $0 = "lfd - child closing"; + exit; + } + return; +} +# end exploit +############################################################################### +# 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 hex2ip +sub hex2ip { + my $bin = pack "C*" => map hex, $_[0] =~ /../g; + my @l = unpack "L*", $bin; + if (@l == 4) { + return join ':', map { sprintf "%x:%x", $_ >> 16, $_ & 0xffff } @l; + } + elsif (@l == 1) { + return join '.', map { $_ >> 24, ($_ >> 16 ) & 0xff, ($_ >> 8) & 0xff, $_ & 0xff } @l; + } +} +## end hex2ip +############################################################################### +## start ipv4in6 +sub ipv4in6 { + my $in = $_[0]; + my @ipv6 = split (":", $in); + + my $v6part1 = hex($ipv6[6]); + my $v6part2 = hex($ipv6[7]); + + my $ip41=scalar($v6part1>>8); + my $ip42=scalar($v6part1&0xff); + my $ip43=scalar($v6part2>>8); + my $ip44=scalar($v6part2&0xff); + + my $out = $ip41 . "." . $ip42 . "." . $ip43 . "." . $ip44; + + return $out; +} +## end ipv4in6 +############################################################################### +# start cleanup +sub cleanup { + $SIG{INT} = 'IGNORE'; + $SIG{TERM} = 'IGNORE'; + $SIG{HUP} = 'IGNORE'; + my $line = shift; + my $message = shift; + + if (($message eq "") and $line) { + $message = "Main Process: $line"; + $line = ""; + } + + $0 = "lfd - stopping"; + + if ($message) { + if ($line ne "") {$message .= ", at line $line"} + logfile("$message"); + } + logfile("daemon stopped"); + + if ($PIDFILE and fileno($PIDFILE)) { + close($PIDFILE); + unlink $pidfile; + } + + kill (9, -$$); + + exit 0; +} +# end cleanup +############################################################################### +# start childcleanup +sub childcleanup { + $SIG{INT} = 'IGNORE'; + $SIG{TERM} = 'IGNORE'; + $SIG{HUP} = 'IGNORE'; + my $line = shift; + my $message = shift; + + if (($message eq "") and $line ne "") { + $message = "Child $childproc: $line"; + $line = ""; + } + + $0 = "child - aborting"; + + if ($message) { + if ($line ne "") {$message .= ", at line $line"} + logfile("$message"); + } + exit; +} +# end childcleanup +############################################################################### +# start ignoreip +sub ignoreip { + my $ip = shift; + my $skip = shift; + + if ($ip eq "") {return 0} + + if ($ips{$ip} or $ipscidr->find($ip) or $ipscidr6->find($ip)) {return 1} + + if ($ignoreips{$ip}) {return 1} + + if ($gignoreips{$ip}) {return 1} + + if ($config{CC_IGNORE}) { + my ($cc,$asn) = iplookup($ip,1); + ($asn,undef) = split(/\s+/,$asn); + if ($cc ne "" and $config{CC_IGNORE} =~ /$cc/i) {return 1} + if ($asn ne "" and $config{CC_IGNORE} =~ /$asn/i) {return 1} + } + + if ($relayip{$ip} and !$skip) {return 1} + + if (@cidrs) { + if ($cidr->find($ip)) {return 1} + if ($cidr6->find($ip)) {return 1} + } + + if (@gcidrs) { + if ($gcidr->find($ip)) {return 1} + if ($gcidr6->find($ip)) {return 1} + } + + if (@rdns and !$skip) { + my $matchdomain; + my $matchip; + + my $dnsip; + my $dnsrip; + my $dnshost; + my $cachehit; + open (my $DNS, "<", "/var/lib/csf/csf.dnscache"); + flock ($DNS, LOCK_SH); + while (my $line = <$DNS>) { + chomp $line; + ($dnsip,$dnsrip,$dnshost) = split(/\|/,$line); + if ($ip eq $dnsip) { + $cachehit = 1; + last; + } + } + close ($DNS); + if ($cachehit) { + $matchip = $dnsrip; + $matchdomain = $dnshost; + if ($config{DEBUG} >= 2) {logfile("debug: (ignoreip) [cached] [$ip]:[$matchip] [$matchdomain]")} + } else { + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die}; + alarm(8); + $matchip = inet_aton($ip); + $matchdomain = gethostbyaddr($matchip, AF_INET); + if ($matchdomain ne "") { + $matchip = gethostbyname($matchdomain); + $matchip = inet_ntoa($matchip); + } + alarm(0); + }; + alarm(0); + unless (checkip(\$matchip)) {$matchip = ""} + sysopen (my $DNS, "/var/lib/csf/csf.dnscache", O_WRONLY | O_APPEND | O_CREAT); + flock ($DNS, LOCK_EX); + print $DNS "$ip|$matchip|$matchdomain\n"; + close ($DNS); + if ($config{DEBUG} >= 2) {logfile("debug: (ignoreip) [not cached] [$ip]:[$matchip] [$matchdomain]")} + } + + if ($ip eq $matchip) { + foreach my $host (@rdns) { + if (($host =~ /\./) and ($matchdomain =~ /$host$/)) { + if ($config{DEBUG} >= 1) {logfile("debug: (ignoreip) [$ip]:[$matchip] [$host]:[$matchdomain]")} + return 1; + } + if ($matchdomain eq $host) { + if ($config{DEBUG} >= 1) {logfile("debug: (ignoreip) [$ip]:[$matchip] [$host]:[$matchdomain]")} + return 1; + } + } + } + } + + return 0; +} +# end ignoreip +############################################################################### +# start linefilter +sub linefilter { + my $line = shift; + my $ad = shift; + my $chain = shift; + my $delete = shift; + my $pktin = "$accept"; + my $pktout = "$accept"; + my $inadd = "-I"; + my $verbose = ""; + my $localin = "ALLOWIN"; + my $localout = "ALLOWOUT"; + 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 { + &iptablescmd(__LINE__,"$iptables $config{IPTABLESWAIT} $verbose -A $chainin $linein -s $line -j $pktin"); + if (($ad eq "deny" and !$config{LF_BLOCKINONLY}) or ($ad ne "deny")) {&iptablescmd(__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 { + &iptablescmd(__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 { + &iptablescmd(__LINE__,"$iptables $config{IPTABLESWAIT} $verbose $inadd $localin $linein -s $line -j $pktin"); + if (($ad eq "deny" and !$config{LF_BLOCKINONLY}) or ($ad ne "deny")) {&iptablescmd(__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 (($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) { + &iptablescmd(__LINE__,"$iptables $config{IPTABLESWAIT} $verbose -A $chainin $linein $protocol $dip $sip $dport $sport -j $pktin"); + } else { + if ($delete) { + &iptablescmd(__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 { + &iptablescmd(__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) { + &iptablescmd(__LINE__,"$iptables $config{IPTABLESWAIT} $verbose -A $chainout $lineout $protocol $dip $sip $dport $sport -j $pktout"); + } else { + if ($delete) { + &iptablescmd(__LINE__,"$iptables $config{IPTABLESWAIT} $verbose -D $localout $lineout $protocol $dip $sip $dport $sport -j $pktout"); + } else { + &iptablescmd(__LINE__,"$iptables $config{IPTABLESWAIT} $verbose $inadd $localout $lineout $protocol $dip $sip $dport $sport -j $pktout"); + } + } + } + } + } + return; +} +# end linefilter +############################################################################### +# start iptablescmd +sub iptablescmd { + my $line = shift; + my $command = shift; + $command =~ s/;`|//g; + 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 (-e "/etc/csf/csf.error") { + &cleanup(__LINE__,"*Error* csf reported an error (see /etc/csf/csf.error). *lfd stopped*"); + exit 1; + } + + if ($config{VPS}) {$status = &checkvps} + if ($status) { + logfile($status); + } else { + if ($config{DEBUG} >= 2) {logfile("debug[$line]: Command:$command")} + if (&csflock) { + logfile("csf is currently restarting - command [$command] skipped on line $line"); + unless ($masterpid == $$) {exit} + } + 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") { + &cleanup(__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} + if ($output[0] =~ /^deny failed\:/) {logfile("*Error*: csf output: $output[0]")} + if ($output[0] =~ /^Error\:/) {logfile("*Error*: csf output: $output[0]")} + if ($output[0] =~ /xtables lock/) {logfile("*Error*: Unable to check csf due to xtables lock, enable WAITLOCK in csf.conf")} + + 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) {logfile("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) {logfile("*Error* processing command for line [$line] ($repeat times): [$output[0]]");} + unless ($output[0] =~ /(^iptables: Unknown error 4294967295)|(xtables lock)/) {$cnt = $repeat} + } + } + elsif ($config{DEBUG} >= 1 and $output[0] =~ /^iptables|ip6tables|xtables|Bad|Another/) { + logfile("*Error* processing command for line [$line]: [$output[0]]"); + } + } + return; +} +# end iptablescmd +############################################################################### +# start syscommand +sub syscommand { + my ($line, @cmd) = @_; + my $cmdline = join(" ",@cmd); + my $status = 0; + my @output; + + if (-e "/etc/csf/csf.error") { + &cleanup(__LINE__,"*Error* csf reported an error (see /etc/csf/csf.error). *lfd stopped*"); + exit 1; + } + + if ($config{VPS}) {$status = &checkvps} + if ($status) { + logfile($status); + } else { + if ($config{DEBUG} >= 2) {logfile("debug[$line]: Command:$cmdline")} + if (&csflock) { + logfile("csf is currently restarting - command [$cmdline] skipped on line $line"); + unless ($masterpid == $$) {exit} + } + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, @cmd); + @output = <$childout>; + waitpid ($cmdpid, 0); + if ($output[0] =~ /# Warning: iptables-legacy tables present/) {shift @output} + if ($output[0] =~ /^deny failed\:/) {logfile("*Error*: csf output: $output[0]")} + if ($output[0] =~ /^Error\:/) {logfile("*Error*: csf output: $output[0]")} + } + return @output; +} +# 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 timer +sub timer { + my $status = shift; + my $check = shift; + my $start = shift; + + if ($status eq "start") { + logfile("debug: TIMER start: $check"); + return Time::HiRes::gettimeofday(); + } else { + if ($start == 0) {return} + my $diff = sprintf '%.6f', (Time::HiRes::gettimeofday() - $start); + logfile("debug: TIMER stop: $check ($diff secs)"); + } + return; +} +# end timer +############################################################################### +# start csflock +sub csflock { + my $ret = 0; + sysopen (my $CSFLOCKFILE, "/var/lib/csf/csf.lock", O_RDWR | O_CREAT) or &childcleanup("*Error* Unable to open csf lock file"); + flock ($CSFLOCKFILE, LOCK_SH | LOCK_NB) or $ret = 1; + close ($CSFLOCKFILE); + + return $ret; +} +# end csflock +############################################################################### +# start lockfail +sub lockfail { + my $section = shift; + logfile("csf is currently restarting - section [$section] skipped"); + exit; +} +# end lockfail +############################################################################### +# start ipblock +sub ipblock { + my $perm = shift; + my $message = shift; + my $ip = shift; + my $port = shift; + my $inout = shift; + my $timeout = shift; + my $cluster = shift; + my $logs = shift; + my $active = shift; + unless ($active) {$active = "other"} + my $return = 0; + + if ($message =~ / exceeds /) {$cluster = 1} + + my @report; + $report[0] = $ip; + if ($port) {$report[1] = "$port"} else {$report[1] = "*"} + if ($perm) {$report[2] = "1"} else {$report[2] = "0"} + if ($inout) {$report[3] = "$inout"} else {$report[3] = "inout"} + if ($timeout) {$report[4] = "$timeout"} else {$report[4] = "0"} + if ($message) {$report[5] = "$message"} else {$report[5] = " "} + if ($logs) {$report[6] = "$logs"} else {$report[6] = " "} + if ($active) {$report[7] = "$active"} + + my $ipv = checkip(\$ip); + unless ($ipv) {return 1} + my (undef,$iscidr) = split(/\//,$ip); + if ($iscidr and !$cluster and ($active ne "CT_SUBNET_LIMIT")) { + if ($config{DEBUG} >= 1) {logfile("debug: IP [$ip] not blocked, contains a CIDR (ignore already blocked message)")} + return 1; + } + + $0 = "lfd - (child) blocking $ip"; + + my $blocked = 0; + if (!$iscidr and ($config{LF_PERMBLOCK} or $config{LF_NETBLOCK})) { + if (&denycheck($ip)) { + $return = 2; + } else { + my $ips; + my $ipmatch; + my $ptext; + my $nips; + my $ntext; + my $nipmatch; + my $ipblock; + my @newdata; + my %skipip; + my %skipnip; + my $block_interval = $config{LF_PERMBLOCK_INTERVAL}; + if ($config{LF_NETBLOCK_INTERVAL} > $config{LF_PERMBLOCK_INTERVAL}) {$block_interval = $config{LF_NETBLOCK_INTERVAL}} + if ($ipv == 4) { + if ($config{LF_NETBLOCK_CLASS} eq "A") { + if ($ip =~ /^(\d+)/) {$ipblock = "$1\.0\.0\.0/8"} + } + elsif ($config{LF_NETBLOCK_CLASS} eq "B") { + if ($ip =~ /^(\d+\.\d+)/) {$ipblock = "$1\.0\.0/16"} + } + elsif ($config{LF_NETBLOCK_CLASS} eq "C") { + if ($ip =~ /^(\d+\.\d+\.\d+)/) {$ipblock = "$1\.0/24"} + } + } + elsif ($ipv == 6 and $config{LF_NETBLOCK_IPV6} ne "") { + if ($config{LF_NETBLOCK_IPV6} eq "/64" or $config{LF_NETBLOCK_IPV6} eq "/56" or $config{LF_NETBLOCK_IPV6} eq "/48" or $config{LF_NETBLOCK_IPV6} eq "/32" or $config{LF_NETBLOCK_IPV6} eq "24") { + eval { + local $SIG{__DIE__} = undef; + my $netip = $ip.$config{LF_NETBLOCK_IPV6}; + my $status = checkip(\$netip); + if ($status == 6) {$ipblock = $netip} + }; + } + } + + sysopen (my $TEMPIP, "/var/lib/csf/csf.tempip", O_RDWR | O_CREAT); + flock ($TEMPIP, LOCK_EX); + my @data = <$TEMPIP>; + chomp @data; + foreach my $line (@data) { + my ($oip,$operm,$otime,$omessage) = split(/\|/,$line,4); + if (time - $otime < $block_interval) { + push @newdata,$line; + } + if ($config{LF_PERMBLOCK} and !$perm) { + if (($ip eq $oip) and ($operm != 1) and (time - $otime < $config{LF_PERMBLOCK_INTERVAL})) { + $ips++; + $ptext .= localtime($otime)." $omessage\n"; + $skipip{$line} = 1; + } + if ($operm and ($ip eq $oip)) { + $ipmatch = 1; + } + } + if ($config{LF_NETBLOCK} and ($ipv == 4) and $ipblock) { + if (time - $otime < $config{LF_NETBLOCK_INTERVAL}) { + my $block = ""; + if ($config{LF_NETBLOCK_CLASS} eq "A") { + if ($oip =~ /^(\d+)/) {$block = "$1\.0\.0\.0/8"} + } + elsif ($config{LF_NETBLOCK_CLASS} eq "B") { + if ($oip =~ /^(\d+\.\d+)/) {$block = "$1\.0\.0/16"} + } + elsif ($config{LF_NETBLOCK_CLASS} eq "C") { + if ($oip =~ /^(\d+\.\d+\.\d+)/) {$block = "$1\.0/24"} + } + if ($block ne "" and ($ipblock eq $block)) { + unless ($oip eq $ip) { + $nips++; + $ntext .= localtime($otime)." $omessage\n"; + $skipnip{$line} = 1; + } + } +# if ($block eq $oip) {$nipmatch = 1} + } + } + if ($config{LF_NETBLOCK} and ($ipv == 6) and $config{LF_NETBLOCK_IPV6} ne "" and $ipblock) { + if (time - $otime < $config{LF_NETBLOCK_INTERVAL}) { + my $block = ""; + eval { + local $SIG{__DIE__} = undef; + my $netip = $oip.$config{LF_NETBLOCK_IPV6}; + my $status = checkip(\$netip); + if ($status == 6) {$block = $netip} + }; + if ($block ne "" and ($ipblock eq $block)) { + unless ($oip eq $ip) { + $nips++; + $ntext .= localtime($otime)." $omessage\n"; + $skipnip{$line} = 1; + } + } +# if ($block eq $oip) {$nipmatch = 1} + } + } + } + if ($ipmatch) { + $ips = 0; + undef %skipip; + if ($config{DEBUG} >= 1) {logfile("debug: $message - already PERM blocked")} + } else { + $ips++; + $ptext .= localtime(time)." $message\n"; + } + if ($nipmatch) { + $nips = 0; + undef %skipnip; + if ($config{DEBUG} >= 1) {logfile("debug: $message - already NET blocked")} + } else { + $nips++; + $ntext .= localtime(time)." $message\n"; + } + + if ($nips > $config{LF_NETBLOCK_COUNT}) { + my $status = 0; + if ($config{VPS}) {$status = &checkvps} + if ($status) { + logfile($status); + } else { + my $tip = iplookup($ipblock); + $message = "(NETBLOCK) $tip has had more than $config{LF_NETBLOCK_COUNT} blocks in the last $config{LF_NETBLOCK_INTERVAL} secs"; + &syscommand(__LINE__,"/usr/sbin/csf","-d",$ipblock,"lfd: $message"); + logfile("$message - *Blocked in csf* [$active]"); + if ($config{CLUSTER_BLOCK} and $config{CLUSTER_SENDTO} and !$cluster) {&lfdclient(1,$message,$ipblock,"","inout","0")} + if ($config{BLOCK_REPORT}) {&block_report($ipblock,"*","1","inout","0",$message,"","LF_NETBLOCK_COUNT")} + if ($config{ST_ENABLE}) {&stats_report($ipblock,"*","1","inout","0",$message,"","LF_NETBLOCK_COUNT")} + $blocked = 1; + } + + if ($config{LF_NETBLOCK_ALERT}) { + $0 = "lfd - (child) sending alert email for $ipblock"; + + my @alert = slurp("/usr/local/csf/tpl/netblock.txt"); + my @message; + my $tip = iplookup($ipblock); + foreach my $line (@alert) { + $line =~ s/\[block\]/$tip/ig; + $line =~ s/\[count\]/$nips/ig; + if (checkip(\$ipblock) == 4) { + $line =~ s/\[class\]/$config{LF_NETBLOCK_CLASS}/ig; + } else { + $line =~ s/\[class\]/$config{LF_NETBLOCK_IPV6}/ig; + } + $line =~ s/\[ips\]/$ntext/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + } + + $ip = $ipblock; + $perm = 1; + $blocked = 1; + } + elsif ($ips > $config{LF_PERMBLOCK_COUNT}) { + my $status = 0; + if ($config{VPS}) {$status = &checkvps} + if ($status) { + logfile($status); + } else { + my $tip = iplookup($ip); + $message = "(PERMBLOCK) $tip has had more than $config{LF_PERMBLOCK_COUNT} temp blocks in the last $config{LF_PERMBLOCK_INTERVAL} secs"; + &syscommand(__LINE__,"/usr/sbin/csf","-tr",$ip); + &syscommand(__LINE__,"/usr/sbin/csf","-d",$ip,"lfd: $message"); + logfile("$message - *Blocked in csf* [$active]"); + if ($config{CLUSTER_BLOCK} and $config{CLUSTER_SENDTO} and !$cluster) {&lfdclient(1,$message,$ip,"","inout","0")} + if ($config{BLOCK_REPORT}) {&block_report($ip,"*","1","inout","0",$message,"","LF_PERMBLOCK_COUNT")} + if ($config{ST_ENABLE}) {&stats_report($ip,"*","1","inout","0",$message,"","LF_PERMBLOCK_COUNT")} + $blocked = 1; + } + if ($config{LF_PERMBLOCK_ALERT}) { + $0 = "lfd - (child) sending alert email for $ip"; + + my @alert = slurp("/usr/local/csf/tpl/permblock.txt"); + my $tip = iplookup($ip); + my @message; + foreach my $line (@alert) { + $line =~ s/\[ip\]/$tip/ig; + $line =~ s/\[count\]/$ips/ig; + $line =~ s/\[blocks\]/$ptext/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + } + $perm = 1; + $blocked = 1; + } + seek ($TEMPIP, 0, 0); + truncate ($TEMPIP, 0); + foreach my $line (@newdata) { + if (($ips > $config{LF_PERMBLOCK_COUNT}) and ($skipip{$line})) {next} + if (($nips > $config{LF_NETBLOCK_COUNT}) and ($skipnip{$line})) {next} + print $TEMPIP "$line\n"; + } + print $TEMPIP "$ip|$perm|".time."|$message\n"; + close ($TEMPIP); + } + } + if (!$blocked and !$return) { + if ($perm) { + if ($port) { + foreach my $dport (split(/\,/,$port)) { + my $status = 0; + if ($config{VPS}) {$status = &checkvps} + if ($status) { + logfile($status); + } else { + if (&denycheck("tcp|in|d=$dport|s=$ip",undef,$perm)) { + $return = 2; + } else { + my ($tport,$proto) = split(/\;/,$dport); + $dport = $tport; + if ($proto eq "") {$proto = "tcp"} + &syscommand(__LINE__,"/usr/sbin/csf","-d","$proto|in|d=$dport|s=$ip","lfd: $message"); + logfile("$message - *Blocked in csf* port=$dport [$active]"); + $blocked = 1; + } + } + } + if ($blocked) {$return = 0} + } else { + my $status = 0; + if ($config{VPS}) {$status = &checkvps} + if ($status) { + logfile($status); + } else { + if (&denycheck($ip,undef,$perm)) { + $blocked = 0; + $return = 2; + } else { + $blocked = 1; + &syscommand(__LINE__,"/usr/sbin/csf","-d",$ip,"lfd: $message"); + logfile("$message - *Blocked in csf* [$active]"); + } + } + } + if ($blocked) { + if ($config{CLUSTER_BLOCK} and $config{CLUSTER_SENDTO} and !$cluster) {&lfdclient(1,$message,$ip,$port,$inout,"0")} + if ($config{BLOCK_REPORT}) {&block_report(@report)} + if ($config{ST_ENABLE}) {&stats_report(@report)} + } + } else { + if (&denycheck($ip,$port,$perm)) { + $return = 2; + } else { + 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} + my $iptype = checkip(\$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) { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -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 { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -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) { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -A DENYIN $eth6devin -s $ip -j $dropin"); + if ($config{MESSENGER6} and $config{MESSENGER_TEMP}) {&domessenger($ip,"A")} + } else { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -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) { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -A DENYOUT $eth6devout -p $proto --dport $dport -d $ip -j $dropout"); + } else { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -A DENYOUT $ethdevout -p $proto --dport $dport -d $ip -j $dropout"); + } + } + } else { + if ($iptype == 6) { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -A DENYOUT $eth6devout -d $ip -j $dropout"); + } else { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -A DENYOUT $ethdevout -d $ip -j $dropout"); + } + } + } + sysopen (my $TEMPBAN, "/var/lib/csf/csf.tempban", O_WRONLY | O_APPEND | O_CREAT) or &childcleanup(__LINE__,"*Error* Cannot append out file: $!"); + flock ($TEMPBAN, LOCK_EX); + print $TEMPBAN time."|$ip|$port|$inout|$timeout|lfd - $message\n"; + close ($TEMPBAN); + + if ($message) {logfile("$message - *Blocked in csf* for $timeout secs [$active]")} + if ($config{CLUSTER_BLOCK} and $config{CLUSTER_SENDTO} and !$cluster) {&lfdclient($perm,$message,$ip,$port,$inout,$timeout)} + if ($config{BLOCK_REPORT}) {&block_report(@report)} + if ($config{ST_ENABLE}) {&stats_report(@report)} + } + } + } + return $return; +} +# end ipblock +############################################################################### +# start ipunblock +sub ipunblock { + if (! -z "/var/lib/csf/csf.tempban") { + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + $0 = "lfd - processing temporary bans"; + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","ipunblock",$timer)} + sysopen (my $TEMPBAN, "/var/lib/csf/csf.tempban", O_RDWR | O_CREAT) or &childcleanup(__LINE__,"Unable to open /var/lib/csf/csf.tempban: $!"); + unless (flock ($TEMPBAN, LOCK_EX | LOCK_NB)) { + if ($config{DEBUG} >= 3) {logfile("debug: Unable to lock csf.tempban in ipunblock")} + } else { + my @data = <$TEMPBAN>; + chomp @data; + + my $cnt = @data; + my @newdata; + foreach my $line (@data) { + my $unblock = 0; + my $logmess = ""; + if ($config{DENY_TEMP_IP_LIMIT} and ($cnt > $config{DENY_TEMP_IP_LIMIT})) { + $unblock = 1; + $logmess = "(too many temporary bans in list)"; + } + my ($time,$ip,$port,$inout,$timeout,$message) = split(/\|/,$line); + my $iptype = checkip(\$ip); + if ((((time - $time) >= $timeout) and $ip) or $unblock) { + 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) { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -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 { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -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)} + } + logfile("Incoming IP $ip:$dport temporary block removed"); + if ($config{UNBLOCK_REPORT}) {&unblock_report($ip,$dport)}; + } + } else { + if ($iptype == 6) { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -D DENYIN $eth6devin -s $ip -j $dropin"); + if ($config{MESSENGER6} and $config{MESSENGER_TEMP}) {&domessenger($ip,"D")} + } else { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -D DENYIN $ethdevin -s $ip -j $dropin"); + if ($config{MESSENGER} and $config{MESSENGER_TEMP}) {&domessenger($ip,"D")} + } + logfile("Incoming IP $ip temporary block removed"); + if ($config{UNBLOCK_REPORT}) {&unblock_report($ip)}; + } + } + 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) { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -D DENYOUT $eth6devout -p $proto --dport $dport -d $ip -j $dropout"); + } else { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -D DENYOUT $ethdevout -p $proto --dport $dport -d $ip -j $dropout"); + } + logfile("Outgoing IP $ip:$dport temporary block removed"); + if ($config{UNBLOCK_REPORT}) {&unblock_report($ip,$dport)}; + } + } else { + if ($iptype == 6) { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -D DENYOUT $eth6devout -d $ip -j $dropout"); + } else { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -D DENYOUT $ethdevout -d $ip -j $dropout"); + } + logfile("Outgoing IP $ip temporary block removed"); + } + if ($config{UNBLOCK_REPORT}) {&unblock_report($ip)}; + } + if ($config{CF_ENABLE} and $message =~ /\(CF_ENABLE\)/) {&cloudflare("remove",$ip,$config{CF_BLOCK})} + } else { + push @newdata, $line; + } + $cnt--; + } + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die}; + alarm(60); + local $SIG{INT} = 'IGNORE'; + local $SIG{TERM} = 'IGNORE'; + local $SIG{HUP} = 'IGNORE'; + seek ($TEMPBAN, 0, 0); + truncate ($TEMPBAN, 0); + foreach my $line (@newdata) {print $TEMPBAN "$line\n"} + }; + alarm(0); + } + close ($TEMPBAN); + if ($config{DEBUG} >= 3) {$timer = &timer("stop","ipunblock",$timer)} + $0 = "lfd - (child) closing"; + exit; + } + } + if (! -z "/var/lib/csf/csf.tempallow") { + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + $0 = "lfd - processing temporary allows"; + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","ipunblock",$timer)} + sysopen (my $TEMPALLOW, "/var/lib/csf/csf.tempallow", O_RDWR | O_CREAT) or &childcleanup(__LINE__,"Enable to open /var/lib/csf/csf.tempallow: $!"); + unless (flock ($TEMPALLOW, LOCK_EX | LOCK_NB)) { + if ($config{DEBUG} >= 3) {logfile("debug: Unable to lock csf.tempallow in ipunblock")} + } else { + my @data = <$TEMPALLOW>; + chomp @data; + + my $cnt = @data; + my @newdata; + foreach my $line (@data) { + my ($time,$ip,$port,$inout,$timeout,$message) = split(/\|/,$line); + my $iptype = checkip(\$ip); + if ((((time - $time) >= $timeout) and $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) { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -D ALLOWIN $eth6devin -p $proto --dport $dport -s $ip -j $accept"); + } else { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -D ALLOWIN $ethdevin -p $proto --dport $dport -s $ip -j $accept"); + } + logfile("Incoming IP $ip:$dport temporary allow removed"); + } + } else { + if ($iptype == 6) { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -D ALLOWIN $eth6devin -s $ip -j $accept"); + } else { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -D ALLOWIN $ethdevin -s $ip -j $accept"); + } + logfile("Incoming IP $ip temporary allow removed"); + } + } + 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) { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -D ALLOWOUT $eth6devout -p $proto --dport $dport -d $ip -j $accept"); + } else { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -D ALLOWOUT $ethdevout -p $proto --dport $dport -d $ip -j $accept"); + } + logfile("Outgoing IP $ip:$dport temporary allow removed"); + } + } else { + if ($iptype == 6) { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -D ALLOWOUT $eth6devout -d $ip -j $accept"); + } else { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -D ALLOWOUT $ethdevout -d $ip -j $accept"); + } + logfile("Outgoing IP $ip temporary allow removed"); + } + } + if ($config{CF_ENABLE} and $message =~ /\(CF_ENABLE\)/) {&cloudflare("remove",$ip,"whitelist")} + } else { + push @newdata, $line; + } + $cnt--; + } + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die}; + alarm(60); + local $SIG{INT} = 'IGNORE'; + local $SIG{TERM} = 'IGNORE'; + local $SIG{HUP} = 'IGNORE'; + seek ($TEMPALLOW, 0, 0); + truncate ($TEMPALLOW, 0); + foreach my $line (@newdata) {print $TEMPALLOW "$line\n"} + }; + alarm(0); + } + close ($TEMPALLOW); + if ($config{DEBUG} >= 3) {$timer = &timer("stop","ipunblock",$timer)} + $0 = "lfd - (child) closing"; + exit; + } + } + return; +} +# end ipunblock +############################################################################### +# start cloudflare +sub cloudflare { + my $action = shift; + my $ip = shift; + my $mode = shift; + my $domains = shift;; + + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","cloudflare",$timer)} + $0 = "lfd - (child) CloudFlare $action..."; + + if ($action eq "remove") { + ConfigServer::CloudFlare::action("remove",$ip,$mode); + } + elsif ($action eq "deny") { + ConfigServer::CloudFlare::action("deny",$ip,$config{CF_BLOCK},"",$domains,1); + } + + if ($config{DEBUG} >= 3) {$timer = &timer("stop","cloudflare",$timer)} + $0 = "lfd - (child) closing"; + exit; + } + return; +} +# end cloudflare +############################################################################### +# start block_report +sub block_report { + my @report = @_; + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","block_report",$timer)} + $0 = "lfd - (child) Block Report..."; + + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die}; + alarm(10); + if ($config{DEBUG} >= 1) {&logfile("debug: BLOCK_REPORT [$config{BLOCK_REPORT}] triggered")} + system($config{BLOCK_REPORT},@report); + alarm(0); + }; + alarm(0); + if ($@) { + logfile("BLOCK_REPORT timed out after 10 seconds"); + } else { + if ($config{DEBUG} >= 3) {logfile("debug: BLOCK_REPORT [$config{BLOCK_REPORT}] for ['$report[0]' '$report[1]' '$report[2]' '$report[3]' '$report[4]' '$report[5]']")} + } + + if ($config{DEBUG} >= 3) {$timer = &timer("stop","block_report",$timer)} + $0 = "lfd - (child) closing"; + exit; + } + return; +} +# end block_report +############################################################################### +# start unblock_report +sub unblock_report { + my $ip = shift; + my $port = shift; + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","unblock_report",$timer)} + $0 = "lfd - (child) Block Report..."; + + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die}; + alarm(10); + system($config{UNBLOCK_REPORT},$ip,$port); + alarm(0); + }; + alarm(0); + if ($@) { + logfile("UNBLOCK_REPORT timed out after 10 seconds"); + } else { + if ($config{DEBUG} >= 3) {logfile("debug: UNBLOCK_REPORT [$config{UNBLOCK_REPORT}] for [$ip] [$port]")} + } + + if ($config{DEBUG} >= 3) {$timer = &timer("stop","unblock_report",$timer)} + $0 = "lfd - (child) closing"; + exit; + } + return; +} +# end unblock_report +############################################################################### +# start stats_report +sub stats_report { + my @report = @_; + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","stats_report",$timer)} + $0 = "lfd - (child) Stats Report..."; + + my $lockstr = "ST_ENABLE_report"; + sysopen (my $THISLOCK, "/var/lib/csf/lock/$lockstr.lock", O_RDWR | O_CREAT) or &childcleanup("*Error* Unable to open /var/lib/csf/lock/$lockstr.lock"); + unless (flock ($THISLOCK, LOCK_EX | LOCK_NB)) { + if ($config{DEBUG} >= 1) { + &childcleanup("debug: *Lock Error* [$lockstr] still active - section skipped"); + } else { + &childcleanup; + } + } + print $THISLOCK time; + + #[0-23] hour, [24-54] day, [55-57] month + my $STATS; + if (-e "/var/lib/csf/stats/lfdstats") { + sysopen ($STATS,"/var/lib/csf/stats/lfdstats", O_RDWR | O_CREAT); + } + elsif (-e "/var/lib/csf/stats/lfdmain") { + sysopen (my $OLDSTATS,"/var/lib/csf/stats/lfdmain", O_RDWR | O_CREAT); + flock ($OLDSTATS, LOCK_EX); + my @stats = <$OLDSTATS>; + chomp @stats; + + my @newstats; + my $cnt = 0; + foreach my $line (@stats) { + if ($cnt == 55) {push @newstats,""} + push @newstats,$line; + $cnt++; + } + sysopen (my $STATS,"/var/lib/csf/stats/lfdstats", O_RDWR | O_CREAT); + flock ($STATS, LOCK_EX); + seek ($STATS, 0, 0); + truncate ($STATS, 0); + foreach my $line (@newstats) { + print $STATS "$line\n"; + } + close ($STATS); + + rename "/var/lib/csf/stats/lfdmain", "/var/lib/csf/stats/lfdmain.".time; + close ($OLDSTATS); + sysopen ($STATS,"/var/lib/csf/stats/lfdstats", O_RDWR | O_CREAT); + } else { + sysopen ($STATS,"/var/lib/csf/stats/lfdstats", O_RDWR | O_CREAT); + } + flock ($STATS, LOCK_EX); + my @stats = <$STATS>; + chomp @stats; + + my $perm = $report[2]; + my $trigger = $report[7]; + my $time = time; + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time); + my @line; + my %triggers; + my $permdate; + my $permcount; + my $tempdate; + my $tempcount; + my $loop; + + @line = split(/\,/,$stats[$hour]); + $permdate = $line[0]; + $permcount = $line[1]; + $tempdate = $line[2]; + $tempcount = $line[3]; + for ($loop = 4; $loop < @line; $loop+=2) { + if ($time - $line[$loop] > (24 * 60 * 60)) {next} + my ($triggerstat,$triggercount) = split(/\:/,$line[$loop+1]); + $triggers{$triggerstat}{date} = $line[$loop]; + $triggers{$triggerstat}{count} = $triggercount; + } + $triggers{$trigger}{date} = $time; + $triggers{$trigger}{count}++; + if ($time - $permdate > (24 * 60 * 60)) {$permdate = 0; $permcount = 0} + if ($time - $tempdate > (24 * 60 * 60)) {$tempdate = 0; $tempcount = 0} + if ($perm) {$permdate = $time; $permcount++} else {$tempdate = $time; $tempcount++} + $stats[$hour] = "$permdate,$permcount,$tempdate,$tempcount"; + foreach my $key (keys %triggers) {$stats[$hour] .= ",$triggers{$key}{date},$key:$triggers{$key}{count}"} + + @line = split(/\,/,$stats[$mday+24]); + undef %triggers; + $permdate = $line[0]; + $permcount = $line[1]; + $tempdate = $line[2]; + $tempcount = $line[3]; + for ($loop = 4; $loop < @line; $loop+=2) { + if ($time - $line[$loop] > (29 * 24 * 60 * 60)) {next} + my ($triggerstat,$triggercount) = split(/\:/,$line[$loop+1]); + $triggers{$triggerstat}{date} = $line[$loop]; + $triggers{$triggerstat}{count} = $triggercount; + } + $triggers{$trigger}{date} = $time; + $triggers{$trigger}{count}++; + if ($time - $permdate > (29 * 24 * 60 * 60)) {$permdate = 0; $permcount = 0} + if ($time - $tempdate > (29 * 24 * 60 * 60)) {$tempdate = 0; $tempcount = 0} + if ($perm) {$permdate = $time; $permcount++} else {$tempdate = $time; $tempcount++} + $stats[$mday+24] = "$permdate,$permcount,$tempdate,$tempcount"; + foreach my $key (keys %triggers) {$stats[$mday+24] .= ",$triggers{$key}{date},$key:$triggers{$key}{count}"} + + @line = split(/\,/,$stats[$mon+56]); + undef %triggers; + $permdate = $line[0]; + $permcount = $line[1]; + $tempdate = $line[2]; + $tempcount = $line[3]; + for ($loop = 4; $loop < @line; $loop+=2) { + if ($time - $line[$loop] > (364 * 24 * 60 * 60)) {next} + my ($triggerstat,$triggercount) = split(/\:/,$line[$loop+1]); + $triggers{$triggerstat}{date} = $line[$loop]; + $triggers{$triggerstat}{count} = $triggercount; + } + $triggers{$trigger}{date} = $time; + $triggers{$trigger}{count}++; + if ($time - $permdate > (364 * 24 * 60 * 60)) {$permdate = 0; $permcount = 0} + if ($time - $tempdate > (364 * 24 * 60 * 60)) {$tempdate = 0; $tempcount = 0} + if ($perm) {$permdate = $time; $permcount++} else {$tempdate = $time; $tempcount++} + $stats[$mon+56] = "$permdate,$permcount,$tempdate,$tempcount"; + foreach my $key (keys %triggers) {$stats[$mon+56] .= ",$triggers{$key}{date},$key:$triggers{$key}{count}"} + + if ($config{CC_LOOKUPS}) { + my $cc = "**"; + my %ccs; + @line = split(/\,/,$stats[69]); + if ($report[5] =~ /\s\((\w\w)\//) {$cc = $1} + for (my $x = 0; $x < @line; $x+=2) {$ccs{$line[$x]} = $line[$x+1]} + $ccs{$cc}++; + $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); + + close ($THISLOCK); + + if ($config{DEBUG} >= 3) {$timer = &timer("stop","stats_report",$timer)} + $0 = "lfd - (child) closing"; + exit; + } + return; +} +# end stats_report +############################################################################### +# 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) - *IP not blocked*"} + } + } + } + return 0; +} +# end checkvps +############################################################################### +# start messengerrecaptcha +sub messengerrecaptcha { + my $timer = time; + my (undef,undef,$uid,$gid,undef,undef,undef,$homedir) = getpwnam($config{MESSENGER_USER}); + if (-z "$homedir/unblock.txt") {return} + + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + if ($config{DEBUG} >= 3) {$timer = &timer("start","messengerrecaptcha",$timer)} + $0 = "lfd - reCAPTCHA csf..."; + $childproc = "Messenger (Recaptcha)"; + $SIG{INT} = \&childcleanup; + $SIG{TERM} = \&childcleanup; + $SIG{HUP} = \&childcleanup; + $SIG{__DIE__} = sub {&childcleanup(@_);}; + + if (-f "$homedir/unblock.txt") { + my @alert = slurp("/usr/local/csf/tpl/recaptcha.txt"); + sysopen (my $UNBLOCK, "$homedir/unblock.txt", O_RDWR | O_CREAT); + flock($UNBLOCK, LOCK_EX); + while (my $line = <$UNBLOCK>) { + chomp $line; + my ($unblockip,$host,$hostip) = split(/;/,$line); + if (checkip(\$unblockip)) { + &logfile("reCAPTCHA: Unblocking client [$unblockip] on domain [$host ($hostip)]"); + &syscommand(__LINE__,"/usr/sbin/csf","-dr",$unblockip); + &syscommand(__LINE__,"/usr/sbin/csf","-tr",$unblockip); + + if ($config{RECAPTCHA_ALERT}) { + my $tip = iplookup($unblockip); + my @message; + foreach my $line (@alert) { + $line =~ s/\[ip\]/$tip/ig; + $line =~ s/\[host\]/$host ($hostip)/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + + if ($config{DEBUG} >= 1) {logfile("debug: recaptcha email sent for $unblockip")} + } + } + } + seek ($UNBLOCK, 0, 0); + truncate ($UNBLOCK, 0); + close ($UNBLOCK); + } + + if ($config{DEBUG} >= 3) {$timer = &timer("stop","messengerrecaptcha",$timer)} + exit; + } + return; +} +# end messengerrecaptcha +############################################################################### +# start messenger +sub messengerstop { + my $version = shift; + if ($version == 1) { + return; + } + elsif ($version == 2) { + if (-e "/etc/apache2/conf.d/csf.messenger.conf") { + unlink("/etc/apache2/conf.d/csf.messenger.conf"); + system("/scripts/restartsrv_httpd"); + logfile("*MESSENGERV2* Removed /etc/apache2/conf.d/csf.messenger.conf"); + } + } + elsif ($version == 3) { + if (-d $config{MESSENGERV3LOCATION}) { + if (-e $config{MESSENGERV3LOCATION}."/csf.messenger.conf") { + unlink($config{MESSENGERV3LOCATION}."/csf.messenger.conf"); + system($config{MESSENGERV3RESTART}); + logfile("*MESSENGERV3* Removed ".$config{MESSENGERV3LOCATION}."/csf.messenger.conf"); + } + } + elsif (-f $config{MESSENGERV3LOCATION}) { + my @conf = slurp($config{MESSENGERV3LOCATION}); + if (grep {$_ =~ m[^Include /var/lib/csf/csf.conf]i} @conf) { + sysopen (my $FILE, $config{MESSENGERV3LOCATION}, O_WRONLY | O_CREAT | O_TRUNC); + flock ($FILE, LOCK_EX); + foreach my $line (@conf) { + $line =~ s/$cleanreg//g; + if ($line =~ m[^Include /var/lib/csf/csf.conf]i) {next} + print $FILE $line."\n"; + } + close ($FILE); + system($config{MESSENGERV3RESTART}); + logfile("*MESSENGERV3* Removed from $config{MESSENGERV3LOCATION}"); + } + } + } + + return; +} +# end messengerstop +############################################################################### +# start messenger +sub messenger { + my $port = shift; + my $user = shift; + my $type = shift; + my $timer = time; + + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + $messengerips{$type} = $childpid; + unless ($childpid) { + if ($config{DEBUG} >= 3) {$timer = &timer("start","messenger",$timer)} + $0 = "lfd - messenger csf..."; + $SIG{INT} = \&childcleanup; + $SIG{TERM} = \&childcleanup; + $SIG{HUP} = \&childcleanup; + $SIG{__DIE__} = sub {&childcleanup(@_);}; + $childproc = "Messenger ($type)"; + + my ($status,$reason) = $messenger1->start($port,$user,$type); + if ($status) { + logfile("*MESSENGER*: Error starting $type service: $reason"); + sysopen (my $TEMPCONF, "/var/lib/csf/csf.tempconf", O_WRONLY | O_APPEND | O_CREAT) or &childcleanup(__LINE__,"*Error* Cannot append out file: $!"); + flock ($TEMPCONF, LOCK_EX); + print $TEMPCONF "MESSENGER_${type}_IN = \"\"\n"; + close ($TEMPCONF); + logfile("*MESSENGER*: $type service temporarily *DISABLED*"); + } + if ($config{DEBUG} >= 3) {$timer = &timer("stop","messenger",$timer)} + exit; + } + return; +} +# end messenger +############################################################################### +# start messengerv2 +sub messengerv2 { + my $timer = time; + + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + if ($config{DEBUG} >= 3) {$timer = &timer("start","messengerv2",$timer)} + $0 = "lfd - messenger csf..."; + + my ($status,$reason) = $messenger2->start(); + if ($status) { + logfile("*MESSENGERV2* Error: $reason"); + } + if ($config{DEBUG} >= 3) {$timer = &timer("stop","messengerv2",$timer)} + exit; + } + return; +} +# end messengerv2 +############################################################################### +# start messengerv3 +sub messengerv3 { + my $timer = time; + + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + if ($config{DEBUG} >= 3) {$timer = &timer("start","messengerv3",$timer)} + $0 = "lfd - messenger csf..."; + + my ($status,$reason) = $messenger3->start(); + if ($status) { + logfile("*MESSENGERV3* Error: $reason"); + } + if ($config{DEBUG} >= 3) {$timer = &timer("stop","messengerv3",$timer)} + exit; + } + return; +} +# end messengerv3 +############################################################################### +# 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 ($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) { + &iptablescmd(__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}) { + &iptablescmd(__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) { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -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}) { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -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) { + &iptablescmd(__LINE__,"$config{IPTABLES} $config{IPTABLESWAIT} -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}) { + &iptablescmd(__LINE__,"$config{IP6TABLES} $config{IPTABLESWAIT} -t nat $del PREROUTING $ethdevin -p tcp -s $ip -m multiport --dports $textports -j REDIRECT --to-ports $config{MESSENGER_TEXT}"); + } + } + } + return; +} +# end domessenger +############################################################################### +# start ui +sub ui { + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + $uiip = $childpid; + unless ($childpid) { + $0 = "lfd UI"; + $SIG{INT} = \&childcleanup; + $SIG{TERM} = \&childcleanup; + $SIG{HUP} = \&childcleanup; + $SIG{__DIE__} = sub {&childcleanup(@_);}; + $childproc = "UI"; + + my @alert = slurp("/usr/local/csf/tpl/uialert.txt"); + my $server; + if ($config{IPV6}) { + $server = IO::Socket::SSL->new( + Domain => AF_INET6, + LocalAddr => $config{UI_IP}, + LocalPort => $config{UI_PORT}, + Type => SOCK_STREAM, + ReuseAddr => 1, + Listen => $config{UI_CHILDREN}, + SSL_server => 1, + SSL_use_cert => 1, + SSL_cipher_list => $config{UI_CIPHER}, + SSL_honor_cipher_order => 1, + SSL_version => $config{UI_SSL_VERSION}, + SSL_key_file => '/etc/csf/ui/server.key', + SSL_cert_file => '/etc/csf/ui/server.crt', + ) or &childcleanup(__LINE__,"UI: *Error* cannot open server on port $config{UI_PORT}: ".IO::Socket::SSL->errstr); + } else { + $server = IO::Socket::SSL->new( + Domain => AF_INET, + LocalAddr => $config{UI_IP}, + LocalPort => $config{UI_PORT}, + Type => SOCK_STREAM, + ReuseAddr => 1, + Listen => $config{UI_CHILDREN}, + SSL_server => 1, + SSL_use_cert => 1, + SSL_cipher_list => $config{UI_CIPHER}, + SSL_honor_cipher_order => 1, + SSL_version => $config{UI_SSL_VERSION}, + SSL_key_file => '/etc/csf/ui/server.key', + SSL_cert_file => '/etc/csf/ui/server.crt', + ) or &childcleanup(__LINE__,"UI: *Error* cannot open server on port $config{UI_PORT}: ".IO::Socket::SSL->errstr); + } + + my $looperrors; + while (1) { + my $client = $server->accept(); + unless ($client) { + $looperrors++; + if ($looperrors > 1000) { + logfile("UI: *Error* looping process"); + last; + } + if ($config{DEBUG} >= 1) {logfile("UI debug: [loop:$looperrors] [$@]")} + next; + } + $SIG{CHLD} = 'IGNORE'; + my $pid = fork; + if ($pid == 0) { + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die "Connection timeout!\n"}; + alarm(10); + close $server; + + our %FORM; + our $myv; + our $script; + our $images; + our $fileinc; + + my $input; + my $session; + my $file; + my $cookie; + my %header; + my %fails; + my $application = "csf"; + my $buffer; + my $clientcnt; + my $request; + my @chars = ('0'..'9','a'..'z','A'..'Z'); + my $valid = "login"; + my $maxheader = 64; + my $maxbody = 64 * 1024 * 1024; + my $maxline = 1024 * 1024; + my $peeraddress = $client->peerhost; + + if ($peeraddress =~ /^::ffff:(\d+\.\d+\.\d+\.\d+)$/) {$peeraddress = $1} + if ($peeraddress eq "") { + close ($client); + alarm(0); + exit; + } + $ENV{REMOTE_ADDR} = $peeraddress; ##no critic + + if ($ips{$peeraddress}) { + logfile("UI: Login attempt from local IP address denied [$peeraddress]"); + if ($config{UI_ALERT} >= 4) { + my @message; + my $tip = iplookup($peeraddress); + foreach my $line (@alert) { + $line =~ s/\[ip\]/$tip/ig; + $line =~ s/\[alert\]/Login attempt from local IP/ig; + $line =~ s/\[text\]/Login attempt from local IP address $tip - denied/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + } + close ($client); + alarm(0); + exit; + } + + if ($config{"UI_BAN"}) { + open (my $UIBAN,"<","/etc/csf/ui/ui.ban"); + flock ($UIBAN, LOCK_SH); + my @records = <$UIBAN>; + chomp @records; + close ($UIBAN); + foreach my $record (@records) { + if ($record =~ /^(\#|\s|\r|\n)/) {next} + my ($rip,undef) = split(/\s/,$record); + if ($rip eq $peeraddress) { + logfile("UI: Access attempt from a banned IP address in /etc/csf/ui/ui.ban - denied [$peeraddress]"); + if ($config{UI_ALERT} >= 4) { + my @message; + my $tip = iplookup($peeraddress); + foreach my $line (@alert) { + $line =~ s/\[ip\]/$tip/ig; + $line =~ s/\[alert\]/Access attempt from banned IP/ig; + $line =~ s/\[text\]/Access attempt from a banned IP $tip in \/etc\/csf\/ui\/ui\.ban - denied/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + } + close ($client); + alarm(0); + exit; + } + } + } + + if ($config{"UI_ALLOW"}) { + my $allow = 0; + sysopen (my $UIALLOW,"/etc/csf/ui/ui.allow", O_RDWR | O_CREAT); + flock ($UIALLOW, LOCK_SH); + my @records = <$UIALLOW>; + chomp @records; + close ($UIALLOW); + foreach my $record (@records) { + if ($record =~ /^(\#|\s|\r|\n)/) {next} + my ($rip,undef) = split(/\s/,$record); + if ($rip eq $peeraddress) { + $allow = 1; + last; + } + my (undef,$cidr) = split(/\//,$rip); + if ($cidr) { + my $uicidr = Net::CIDR::Lite->new; + eval {local $SIG{__DIE__} = undef; $uicidr->add($rip)}; + if ($uicidr->find($peeraddress)) { + $allow = 1; + last; + } + } + } + unless ($allow) { + logfile("UI: Access attempt from an IP not in /etc/csf/ui/ui.allow - denied [$peeraddress]"); + if ($config{UI_ALERT} >= 4) { + my @message; + my $tip = iplookup($peeraddress); + foreach my $line (@alert) { + $line =~ s/\[ip\]/$tip/ig; + $line =~ s/\[alert\]/Login attempt/ig; + $line =~ s/\[text\]/Access attempt from an IP $tip not in \/etc\/csf\/ui\/ui\.allow - denied/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + } + close ($client); + alarm(0); + exit; + } + } + + select $client; ##no critic + $| = 1; + + $clientcnt = 0; + while ($request !~ /\n$/) { + my $char; + $client->read($char,1); + $request .= $char; + $clientcnt++; + if ($char eq "") { + if ($config{DEBUG} >= 2) {logfile("UI debug: Child [request] finished")} + close ($client); + alarm(0); + exit; + } + if ($clientcnt > $maxline) { + &ui_413; + close ($client); + alarm(0); + exit; + } + } + $request =~ s/\r\n$//; + if ($request =~ /^(GET|POST)\s(\S+)\sHTTP/) { + ($file,undef) = split(/\?/,$2); + if ($file =~ /^\/(\w+)(\/.*)/) { + $session = $1; + $file = $2; + } + } else { + close ($client); + alarm(0); + exit; + } + my $linecnt; + while (1) { + my $line; + $clientcnt = 0; + while ($line !~ /\n$/) { + my $char; + $client->read($char,1); + $line .= $char; + $clientcnt++; + if ($char eq "") { + if ($config{DEBUG} >= 2) {logfile("UI debug: Child [header] finished")} + close ($client); + alarm(0); + exit; + } + if ($clientcnt > $maxline) { + &ui_413; + close ($client); + alarm(0); + exit; + } + } + if ($line =~ /^\r\n$/) {last} + $line =~ s/\r\n$//; + my ($field,$value) = split(/\:\s/,$line); + $header{$field} = $value; + if ($config{DEBUG} >= 2) {logfile("UI debug: header [$field] [$value]")} + $linecnt++; + if ($linecnt > $maxheader) { + &ui_413; + close ($client); + alarm(0); + exit; + } + } + if ($header{'Content-Length'} > 0) { + if ($header{'Content-Length'} > $maxbody) { + &ui_413; + close ($client); + alarm(0); + exit; + } else { + if ($header{'Content-Type'} =~ /multipart\/form-data/) { + $client->read($fileinc,$header{'Content-Length'}); + } else { + $client->read($buffer,$header{'Content-Length'}); + } + } + } + if ($request =~ /^GET\s(\S+)\sHTTP/) {if ($1 =~ /\?([^\?]*)$/) {$buffer = $1}} + if ($config{DEBUG} >= 2) {logfile("UI debug: request [$request] buffer [$buffer]")} + 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; + } + if ($header{Cookie} =~ /csfsession=(\w+)/) {$cookie = $1} + + if (($session ne "" and $cookie ne "") or defined $FORM{csflogin}) { + sysopen (my $SESSION,"/var/lib/csf/ui/ui.session", O_RDWR | O_CREAT) or &childcleanup(__LINE__,"UI: unable to open csf.session: $!"); + flock ($SESSION, LOCK_EX); + my @records = <$SESSION>; + chomp @records; + seek ($SESSION, 0, 0); + truncate ($SESSION, 0); + + my $md5current = Digest::MD5->new; + $md5current->add($header{'User-Agent'}); + my $md5sum = $md5current->b64digest; + foreach my $record (@records) { + my ($rtype,$rstart,$rtime,$rsession,$rcookie,$rip,$rhead,$rapp) = split(/\|/,$record,8); + if ($rtype eq "login" and $rip eq $peeraddress and $rsession eq $session) { + if ((time - $rtime) > $config{UI_TIMEOUT}) { + $valid = "login"; + $record = ""; + ($rstart,$rtime,$rsession,$rcookie,$rip,$rhead) = ""; + logfile("UI: *Invalid session* $peeraddress [timeout]"); + } + elsif ($rcookie eq $cookie) { + if ($rhead eq $md5sum) { + if ($FORM{csfaction} eq "csflogout") { + $valid = "login"; + $record = ""; + logfile("UI: Successful logout from $peeraddress"); + } else { + $valid = "session"; + $application = $rapp; + $rtime = time; + $record = "$rtype|$rstart|$rtime|$rsession|$rcookie|$rip|$rhead|$rapp"; + } + } else { + $valid = "fail"; + $record = ""; + logfile("UI: *Invalid session* $peeraddress [session-header]"); + } + } else { + $valid = "fail"; + $record = ""; + logfile("UI: *Invalid session* $peeraddress [session-cookie]"); + } + } else { + if ($rtype eq "login") { + if ((time - $rtime) > $config{UI_TIMEOUT}) { + $record = ""; + ($rstart,$rtime,$rsession,$rcookie,$rip,$rhead) = ""; + } + } + elsif ($rtype eq "fail") { + if ((time - $rstart) > 86400) { + $record = ""; + } else { + $fails{$rip}++; + } + } + } + if ($record ne "") {print $SESSION "$record\n"} + } + close ($SESSION); + } else { + $valid = "login"; + } + if (defined $FORM{csflogin} and $valid ne "fail") { + if ($FORM{csflogin} eq $config{UI_USER} and $FORM{csfpassword} eq $config{UI_PASS}) { + $valid = "yes"; + } else { + $valid = "fail"; + } + } + + if ($valid eq "fail") { + $fails{$peeraddress}++; + if ($fails{$peeraddress} > $config{UI_RETRY}) { + if ($config{UI_BAN}) { + sysopen (my $SESSIONBAN,"/etc/csf/ui/ui.ban", O_WRONLY | O_APPEND | O_CREAT) or &childcleanup(__LINE__,"UI: unable to open csf.session: $!"); + flock ($SESSIONBAN, LOCK_EX); + print $SESSIONBAN "$peeraddress - Banned for too many login failures ".localtime()."\n"; + close ($SESSIONBAN); + logfile("UI: *Invalid login* attempts from $peeraddress [$fails{$peeraddress}/$config{UI_RETRY}] - Banned in /etc/csf/ui/ui.ban"); + } else { + logfile("UI: *Invalid login* attempts from $peeraddress [$fails{$peeraddress}/$config{UI_RETRY}] - Not Banned"); + } + sysopen (my $SESSION,"/var/lib/csf/ui/ui.session", O_RDWR | O_CREAT) or &childcleanup(__LINE__,"UI: unable to open csf.session: $!"); + flock ($SESSION, LOCK_EX); + my @records = <$SESSION>; + chomp @records; + seek ($SESSION, 0, 0); + truncate ($SESSION, 0); + foreach my $record (@records) { + my ($rtype,$rstart,$rtime,$rsession,$rcookie,$rip,$rhead,$rapp) = split(/\|/,$record,8); + if ($rip eq $peeraddress) {next} + print $SESSION "$record\n" + } + close ($SESSION); + if ($config{UI_BLOCK}) { + my $perm = 0; + if ($config{UI_BLOCK} == 1) {$perm = 1} + my $tip = iplookup($peeraddress); + &ipblock("1","UI: Invalid login attempts from $tip",$peeraddress,"","in",$config{UI_BLOCK},0,"UI: *Invalid login* attempts from $peeraddress [$fails{$peeraddress}/$config{UI_RETRY}] - Banned","UI_RETRY"); + } + if ($config{UI_ALERT} >= 1) { + my @message; + my $tip = iplookup($peeraddress); + my $text; + if ($config{UI_BAN}) {$text .= "Banned in ui.ban"} + if ($config{UI_BLOCK}) { + if ($text ne "") {$text .= ", "} + $text .= "Blocked in csf"; + } + foreach my $line (@alert) { + $line =~ s/\[ip\]/$tip/ig; + $line =~ s/\[alert\]/Login failure \[$fails{$peeraddress}\/$config{UI_RETRY}]/ig; + $line =~ s/\[text\]/Login failure from IP address $tip \[$fails{$peeraddress}\/$config{UI_RETRY}] - $text/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + } + &ui_403; + close ($client); + alarm(0); + exit; + } else { + my $time = time; + sysopen (my $SESSION,"/var/lib/csf/ui/ui.session", O_WRONLY | O_APPEND | O_CREAT) or &childcleanup(__LINE__,"UI: unable to open csf.session: $!"); + flock ($SESSION, LOCK_EX); + print $SESSION "fail|$time||||$peeraddress||\n"; + close ($SESSION); + $valid = "login"; + logfile("UI: *Invalid login* attempt from $peeraddress [$fails{$peeraddress}/$config{UI_RETRY}]"); + if ($config{UI_ALERT} >= 2) { + my @message; + my $tip = iplookup($peeraddress); + foreach my $line (@alert) { + $line =~ s/\[ip\]/$tip/ig; + $line =~ s/\[alert\]/Login failure \[$fails{$peeraddress}\/$config{UI_RETRY}]/ig; + $line =~ s/\[text\]/Login failure from IP address $tip \[$fails{$peeraddress}\/$config{UI_RETRY}] - denied/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + } + } + } + if ($valid eq "yes") { + srand; + $session = join '', map {$chars[rand(@chars)]} (1..(15 + int(rand(15)))); + $cookie = join '', map {$chars[rand(@chars)]} (1..(15 + int(rand(15)))); + + my $md5current = Digest::MD5->new; + $md5current->add($header{'User-Agent'}); + my $md5sum = $md5current->b64digest; + my $time = time; + sysopen (my $SESSION,"/var/lib/csf/ui/ui.session", O_RDWR | O_CREAT) or &childcleanup(__LINE__,"UI: unable to open csf.session: $!"); + flock ($SESSION, LOCK_EX); + my @records = <$SESSION>; + chomp @records; + seek ($SESSION, 0, 0); + truncate ($SESSION, 0); + foreach my $record (@records) { + my ($rtype,$rstart,$rtime,$rsession,$rcookie,$rip,$rhead) = split(/\|/,$record,8); + if ($rtype eq "fail" and $rip eq $peeraddress) {next} + print $SESSION "$record\n" + } + print $SESSION "login|$time|$time|$session|$cookie|$peeraddress|$md5sum|$application\n"; + close ($SESSION); + + print "HTTP/1.0 301 Moved Permanently\r\n"; + print "Location: /$session/\r\n"; + print "Set-Cookie: csfsession=$cookie; secure\r\n"; + print "\r\n"; + + logfile("UI: Successful login from $peeraddress"); + if ($config{UI_ALERT} >= 3) { + my @message; + my $tip = iplookup($peeraddress); + foreach my $line (@alert) { + $line =~ s/\[ip\]/$tip/ig; + $line =~ s/\[alert\]/Login success/ig; + $line =~ s/\[text\]/Login success from IP address $tip/ig; + push @message, $line; + } + ConfigServer::Sendmail::relay("", "", @message); + } + } + if ($valid eq "login") { + print "HTTP/1.0 200 OK\r\n"; + print "Content-type: text/html\r\n"; + print "\r\n"; + print "\n"; + print "\nConfigServer Security & Firewall\n\n"; + if ($valid eq "failed") {print "

          Login Failed

          \n"} + print "
          \n"; + print "
          \n"; + print "\n"; + print "\n"; + print "\n"; + print "<", "/table>\n"; + print "\n\n\n"; + } + if ($valid eq "session") { + if (defined $FORM{csfapp} and ($FORM{csfapp} ne $application)) { + my $newapp = $application; + if ($FORM{csfapp} eq "csf") {$newapp = "csf"} + elsif ($FORM{csfapp} eq "cxs" and $config{UI_CXS}) {$newapp = "cxs"} + elsif ($FORM{csfapp} eq "cse" and $config{UI_CSE}) {$newapp = "cse"} + if ($newapp ne $application) { + sysopen (my $SESSION,"/var/lib/csf/ui/ui.session", O_RDWR | O_CREAT) or &childcleanup(__LINE__,"UI: unable to open csf.session: $!"); + flock ($SESSION, LOCK_EX); + my @records = <$SESSION>; + chomp @records; + seek ($SESSION, 0, 0); + truncate ($SESSION, 0); + foreach my $record (@records) { + my ($rtype,$rstart,$rtime,$rsession,$rcookie,$rip,$rhead,$rapp) = split(/\|/,$record,8); + if ($rip eq $peeraddress and $rsession eq $session) { + $record = "$rtype|$rstart|$rtime|$rsession|$rcookie|$rip|$rhead|$newapp"; + $application = $newapp; + } + print $SESSION "$record\n" + } + close ($SESSION); + } + } + if ($file eq "/") { + print "HTTP/1.0 200 OK\r\n"; + if ($application eq "csf") { + open (my $IN, "<", "/etc/csf/version.txt") or die $!; + flock ($IN, LOCK_SH); + $myv = <$IN>; + close ($IN); + chomp $myv; + $script = "/$session/"; + $images = "/$session/images"; + $config{THIS_UI} = 1; + 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 = ""; + } + + print "Content-type: text/html\r\n"; + print "\r\n"; + unless ($FORM{action} eq "tailcmd" or $FORM{action} =~ /^cf/ or $FORM{action} eq "logtailcmd" or $FORM{action} eq "loggrepcmd") { + print < + + +ConfigServer Security & Firewall + + +$bootstrapcss + +$jqueryjs +$bootstrapjs + +\n"; + print @header; + print < + +
          + +
          +EOF + } + unless ($FORM{action} eq "tailcmd" or $FORM{action} =~ /^cf/ or $FORM{action} eq "logtailcmd" or $FORM{action} eq "loggrepcmd") { + print "
          \n"; + if ($config{UI_CXS} or $config{UI_CSE}) { + print "
          \n"; + } + print " csf Logout\n"; + print "
          \n"; + print < +ConfigServer Firewall & Security +

          ConfigServer Security & Firewall - csf v$myv

          +
          +EOF + } + ConfigServer::DisplayUI::main(\%FORM, $script, 0, $images, $myv, $config{THIS_UI}); + unless ($FORM{action} eq "tailcmd" or $FORM{action} =~ /^cf/ or $FORM{action} eq "logtailcmd" or $FORM{action} eq "loggrepcmd") { + print < +\n"; + print @footer; + print "\n"; + print "\n"; + } + } + elsif ($application eq "cxs" and $config{UI_CXS}) { + my @data = &syscommand(__LINE__,"/usr/sbin/cxs","--version"); + chomp @data; + if ($data[0] =~ /v(.*)$/) {$myv = $1} + my %ajaxsubs = ( + "cc_body" => 1, + "cc_dbody" => 1, + "cc_restore" => 1, + "cc_report" => 1, + "cc_showreports" => 1, + "cc_ignore" => 1, + "cc_blockip" => 1, + "cc_delete" => 1, + "cc_edelete" => 1, + "tailcmd" => 1, + "tailscancmd" => 1, + ); + my %fullsubs = ( + "cc_setup" => 1, + "cc_setup1" => 1, + "cc_setup2" => 1, + "cc_setup3" => 1, + "cc_setup4" => 1, + "cc_setup5" => 1, + "cc_setup6" => 1, + "cc_delreport" => 1, + "cc_reports" => 1, + "cc_stats" => 1, + "cc_file" => 1, + ); + + $script = "/$session/"; + $images = "/$session/images/cxs"; + $config{THIS_UI} = 1; + my $bootstrapcss = ""; + my $jqueryjs = ""; + my $bootstrapjs = ""; + my $fontawesome = ""; + if ($FORM{action} eq "cc_body" or $FORM{action} eq "cc_dbody" or $FORM{action} eq "cc_showreports") { + } elsif ($ajaxsubs{$FORM{action}} or $FORM{action} eq "tailcmd" or $FORM{action} eq "tailscancmd") { + print "content-type: text/plain\n\n"; + } else { + print "Content-type: text/html\n\n"; + unless ($FORM{action} eq "RunScan" or ($FORM{action} =~ /^cc_/ and !$fullsubs{$FORM{action}} and $FORM{action} !~ /^cc_\w+bulk$/) or $FORM{action} eq "Run Scan" or $FORM{action} eq "viewq" or $FORM{action} eq "tailcmd" or $FORM{action} eq "tailscancmd") { + print < + + +ConfigServer eXploit Scanner + + +$bootstrapcss +$fontawesome + +$jqueryjs +$bootstrapjs + + + +
          + +
          +EOF + print "
          \n"; + if ($config{UI_CXS} or $config{UI_CSE}) { + print "
          \n"; + } + print " cxs Logout\n"; + print "
          \n"; + print < +ConfigServer eXploit Scanner +

          ConfigServer eXploit Scanner - cxs v$myv

          +
          +EOF + } else { + print < + + + $bootstrapcss + + $jqueryjs + $bootstrapjs + + +
          + +EOF + } + } + ConfigServer::cxsUI::displayUI(\%FORM,\%ajaxsubs,$script,"",$images,$myv, "cpsess".$session); + + unless ($ajaxsubs{$FORM{action}}) { + print < + \$("#loader").hide(); + + + +EOF + } + } + elsif ($application eq "cse" and $config{UI_CSE}) { + $script = "/$session/"; + $images = "/$session/images"; + $config{THIS_UI} = 1; + ConfigServer::cseUI::main(\%FORM, $fileinc, $script, 0, $images, $myv, $config{THIS_UI}); + } + } + elsif ($file =~ /^\/images\/(\w+\/)?(\w+\/)?(\w+\/)?([\w\-]+\.(gif|png|jpg|[\w\-]+\.js|[\w\-]+\.css|css|[\w\-]+\.woff2|woff2|[\w\-]+\.woff|woff|[\w\-]+\.tff|tff))/i) { + my $type = $2; + if ($type eq "jpg") {$type = "jpeg"} + print "HTTP/1.0 200 OK\r\n"; + if ($file =~ /^\/images\/((\w+\/)?(\w+\/)?(\w+\/)?[\w\-]+\.(gif|png|jpg))/i) { + print "Content-type: image/$type\r\n"; + } + elsif ($file =~ /^\/images\/((\w+\/)?(\w+\/)?(\w+\/)?[\w\-]+\.([\w\-]+\.css|css))/i) { + print "Content-type: text/css\r\n"; + } + elsif ($file =~ /^\/images\/((\w+\/)?(\w+\/)?(\w+\/)?[\w\-]+\.([\w\-]+\.js))/i) { + print "Content-type: text/plain\r\n"; + } + elsif ($file =~ /^\/images\/((\w+\/)?(\w+\/)?(\w+\/)?[\w\-]+\.([\w\-]+\.woff2|woff2))/i) { + print "Content-type: application/font-woff2\r\n"; + } + elsif ($file =~ /^\/images\/((\w+\/)?(\w+\/)?(\w+\/)?[\w\-]+\.([\w\-]+\.woff|woff))/i) { + print "Content-type: application/font-woff\r\n"; + } + elsif ($file =~ /^\/images\/((\w+\/)?(\w+\/)?(\w+\/)?[\w\-]+\.([\w\-]+\.tff|tff))/i) { + print "Content-type: application/octet-stream\r\n"; + } + print "\r\n"; + open (my $IMAGE, "<", "/etc/csf/ui/images/$1"); + flock ($IMAGE, LOCK_SH); + while (<$IMAGE>) {print $_} + close ($IMAGE); + } else { + &ui_403; + } + } + alarm(0); + }; + if ($@) {logfile("*UI* child: [$!] [$@]")} + $client->close(); + alarm(0); + exit; + } + $client->close(SSL_no_shutdown => 1); + } + exit; + } + return; +} +# end ui +############################################################################### +# ui_403 +sub ui_403 { + print "HTTP/1.0 403 Forbidden\r\n"; + print "Content-type: text/html\r\n"; + print "\r\n"; + print "\n\n403 Forbidden\n\n\n"; + print "

          403 Forbidden

          \n"; + print "You don't have permission to access this resource\n"; + print "<", "/body>\n\n"; + return; +} +# end ui_403 +############################################################################### +# ui_413 +sub ui_413 { + print "HTTP/1.0 413 Request Entity Too Large\r\n"; + print "Content-type: text/html\r\n"; + print "\r\n"; + print "\n\n413 Request Entity Too Large\n\n\n"; + print "

          413 Request Entity Too Large

          \n"; + print "The Request Data is too large for this server to handle"; + print "<", "/body>\n\n"; + return; +} +# end ui_413 +############################################################################### +# start lfdserver +sub lfdserver { + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + $clusterip = $childpid; + unless ($childpid) { + $childproc = "Cluster"; + my $cipher = Crypt::CBC->new( -key => $config{CLUSTER_KEY}, -cipher => 'Blowfish_PP'); + my %cmembers; + foreach my $cip (split(/\,/,$config{CLUSTER_RECVFROM})) {$cmembers{$cip} = 1} + if ($config{CLUSTER_MASTER}) {$cmembers{$config{CLUSTER_MASTER}} = 1} + + $0 = "lfd Cluster Server"; + $SIG{INT} = \&childcleanup; + $SIG{TERM} = \&childcleanup; + $SIG{HUP} = \&childcleanup; + $SIG{__DIE__} = sub {&childcleanup(@_);}; + + my $server = IO::Socket::INET->new( + LocalPort => $config{CLUSTER_PORT}, + Type => SOCK_STREAM, + ReuseAddr => 1, + Listen => $config{CLUSTER_CHILDREN}, + ) or &childcleanup(__LINE__,"*Error* cannot open server on port $config{CLUSTER_PORT}: $!"); + + while (1) { + while (my ($client, $c_addr) = $server->accept()) { + $SIG{CHLD} = 'IGNORE'; + my $pid = fork; + if ($pid == 0) { + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die}; + alarm(10); + close $server; + + my ($cport,$iaddr) = sockaddr_in($c_addr); + my $peeraddress = inet_ntoa($iaddr); + my $pip = iplookup($peeraddress); + + if ($cmembers{$peeraddress}) { + binmode $client; + $| = 1; + my $line; + my $grep; + my $tip; + while ($line !~ /END\n$/) { + my $char; + $client->read($char,1) or last; + $line .= $char; + } + $line =~ s/END\n$//; + + my $decrypted = $cipher->decrypt($line); + if ($config{DEBUG} >= 2) {logfile("debug: Cluster member $peeraddress said [$decrypted]")} + my ($command,$ip,$perm,$ports,$inout,$timeout,$message) = split(/\s/,$decrypted,7); + if ($perm eq "") {$perm = 1} + if ($ports eq "*") {$ports = ""} + if (checkip(\$ip)) {$tip = iplookup($ip)} + if ($message eq "") {$message = "Not provided - $tip"} + + if ($command eq "D") { + &ipblock($perm,"Cluster member $pip said, DENY $ip, Reason:[$message]",$ip,$ports,$inout,$timeout,1,"","LF_CLUSTER"); + } + elsif ($command eq "TD") { + &ipblock($perm,"Cluster member $pip said, TEMPDENY $ip, Reason:[$message]",$ip,$ports,$inout,$timeout,1,"","LF_CLUSTER"); + } + elsif ($command eq "A" and checkip(\$ip)) { + logfile("Cluster member $pip said, ALLOW $ip, [$message]"); + &syscommand(__LINE__,"/usr/sbin/csf","-a",$ip,"Cluster member $pip said, ALLOW $ip, Reason:[$message]"); + } + elsif ($command eq "TA") { + logfile("Cluster member $pip said, TEMPALLOW $ip, Reason:[$message]"); + &syscommand(__LINE__,"/usr/sbin/csf","-ta",$ip,$timeout,"-p",$ports,"-d",$inout,"Cluster member $pip said, TEMPALLOW $ip, Reason:[$message]"); + } + elsif ($command eq "AR" and checkip(\$ip)) { + logfile("Cluster member $pip said, REMOVE ALLOW $tip"); + &syscommand(__LINE__,"/usr/sbin/csf","-ar",$ip); + &syscommand(__LINE__,"/usr/sbin/csf","-tr",$ip); + } + elsif ($command eq "R" and checkip(\$ip)) { + logfile("Cluster member $pip said, REMOVE DENY $tip"); + &syscommand(__LINE__,"/usr/sbin/csf","-dr",$ip); + &syscommand(__LINE__,"/usr/sbin/csf","-tr",$ip); + } + elsif ($command eq "I" and checkip(\$ip)) { + my $ignorematches; + 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) { + $ignorematches = 1; + last; + } + } + sysopen (my $IGNORE, "/etc/csf/csf.ignore", O_RDWR | O_CREAT); + flock ($IGNORE, LOCK_EX); + my $text = join("", <$IGNORE>); + @ignore = split(/$slurpreg/,$text); + chomp @ignore; + unless ($ignorematches) { + print $IGNORE "$ip # Cluster member $pip said, IGNORE $ip, Reason:[$message] - ".localtime(time)."\n"; + logfile("Cluster member $pip said, IGNORE $ip, [$message]"); + logfile("Cluster - lfd restarting..."); + open (my $LFDOUT, ">", "/var/lib/csf/lfd.restart"); + close ($LFDOUT); + } else { + logfile("Cluster member $pip said, IGNORE $ip, [$message], however it is already being ignored"); + } + close ($IGNORE); + } + elsif ($command eq "IR" and checkip(\$ip)) { + my $hit; + sysopen (my $IGNORE, "/etc/csf/csf.ignore", O_RDWR | O_CREAT); + flock ($IGNORE, LOCK_EX); + my $text = join("", <$IGNORE>); + my @ignore = split(/$slurpreg/,$text); + chomp @ignore; + seek ($IGNORE, 0, 0); + truncate ($IGNORE, 0); + foreach my $line (@ignore) { + $line =~ s/$cleanreg//g; + my ($ipd,$commentd) = split (/\s/,$line,2); + checkip(\$ipd); + if ($ipd eq $ip) { + $hit = 1; + next; + } else { + print $IGNORE $line."\n"; + } + } + close ($IGNORE); + if ($hit) { + logfile("Cluster member $pip said, REMOVE IGNORE $tip"); + logfile("Cluster - lfd restarting..."); + open (my $LFDOUT, ">", "/var/lib/csf/lfd.restart"); + close ($LFDOUT); + } else { + logfile("Cluster member $pip said, REMOVE IGNORE $tip, however it is not in csf.ignore"); + } + } + elsif ($command eq "PING") { + logfile("Cluster member $pip said PING!"); + } + elsif ($command eq "G") { + logfile("Cluster member $pip said GREP $tip"); + my @output = &syscommand(__LINE__,"/usr/sbin/csf","-g",$ip); + $grep = join("",@output); + } + elsif ($command eq "C") { + my (undef,$name,$value) = split(/\s/,$decrypted,3); + if ($config{CLUSTER_MASTER} and ($config{CLUSTER_MASTER} eq $peeraddress)) { + $value =~ s/\"|\=//g; + $value =~ s/(^\s*)|(\s*$)//g; + if ($config{CLUSTER_CONFIG}) { + logfile("Cluster member $pip said set [$name = \"$value\"]"); + &updateconfig($name,$value); + } else { + logfile("Cluster member $pip said set [$name = \"$value\"], however CLUSTER_CONFIG disabled"); + } + } else { + logfile("*Cluster* member $pip said set [$name = \"$value\"], however it is not the CLUSTER_MASTER"); + } + } + elsif ($command eq "FILE") { + my (undef,$filename) = split(/\s/,$decrypted); + my ($file, $filedir) = fileparse($filename); + if ($config{CLUSTER_MASTER} and ($config{CLUSTER_MASTER} eq $peeraddress)) { + if ($config{CLUSTER_CONFIG}) { + my (undef,$content) = split(/\n/,$decrypted,2); + logfile("Cluster member $pip said store file [$file]"); + open (my $FH, ">", "/etc/csf/$file"); + flock ($FH, LOCK_EX); + binmode ($FH); + print $FH $content; + close ($FH); + } else { + logfile("*Cluster* member $pip said store file [$file], however CLUSTER_CONFIG disabled"); + } + } else { + logfile("*Cluster* member $pip said store file [$file], however it is not the CLUSTER_MASTER"); + } + } + elsif ($command eq "RESTART") { + if ($config{CLUSTER_MASTER} and ($config{CLUSTER_MASTER} eq $peeraddress)) { + if ($config{CLUSTER_CONFIG}) { + logfile("Cluster member $pip said restart csf and lfd"); + logfile("Cluster - csf restarting..."); + &syscommand(__LINE__,"/usr/sbin/csf","-sf"); + logfile("Cluster - lfd restarting..."); + open (my $LFDOUT, ">", "/var/lib/csf/lfd.restart"); + close ($LFDOUT); + } else { + logfile("*Cluster* member $pip said restart csf and lfd, however CLUSTER_CONFIG disabled"); + } + } else { + logfile("*Cluster* member $pip said restart csf and lfd, however it is not the CLUSTER_MASTER"); + } + } + else { + logfile("*WARNING* Cluster member $pip talking nonsense"); + } + + if ($command eq "PING") { + print $client "PONG!\n"; + } + elsif ($command eq "G") { + print $client "$grep\n"; + } + else { + print $client "Received\n"; + } + } else { + logfile("*WARNING* $pip attempted to connect to the Cluster but not a member!"); + } + alarm(0); + }; + alarm(0); + shutdown ($client,2); + $client->close(); + exit; + } + $client->close(); + } + } + } + return; +} +# end lfdserver +############################################################################### +# start lfdclient +sub lfdclient { + my $perm = shift; + my $message = shift; + my $ip = shift; + my $port = shift; + my $inout = shift; + my $timeout = shift; + if ($port eq "") {$port = "*"} + + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","lfdclient",$timer)} + $0 = "lfd - Cluster client"; + + my $cipher = Crypt::CBC->new( -key => $config{CLUSTER_KEY}, -cipher => 'Blowfish_PP'); + my $text; + if ($perm) { + $text = "D $ip $perm $port $inout $timeout $message"; + } else { + $text = "TD $ip $perm $port $inout $timeout $message"; + } + my $encrypted = $cipher->encrypt($text)."END\n"; + + foreach my $cip (split(/\,/,$config{CLUSTER_SENDTO})) { + if ($ips{$cip} or $ipscidr->find($cip) or $ipscidr6->find($cip) or ($cip eq $config{CLUSTER_NAT})) {next} + my $localaddr = "0.0.0.0"; + if ($config{CLUSTER_LOCALADDR}) {$localaddr = $config{CLUSTER_LOCALADDR}} + my $tip = iplookup($cip); + my $sock; + eval {$sock = IO::Socket::INET->new(PeerAddr => $cip, PeerPort => $config{CLUSTER_PORT}, LocalAddr => $localaddr, Timeout => '10');}; + unless (defined $sock) { + logfile("Cluster: Failed to connect to $tip"); + } else { + my $status = send($sock,$encrypted,0); + unless ($status) { + logfile("Cluster: Failed for $tip - $status"); + } else { + if ($perm) { + logfile("Cluster: DENY $ip sent to $tip"); + } else { + logfile("Cluster: TEMPDENY $ip sent to $tip"); + } + } + shutdown($sock,2); + } + } + if ($config{DEBUG} >= 3) {$timer = &timer("stop","lfdclient",$timer)} + $0 = "lfd - (child) closing"; + exit; + } + return; +} +# end lfdclient +############################################################################### +# start updateconfig +sub updateconfig { + my $chname = shift; + my $chvalue = shift; + + sysopen (my $OUT, "/etc/csf/csf.conf", O_RDWR | O_CREAT); + flock ($OUT, LOCK_EX); + my @confdata = <$OUT>; + chomp @confdata; + 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 ($name eq $chname) { + print $OUT "$name = \"$chvalue\"\n"; + } else { + print $OUT "$confdata[$x]\n"; + } + } else { + print $OUT "$confdata[$x]\n"; + } + } + close ($OUT); + return; +} +# end updateconfig +############################################################################### +# start stats +sub stats { + my $line = shift; + my $type = shift; + + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","stats",$timer)} + $0 = "lfd - (child) Statistics..."; + + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die}; + alarm(15); + if ($type eq "iptables") { + my ($in,$out,$src,$dst,$text); + if ($line =~ /IN=(\S+)/) {$in = $1} + if ($line =~ /OUT=(\S+)/) {$out = $1} + if ($line =~ /SRC=(\S+)/) {$src = $1} + if ($line =~ /DST=(\S+)/) {$dst = $1} + + if ($config{ST_LOOKUP}) { + if ($in and $src) {$text = iplookup($src)} + elsif ($out and $dst) {$text = iplookup($dst)} + } + + sysopen (my $IPTABLES, "/var/lib/csf/stats/iptables_log", O_WRONLY | O_APPEND | O_CREAT); + flock ($IPTABLES, LOCK_EX); + print $IPTABLES "$text|$line\n"; + close ($IPTABLES); + + if ((stat("/var/lib/csf/stats/iptables_log"))[7] > (2048 * $config{ST_IPTABLES})) { + my $lockstr = "ST_IPTABLES"; + sysopen (my $THISLOCK, "/var/lib/csf/lock/$lockstr.lock", O_RDWR | O_CREAT) or &childcleanup("*Error* Unable to open /var/lib/csf/lock/$lockstr.lock"); + unless (flock ($THISLOCK, LOCK_EX | LOCK_NB)) { + if ($config{DEBUG} >= 1) { + &childcleanup("debug: *Lock Error* [$lockstr] still active - section skipped"); + } else { + &childcleanup; + } + } + + print $THISLOCK time; + sysopen (my $IPTABLES, "/var/lib/csf/stats/iptables_log", O_RDWR | O_CREAT); + flock ($IPTABLES, LOCK_EX); + + my @iptables = <$IPTABLES>; + chomp @iptables; + my @last = @iptables[-$config{ST_IPTABLES}..-1]; + + seek ($IPTABLES, 0, 0); + truncate ($IPTABLES, 0); + + foreach my $line (@last) { + print $IPTABLES "$line\n" + } + close ($IPTABLES); + } + + if ($config{DEBUG} >= 2) {logfile("debug: STATS added iptables [$src -> $dst] log line")} + } + alarm(0); + }; + alarm(0); + if ($@) {logfile("STATS: 15 sec. timeout performing iptables_log")} + + if ($config{DEBUG} >= 3) {$timer = &timer("stop","stats",$timer)} + $0 = "lfd - (child) closing"; + exit; + } + return; +} +# end stats +############################################################################### +# start systemstats +sub systemstats { + $SIG{CHLD} = 'IGNORE'; + unless (defined ($childpid = fork)) { + &cleanup(__LINE__,"*Error* cannot fork: $!"); + } + $forks{$childpid} = 1; + unless ($childpid) { + my $timer = time; + if ($config{DEBUG} >= 3) {$timer = &timer("start","systemstats",$timer)} + $0 = "lfd - (child) System Statistics..."; + + my $lockstr = "ST_SYSTEM"; + sysopen (my $THISLOCK, "/var/lib/csf/lock/$lockstr.lock", O_RDWR | O_CREAT) or &childcleanup("*Error* Unable to open /var/lib/csf/lock/$lockstr.lock"); + flock ($THISLOCK, LOCK_EX | LOCK_NB) or &childcleanup("*Lock Error* [$lockstr] still active - section skipped"); + print $THISLOCK time; + + local $SIG{__DIE__} = undef; + + my $time = time; + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time); + my $cputotal; + my $cpuidle; + my $cpuiowait; + my $memtotal; + my $memfree; + my $memswaptotal; + my $memswapfree; + my $netin; + my $netout; + my $diskread; + my $diskwrite; + my $mailin; + my $mailout; + my $cputemp; + my $mysqlin; + my $mysqlout; + my $mysqlq; + my $mysqlsq; + my $mysqlcn; + my $mysqlth; + my $apachecpu; + my $apacheacc; + my $apachebwork; + my $apacheiwork; + my $diskw; + my $memcached; + + open (my $STAT, "<", "/proc/stat"); + flock ($STAT, LOCK_SH); + my $line = <$STAT>; + close ($STAT); + chomp $line; + my @cpu = split(/\s+/,$line); + shift @cpu; + foreach (@cpu) {$cputotal += $_} + $cpuidle = $cpu[3]; + $cpuiowait = $cpu[4]; + + open (my $MEMINFO, "<", "/proc/meminfo"); + flock ($MEMINFO, LOCK_SH); + my @memdata = <$MEMINFO>; + close ($MEMINFO); + chomp @memdata; + foreach my $line (@memdata) { + if ($line =~ /^MemTotal:\s+(\d+)\s+/) {$memtotal = $1} + if ($line =~ /^MemFree:\s+(\d+)\s+/) {$memfree = $1} + if ($line =~ /^SwapTotal:\s+(\d+)\s+/) {$memswaptotal = $1} + if ($line =~ /^SwapFree:\s+(\d+)\s+/) {$memswapfree = $1} + if ($line =~ /^Cached:\s+(\d+)\s+/) {$memcached = $1} + } + + open (my $LOADAVG, "<", "/proc/loadavg"); + flock ($LOADAVG, LOCK_SH); + my $loadavg = <$LOADAVG>; + close ($LOADAVG); + chomp $loadavg; + my @load = split(/\s+/,$loadavg); + + opendir (DIR, "/sys/class/net"); + while (my $dir = readdir(DIR)) { + if ($dir eq "." or $dir eq ".." or $dir eq "lo") {next} + open (my $IN, "<", "/sys/class/net/$dir/operstate"); + flock ($IN, LOCK_SH); + my $state = <$IN>; + close ($IN); + chomp $state; + if ($state ne "down") { + open (my $RX_BYTES, "<", "/sys/class/net/$dir/statistics/rx_bytes"); + flock ($RX_BYTES, LOCK_SH); + my $datain = <$RX_BYTES>; + close ($RX_BYTES); + chomp $datain; + $netin += $datain; + + open (my $TX_BYTES, "<", "/sys/class/net/$dir/statistics/tx_bytes"); + flock ($TX_BYTES, LOCK_SH); + my $dataout = <$TX_BYTES>; + close ($TX_BYTES); + chomp $dataout; + $netout += $dataout; + } + } + closedir (DIR); + + if (-e "/proc/diskstats") { + open (my $IN, "<", "/proc/diskstats"); + flock ($IN, LOCK_SH); + my @diskdata = <$IN>; + close ($IN); + chomp @diskdata; + foreach my $line (@diskdata) { + my @item = split(/\s+/,$line); + if ($item[3] =~ /^[[:alpha:]]+$/) { + $diskread += $item[4]; + $diskwrite += $item[8]; + } + } + if ($diskread < 1) { + foreach my $line (@diskdata) { + my @item = split(/\s+/,$line); + if ($item[3] =~ /^[[:alpha:]]+\d+$/) { + $diskread += $item[4]; + $diskwrite += $item[8]; + } + } + } + } + + my $dotemp = 0; + if (-e "/sys/devices/platform/coretemp.0/temp3_input") {$dotemp = 3} + if (-e "/sys/devices/platform/coretemp.0/temp2_input") {$dotemp = 2} + if (-e "/sys/devices/platform/coretemp.0/temp1_input") {$dotemp = 1} + if ($dotemp) { + opendir (DIR, "/sys/devices/platform"); + while (my $dir = readdir(DIR)) { + unless ($dir =~ /^coretemp/) {next} + open (my $IN, "<", "/sys/devices/platform/$dir/temp".$dotemp."_input"); + flock ($IN, LOCK_SH); + my $temp = <$IN>; + close ($IN); + chomp $temp; + if ($temp > $cputemp) {$cputemp = $temp} + } + closedir (DIR); + $cputemp = sprintf("%.2f",$cputemp/1000) + } + + sysopen (my $EMAIL, "/var/lib/csf/stats/email", O_RDWR | O_CREAT); + flock ($EMAIL, LOCK_EX); + my $stats = <$EMAIL>; + chomp $stats; + ($mailout,$mailin) = split(/\:/,$stats); + seek ($EMAIL, 0, 0); + truncate ($EMAIL, 0); + print $EMAIL "0:0"; + close ($EMAIL); + + if ($config{ST_MYSQL}) { + eval('use DBI;'); ##no critic + if ($@) { + sysopen (my $TEMPCONF, "/var/lib/csf/csf.tempconf", O_WRONLY | O_APPEND | O_CREAT) or &childcleanup(__LINE__,"*Error* Cannot append out file: $!"); + flock ($TEMPCONF, LOCK_EX); + print $TEMPCONF "ST_MYSQL = \"0\"\n"; + close ($TEMPCONF); + logfile("STATS: DBI Perl Module missing - ST_MYSQL has been temporarily disabled. You should disable ST_MYSQL and restart lfd if you do not use this feature"); + } else { + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die}; + alarm(15); + my $dbuser = $config{ST_MYSQL_USER}; + my $dbpass = $config{ST_MYSQL_PASS}; + my $dbhost = $config{ST_MYSQL_HOST}; + if ($dbpass eq "" and $dbuser eq "root") { + open (my $DBS, "<", "/root/.my.cnf"); + flock ($DBS, LOCK_SH); + while (<$DBS>) { + chomp; + if (/^pass(word)?=(\S+)/) { + $dbpass = $2; + $dbpass =~ s/^\"|\"$//g; + } + if (/^host=(\S+)/) { + $dbhost = $1; + $dbhost =~ s/^\"|\"$//g; + } + } + close ($DBS); + } + my $status; + my $dbh = DBI->connect("DBI:mysql:hostname=".$dbhost,$dbuser,$dbpass,{PrintError=>0}) or $status = $DBI::errstr; + if ($status) { + logfile("STATS: Unable to connect to MySQL: [$DBI::errstr] - You should disable ST_MYSQL and restart lfd if you do not use this feature"); + } else { + my $sth = $dbh->prepare('SHOW /*!50002 GLOBAL */ STATUS'); + $sth->execute(); + while(my ($key, $val) = $sth->fetchrow_array()) { + if ($key eq "Bytes_received") {$mysqlin = $val} + if ($key eq "Bytes_sent") {$mysqlout = $val} + if ($key eq "Queries") {$mysqlq = $val} + if ($key eq "Slow_queries") {$mysqlsq = $val} + if ($key eq "Connections") {$mysqlcn = $val} + if ($key eq "Threads_connected") {$mysqlth = $val} + } + } + alarm(0); + }; + alarm(0); + if ($@) {logfile("STATS: 15 sec. timeout performing ST_MYSQL")} + } + } + + if ($config{ST_APACHE}) { + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die}; + alarm(15); + my $url = $config{PT_APACHESTATUS}."?auto"; + my ($status, $apache) = $urlget->urlget($url); + if ($status) { + logfile("STATS: Unable to retrieve Apache Server Status [$url] - $apache"); + } else { + foreach my $line (split(/\n/,$apache)) { + my ($item,$val) = split(/:\s*/,$line); + if ($item eq "CPULoad") {$apachecpu = $val} + if ($item eq "Total Accesses") {$apacheacc = $val} + if ($item eq "BusyWorkers") {$apachebwork = $val} + if ($item eq "IdleWorkers") {$apacheiwork = $val} + } + } + alarm(0); + }; + alarm(0); + if ($@) {logfile("STATS: 15 sec. timeout performing ST_APACHE")} + } + + if ($config{ST_DISKW}) { + my $skip = 0; + if (-e "/var/lib/csf/csf.tempdisk") { + open (my $ST_DISKW, "<", "/var/lib/csf/csf.tempdisk"); + flock ($ST_DISKW, LOCK_SH); + my $line = <$ST_DISKW>; + chomp $line; + close ($ST_DISKW); + my ($time,$rate) = split (/\:/,$line); + if ($config{ST_DISKW_FREQ} < 1) {$config{ST_DISKW_FREQ} = 1} + if (time - $time < (60 * $config{ST_DISKW_FREQ})) { + $skip = 1; + $diskw = $rate; + } + } + unless ($skip) { + eval { + local $SIG{__DIE__} = undef; + local $SIG{'ALRM'} = sub {die}; + alarm(15); + my @dddata = &syscommand(__LINE__,"$config{DD} $config{ST_DISKW_DD}"); + chomp @dddata; + foreach my $line (@dddata) { + if ($line =~ / (\d+(\.\d*)?) MB\/s$/) { + $diskw = $1; + last; + } + if ($line =~ / (\d+(\.\d*)?) GB\/s$/) { + $diskw = $1 * 1024; + last; + } + } + alarm(0); + }; + alarm(0); + if ($@) { + $diskw = 0; + logfile("STATS: 15 sec. timeout performing ST_DISKW"); + } + sysopen (my $ST_DISKW, "/var/lib/csf/csf.tempdisk", O_WRONLY | O_CREAT); + flock ($ST_DISKW, LOCK_EX); + print $ST_DISKW time.":$diskw\n"; + close ($ST_DISKW); + } + } + + sysopen (my $SYSSTAT,"/var/lib/csf/stats/system", O_WRONLY | O_APPEND | O_CREAT); + flock ($SYSSTAT, LOCK_EX); + print $SYSSTAT "$time,$cputotal,$cpuidle,$cpuiowait,$memtotal,$memfree,$memswaptotal,$memswapfree,$load[0],$load[1],$load[2],$netin,$netout,$diskread,$diskwrite,$mailin,$mailout,$cputemp,$mysqlin,$mysqlout,$mysqlq,$mysqlsq,$mysqlcn,$mysqlth,$apachecpu,$apacheacc,$apachebwork,$apacheiwork,$diskw,$memcached\n"; + close ($SYSSTAT); + + close ($THISLOCK ); + + if ($config{DEBUG} >= 3) {$timer = &timer("stop","systemstats",$timer)} + $0 = "lfd - (child) closing"; + exit; + } + return; +} +# end systemstats +############################################################################### +# start allowip +sub allowip { + my $ipmatch = shift; + + 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); + if ($ipd eq $ipmatch) { + return 1; + } + elsif ($ipd =~ /(\S+\/\d+)/) { + my $cidrhit = $1; + if (checkip(\$cidrhit)) { + my $dcidr = Net::CIDR::Lite->new; + eval {local $SIG{__DIE__} = undef; $dcidr->add($cidrhit)}; + if ($@) {logfile("Invalid CIDR in csf.allow: $cidrhit")} + if ($dcidr->find($ipmatch)) { + return 1; + } + } + } + } + + if ($config{GLOBAL_ALLOW} and -e "/var/lib/csf/csf.gallow") { + open (my $IN, "<", "/var/lib/csf/csf.gallow"); + flock ($IN, LOCK_SH); + my @allow = <$IN>; + close ($IN); + chomp @allow; + foreach my $line (@allow) { + if ($line eq "") {next} + if ($line =~ /^\s*\#/) {next} + my ($ipd,$commentd) = split (/\s/,$line,2); + if ($ipd eq $ipmatch) { + return 2; + } + elsif ($ipd =~ /(\S+\/\d+)/) { + my $cidrhit = $1; + if (checkip(\$cidrhit)) { + my $dcidr = Net::CIDR::Lite->new; + eval {local $SIG{__DIE__} = undef; $dcidr->add($cidrhit)}; + if ($@) {logfile("Invalid CIDR in csf.gallow: $cidrhit")} + if ($dcidr->find($ipmatch)) { + return 2; + } + } + } + } + } + return; +} +# end allowip +############################################################################### +# start testregex +sub testregex { + my $match = shift; + eval { + local $SIG{__DIE__} = undef; + my $test =~ /$match/; + }; + if ($@) {return 0} + return 1; +} +# end testregex +############################################################################### +# start faststart +sub faststart { + my $text = shift; + $faststart = 0; + my $verbose = 1; + if ($text =~ /^Blocklist \[CXS_/) {$verbose = 0} + if (@faststart4) { + if ($config{DEBUG} >= 1 and $verbose) {logfile("FASTSTART loading $text (IPv4)")}; + my $status; + if ($config{VPS}) {$status = &fastvps(scalar @faststart4)} + if ($status) { + logfile($status); + } else { + &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]} + logfile("*Error* FASTSTART: ($text IPv4) [$cmd] [$results[0]]"); + } + &iptableslock("unlock",1); + } + } + if (@faststart4nat) { + if ($config{DEBUG} >= 1 and $verbose) {logfile("FASTSTART loading $text (IPv4 nat)")}; + my $status; + if ($config{VPS}) {$status = &fastvps(scalar @faststart4nat)} + if ($status) { + logfile($status); + } else { + &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]} + logfile("*Error* FASTSTART: ($text IPv4nat) [$cmd] [$results[0]]"); + } + &iptableslock("unlock",1); + } + } + if (@faststart6) { + if ($config{DEBUG} >= 1 and $verbose) {logfile("FASTSTART loading $text (IPv6)")}; + my $status; + if ($config{VPS}) {$status = &fastvps(scalar @faststart6)} + if ($status) { + logfile($status); + } else { + &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]} + logfile("*Error* FASTSTART: ($text IPv6) [$cmd] [$results[0]]"); + } + &iptableslock("unlock",1); + } + } + if (@faststart6nat) { + if ($config{DEBUG} >= 1 and $verbose) {logfile("FASTSTART loading $text (IPv6 nat)")}; + my $status; + if ($config{VPS}) {$status = &fastvps(scalar @faststart6nat)} + if ($status) { + logfile($status); + } else { + &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]} + logfile("*Error* FASTSTART: ($text IPv6nat) [$cmd] [$results[0]]"); + } + &iptableslock("unlock",1); + } + } + if (@faststartipset) { + if ($config{DEBUG} >= 1 and $verbose) {logfile("FASTSTART loading $text (IPSET)")}; + 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/) { + logfile("FASTSTART: (IPSET) Error:[$results[0]]"); + } + } + undef @faststart4; + undef @faststart4nat; + undef @faststart6; + undef @faststart6nat; + undef @faststartipset; + 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; + my $family = "inet"; + if ($set =~ /_6/) {$family = "inet6"} + 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/) { + logfile("*Error* IPSET: [$results[0]]"); + } + return; +} +# end ipsetcreate +############################################################################### +# start ipsetrestore +sub ipsetrestore { + my $set = shift; + my $verbose = 1; + if ($set =~ /^new_(6_)?CXS_/) {$verbose = 0} + my $family = "inet"; + if ($set =~ /_6/) {$family = "inet6"} + if ($verbose) {logfile("IPSET: loading set $set with ".scalar(@ipset)." entries")} + + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, $config{IPSET},"restore"); + print $childin "create -exist $set hash:net family $family hashsize $config{LF_IPSET_HASHSIZE} maxelem $config{LF_IPSET_MAXELEM}\n".join("\n",@ipset)."\n"; + close $childin; + my @results = <$childout>; + waitpid ($cmdpid, 0); + chomp @results; + if ($results[0] =~ /^ipset/) { + logfile("*Error* [$set] IPSET: [$results[0]]"); + } + undef @ipset; + return; +} +# end ipsetrestore +############################################################################### +# start ipsetswap +sub ipsetswap { + my $from = shift; + my $to = shift; + my $verbose = 1; + if ($from =~ /^new_(6_)?CXS_/) {$verbose = 0} + if ($verbose) {logfile("IPSET: switching set $from to $to")} + + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, $config{IPSET},"swap",$from,$to); + close $childin; + my @results = <$childout>; + waitpid ($cmdpid, 0); + chomp @results; + if ($results[0] =~ /^ipset/) { + logfile("*Error* IPSET: [$results[0]]"); + } + + $cmdpid = open3($childin, $childout, $childout, $config{IPSET},"flush",$from); + close $childin; + @results = <$childout>; + waitpid ($cmdpid, 0); + chomp @results; + if ($results[0] =~ /^ipset/) { + logfile("*Error* IPSET: [$results[0]]"); + } + + $cmdpid = open3($childin, $childout, $childout, $config{IPSET},"destroy",$from); + close $childin; + @results = <$childout>; + waitpid ($cmdpid, 0); + chomp @results; + if ($results[0] =~ /^ipset/) { + logfile("*Error* [$from] [$to] IPSET: [$results[0]]"); + } + return; +} +# end ipsetswap +############################################################################### +# start ipsetadd +sub ipsetadd { + my $set = shift; + my $ip = shift; + if ($set =~ /GDENY/ or $set =~ /GALLOW/) { + if ($set =~ /^(\w+)(IN|OUT)$/) {$set = $1} + } else { + if ($set =~ /^chain(_6)?_NEW(\w+)$/) {$set = "chain".$1."_".$2} + if ($set =~ /^bl(_6)?_NEW(\w+)$/) {$set = "bl".$1."_".$2} + if ($set =~ /^(\w+)(IN|OUT)$/) {$set = $1} + } + if ($set eq "" or $ip eq "") {return} + if ($faststart) { + push @faststartipset, "add -exist $set $ip"; + return; + } + if ($config{DEBUG} >= 1) {logfile("debug: IPSET adding [$ip] to set [$set]")} + 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/) { + logfile("*Error* [$set] IPSET: [$results[0]]"); + } + return; +} +# end ipsetadd +############################################################################### +# start ipsetdel +sub ipsetdel { + my $set = shift; + my $ip = shift; + if ($set =~ /^chain(_6)?_NEW(\w+)$/) {$set = "chain".$1."_".$2} + if ($set =~ /^bl(_6)?_NEW(\w+)$/) {$set = "bl".$1."_".$2} + if ($set =~ /^(\w+)(IN|OUT)$/) {$set = $1} + if ($set eq "" or $ip eq "") {return} + if ($config{DEBUG} >= 1) {logfile("debug: IPSET deleting [$ip] from set [$set]")} + 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/) { + logfile("*Error* [$set] IPSET: [$results[0]]"); + } + return; +} +# end ipsetadd +############################################################################### +# start ipsetflush +sub ipsetflush { + my $set = shift; + logfile("IPSET: flushing set $set"); + + my ($childin, $childout); + my $cmdpid = open3($childin, $childout, $childout, $config{IPSET},"flush",$set); + close $childin; + my @results = <$childout>; + waitpid ($cmdpid, 0); + chomp @results; + if ($results[0] =~ /^ipset/) { + logfile("*Error* IPSET: [$results[0]]"); + } + return; +} +# end ipsetflush +############################################################################### diff --git a/src/redux/lfd.service b/src/redux/lfd.service new file mode 100644 index 000000000..07b21df58 --- /dev/null +++ b/src/redux/lfd.service @@ -0,0 +1,12 @@ +[Unit] +Description=ConfigServer Firewall & Security - lfd +After=network.target csf.service + +[Service] +LimitNOFILE=4096 +ExecStart=/usr/sbin/lfd +Type=forking +PIDFile=/run/lfd.pid + +[Install] +WantedBy=multi-user.target diff --git a/src/redux/lfd.sh b/src/redux/lfd.sh new file mode 100644 index 000000000..14f94bb32 --- /dev/null +++ b/src/redux/lfd.sh @@ -0,0 +1,102 @@ +#!/bin/bash +# +############################################################################### +# lfd +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# +# chkconfig: 2345 20 75 +# description: Login Failure Daemon +# +### BEGIN INIT INFO +# Provides: lfd +# Required-Start: $network $syslog +# Required-Stop: $network $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: csf Login Failure Daemon (lfd) +# Description: csf Login Failure Daemon (lfd) init script +### END INIT INFO +# + +[ -f /usr/sbin/lfd ] || exit 0 + +# Source function library. +if [ -f /etc/init.d/functions ]; then + . /etc/init.d/functions +fi + +RETVAL=0 +PID=/var/run/lfd.pid +DAEMON=/usr/sbin/lfd +PIDOF=pidof + +if [ -f /etc/SuSE-release ]; then + . /etc/rc.status + rc_reset +fi + +# See how we were called. +case "$1" in + start) + echo -n "Starting lfd:" + ulimit -n 4096 + $DAEMON + 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 + ;; + stop) + echo -n "Stopping lfd:" + if [ -f /etc/SuSE-release ]; then + killproc lfd + rc_status -v + elif [ -f /etc/debian_version ] || [ -f /etc/lsb-release ] || [ -f /etc/gentoo-release ]; then + lfd=`cat /var/run/lfd.pid 2>/dev/null` + if [ -n "${lfd}" ] && [ -e /proc/"${lfd}" ]; then + kill "$lfd"; + fi + echo " Done" + else + killproc lfd + success + echo + fi + ;; + status) + echo -n "Status of lfd:" + if [ -f /etc/SuSE-release ]; then + checkproc lfd + rc_status -v + RETVAL=$? + elif [ -f /etc/debian_version ] || [ -f /etc/lsb-release ] || [ -f /etc/gentoo-release ]; then + lfd=`cat /var/run/lfd.pid 2>/dev/null` + if [ -n "${lfd}" ] && [ -e /proc/"${lfd}" ]; then + echo " Running" + else + echo " Stopped" + RETVAL=3 + fi + else + status lfd + RETVAL=$? + echo + fi + ;; + restart|force-reload) + $0 stop + $0 start + ;; + *) + echo "Usage: /etc/init.d/lfd start|stop|restart|force-reload|status" + exit 1 +esac + +exit $RETVAL diff --git a/src/redux/lfdcron.directadmin.sh b/src/redux/lfdcron.directadmin.sh new file mode 100644 index 000000000..6e7553e6a --- /dev/null +++ b/src/redux/lfdcron.directadmin.sh @@ -0,0 +1,2 @@ +SHELL=/bin/sh +0 0 * * * root /usr/sbin/csf --lfd restart > /dev/null 2>&1 diff --git a/src/redux/lfdcron.sh b/src/redux/lfdcron.sh new file mode 100644 index 000000000..6e7553e6a --- /dev/null +++ b/src/redux/lfdcron.sh @@ -0,0 +1,2 @@ +SHELL=/bin/sh +0 0 * * * root /usr/sbin/csf --lfd restart > /dev/null 2>&1 diff --git a/src/redux/license.txt b/src/redux/license.txt new file mode 100644 index 000000000..e1f22c2b1 --- /dev/null +++ b/src/redux/license.txt @@ -0,0 +1,234 @@ +Way to the Web Product License + +LICENCE TERMS AND CONDITIONS + +1. LICENCE + + 1.1 Way to the Web Limited of 73, Donaldson Way, Woodley, + Reading, Berkshire, RG5 4XL ("Way to the Web") hereby grants + you a non-exclusive, non-transferable licence to download and + use (the "Product") and the accompanying documentation (the + "Documentation") on the following terms. + + 1.2 The copyright and all other rights in the Product and the + Documentation remain with Way to the Web. + +2. ACCEPTANCE + + You are deemed to have accepted the terms and conditions of this + Licence by downloading the Product. + +3. SCOPE OF LICENCE + + 3.1 You shall not: + + 3.1.1 modify, adapt, merge, translate, decompile, + disassemble, or reverse engineer the Product, except as + permitted by law; or + + 3.1.2 sell, assign, rent, sub-license, loan, mortgage, + charge or otherwise deal in any way in the Product or + Documentation or any interest in them except as expressly + provided in this Licence. + +4. DURATION OF LICENCE + + 4.1 This Licence shall commence on the date hereof and, subject + to other terms of this Licence, shall continue thereafter for as + long as you continue to use the Product. + + 4.2 This Licence shall terminate automatically if you fail to + abide by any of its terms. + + 4.3 Upon termination of this Licence you shall destroy the + Product and the Documentation and shall erase all copies of the + Product under your control and stored on any medium. + +5. WARRANTIES AND REMEDIES + + 5.1 Way to the Web warrants that for a period of 90 days from the + date that the Product is downloaded, it will provide the facilities + and functions set out in the Documentation when properly used and + further, that the Documentation will provide adequate instruction to + enable you to make proper use of such facilities and functions. + + 5.2 The said warranty shall be subject to you complying with + your obligations hereunder and to there having been made no + alterations to the Product by any person other than Way to the Web. + When notifying a defect or error you shall (so far as you are able) + provide Way to the Web with a documented example of such defect or + error. + + 5. 3 Way to the Web shall have no liability or obligations under + the said warranty other than to remedy breaches thereof by the + provision of materials and services within a reasonable time and + without charge to you. If Way to the Web shall fail to comply with + such obligations its liability for such failure shall be limited as + specified in Clause 6. The foregoing states the entire liability of + Way to the Web, whether in contract or tort, for defects and errors + in the Products and the Documentation. + + 5.4 You acknowledge that the Products have not been prepared to + meet your individual requirements and that it is therefore your + responsibility to ensure that the facilities and functions described + in the Documentation meet your requirements. Way to the Web shall not + be liable for any failure of the Products to provide any facility or + function not specified in the Documentation + + 5.5 Way to the Web does not warrant that the operation of the + Products will be uninterrupted or error free or that all errors will + be remedied. + + 5.6 Except as expressly provided in this Licence, no warranty, + condition, undertaking or term, express or implied, statutory or + otherwise, as to the condition, quality, performance or fitness for + purpose of the Products or the Documentation is given or assumed by + Way to the Web and all such warranties, conditions, undertakings and + terms are hereby excluded to the fullest extent permitted by law. + +6. LIABILITY + + 6.1 Way to the Web will indemnify you and keep you fully and + effectively indemnified against any loss of or damage to any property + or injury to or death of any person caused by any negligent act or + omission or wilful misconduct of Way to the Web, its employees, + agents or sub-contractors or by any breach of its contractual + obligations arising out of this Licence. + + 6.2 Except in respect of injury to or death of any person caused + by negligence (for which no limit applies) Way to the Web's + liability to you under sub-clause 6.1 above in respect of each event + or series of connected events shall not exceed one and a half times + the price you paid to licence the Product. + + 6.3 Notwithstanding anything else contained in this Licence, Way + to the Web shall not be liable to you for loss of profits or + contracts or indirect or consequential loss or damage whether arising + from negligence, breach of contract or howsoever caused + + 6.4 Way to the Web shall not be liable to you for any loss + arising out of your failure to keep full and up-to-date security + copies of the computer programs and data you use. + +7. CONFIDENTIAL INFORMATION + + 7.1 You undertake to treat as confidential and keep secret all + information contained or embodied in the Products and the + Documentation which, by its nature has the necessary quality of + confidence about it ("Confidential Information"), provided that this + clause shall not extend to any information which is already public + knowledge or becomes so at a future date (otherwise than as a result + of a breach of this clause). + + 7.2 You shall not without the prior written consent of Way to the + Web divulge any part of the Confidential Information to any person + except to: + + 7.2.1 your own employees and then only to those employees + who need to know the same; + + 7.2.2 your auditors and any other persons or bodies having + a right duty or obligation to know your business and then + only in pursuance of such right duty or obligation; + + 7.2.3 any person who is from time to time appointed by you + to maintain your network, website or the equipment upon + which the Product is being used (in accordance with the terms + of the Licence) and then only to the extent necessary to + enable such person properly to maintain such network, website + or equipment. + + 7.3 You undertake to ensure that the persons and bodies mentioned + in paragraphs 7.2.1, 7.2.2 and 7.2.3 are made aware prior to the + disclosure of any part of the Confidential Information that the same + is confidential and that they owe a duty of confidence to Way to the + Web. You shall indemnify Way to the Web against any loss or damage + which Way to the Web may sustain or incur as a result of your + failing to comply with such undertaking + + 7.4 You shall promptly notify Way to the Web if you become aware + of any breach of confidence by any person to whom you divulge all or + any part of the Confidential Information and shall give Way to the + Web all reasonable assistance in connection with any proceedings + which Way to the Web may institute against such person for breach of + confidence. + + 7.5 The foregoing obligations as to confidentiality shall remain + in full force and effect notwithstanding any termination of this + Licence. + +8. INDEMNITIES + + 8.1 Way to the Web shall indemnify you against any claim that the + normal use or possession of the Products and/or Documentation + infringes the intellectual property rights of any third party + provided that Way to the Web is given immediate and complete control + of such claim, that you do not prejudice Way to the Web's defence + of such claim, that you give Way to the Web all reasonable + assistance with such claim and that the claim does not arise as a + result of the use of the Products and/or Documentation in combination + with any equipment or programs not supplied or approved by Way to + the Web. Way to the Web shall have the right to replace or change all + or any part of the Products and/or Documentation in order to avoid + any infringement. The foregoing states the entire liability of Way to + the Web to you in respect of the infringement of the intellectual + property rights of any third party + + 8.2 Except to the extent caused by Way to the Web's breach of + its obligations hereunder, or its negligent or wilful misconduct in + connection with this Licence, and without limiting Way to the Web's + obligations in sub-clause 8.1 above, you shall indemnify and hold + Way to the Web harmless from any and all liability, loss and damage + Way to the Web may suffer as a result of claims demands or judgments + by any third party arising out of your use or operation of the + Products, the Documentation and related output. You shall, at your + expense, defend any such action, suit or claim against Way to the + Web. + +9. SUPPORT + + Way to the Web's technical support staff will, between the hours of + 9.00 and 17.30 UK time Monday to Friday inclusive (except on bank and + public holidays), endeavour to answer on-line or by email any queries + you may have about the Product. For support please either use the + on-line support desk or the on-line support forum given on our + Website or in the Documentation. Any Product updates that may be + made available by Way to the Web from time to time will be supplied + at Way to the Web's then prevailing charges and subject to Way to the + Web's then prevailing terms and conditions. Way to the Web does not + guarantee backward compatibility with previous versions of the + Product as it retains the right to add, remove or modify any feature + or function in previous versions, at its sole discretion. + +10. OTHER SERVICES + + Way to the Web may also provide you with, at its option and subject + to its then prevailing charges and terms and conditions, other + services in relation to the Product, such as installation and + consultancy services. Please contact Way to the Web at the number + given on our Website or in the Documentation for more information + about such services. + +11. CONSUMERS + + If you deal as a consumer as defined in the Unfair Contract Terms Act + 1977, your statutory rights remain unaffected. + +12. PERSONAL INFORMATION CONTROL + + You agree to comply with all applicable laws, regulations, rulings and + orders of the EU, US and other countries (including but not limited to + the EU's GDPR) in which you have operations relating to the protection, + use, and distribution of personal information of your users or + visitors on any devices which have the Program installed or stored. + Further, you shall indemnify Way to the Web for any and all claims + resulting from your violation of any such laws, regulations, rulings, + or orders. + +13. LAW + + This Licence constitutes the entire agreement between you and Way to + the Web relating to the Product and the Documentation and is governed + by and construed in accordance with the laws of England. The courts + of England shall have exclusive jurisdiction. + diff --git a/src/redux/litespeed.http.txt b/src/redux/litespeed.http.txt new file mode 100644 index 000000000..8e4d3ec4f --- /dev/null +++ b/src/redux/litespeed.http.txt @@ -0,0 +1,15 @@ +listener csf { + map csf * + address *:[PORT] + secure 0 +} + +# Virtualhost start - do not remove this line +virtualHost csf { + vhRoot [DIRECTORY] + allowSymbolLink 1 + enableScript 1 + restrained 1 + docRoot [DOCUMENTROOT] +} +# Virtualhost end - do not remove this line diff --git a/src/redux/litespeed.https.txt b/src/redux/litespeed.https.txt new file mode 100644 index 000000000..2f3550268 --- /dev/null +++ b/src/redux/litespeed.https.txt @@ -0,0 +1,32 @@ +listener csfSSL { + [MAPS] + address *:[SSLPORT] + secure 1 + keyFile [SSLCERTIFICATEKEYFILE] + certFile [SSLCERTIFICATEFILE] +} + +# Virtualhost start - do not remove this line +virtualHost csfssl.[SERVERNAME] { + vhRoot [DIRECTORY] + allowSymbolLink 1 + enableScript 1 + restrained 1 + docRoot [DOCUMENTROOT] + vhDomain [SERVERNAME] + vhAliases [SERVERALIAS] + vhssl { + keyFile [SSLCERTIFICATEKEYFILE] + certFile [SSLCERTIFICATEFILE] + certChain 1 + sslProtocol 24 + ciphers EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH:ECDHE-RSA-AES128-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA128:DHE-RSA-AES128-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA128:ECDHE-RSA-AES128-SHA384:ECDHE-RSA-AES128-SHA128:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA128:DHE-RSA-AES128-SHA128:DHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA384:AES128-GCM-SHA128:AES128-SHA128:AES128-SHA128:AES128-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4 + enableECDHE 1 + renegProtection 1 + sslSessionCache 1 + enableSpdy 15 + enableStapling 1 + ocspRespMaxAge 86400 + } +} +# Virtualhost end - do not remove this line diff --git a/src/redux/litespeed.main.txt b/src/redux/litespeed.main.txt new file mode 100644 index 000000000..e69de29bb diff --git a/src/redux/loadalert.txt b/src/redux/loadalert.txt new file mode 100644 index 000000000..2777b57b4 --- /dev/null +++ b/src/redux/loadalert.txt @@ -0,0 +1,55 @@ +From: root +To: root +Subject: lfd on [hostname]: High [loadavg] minute load average alert - [reportload] +MIME-Version: 1.0 +Content-Type: multipart/mixed; + boundary="------------[boundary]" + +This is a multi-part message in MIME format. +--------------[boundary] +Content-Type: text/plain; +Content-Transfer-Encoding: 7bit + +Time: [time] +1 Min Load Avg: [loadavg1] +5 Min Load Avg: [loadavg5] +15 Min Load Avg: [loadavg15] +Running/Total Processes: [totprocs] + +--------------[boundary] +Content-Type: text/plain; +Content-Transfer-Encoding: 7bit +Content-Disposition: attachment; + filename="ps.txt" + +Output from ps: +[processlist] + +--------------[boundary] +Content-Type: text/plain; +Content-Transfer-Encoding: 7bit +Content-Disposition: attachment; + filename="vmstat.txt" + +Output from vmstat: +[vmstat] + +--------------[boundary] +Content-Type: text/plain; +Content-Transfer-Encoding: 7bit +Content-Disposition: attachment; + filename="netstat.txt" + +Output from netstat: +[netstat] + +--------------[boundary] +Content-Type: text/html; + name="apachestatus.html" +Content-Transfer-Encoding: 7bit +Content-Disposition: attachment; + filename="apachestatus.html" + +[apache] + +--------------[boundary]-- diff --git a/src/redux/logalert.txt b/src/redux/logalert.txt new file mode 100644 index 000000000..38ce1015d --- /dev/null +++ b/src/redux/logalert.txt @@ -0,0 +1,5 @@ +From: root +To: root +Subject: lfd on [hostname]: Log Scanner Report for [hour], (lines:[lines]) + +[text] diff --git a/src/redux/logfloodalert.txt b/src/redux/logfloodalert.txt new file mode 100644 index 000000000..d2aa207f5 --- /dev/null +++ b/src/redux/logfloodalert.txt @@ -0,0 +1,6 @@ +From: root +To: root +Subject: lfd on [hostname]: Log file flooding + +Time: [time] +Alert: [text] diff --git a/src/redux/messenger/en.php b/src/redux/messenger/en.php new file mode 100644 index 000000000..b6ed2445f --- /dev/null +++ b/src/redux/messenger/en.php @@ -0,0 +1,15 @@ + "The firewall on this server is blocking your connection.", + "contact" => "You need to contact the server owner or hosting provider for further information.", + "blocked ip" => "Your blocked IP address is:", + "hostname" => "The hostname of this server is:", + "recaptcha title" => "You can try to unblock yourself using ReCAPTCHA:", + "recaptcha note" => "Please note: Not all unblock requests will be successful as it is dependent on how your IP address is being blocked. If the unblock fails you will need to contact the server owner or hosting provider for further information.", + "recaptcha success" => "Passed human test. Please wait a few seconds and your IP address should be unblocked and you can return to the website:", + "recaptcha failure" => "Failed to pass ReCAPTCHA test. Please try again.", + "recaptcha hostfail" => "There has been a problem verifying the hostname:", + "recaptcha error" => "There has been a problem. Please click on the reCAPTCHA box.", + "unblock submit" => "Unblock", + ); +?> diff --git a/src/redux/messenger/index.html b/src/redux/messenger/index.html new file mode 100644 index 000000000..925782e18 --- /dev/null +++ b/src/redux/messenger/index.html @@ -0,0 +1,195 @@ + + + + Unauthorized Access + + + + + +

          The firewall on this server is blocking your connection.

          +

          You need to contact the server owner or hosting provider for further information.

          +

          Your blocked IP address is: [IPADDRESS]

          +

          This server's hostname is: [HOSTNAME]

          + + diff --git a/src/redux/messenger/index.php b/src/redux/messenger/index.php new file mode 100644 index 000000000..4b2c1baa5 --- /dev/null +++ b/src/redux/messenger/index.php @@ -0,0 +1,212 @@ + + + + Unauthorized Access + + + + + + + + + +
          + +

          +

          +

          +

          +
          + + diff --git a/src/redux/messenger/index.recaptcha.html b/src/redux/messenger/index.recaptcha.html new file mode 100644 index 000000000..67f146919 --- /dev/null +++ b/src/redux/messenger/index.recaptcha.html @@ -0,0 +1,229 @@ + + + + Unauthorized Access + + + + + + +

          The firewall on this server is blocking your connection.

          +

          You need to contact the server owner or hosting provider for further information.

          +

          Your blocked IP address is: [IPADDRESS]

          +

          This server's hostname is: [HOSTNAME]

          + +
          +

          If you are a human you can unblock yourself using ReCAPTCHA:

          +

          Please note: Not all unblock requests will be successful as it is dependent on how your IP address is being blocked. If the unblock fails you will need to contact the server owner or hosting provider for further information.

          + + +
          + + +
          + + +

          + + [RECAPTCHA_SUCCESS="Passed human test. Please wait a few seconds and your IP address should be unblocked."] + [RECAPTCHA_FAILURE="Failed to pass human test. Please try again."] + [RECAPTCHA_ERROR="There has been a problem:"] +

          + + + + diff --git a/src/redux/messenger/index.recaptcha.php b/src/redux/messenger/index.recaptcha.php new file mode 100644 index 000000000..63a7ecee3 --- /dev/null +++ b/src/redux/messenger/index.recaptcha.php @@ -0,0 +1,273 @@ + + + + Unauthorized Access + + + + + + + + + +
          + +

          +

          +

          +

          + +
          +

          + +
          +
          +
          +
          +
          +
          +
          + +
          +
          +
          + + +
          + $secret,'response' => $_POST['g-recaptcha-response']); + $verify = curl_init(); + curl_setopt($verify, CURLOPT_URL, "https://www.google.com/recaptcha/api/siteverify"); + curl_setopt($verify, CURLOPT_POST, true); + curl_setopt($verify, CURLOPT_POSTFIELDS, http_build_query($data)); + curl_setopt($verify, CURLOPT_SSL_VERIFYPEER, false); + curl_setopt($verify, CURLOPT_RETURNTRANSFER, true); + $verifyResponse = curl_exec($verify); + $responseData = json_decode($verifyResponse); + if($responseData->success) { + if ($responseData->hostname == $_SERVER['SERVER_NAME']) { + $alert = 'success'; + $message = $lang["recaptcha success"] . "
          " . $_SERVER['REQUEST_URI'] . ""; + file_put_contents($unblockfile, $_SERVER['REMOTE_ADDR'].";".$_SERVER['SERVER_NAME'].";".$_SERVER['SERVER_ADDR']."\n", FILE_APPEND | LOCK_EX); + file_put_contents($logfile,$date . "*Success*, ReCaptcha (" . $_SERVER['REMOTE_ADDR'].": [".$_SERVER['SERVER_NAME']." (".$_SERVER['SERVER_ADDR'].")] requested unblock\n", FILE_APPEND | LOCK_EX); + } else { + $alert = "danger"; + $message = $lang["recaptcha hostfail"] . ' ['.$responseData->hostname.' != '.$_SERVER['SERVER_NAME'].']'; + file_put_contents($logfile,$date . "*Failed*, ReCaptcha (" . $_SERVER['REMOTE_ADDR'].": [".$_SERVER['SERVER_NAME']." (".$_SERVER['SERVER_ADDR'].")] does not appear to be hosted on this server\n", FILE_APPEND | LOCK_EX); + } + } else { + $alert = "danger"; + $message = $lang["recaptcha failure"]; + file_put_contents($logfile,$date . "*Error*, ReCaptcha (" . $_SERVER['REMOTE_ADDR'].": $responseData\n", FILE_APPEND | LOCK_EX); + } + } else { + $alert = "danger"; + $message = $lang["recaptcha error"]; + } + echo '

          ' . $message . '

          '; + } + ?> + +
          +
          + + diff --git a/src/redux/messenger/index.text b/src/redux/messenger/index.text new file mode 100644 index 000000000..5fa42b96b --- /dev/null +++ b/src/redux/messenger/index.text @@ -0,0 +1,4 @@ +The firewall on this server is blocking your connection. +You need to contact the server owner or hosting provider for further information. +Your blocked IP address is: [IPADDRESS] +This server's hostname is: [HOSTNAME] diff --git a/src/redux/migratedata.sh b/src/redux/migratedata.sh new file mode 100644 index 000000000..25a331ac9 --- /dev/null +++ b/src/redux/migratedata.sh @@ -0,0 +1,244 @@ +#!/bin/sh +############################################################################### +# Copyright 2006-2018, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### + +umask 0177 + +touch /etc/csf/csf.disable +/etc/init.d/lfd stop + +# temp data: + +cp -avf /etc/csf/csf.4.saved /var/lib/csf/ +cp -avf /etc/csf/csf.6.saved /var/lib/csf/ +cp -avf /etc/csf/csf.block.AUTOSHUN /var/lib/csf/ +cp -avf /etc/csf/csf.block.BFB /var/lib/csf/ +cp -avf /etc/csf/csf.block.BOGON /var/lib/csf/ +cp -avf /etc/csf/csf.block.CIARMY /var/lib/csf/ +cp -avf /etc/csf/csf.block.DSHIELD /var/lib/csf/ +cp -avf /etc/csf/csf.block.HONEYPOT /var/lib/csf/ +cp -avf /etc/csf/csf.block.MAXMIND /var/lib/csf/ +cp -avf /etc/csf/csf.block.OPENBL /var/lib/csf/ +cp -avf /etc/csf/csf.block.RBN /var/lib/csf/ +cp -avf /etc/csf/csf.block.SPAMDROP /var/lib/csf/ +cp -avf /etc/csf/csf.block.SPAMEDROP /var/lib/csf/ +cp -avf /etc/csf/csf.block.TOR /var/lib/csf/ +cp -avf /etc/csf/csf.ccignore /var/lib/csf/ +cp -avf /etc/csf/csf.cclookup /var/lib/csf/ +cp -avf /etc/csf/csf.div /usr/local/csf/lib/ +cp -avf /etc/csf/csf.dnscache /var/lib/csf/ +cp -avf /etc/csf/csf.dwdisable /var/lib/csf/ +cp -avf /etc/csf/csf.gallow /var/lib/csf/ +cp -avf /etc/csf/csf.gdeny /var/lib/csf/ +cp -avf /etc/csf/csf.gdyndns /var/lib/csf/ +cp -avf /etc/csf/csf.gignore /var/lib/csf/ +cp -avf /etc/csf/csf.load /var/lib/csf/ +cp -avf /etc/csf/csf.lock /var/lib/csf/ +cp -avf /etc/csf/csf.logmax /var/lib/csf/ +cp -avf /etc/csf/csf.logrun /var/lib/csf/ +cp -avf /etc/csf/csf.logtemp /var/lib/csf/ +cp -avf /etc/csf/csf.queue /var/lib/csf/ +cp -avf /etc/csf/csf.restart /var/lib/csf/ +cp -avf /etc/csf/csf.tempallow /var/lib/csf/ +cp -avf /etc/csf/csf.tempban /var/lib/csf/ +cp -avf /etc/csf/csf.tempconf /var/lib/csf/ +cp -avf /etc/csf/csf.tempdisk /var/lib/csf/ +cp -avf /etc/csf/csf.tempdyn /var/lib/csf/ +cp -avf /etc/csf/csf.tempexp /var/lib/csf/ +cp -avf /etc/csf/csf.tempexploit /var/lib/csf/ +cp -avf /etc/csf/csf.tempfiles /var/lib/csf/ +cp -avf /etc/csf/csf.tempgdyn /var/lib/csf/ +cp -avf /etc/csf/csf.tempint /var/lib/csf/ +cp -avf /etc/csf/csf.tempip /var/lib/csf/ +cp -avf /etc/csf/csf.temppids /var/lib/csf/ +cp -avf /etc/csf/csf.tempusers /var/lib/csf/ +cp -avf /etc/csf/csf.tempwatch /var/lib/csf/ +cp -avf /etc/csf/Geo/GeoIP.dat /var/lib/csf/Geo/ +cp -avf /etc/csf/Geo/GeoLiteCity.dat /var/lib/csf/Geo/ +cp -avf /etc/csf/lfd.enable /var/lib/csf/ +cp -avf /etc/csf/lfd.restart /var/lib/csf/ +cp -avf /etc/csf/lfd.start /var/lib/csf/ +cp -avf /etc/csf/lock/ /var/lib/csf/ +cp -avf /etc/csf/nocheck /var/lib/csf/ +cp -avf /etc/csf/sanity.txt /usr/local/csf/lib/ +cp -avf /etc/csf/stats/ /var/lib/csf/ +cp -avf /etc/csf/suspicious.tar /var/lib/csf/ +cp -avf /etc/csf/ui/ui.session /var/lib/csf/ui/ +cp -avf /etc/csf/webmin/ /usr/local/csf/lib/ +cp -avf /etc/csf/zone/ /var/lib/csf/ + +rm -fv /etc/csf/csf.4.saved +rm -fv /etc/csf/csf.6.saved +rm -fv /etc/csf/csf.block.AUTOSHUN +rm -fv /etc/csf/csf.block.BFB +rm -fv /etc/csf/csf.block.BOGON +rm -fv /etc/csf/csf.block.CIARMY +rm -fv /etc/csf/csf.block.DSHIELD +rm -fv /etc/csf/csf.block.HONEYPOT +rm -fv /etc/csf/csf.block.MAXMIND +rm -fv /etc/csf/csf.block.OPENBL +rm -fv /etc/csf/csf.block.RBN +rm -fv /etc/csf/csf.block.SPAMDROP +rm -fv /etc/csf/csf.block.SPAMEDROP +rm -fv /etc/csf/csf.block.TOR +rm -fv /etc/csf/csf.ccignore +rm -fv /etc/csf/csf.cclookup +rm -fv /etc/csf/csf.div +rm -fv /etc/csf/csf.dnscache +rm -fv /etc/csf/csf.dwdisable +rm -fv /etc/csf/csf.gallow +rm -fv /etc/csf/csf.gdeny +rm -fv /etc/csf/csf.gdyndns +rm -fv /etc/csf/csf.gignore +rm -fv /etc/csf/csf.load +rm -fv /etc/csf/csf.lock +rm -fv /etc/csf/csf.logmax +rm -fv /etc/csf/csf.logrun +rm -fv /etc/csf/csf.logtemp +rm -fv /etc/csf/csf.queue +rm -fv /etc/csf/csf.restart +rm -fv /etc/csf/csf.tempallow +rm -fv /etc/csf/csf.tempban +rm -fv /etc/csf/csf.tempconf +rm -fv /etc/csf/csf.tempdisk +rm -fv /etc/csf/csf.tempdyn +rm -fv /etc/csf/csf.tempexp +rm -fv /etc/csf/csf.tempexploit +rm -fv /etc/csf/csf.tempfiles +rm -fv /etc/csf/csf.tempgdyn +rm -fv /etc/csf/csf.tempint +rm -fv /etc/csf/csf.tempip +rm -fv /etc/csf/csf.temppids +rm -fv /etc/csf/csf.tempusers +rm -fv /etc/csf/csf.tempwatch +rm -fv /etc/csf/Geo/GeoIP.dat +rm -fv /etc/csf/Geo/GeoLiteCity.dat +rm -fv /etc/csf/lfd.enable +rm -fv /etc/csf/lfd.restart +rm -fv /etc/csf/lfd.start +rm -Rfv /etc/csf/lock/ +rm -fv /etc/csf/nocheck +rm -fv /etc/csf/sanity.txt +rm -Rfv /etc/csf/stats/ +rm -fv /etc/csf/suspicious.tar +rm -fv /etc/csf/ui/ui.session +rm -Rfv /etc/csf/webmin/ +rm -Rfv /etc/csf/zone/ + +# email alert templates: + +cp -avf /etc/csf/accounttracking.txt /usr/local/csf/tpl/ +cp -avf /etc/csf/alert.txt /usr/local/csf/tpl/ +cp -avf /etc/csf/connectiontracking.txt /usr/local/csf/tpl/ +cp -avf /etc/csf/consolealert.txt /usr/local/csf/tpl/ +cp -avf /etc/csf/cpanelalert.txt /usr/local/csf/tpl/ +cp -avf /etc/csf/exploitalert.txt /usr/local/csf/tpl/ +cp -avf /etc/csf/filealert.txt /usr/local/csf/tpl/ +cp -avf /etc/csf/forkbombalert.txt /usr/local/csf/tpl/ +cp -avf /etc/csf/integrityalert.txt /usr/local/csf/tpl/ +cp -avf /etc/csf/loadalert.txt /usr/local/csf/tpl/ +cp -avf /etc/csf/logalert.txt /usr/local/csf/tpl/ +cp -avf /etc/csf/logfloodalert.txt /usr/local/csf/tpl/ +cp -avf /etc/csf/netblock.txt /usr/local/csf/tpl/ +cp -avf /etc/csf/permblock.txt /usr/local/csf/tpl/ +cp -avf /etc/csf/portknocking.txt /usr/local/csf/tpl/ +cp -avf /etc/csf/portscan.txt /usr/local/csf/tpl/ +cp -avf /etc/csf/processtracking.txt /usr/local/csf/tpl/ +cp -avf /etc/csf/queuealert.txt /usr/local/csf/tpl/ +cp -avf /etc/csf/relayalert.txt /usr/local/csf/tpl/ +cp -avf /etc/csf/resalert.txt /usr/local/csf/tpl/ +cp -avf /etc/csf/reselleralert.txt /usr/local/csf/tpl/ +cp -avf /etc/csf/scriptalert.txt /usr/local/csf/tpl/ +cp -avf /etc/csf/sshalert.txt /usr/local/csf/tpl/ +cp -avf /etc/csf/sualert.txt /usr/local/csf/tpl/ +cp -avf /etc/csf/syslogalert.txt /usr/local/csf/tpl/ +cp -avf /etc/csf/tracking.txt /usr/local/csf/tpl/ +cp -avf /etc/csf/uialert.txt /usr/local/csf/tpl/ +cp -avf /etc/csf/uidscan.txt /usr/local/csf/tpl/ +cp -avf /etc/csf/usertracking.txt /usr/local/csf/tpl/ +cp -avf /etc/csf/watchalert.txt /usr/local/csf/tpl/ +cp -avf /etc/csf/webminalert.txt /usr/local/csf/tpl/ +cp -avf /etc/csf/x-arf.txt /usr/local/csf/tpl/ + +rm -fv /etc/csf/accounttracking.txt +rm -fv /etc/csf/alert.txt +rm -fv /etc/csf/connectiontracking.txt +rm -fv /etc/csf/consolealert.txt +rm -fv /etc/csf/cpanelalert.txt +rm -fv /etc/csf/exploitalert.txt +rm -fv /etc/csf/filealert.txt +rm -fv /etc/csf/forkbombalert.txt +rm -fv /etc/csf/integrityalert.txt +rm -fv /etc/csf/loadalert.txt +rm -fv /etc/csf/logalert.txt +rm -fv /etc/csf/logfloodalert.txt +rm -fv /etc/csf/netblock.txt +rm -fv /etc/csf/permblock.txt +rm -fv /etc/csf/portknocking.txt +rm -fv /etc/csf/portscan.txt +rm -fv /etc/csf/processtracking.txt +rm -fv /etc/csf/queuealert.txt +rm -fv /etc/csf/relayalert.txt +rm -fv /etc/csf/resalert.txt +rm -fv /etc/csf/reselleralert.txt +rm -fv /etc/csf/scriptalert.txt +rm -fv /etc/csf/sshalert.txt +rm -fv /etc/csf/sualert.txt +rm -fv /etc/csf/syslogalert.txt +rm -fv /etc/csf/tracking.txt +rm -fv /etc/csf/uialert.txt +rm -fv /etc/csf/uidscan.txt +rm -fv /etc/csf/usertracking.txt +rm -fv /etc/csf/watchalert.txt +rm -fv /etc/csf/webminalert.txt +rm -fv /etc/csf/x-arf.txt + +# perl modules: + +rm -Rfv /etc/csf/Crypt +rm -Rfv /etc/csf/Geo +rm -Rfv /etc/csf/HTTP +rm -Rfv /etc/csf/Net + +# scripts: + +cp -avf /etc/csf/cseui.pl /usr/local/csf/bin/ +cp -avf /etc/csf/csftest.pl /usr/local/csf/bin/ +cp -avf /etc/csf/csfui.pl /usr/local/csf/bin/ +cp -avf /etc/csf/csfuir.pl /usr/local/csf/bin/ +cp -avf /etc/csf/migratedata.pl /usr/local/csf/bin/ +cp -avf /etc/csf/pt_deleted_action.pl /usr/local/csf/bin/ +cp -avf /etc/csf/regex.custom.pm /usr/local/csf/bin/ +cp -avf /etc/csf/regex.pm /usr/local/csf/bin/ +cp -avf /etc/csf/remove_apf_bfd.sh /usr/local/csf/bin/ +cp -avf /etc/csf/servercheck.pm /usr/local/csf/bin/ +cp -avf /etc/csf/uninstall.sh /usr/local/csf/bin/ + +rm -fv /etc/csf/cseui.pl +rm -fv /etc/csf/csftest.pl +rm -fv /etc/csf/csfui.pl +rm -fv /etc/csf/csfuir.pl +rm -fv /etc/csf/migratedata.pl +rm -fv /etc/csf/pt_deleted_action.pl +rm -fv /etc/csf/regex.custom.pm +rm -fv /etc/csf/regex.pm +rm -fv /etc/csf/remove_apf_bfd.sh +rm -fv /etc/csf/servercheck.pm +rm -fv /etc/csf/uninstall.sh + +# other: + +rm -fv /etc/csf/*.new +rm -fv /etc/csf/dd_test +rm -fv /etc/csf/csfwebmin.tgz +rm -fv /etc/csf/csf.spamhaus /etc/csf/csf.dshield /etc/csf/csf.tor /etc/csf/csf.bogon +rm -Rfv /etc/csf/File +rm -Rfv /etc/csf/Geography +rm -Rfv /etc/csf/IP +rm -Rfv /etc/csf/Math +rm -Rfv /etc/csf/Sys + +rm -fv /etc/csf/csf.disable diff --git a/src/redux/modsecipdbalert.txt b/src/redux/modsecipdbalert.txt new file mode 100644 index 000000000..759492ede --- /dev/null +++ b/src/redux/modsecipdbalert.txt @@ -0,0 +1,9 @@ +From: root +To: root +Subject: lfd on [hostname]: ModSecurity persistent IP database size alert + +Time: [time] + +[text] + +This requires further investigation otherwise it will start to affect server performance. diff --git a/src/redux/netblock.txt b/src/redux/netblock.txt new file mode 100644 index 000000000..2d92dea4c --- /dev/null +++ b/src/redux/netblock.txt @@ -0,0 +1,10 @@ +From: root +To: root +Subject: lfd on [hostname]: Network class [class] [block] has been blocked + +Time: [time] +Block: [block] +Hits: [count] + +IP addresses that triggered the block +[ips] diff --git a/src/redux/os.pl b/src/redux/os.pl new file mode 100644 index 000000000..06d19a952 --- /dev/null +++ b/src/redux/os.pl @@ -0,0 +1,172 @@ +#!/usr/bin/perl +############################################################################### +# Copyright 2006-2023, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +## no critic (RequireUseWarnings, ProhibitExplicitReturnUndef, ProhibitMixedBooleanOperators, RequireBriefOpen) +use strict; +use lib '/usr/local/csf/lib'; +use Fcntl qw(:DEFAULT :flock); + +umask(0177); + + +if (-l "/var/run" and readlink("/var/run") eq "../run" and -d "/run") { + sysopen (my $LFD, "lfd.service", O_RDWR); + my @data = <$LFD>; + seek ($LFD, 0, 0); + truncate ($LFD, 0); + foreach my $line (@data) { + if ($line =~ /^PIDFile=/) { + print $LFD "PIDFile=/run/lfd.pid\n"; + } else { + print $LFD $line; + } + } + close ($LFD); +} + +my $return = 0; +my @modules = ("Fcntl","File::Find","File::Path","IPC::Open3","Net::SMTP","POSIX","Socket","Math::BigInt"); +foreach my $module (@modules) { +# print STDERR "Checking for $module\n"; + local $SIG{__DIE__} = undef; + eval ("use $module"); ##no critic + if ($@) { + print STDERR "\n".$@; + $return = 1; + } +} + +if (-e "/usr/sbin/iptables-nft") { + print STDERR "Configuration modified to use iptables-nft\n"; + system("update-alternatives", "--set", "iptables", "/usr/sbin/iptables-nft"); + if (-e "/usr/sbin/ip6tables-nft") { + print STDERR "Configuration modified to use ip6tables-nft\n"; + system("update-alternatives", "--set", "ip6tables", "/usr/sbin/ip6tables-nft"); + } +} + +if (-e "/etc/redhat-release") { + print STDERR "Using configuration defaults\n"; +} +elsif (-e "/etc/SuSE-release") { + open (my $IN, "<", "csf.generic.conf") or die $!; + flock ($IN, LOCK_SH) or die $!; + my @config = <$IN>; + close ($IN); + chomp @config; + open (my $OUT, ">", "csf.generic.conf") or die $!; + flock ($OUT, LOCK_EX) or die $!; + foreach my $line (@config) { + if ($line =~ /^IPTABLES /) {$line = 'IPTABLES = "/usr/sbin/iptables"'} + if ($line =~ /^FUSER/) {$line = 'FUSER = "/bin/fuser"'} + if ($line =~ /^HTACCESS_LOG/) {$line = 'HTACCESS_LOG = "/var/log/apache2/error_log"'} + if ($line =~ /^MODSEC_LOG/) {$line = 'MODSEC_LOG = "/var/log/apache2/error_log"'} + if ($line =~ /^SSHD_LOG/) {$line = 'SSHD_LOG = "/var/log/messages"'} + if ($line =~ /^SU_LOG/) {$line = 'SU_LOG = "/var/log/messages"'} + if ($line =~ /^FTPD_LOG/) {$line = 'FTPD_LOG = "/var/log/messages"'} + if ($line =~ /^POP3D_LOG/) {$line = 'POP3D_LOG = "/var/log/mail"'} + if ($line =~ /^IMAPD_LOG/) {$line = 'IMAPD_LOG = "/var/log/mail"'} + print $OUT $line."\n"; + } + close ($OUT); + print STDERR "Configuration modified for SuSE settings /etc/csf/csf.conf\n"; +} +elsif ((-e "/etc/debian_version") or (-e "/etc/lsb-release") or (-e "/etc/gentoo-release")) { + open (my $IN, "<", "csf.generic.conf") or die $!; + flock ($IN, LOCK_SH) or die $!; + my @config = <$IN>; + close ($IN); + chomp @config; + open (my $GENERIC, ">", "csf.generic.conf") or die $!; + flock ($GENERIC, LOCK_EX) or die $!; + foreach my $line (@config) { + if ($line =~ /^FUSER/) {$line = 'FUSER = "/bin/fuser"'} + if ($line =~ /^HTACCESS_LOG/) {$line = 'HTACCESS_LOG = "/var/log/apache2/error.log"'} + if ($line =~ /^MODSEC_LOG/) {$line = 'MODSEC_LOG = "/var/log/apache2/error.log"'} + 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/messages"'} + if ($line =~ /^FTPD_LOG/) {$line = 'FTPD_LOG = "/var/log/messages"'} + if ($line =~ /^POP3D_LOG/) {$line = 'POP3D_LOG = "/var/log/mail.log"'} + if ($line =~ /^IMAPD_LOG/) {$line = 'IMAPD_LOG = "/var/log/mail.log"'} + if ($line =~ /^SYSTEMCTL /) {$line = 'SYSTEMCTL = "/bin/systemctl"'} + if ($line =~ /^IPSET /) {$line = 'IPSET = "/sbin/ipset"'} + if ($line =~ /^IP /) {$line = 'IP = "/bin/ip"'} + if ($line =~ /^ZGREP /) {$line = 'ZGREP = "/bin/zgrep"'} + print $GENERIC $line."\n"; + } + close ($GENERIC); + + open (my $DIRECTADMIN, "<", "csf.directadmin.conf") or die $!; + flock ($DIRECTADMIN, LOCK_SH) or die $!; + @config = <$DIRECTADMIN>; + close ($DIRECTADMIN); + chomp @config; + open (my $OUT, ">", "csf.directadmin.conf") or die $!; + flock ($OUT, LOCK_EX) or die $!; + foreach my $line (@config) { + if ($line =~ /^FUSER/) {$line = 'FUSER = "/bin/fuser"'} + if ($line =~ /^SYSTEMCTL /) {$line = 'SYSTEMCTL = "/bin/systemctl"'} + if ($line =~ /^IPSET /) {$line = 'IPSET = "/sbin/ipset"'} + if ($line =~ /^IP /) {$line = 'IP = "/bin/ip"'} + if ($line =~ /^ZGREP /) {$line = 'ZGREP = "/bin/zgrep"'} + print $OUT $line."\n"; + } + close ($OUT); + print STDERR "Configuration modified for Debian/Ubuntu/Gentoo settings /etc/csf/csf.conf\n"; + + open (my $IN, "<", "csf.cyberpanel.conf") or die $!; + flock ($IN, LOCK_SH) or die $!; + my @config = <$IN>; + close ($IN); + chomp @config; + open (my $GENERIC, ">", "csf.cyberpanel.conf") or die $!; + flock ($GENERIC, LOCK_EX) or die $!; + foreach my $line (@config) { + if ($line =~ /^FUSER/) {$line = 'FUSER = "/bin/fuser"'} + if ($line =~ /^IPTABLES_LOG/) {$line = 'IPTABLES_LOG = "/var/log/kern.log"'} + if ($line =~ /^HTACCESS_LOG/) {$line = 'HTACCESS_LOG = "/var/log/apache2/error.log"'} + if ($line =~ /^MODSEC_LOG/) {$line = 'MODSEC_LOG = "/var/log/apache2/error.log"'} + 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/messages"'} + if ($line =~ /^FTPD_LOG/) {$line = 'FTPD_LOG = "/var/log/messages"'} + if ($line =~ /^POP3D_LOG/) {$line = 'POP3D_LOG = "/var/log/mail.log"'} + if ($line =~ /^IMAPD_LOG/) {$line = 'IMAPD_LOG = "/var/log/mail.log"'} + if ($line =~ /^SYSTEMCTL /) {$line = 'SYSTEMCTL = "/bin/systemctl"'} + if ($line =~ /^IPSET /) {$line = 'IPSET = "/sbin/ipset"'} + if ($line =~ /^IP /) {$line = 'IP = "/bin/ip"'} + if ($line =~ /^ZGREP /) {$line = 'ZGREP = "/bin/zgrep"'} + print $GENERIC $line."\n"; + } + close ($GENERIC); +} +elsif (-e "/etc/slackware-version") { + open (my $IN, "<", "csf.generic.conf") or die $!; + flock ($IN, LOCK_SH) or die $!; + my @config = <$IN>; + close ($IN); + chomp @config; + open (my $OUT, ">", "csf.generic.conf") or die $!; + flock ($OUT, LOCK_EX) or die $!; + foreach my $line (@config) { + if ($line =~ /^IPTABLES /) {$line = 'IPTABLES = "/usr/sbin/iptables"'} + if ($line =~ /^FUSER/) {$line = 'FUSER = "/usr/bin/fuser"'} + if ($line =~ /^HTACCESS_LOG/) {$line = 'HTACCESS_LOG = "/var/log/httpd/error.log"'} + if ($line =~ /^MODSEC_LOG/) {$line = 'MODSEC_LOG = "/var/log/httpd/error.log"'} + if ($line =~ /^SSHD_LOG/) {$line = 'SSHD_LOG = "/var/log/messages"'} + if ($line =~ /^SU_LOG/) {$line = 'SU_LOG = "/var/log/messages"'} + if ($line =~ /^FTPD_LOG/) {$line = 'FTPD_LOG = "/var/log/messages"'} + if ($line =~ /^POP3D_LOG/) {$line = 'POP3D_LOG = "/var/log/maillog"'} + if ($line =~ /^IMAPD_LOG/) {$line = 'IMAPD_LOG = "/var/log/maillog"'} + print $OUT $line."\n"; + } + close ($OUT); + print STDERR "Configuration modified for Slackware settings /etc/csf/csf.conf\n"; +} else {print STDERR "Using configuration defaults\n"} + +print $return; +exit; diff --git a/src/redux/perf.sh b/src/redux/perf.sh new file mode 100644 index 000000000..41d522e08 --- /dev/null +++ b/src/redux/perf.sh @@ -0,0 +1,9 @@ +#!/bin/bash +cd /etc/csf +rm -Rf /home/webumake/public_html/nytpro* +/usr/local/cpanel/3rdparty/bin/perl -d:NYTProf /etc/csf/csf.pl -r +/usr/local/cpanel/3rdparty/perl/522/bin/nytprofhtml --open +/bin/cp -avf nytprof /home/webumake/public_html/. +chmod -R 755 /home/webumake/public_html/nytprof + +# browse to http://www.webumake.net/nytprof/etc-csf-csf-pl-1-line.html diff --git a/src/redux/permblock.txt b/src/redux/permblock.txt new file mode 100644 index 000000000..561f8ccb0 --- /dev/null +++ b/src/redux/permblock.txt @@ -0,0 +1,10 @@ +From: root +To: root +Subject: lfd on [hostname]: [ip] blocked permanently + +Time: [time] +IP: [ip] +Temporary Blocks: [count] + +Temporary blocks that triggered the permanent block: +[blocks] diff --git a/src/redux/portknocking.txt b/src/redux/portknocking.txt new file mode 100644 index 000000000..38ef68d17 --- /dev/null +++ b/src/redux/portknocking.txt @@ -0,0 +1,7 @@ +From: root +To: root +Subject: lfd on [hostname]: Port Knocking port opened by [ip] + +Time: [time] +IP: [ip] +Port: [port] diff --git a/src/redux/portscan.txt b/src/redux/portscan.txt new file mode 100644 index 000000000..becbba977 --- /dev/null +++ b/src/redux/portscan.txt @@ -0,0 +1,11 @@ +From: root +To: root +Subject: lfd on [hostname]: [ip] blocked for port scanning + +Time: [time] +IP: [ip] +Hits: [count] +Blocked: [temp] + +Sample of block hits: +[blocks] diff --git a/src/redux/processtracking.txt b/src/redux/processtracking.txt new file mode 100644 index 000000000..5bc17514d --- /dev/null +++ b/src/redux/processtracking.txt @@ -0,0 +1,31 @@ +From: root +To: root +Subject: lfd on [hostname]: Suspicious process running under user [user] + +Time: [time] +PID: [pid] +Account: [user] +Uptime: [uptime] seconds + + +Executable: + +[exe] + + +Command Line (often faked in exploits): + +[cmdline] + + +Network connections by the process (if any): + +[sockets] + +Files open by the process (if any): + +[files] + +Memory maps by the process (if any): + +[maps] diff --git a/src/redux/profiles/block_all_perm.conf b/src/redux/profiles/block_all_perm.conf new file mode 100644 index 000000000..731333b2e --- /dev/null +++ b/src/redux/profiles/block_all_perm.conf @@ -0,0 +1,32 @@ +# Profile: This provides a configuration where all blocks are configured to be +# permanent +CT_BLOCK_TIME = "0" +CT_PERMANENT = "1" +DENY_IP_LIMIT = "400" +LF_APACHE_403_PERM = "1" +LF_APACHE_404_PERM = "1" +LF_BIND_PERM = "1" +LF_CPANEL_PERM = "1" +LF_CXS_PERM = "1" +LF_DISTFTP_PERM = "1" +LF_DISTSMTP_PERM = "1" +LF_EXIMSYNTAX_PERM = "1" +LF_FTPD_PERM = "1" +LF_HTACCESS_PERM = "1" +LF_IMAPD_PERM = "1" +LF_MODSEC_PERM = "1" +LF_NETBLOCK = "1" +LF_PERMBLOCK = "1" +LF_POP3D_PERM = "1" +LF_QOS_PERM = "1" +LF_SMTPAUTH_PERM = "1" +LF_SSHD_PERM = "1" +LF_SUHOSIN_PERM = "1" +LF_SYMLINK_PERM = "1" +LF_TRIGGER_PERM = "1" +LF_WEBMIN_PERM = "1" +PS_BLOCK_TIME = "0" +PS_PERMANENT = "1" +RT_AUTHRELAY_BLOCK = "1" +RT_POPRELAY_BLOCK = "1" +RT_RELAY_BLOCK = "1" diff --git a/src/redux/profiles/block_all_temp.conf b/src/redux/profiles/block_all_temp.conf new file mode 100644 index 000000000..6b325088c --- /dev/null +++ b/src/redux/profiles/block_all_temp.conf @@ -0,0 +1,32 @@ +# Profile: This provides a configuration where all blocks are configured to be +# temporary for a duration of one hour +CT_BLOCK_TIME = "3600" +CT_PERMANENT = "0" +DENY_TEMP_IP_LIMIT = "200" +LF_APACHE_403_PERM = "3600" +LF_APACHE_404_PERM = "3600" +LF_BIND_PERM = "3600" +LF_CPANEL_PERM = "3600" +LF_CXS_PERM = "3600" +LF_DISTFTP_PERM = "3600" +LF_DISTSMTP_PERM = "3600" +LF_EXIMSYNTAX_PERM = "3600" +LF_FTPD_PERM = "3600" +LF_HTACCESS_PERM = "3600" +LF_IMAPD_PERM = "3600" +LF_MODSEC_PERM = "3600" +LF_NETBLOCK = "0" +LF_PERMBLOCK = "0" +LF_POP3D_PERM = "3600" +LF_QOS_PERM = "3600" +LF_SMTPAUTH_PERM = "3600" +LF_SSHD_PERM = "3600" +LF_SUHOSIN_PERM = "3600" +LF_SYMLINK_PERM = "3600" +LF_TRIGGER_PERM = "3600" +LF_WEBMIN_PERM = "3600" +PS_BLOCK_TIME = "3600" +PS_PERMANENT = "0" +RT_AUTHRELAY_BLOCK = "3600" +RT_POPRELAY_BLOCK = "3600" +RT_RELAY_BLOCK = "3600" diff --git a/src/redux/profiles/disable_alerts.conf b/src/redux/profiles/disable_alerts.conf new file mode 100644 index 000000000..69f8ff755 --- /dev/null +++ b/src/redux/profiles/disable_alerts.conf @@ -0,0 +1,38 @@ +# Profile: This profile disables all options that will send email alerts. This +# profile is not recommended as the alerts often provide essential information +# about blocks and hacking activity on a server and if disabled that +# information will be lost. Additionally, some of these options disable +# functionality. +AT_ALERT = "0" +CT_EMAIL_ALERT = "0" +LF_CONSOLE_EMAIL_ALERT = "0" +LF_CPANEL_ALERT = "0" +LF_DIRWATCH = "0" +LF_EMAIL_ALERT = "0" +LF_INTEGRITY = "0" +LF_NETBLOCK_ALERT = "0" +LF_PERMBLOCK_ALERT = "0" +LF_QUEUE_ALERT = "0" +LF_SCRIPT_ALERT = "0" +LF_SSH_EMAIL_ALERT = "0" +LF_SU_EMAIL_ALERT = "0" +LF_WEBMIN_EMAIL_ALERT = "0" +LOGFLOOD_ALERT = "0" +LOGSCANNER = "0" +LT_EMAIL_ALERT = "0" +PORTKNOCKING_ALERT = "0" +PS_EMAIL_ALERT = "0" +PT_INTERVAL = "0" +PT_LOAD = "0" +PT_USERKILL_ALERT = "0" +RT_AUTHRELAY_ALERT = "0" +RT_LOCALHOSTRELAY_ALERT = "0" +RT_LOCALRELAY_ALERT = "0" +RT_POPRELAY_ALERT = "0" +RT_RELAY_ALERT = "0" +SYSLOG_CHECK = "0" +UID_INTERVAL = "0" +RECAPTCHA_ALERT = "0" +LF_DISTSMTP_ALERT = "0" +LF_DISTFTP_ALERT = "0" +LF_MODSECIPDB_ALERT = "0" diff --git a/src/redux/profiles/protection_high.conf b/src/redux/profiles/protection_high.conf new file mode 100644 index 000000000..bf5d023c2 --- /dev/null +++ b/src/redux/profiles/protection_high.conf @@ -0,0 +1,61 @@ +# Profile: This provides a high security level configuration that sets low +# levels for failure blocking and enables some of the more advanced features to +# provide a more secure configuration. It also enables a large number of alert +# emails. This profile can increase the rate of false-positive blocks +AT_ALERT = "1" +AUTO_UPDATES = "1" +CT_LIMIT = "300" +DROP_LOGGING = "1" +DROP_ONLYRES = "0" +ICMP_IN_RATE = "1/s" +IGNORE_ALLOW = "0" +LF_BLOCKINONLY = "0" +LF_CONSOLE_EMAIL_ALERT = "1" +LF_CPANEL = "3" +LF_CPANEL_ALERT = "1" +LF_CSF = "1" +LF_CXS = "1" +LF_DIRWATCH = "300" +LF_DISTATTACK = "1" +LF_DISTFTP = "5" +LF_DISTSMTP = "5" +LF_EXIMSYNTAX = "10" +LF_FTPD = "5" +LF_HTACCESS = "5" +LF_IMAPD = "5" +LF_INTEGRITY = "3600" +LF_MODSEC = "3" +LF_NETBLOCK = "1" +LF_PERMBLOCK = "1" +LF_POP3D = "5" +LF_QUEUE_ALERT = "2000" +LF_SCRIPT_ALERT = "1" +LF_SMTPAUTH = "5" +LF_SSH_EMAIL_ALERT = "1" +LF_SSHD = "3" +LF_SU_EMAIL_ALERT = "1" +LF_SYMLINK = "5" +LF_WEBMIN = "3" +LF_WEBMIN_EMAIL_ALERT = "1" +LOGSCANNER = "1" +LOGSCANNER_INTERVAL = "hourly" +PACKET_FILTER = "1" +PS_EMAIL_ALERT = "1" +PS_INTERVAL = "300" +PT_ALL_USERS = "1" +PT_DELETED = "1" +PT_FORKBOMB = "250" +PT_LIMIT = "60" +PT_SKIP_HTTP = "0" +RELAYHOSTS = "0" +RESTRICT_SYSLOG = "3" +RESTRICT_UI = "1" +RT_AUTHRELAY_ALERT = "1" +RT_LOCALHOSTRELAY_ALERT = "1" +RT_POPRELAY_ALERT = "1" +RT_RELAY_ALERT = "1" +SMTP_BLOCK = "1" +SYSLOG_CHECK = "300" +UDPFLOOD = "1" +UDPFLOOD_LOGGING = "1" +UID_INTERVAL = "600" diff --git a/src/redux/profiles/protection_low.conf b/src/redux/profiles/protection_low.conf new file mode 100644 index 000000000..e566d168a --- /dev/null +++ b/src/redux/profiles/protection_low.conf @@ -0,0 +1,60 @@ +# Profile: This provides a low security level configuration that sets high +# levels for login failure blocking and disables some of the more advanced +# features to provide a more simple configuration. It also disables a large +# number of alert emails. This profile can decrease the rate of false-positive +# blocks and reduced the load lfd places on the server, but is much less secure +AT_ALERT = "0" +AUTO_UPDATES = "0" +CONNLIMIT = "" +CT_LIMIT = "0" +ICMP_IN = "1" +ICMP_IN_RATE = "0" +ICMP_OUT = "1" +ICMP_OUT_RATE = "0" +LF_APACHE_403 = "0" +LF_APACHE_404 = "0" +LF_BIND = "0" +LF_BLOCKINONLY = "0" +LF_CONSOLE_EMAIL_ALERT = "0" +LF_CPANEL = "20" +LF_CPANEL_ALERT = "0" +LF_CXS = "0" +LF_DIRWATCH = "0" +LF_EXIMSYNTAX = "20" +LF_FTPD = "20" +LF_HTACCESS = "20" +LF_IMAPD = "20" +LF_INTEGRITY = "0" +LF_MODSEC = "20" +LF_NETBLOCK = "0" +LF_PERMBLOCK = "0" +LF_POP3D = "20" +LF_QOS = "0" +LF_QUEUE_ALERT = "0" +LF_SCRIPT_ALERT = "0" +LF_SMTPAUTH = "20" +LF_SSHD = "20" +LF_SUHOSIN = "0" +LF_SYMLINK = "0" +LF_WEBMIN = "0" +LF_WEBMIN_EMAIL_ALERT = "0" +LOGSCANNER = "0" +LT_IMAPD = "0" +LT_POP3D = "0" +PACKET_FILTER = "0" +PORTFLOOD = "" +PS_INTERVAL = "0" +PT_LIMIT = "0" +RELAYHOSTS = "0" +RESTRICT_SYSLOG = "2" +RESTRICT_UI = "0" +RT_AUTHRELAY_ALERT = "0" +RT_LOCALHOSTRELAY_ALERT = "0" +RT_LOCALRELAY_ALERT = "0" +RT_POPRELAY_ALERT = "0" +RT_RELAY_ALERT = "0" +SMTP_BLOCK = "0" +ST_ENABLE = "0" +SYNFLOOD = "0" +UDPFLOOD = "0" +UID_INTERVAL = "0" diff --git a/src/redux/profiles/protection_medium.conf b/src/redux/profiles/protection_medium.conf new file mode 100644 index 000000000..efa7842e5 --- /dev/null +++ b/src/redux/profiles/protection_medium.conf @@ -0,0 +1,62 @@ +# Profile: This provides a medium security level configuration that sets medium +# levels for login failure blocking and minimises false-positives. It is a +# slightly higher level than the default installation +AT_ALERT = "2" +AUTO_UPDATES = "1" +CONNLIMIT = "" +CT_LIMIT = "300" +ICMP_IN = "1" +ICMP_IN_RATE = "1/s" +ICMP_OUT = "1" +ICMP_OUT_RATE = "0" +LF_APACHE_403 = "0" +LF_APACHE_404 = "0" +LF_BIND = "0" +LF_BLOCKINONLY = "0" +LF_CONSOLE_EMAIL_ALERT = "0" +LF_CPANEL = "5" +LF_CPANEL_ALERT = "1" +LF_CXS = "1" +LF_DIRWATCH = "300" +LF_DISTATTACK = "1" +LF_EXIMSYNTAX = "10" +LF_FTPD = "10" +LF_HTACCESS = "5" +LF_IMAPD = "10" +LF_INTEGRITY = "3600" +LF_MODSEC = "5" +LF_NETBLOCK = "0" +LF_PERMBLOCK = "1" +LF_POP3D = "10" +LF_QOS = "0" +LF_QUEUE_ALERT = "2000" +LF_SCRIPT_ALERT = "1" +LF_SMTPAUTH = "5" +LF_SSHD = "5" +LF_SUHOSIN = "0" +LF_SYMLINK = "0" +LF_WEBMIN = "0" +LF_WEBMIN_EMAIL_ALERT = "0" +LOGSCANNER = "0" +LT_IMAPD = "0" +LT_POP3D = "0" +PACKET_FILTER = "1" +PORTFLOOD = "" +PS_INTERVAL = "0" +PT_ALL_USERS = "1" +PT_LIMIT = "60" +RELAYHOSTS = "0" +RESTRICT_SYSLOG = "3" +RESTRICT_UI = "1" +RT_AUTHRELAY_ALERT = "1" +RT_LOCALHOSTRELAY_ALERT = "1" +RT_LOCALRELAY_ALERT = "1" +RT_POPRELAY_ALERT = "1" +RT_RELAY_ALERT = "1" +SMTP_ALLOWLOCAL = "1" +SMTP_BLOCK = "1" +ST_ENABLE = "1" +SYNFLOOD = "0" +SYSLOG_CHECK = "300" +UDPFLOOD = "0" +UID_INTERVAL = "0" diff --git a/src/redux/pt_deleted_action.pl b/src/redux/pt_deleted_action.pl new file mode 100644 index 000000000..2f32c0ea2 --- /dev/null +++ b/src/redux/pt_deleted_action.pl @@ -0,0 +1,26 @@ +#!/usr/bin/perl +############################################################################### +# Copyright 2006-2023, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### +# Example PT_DELETED_ACTION script +use strict; + +my $exe = $ARGV[0]; +my $pid = $ARGV[1]; +my $user = $ARGV[2]; +my $ppid = $ARGV[3]; + +if ($exe =~ m[^/usr/libexec/dovecot/imap-login]) {exec("/etc/init.d/dovecot restart")} +elsif ($exe =~ m[^/usr/libexec/dovecot/pop3-login]) {exec("/etc/init.d/dovecot restart")} +elsif ($exe =~ m[^/usr/sbin/pure-ftpd]) {exec("/etc/init.d/pure-ftpd restart")} +elsif ($exe =~ m[^/usr/sbin/pure-authd]) {exec("/etc/init.d/pure-ftpd restart")} +elsif ($exe =~ m[^/bin/dbus-daemon]) {exec("/etc/init.d/messagebus restart")} +elsif ($exe =~ m[^/usr/sbin/hald]) {exec("/etc/init.d/haldaemon restart")} +elsif ($exe =~ m[^/usr/sbin/mysqld]) {exec("/etc/init.d/mysql restart")} +elsif ($exe =~ m[^/usr/sbin/exim]) {exec("/etc/init.d/exim restart")} + +exit; + +############################################################################### diff --git a/src/redux/queuealert.txt b/src/redux/queuealert.txt new file mode 100644 index 000000000..95360f147 --- /dev/null +++ b/src/redux/queuealert.txt @@ -0,0 +1,7 @@ +From: root +To: root +Subject: lfd on [hostname]: Email queue size alert + +Time: [time] + +[text] diff --git a/src/redux/readme.txt b/src/redux/readme.txt new file mode 100644 index 000000000..24e46d8a1 --- /dev/null +++ b/src/redux/readme.txt @@ -0,0 +1,1734 @@ +############################################################################### +# Copyright 2006-2023, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### + + +ConfigServer Security & Firewall +################################ + +This suite of scripts provides: + + 1. A straight-forward SPI iptables firewall script + 2. A daemon process that checks for Login Authentication + 3. A Control Panel configuration interface + 4. ... and much more! + +The reason we have developed this suite is that we have found over the years of +providing server management services that many of the tools available for the +task are either over-complex, not very friendly, or simply aren't as effective +as they could or should be. + + +This document contains: + +1. Introduction + +2. csf Principles + +3. lfd Principles + +4. csf Command Line Options + +5. lfd Command Line Options + +6. Login Tracking + +7. Script Email Alerts + +8. Process Tracking + +9. Directory Watching + +10. Advanced Allow/Deny Filters + +11. Multiple Ethernet Devices + +12. Installation on a Generic Linux Server + +13. A note about FTP Connection Issues + +14. Messenger Service (v1, v2 and v3) + +15. Block Reporting + +16. Port Flood Protection + +17. External Pre- and Post- Scripts + +18. lfd Clustering + +19. Port Knocking + +20. Connection Limit Protection + +21. Port/IP address Redirection + +22. Integrated User Interface Feature + +23. IP Block Lists + +24. Mitigating issues with syslog/rsyslog logs (RESTRICT_SYSLOG) + +25. Exim SMTP AUTH Restriction + +26. UI Skinning and Mobile View + +27. CloudFlare + +28. InterWorx + +29. CentOS Web Panel (CWP) + + +1. Introduction +############### + + +ConfigServer Firewall (csf) +=========================== + +We have developed an SPI iptables firewall that is straight-forward, easy and +flexible to configure and secure with extra checks to ensure smooth operation. + +csf can be used on any (supported - see the website) generic Linux OS. + +The csf installation includes preconfigured configurations and control panel +UI's for cPanel, DirectAdmin and Webmin + +Directory structure: + +/etc/csf/ - 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 + + +Login Failure Daemon (lfd) +========================== + +To complement the ConfigServer Firewall, we have developed a daemon process +that runs all the time and periodically (every X seconds) scans the latest log +file entries for login attempts against your server that continually fail +within a short period of time. Such attempts are often called "Brute-force +attacks" and the daemon process responds very quickly to such patterns and +blocks offending IP's quickly. Other similar products run every x minutes via +cron and as such often miss break-in attempts until after they've finished, our +daemon eliminates such long waits and makes it much more effective at +performing its task. + +There are an array of extensive checks that lfd can perform to help alert the +server administrator of changes to the server, potential problems and possible +compromises. + +On cPanel servers, lfd is integrated into the WHM > Service Manager, which will +restart lfd if it fails for any reason. + +Control Panel Interface +======================= + +To help with the ease and flexibility of the suite we have developed a +front-end to both csf and lfd for cPanel, DirectAdmin and Webmin. From there +you can modify the configuration files and stop, start and restart the +applications and check their status. This makes configuring and managing the +firewall very simple indeed. + +There is, of course, a comprehensive Command Line Interface (CLI) for csf. + + +2. csf Principles +################# + +The idea with csf, as with most iptables firewall configurations, is to block +everything and then allow through only those connections that you want. This is +done in iptables by DROPPING all connections in and out of the server on all +protocols. Then allow traffic in and out from existing connections. Then open +ports up in and outgoing for both TCP and UDP individually. + +This way we can control exactly what traffic is allowed in and out of the +server and helps protect the server from malicious attack. + +In particular it prevents unauthorised access to network daemons that we want +to restrict access by IP address, and also should a service suffer a +compromise, it can help prevent access to compromise networks daemons, a +typical example being a hackers sshd daemon running on a random open port. +Perhaps the greatest of reasons is to help mitigate the effects of suffering a +root compromise where often they only way to take advantage of such a failure +is to open a daemon for the hacker to access the server on. While this won't +prevent root compromises, it can help slow them down enough for you to notice +and react. + +Another way that a port filtering firewall can help is when a user level +compromise occurs and a hacker installs DOS tools to effect other servers. A +firewall configured to block outgoing connections except on specific ports can +help prevent DOS attacks from working and make it immediately apparent to you +from the system logs. + +csf has been designed to keep this configuration simple, but still flexible +enough to give you options to suit your server environment. Often firewall +scripts can become cumbersome of complex making it impossible to identify where +problems lie and to easily fix them. + +To take advantage of kernel logging of iptables dropped connections you should +ensure that kernel logging daemon (klogd) is enabled. Typically, VPS servers +have this disabled and you should check /etc/init.d/syslog and make sure that +any klogd lines are not commented out. If you change the file, remember to +restart syslog. + + +3. lfd Principles +################# + +One of the best ways to protect the server from inbound attack against network +daemons is to monitor their authentication logs. Invalid login attempts which +happen in a short space of time from the same source can often mean someone is +attempting to brute-force their way into the server, usually by guessing +usernames and passwords and therefore generating authentication and login +failures. + +lfd can monitor the most commonly abused protocols, SSHD, POP3, IMAP, FTP and +HTTP password protection. Unlike other applications, lfd is a daemon process +that monitors logs continuously and so can react within seconds of detecting +such attempts. It also monitors across protocols, so if attempts are made on +different protocols in a short space of time, all those attempts will be +counted against the threshold. + +Once the number of failed login attempts is reached, lfd immediately forks a +sub-process and uses csf to block the offending IP address from both in and +outgoing connections. Stopping the attack in its tracks in a quick and timely +manner. Other applications that use cron job timings to run usually completely +miss brute force attacks as they run usually every 5 minutes or by which time +the attack could be over, or simply biding its time. In the meantime lfd will +have block the offenders IP address. + +By running the block and alert email actions in a sub-process, the main daemon +can continue monitoring the logs without delay. + +If you want to know when lfd blocks an IP address you can enable the email +alert (which is on by default) and you should watch the log file in +/var/log/lfd.log. + + +4. csf Command Line Options +########################### + +Before configuring and starting csf for the first time, it is a good idea to +run the script /etc/csf/csftest.pl using: + +perl /etc/csf/csftest.pl + +This script will test whether the required iptables modules are functioning on +the server. Don't worry if it cannot run all the features, so long as the +script doesn't report any FATAL errors. + + +You can view the csf command line options by using either: + +# man csf + +or + +# csf -h + +These options allow you to easily and quickly control and view csf. All the +configuration files for csf are in /etc/csf and include: + +csf.conf - the main configuration file, it has helpful comments explaining + what each option does +csf.allow - a list of IP's and CIDR addresses that should always be allowed + through the firewall +csf.deny - a list of IP's and CIDR addresses that should never be allowed + through the firewall +csf.ignore - a list of IP's and CIDR addresses that lfd should ignore and + not block if detected +csf.*ignore - various ignore files that list files, users, IP's that lfd + should ignore. See each file for their specific purpose and + tax + +If you modify any of the files listed above, you will need to restart csf and +then lfd to have them take effect. If you use the command line options to add +or deny IP addresses, then csf automatically does this for you. + +Both csf.allow and csf.deny can have comments after the IP address listed. The +comments must be on the same line as the IP address otherwise the IP rotation +of csf.deny will remove them. + +If editing the csf.allow or csf.deny files directly, either from shell or the +WHM UI, you should put a # between the IP address and the comment +like this: + +11.22.33.44 # Added because I don't like them + +You can also include comments when using the csf -a or csf -d commands, but in +those cases you must not use a # like this: + +csf -d 11.22.33.44 Added because I don't like them + +If you use the shell commands then each comment line will be timestamped. You +will also find that if lfd blocks an IP address it will add a descriptive +comment plus timestamp. + +If you don't want csf to rotate a particular IP in csf.deny if the line limit +is reach you can do so by adding "do not delete" within the comment field, +e.g.: + +11.22.33.44 # Added because I don't like them. do not delete + +Include statement in configuration files +======================================== + +You can use an Include statement in the following files that conform to the +format of the originating file: + +/etc/csf/csf.allow +/etc/csf/csf.blocklists +/etc/csf/csf.cloudflare +/etc/csf/csf.deny +/etc/csf/csf.dirwatch +/etc/csf/csf.dyndns +/etc/csf/csf.fignore +/etc/csf/csf.ignore +/etc/csf/csf.logfiles +/etc/csf/csf.logignore +/etc/csf/csf.mignore +/etc/csf/csf.pignore +/etc/csf/csf.rblconf +/etc/csf/csf.redirect +/etc/csf/csf.rignore +/etc/csf/csf.signore +/etc/csf/csf.sips +/etc/csf/csf.smtpauth +/etc/csf/csf.suignore +/etc/csf/csf.syslogs +/etc/csf/csf.syslogusers +/etc/csf/csf.uidignore + +You must specify the full path to the included file, e.g. in +/etc/csf/csf.allow: + +Include /etc/csf/csf.alsoallow + +Do NOT put a comment after the Include filename as this will not work and will +invalidate the Include line. + +Note: None of the csf commands for adding or removing entries from the +originating file will be performed on Include files. They are treated as +read-only. + + +5. lfd Command Line Options +########################### + +lfd does not have any command line options of its own but is controlled through +init or systemd which stops and starts the daemon. It is configured using the +/etc/csf/csf.conf file. + +The best way to see what lfd is up to is to take a look in /var/log/lfd.log +where its activities are logged. + +The various email alert templates follow, care should be taken if you +modify that file to maintain the correct format: + +/usr/local/csf/tpl/accounttracking.txt - for account tracking alert emails +/usr/local/csf/tpl/alert.txt - for port blocking emails +/usr/local/csf/tpl/connectiontracking.txt - for connection tracking emails +/usr/local/csf/tpl/consolealert.txt - for console root login alert emails +/usr/local/csf/tpl/cpanelalert.txt - for WHM/cPanel account access emails +/usr/local/csf/tpl/exploitalert.txt - for system exploit alert emails +/usr/local/csf/tpl/filealert.txt - for suspicious file alert emails +/usr/local/csf/tpl/forkbombalert.txt - for fork bomb alert emails +/usr/local/csf/tpl/integrityalert.txt - for system integrity alert emails +/usr/local/csf/tpl/loadalert.txt - for high load average alert emails +/usr/local/csf/tpl/logalert.txt - for log scanner report emails +/usr/local/csf/tpl/logfloodalert.txt - for log file flooding alert emails +/usr/local/csf/tpl/modsecipdbcheck.txt - for ModSecurity IP DB size alert emails +/usr/local/csf/tpl/netblock.txt - for netblock alert emails +/usr/local/csf/tpl/permblock.txt - for temporary to permanent block alert emails +/usr/local/csf/tpl/portknocking.txt - for Port Knocking alert emails +/usr/local/csf/tpl/portscan.txt - for port scan tracking alert emails +/usr/local/csf/tpl/processtracking.txt - for process tracking alert emails +/usr/local/csf/tpl/queuealert.txt - for email queue alert emails +/usr/local/csf/tpl/relayalert.txt - for email relay alert emails +/usr/local/csf/tpl/resalert.txt - for process resource alert emails +/usr/local/csf/tpl/scriptalert.txt - for script alert emails +/usr/local/csf/tpl/sshalert.txt - for SSH login emails +/usr/local/csf/tpl/sualert.txt - for SU alert emails +/usr/local/csf/tpl/tracking.txt - for POP3/IMAP blocking emails +/usr/local/csf/tpl/uialert.txt - for UI alert emails +/usr/local/csf/tpl/usertracking.txt - for user process tracking alert emails +/usr/local/csf/tpl/watchalert.txt - for watched file and directory change alert emails +/usr/local/csf/tpl/webminalert.txt - for Webmin login emails + +6. Login Tracking +################# + +Login tracking is an extension of lfd, it keeps track of POP3 and IMAP logins +and limits them to X connections per hour per account per IP address. It uses +iptables to block offenders to the appropriate protocol port only and flushes +them every hour and starts counting logins afresh. All of these blocks are +temporary and can be cleared manually by restarting csf. + +There are two settings, one of POP3 and one for IMAP logins. It's generally +not a good idea to track IMAP logins as many clients login each time to perform +a protocol transaction (there's no need for them to repeatedly login, but you +can't avoid bad client programming!). So, if you do have a need to have some +limit to IMAP logins, it is probably best to set the login limit quite high. + +If you want to know when lfd temporarily blocks an IP address you can enable +the email tracking alerts option (which is on by default) + +You can also add your own login failure tracking using regular expression +matching. Please read /usr/local/csf/bin/regex.custom.pm for more information + +Important Note: To enable successful SSHD login tracking you should ensure that +UseDNS in /etc/ssh/sshd_config is disabled by using: + +UseDNS no + +and that sshd has then been restarted. + +7. Script Email Alerts +###################### + +(cPanel installations of csf only) + +lfd can scan for emails being sent through exim from scripts on the server. + +To use this feature you must add an extended email logging line to WHM > +Exim Configuration Manager > Advanced Editor. Search for log_selector and +ensure that the following are included: + +log_selector = +arguments +subject +received_recipients + +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. + +This option uses the /usr/local/csf/tpl/scriptalert text file for alert emails. + +If you enable the option LF_SCRIPT_ALERT then lfd will disable the path using +chattr +i and chmod 000 so that the user cannot re-enable it. The alert email +also then includes the commands needed to re-enable the offending path. + +Any false-positives can be added to /etc/csf/csf.signore and lfd will then +ignore those listed scripts. + +8. 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. Processes (PIDs) are only +reported once unless lfd is restarted. + +There is an ignore file /etc/csf/csf.pignore which can be used to whitelist +either usernames or full paths to binaries. Care should be taken with ignoring +users or files so that you don't force false-negatives. + +You must use the following format: + +exe:/full/path/to/file +user:username +cmd:command line + +The command line as reported in /proc has the trailing null character removed +and all other occurrences replaced with a space. So, the line you specify in +the file should have space separators for the command line arguments, not null +characters. + +It is strongly recommended that you use command line ignores very carefully +as any process can change what is reported to the OS. + +Don't list the paths to perl or php as this will prevent detection of +suspicious web scripts. + +For more information on the difference between executable and command line, you +should read and understand how the linux /proc pseudo-filesystem works: + +man proc +man lsof + +It is beyond the scope of this application to explain how to investigate +processes in the linux /proc architecture. + +The email alerts are sent using the processtracking.txt email template. + +It should be noted that this feature will not pickup a root compromise as root +processes are ignored - you should use established IDS tools for such security +considerations. + +*** NOTE *** You _will_ get false-positives with this particular feature. The +reason for the feature is to bring to your attention processes that have either +been running for a long time under a user account, or that have ports open +outside of your server. You should satisfy yourself that they are indeed false- +positives before either ignoring them or trapping them in the csf.pignore file. + +We've done our best to minimise false-positives, but there's a balance between +being cautious and the sensitivity needed to pick up exploits. + +The script itself cannot distinguish between malicious intent and intended +script function - that's your job as the server administrator ;-) + +The setting PT_SKIP_HTTP does reduce the number of false-positives by not +checking scripts running directly or through CGI in Apache. However, disabling +this setting will make a more thorough job of detecting active exploits of all +varieties. + +Another alternative might be to disable PT_SKIP_HTTP and increase PT_LIMIT to +avoid picking up web scripts, however this means that real exploits will run +for longer before they're picked up. + +You can, of course, turn the feature off too - if you really want to. + + +9. Directory Watching +##################### + +Directory Watching enables lfd to check /tmp and /dev/shm and other pertinent +directories for suspicious files, i.e. script exploits. + +If a suspicious file is found an email alert is sent using the template +filealert.txt. + +NOTE: Only one alert per file is sent until lfd is restarted, so if you remove +a suspicious file, remember to restart lfd + +To remove any suspicious files found during directory watching, enable +corresponding setting the suspicious files will be appended to a tarball in +/var/lib/csf/suspicious.tar and deleted from their original location. Symlinks +are simply removed. + +If you want to extract the tarball to your current location, use: + +tar -xpf /var/lib/csf/suspicious.tar + +This will preserver the path and permissions of the original file. + +Any false-positives can be added to /etc/csf/csf.fignore and lfd will then +ignore those listed files and directories. + +Within csf.fignore 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 asterisk (*), +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 + +For information on perl regular expressions: +http://www.perl.com/doc/manual/html/pod/perlre.html + +The second aspect of Directory Watching is enabled with LF_DIRWATCH_FILE. 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. It uses a +simple md5sum match from the output of "ls -laAR" on the entry and so will +traverse directories if specified. + + +10. Advanced Allow/Deny Filters +############################### + +In /etc/csf/csf.allow and /etc/csf/csf.deny you can add more complex port and +ip filters using the following format (you must specify a port AND an IP +address): + +tcp/udp|in/out|s/d=port|s/d=ip|u=uid + +Broken down: + +tcp/udp : EITHER tcp OR udp OR icmp protocol +in/out : EITHER incoming OR outgoing connections +s/d=port : EITHER source OR destination port number (or ICMP type) + (use a _ for a port range, e.g. 2000_3000) + (use a , for a multiport list of up to 15 ports, e.g. 22,80,443) +s/d=ip : EITHER source OR destination IP address +u/g=UID : EITHER UID or GID of source packet, implies outgoing connections, + s/d=IP value is ignored + +Note: ICMP filtering uses the "port" for s/d=port to set the ICMP type. +Whether you use s or d is not relevant as either simply uses the iptables +--icmp-type option. Use "iptables -p icmp -h" for a list of valid ICMP types. +Only one type per filter is supported + +Examples: + +# TCP connections inbound to port 3306 from IP 11.22.33.44 +tcp|in|d=3306|s=11.22.33.44 + +# TCP connections outbound to port 22 on IP 11.22.33.44 +tcp|out|d=22|d=11.22.33.44 + +Note| If omitted, the default protocol is set to "tcp", the default connection +direction is set to "in", so| + +# TCP connections inbound to port 22 from IP 44.33.22.11 +d=22|s=44.33.22.11 + +# TCP connections outbound to port 80 from UID 99 +tcp|out|d=80||u=99 + +# ICMP connections inbound for type ping from 44.33.22.11 +icmp|in|d=ping|s=44.33.22.11 + +# TCP connections inbound to port 22 from Dynamic DNS address +# www.configserver.com (for use in csf.dyndns only) +tcp|in|d=22|s=www.configserver.com + +# TCP connections inbound to port 22,80,443 from IP 44.33.22.11 +d=22,80,443|s=44.33.22.11 + + +11. Multiple Ethernet Devices +############################# + +If you have multiple ethernet NICs that you want to apply all rules to, then +you can set ETH_DEVICE to the interface name immediately followed by a plus +sign. For example, eth+ will apply all iptables rules to eth0, eth1, etc. + +That said, if you leave ETH_DEVICE blank all rules will be applied to all +ethernet devices equally. + + +12. Installation on a Generic Linux Server +########################################## + +csf+lfd can be configured to run on a generic Linux server. There are some +changes to the features available: + +1. The default port range is for a typical non-cPanel web server and may need + altering to suit the servers environment + +2. The Process Tracking ignore file may need expanding in /etc/csf/csf.pignore + to suit the server environment + +3. A standard Webmin Module to configure csf is included - see the install.txt + for more information + +The codebase is the same for a all installations, the csf.conf file simply has +the cPanel specific options removed and the GENERIC option added + + +13. A note about FTP Connection Issues +###################################### + +It is important when using an SPI firewall to ensure FTP client applications +are configured to use Passive (PASV) mode connections to the server. + +On servers running Monolithic kernels (e.g. VPS Virtuozzo/OpenVZ and custom +built kernels) ip_conntrack and ip_conntrack_ftp iptables kernel modules may +not be available or fully functional. If this happens, FTP passive mode (PASV) +won't work. In such circumstances you will have to open a hole in your firewall +and configure the FTP server to use that same hole. + +For example, with pure-ftpd you could add the port range 30000:35000 to TCP_IN +and add the following line to /etc/pure-ftpd.conf and then restart pure-ftpd: +PassivePortRange 30000 35000 + +For example, with proftpd you could add the port range 30000:35000 to TCP_IN +and add the following line to /etc/proftpd.conf and then restart proftpd: +PassivePorts 30000 35000 + +FTP over SSL/TLS will usually fail when using an SPI firewall. This is because +of the way the FTP protocol established a connection between client and server. +iptables fails to establish a related connection when using FTP over SSL +because the FTP control connection is encrypted and so cannot track the +relationship between the connection and the allocation of an ephemeral port. + +If you need to use FTP over SSL, you will have to open up a passive port block +in both csf and your FTP server configuration (see above). + +Perversely, this makes your firewall less secure, while trying to make FTP +connections more secure. + + +14. 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 several daemons running on ports providing HTTPS, HTML or TEXT +message. + +This services uses the iptables nat table and the associated PREROUTING chain. +The ipt_REDIRECT module is used to redirect the incoming port to the relevant +messenger service server port. + +Temporary and/or permanent (csf.deny) IP addresses can be serviced by this +feature. + +It does NOT include redirection of any GLOBAL or BLOCK deny lists. + +It does require the IO::Socket::INET perl module. + +It 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. + +If you change any of the files in /etc/csf/messenger/ you must restart lfd as +they are all cached in memory. + +Use of this feature can be controlled by the Country Code options: +CC_MESSENGER_ALLOW = "" +CC_MESSENGER_DENY = "" +See /etc/csf/csf.conf for an explanation of those options. + + +Messenger User +============== + +You should create a unique user that the messenger services will run under. +This user should be disabled and have no shell access, but should have a home +directory. + +For example, you can create such an account (in this example called "csf") from +the root shell using: + +useradd csf -s /bin/false + +TEXT Messenger Server +===================== + +The TEXT message that is displayed is provided by the file: + +/etc/csf/messenger/index.text + +This file should only contain text. The TEXT server providing this file simply +sends the contents to the connecting port and no protocol exchange takes place. +this means that it may not be suitable for use with protocols such as POP3. + +The server has a built-in function that will replace the text [IPADDRESS] in +index.text with the IP address that is blocked by the firewall. This will help +the blocked user know what their blocked IP address is. You can also use the +text [HOSTAME] which will be replaced by the servers FQDN hostname. + +The TEXT server does not support SSL connections, so redirecting port 995 will +not work. + +The TEXT server port should not be added to the TCP_IN list. + +There is a maximum of 15 port allowed in MESSENGER_TEXT_IN. + +HTML and HTTPS Messenger v1 Server +================================== + +The HTML and HTTPS message that is displayed is provided by the file: + +/etc/csf/messenger/index.html +/etc/csf/messenger/index.recaptcha.html (if using the RECAPTCHA_* feature) + +The HTML server providing this page is very rudimentary but will accept the use +of linked images that are stored in the /etc/csf/messenger/ directory. The +images must be of either jpg, gif or png format. These images are loaded into +memory so you should keep the number and size to a minimum. No other linked +resource files are supported (e.g. .css, .js). + +It is recommeneded to to use inline images (source embedding) to improve page +load speed and reduce lfd overheads. + +As the HTML server requires interaction with the client, there is a timer on +the connection to prevent port hogging. + +The server has a built-in function that will replace the text [IPADDRESS] in +index.html with the IP address that is blocked by the firewall. This will help +the blocked user know what their blocked IP address is. You can also use the +text [HOSTAME] which will be replaced by the servers FQDN hostname. + +The HTTPS service obtains the necessary certificates from MESSENGER_HTTPS_CONF. + +The HTML and HTTPS server ports should not be added to the TCP_IN list. + +There is a maximum of 15 ports allowed in MESSENGER_HTML_IN and +MESSENGER_HTTPS_IN. + +HTML and HTTPS Messenger v2 Server +================================== + +This service is only available to cPanel servers running Apache. It utilises +the existing Apache service to provide the message as well as RECAPTCHA +unblocking. It is enabled through the MESSENGERV2 option. + +The server must be running Apache v2.4 and using cPanel's EasyApache v4. + +HTML and HTTPS Messenger v3 Server +================================== + +This service is available to servers running Apache or Litespeed/Openlitespeed. +It utilises the existing web server service to provide the message as well as +RECAPTCHA unblocking. It is enabled through the MESSENGERV3 option. + +The web server configuration is created in /var/lib/csf/csf.conf using the +following templates in /usr/local/csf/tpl/: + +apache.main.txt +apache.http.txt +apache.https.txt + +litespeed.main.txt +litespeed.http.txt +litespeed.https.txt + +*.main.txt can contain any web server directives required for the service to +function. +*.http.txt contains the configuration to offer the HTTP service +*.https.txt contains the configuration to offer the HTTPS service. In this file +the virtualhost container is created for each domain served with a certificate +on the server. + +These templates are not overwritten during a csf upgrade. + +PHP is needed to display the MESSENGER web files (see following). This is +controlled by the MESSENGERV3PHPHANDLER setting. + +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 under the MESSENGER_USER account. This line will be included +within each MESSENGER VirtualHost container. This will replace the +[MESSENGERV3PHPHANDLER] line from the csf webserver template files. + +Messenger v2 and v3 +=================== + +For the service to work, the Messenger User MUST have a specific directory +structure. This will be created by the script if it does not exist so long as +the user has been created with a home directory. The structure needs to mimic +the standard web server setup, e.g. using "csf" as the user: + +/home/csf/ (Owner csf:csf, Permissions 711) +/home/csf/public_html/ (Owner csf:nobody, Permissions 711) + +lfd will populate this structure with the following files: + +/home/csf/public_html/.htaccess +/home/csf/public_html/index.php + +If RECAPTCHA_* is enabled these files will be created if they do not already +exist: + +/home/csf/recaptcha.php +/home/csf/public_html/index.php +/home/csf/en.php + +The HTML and HTTPS index file is created from (respectively): +/etc/csf/messenger/index.php +/etc/csf/messenger/index.recaptcha.php +/etc/csf/messenger/en.php + +You should NOT modify the templates in /etc/csf/messenger/ as they will be +overwritten when csf upgrades. Instead modify the files within /home/csf/. + +Each time lfd is restarted a check is made of the preceding structure and any +missing files are recreated. This process also creates the configuration file +for Apache in /etc/apache2/conf.d/csf.messenger.conf and restarts httpd. + +/etc/apache2/conf.d/csf.messenger.conf contains all the VirtualHost directives +to serve the MESSENGERV2 services. + +Translation of /home/csf/en.php is possible by creating the appropriate +[abbr].php file. + +The HTML and HTTPS server ports should NOT be added to the TCP_IN list. + +As Apache is handling all requests for HTML and HTTPS connections, all +scripting for the service is provided by the files in /home/csf/public_html/ +which allows the use of PHP and CGI scripts. + + +15. Block Reporting +################### + +lfd can run an external script when it performs and IP address block following +for example a login failure. This is done by setting the configuration variable +BLOCK_REPORT to a script that must be executable. The following parameters are +passed the the script as arguments: + +ARG 1 = IP Address # The IP address or CIDR being blocked +ARG 2 = ports # Port, comma separated list or * for all ports +ARG 3 = permanent # 0=temporary block, 1=permanent block +ARG 4 = inout # Direction of block: in, out or inout +ARG 5 = timeout # If a temporary block, TTL in seconds, otherwise 0 +ARG 6 = message # Message containing reason for block +ARG 7 = logs # The logs lines that triggered the block (will contain + # line feeds between each log line) +ARG 8 = trigger # The configuration settings triggered + +lfd launches the BLOCK_REPORT in a forked process which terminates after 10 +seconds if not completed by then. It runs under the root account, so great care +should be exercised with regard to security of the BLOCK_REPORT script. + +To also run an external script when a temporary block is unblocked by lfd. +UNBLOCK_REPORT can be the full path of the external script which must be +executable. The following parameters are passed the the script as arguments: + +ARG 1 = IP Address # The IP address or CIDR being blocked +ARG 2 = port* # Port, there could be multiple unblocks for each IP + +[*] If a port was specified in the initial block. + +16. 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. + +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. + +By default ipt_recent tracks only the last 100 IP addresses. The tracked IP +addresses can be viewed in /proc/net/ipt_recent/* where the port number is the +filename. + +Syntax for the PORTFLOOD setting: + +PORTFLOOD is a comma separated list of: +port;protocol;hit count*;interval seconds + +So, a setting of PORTFLOOD = "22;tcp;5;300,80;tcp;20;5" means: + +1. If more than 5 connections to tcp port 22 within 300 seconds, then block +that IP address from port 22 for at least 300 seconds after the last packet is +seen, i.e. there must be a "quiet" period of 300 seconds before the block is +lifted + +2. If more than 20 connections to tcp port 80 within 5 seconds, then block +that IP address from port 80 for at least 5 seconds after the last packet is +seen, i.e. there must be a "quiet" period of 5 seconds before the block is +lifted + +More information about the ipt_recent module can be found in the iptables man +page and at http://snowman.net/projects/ipt_recent/ + +Note: Blocked IP addresses do not appear in any of the iptables chains when +using this module. You must manipulate the /proc/net/ipt_recent/* files as per +the module documentation to view and remove IP addresses that are currently +blocked if the blocks have not yet expired. + +Restarting csf resets the ipt_recent tables and removes all of its blocks. + +Note: There are some restrictions when using ipt_recent: + +1. By default it only tracks 100 addresses per table (we try and increase this +to 1000 via modprobe) + +2. By default it only counts 20 packets per address remembered + +*This means that you need to keep the hit count to below 20. + + +17. External Pre- and Post- Scripts +################################### + +External commands (e.g. iptables rules not covered by csf) can be run before +and/or after csf sets up the iptables chains and rules. + +1. To run external commands before csf configures iptables create the file: + +/usr/local/csf/bin/csfpre.sh + +Set that file as executable and add an appropriate shebang interpreter line and +then whatever external commands you wish to execute. + +For example: + +#!/bin/sh +/some/path/to/binary -a -b -c etc + +Then chmod +x /usr/local/csf/bin/csfpre.sh + +2. To run external commands after csf configures iptables create the file: + +/usr/local/csf/bin/csfpost.sh + +Set that file as executable and add an appropriate shebang interpreter line and +then whatever external commands you wish to execute. + + +Note: The scripts can alternatively be placed in /etc/csf/. If a script is found in +both locations (/etc/csf/ and /usr/local/csf/bin/) then only the script in +/usr/local/csf/bin/ will be executed. + +csfpre.sh/csfpost.sh are run directly. 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 them run. + +Note: While csf runs the script with a preset PATH, you MUST use the full path +to any binaries that you execute within these scripts to ensure they are run +correctly + + +18. lfd Clustering +################## + +This 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 + +In the configuration there are two comma separated lists of IP addresses: + +CLUSTER_SENDTO = "" +CLUSTER_RECVFROM = "" + +Note: Do not use spaces in these lists + +If you want all members of the lfd cluster to send block notifications to each +other then both settings should be them same. You also need to enable +CLUSTER_BLOCK (enabled by default) for lfd to automatically send blocks to all +members in CLUSTER_SENDTO. + +However, you can also set up a cluster such that some members only provide +notifications to others and do not accept blocks from others. For example, you +may have a cluster of servers that includes one that hosts a support desk that +you do not want to block clients from accessing. In such an example you might +want to exclude the support desk server from the CLUSTER_SENDTO list, but +include it in the CLUSTER_RECVFROM list. + +The option CLUSTER_MASTER is the IP address of the master node in the cluster +allowed to send CLUSTER_CONFIG changes to servers listed in the local +CLUSTER_SENDTO list. Only cluster members that have CLUSTER_MASTER set to this +IP address will accept CLUSTER_CONFIG changes. + +There is another option, CLUSTER_NAT that should be used if the IP address of +the server does not appear in ip/ifconfig, for example if it is a NAT +configuration. If this is the case, add the IP address of the server that this +configuration is on and used in CLUSTER_SENDTO/CLUSTER_RECVFROM to CLUSTER_NAT. + +CLUSTER_LOCALADDR can be set if you do not want to use the servers main IP, +i.e. the first one listed via 0.0.0.0. + +The CLUSTER_PORT must be set to the same port on all servers. The port should +NOT be opened in TCP_IN or TCP_OUT as csf will automatically add appropriate in +and out bound rules to allow communication between cluster members. + +The CLUSTER_KEY is a secret key used to encrypt cluster communications using +the Blowfish algorithm. It should be between 8 and 56 ASCII characters long, +longer is better, and must be the same on all members of the cluster. + +This key must be kept secret! + +When blocks are sent around the cluster they will maintain their originals +parameters, e.g. permanent/temporary, direction (in/out), ports, etc. All +blocks are traded except for LT_POP3D and LT_IMAPD. + +The cluster uses 10 second timeouts in its communications, if the timeout is +reached then that cluster members notification will be lost. + +Note: You must restart csf and then lfd after making any CLUSTER_* changes + +lfd Cluster CLI and UI +====================== + +See csf --help for the list of new CLI commands. Additional options will +automatically become available in the UI once CLUSTER_SENDTO has been +configured. + +Only cluster members listed in CLUSTER_RECVFROM can send out requests to those +members listed in CLUSTER_SENDTO. + +Only the server listed in CLUSTER_MASTER will be accepted as the source of +CLUSTER_CONFIG configuration option requests, such as: +--cconfig, --cfile, --crestart + +The CLI options --cfile and --cfiler allow you to synchronise csf configuration +files throughout a cluster from the CLUSTER_MASTER server. + +There is currently only provision for permanent simple IP denies and allows +from the CLI (i.e. not Allow/Deny Filters). + +The cluster PING sends a ping to each CLUSTER_SENDTO member which will report +the request in their respective lfd.log files. This is intended as a test to +confirm that cluster communications are functioning. + +The options to change the configuration option in csf.conf in cluster members +should be used with caution to ensure that member specific options are not +overwritten. The intention of the two options is that the --cconfig option be +used if multiple changes are required and the final request is a --cconfigr to +restart csf and lfd to effect the requested changes immediately. + + +A Note on lfd Cluster Security +============================== + +The clustering option is undoubtedly powerful in allowing servers to +pre-emptively block access attempts as one server is hit before the attack can +spread to other members of the cluster. + +This communication, however, does introduce a security risk. Since +communications are made over the network, they are open to interception. Also, +there is nothing to stop any local user from accessing the network port and +sending data to it, though it will be discarded unless properly encrypted[*]. + +There are security measures implemented to help mitigate attacks: + +1. csf constructs iptables rules such that only cluster members can communicate +over the cluster port with each other + +2. The clustered servers will only accept data from connections from IPs listed +in CLUSTER_RECVFROM or CLUSTER_MASTER + +3. [*]All communications are encrypted using the Blowfish symmetric block cipher +through a Pure Perl cpan module using the Cipher Block Chaining module and the +configured CLUSTER_KEY + +4. CLUSTER_CONFIG set to 0 prevents the processing of configuration option +requests + +5. Only CLUSTER_MASTER will be accepted as the source of CLUSTER_CONFIG +configuration option requests + +Should the configured secret key (passphrase) be compromised or guessed or a +flaw found in the encryption modules or their implementation in csf, a +malicious connection could reconfigure the csf firewall and then leverage a +local or remote root escalation. This should be considered if you decide to use +this option. + +THERE ARE NO GUARANTEES OR WARRANTIES PROVIDED THAT THIS FACILITY IS SECURE AND +ANY DAMAGE ARISING FROM THE EXPLOITATION OF THIS OPTION IS ENTIRELY AT YOUR OWN +RISK. + + +19. Port Knocking +################# + +This option configures iptables to offer port knocking to open sensitive ports +based on a sequence of knocked ports for the connecting IP address. + +For mor information on the idea of port knocking see: +http://www.portknocking.org/ + +The feature requires that you list a random selection of unused ports (at least +3) with a timeout. The ports you choose must not be in use and not appear in +TCP_IN (UDP_IN for udp packets). The port to be opened must also not appear in +TCP_IN (UDP_IN for udp packets). + +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. + +By default ipt_recent tracks only the last 100 IP addresses. The tracked IP +addresses can be viewed in /proc/net/ipt_recent/* + +Syntax for the PORTKNOCKING setting: + +PORTKNOCKING is a comma separated list of: +openport;protocol;timeout;kport1;kport2;kport3[...;kportN] + +So, a setting of PORTKNOCKING = "22;TCP;20;100;200;300;400" means: + +Open Port 22 TCP for 20 seconds to the connecting IP address to new connections +once ports 100, 200, 300 and 400 have been accessed (i.e. knocked with a SYN +packet) each knock being less than 20 seconds apart. + +Access to port 22 remains active after 20 seconds until the connection is +dropped, however new connections will not be allowed. + +More information about the ipt_recent module can be found in the iptables man +page and at http://snowman.net/projects/ipt_recent/ + +Note: IP addresses do not appear in any of the iptables chains when using this +module. You must view the /proc/net/ipt_recent/* files as per the module +documentation to view IP addresses in the various stages of the knock. + +Restarting csf resets the ipt_recent tables and removes all of the knocks. + + +20. Connection Limit Protection +############################### + +This option configures iptables to offer 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 new +concurrent 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. + +Also, although included in some older versions or RedHat/CentOS, it was only +actually available from v5.3+ + +The protection can only be applied to the TCP protocol. + +Syntax for the CONNLIMIT setting: + +CONNLIMIT is a comma separated list of: +port;limit + +So, a setting of CONNLIMIT = "22;5,80;20" means: + +1. Only allow up to 5 concurrent new connections to port 22 per IP address + +2. Only allow up to 20 concurrent new connections to port 80 per IP address + +Note: Existing connections are not included in the count, only new SYN packets, +i.e. new connections + +Note: Run /etc/csf/csftest.pl to check whether this option will function on the +server + + +21. Port/IP address Redirection +############################### + +This feature uses the file /etc/csf/csf.redirect which 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: +*|666|*|25|tcp +192.168.254.60|666|*|25|tcp +192.168.254.4|666|*|25|tcp + +Where a port is specified it cannot be a range, only a single port. + +All redirections to another IP address will always appear on the destination +server with the source of this server, not the originating IP address. + +This feature is not intended to be used for routing, NAT, VPN, etc tasks + +Note: /proc/sys/net/ipv4/ip_forward must be set to 1 for DNAT connections to +work. csf will set this where it can, but if the kernel value cannot be set +then the DNAT redirection many not work. + + +22. Integrated User Interface Feature +##################################### + +Integrated User Interface. This feature provides a HTML UI to the features of +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: + + 1. An SSL connection is required + 2. Separate ban and allow files are provided to only allow access to listed + IP addresses + 3. Local IP addresses cannot connect to the UI (i.e. all IP addresses + configured on the server NICs) + 4. Unique sessions, session timeouts, session cookies and browser headers are + used to identify and restrict active sessions + +Requirements: + + 1. openssl + 2. Perl modules: Net::SSLeay, IO::Socket::SSL and dependent modules + 4. SSL keys + 5. Entries in /etc/csf/ui/ui.allow + +The SSL server uses the following files: + + SSL Key goes into /etc/csf/ui/server.key + SSL Certificate goes into /etc/csf/ui/server.crt + +Preferably, real CA signed certificates should be used. You can use an +existing domain and cert for accessing the UI by populating the two files +mentioned. If the cert has a ca bundle, it should be appended to the server.crt +file. lfd must be restarted after making any changes: +http://httpd.apache.org/docs/current/ssl/ssl_faq.html#realcert + +Alternatively, you could generate your own self-signed certificate: +http://httpd.apache.org/docs/current/ssl/ssl_faq.html#selfcert + +Any keys used must have their pass-phrase removed: +http://httpd.apache.org/docs/current/ssl/ssl_faq.html#removepassphrase + +The login URL should use the domain you have listed in the self-signed cert: +https://: + +For example: https://www.somedomain.com:6666 + +Your browser must accept session cookies to gain access. + +UI_ALLOW is enabled by default, so IP addresses (or CIDRs) allowed to use this +UI must be listed in /etc/csf/ui/ui.allow before trying to connect to the UI. + +Only IP addresses can be listed/used in /etc/csf/ui/ui.ban - this file should +only be used by the UI to prevent login. Use csf blocks to prevent access to +the configured port and only use Advanced Allow/Deny Filters for access, i.e. +do not list the port in TCP_IN. + +Logging for UI events are logged to the lfd /var/log/lfd.log file. Check this +file if you are unable to access the UI. + +Required Perl Modules: + + For example, on Debian v6 the perl modules can be installed using: + + apt-get install libio-socket-ssl-perl libcrypt-ssleay-perl \ + libnet-libidn-perl libio-socket-inet6-perl libsocket6-perl + + For example, on CentOS v6 the perl modules can be installed using: + + yum install perl-IO-Socket-SSL.noarch perl-Net-SSLeay perl-Net-LibIDN \ + perl-IO-Socket-INET6 perl-Socket6 + + +23. IP Block Lists +################## + +This feature allows csf/lfd to periodically download lists of IP addresses and +CIDRs from pubished block or black lists. It is controlled by the file: +/etc/csf/csf.blocklists + +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 thsese lists are very long (thousands of IP addresses) and +could cause serious network and/or performance issues, 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. + + +24. Mitigating issues with syslog/rsyslog logs (RESTRICT_SYSLOG) +############################################## + +Unfortunately, it is trivial for end-users and scripts run by end-users to +spoof log lines that appear identical to any log line reported in logs +maintained by syslog/rsyslog. You can identify these logs by looking in +/etc/syslog.conf or /etc/rsyslog.conf + +This means that anyone on the server can maliciously trigger applications that +monitor these logs, such as lfd does for the following options: + +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 ST_ENABLE SYSLOG_CHECK LOGSCANNER CUSTOM*_LOG + +A malicious user could use this issue to trigger confusing emails regarding +both successful and failed login attempts, kernel log lines (including iptables +log lines) etc. Unfortunately, there is very little that can be done about this +as syslog/rsyslog has no security framework. Some attempt was made in newer +versions of rsyslog, but this version is not available in the current versions +used by RedHat/CentOS v6. It also has to be enabled and can will have adverse +effects on utilities that expect a certain format for the log lines. + +To mitigate spoofing attempts we recommend the following, if you are willing to +accept the consequences of spoofed log lines: + +1. We recommend setting RESTRICT_SYSLOG to "3" for use with option +RESTRICT_SYSLOG_GROUP to restrict access to the syslog/rsyslog unix socket(s) + +2. Go through the options above ensuring that only those that you need are +enabled + +3. Ensure that DENY_IP_LIMIT and DENY_TEMP_IP_LIMIT are set reasonably low (for +example, 200). This will limit attempts to block large numbers of IP addresses + +4. Ensure that administrator/support IP addresses are listed in +/etc/csf/csf.allow and perhaps /etc/csf/csf.ignore. This will prevent malicious +blocking from denying you access to the server + +5. To confirm successful logins to SSH, use the "last" utility from the root +shell, e.g.: + +last -da + +6. Regularly check the server and user data for exploits, old vulnerable +applications and out of date OS applications + +7. Consider carefully any application that you use that centralises actions and +syslog/rsyslog logs and the implications of spoofed log lines + +8. Consider the implications of this overall issue on applications and scripts +other than csf/lfd that use the affected log files + +9. Do not enable syslog/rsyslog reception via UDP/TCP ports + +10. For CloudLinux clients utilizing CageFS this can be prevented by limiting +access to /dev/log inside CageFS. +For that remove file: /etc/rsyslog.d/schroot.conf +Or remove this line from that file: +$AddUnixListenSocket /usr/share/cagefs-skeleton/dev/log + +That will prevent end user's access to /dev/log, preventing them from spoofing. +However, this does also break cron job logging. + + +25. Exim SMTP AUTH Restriction +############################## + +The option SMTPAUTH_RESTRICT will only allow SMTP AUTH to be advertised to the +IP addresses listed in /etc/csf/csf.smtpauth plus the localhost IP addresses. + +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, the localhost IP addresses, plus any countries +listed in CC_ALLOW_SMTPAUTH + +To make this option work you MUST make the following modifications to your +exim.conf: + + +On cPanel servers you can do this by: +===================================== + +1. Navigate to WHM > Exim Configuration Manager > Advanced Editor + +2. Search within the window and ensure that "auth_advertise_hosts" has not been + set + +3. Scroll down and click "Add additional configuration setting" + +4. From the drop-down box select "auth_advertise_hosts" + +5. In the input box after the = sign add the following on one line: + +${if match_ip{$sender_host_address}{iplsearch;/etc/exim.smtpauth}{*}{}} + +6. Scroll to the bottom and click "Save" + +7. That should be all that is required after having made any necessary changes + within csf.conf and restarting csf and then lfd + +8. Be sure to test extensively to ensure the option works as expected + +To reverse this change: + +1. Navigate to WHM > Exim Configuration Manager > Advanced Editor + +2. Search within the window for "auth_advertise_hosts" + +3. Click the wastebasket icon next to the option (if there is no wastebasket + you should be able to change the setting to * to advertise to all IP's) + +4. Scroll to the bottom and click "Save" + +5. Disable SMTPAUTH_RESTRICT and CC_ALLOW_SMTPAUTH in csf.conf and then restart + csf and then lfd + + +Alternatively, on cPanel: +========================= + +1. Edit /etc/exim.conf.local and add the following line to an @CONFIG@ section + all on one line: + +auth_advertise_hosts = ${if match_ip{$sender_host_address}{iplsearch;/etc/exim.smtpauth}{*}{}} + +2. Rebuild the exim configuration: + +/scripts/buildeximconf +service exim restart + +3. Be sure to test extensively to ensure the option works as expected + + +On non-cPanel platforms: +======================== + +1. Modify your active exim.conf and add the following as a single line near the + top all on one line: + +auth_advertise_hosts = ${if match_ip{$sender_host_address}{iplsearch;/etc/exim.smtpauth}{*}{}} + +2. Restart exim + +3. Be sure to test extensively to ensure the option works as expected + + +26. UI Skinning and Mobile View +############################### + +The csf UI provided through cPanel, DirectAdmin, Webmin and the integrated UI +via lfd, all user the Bootstrap and jQuery frameworks. Additional styling is +added to complement the frameworks and the UI flow. + +If you want to make changes to the styling or add jQuery or JavaScript code you +can create: + +1. A text file /etc/csf/csf.header which will be included in each of +the UI pages before the closing tag + +2. A text file /etc/csf/csf.body which will be included in each of the UI +pages after the opening tag[*] + +3. A text file /etc/csf/csf.footer which will be included in each of the UI +pages before the closing tag + +The html tag will also have a data-post field containing the internal action +being performed by the UI. + +You can also make additions to the and tags by creating +/etc/csf/csf.htmltag and /etc/csf/csf.bodytag respectively[*]. Additions made +in these files MUST all be on a single line at the top of the file, anything +else will be ignored. The text will then be placed within the respective tag, +e.g. if you want you would put the following on a +single line in /etc/csf/csf.bodytag: +data-name='result' + +[*] This functionality is ONLY available on webmin servers + +The Mobile View feature has a breakpoint of 600px which will initiate the full +browser subset of UI features. This may mean breaking out of framesets in some +control panels, so a return to the main control panel window is included. Also +switching back to the Desktop view will remain in the full browser display. + +If you switch to the Mobile View and then switch to main control panel window +further accesses to the UI will always default to the Mobile View. If you +switch back after returning to the Desktop View, subsequent access will default +to that view. This reverts back to the default breakpoint behaviour in new +browser sessions as the system uses session cookies to keep track of the chosen +view which are reset one browser shutdown. + +There are options in csf.conf that control the behaviour of these options under +STYLE_*. Any styling changes MUST respect these options. + +Note: We do NOT recommend reformatting the UI output as any changes in the core +code may not be reflected in the user experience and can break the product. +Only style changes should be made. + + +27. 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. + +There are several restrictions to using this feature: + +1. All lfd blocks will be temporary blocks so that csf/lfd can keep blocks in + sync with CloudFlare + +2. Automatic blocks via lfd are limited to LF_MODSEC and LF_CXS triggers as + only through these can the domain name be determined. Any users that own + domains that are involved in the trigger will get a block in their + CloudFlare Firewall. Additionally, any users with the special case "any" + will also get blocks + +3. The temporary/permanent config of the lfd settings are ignored and CF_TEMP + is used instead + +4. LF_TRIGGER must not be used, the feature will not work with it enabled + +5. mod_cloudflare or similar must be used to report real IP in the Apache logs + +6. URLGET must be set to 2 (i.e. LWP) must be used + +7. If PERMBLOCK is used, the last tempblock will remain and never be cleared. + So any CloudFlare Firewall entries must be manually cleared in CloudFlare + or via CLI + +8. There are restrictions imposed by CloudFlare to the number of rules that + can be created depending on the type of account used. See + https://goo.gl/ssGu7v for more information + +9. When restarting csf, any old temporary blocks will still be created for lfd + to clear when it restarts + +10. All interaction with CloudFlare is at User-level, not Zone-level + +11. If using the CloudFlare cPanel user plugin, it must be v7+ + +CF_TEMP should be configured taking into account the maximum number of rules +that the CloudFlare account allows: https://goo.gl/ssGu7v + +All CloudFlare users for the domains that are involved in LF_MODSEC and +LF_CXS triggers will have a CloudFlare rule added. Any CloudFlare account +configured to use the special case "any" field value in csf.cloudflare will +have a CloudFlare rule added regardless of domain. + +NOTE: You should always list the CloudFlare IP addresses in /etc/csf/csf.ignore +to prevent them from being blocked by lfd from https://www.cloudflare.com/ips/ + + +CLI commands +============ + +There are also accompanying csf CLI commands available (see man) to interact +with the Cloudflare firewall. + +Enabling CF_ENABLE enables two CloudFlare buttons in the UI in the "Other" +section that mirror the CLI commands. + +1. Using the CLI commands all, block, challenge or whitelist rules in the +provided users CloudFlare firewall can be listed, e.g.: + +csf --cloudflare list all [user1,user2,...] + +2. Block, challenge and whitelist rules can be added for IPs to the provided +users CloudFlare firewall, e.g.: + +csf --cloudflare add challenge 11.22.33.44 [user1,user2,...] + +Note: These rules are NOT cleared by lfd and do NOT create an equivalent +iptables rule in csf) + +3. Rules can be deleted for IPs to the provided users CloudFlare firewall, +e.g.: + +csf --cloudflare del 11.22.33.44 [domain,domain2,...] + +Note: These rules are NOT cleared in csf if they exist + +4. Domains can also be used instead of users, or a mixture of both e.g.: + +csf --cloudflare list all [user,user2,domain,...] + +5. IPs can be added both the users CloudFlare firewall and to csf as temporary +allow or deny, e.g.: + +csf --cloudflare tempadd deny 11.22.33.44 [user1,user2,...] + +Note: This applies the allow/deny for the IP address in csf for CF_TEMP seconds +as well as the users CloudFlare Firewall. Once the temporary entry expires lfd +removes the IP address from both csf (as normal) as well as the users +CloudFlare Firewall. + +Note: Any CloudFlare account configured to use the special case "any" field +value in csf.cloudflare will also have a CloudFlare rule added. + +Note: In the above IP addresses are used as the target for each rule. However, +the 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. + +6. To manually remove an IP block that was blocked via CF_ENABLE in lfd or by +using "tempadd" use the normal csf temp CLI commands. This will remove the +rules from both iptables and the users CloudFlare firewall, e.g.: + +csf --tr 44.33.22.11 + + +28. InterWorx +############# + +InterWorx integration is available for csf. The installation makes changes to +the underlying InterWorx installation due to its current dependence on APF. To +cater for this, installing csf will replace /etc/apf/apf with a stub script +that redirects commands to csf. The script is then chattr +ia to prevent it +being overwritten. + +Note: None of the apf conf files are used and are ignored by csf. + +The Firewall UI option in NodeWorx should now not be used and any changes made +there will not be reflected in iptables. + +There is a UI option under "ConfigServer Services" for "ConfigServer Firewall & +Security" that should now be used. + +The installation will also replace the Firewall page in NodeWorx with a dummy +page stating that csf should be used instead. lfd will replace the page upon +restart incase of upgrades to InterWorx. If you want to disable this behaviour, +create an empty file as follows: + +touch /etc/cxs/interworx.firewall + +The InterWorx plugin for csf is auto-enabled. Enabling or Disabling the +InterWorx plugin has no effect on csf itself, only the UI plugin presence. + +NOTE: Unless you have configured a root forwarder, you should edit the csf +configuration settings in /etc/csf/csf.conf or via the UI and set LF_ALERT_TO +to a suitable email address. After making any changes, restart csf and then +lfd. + + +28. CentOS Web Panel (CWP) +########################## + +CWP integration is available for csf. Since CWP already has some custom +modifications, these have been taken into account. To access the now inbuilt UI +in CWP, there is a new menu option in CWP > ConfigServer Scripts > ConfigServer +Firewall. + +There is now an option in /etc/csf/csf.conf for LF_CWP for login failure +detection. However, this WILL NOT work with the default CWP installation as +there is a custom entry in /etc/csf/regex.custom.pm. The now official detection +will be ignored while this is in place. + +If you want to use the now inbuilt detection you must edit +/etc/csf/regex.custom.pm and remove the 3 lines that comprise the custom entry +and then restart lfd. diff --git a/src/redux/recaptcha.txt b/src/redux/recaptcha.txt new file mode 100644 index 000000000..dedf94b6d --- /dev/null +++ b/src/redux/recaptcha.txt @@ -0,0 +1,8 @@ +From: root +To: root +Subject: lfd on [hostname]: recaptcha [ip] + +Time: [time] +IP: [ip] + +Recaptcha unblock of [ip] on [host] requested diff --git a/src/redux/regex.custom.pm b/src/redux/regex.custom.pm new file mode 100644 index 000000000..ea0e735ad --- /dev/null +++ b/src/redux/regex.custom.pm @@ -0,0 +1,50 @@ +#!/usr/bin/perl +############################################################################### +# Copyright 2006-2023, Way to the Web Limited +# URL: http://www.configserver.com +# Email: sales@waytotheweb.com +############################################################################### + +sub custom_line { + my $line = shift; + my $lgfile = shift; + +# Do not edit before this point +############################################################################### +# +# Custom regex matching can be added to this file without it being overwritten +# by csf upgrades. The format is slightly different to regex.pm to cater for +# additional parameters. You need to specify the log file that needs to be +# scanned for log line matches in csf.conf under CUSTOMx_LOG. You can scan up +# to 9 custom logs (CUSTOM1_LOG .. CUSTOM9_LOG) +# +# The regex matches in this file will supercede the matches in regex.pm +# +# Example: +# if (($globlogs{CUSTOM1_LOG}{$lgfile}) and ($line =~ /^\S+\s+\d+\s+\S+ \S+ pure-ftpd: \(\?\@(\d+\.\d+\.\d+\.\d+)\) \[WARNING\] Authentication failed for user/)) { +# return ("Failed myftpmatch login from",$1,"myftpmatch","5","20,21","1","0"); +# } +# +# The return values from this example are as follows: +# +# "Failed myftpmatch login from" = text for custom failure message +# $1 = the offending IP address +# "myftpmatch" = a unique identifier for this custom rule, must be alphanumeric and have no spaces +# "5" = the trigger level for blocking +# "20,21" = the ports to block the IP from in a comma separated list, only used if LF_SELECT enabled. To specify the protocol use 53;udp,53;tcp +# "1" = n/temporary (n = number of seconds to temporarily block) or 1/permanant IP block, only used if LF_TRIGGER is disabled +# "0" = whether to trigger Cloudflare block if CF_ENABLE is set. "0" = disable, "1" = enable + + + +# If the matches in this file are not syntactically correct for perl then lfd +# will fail with an error. You are responsible for the security of any regex +# expressions you use. Remember that log file spoofing can exploit poorly +# constructed regex's +############################################################################### +# Do not edit beyond this point + + return 0; +} + +1; diff --git a/src/redux/regex.txt b/src/redux/regex.txt new file mode 100644 index 000000000..45d0e8dd9 --- /dev/null +++ b/src/redux/regex.txt @@ -0,0 +1,143 @@ +Dec 15 10:55:18 pegasus kernel: Firewall: *UDP_IN Blocked* IN=eth1 OUT= MAC=00:1a:4b:de:41:02:00:15:62:4a:39:80:08:00 SRC=7.6.5.4 DST=1.2.3.4 LEN=52 TOS=0x00 PREC=0x00 TTL=118 ID=42240 DF PROTO=UDP SPT=3708 DPT=53 WINDOW=17520 RES=0x00 ACK URGP=0 + +Apr 30 16:41:23 worg sshd[31378]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=2001:0:5ef5:73ba:204a:1a20:a83d:337c user=root +Apr 30 16:41:25 worg sshd[31378]: Failed password for root from 2604:a880:0800:0010:0000:0000:0970:a001 port 52182 ssh2 + +193.168.254.89 - webumake [08/11/2014:20:12:19 -0000] "POST /login/?login_only=1 HTTP/1.1" FAILED LOGIN cpaneld: access denied for root, reseller, and user password + +Jun 15 17:19:38 test sshd[1]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=196.201.78.12 user=test + +Dec 1 03:27:28 mx sshd[743]: Failed none for mxadmin from 151.99.255.8 port 4321 ssh2 + +Sep 15 02:00:30 sol sshd[16364]: Failed password for invalid user test from ::ffff:61.167.1.1 port 53382 ssh2 +Oct 15 07:41:16 localhost sshd[15184]: Failed password for bob from 21.2.3.6 port 41501 ssh2 +Nov 4 18:40:28 localhost sshd[17588]: Failed password for illegal user admin from 210.127.243.85 + +May 11 22:08:34 salle sshd[5543]: Failed keyboard-interactive/pam for invalid user abdukrahman from 62.206.22.124 port 50525 ssh2 +May 11 22:08:34 salle sshd[5543]: Failed keyboard-interactive for abdukrahman from 62.206.22.124 port 50525 ssh2 + +Jan 27 04:02:48 localhost sshd[23914]: Invalid user jordan from 67.15.40.2 + +Nov 4 18:40:28 localhost sshd[12424]: User root from 2607:f0d0:1002:81::2 not allowed because not listed in AllowUsers +Nov 4 18:40:28 localhost sshd[12424]: User root from 1.2.3.4 not allowed because not listed in AllowUsers + +Nov 4 18:40:28 localhost sshd[17588]: Illegal user admin from 210.127.243.86 +Nov 4 18:40:28 localhost sshd[17588]: Illegal user admin from 210.127.243.87 +Nov 4 18:40:28 localhost sshd[17588]: Illegal user admin from 210.127.243.88 +Nov 4 18:40:28 localhost sshd[17588]: Illegal user admin from 210.127.243.89 +Nov 4 18:40:28 localhost sshd[17588]: Illegal user admin from 210.127.243.80 + +Jul 6 14:57:00 tux sshd[19136]: error: PAM: Authentication failure for andrew from 1.2.3.4 + +Apr 23 21:57:40 dns2 pop3d: LOGIN FAILED, user=info@mydomain.com, ip=[::ffff:99.2.33.4] +Apr 23 21:57:40 dns2 imapd: LOGIN FAILED, user=info@mydomain.eu, ip=[::ffff:18.22.3.4] + +Nov 25 17:12:15 webmail ipop3d[4920]: Login failed user=mailuser auth=mailuser host=ntserver.domain.com [192.168.0.3] +Nov 25 17:12:15 webmail imapd[4920]: Login failed user=mailuser auth=mailuser host=ntserver.domain.com [192.168.0.3] + +Jan 17 10:45:40 elct dovecot: pop3-login: Aborted login: user=, method=PLAIN, rip=1.2.3.4, lip=127.0.0.1, secured +Jan 17 10:45:40 elct dovecot: imap-login: Aborted login: user=, method=PLAIN, rip=1.2.3.4, lip=127.0.0.1, secured + +Nov 01 06:43:09 pop3-login: Info: Aborted login (auth failed, 1 attempts): user=, method=PLAIN, rip=110.234.127.52, lip=x.x.y.z +Nov 01 06:43:09 imap-login: Info: Aborted login (auth failed, 1 attempts): user=, method=PLAIN, rip=110.234.127.52, lip=x.x.y.z + +[04/Dec/2008 10:55:09] POP3: Invalid password for user joel<_a.t_>company.com. Attempt from IP address 76.235.150.55 +[04/Dec/2008 10:59:36] POP3: User company\joel<_a.t_>kerio.company.com doesn't exist. Attempt from IP address 10.17.28.50 +[04/Dec/2008 10:55:09] IMAP: Invalid password for user joel<_a.t_>company.com. Attempt from IP address 76.235.150.55 +[04/Dec/2008 10:59:36] IMAP: User company\joel<_a.t_>kerio.company.com doesn't exist. Attempt from IP address 10.17.28.50 + +May 1 10:31:48 worg pure-ftpd: (?@2001_0_5ef5_73ba_204a_1a20_a83d_337c) [WARNING] Authentication failed for user [bob] +Mar 28 09:06:31 homer pure-ftpd: (?@1.2.3.4) [WARNING] Authentication failed for user [bosshelp] + +May 31 10:53:14 mail proftpd[15302]: xxxxxxxxxx (2607:f0d0:1002:81::2[2607:f0d0:1002:81::2]) - no such user 'alpha' +May 31 10:53:14 mail proftpd[15302]: xxxxxxxxxx (::ffff:192.168.0.213[::ffff:192.168.0.213]) - no such user 'alpha' +May 31 10:53:14 mail proftpd[15302]: xxxxxxxxxx (::ffff:192.168.0.213[::ffff:192.168.0.213]) - USER alpha: no such user found from ::ffff:192.168.0.213 [::ffff:192.168.0.213] to ::ffff:192.168.0.210:21 +May 31 10:53:14 mail proftpd[15302]: xxxxxxxxxx (::ffff:192.168.0.213[::ffff:192.168.0.213]) - SECURITY VIOLATION +May 31 10:52:54 mail proftpd[15302]: xxxxxxxxxx (::ffff:192.168.0.213[::ffff:192.168.0.213]) - USER lee (Login failed): Incorrect password. +Apr 28 17:21:52 server1.local proftpd[53084] server1.local (118.244.187.123[118.244.187.123]): USER kitchenstewardship: no such user found from 118.244.187.123 [118.244.187.123] to 107.1.17.5:21 + +May 1 12:43:17 vps vsftpd(pam_unix)[11377]: authentication failure; logname= uid=0 euid=0 tty= ruser= rhost=72.232.10.66 user=mysql + +[Sun Apr 25 17:51:52 2014] [error] [client 2607:f0d0:1002:81::2] user lowrian not found: /admin/file_manager.php +[Mon Sep 24 17:48:41 2007] [error] [client 87.113.94.100] user lowrian not found: /admin/file_manager.php +[Thu Feb 03 13:04:23 2005] [error] [client 12.34.56.78] user firstuser: authentication failure for "/svn/!svn/act/74436339-4e10-0930-acb9-a38e2fadb293": Password Mismatch +[Tue Feb 25 15:51:13.383454 2014] [auth_basic:error] [pid 604443] [client 192.168.254.10:16381] AH01618: user bob not found: /pwd/ + +[Tue Feb 25 08:54:26.294882 2014] [access_compat:error] [pid 12873] [client 188.143.234.4:3177] AH01797: client denied by server configuration: /home/conblog/public_html/wp-content/plugins/islidex + +[Tue Feb 25 16:27:36.533596 2014] [:error] [pid 6024] [client 24.238.73.15:35271] File does not exist: /home/webumake/public_html/external.php + +2010/09/09 19:46:46 [error] 5596#560: *3 user "aaa": password mismatch, client: 9.183.126.52, server: myserver, request: "GET /shortlog/d6b56cc4c6d1 HTTP/1.1", host: "myhost" +2012/08/25 10:07:01 [error] 5866#0: *1 no user/password was provided for basic authentication, client: 196.5.5.6, server: localhost, request: "GET /pma HTTP/1.1", host: "localhost:81" 2012/08/25 10:07:04 [error] 5866#0: *1 user "ajfkla" was not found in "/etc/nginx/htpasswd", client: 127.0.0.1, server: localhost, request: "GET /pma HTTP/1.1", host: "localhost:81" +2011/08/31 13:01:19 [error] 6541#0: *5 user "bob" was not found in "/etc/nginx/htpasswd", client: 196.5.5.5, server: myserver, request: "GET / HTTP/1.1", host: "myhost" + +[Sat May 01 10:52:46 2014] [error] [client 94.41.178.204] ModSecurity: Access denied with code 403 (phase 2). Pattern match "indy library" at REQUEST_HEADERS:User-Agent. [file "/usr/local/apache/conf/modsec/20_asl_useragents.conf"] [line "174"] [id "330036"] [rev "1"] [msg "Atomicorp.com - FREE UNSUPPORTED DELAYED FEED - WAF Rules: Suspicious User agent detected"] [severity "CRITICAL"] [hostname "forum.configserver.com"] [uri "/register.php"] [unique_id "S9v57lUNw@sAAFHNRgAAAAAE"] + +[Wed Feb 29 08:25:19 2014] [error] [client 178.137.167.112] ModSecurity: Access denied with code 406 (phase 2). File "/tmp/20140229-082519-T03g71UNwkgAAEH7pVAAAAAO-file-fnVKf3" rejected by the approver script "/etc/cxs/cxscgi.sh": 0 [file "/usr/local/apache/conf/modsec2.user.conf"] [line "6"] [id "1010101"] [severity "CRITICAL"] [hostname "www.kalyr.com"] [uri "/weblog//wp-content/plugins/1-flash-gallery/upload.php"] [unique_id "T03g71UNwkgAAEH7pVAAAAAO"] + +[Tue Jul 23 10:40:41.122319 2014] [:error] [pid 7199] [client 199.168.254.10] ModSecurity: Access denied with code 406 (phase 2). File "/tmp/20140723-104034-Ue5PksCo-jwAABwfei0AAAAA-file-v3XRcU" rejected by the approver script "/etc/cxs/cxscgi.sh": 0 [file "/usr/local/apache/conf/modsec2.user.conf"] [line "4"] [id "1010101"] [severity "CRITICAL"] [hostname "www.webumake.net"] [uri "/uptest/test.php"] [unique_id "Ue5PksCo-jwAABwfei0AAAAA"] + +[Wed Feb 29 09:13:30 2014] [error] [client 216.129.118.139] mod_qos(045): access denied, invalid request line: can't parse uri, c=216.129.118.139, id=T03sOlUNwkgAAFzhznAAAAAK + +May 23 17:26:43 dnsonly webmin[2317]: Invalid login as root from 199.168.254.10 +May 23 17:26:51 dnsonly webmin[2319]: Successful login as root from 199.168.254.10 + +DA: +2014:07:07-11:08:13: '6.6.6.6' 2 failed login attempts. Account 'admin' +2014:05:08-01:40:09: '198.168.0.1' 15 failed login attempt on account 'test' + +Apr 30 13:34:12 server named[3100]: client 2607:f0d0:1002:81::2#3147: update 'configserver.org/IN' denied +Apr 30 13:34:12 server named[3100]: client 66.98.212.33#3147: update 'configserver.org/IN' denied + + +2009-03-25 15:59:33 fixed_login authenticator failed for localhost (domain.com) [1.2.3.4]: 535 Incorrect authentication data (set_id=user@domain.com) + +May 1 11:25:57 server pop3d-ssl: LOGIN, user=sales@waytotheweb.com, ip=[::ffff:82.10.53.229], port=[64420] +May 1 11:25:57 server pop3d-ssl: LOGIN, user=sales@waytotheweb.com, ip=[2607:f0d0:1002:81::10], port=[64420] + +May 1 15:12:59 homer dovecot: pop3-login: Login: user=, method=PLAIN, rip=196.168.254.40, lip=196.168.254.71 + +May 1 15:24:35 homer sshd[7155]: Accepted publickey for root from 192.168.254.4 port 57306 ssh2 +May 1 15:26:09 worg sshd[27196]: Accepted publickey for root from 2001:0:5ef5:73ba:204a:1a20:a83d:337c port 57415 ssh2 + +Apr 14 05:40:32 worg kernel: Firewall: *TCP_IN Blocked* IN=eth1 OUT= MAC=00:30:48:5b:41:6f:00:1a:30:38:90:00:08:00 SRC=60.50.78.146 DST=75.126.194.219 LEN=60 TOS=0x00 PREC=0x00 TTL=51 ID=13875 DF PROTO=TCP SPT=4345 DPT=23 WINDOW=5808 RES=0x00 SYN URGP=0 +Apr 30 16:00:20 worg kernel: Firewall: *TCP6_IN Blocked* IN=eth1 OUT= MAC=00:30:48:5b:41:6f:00:1a:30:38:90:00:86:dd SRC=2001:0000:5ef5:73ba:204a:1a20:a83d:337c DST=2607:f0d0:1002:0081:0000:0000:0000:0002 LEN=72 TC=0 HOPLIMIT=122 FLOWLBL=0 PROTO=TCP SPT=51117 DPT=8822 WINDOW=8192 RES=0x00 SYN URGP=0 + + +Apr 21 16:48:33 homer pure-ftpd: (?@196.168.254.4) [INFO] webumake@webumake.net is now logged in +Apr 21 16:16:29 da proftpd[2817]: da.webumake.net (::ffff:196.168.254.4[::ffff:192.168.254.4]) - USER webumake: Login successful. + + +Sep 11 09:11:47 homer kernel: Knock: *587_IN* IN=eth0 OUT= MAC=08:00:27:c7:3b:e5:00:26:18:ef:37:2e:08:00 SRC=192.168.254.4 DST=192.168.254.71 LEN=52 TOS=0x00 PREC=0x00 TTL=128 ID=28467 DF PROTO=TCP SPT=50756 DPT=587 WINDOW=8192 RES=0x00 SYN URGP=0 + +[Mon Mar 18 11:27:02 2014] [error] [client 5.79.3.49] Caught race condition abuser. attacker: 506, victim: 0 open file owner: 0, open file: /home/config/public_html/build/configserver +[Tue Feb 25 11:17:19.971626 2014] [core:error] [pid 28127] [client 217.40.166.113:34338] Caught race condition abuser. attacker: 542, victim: 0 open file owner: 0, open file: /usr/local/cpanel/img-sys/bg.jpg + +2014-05-24 17:11:09 cwd=/home/webumake/public_html/has space 3 args: /usr/sbin/sendmail -t -i +2014-05-15 10:54:19 1Ucfu7-0007IT-3b H=localhost (starfish.arvixe.com) [127.0.0.1]:48531 Warning: Mail From: 8mm\342\230\272 Network System user: guruayy This message was sent via script. The details are as follows: SCRIPT_FILENAME=/home/guruayy/public_html/live/index.php REQUEST_URI=/index.php?do=/admincp/user/browse/view_pending/page_0/ PWD=/home/guruayy/public_html/live REMOTE_ADDR=70.215.67.177 + + +2014-09-12 03:06:40 SMTP call from (zhuyuan.cn) [222.185.244.195]:59693 dropped: too many syntax or protocol errors (last command was " by 222.222.222.2 with ESMTP") + +Courier IMAP +Mar 10 09:19:32 web3 courier-imapd: LOGIN FAILED, user=user@example.com, ip=[::ffff:68.148.104.146] +Mar 10 11:49:19 web3 courier-pop3d: LOGIN FAILED, user=user@example.com, ip=[::ffff:72.172.109.25] + +Qmail SMTP AUTH +Mar 10 14:17:40 web1 smtp_auth: FAILED: user@example.com - password incorrect from host81-138-18-4.in-addr.btopenworld.com [81.138.18.4] + +Postfix SMTP_AUTH +Mar 11 04:11:24 plesk115 postfix/smtpd[2520]: warning: unknown[192.168.1.113]: SASL PLAIN authentication failed: authentication failure +Mar 11 04:11:24 plesk115 postfix/smtpd[2520]: warning: unknown[192.168.1.113]: SASL LOGIN authentication failed: authentication failure +Sep 21 23:52:03 server01 postfix/smtpd[26732]: warning: dslb-088-073-067-2.pools.arcor-ip.net[88.73.67.12]: SASL LOGIN authentication failed +Feb 11 12:11:34 hostname postfix/smtpd[113557]: warning: trusted[1.2.3.4]: SASL PLAIN authentication failed: authentication failure + + +[18-Sep-2023 11:01:56 +0000]: IMAP Error: Login failed for martynas from 78.62.57.226. AUTHENTICATE PLAIN: Authentication failed. in /var/www/html/roundcubemail-1.0.2/program/lib/Roundcube/rcube_imap.php on line 184 (POST /roundcube/?_task=login?_task=login&_action=login) +[18-Sep-2023 11:02:11 +0000]: IMAP Error: Login failed for jonathan@configserver.com from 78.62.57.226. AUTHENTICATE PLAIN: Authentication failed. in /var/www/html/roundcubemail-1.0.2/program/lib/Roundcube/rcube_imap.php on line 184 (POST /roundcube/?_task=login?_task=login&_action=login) +09/18/2014 11:03:08 [LOGIN_ERROR] jonathan@configserver.com (martynas.it) from 78.62.57.226: Unknown user or password incorrect. +Sep 18 11:03:58:: pma auth user='jonathan_whmcs' status='mysql-denied' ip='78.62.57.226' + + +2014-06-04 17:05:35 dovecot_login authenticator failed for chirpy.configserver.com ([192.168.254.4]) [87.194.204.131]:63622: 535 Incorrect authentication data (set_id=sales@waytotheweb.com) +2014-06-04 17:07:08 [16223] dovecot_plain authenticator failed for chirpy.configserver.com ([192.168.254.4]) [87.194.204.131]:63708 I=[85.13.195.235]:465: 535 Incorrect authentication data (set_id=sales@waytotheweb.com) diff --git a/src/redux/relayalert.txt b/src/redux/relayalert.txt new file mode 100644 index 000000000..da6f8fe1c --- /dev/null +++ b/src/redux/relayalert.txt @@ -0,0 +1,12 @@ +From: root +To: root +Subject: lfd on [hostname]: [check] Alert for [ip] + +Time: [time] +Type: [type] - [ip] +Count: [count] emails relayed +Blocked: [block] + +Sample of the first 10 emails: + +[emails] diff --git a/src/redux/remove_apf_bfd.sh b/src/redux/remove_apf_bfd.sh new file mode 100644 index 000000000..dbd60d5de --- /dev/null +++ b/src/redux/remove_apf_bfd.sh @@ -0,0 +1,22 @@ +#!/bin/sh +echo "Removing apf and/or bfd..." +echo + +apf -f +rm -fv /etc/cron.daily/fw +rm -fv /etc/cron.daily/apf +rm -fv /etc/cron.d/refresh.apf +rm -fv /etc/logrotate.d/apf +rm -fv /var/log/apf* +/sbin/chkconfig apf off +/sbin/chkconfig apf --del +rm -fv /etc/init.d/apf +rm -Rfv /etc/apf + +rm -fv /etc/cron.d/bfd +rm -fv /etc/logrotate.d/bfd +rm -fv /var/log/bfd* +rm -Rfv /usr/local/bfd + +echo +echo "...Done" diff --git a/src/redux/resalert.txt b/src/redux/resalert.txt new file mode 100644 index 000000000..694982ed2 --- /dev/null +++ b/src/redux/resalert.txt @@ -0,0 +1,12 @@ +From: root +To: root +Subject: lfd on [hostname]: Excessive resource usage: [user] ([pid]) + +Time: [time] +Account: [user] +Resource: [resource] +Exceeded: [level] +Executable: [exe] +Command Line: [cmd] +PID: [pid] +Killed: [kill] diff --git a/src/redux/reselleralert.txt b/src/redux/reselleralert.txt new file mode 100644 index 000000000..b1da34188 --- /dev/null +++ b/src/redux/reselleralert.txt @@ -0,0 +1,10 @@ +From: root +To: root +Subject: csf UI on [hostname]: reseller [reseller] - [action] + +Time: [time] +Reseller: [reseller] +Reseller IP: [rip] +Action: [action] [ip] + +[text] diff --git a/src/redux/restricted.txt b/src/redux/restricted.txt new file mode 100644 index 000000000..128d1dfa6 --- /dev/null +++ b/src/redux/restricted.txt @@ -0,0 +1,105 @@ +BIND_LOG +BLOCK_REPORT +CHATTR +CLUSTER_KEY +CLUSTER_LOCALADDR +CLUSTER_MASTER +CLUSTER_PORT +CLUSTER_RECVFROM +CLUSTER_SENDTO +CPANEL_ACCESSLOG +CPANEL_LOG +CURL +CUSTOM1_LOG +CUSTOM2_LOG +CUSTOM3_LOG +CUSTOM4_LOG +CUSTOM5_LOG +CUSTOM6_LOG +CUSTOM7_LOG +CUSTOM8_LOG +CUSTOM9_LOG +DD +DEBUG +DIRECTADMIN +DIRECTADMIN_LOG +DIRECTADMIN_LOG_P +DIRECTADMIN_LOG_R +DIRECTADMIN_LOG_S +FTPD_LOG +GENERIC +GREP +GUNZIP +HOST +HTACCESS_LOG +IFCONFIG +IMAPD_LOG +IP +IP6TABLES +IP6TABLES_RESTORE +IP6TABLES_SAVE +IPSET +IPTABLES +IPTABLES_LOG +IPTABLES_RESTORE +IPTABLES_SAVE +LF_CPANEL_ALERT_ACTION +LF_DIST_ACTION +LF_SCRIPT_ACTION +LS +MD5SUM +MESSENGERV3PHPHANDLER +MESSENGERV3RESTART +MESSENGERV3TEST +MODPROBE +MODSEC_LOG +NETSTAT +OLD_REAPER +POP3D_LOG +PORTS_bind +PORTS_cpanel +PORTS_cxs +PORTS_directadmin +PORTS_eximsyntax +PORTS_ftpd +PORTS_htpasswd +PORTS_imapd +PORTS_mod_qos +PORTS_mod_security +PORTS_pop3d +PORTS_smtpauth +PORTS_sshd +PORTS_suhosin +PORTS_symlink +PORTS_webmin +PS +PT_DELETED_ACTION +PT_LOAD_ACTION +PT_USER_ACTION +RESTRICT_UI +RT_ACTION +SCRIPT_LOG +SENDMAIL +SMTPAUTH_LOG +SMTPRELAY_LOG +SSHD_LOG +ST_DISKW_DD +ST_MYSQL_HOST +ST_MYSQL_PASS +ST_MYSQL_USER +SU_LOG +SUHOSIN_LOG +SYSLOG_LOG +SYSTEMCTL +TAIL +TAR +UI_CSE +UI_CXS +UI_PASS +UI_USER +UNBLOCK_REPORT +UNZIP +VMSTAT +WEBMIN_LOG +WGET +ZGREP diff --git a/src/redux/sanity.txt b/src/redux/sanity.txt new file mode 100644 index 000000000..73d5d6ce5 --- /dev/null +++ b/src/redux/sanity.txt @@ -0,0 +1,232 @@ +AT_ALERT=0-3=2 +AT_DIR=0-1=1 +AT_GID=0-1=1 +AT_INTERVAL=10-3600=60 +AT_NEW=0-1=1 +AT_OLD=0-1=1 +AT_PASSWD=0-1=1 +AT_SHELL=0-1=1 +AT_UID=0-1=1 +AUTO_UPDATES=0-1=1 +CC_INTERVAL=1-31=14 +CC_LOOKUPS=0-4=1 +CC6_LOOKUPS=0-1 +CLUSTER_BLOCK=0-1=1 +CLUSTER_CHILDREN=1-100=10 +CLUSTER_CONFIG=0-1=0 +CONNLIMIT_LOGGING=0-1=0 +CT_BLOCK_TIME=300-86400=1800 +CT_EMAIL_ALERT=0-1=1 +CT_INTERVAL=10-3600=30 +CT_LIMIT=0|10-1000=0 +CT_PERMANENT=0-1=0 +CT_SKIP_TIME_WAIT=0-1=0 +DEBUG=0=0 +DENY_IP_LIMIT=10-1000=200 +DENY_TEMP_IP_LIMIT=10-1000=100 +DNS_STRICT=0-1=0 +DNS_STRICT_NS=0-1=0 +DROP=DROP|TARPIT|REJECT=DROP +DROP_IP_LOGGING=0-1=0 +DROP_LOGGING=0-1=1 +DROP_ONLYRES=0-1=0 +DROP_OUT_LOGGING=0-1=1 +DROP_PF_LOGGING=0-1=0 +DROP_UID_LOGGING=0-1=1 +DYNDNS=0-86400=0 +DYNDNS_IGNORE=0-1=0 +FASTSTART=0-1=1 +GLOBAL_DYNDNS_IGNORE=0-1=0 +GLOBAL_DYNDNS_INTERVAL=60-86400=600 +ICMP_IN=0-1=1 +ICMP_OUT=0-1=1 +IGNORE_ALLOW=0-1=0 +IPV6=0-1=0 +IPV6_ICMP_STRICT=0-1=0 +IPV6_SPI=0-1=1 +LF_APACHE_403=0|60-1000=0 +LF_APACHE_403_PERM=0-604800=3600 +LF_APACHE_404=0|60-1000=0 +LF_APACHE_404_PERM=0-604800=3600 +LF_BIND=0|60-1000=0 +LF_BIND_PERM=0-604800=1 +LF_BLOCKINONLY=0-1=0 +LF_CONSOLE_EMAIL_ALERT=0-1=1 +LF_CPANEL=0-100=5 +LF_CPANEL_ALERT=0-1=1 +LF_CPANEL_PERM=0-604800=1 +LF_CSF=0-1=1 +LF_CXS=0-10=0=0 +LF_CXS_PERM=0-604800=1 +LF_DAEMON=0-1=1 +LF_DIRWATCH=0|30-86400=300 +LF_DIRWATCH_DISABLE=0-1=0 +LF_DIRWATCH_FILE=0|30-86400=0 +LF_DIST_INTERVAL=60-86400=300 +LF_DISTATTACK=0-1=0 +LF_DISTATTACK_UNIQ=2-20=2 +LF_DISTFTP=0-20=0 +LF_DISTFTP_ALERT=0-1=1 +LF_DISTFTP_PERM=0-604800=1 +LF_DISTFTP_UNIQ=2-20=2 +LF_DISTSMTP=0-20=0 +LF_DISTSMTP_ALERT=0-1=1 +LF_DISTSMTP_PERM=0-604800=1 +LF_DISTSMTP_UNIQ=2-20=3 +LF_EMAIL_ALERT=0-1=1 +LF_EXIMSYNTAX=0-100=10 +LF_EXIMSYNTAX_PERM=0-604800=1 +LF_EXPLOIT=0|6-86400=300 +LF_FLUSH=3600-86400=3600 +LF_FTPD=0-100=10 +LF_FTPD_PERM=0-604800=1 +LF_GLOBAL=0|60-604800=0 +LF_HTACCESS=0-100=5 +LF_HTACCESS_PERM=0-604800=1 +LF_IMAPD=0-100=10 +LF_IMAPD_PERM=0-604800=1 +LF_INTEGRITY=0|120-86400=3600 +LF_INTERVAL=60-86400=3600 +LF_IPSET=0-1=1 +LF_LOOKUPS=0-1=1 +LF_MODSEC=0-100=5 +LF_MODSEC_PERM=0-604800=1 +LF_NETBLOCK=0-1=0 +LF_NETBLOCK_ALERT=0-1=1 +LF_NETBLOCK_CLASS=A|B|C=C +LF_NETBLOCK_COUNT=1-255=4 +LF_NETBLOCK_INTERVAL=3600-604800=86400 +LF_PARSE=5-20=5 +LF_PERMBLOCK=0-1=1 +LF_PERMBLOCK_ALERT=0-1=1 +LF_PERMBLOCK_COUNT=1-255=4 +LF_PERMBLOCK_INTERVAL=3600-604800=86400 +LF_POP3D=0-100=10 +LF_POP3D_PERM=0-604800=1 +LF_QOS=0-100=0=0 +LF_QOS_PERM=0-604800=1 +LF_QUEUE_ALERT=0-5000=2000 +LF_QUEUE_INTERVAL=0|30-86400=300 +LF_QUICKSTART=0-1=0 +LF_REPEATBLOCK=0-5=0 +LF_SCRIPT_ALERT=0-1=0 +LF_SCRIPT_LIMIT=0-5000=100 +LF_SCRIPT_PERM=0-1=0 +LF_SELECT=0-1=0 +LF_SMTPAUTH=0-100=5 +LF_SMTPAUTH_PERM=0-604800=1 +LF_SPI=0-1=1 +LF_SPI=0-1=1 +LF_SSH_EMAIL_ALERT=0-1=1 +LF_SSHD=0-100=5 +LF_SSHD_PERM=0-604800=1 +LF_SU_EMAIL_ALERT=0-1=1 +LF_SUHOSIN=0-100=0=0 +LF_SUHOSIN_PERM=0-604800=1 +LF_SYMLINK=0-100=0=0 +LF_SYMLINK_PERM=0-604800=1 +LF_TRIGGER=0-100=0 +LF_TRIGGER_PERM=0-604800=1 +LF_WEBMIN=0-100=0=0 +LF_WEBMIN_EMAIL_ALERT=0-1=1 +LF_WEBMIN_PERM=0-604800=1 +LFDSTART=0-1=0 +LOGFLOOD_ALERT=0-1=0 +LOGSCANNER=0-1=0 +LOGSCANNER_EMPTY=0-1=1 +LOGSCANNER_INTERVAL=hourly|daily|manual=hourly +LOGSCANNER_LINES=1000-100000=5000 +LOGSCANNER_STYLE=1-2=1 +LT_EMAIL_ALERT=0-1=1 +LT_IMAPD=0-180=0 +LT_POP3D=0-180=60 +LT_SKIPPERMBLOCK=0-1=0 +MESSENGER=0-1=0 +MESSENGER_CHILDREN=2-2023=10 +MESSENGER_HTML=1023-65535=8888 +MESSENGER_PERM=0-1=1 +MESSENGER_TEMP=0-1=1 +MESSENGER_TEXT=1023-65535=8889 +OLD_REAPER=0-1=0 +PACKET_FILTER=0-1=1 +PORTKNOCKING_ALERT=0-1=1 +PORTKNOCKING_LOG=0-1=1 +PS_BLOCK_TIME=300-86400=3600 +PS_DIVERSITY=1-100=1 +PS_EMAIL_ALERT=0-1=1 +PS_INTERVAL=0|60-3600=300 +PS_LIMIT=2-20=10 +PS_PERMANENT=0-1=0 +PT_ALL_USERS=0-1=0 +PT_DELETED=0-1=1 +PT_FORKBOMB=0|100-1000=0 +PT_INTERVAL=10-3600=60 +PT_LIMIT=0-3600=60 +PT_LOAD=0-3600=30 +PT_LOAD_AVG=1|5|15=5 +PT_LOAD_LEVEL=2-20=6 +PT_LOAD_SKIP=1800-86400=3600 +PT_SKIP_HTTP=0-1=0 +PT_SSHDHUNG=0-1=0 +PT_USERKILL=0-1=0 +PT_USERKILL_ALERT=0-1=1 +PT_USERMEM=0-1024=256 +PT_USERPROC=0-100=10 +PT_USERTIME=0-86400=1800 +RELAYHOSTS=0-1=0 +RESTRICT_SYSLOG=0-3=0 +RT_AUTHRELAY_ALERT=0-1=1 +RT_AUTHRELAY_BLOCK=0-604800=0 +RT_AUTHRELAY_LIMIT=2-10000=100 +RT_LOCALHOSTRELAY_ALERT=0-1=1 +RT_LOCALHOSTRELAY_LIMIT=2-10000=100 +RT_LOCALRELAY_ALERT=0-1=1 +RT_LOCALRELAY_LIMIT=2-10000=100 +RT_POPRELAY_ALERT=0-1=1 +RT_POPRELAY_BLOCK=0-604800=0 +RT_POPRELAY_LIMIT=2-10000=100 +RT_RELAY_ALERT=0-1=1 +RT_RELAY_BLOCK=0-604800=0 +RT_RELAY_LIMIT=2-10000=100 +SAFECHAINUPDATE=0-1=0 +SMTP_ALLOWLOCAL=0-1=0 +SMTP_BLOCK=0-1=0 +SMTP_REDIRECT=0-1=0 +SMTPAUTH_RESTRICT=0-1=0 +STYLE_CUSTOM=0-1=1 +STYLE_MOBILE=0-1=1 +ST_APACHE=0-1=0 +ST_DISKW=0-1=0 +ST_DISKW_FREQ=1-1440=5 +ST_ENABLE=0-1=1 +ST_IPTABLES=10-1000=100 +ST_LOOKUP=0-1=0 +ST_MYSQL=0-1=0 +ST_SYSTEM=0-1=1 +ST_SYSTEM_MAXDAYS=7-366=30 +SYNFLOOD=0-1=0 +SYSLOG=0-1=0 +SYSLOG_CHECK=0|60-3600=0 +TESTING=0-1=0 +TESTING_INTERVAL=1-60=5 +UDPFLOOD=0-1=0 +UDPFLOOD_LOGGING=0-1=1 +UI=0-1=0 +UI_ALERT=0-4=4 +UI_ALLOW=1=1 +UI_BAN=1=1 +UI_BLOCK=1=1 +UI_BUTTONS=0-1=1 +UI_CHILDREN=1-10=5 +UI_PORT=1023-65535=6666 +UI_RETRY=0-10=5 +UI_TIMEOUT=60-300=300 +UID_INTERVAL=0|60-86400=300 +UID_LIMIT=1-100=10 +URLGET=1-3=2 +USE_CONNTRACK=0-1=1 +VERBOSE=0-1=1 +WATCH_MODE=0-1=0 +X_ARF=0-1=0 +X_ARF_ABUSE=0-1=0 +PT_SSHDKILL=0-1=0 diff --git a/src/redux/scriptalert.txt b/src/redux/scriptalert.txt new file mode 100644 index 000000000..5b070daf9 --- /dev/null +++ b/src/redux/scriptalert.txt @@ -0,0 +1,15 @@ +From: root +To: root +Subject: lfd on [hostname]: Script Alert for [path] + +Time: [time] +Path: [path] +Count: [count] emails sent + +Sample of the first 10 emails: + +[emails] + +Possible Scripts: + +[scripts] diff --git a/src/redux/sshalert.txt b/src/redux/sshalert.txt new file mode 100644 index 000000000..88b50000a --- /dev/null +++ b/src/redux/sshalert.txt @@ -0,0 +1,12 @@ +From: root +To: root +Subject: lfd on [hostname]: SSH login alert for user [account] from [ip] + +Time: [time] +IP: [ip] +Account: [account] +Method: [method] authentication + +Log line: + +[text] diff --git a/src/redux/sualert.txt b/src/redux/sualert.txt new file mode 100644 index 000000000..7c49aad9e --- /dev/null +++ b/src/redux/sualert.txt @@ -0,0 +1,12 @@ +From: root +To: root +Subject: lfd on [hostname]: SUDO login alert - [status] from [from] to [to] + +Time: [time] +From: [from] +To: [to] +Status: [status] + +Log line: + +[text] diff --git a/src/redux/sudoalert.txt b/src/redux/sudoalert.txt new file mode 100644 index 000000000..7c49aad9e --- /dev/null +++ b/src/redux/sudoalert.txt @@ -0,0 +1,12 @@ +From: root +To: root +Subject: lfd on [hostname]: SUDO login alert - [status] from [from] to [to] + +Time: [time] +From: [from] +To: [to] +Status: [status] + +Log line: + +[text] diff --git a/src/redux/syslogalert.txt b/src/redux/syslogalert.txt new file mode 100644 index 000000000..d89971a9a --- /dev/null +++ b/src/redux/syslogalert.txt @@ -0,0 +1,8 @@ +From: root +To: root +Subject: lfd on [hostname]: SYSLOG Check Failed + +Time: [time] +Error: Failed to detect code [[code]] in SYSLOG_LOG [[log]] + +SYSLOG may not be running correctly on [hostname] diff --git a/src/redux/tracking.txt b/src/redux/tracking.txt new file mode 100644 index 000000000..495adf01a --- /dev/null +++ b/src/redux/tracking.txt @@ -0,0 +1,12 @@ +From: root +To: root +Subject: lfd on [hostname]: [account] blocked for [app] access + +Time: [time] +Account: [account] +Application: [app] +IP: [ip] +Logins: [logins] +Interval: [timeout] +Allowable: [rate] logins per hour in 3600 second interval +Flushed in: [flush] seconds diff --git a/src/redux/ui/images/LICENSE.txt b/src/redux/ui/images/LICENSE.txt new file mode 100644 index 000000000..34da9d9ee --- /dev/null +++ b/src/redux/ui/images/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/src/redux/ui/images/admin_icon.svg b/src/redux/ui/images/admin_icon.svg new file mode 100644 index 000000000..1c928ea0d --- /dev/null +++ b/src/redux/ui/images/admin_icon.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/redux/ui/images/bootstrap-chosen.css b/src/redux/ui/images/bootstrap-chosen.css new file mode 100644 index 000000000..54e6a1398 --- /dev/null +++ b/src/redux/ui/images/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/src/redux/ui/images/bootstrap/css/bootstrap.min.css b/src/redux/ui/images/bootstrap/css/bootstrap.min.css new file mode 100644 index 000000000..b89ef7f3e --- /dev/null +++ b/src/redux/ui/images/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/src/redux/ui/images/bootstrap/css/bootstrap.min.css.map b/src/redux/ui/images/bootstrap/css/bootstrap.min.css.map new file mode 100644 index 000000000..0c2c93492 --- /dev/null +++ b/src/redux/ui/images/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,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A,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
          Username:
          Password:
          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(" + + + + + diff --git a/src/redux/webmin/csf/images/admin_icon.svg b/src/redux/webmin/csf/images/admin_icon.svg new file mode 100644 index 000000000..1c928ea0d --- /dev/null +++ b/src/redux/webmin/csf/images/admin_icon.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/redux/webmin/csf/images/bootstrap-chosen.css b/src/redux/webmin/csf/images/bootstrap-chosen.css new file mode 100644 index 000000000..54e6a1398 --- /dev/null +++ b/src/redux/webmin/csf/images/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/src/redux/webmin/csf/images/bootstrap/css/bootstrap.min.css b/src/redux/webmin/csf/images/bootstrap/css/bootstrap.min.css new file mode 100644 index 000000000..b89ef7f3e --- /dev/null +++ b/src/redux/webmin/csf/images/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/src/redux/webmin/csf/images/bootstrap/css/bootstrap.min.css.map b/src/redux/webmin/csf/images/bootstrap/css/bootstrap.min.css.map new file mode 100644 index 000000000..0c2c93492 --- /dev/null +++ b/src/redux/webmin/csf/images/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,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A,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
          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("