From ab1c04ae7b95053160e3b264b7e765ca409890fe Mon Sep 17 00:00:00 2001 From: gethvi Date: Wed, 22 Nov 2023 13:38:53 +0100 Subject: [PATCH] Merges API and Manager to IntelMQ project. --- .github/workflows/unittests.yml | 2 +- intelmq/__main__.py | 72 + intelmq/api/__init__.py | 0 intelmq/api/config.py | 61 + intelmq/api/dependencies.py | 62 + intelmq/api/exceptions.py | 25 + intelmq/api/files.py | 79 + intelmq/api/models.py | 12 + intelmq/api/router.py | 226 + intelmq/api/runctl.py | 159 + intelmq/api/session.py | 165 + intelmq/api/util.py | 54 + intelmq/api/version.py | 7 + intelmq/etc/runtime.yaml | 7 + intelmq/lib/utils.py | 5 + intelmq/server.py | 40 + intelmq/tests/api/__init__.py | 0 intelmq/tests/api/test_api.py | 211 + intelmq/tests/api/test_sessionstore.py | 66 + intelmq/web/__init__.py | 0 intelmq/web/router.py | 76 + intelmq/web/static/css/management.css | 14 + intelmq/web/static/css/management.css.map | 1 + intelmq/web/static/css/sb-admin-2.css | 437 + intelmq/web/static/css/sb-admin-2.css.map | 1 + intelmq/web/static/css/style.css | 149 + intelmq/web/static/css/style.css.map | 1 + intelmq/web/static/images/1140x319.gif | Bin 0 -> 3681 bytes intelmq/web/static/images/about.png | Bin 0 -> 6370 bytes intelmq/web/static/images/abouticon-20.png | Bin 0 -> 795 bytes intelmq/web/static/images/abouticon-24.png | Bin 0 -> 1005 bytes intelmq/web/static/images/check.png | Bin 0 -> 3060 bytes intelmq/web/static/images/check.svg | 122 + intelmq/web/static/images/configuration.png | Bin 0 -> 11566 bytes intelmq/web/static/images/logo.png | Bin 0 -> 30358 bytes intelmq/web/static/images/logo2.png | Bin 0 -> 63765 bytes .../web/static/images/logo_no_margin_6.png | Bin 0 -> 19579 bytes intelmq/web/static/images/management.png | Bin 0 -> 9058 bytes intelmq/web/static/images/monitor.png | Bin 0 -> 3702 bytes intelmq/web/static/images/redrawicon-20.png | Bin 0 -> 395 bytes intelmq/web/static/images/saveicon-128.png | Bin 0 -> 627 bytes intelmq/web/static/images/saveicon-20.png | Bin 0 -> 361 bytes intelmq/web/static/images/saveicon-24.png | Bin 0 -> 264 bytes intelmq/web/static/images/trashicon-20.png | Bin 0 -> 350 bytes intelmq/web/static/images/waiting.gif | Bin 0 -> 30263 bytes intelmq/web/static/js/about.js | 55 + intelmq/web/static/js/check.js | 28 + intelmq/web/static/js/config.js | 0 intelmq/web/static/js/configs.js | 1029 + intelmq/web/static/js/defaults.js | 90 + intelmq/web/static/js/management.js | 148 + intelmq/web/static/js/monitor.js | 601 + .../web/static/js/network-configuration.js | 283 + intelmq/web/static/js/positions.js | 24 + intelmq/web/static/js/runtime.js | 93 + intelmq/web/static/js/sb-admin-2.js | 50 + intelmq/web/static/js/static.js | 600 + intelmq/web/static/less/management.less | 18 + intelmq/web/static/less/sb-admin-2.less | 542 + intelmq/web/static/less/style.less | 188 + .../static/plugins/bootstrap/bootstrap.css | 6834 ++ .../web/static/plugins/bootstrap/bootstrap.js | 2580 + .../plugins/bootstrap/bootstrap.min.css | 6 + .../static/plugins/bootstrap/bootstrap.min.js | 6 + .../dataTables/dataTables.bootstrap.css | 233 + .../dataTables/dataTables.bootstrap.js | 245 + .../plugins/dataTables/jquery.dataTables.js | 15243 +++++ .../font-awesome-4.1.0/css/font-awesome.css | 1566 + .../css/font-awesome.min.css | 4 + .../font-awesome-4.1.0/fonts/FontAwesome.otf | Bin 0 -> 75188 bytes .../fonts/fontawesome-webfont.eot | Bin 0 -> 72449 bytes .../fonts/fontawesome-webfont.svg | 504 + .../fonts/fontawesome-webfont.ttf | Bin 0 -> 141564 bytes .../fonts/fontawesome-webfont.woff | Bin 0 -> 83760 bytes .../less/bordered-pulled.less | 16 + .../plugins/font-awesome-4.1.0/less/core.less | 12 + .../font-awesome-4.1.0/less/fixed-width.less | 6 + .../font-awesome-4.1.0/less/font-awesome.less | 17 + .../font-awesome-4.1.0/less/icons.less | 506 + .../font-awesome-4.1.0/less/larger.less | 13 + .../plugins/font-awesome-4.1.0/less/list.less | 19 + .../font-awesome-4.1.0/less/mixins.less | 20 + .../plugins/font-awesome-4.1.0/less/path.less | 14 + .../less/rotated-flipped.less | 9 + .../font-awesome-4.1.0/less/spinning.less | 32 + .../font-awesome-4.1.0/less/stacked.less | 20 + .../font-awesome-4.1.0/less/variables.less | 515 + .../scss/_bordered-pulled.scss | 16 + .../font-awesome-4.1.0/scss/_core.scss | 12 + .../font-awesome-4.1.0/scss/_fixed-width.scss | 6 + .../font-awesome-4.1.0/scss/_icons.scss | 506 + .../font-awesome-4.1.0/scss/_larger.scss | 13 + .../font-awesome-4.1.0/scss/_list.scss | 19 + .../font-awesome-4.1.0/scss/_mixins.scss | 20 + .../font-awesome-4.1.0/scss/_path.scss | 14 + .../scss/_rotated-flipped.scss | 9 + .../font-awesome-4.1.0/scss/_spinning.scss | 32 + .../font-awesome-4.1.0/scss/_stacked.scss | 20 + .../font-awesome-4.1.0/scss/_variables.scss | 515 + .../font-awesome-4.1.0/scss/font-awesome.scss | 17 + .../fonts/glyphicons-halflings-regular.eot | Bin 0 -> 20335 bytes .../fonts/glyphicons-halflings-regular.svg | 229 + .../fonts/glyphicons-halflings-regular.ttf | Bin 0 -> 41280 bytes .../fonts/glyphicons-halflings-regular.woff | Bin 0 -> 23320 bytes intelmq/web/static/plugins/jquery-3.5.1.js | 10872 ++++ .../web/static/plugins/jquery-3.5.1.min.js | 2 + .../web/static/plugins/jquery-3.5.1.min.map | 1 + .../static/plugins/metisMenu/metisMenu.css | 63 + .../web/static/plugins/metisMenu/metisMenu.js | 72 + .../plugins/metisMenu/metisMenu.min.css | 1 + .../static/plugins/metisMenu/metisMenu.min.js | 9 + .../vis.js/img/graph/acceptDeleteIcon.png | Bin 0 -> 20675 bytes .../plugins/vis.js/img/graph/addNodeIcon.png | Bin 0 -> 20998 bytes .../plugins/vis.js/img/graph/backIcon.png | Bin 0 -> 20802 bytes .../plugins/vis.js/img/graph/connectIcon.png | Bin 0 -> 20764 bytes .../static/plugins/vis.js/img/graph/cross.png | Bin 0 -> 18303 bytes .../plugins/vis.js/img/graph/cross2.png | Bin 0 -> 17768 bytes .../plugins/vis.js/img/graph/deleteIcon.png | Bin 0 -> 20981 bytes .../plugins/vis.js/img/graph/downArrow.png | Bin 0 -> 4460 bytes .../plugins/vis.js/img/graph/editIcon.png | Bin 0 -> 21016 bytes .../plugins/vis.js/img/graph/leftArrow.png | Bin 0 -> 4531 bytes .../static/plugins/vis.js/img/graph/minus.png | Bin 0 -> 4147 bytes .../static/plugins/vis.js/img/graph/plus.png | Bin 0 -> 4341 bytes .../plugins/vis.js/img/graph/rightArrow.png | Bin 0 -> 4514 bytes .../plugins/vis.js/img/graph/upArrow.png | Bin 0 -> 4461 bytes .../plugins/vis.js/img/graph/zoomExtends.png | Bin 0 -> 4464 bytes .../vis.js/img/network/acceptDeleteIcon.png | Bin 0 -> 20675 bytes .../vis.js/img/network/addNodeIcon.png | Bin 0 -> 20998 bytes .../plugins/vis.js/img/network/backIcon.png | Bin 0 -> 20802 bytes .../vis.js/img/network/connectIcon.png | Bin 0 -> 20764 bytes .../plugins/vis.js/img/network/cross.png | Bin 0 -> 18303 bytes .../plugins/vis.js/img/network/cross2.png | Bin 0 -> 17768 bytes .../plugins/vis.js/img/network/deleteIcon.png | Bin 0 -> 20981 bytes .../plugins/vis.js/img/network/downArrow.png | Bin 0 -> 4460 bytes .../plugins/vis.js/img/network/editIcon.png | Bin 0 -> 21016 bytes .../plugins/vis.js/img/network/leftArrow.png | Bin 0 -> 4531 bytes .../plugins/vis.js/img/network/minus.png | Bin 0 -> 4147 bytes .../plugins/vis.js/img/network/plus.png | Bin 0 -> 4341 bytes .../plugins/vis.js/img/network/rightArrow.png | Bin 0 -> 4514 bytes .../plugins/vis.js/img/network/upArrow.png | Bin 0 -> 4461 bytes .../vis.js/img/network/zoomExtends.png | Bin 0 -> 4464 bytes .../plugins/vis.js/img/timeline/delete.png | Bin 0 -> 665 bytes .../static/plugins/vis.js/vis-graph3d.min.js | 34 + .../static/plugins/vis.js/vis-network.min.css | 1 + .../static/plugins/vis.js/vis-network.min.js | 42 + .../vis.js/vis-timeline-graph2d.min.css | 1 + .../vis.js/vis-timeline-graph2d.min.js | 40 + intelmq/web/static/plugins/vis.js/vis.css | 1584 + intelmq/web/static/plugins/vis.js/vis.js | 53118 ++++++++++++++++ intelmq/web/static/plugins/vis.js/vis.js.map | 1 + intelmq/web/static/plugins/vis.js/vis.map | 1 + intelmq/web/static/plugins/vis.js/vis.min.css | 1 + intelmq/web/static/plugins/vis.js/vis.min.js | 46 + intelmq/web/templates/about.html | 71 + intelmq/web/templates/base.html | 156 + intelmq/web/templates/check.html | 32 + intelmq/web/templates/configuration.html | 167 + intelmq/web/templates/index.html | 92 + intelmq/web/templates/management.html | 84 + intelmq/web/templates/monitor.html | 161 + setup.py | 10 +- 161 files changed, 102311 insertions(+), 2 deletions(-) create mode 100644 intelmq/__main__.py create mode 100644 intelmq/api/__init__.py create mode 100644 intelmq/api/config.py create mode 100644 intelmq/api/dependencies.py create mode 100644 intelmq/api/exceptions.py create mode 100644 intelmq/api/files.py create mode 100644 intelmq/api/models.py create mode 100644 intelmq/api/router.py create mode 100644 intelmq/api/runctl.py create mode 100644 intelmq/api/session.py create mode 100644 intelmq/api/util.py create mode 100644 intelmq/api/version.py create mode 100644 intelmq/server.py create mode 100644 intelmq/tests/api/__init__.py create mode 100644 intelmq/tests/api/test_api.py create mode 100644 intelmq/tests/api/test_sessionstore.py create mode 100644 intelmq/web/__init__.py create mode 100644 intelmq/web/router.py create mode 100644 intelmq/web/static/css/management.css create mode 100644 intelmq/web/static/css/management.css.map create mode 100644 intelmq/web/static/css/sb-admin-2.css create mode 100644 intelmq/web/static/css/sb-admin-2.css.map create mode 100644 intelmq/web/static/css/style.css create mode 100644 intelmq/web/static/css/style.css.map create mode 100644 intelmq/web/static/images/1140x319.gif create mode 100644 intelmq/web/static/images/about.png create mode 100644 intelmq/web/static/images/abouticon-20.png create mode 100644 intelmq/web/static/images/abouticon-24.png create mode 100644 intelmq/web/static/images/check.png create mode 100644 intelmq/web/static/images/check.svg create mode 100644 intelmq/web/static/images/configuration.png create mode 100644 intelmq/web/static/images/logo.png create mode 100644 intelmq/web/static/images/logo2.png create mode 100644 intelmq/web/static/images/logo_no_margin_6.png create mode 100644 intelmq/web/static/images/management.png create mode 100644 intelmq/web/static/images/monitor.png create mode 100644 intelmq/web/static/images/redrawicon-20.png create mode 100644 intelmq/web/static/images/saveicon-128.png create mode 100644 intelmq/web/static/images/saveicon-20.png create mode 100644 intelmq/web/static/images/saveicon-24.png create mode 100644 intelmq/web/static/images/trashicon-20.png create mode 100644 intelmq/web/static/images/waiting.gif create mode 100644 intelmq/web/static/js/about.js create mode 100644 intelmq/web/static/js/check.js create mode 100644 intelmq/web/static/js/config.js create mode 100644 intelmq/web/static/js/configs.js create mode 100644 intelmq/web/static/js/defaults.js create mode 100644 intelmq/web/static/js/management.js create mode 100644 intelmq/web/static/js/monitor.js create mode 100644 intelmq/web/static/js/network-configuration.js create mode 100644 intelmq/web/static/js/positions.js create mode 100644 intelmq/web/static/js/runtime.js create mode 100644 intelmq/web/static/js/sb-admin-2.js create mode 100644 intelmq/web/static/js/static.js create mode 100644 intelmq/web/static/less/management.less create mode 100644 intelmq/web/static/less/sb-admin-2.less create mode 100644 intelmq/web/static/less/style.less create mode 100644 intelmq/web/static/plugins/bootstrap/bootstrap.css create mode 100644 intelmq/web/static/plugins/bootstrap/bootstrap.js create mode 100644 intelmq/web/static/plugins/bootstrap/bootstrap.min.css create mode 100644 intelmq/web/static/plugins/bootstrap/bootstrap.min.js create mode 100644 intelmq/web/static/plugins/dataTables/dataTables.bootstrap.css create mode 100644 intelmq/web/static/plugins/dataTables/dataTables.bootstrap.js create mode 100644 intelmq/web/static/plugins/dataTables/jquery.dataTables.js create mode 100644 intelmq/web/static/plugins/font-awesome-4.1.0/css/font-awesome.css create mode 100644 intelmq/web/static/plugins/font-awesome-4.1.0/css/font-awesome.min.css create mode 100644 intelmq/web/static/plugins/font-awesome-4.1.0/fonts/FontAwesome.otf create mode 100644 intelmq/web/static/plugins/font-awesome-4.1.0/fonts/fontawesome-webfont.eot create mode 100644 intelmq/web/static/plugins/font-awesome-4.1.0/fonts/fontawesome-webfont.svg create mode 100644 intelmq/web/static/plugins/font-awesome-4.1.0/fonts/fontawesome-webfont.ttf create mode 100644 intelmq/web/static/plugins/font-awesome-4.1.0/fonts/fontawesome-webfont.woff create mode 100644 intelmq/web/static/plugins/font-awesome-4.1.0/less/bordered-pulled.less create mode 100644 intelmq/web/static/plugins/font-awesome-4.1.0/less/core.less create mode 100644 intelmq/web/static/plugins/font-awesome-4.1.0/less/fixed-width.less create mode 100644 intelmq/web/static/plugins/font-awesome-4.1.0/less/font-awesome.less create mode 100644 intelmq/web/static/plugins/font-awesome-4.1.0/less/icons.less create mode 100644 intelmq/web/static/plugins/font-awesome-4.1.0/less/larger.less create mode 100644 intelmq/web/static/plugins/font-awesome-4.1.0/less/list.less create mode 100644 intelmq/web/static/plugins/font-awesome-4.1.0/less/mixins.less create mode 100644 intelmq/web/static/plugins/font-awesome-4.1.0/less/path.less create mode 100644 intelmq/web/static/plugins/font-awesome-4.1.0/less/rotated-flipped.less create mode 100644 intelmq/web/static/plugins/font-awesome-4.1.0/less/spinning.less create mode 100644 intelmq/web/static/plugins/font-awesome-4.1.0/less/stacked.less create mode 100644 intelmq/web/static/plugins/font-awesome-4.1.0/less/variables.less create mode 100644 intelmq/web/static/plugins/font-awesome-4.1.0/scss/_bordered-pulled.scss create mode 100644 intelmq/web/static/plugins/font-awesome-4.1.0/scss/_core.scss create mode 100644 intelmq/web/static/plugins/font-awesome-4.1.0/scss/_fixed-width.scss create mode 100644 intelmq/web/static/plugins/font-awesome-4.1.0/scss/_icons.scss create mode 100644 intelmq/web/static/plugins/font-awesome-4.1.0/scss/_larger.scss create mode 100644 intelmq/web/static/plugins/font-awesome-4.1.0/scss/_list.scss create mode 100644 intelmq/web/static/plugins/font-awesome-4.1.0/scss/_mixins.scss create mode 100644 intelmq/web/static/plugins/font-awesome-4.1.0/scss/_path.scss create mode 100644 intelmq/web/static/plugins/font-awesome-4.1.0/scss/_rotated-flipped.scss create mode 100644 intelmq/web/static/plugins/font-awesome-4.1.0/scss/_spinning.scss create mode 100644 intelmq/web/static/plugins/font-awesome-4.1.0/scss/_stacked.scss create mode 100644 intelmq/web/static/plugins/font-awesome-4.1.0/scss/_variables.scss create mode 100644 intelmq/web/static/plugins/font-awesome-4.1.0/scss/font-awesome.scss create mode 100644 intelmq/web/static/plugins/fonts/glyphicons-halflings-regular.eot create mode 100644 intelmq/web/static/plugins/fonts/glyphicons-halflings-regular.svg create mode 100644 intelmq/web/static/plugins/fonts/glyphicons-halflings-regular.ttf create mode 100644 intelmq/web/static/plugins/fonts/glyphicons-halflings-regular.woff create mode 100644 intelmq/web/static/plugins/jquery-3.5.1.js create mode 100644 intelmq/web/static/plugins/jquery-3.5.1.min.js create mode 100644 intelmq/web/static/plugins/jquery-3.5.1.min.map create mode 100644 intelmq/web/static/plugins/metisMenu/metisMenu.css create mode 100644 intelmq/web/static/plugins/metisMenu/metisMenu.js create mode 100644 intelmq/web/static/plugins/metisMenu/metisMenu.min.css create mode 100644 intelmq/web/static/plugins/metisMenu/metisMenu.min.js create mode 100644 intelmq/web/static/plugins/vis.js/img/graph/acceptDeleteIcon.png create mode 100644 intelmq/web/static/plugins/vis.js/img/graph/addNodeIcon.png create mode 100644 intelmq/web/static/plugins/vis.js/img/graph/backIcon.png create mode 100644 intelmq/web/static/plugins/vis.js/img/graph/connectIcon.png create mode 100644 intelmq/web/static/plugins/vis.js/img/graph/cross.png create mode 100644 intelmq/web/static/plugins/vis.js/img/graph/cross2.png create mode 100644 intelmq/web/static/plugins/vis.js/img/graph/deleteIcon.png create mode 100644 intelmq/web/static/plugins/vis.js/img/graph/downArrow.png create mode 100644 intelmq/web/static/plugins/vis.js/img/graph/editIcon.png create mode 100644 intelmq/web/static/plugins/vis.js/img/graph/leftArrow.png create mode 100644 intelmq/web/static/plugins/vis.js/img/graph/minus.png create mode 100644 intelmq/web/static/plugins/vis.js/img/graph/plus.png create mode 100644 intelmq/web/static/plugins/vis.js/img/graph/rightArrow.png create mode 100644 intelmq/web/static/plugins/vis.js/img/graph/upArrow.png create mode 100644 intelmq/web/static/plugins/vis.js/img/graph/zoomExtends.png create mode 100644 intelmq/web/static/plugins/vis.js/img/network/acceptDeleteIcon.png create mode 100644 intelmq/web/static/plugins/vis.js/img/network/addNodeIcon.png create mode 100644 intelmq/web/static/plugins/vis.js/img/network/backIcon.png create mode 100644 intelmq/web/static/plugins/vis.js/img/network/connectIcon.png create mode 100644 intelmq/web/static/plugins/vis.js/img/network/cross.png create mode 100644 intelmq/web/static/plugins/vis.js/img/network/cross2.png create mode 100644 intelmq/web/static/plugins/vis.js/img/network/deleteIcon.png create mode 100644 intelmq/web/static/plugins/vis.js/img/network/downArrow.png create mode 100644 intelmq/web/static/plugins/vis.js/img/network/editIcon.png create mode 100644 intelmq/web/static/plugins/vis.js/img/network/leftArrow.png create mode 100644 intelmq/web/static/plugins/vis.js/img/network/minus.png create mode 100644 intelmq/web/static/plugins/vis.js/img/network/plus.png create mode 100644 intelmq/web/static/plugins/vis.js/img/network/rightArrow.png create mode 100644 intelmq/web/static/plugins/vis.js/img/network/upArrow.png create mode 100644 intelmq/web/static/plugins/vis.js/img/network/zoomExtends.png create mode 100644 intelmq/web/static/plugins/vis.js/img/timeline/delete.png create mode 100644 intelmq/web/static/plugins/vis.js/vis-graph3d.min.js create mode 100644 intelmq/web/static/plugins/vis.js/vis-network.min.css create mode 100644 intelmq/web/static/plugins/vis.js/vis-network.min.js create mode 100644 intelmq/web/static/plugins/vis.js/vis-timeline-graph2d.min.css create mode 100644 intelmq/web/static/plugins/vis.js/vis-timeline-graph2d.min.js create mode 100644 intelmq/web/static/plugins/vis.js/vis.css create mode 100644 intelmq/web/static/plugins/vis.js/vis.js create mode 100644 intelmq/web/static/plugins/vis.js/vis.js.map create mode 100644 intelmq/web/static/plugins/vis.js/vis.map create mode 100644 intelmq/web/static/plugins/vis.js/vis.min.css create mode 100644 intelmq/web/static/plugins/vis.js/vis.min.js create mode 100644 intelmq/web/templates/about.html create mode 100644 intelmq/web/templates/base.html create mode 100644 intelmq/web/templates/check.html create mode 100644 intelmq/web/templates/configuration.html create mode 100644 intelmq/web/templates/index.html create mode 100644 intelmq/web/templates/management.html create mode 100644 intelmq/web/templates/monitor.html diff --git a/.github/workflows/unittests.yml b/.github/workflows/unittests.yml index 1dee5735f..0e6c7bb82 100644 --- a/.github/workflows/unittests.yml +++ b/.github/workflows/unittests.yml @@ -62,7 +62,7 @@ jobs: run: bash .github/workflows/scripts/setup-full.sh - name: Install test dependencies - run: pip install pytest-cov Cerberus requests_mock coverage + run: pip install pytest-cov Cerberus requests_mock coverage httpx pycodestyle - name: Install dependencies if: ${{ matrix.type == 'basic' }} diff --git a/intelmq/__main__.py b/intelmq/__main__.py new file mode 100644 index 000000000..beee02085 --- /dev/null +++ b/intelmq/__main__.py @@ -0,0 +1,72 @@ +import argparse +import getpass +import sys + +import uvicorn + +from intelmq.api.config import Config +from intelmq.api.session import SessionStore +from intelmq.lib import utils + + +def server_start(host: str = None, port: int = None, debug: bool = False, *args, **kwargs): + server_settings = utils.get_server_settings() + host = host if host is not None else server_settings.get("host", "0.0.0.0") + port = int(port) if port is not None else int(server_settings.get("port", 8080)) + + return uvicorn.run( + "intelmq.server:app", + host=host, + reload=debug, + port=port, + workers=1, + ) + + +def server_adduser(username: str, password: str = None, *args, **kwargs): + api_config: Config = Config() + + if api_config.session_store is None: + print("Could not add user- no session store configured in configuration!", file=sys.stderr) + exit(1) + + session_store = SessionStore(str(api_config.session_store), api_config.session_duration) + password = getpass.getpass() if password is None else password + session_store.add_user(username, password) + print(f"Added user {username} to intelmq session file.") + + +def main(): + parser = argparse.ArgumentParser(prog="intelmq", usage="intelmq [OPTIONS] COMMAND") + parser.set_defaults(func=(lambda *_, **__: parser.print_help())) # wrapper to accept args and kwargs + parser._optionals.title = "Options" + parser.add_argument("--version", action="store_true", help="print version and exit", default=None) + commands = parser.add_subparsers(metavar="", title="Commands") + + # intelmq server + srv_parser = commands.add_parser("server", help="server subcommands", usage="intelmq server [COMMAND]") + srv_parser.set_defaults(func=(lambda *_, **__: srv_parser.print_help())) # wrapper to accept args and kwargs + srv_parser._optionals.title = "Options" + srv_subcommands = srv_parser.add_subparsers(metavar="", title="Commands") + + # intelmq server start + srv_start = srv_subcommands.add_parser("start", help="start the server", usage="intelmq server start [OPTIONS]") + srv_start.set_defaults(func=server_start) + srv_start._optionals.title = "Options" + srv_start.add_argument("--debug", action="store_true", dest="debug", default=None) + srv_start.add_argument("--host", type=str, dest="host") + srv_start.add_argument("--port", type=int, dest="port") + + # intelmq server adduser + srv_adduser = srv_subcommands.add_parser("adduser", help="adds new user", usage="intelmq server adduser [OPTIONS]") + srv_adduser.set_defaults(func=server_adduser) + srv_adduser._optionals.title = "Options" + srv_adduser.add_argument('--username', required=True, help='The username of the account.', type=str) + srv_adduser.add_argument('--password', required=False, help='The password of the account.', type=str) + + args = parser.parse_args() + return args.func(**vars(args)) + + +if __name__ == "__main__": + main() diff --git a/intelmq/api/__init__.py b/intelmq/api/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/intelmq/api/config.py b/intelmq/api/config.py new file mode 100644 index 000000000..d4959e733 --- /dev/null +++ b/intelmq/api/config.py @@ -0,0 +1,61 @@ +"""Configuration for IntelMQ Manager + +SPDX-FileCopyrightText: 2020 Intevation GmbH +SPDX-License-Identifier: AGPL-3.0-or-later + +Funding: of initial version by SUNET +Author(s): + * Bernhard Herzog +""" + +from typing import List, Optional +from pathlib import Path +from intelmq.lib import utils + + +class Config: + + """Configuration settings for IntelMQ Manager""" + + intelmq_ctl_cmd: List[str] = ["sudo", "-u", "intelmq", "/usr/local/bin/intelmqctl"] + + allowed_path: Path = Path("/opt/intelmq/var/lib/bots/") + + session_store: Optional[Path] = None + + session_duration: int = 24 * 3600 + + allow_origins: List[str] = ['*'] + + enable_webgui: bool = True + + host: str = "0.0.0.0" + + port: int = 8080 + + def __init__(self): + server_settings = utils.get_server_settings() + + if "intelmq_ctl_cmd" in server_settings: + self.intelmq_ctl_cmd = server_settings["intelmq_ctl_cmd"] + + if "allowed_path" in server_settings: + self.allowed_path = Path(server_settings["allowed_path"]) + + if "session_store" in server_settings: + self.session_store = Path(server_settings["session_store"]) + + if "session_duration" in server_settings: + self.session_duration = int(server_settings["session_duration"]) + + if "allow_origins" in server_settings: + self.allow_origins = server_settings['allow_origins'] + + if "enable_webgui" in server_settings: + self.enable_webgui = server_settings["enable_webgui"] + + if "host" in server_settings: + self.host = server_settings["host"] + + if "port" in server_settings: + self.host = server_settings["port"] diff --git a/intelmq/api/dependencies.py b/intelmq/api/dependencies.py new file mode 100644 index 000000000..ec349f129 --- /dev/null +++ b/intelmq/api/dependencies.py @@ -0,0 +1,62 @@ +"""Dependencies of the API endpoints, in the FastAPI style + +SPDX-FileCopyrightText: 2022 CERT.at GmbH +SPDX-License-Identifier: AGPL-3.0-or-later +""" + +import typing +from typing import Generic, Optional, TypeVar + +from fastapi import Depends, Header, HTTPException, Response, status + +import intelmq.api.config +import intelmq.api.session as session + +T = TypeVar("T") + + +class OneTimeDependency(Generic[T]): + """Allows one-time explicit initialization of the dependency, + and then returning it on every usage. + + It emulates the previous behavior that used global variables""" + + def __init__(self) -> None: + self._value: Optional[T] = None + + def initialize(self, value: T) -> None: + self._value = value + + def __call__(self) -> Optional[T]: + return self._value + + +api_config = OneTimeDependency[intelmq.api.config.Config]() +session_store = OneTimeDependency[session.SessionStore]() + + +def cached_response(max_age: int): + """Adds the cache headers to the response""" + def _cached_response(response: Response): + response.headers["cache-control"] = f"max-age={max_age}" + return _cached_response + + +def token_authorization(authorization: typing.Union[str, None] = Header(default=None), + session: session.SessionStore = Depends(session_store)): + if session is not None: + if not authorization or not session.verify_token(authorization): + raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail={ + "Authentication Required": + "Please provide valid Token verification credentials" + }) + + +def startup(config: intelmq.api.config.Config): + """A starting point to one-time initialization of necessary dependencies. This needs to + be called by the application on the startup.""" + api_config.initialize(config) + session_file = config.session_store + if session_file is not None: + session_store.initialize(session.SessionStore(str(session_file), + config.session_duration)) diff --git a/intelmq/api/exceptions.py b/intelmq/api/exceptions.py new file mode 100644 index 000000000..5b7dc32e8 --- /dev/null +++ b/intelmq/api/exceptions.py @@ -0,0 +1,25 @@ +"""Exception handlers for API + +SPDX-FileCopyrightText: 2022 CERT.at GmbH +SPDX-License-Identifier: AGPL-3.0-or-later +""" + +from fastapi import FastAPI, Request, status +from fastapi.responses import JSONResponse +from starlette.exceptions import HTTPException as StarletteHTTPException + +import intelmq.api.runctl as runctl + + +def ctl_error_handler(request: Request, exc: runctl.IntelMQCtlError): + return JSONResponse(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, content=exc.error_dict) + + +def handle_generic_error(request: Request, exc: StarletteHTTPException): + return JSONResponse(status_code=exc.status_code, content={"error": exc.detail}) + + +def register(app: FastAPI): + """A hook to register handlers in the app. Need to be called before startup""" + app.add_exception_handler(runctl.IntelMQCtlError, ctl_error_handler) + app.add_exception_handler(StarletteHTTPException, handle_generic_error) diff --git a/intelmq/api/files.py b/intelmq/api/files.py new file mode 100644 index 000000000..f3c891b15 --- /dev/null +++ b/intelmq/api/files.py @@ -0,0 +1,79 @@ +"""Direct access to IntelMQ files and directories + +SPDX-FileCopyrightText: 2020 Intevation GmbH +SPDX-License-Identifier: AGPL-3.0-or-later + +Funding: of initial version by SUNET +Author(s): + * Bernhard Herzog + +This module implements the part of the IntelMQ-Manager backend that +allows direct read and write access to some of the files used by +IntelMQ. +""" + +from pathlib import PurePath, Path +from typing import Optional, Tuple, Union, Dict, Any, Iterable, BinaryIO + +from intelmq.api.config import Config + + +def path_starts_with(path: PurePath, prefix: PurePath) -> bool: + """Return whether the path starts with prefix. + + Both arguments must be absolute paths. If not, this function raises + a ValueError. + + This function compares the path components, so it's not a simple + string prefix test. + """ + if not path.is_absolute(): + raise ValueError("{!r} is not absolute".format(path)) + if not prefix.is_absolute(): + raise ValueError("{!r} is not absolute".format(prefix)) + return path.parts[:len(prefix.parts)] == prefix.parts + + +class FileAccess: + + def __init__(self, config: Config): + self.allowed_path = config.allowed_path + + def file_name_allowed(self, filename: str) -> Optional[Tuple[bool, Path]]: + """Determine wether the API should allow access to a file.""" + resolved = Path(filename).resolve() + if not path_starts_with(resolved, self.allowed_path): + return None + + return (False, resolved) + + def load_file_or_directory(self, unvalidated_filename: str, fetch: bool) \ + -> Union[Tuple[str, Union[BinaryIO, Dict[str, Any]]], None]: + allowed = self.file_name_allowed(unvalidated_filename) + if allowed is None: + return None + + content_type = "application/json" + predefined, normalized = allowed + + if predefined or fetch: + if fetch: + content_type = "text/html" + return (content_type, open(normalized, "rb")) + + result = {"files": {}} # type: Dict[str, Any] + if normalized.is_dir(): + result["directory"] = str(normalized) + files = normalized.iterdir() # type: Iterable[Path] + else: + files = [normalized] + + for path in files: + stat = path.stat() + if stat.st_size < 2000: + # FIXME: don't hardwire this size + obj = {"contents": path.read_text()} # type: Dict[str, Any] + else: + obj = {"size": stat.st_size, "path": str(path.resolve())} + result["files"][path.name] = obj + return (content_type, result) diff --git a/intelmq/api/models.py b/intelmq/api/models.py new file mode 100644 index 000000000..65f646688 --- /dev/null +++ b/intelmq/api/models.py @@ -0,0 +1,12 @@ +"""Models used in API + +SPDX-FileCopyrightText: 2023 CERT.at GmbH +SPDX-License-Identifier: AGPL-3.0-or-later +""" + +from pydantic import BaseModel + + +class TokenResponse(BaseModel): + login_token: str + username: str diff --git a/intelmq/api/router.py b/intelmq/api/router.py new file mode 100644 index 000000000..732d00179 --- /dev/null +++ b/intelmq/api/router.py @@ -0,0 +1,226 @@ +"""HTTP-API backend of IntelMQ-Manager + +SPDX-FileCopyrightText: 2020 Intevation GmbH +SPDX-License-Identifier: AGPL-3.0-or-later + +Funding: of initial version by SUNET +Author(s): + * Bernhard Herzog + +This module implements the HTTP part of the API backend of +IntelMQ-Manager. The logic itself is in the runctl & files modules. +""" + +import json +import pathlib +import string +import typing + +from fastapi import APIRouter, Depends, Form, HTTPException, Response, status +from fastapi.responses import JSONResponse, PlainTextResponse +from intelmq.lib import utils # type: ignore +from typing_extensions import Literal # Python 3.8+ + +import intelmq.api.config +import intelmq.api.files as files +import intelmq.api.runctl as runctl +import intelmq.api.session as session + +from .dependencies import (api_config, cached_response, session_store, + token_authorization) +from .models import TokenResponse + +router = APIRouter() + + +Levels = Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL", "ALL"] +Actions = Literal["start", "stop", "restart", "reload", "status"] +Groups = Literal["collectors", "parsers", "experts", "outputs", "botnet"] +BotCmds = Literal["get", "pop", "send", "process"] +Pages = Literal["configs", "management", "monitor", "check", "about", "index"] + +ID_CHARS = set(string.ascii_letters + string.digits + "-") + + +def ID(id: str) -> str: + if not set(id) < ID_CHARS: + raise ValueError("Invalid character in {!r}".format(id)) + return id + + +def runner(config: intelmq.api.config.Config = Depends(api_config)): + return runctl.RunIntelMQCtl(config.intelmq_ctl_cmd) + + +def file_access(config: intelmq.api.config.Config = Depends(api_config)): + return files.FileAccess(config) + + +cached = Depends(cached_response(max_age=3)) +authorized = Depends(token_authorization) + + +class JSONFileResponse(JSONResponse): + """Directly pass JSONFile (bytes) with the correct content type to the response""" + + def render(self, content: runctl.JSONFile) -> bytes: + return content + + +@router.get("/") +def api_base_url(): + """Do not rename or delete!""" + return JSONResponse({}) + + +@router.get("/botnet", dependencies=[authorized]) +def botnet(action: Actions, group: typing.Optional[Groups] = None, + runner: runctl.RunIntelMQCtl = Depends(runner)): + return JSONFileResponse(runner.botnet(action, group)) + + +@router.get("/bot", dependencies=[authorized]) +def bot(action: Actions, id: str = Depends(ID), runner: runctl.RunIntelMQCtl = Depends(runner)): + return JSONFileResponse(runner.bot(action, id)) + + +@router.get("/getlog", dependencies=[authorized, cached]) +def get_log(lines: int, id: str = Depends(ID), level: Levels = "DEBUG", + runner: runctl.RunIntelMQCtl = Depends(runner)): + return JSONFileResponse(runner.log(id, lines, level)) + + +@router.get("/queues", dependencies=[authorized, cached]) +def queues(runner: runctl.RunIntelMQCtl = Depends(runner)): + return JSONFileResponse(runner.list("queues")) + + +@router.get("/queues-and-status", dependencies=[authorized, cached]) +def queues_and_status(runner: runctl.RunIntelMQCtl = Depends(runner)): + return JSONFileResponse(runner.list("queues-and-status")) + + +@router.get("/bots", dependencies=[authorized, cached]) +def bots(runner: runctl.RunIntelMQCtl = Depends(runner)): + return JSONFileResponse(runner.list("bots")) + + +@router.get("/version", dependencies=[authorized], response_model=dict) +def version(runner: runctl.RunIntelMQCtl = Depends(runner)): + return runner.version() + + +@router.get("/check", dependencies=[authorized]) +def check(runner: runctl.RunIntelMQCtl = Depends(runner)): + return JSONFileResponse(runner.check()) + + +@router.get("/clear", dependencies=[authorized]) +def clear(id: str = Depends(ID), runner: runctl.RunIntelMQCtl = Depends(runner)): + return JSONFileResponse(runner.clear(id)) + + +@router.post("/run", dependencies=[authorized], response_model=str) +def run(bot: str, cmd: BotCmds, show: bool = False, dry: bool = False, msg: str = Form(default=""), + runner: runctl.RunIntelMQCtl = Depends(runner)): + return runner.run(bot, cmd, show, dry, msg) + + +@router.get("/debug", dependencies=[authorized]) +def debug(runner: runctl.RunIntelMQCtl = Depends(runner)): + return JSONFileResponse(runner.debug()) + + +@router.get("/config", dependencies=[authorized]) +def config(file: str, fetch: bool = False, + file_access: files.FileAccess = Depends(file_access)): + result = file_access.load_file_or_directory(file, fetch) + if result is None: + return ["Unknown resource"] + + content_type, contents = result + return Response(contents, headers={"content-type": content_type}) + + +@router.post("/login", status_code=status.HTTP_200_OK, response_model=TokenResponse) +def login(username: str = Form(...), password: str = Form(...), + session: session.SessionStore = Depends(session_store)): + if session is None: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail="Session store is disabled by configuration! No login possible and required.", + ) + else: + known = session.verify_user(username, password) + if known is not None: + token = session.new_session({"username": username}) + return {"login_token": token, + "username": username, + } + else: + raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, + detail="Invalid username and/or password.") + + +@router.get("/harmonization", dependencies=[authorized], response_model=dict) +def get_harmonization(runner: runctl.RunIntelMQCtl = Depends(runner)): + harmonization = pathlib.Path('/opt/intelmq/etc/harmonization.conf') + paths = runner.get_paths() + if 'CONFIG_DIR' in paths: + harmonization = pathlib.Path(paths['CONFIG_DIR']) / 'harmonization.conf' + try: + return json.loads(harmonization.read_text()) + except OSError as e: + print(f"Could not read {harmonization}: {str(e)}") + return {} + + +@router.get("/runtime", dependencies=[authorized], response_model=dict) +def get_runtime(): + return utils.get_runtime() + + +@router.post("//runtime", dependencies=[authorized], response_model=str, deprecated=True, + description="Invalid path for compatibility with older IntelMQ Manager versions", + response_class=PlainTextResponse) +@router.post("/runtime", dependencies=[authorized], response_model=str, + response_class=PlainTextResponse) +def post_runtime(body: dict): + try: + utils.set_runtime(body) + return "success" + except Exception as e: + print(f"Could not write runtime {str(e)}") + return str(e) + + +@router.get("/positions", dependencies=[authorized], response_model=dict) +def get_positions(runner: runctl.RunIntelMQCtl = Depends(runner)): + positions = pathlib.Path('/opt/intelmq/etc/manager/positions.conf') + paths = runner.get_paths() + if 'CONFIG_DIR' in paths: + positions = pathlib.Path(paths['CONFIG_DIR']) / 'manager/positions.conf' + try: + return json.loads(positions.read_text()) + except OSError as e: + print(f"Could not read {positions}: {str(e)}") + return {} + + +@router.post("//positions", dependencies=[authorized], response_model=str, deprecated=True, + description="Invalid path for compatibility with older IntelMQ Manager versions", + response_class=PlainTextResponse) +@router.post("/positions", dependencies=[authorized], response_model=str, + response_class=PlainTextResponse) +def post_positions(body: dict, runner: runctl.RunIntelMQCtl = Depends(runner)): + positions = pathlib.Path('/opt/intelmq/etc/manager/positions.conf') + paths = runner.get_paths() + if 'CONFIG_DIR' in paths: + positions = pathlib.Path(paths['CONFIG_DIR']) / 'manager/positions.conf' + try: + positions.parent.mkdir(exist_ok=True) + positions.write_text(json.dumps(body, indent=4)) + return "success" + except OSError as e: + print(f"Error creating {positions.parent} or writing to {positions}: {str(e)}") + return str(e) diff --git a/intelmq/api/runctl.py b/intelmq/api/runctl.py new file mode 100644 index 000000000..495325852 --- /dev/null +++ b/intelmq/api/runctl.py @@ -0,0 +1,159 @@ +"""Control IntelMQ with the intelmqctl command. + +SPDX-FileCopyrightText: 2020 Intevation GmbH +SPDX-License-Identifier: AGPL-3.0-or-later + +Funding: of initial version by SUNET +Author(s): + * Bernhard Herzog + +This module contains code to run the intelmqctl command as needed by the +manager's API backend. +""" + +import io +import json +import subprocess +from typing import List, Dict, Optional + +from intelmq.api.util import shell_command_for_errors +from .version import __version__ + +# +# Typing aliases for use with RunIntelMQCtl +# +# Arguments for a subprocess command line are a list of strings. +Args = List[str] + +# JSON output of intelmqctl is returned as bytes and then simply +# passed to the response without (de)serialization. Type alias +# for clear understanding of expected format and content type +JSONFile = bytes + + +class IntelMQCtlError(Exception): + + def __init__(self, error_dict): + self.error_dict = error_dict + + def __str__(self): + return self.error_dict["message"] + + +failure_tips = [ + ("sudo: no tty present and no askpass program specified", + "Is sudoers file or IntelMQ-Manager " + "set up correctly?"), + ("Permission denied: '/opt/intelmq", + "Has the user accessing intelmq folder the read/write permissions?" + " This might be user intelmq or www-data, depending on your configuration," + " ex: sudo chown intelmq.intelmq /opt/intelmq -R" + " && sudo chmod u+rw /opt/intelmq -R"), + ("sqlite3.OperationalError: no such table", + "SQLite database may not have been" + " initialized.") # noqa +] + + +class RunIntelMQCtl: + + def __init__(self, base_cmd: Args): + self.base_cmd = base_cmd + + def _run_intelmq_ctl(self, args: Args) -> subprocess.CompletedProcess: + command = self.base_cmd + args + result = subprocess.run(command, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + + # Detect errors + # + # The logic here follows the original PHP code but it differs in + # some respects. One difference is that intelmqctl can exit with + # an exit code != 0 even if it actually was successful, so we + # cannot actually use the exit code. The PHP code appears to use + # it, but the exit code it examines is not the exit code of + # intelmqctl but of a little shell script that basically ends up + # ignoring intelmqctl's exit code. + if not result.stdout or result.stderr: + message = str(result.stderr, errors="replace") + + if not message: + message = "Failed to execute intelmqctl." + + for msg_fragment, tip in failure_tips: + if msg_fragment in message: + break + else: + tip = "" + + raise IntelMQCtlError({"tip": tip, + "message": message, + "command": shell_command_for_errors(command), + }) + return result + + def _run_json(self, args: Args) -> JSONFile: + completed = self._run_intelmq_ctl(["--type", "json"] + args) + return completed.stdout + + def _run_str(self, args: Args) -> str: + completed = self._run_intelmq_ctl(args) + return str(completed.stdout, "ascii") + + def botnet(self, action: str, group: Optional[str]) -> JSONFile: + args = [action] + if group is not None and group != "botnet": + args.extend(["--group", group]) + return self._run_json(args) + + def bot(self, action: str, bot_id: str) -> JSONFile: + return self._run_json([action, bot_id]) + + def log(self, bot_id: str, lines: int, level: str) -> JSONFile: + if level == "ALL": + level = "DEBUG" + return self._run_json(["log", bot_id, str(lines), level]) + + def list(self, kind: str) -> JSONFile: + return self._run_json(["list", kind]) + + def version(self) -> Dict[str, str]: + intelmq_version = self._run_str(["--version"]).strip() + return {"intelmq": intelmq_version, + "intelmq-api": __version__, + } + + def check(self) -> JSONFile: + return self._run_json(["check"]) + + def clear(self, queue_name: str) -> JSONFile: + return self._run_json(["clear", queue_name]) + + def run(self, bot_id: str, cmd: str, show: bool, dry: bool, + msg: str) -> str: + args = ["run", bot_id] + if cmd == "get": + args.extend(["message", "get"]) + elif cmd == "pop": + args.extend(["message", "pop"]) + elif cmd == "send": + args.extend(["message", "send", msg]) + elif cmd == "process": + args.append("process") + if show: + args.append("--show-sent") + if dry: + args.append("--dry") + args.extend(["--msg", msg]) + return self._run_str(args) + + def debug(self, get_paths: bool = False) -> JSONFile: + args = ["debug"] + if get_paths: + args.append("--get-paths") + return self._run_json(args) + + def get_paths(self) -> Dict[str, str]: + return dict(json.load(io.BytesIO(self.debug(get_paths=True)))["paths"]) diff --git a/intelmq/api/session.py b/intelmq/api/session.py new file mode 100644 index 000000000..1eb8e067e --- /dev/null +++ b/intelmq/api/session.py @@ -0,0 +1,165 @@ +"""Session support for IntelMQ-Manager + +SPDX-FileCopyrightText: 2020 Intevation GmbH +SPDX-License-Identifier: AGPL-3.0-or-later + +Funding: of initial version by SUNET +Author(s): + * Bernhard Herzog +""" + +import os +from typing import Tuple, Optional, Union +from contextlib import contextmanager +import json +import threading +import hashlib + +import sqlite3 + + +INIT_DB_SQL = """ +BEGIN; +CREATE TABLE version (version INTEGER); +INSERT INTO version (version) VALUES (1); + +CREATE TABLE session ( + session_id TEXT PRIMARY KEY, + modified TIMESTAMP, + data BLOB +); + +CREATE TABLE user( + username TEXT PRIMARY KEY, + password TEXT, + salt TEXT +); + +COMMIT; +""" + +LOOKUP_SESSION_SQL = """ +SELECT data FROM session WHERE session_id = ?; +""" + +STORE_SESSION_SQL = """ +INSERT OR REPLACE INTO session (session_id, modified, data) +VALUES (?, CURRENT_TIMESTAMP, ?); +""" + +EXPIRATION_SQL = """ +DELETE FROM session + WHERE strftime('%s', 'now') - strftime('%s', modified) > ?; +""" + +TOUCH_SESSION_SQL = """ +UPDATE session SET modified = CURRENT_TIMESTAMP WHERE session_id = ?; +""" + +ADD_USER_SQL = """ +INSERT OR REPLACE INTO user (username, password, salt) VALUES (?, ?, ?); +""" + +LOOKUP_USER_SQL = """ +SELECT username, password, salt FROM user WHERE username = ?; +""" + + +class SessionStore: + """Session store based on SQLite + + The SQLite database is used in autocommit mode avoid blocking + connections to the same database from other processes. This ensures + that no transactions are open for very long. The transactions this + class needs to do are all single statements anyway, so autocommit is + no problem. + + Instances of this class can be used by multiple threads + simultaneously. Use of the underlying sqlite connection object is + serialized between threads with a lock. + """ + + def __init__(self, dbname: str, max_duration: int): + self.dbname = dbname + self.max_duration = max_duration + if not os.path.isfile(self.dbname): + self.init_sqlite_db() + self.lock = threading.Lock() + self.connection = self.connect() + + def connect(self) -> sqlite3.Connection: + return sqlite3.connect(self.dbname, check_same_thread=False, + isolation_level=None) + + @contextmanager + def get_con(self): + with self.lock: + yield self.connection + + def init_sqlite_db(self): + with self.connect() as con: + con.executescript(INIT_DB_SQL) + + def execute(self, stmt: str, params: tuple) -> Optional[tuple]: + try: + with self.get_con() as con: + return con.execute(stmt, params).fetchone() + except sqlite3.OperationalError as exc: + print(f"SQLite3-Error ({exc}): Possibly missing write permissions to" + " session file (or the folder it is located in).") + return None + + # + # Methods for session data + # + + def expire_sessions(self): + self.execute(EXPIRATION_SQL, (self.max_duration,)) + + def get(self, session_id: str) -> Optional[dict]: + self.expire_sessions() + row = self.execute(LOOKUP_SESSION_SQL, (session_id,)) + if row is not None: + return json.loads(row[0]) + return None + + def set(self, session_id: str, session_data: dict): + self.execute(STORE_SESSION_SQL, + (session_id, json.dumps(session_data))) + + def new_session(self, session_data: dict) -> str: + token = os.urandom(16).hex() + self.set(token, session_data) + return token + + def verify_token(self, token: str) -> Union[bool, dict]: + session_data = self.get(token) + if session_data is not None: + self.execute(TOUCH_SESSION_SQL, (token,)) + return session_data + return False + + # + # User account methods + # + + def add_user(self, username: str, password: str): + hashed, salt = self.hash_password(password) + self.execute(ADD_USER_SQL, (username, hashed, salt)) + + def verify_user(self, username: str, password: str) -> Optional[dict]: + row = self.execute(LOOKUP_USER_SQL, (username,)) + if row is not None: + username, stored_hash, salt = row + hashed = self.hash_password(password, bytes.fromhex(salt))[0] + if hashed == stored_hash: + return {"username": username} + return None + + def hash_password(self, password: str, + salt: Optional[bytes] = None) -> Tuple[str, str]: + if salt is None: + salt = os.urandom(16) + hashed = hashlib.pbkdf2_hmac("sha256", password.encode("utf8"), salt, + 100000) + return (hashed.hex(), salt.hex()) diff --git a/intelmq/api/util.py b/intelmq/api/util.py new file mode 100644 index 000000000..1e1559f24 --- /dev/null +++ b/intelmq/api/util.py @@ -0,0 +1,54 @@ +"""Helper functions for the API + +SPDX-FileCopyrightText: 2020 Intevation GmbH +SPDX-License-Identifier: AGPL-3.0-or-later + +Funding: of initial version by SUNET +Author(s): + * Bernhard Herzog +""" + +import os +import pwd +import shlex +from typing import List + + +def effective_user_name() -> str: + """Return the name of the effective user""" + return pwd.getpwuid(os.geteuid()).pw_name + + +def format_shell_command(words: List[str]) -> str: + """Format a shell command as a string for use with a shell. + + This function turns a command given as a list of strings as a single + string that could be interpreted by the shell. + + When invoking subprocesses it's usually best to use a list of + strings as the command so that no shell is involved so that one + doesn't have to care about quoting. However, for error messages it's + convenient for the user to see the command as it would be written + for the shell so that it's easy to e.g. test it in an interactive + shell. + + This function is basically identical to shlex.join function that was + added in Python 3.8. + """ + return " ".join(shlex.quote(word) for word in words) + + +def shell_command_for_errors(words: List[str]) -> str: + """Return a formatted shell command for error messages. + + The return value contains the command formatted for use in a shell + with a prefix that uses sudo to execute the command as the users + this API is running as. This is intended primarily for error + messages so that users of the web interface can use the command to + replicate the problems that may be encountered. + + This is particularly interesting for the usual case where we do not + invoke intelmqctl directly but run it via sudo from code executed by + special users like www-data. + """ + return format_shell_command(["sudo", "-u", effective_user_name()] + words) diff --git a/intelmq/api/version.py b/intelmq/api/version.py new file mode 100644 index 000000000..90c0876e1 --- /dev/null +++ b/intelmq/api/version.py @@ -0,0 +1,7 @@ +""" Version file for intelmq-api + +SPDX-FileCopyrightText: 2020-2023 Birger Schacht, Sebastian Wagner +SPDX-License-Identifier: AGPL-3.0-or-later +""" +__version_info__ = (3, 2, 0) +__version__ = '.'.join(map(str, __version_info__)) diff --git a/intelmq/etc/runtime.yaml b/intelmq/etc/runtime.yaml index 170f0cbfd..603481026 100644 --- a/intelmq/etc/runtime.yaml +++ b/intelmq/etc/runtime.yaml @@ -1,3 +1,10 @@ +global: + server: + host: 127.0.0.1 + port: 8080 + enable_webgui: true + intelmq_ctl_cmd: ["sudo", "-u", "intelmq", "/usr/local/bin/intelmqctl"] + cymru-whois-expert: bot_id: cymru-whois-expert description: Cymru Whois (IP to ASN) is the bot responsible to add network information diff --git a/intelmq/lib/utils.py b/intelmq/lib/utils.py index 5701db1af..1021eeb56 100644 --- a/intelmq/lib/utils.py +++ b/intelmq/lib/utils.py @@ -925,6 +925,11 @@ def get_global_settings() -> dict: return runtime_conf.get('global', {}) +def get_server_settings() -> dict: + global_settings = get_global_settings() + return global_settings.get('server', {}) + + def set_runtime(runtime: dict) -> dict: write_configuration(configuration_filepath=RUNTIME_CONF_FILE, content=runtime) return get_runtime() diff --git a/intelmq/server.py b/intelmq/server.py new file mode 100644 index 000000000..3bafaa664 --- /dev/null +++ b/intelmq/server.py @@ -0,0 +1,40 @@ +"""Main entrypoint for the API application + +SPDX-FileCopyrightText: 2022 CERT.at GmbH +SPDX-License-Identifier: AGPL-3.0-or-later +""" + +import os +import pathlib + +from fastapi import FastAPI +from fastapi.staticfiles import StaticFiles +from fastapi.middleware.cors import CORSMiddleware + +import intelmq.api.config +import intelmq.api.dependencies +import intelmq.api.exceptions + +from intelmq.api.router import router as api_router +from intelmq.web.router import router as web_router + +config = intelmq.api.config.Config() + +app = FastAPI(root_path=os.environ.get("ROOT_PATH", "")) + + +@app.on_event("startup") +def init_app(): + intelmq.api.dependencies.startup(config) + + +app.add_middleware(CORSMiddleware, allow_origins=config.allow_origins, allow_methods=("GET", "POST")) + +app.include_router(api_router, prefix="/api/v1") + +if config.enable_webgui: + static_files = pathlib.Path(__file__).parent / "web" / "static" + app.mount("/static", StaticFiles(directory=static_files), name="static") + app.include_router(web_router) + +intelmq.api.exceptions.register(app) diff --git a/intelmq/tests/api/__init__.py b/intelmq/tests/api/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/intelmq/tests/api/test_api.py b/intelmq/tests/api/test_api.py new file mode 100644 index 000000000..b7cd8f7cc --- /dev/null +++ b/intelmq/tests/api/test_api.py @@ -0,0 +1,211 @@ +"""Basic tests for the API endpoints + +SPDX-FileCopyrightText: 2022 CERT.at Gmbh +SPDX-License-Identifier: AGPL-3.0-or-later +""" + +import json +import os +import subprocess +import tempfile +from tempfile import TemporaryDirectory +from typing import Dict, List, Optional +from unittest import TestCase, mock + +from fastapi.testclient import TestClient +from intelmq.lib import utils # type: ignore + +from intelmq.api import dependencies +from intelmq.api.router import runner +from intelmq.api.config import Config +from intelmq.api.dependencies import session_store +# from intelmq.api.main import app +from intelmq.server import app +from intelmq.api.runctl import RunIntelMQCtl +from intelmq.api.session import SessionStore +from intelmq.api.version import __version__ + + +class DummyConfig(Config): + def __init__(self): + # Prevent loading from file + pass + + +class DummyRunner(RunIntelMQCtl): + + def __init__(self, base_cmd, paths: Optional[dict] = None): + super().__init__(base_cmd) + self._paths = paths + + def _run_intelmq_ctl(self, args: List[str]) -> subprocess.CompletedProcess: + # simulate dummy response from the CLI command + return subprocess.CompletedProcess(args, 0, b'{"some": "json"}') + + def get_paths(self) -> Dict[str, str]: + if self._paths is None: + return super().get_paths() + else: + return self._paths + + +def get_dummy_reader(**kwargs): + def dummy_runner(): + return DummyRunner([], **kwargs) + return dummy_runner + + +class TestApiWithCLI(TestCase): + def setUp(self) -> None: + self.client = TestClient(app=app) + dependencies.startup(DummyConfig()) + app.dependency_overrides[runner] = get_dummy_reader() + + def tearDown(self) -> None: + app.dependency_overrides = {} + + def test_version(self): + response = self.client.get("/api/v1/version") + self.assertEqual(response.status_code, 200) + self.assertIsInstance(response.json(), dict) + self.assertEqual(response.json()["intelmq-api"], __version__) + + def test_ensure_response_get_values_and_is_json(self): + json_paths = ["botnet?action=status", "bot?action=status&id=1", + "getlog?lines=1&id=1", "queues", "queues-and-status", + "bots", "check", "debug"] + + for path in json_paths: + with self.subTest(path): + response = self.client.get(f"/api/v1/{path}") + self.assertEqual(response.status_code, 200) + self.assertIsInstance(response.json(), dict) + self.assertEqual(response.json(), {"some": "json"}) + + def test_run_input(self): + response = self.client.post( + "/api/v1/run?bot=feodo-tracker-browse-parser&cmd=get&dry=false&show=false", + data={"msg": "some message"}) + self.assertEqual(response.status_code, 200) + + +class TestApiWithDir(TestCase): + def setUp(self) -> None: + self.client = TestClient(app=app) + dependencies.startup(DummyConfig()) + self.conf_dir = TemporaryDirectory() + app.dependency_overrides[runner] = get_dummy_reader( + paths={"CONFIG_DIR": self.conf_dir.name}) + + self.save_runtime() + self.save_positions() + + self.path_patcher = mock.patch( + "intelmq.lib.utils.RUNTIME_CONF_FILE", f"{self.conf_dir.name}/runtime.yaml") + self.path_patcher.start() + + def save_runtime(self): + with open(f"{self.conf_dir.name}/runtime.yaml", "w+") as f: + json.dump({}, f) + + def save_positions(self): + os.makedirs(f"{self.conf_dir.name}/manager", exist_ok=True) + with open(f"{self.conf_dir.name}/manager/positions.conf", "w+") as f: + json.dump({}, f) + + def tearDown(self) -> None: + app.dependency_overrides = {} + self.path_patcher.stop() + self.conf_dir.cleanup() + + def test_handle_path_with_doubled_slashes(self): + """The IntelMQ Manager doubles slashes in some paths, but FastAPI doesn't handle it. + + In addition, IntelMQ Manager doesn't respect redirection. As so, keeping the invalid + paths for backward compatibility.""" + PATHS = ["/api/v1//runtime", "/api/v1//positions"] + for path in PATHS: + with self.subTest(path): + response = self.client.post(path, json={}) + self.assertEqual(response.status_code, 200) + self.assertEqual(response.text, "success") + + def test_post_runtime(self): + data = { + "some-bot": { + "bot_id": "bot-1", + "description": "Test", + "enabled": True, + "parameters": { + "destination_queues": { + "_default": [ + "file-output-queue" + ] + }, + "overwrite": True, + }, + "run_mode": "continuous" + } + } + response = self.client.post("/api/v1/runtime", json=data) + + self.assertEqual(response.status_code, 200) + self.assertEqual(response.text, "success") + + self.assertEqual(utils.get_runtime(), data) + + def test_post_positions(self): + data = { + "some-bot": { + "x": 21, + "y": 314 + } + } + response = self.client.post("/api/v1/positions", json=data) + + self.assertEqual(response.status_code, 200) + self.assertEqual(response.text, "success") + + with open(f"{self.conf_dir.name}/manager/positions.conf", "r") as f: + saved = json.load(f) + self.assertEqual(saved, data) + + +class TestAPILogin(TestCase): + def setUp(self) -> None: + self.client = TestClient(app=app) + dependencies.startup(DummyConfig()) + self.temp_dir = tempfile.TemporaryDirectory() + self.addCleanup(self.temp_dir.cleanup) + + self.session = SessionStore(os.path.join(self.temp_dir.name, 'sessionsb'), 1000000) + self.session.add_user('test', 'pass') + + app.dependency_overrides[session_store] = lambda: self.session + app.dependency_overrides[runner] = get_dummy_reader() + + def tearDown(self) -> None: + app.dependency_overrides = {} + + def test_login(self): + response = self.client.post("/api/v1/login", data={"username": "test", "password": "pass"}) + self.assertEqual(response.status_code, 200) + self.assertIsNotNone(response.json().get("login_token")) + + def test_login_and_call(self): + response = self.client.post("/api/v1/login", data={"username": "test", "password": "pass"}) + self.assertEqual(response.status_code, 200) + + token = response.json().get("login_token") + authorized_response = self.client.get("/api/v1/version", headers={"authorization": token}) + self.assertEqual(authorized_response.status_code, 200) + self.assertEqual(authorized_response.json()["intelmq-api"], __version__) + + def test_unauthorized_call(self): + response = self.client.get("/api/v1/version") + self.assertEqual(response.status_code, 401) + + def test_bad_token(self): + response = self.client.get( + "/api/v1/version", headers={"authorization": "not-a-valid-token"}) + self.assertEqual(response.status_code, 401) diff --git a/intelmq/tests/api/test_sessionstore.py b/intelmq/tests/api/test_sessionstore.py new file mode 100644 index 000000000..765cab5c6 --- /dev/null +++ b/intelmq/tests/api/test_sessionstore.py @@ -0,0 +1,66 @@ +"""Tests for IntelMQ-Manager + +SPDX-FileCopyrightText: 2020 Intevation GmbH +SPDX-License-Identifier: AGPL-3.0-or-later +""" +import unittest +import tempfile +import os +from pathlib import Path + +from intelmq.api.session import SessionStore + + +class TestSessionStore(unittest.TestCase): + + def setUp(self): + self.temp_dir = tempfile.TemporaryDirectory() + self.addCleanup(self.temp_dir.cleanup) + + def test_basic_usage(self): + store = SessionStore(os.path.join(self.temp_dir.name, "sessiondb"), + 3600) + session_data = {"csrf_token": "very-secret"} + store.set("some-uniqe-id", session_data) + self.assertEqual(store.get("some-uniqe-id"), session_data) + + def test_unknown_session_is_None(self): + store = SessionStore(os.path.join(self.temp_dir.name, "sessiondb"), + 3600) + self.assertIsNone(store.get("some-unknown-id")) + + def test_set_overwriting(self): + store = SessionStore(os.path.join(self.temp_dir.name, "sessiondb"), + 3600) + store.set("just-a-session-id", {"some": "thing"}) + new_data = {"some": "other-thing"} + store.set("just-a-session-id", new_data) + self.assertEqual(store.get("just-a-session-id"), new_data) + + def test_new_session(self): + store = SessionStore(os.path.join(self.temp_dir.name, "sessiondb"), + 3600) + token = store.new_session({"username": "some-user"}) + self.assertEqual(store.verify_token(token), + {"username": "some-user"}) + + def test_verify_unknown_token(self): + store = SessionStore(os.path.join(self.temp_dir.name, "sessiondb"), + 3600) + token = store.new_session({"username": "some-user"}) + # Check that verify_token returns exactly False. This is what + # hug checks for as well in hug.authentication.authenticator + self.assertIs(store.verify_token("wrong-token"), False) + + def test_user_account(self): + store = SessionStore(os.path.join(self.temp_dir.name, "sessiondb"), + 3600) + store.add_user("someone", "some-password") + self.assertEqual(store.verify_user("someone", "some-password"), + {"username": "someone"}) + + def test_user_account_verify_failed(self): + store = SessionStore(os.path.join(self.temp_dir.name, "sessiondb"), + 3600) + store.add_user("someone", "some-password") + self.assertEqual(store.verify_user("someone", "wrong-password"), None) diff --git a/intelmq/web/__init__.py b/intelmq/web/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/intelmq/web/router.py b/intelmq/web/router.py new file mode 100644 index 000000000..3f08aaf85 --- /dev/null +++ b/intelmq/web/router.py @@ -0,0 +1,76 @@ +import pathlib +import collections + +from fastapi import APIRouter, Request +from fastapi.responses import HTMLResponse +from fastapi.templating import Jinja2Templates + +router = APIRouter(default_response_class=HTMLResponse) +templates_dir = pathlib.Path(__file__).parent / "templates" +templates = Jinja2Templates(directory=templates_dir) +Page = collections.namedtuple("Page", ["name", "title", "url", "icon_url"]) + + +def get_pages(request: Request): + return [ + Page( + name="configs", + title="Configuration", + url=request.url_for('get_configuration'), + icon_url=request.url_for('static', path='images/configuration.png'), + ), + Page( + name="management", + title="Management", + url=request.url_for('get_management'), + icon_url=request.url_for('static', path='images/management.png'), + ), + Page( + name="monitor", + title="Monitor", + url=request.url_for('get_monitor'), + icon_url=request.url_for('static', path='images/monitor.png'), + ), + Page( + name="check", + title="Check", + url=request.url_for('get_check'), + icon_url=request.url_for('static', path='images/check.png'), + ), + Page( + name="about", + title="About", + url=request.url_for('get_about'), + icon_url=request.url_for('static', path='images/about.png'), + ) + ] + + +@router.get("/") +async def get_index(request: Request): + return templates.TemplateResponse("index.html", {"request": request, "pages": get_pages(request)}) + + +@router.get("/configuration") +async def get_configuration(request: Request): + return templates.TemplateResponse("configuration.html", {"request": request, "pages": get_pages(request)}) + + +@router.get("/management") +def get_management(request: Request): + return templates.TemplateResponse("management.html", {"request": request, "pages": get_pages(request)}) + + +@router.get("/monitor") +def get_monitor(request: Request): + return templates.TemplateResponse("monitor.html", {"request": request, "pages": get_pages(request)}) + + +@router.get("/check") +def get_check(request: Request): + return templates.TemplateResponse("check.html", {"request": request, "pages": get_pages(request)}) + + +@router.get("/about") +def get_about(request: Request): + return templates.TemplateResponse("about.html", {"request": request, "pages": get_pages(request)}) diff --git a/intelmq/web/static/css/management.css b/intelmq/web/static/css/management.css new file mode 100644 index 000000000..37bbed35d --- /dev/null +++ b/intelmq/web/static/css/management.css @@ -0,0 +1,14 @@ +#botnet-panels > div.panel .panel-div { + margin-bottom: 16px; +} +#botnet-status { + padding: 8px; +} +#graph-container { + margin-top: 16px; + overflow: auto; +} +#bot-table-panel { + overflow: auto; +} +/*# sourceMappingURL=management.css.map */ \ No newline at end of file diff --git a/intelmq/web/static/css/management.css.map b/intelmq/web/static/css/management.css.map new file mode 100644 index 000000000..daf0441da --- /dev/null +++ b/intelmq/web/static/css/management.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["../less/management.less"],"names":[],"mappings":"AAAA,cAAe,MAAK,MAChB;EACI,mBAAA;;AAIR;EACI,YAAA;;AAGJ;EACI,gBAAA;EACA,cAAA;;AAGJ;EACI,cAAA","file":"management.css"} \ No newline at end of file diff --git a/intelmq/web/static/css/sb-admin-2.css b/intelmq/web/static/css/sb-admin-2.css new file mode 100644 index 000000000..d879f96bc --- /dev/null +++ b/intelmq/web/static/css/sb-admin-2.css @@ -0,0 +1,437 @@ +/*! + * Start Bootstrap - SB Admin 2 Bootstrap Admin Theme (http://startbootstrap.com) + * Code licensed under the Apache License v2.0. + * For details, see http://www.apache.org/licenses/LICENSE-2.0. + */ +body { + background-color: #f8f8f8; + overflow: auto; +} +@media (min-width: 768px) { + body { + overflow: hidden; + } +} +#page-wrapper { + margin: 0px; + padding: 0px; + min-height: 568px; + background-color: #fff; +} +#page-wrapper-with-sidebar { + padding: 0px; + min-height: 568px; + background-color: #fff; +} +@media (min-width: 768px) { + #page-wrapper-with-sidebar { + position: inherit; + margin: 0 0 0 250px; + padding: 0px; + border-left: 1px solid #e7e7e7; + } +} +.navbar-top-links li { + display: inline-block; +} +.navbar-top-links li:last-child { + margin-right: 15px; +} +.navbar-top-links li a { + padding: 15px; + min-height: 50px; +} +.navbar-top-links .dropdown-menu li { + display: block; +} +.navbar-top-links .dropdown-menu li:last-child { + margin-right: 0; +} +.navbar-top-links .dropdown-menu li a { + padding: 3px 20px; + min-height: 0; +} +.navbar-top-links .dropdown-menu li a div { + white-space: normal; +} +.navbar-top-links .dropdown-messages, +.navbar-top-links .dropdown-tasks, +.navbar-top-links .dropdown-alerts { + width: 310px; + min-width: 0; +} +.navbar-top-links .dropdown-messages { + margin-left: 5px; +} +.navbar-top-links .dropdown-tasks { + margin-left: -59px; +} +.navbar-top-links .dropdown-alerts { + margin-left: -123px; +} +.navbar-top-links .dropdown-user { + right: 0; + left: auto; +} +.sidebar .sidebar-nav.navbar-collapse { + padding-right: 0; + padding-left: 0; +} +.sidebar .sidebar-search { + padding: 15px; +} +.sidebar ul li { + border-bottom: 1px solid #e7e7e7; +} +.sidebar ul li a.active { + background-color: #eee; +} +.sidebar .arrow { + float: right; +} +.sidebar .fa.arrow:before { + content: "\f104"; +} +.sidebar .active > a > .fa.arrow:before { + content: "\f107"; +} +.sidebar .nav-second-level li, +.sidebar .nav-third-level li { + border-bottom: 0!important; +} +.sidebar .nav-second-level li a { + padding-left: 37px; +} +.sidebar .nav-third-level li a { + padding-left: 52px; +} +#customListItem { + border-bottom: none; + padding-top: 10px; + padding-bottom: 10px; + text-align: center; +} +@media (min-width: 768px) { + .sidebar { + z-index: 1; + position: absolute; + width: 250px; + margin-top: 0px; + } + .navbar-top-links .dropdown-messages, + .navbar-top-links .dropdown-tasks, + .navbar-top-links .dropdown-alerts { + margin-left: auto; + } +} +.btn-outline { + color: inherit; + background-color: transparent; + transition: all .5s; +} +.btn-primary.btn-outline { + color: #428bca; +} +.btn-success.btn-outline { + color: #5cb85c; +} +.btn-info.btn-outline { + color: #5bc0de; +} +.btn-warning.btn-outline { + color: #f0ad4e; +} +.btn-danger.btn-outline { + color: #d9534f; +} +.btn-primary.btn-outline:hover, +.btn-success.btn-outline:hover, +.btn-info.btn-outline:hover, +.btn-warning.btn-outline:hover, +.btn-danger.btn-outline:hover { + color: #fff; +} +.chat { + margin: 0; + padding: 0; + list-style: none; +} +.chat li { + margin-bottom: 10px; + padding-bottom: 5px; + border-bottom: 1px dotted #999; +} +.chat li.left .chat-body { + margin-left: 60px; +} +.chat li.right .chat-body { + margin-right: 60px; +} +.chat li .chat-body p { + margin: 0; +} +.panel .slidedown .glyphicon, +.chat .glyphicon { + margin-right: 5px; +} +.chat-panel .panel-body { + height: 350px; + overflow-y: scroll; +} +.login-panel { + margin-top: 25%; +} +.flot-chart { + display: block; + height: 400px; +} +.flot-chart-content { + width: 100%; + height: 100%; +} +table.dataTable thead .sorting, +table.dataTable thead .sorting_asc, +table.dataTable thead .sorting_desc { + background: transparent; +} +table.dataTable thead .sorting_asc:after { + content: "\f0de"; + float: right; + font-family: fontawesome; +} +table.dataTable thead .sorting_desc:after { + content: "\f0dd"; + float: right; + font-family: fontawesome; +} +table.dataTable thead .sorting:after { + content: "\f0dc"; + float: right; + font-family: fontawesome; + color: rgba(50, 50, 50, 0.5); +} +.highlightHovering td:first-child:hover { + font-weight: bold; + cursor: pointer; +} +.btn-circle { + width: 30px; + height: 30px; + padding: 6px 0; + border-radius: 15px; + text-align: center; + font-size: 12px; + line-height: 1.428571429; +} +.btn-circle.btn-lg { + width: 50px; + height: 50px; + padding: 10px 16px; + border-radius: 25px; + font-size: 18px; + line-height: 1.33; +} +.btn-circle.btn-xl { + width: 70px; + height: 70px; + padding: 10px 16px; + border-radius: 35px; + font-size: 24px; + line-height: 1.33; +} +.show-grid [class^=col-] { + padding-top: 10px; + padding-bottom: 10px; + border: 1px solid #ddd; + background-color: #eee!important; +} +.show-grid { + margin: 15px 0; +} +.huge { + font-size: 40px; +} +.panel-green { + border-color: #5cb85c; +} +.panel-green .panel-heading { + border-color: #5cb85c; + color: #fff; + background-color: #5cb85c; +} +.panel-green a { + color: #5cb85c; +} +.panel-green a:hover { + color: #3d8b3d; +} +.panel-red { + border-color: #d9534f; +} +.panel-red .panel-heading { + border-color: #d9534f; + color: #fff; + background-color: #d9534f; +} +.panel-red a { + color: #d9534f; +} +.panel-red a:hover { + color: #b52b27; +} +.panel-yellow { + border-color: #f0ad4e; +} +.panel-yellow .panel-heading { + border-color: #f0ad4e; + color: #fff; + background-color: #f0ad4e; +} +.panel-yellow a { + color: #f0ad4e; +} +.panel-yellow a:hover { + color: #df8a13; +} +.jumbotron { + margin-bottom: 15px; + margin-top: 15px; + margin-left: auto; + margin-right: auto; + padding: 0px; + text-align: center; + height: 100%; + max-width: 90%; +} +.jumbotron .page-header-text { + background-color: #000000; + background-size: contain; + max-width: 100%; +} +.jumbotron .page-header-text span { + color: #ffffff; + text-align: center; + height: 100%; +} +.jumbotron-row { + margin-top: 15px; +} +.center-row { + text-align: center; +} +.center-row-content { + overflow: auto; + display: inline-block; + float: none; + margin: auto; +} +.header-img img { + height: 100px; + padding: 5px; +} +.thumbnail img { + width: 128px; + height: 128px; + padding: 15px; +} +.form-group { + margin-bottom: 45px; +} +#bot-table td:first-child:hover { + font-weight: bold; + cursor: pointer; +} +#network-popUp { + display: none; + position: absolute; + top: 15%; + left: 5%; + margin: auto; + z-index: 299; + background-color: #FFFFFF; + border-style: solid; + border-width: 3px; + border-color: #5394ed; + padding: 10px; + width: 90%; + text-align: center; +} +@media (min-width: 768px) { + #network-popUp { + left: 25%; + width: 50%; + } +} +#network-popUp-fields { + background: #FFFFFF; + width: 100%; +} +#network-popUp-fields input { + width: 100%; +} +#network-popUp-fields td { + text-align: left; +} +form { + display: inline-block; + margin-bottom: 10px; +} +#border { + text-align: center !important; + font-weight: bold; +} +#network-popUp-title { + width: 100%; + font-size: 28px; + display: inherit; +} +#network-row { + display: none; + height: 90%; +} +#network-row.col-xs-10 { + height: 100%; +} +#network-row.col-xs-2 { + height: 100%; +} +#network-tab { + height: 100%; +} +.with-bot { + max-height: 75%; + overflow-y: auto; +} +#logs-panel { + margin-top: 15px; +} +#queues-panel { + margin-top: 15px; +} +#queues-panel .width-80 { + width: 80%; +} +#queues-panel .width-20 { + width: 20%; +} +.waiting { + background-image: url('../images/waiting.gif'); + background-repeat: no-repeat; + background-size: 16px; + background-position: right 10px center; +} +.row { + margin: 0px; +} +.navbar-config { + margin-right: 16px; +} +.index-link:hover { + text-decoration: none; + box-shadow: 1px 1px 16px #000000; +} +.index-link { + display: block; + box-shadow: 1px 1px 16px rgba(0, 0, 0, 0.2); +} +/*# sourceMappingURL=sb-admin-2.css.map */ \ No newline at end of file diff --git a/intelmq/web/static/css/sb-admin-2.css.map b/intelmq/web/static/css/sb-admin-2.css.map new file mode 100644 index 000000000..aa7778b12 --- /dev/null +++ b/intelmq/web/static/css/sb-admin-2.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["../less/sb-admin-2.less"],"names":[],"mappings":"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","file":"sb-admin-2.css"} \ No newline at end of file diff --git a/intelmq/web/static/css/style.css b/intelmq/web/static/css/style.css new file mode 100644 index 000000000..667d05e83 --- /dev/null +++ b/intelmq/web/static/css/style.css @@ -0,0 +1,149 @@ +/* + * Navigation + */ +nav ul.nav.navbar-top-links li.active { + color: #555; + cursor: default; + background-color: #fff; + border: 1px solid #ddd; + border-bottom-color: transparent; +} +/* + * Common elements + */ +#common-templates { + display: none; +} +#wrapper .navbar #log-window { + background-color: black; + color: white; + display: none; + float: right; + margin: 5px 5px; + padding: 5px; + width: 500px; + height: 44px; + overflow: auto; + resize: vertical; + position: absolute; + top: 0; + right: 0; + cursor: pointer; +} +#wrapper .navbar #log-window.extended { + height: auto; + max-height: 100vh; + width: auto; + cursor: unset; + overflow: scroll; +} +#wrapper .navbar #log-window [role=close] { + float: right; + cursor: pointer; +} +#wrapper .navbar #log-window .command { + 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; + overflow: auto; + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; +} +#wrapper .navbar #log-window .alert a { + text-decoration: underline; + display: inline-block; + padding: 4px; + border: 1px solid #ccc; + border-radius: 10px; +} +.fa { + font-family: FontAwesome; +} +.control-buttons [data-url=status] { + display: none; +} +/* + * Management page + */ +#botnet-panels > .panel[data-botnet-group] { + display: none; +} +#botnet-panels > .panel[data-botnet-group][data-botnet-group=botnet] { + display: block; +} +/* + * Monitor page + */ +#botnet-panels .panel .control-buttons [data-role=control-status] { + display: none; +} +#inspect-panel .control-buttons { + float: right; +} +#inspect-panel button[data-role="clear"] { + float: right; +} +#inspect-panel #command-show { + display: none; +} +#inspect-panel textarea { + resize: vertical; +} +/* + * Config page + */ +#templates { + display: none; +} +#network-container .control-buttons { + float: left; +} +#network-container .control-buttons button { + height: 25px; +} +#network-container .control-buttons button span { + top: -2px; +} +#network-container .monitor-button div a { + color: black; +} +#network-container .duplicate-button { + background-image: url('../plugins/vis.js/img/network/addNodeIcon.png'); +} +#network-container .network-right-menu > div { + display: block; +} +#network-container .network-right-menu .vis-live-toggle, +#network-container .network-right-menu .vis-physics-toggle { + border-radius: 10px; + position: absolute; + right: 560px; + top: 35px; + white-space: nowrap; + padding: 5px 0 5px 5px; + cursor: pointer; +} +#network-container .network-right-menu .vis-live-toggle.running, +#network-container .network-right-menu .vis-physics-toggle.running { + background-color: #00D000; +} +#network-container .network-right-menu .vis-live-toggle .icon { + background-image: url("../images/monitor.png"); + background-repeat: no-repeat; + background-size: 30%; + padding-left: 30px; + padding-right: 15px; + position: relative; + z-index: 20; +} +#network-container .network-right-menu .vis-physics-toggle { + right: 480px; +} +/*# sourceMappingURL=style.css.map */ \ No newline at end of file diff --git a/intelmq/web/static/css/style.css.map b/intelmq/web/static/css/style.css.map new file mode 100644 index 000000000..743088e70 --- /dev/null +++ b/intelmq/web/static/css/style.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["../less/style.less"],"names":[],"mappings":";;;AAGA,GAAI,GAAE,IAAI,iBAAkB,GAAE;EAC5B,WAAA;EACA,eAAA;EACA,sBAAA;EACA,sBAAA;EACA,gCAAA;;;;;AAMF;EACE,aAAA;;AAGF,QAAS,QAAQ;EACf,uBAAA;EACA,YAAA;EACA,aAAA;EACA,YAAA;EACA,eAAA;EACA,YAAA;EACA,YAAA;EACA,YAAA;EACA,cAAA;EACA,gBAAA;EACA,kBAAA;EACA,MAAA;EACA,QAAA;EACA,eAAA;;AAEA,QAhBO,QAAQ,YAgBd;EACC,YAAA;EACA,iBAAA;EACA,WAAA;EACA,aAAA;EACA,gBAAA;;AArBJ,QAAS,QAAQ,YAwBf;EACE,YAAA;EACA,eAAA;;AA1BJ,QAAS,QAAQ,YA6Bf;EACE,cAAA;EACA,cAAA;EACA,gBAAA;EACA,eAAA;EACA,uBAAA;EACA,WAAA;EACA,qBAAA;EACA,qBAAA;EACA,yBAAA;EACA,sBAAA;EACA,kBAAA;EACA,cAAA;EACA,sCAAsC,wBAAtC;;AA1CJ,QAAS,QAAQ,YA6Cb,OAAO;EACH,0BAAA;EACA,qBAAA;EACA,YAAA;EACA,sBAAA;EACA,mBAAA;;AAIR;EACE,wBAAA;;AAGF,gBAAiB;EACf,aAAA;;;;;AAMF,cAAe,SAAQ;EACrB,aAAA;;AACA,cAFa,SAAQ,mBAEpB;EACC,cAAA;;;;;AAOJ,cAAe,OAAO,iBAAiB;EACrC,aAAA;;AAGF,cACE;EACE,YAAA;;AAFJ,cAKE,OAAM;EACJ,YAAA;;AANJ,cASE;EACE,aAAA;;AAVJ,cAaE;EACE,gBAAA;;;;;AAQJ;EACE,aAAA;;AAMF,kBAEE;EACE,WAAA;;AAHJ,kBAEE,iBAGE;EACE,YAAA;;AANN,kBAEE,iBAGE,OAGE;EACE,SAAA;;AATR,kBAcE,gBAGE,IAAI;EACF,YAAA;;AAlBN,kBAsBE;EACE,sBAAsB,gDAAtB;;AAvBJ,kBA0BE,oBACE;EACE,cAAA;;AA5BN,kBA0BE,oBAKE;AA/BJ,kBA0BE,oBAKoB;EAChB,mBAAA;EACA,kBAAA;EACA,YAAA;EACA,SAAA;EACA,mBAAA;EACA,sBAAA;EACA,eAAA;;AAEA,kBAdJ,oBAKE,iBASG;AAAD,kBAdJ,oBAKoB,oBASf;EAGC,yBAAA;;AA3CR,kBA0BE,oBAqBE,iBAAiB;EACf,sBAAsB,wBAAtB;EACA,4BAAA;EACA,oBAAA;EACA,kBAAA;EACA,mBAAA;EACA,kBAAA;EACA,WAAA;;AAtDN,kBA0BE,oBA+BE;EACE,YAAA","file":"style.css"} \ No newline at end of file diff --git a/intelmq/web/static/images/1140x319.gif b/intelmq/web/static/images/1140x319.gif new file mode 100644 index 0000000000000000000000000000000000000000..8df8f1066a81b5d5b3a6d84194c4d1f77841d7f2 GIT binary patch literal 3681 zcmV-n4xaHxNk%v~VRQsP0pkDw%*@P|mX@ljs=mIyoSdA+#l^R`x1*z@v9YlL00000 z00000000000000000000EC2ui0CWUD0RRO45XecZy*TU5yZ>M)j$~<`XsWJk>%MR- z&vb3yc&_h!@BhG{a7Zi~kI1BQ$!t2G(5Q4uty-_xtai)odcWYXcuX#v&*-#z&2GEj z@VIs;jK6uCK7Mva__cwzs&sy1Tr+zQ4f1!o$SH#>dFX%FE2n&d<=%($mz{*4NnC z+S}aS-rwNi;^XAy=I7|?>g(+7?(gvN^7Hid_V@Vt`uqI-{{H|23LHqVpuvL(6DnND zu%W|;5F<*QNU@^Dix@L%+{m$`$B+IXLy8oJq5$&6_xL z>fFh*r_Y~2g9;r=w5ZXeNRujE%CxD|r%fOt?uiw9b0}CEZxUk{Fh!ZPb%($`R$B-jSo=my2 z<;$2eYu?Pcv**vCLyI0wy0q!js8g$6&APSg*RW&Do=v;9?c2C>>)y?~x9{J;g9{%{ zytwh>$dfBy&b+zv=g^}|pH98H_3PNPYv0bjyZ7(l!;2qJzP$PK=+moT&%V9;_weJ( zpHIKO{rmXy>)+46zyJRL2L34EfCLt3;DHDxsNjMOHt67k5Jo8BgcMe2;e{AxsNsej zcIe@UAciO+2L%`)zySmV5C8!O2w*?~l?;FYiYl(y;)`e$fWV0q@M2*5a^Hv-gX zWB@o6d8CRu6hHt01K2RY0ZT4Ilg20_s9+2k@Z*u9vo_tn`K$_JQ5T>9rD9UFJ1uQARpDGwoD3@3! z;^d`<(%|TwENsf@k_1qS=rVzVDnqJp;$Y{Jhq6HEs7JmZg!d*rSzB&#Y4)mnRGroa4x66&b#EW;SQtiu`T?oYz^{~nnI-d)@bS;%qAQFyd?-+E(xMK zyyC+B?s6}!=8_9=4IUc_@d&Rbd_W)-Ta57s8>4$d$rhiS@h=j8j6%%=&j4+e1f)=~ zz9Z+cXv`+yJh2ErI~?@PwX~dTr6FHhL(0P59CeM8N?`QGel%?HyCgWxu?bht+cVR- zY@IX3LkC;K&Q_)X_mU7NZRE6iz|5tKFqWt{&myROGzfF^jAMyqON;g`V!O?5;x^M+ zD8D6?jrRoph1YoY9(HR^xdd%j%`)U`hX8rK6ohW@;#MLjFA2`O+i0OHf6zPF8FU_i%y}SOrn4F(-a+)< zmXQ4R8(gm<>ddopewUGd@V<)bBPoOW>{EO@2W40PM&{Vlfc65gyb8>3d-3}~;;Lu7 z)wQn`-n)~R0Fb~AM6gT~te^@ScqIRI0Du9woCQEA!Z}(!)T&$ToGrlNkWz1k_hbQ&#eltpL&nWGTZs@{&YlJ7frk=*U4*B9gk) zz%PUO0VDbdm$~?52&CD>Tdu&29}p!Zw26XWQttz;JQ6f4LnTnZ8a>pS z>bxlhm|4s_DUzv86)Op93Pj9tX{#DYo=+tJQ5evQQZY3WQPXMERtb@gA6OztR}^-WPz6CCClIw^G8Uv5w5wJv z&{eNeR*Ek8MQXsGPB!Vgd{+m_I0zj&@ z9N=7U3yR$8Q?U^n?Gv%fzu>-bxGyjOik_rGTi)(TSL%UKFWynZr8mUh$-a?I!(1Ycml~25=tL? z0|Fn(Pco3EJc%e(^f8zf7p9R(2L0AH^OfdjZ8Y}G?I0hcB-3+9eSMXJUYR5bA zDpFidsZz?B6@D>{S1f`Xay6tw$T0zHK+XBVYrWGI@+OGPWB_osh)RxemrZx40ig88 zIL?)AFRSDVl-Nf=5^nqv8M)RXbfY!#Xg-Gku@?Yfk|DjzKLa{iS$>iY$Y);?Ghd7m^Y4*%5GWBu9@b#01LH*y5M zjjNK2D%|hs;LS#wuMl)}saSUaprEFesHuGkYws7Fz-H~X^}NXc#z4^~hJsX)4OwXC z`D?jmcO=}M(h%e~1J@(-oj!_EeoJmt;w}PoW6SIHUdq`5#{|Lk8UhI;wb&RCaAV)f zgZW|H2-)tduuVWdGrcq78Mnm7T`STS=T6BYM=i;BfZYCo1A(k7C@cUcr9OwpJQFh? zYBRst>y>M}r>}Nw58kKgaQ*Zl5{udd!fi+24={@Q%>JHjt-gLM1+2OY)ws+|r4scJs-j!3#p z`+Rz|+dICaeZiI#-zVz4pJ?>>5eAB=C?7c^Q2H*~PZ#N0oR;a0r0WiSZFP{;* zpMCT>u7R9uAoe@J_xge`fUJrC`6iHYOpX5iUH*H%>9pVb_zRwam39E|%VI4s=K{+` zd@*%=`Nsn1Gl2E?2;p~N`v-q+W_BDfQaX@nQ6qaW;4~eleCBk2lqW$AD0(3HRLJ*W z5lC|xV0?45a5>;if>vfZ&^XhDew}xM*~N4t*a;7)K+E=nKp2F~c3$MgVF<+mHi!dP zQvd};e<~0)P6z-XM11%seK3$2;_LVqPXo!cXh@@AC{wimMYX^E35O0lgHPdoKuLp>fxPpbEfe`44 znFWcQ2#2!heEeqv(o|k)XMKg1hc4ENGf+RfLyVy)foup{wYX)7sA9Khf}ogcRJ2Bm zhXW|ZP)A4uC5A%7qj#TGV&1omhp>gZxMF$bermIdl;nsK&{3OchHZ!@GloW&5{{oJ zidOTA;y4L%CWLJmgjCp%LHLhA_>PMhjnc>|q+^d8FeS^jRAsYlWr&2mS9l^NgoFo> zB~U*WxsQz?c?#8cp5||J)`m1NXC;(leHdwySB4-t0`F6Z9{C3^8H-;tl8k5p;C3l8 zX_J?7Qj;|%CCNg9C~YGkPYgN!lX*~+A9$1Pm6Oz%FcaC7`nY-y6$3kYDIMvPuM+~> zsFaexl)UGZ&GmS<7GyL)E4#B^G+=ScxK<*`N<;~kjz^YM*_CApl?fSYT&R%UHF-1O zmSr-P&S;lt*oNvzmvCW_qS*nx<;Hrfk}#Zu+Kh8mDqP zr*vAUc6z6Hnx}fYr+nI{e)^|?8mNLgsDxUmhI*)ony8ApsEpdEj{2yO8mW>xsgzo& zmU^j}nyH$)sU)1*sh;|&pc<;8I;x~vs-}9XsG6#(x~i<&s;>H~uo|ms5di=@e|Qh3 literal 0 HcmV?d00001 diff --git a/intelmq/web/static/images/about.png b/intelmq/web/static/images/about.png new file mode 100644 index 0000000000000000000000000000000000000000..b56971511546baf05e964076f2c73fbfc160d578 GIT binary patch literal 6370 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 Kg{PYkuKo`ZQo05J literal 0 HcmV?d00001 diff --git a/intelmq/web/static/images/abouticon-20.png b/intelmq/web/static/images/abouticon-20.png new file mode 100644 index 0000000000000000000000000000000000000000..8b77935e29e4fe602b0efa01c66d6dff2b04c438 GIT binary patch literal 795 zcmV+$1LXXPP)h(&y-7qtR5*>Ll|gG0Q51#Gc`uJl8*9xl z#8|RwgGeET2o@@Iui#QB1(#j;FRJ1na9MEYrVH)LUtpo7V6`DoDvt4lC~N0 zOs|VfOVmuJ;MvXGGav8Xx%WOIUMv&}j_bM;#u&$1>i~c;CbZUuK@hZk-wy%E(2s|` zoSU1=7-PyJvM3_=NzMS6iNbXesgv9yx!LJ-_V)MpPZGhUQfb;4^MvFwfIA~H0)PV% zS+~}{saC6pg8@DGP%f8?TI*GkD*&bvpa9^JoL5TS%;)pfMxzn@11^8voacF!X0v&8365&|l;lbr^!)sMr`PK(0(cMLF3H?QjHDr1R7$n8+3aqs z)#@q$G{%&pnr7mTMRM=-^z=us*ZU5jKEyIka@ld5G63pAp)i)oWR^%SC8Ru+PN#+B zLz0h3Izv1jfST6&W6E{iiKwMwi6U|WpbOxIQfe4*(7WKe?(38>#u1U37*hwpj)<%S z_(HM-;3a??BiKb_jH9B78VUxGCRtWWJ+Rh(?RL9wMdZV%6O){_);cP|qyS8ch?`EQ zRrD^Y6a)Zej0rLPFAr+>`1tr#YwZD;Pw>`_F`=^7h9VLR7LiayKGkZqGXVE6y1oEV zv(|nw_L@xK9st<%eLvIy zkj-X;R4R3yeaB{Y_l z@}Q!Ae`l>-y;z@@+pXDb9_91-D#;wl;*gWa=?uVzh&-=UDwj?0$3AW}8iD6|6{S?0 zTdV*8002ovPDHLkV1k3lZR-F4 literal 0 HcmV?d00001 diff --git a/intelmq/web/static/images/abouticon-24.png b/intelmq/web/static/images/abouticon-24.png new file mode 100644 index 0000000000000000000000000000000000000000..3e9f35343cb1f5ed95f95ef33e48e1abdd4a0ce4 GIT binary patch literal 1005 zcmVh($8FWQhbW?9;ba!ELWdK2BZ(?O2No`?g zWm08fWO;GPWjp`?0n2GrSaeuTOgdw4Z7yMCZ(?OGcx`Y10RUB0MlCo1SWQeiV{dIP zVPtP&WiEJaZ~!QgeNxMA+b|IP6@s}|A}Lu`OhgS_$wG5b5jY0gt4uL5;qU>Ht`+}U z5Ba42LMbP5ivkKyyUUr~S#oY}d(*N#_h8GPgeu_gU#}2|u7KaO1~;bUJMr~o`NQek zhMo3o(ZSo#;HIa&G?M!k^zvCb+840x^p?{Q4`l?w8RGW^Tn-oDM{^HKZ8^wd95Fn{ zU`}F^&hk9}1QJXz!U-ZtL~@!Y6l3syV3=mRN4l=+_gNt;;LdwP5jq}^@iC3HeL`fh zSPVUqBnpVgy(r)Ik#bjKhl)F9h4DfwFy!r4AAAAfxPmm7w#volbz-I^>RW?IjL|>9 zrui5uMwcAFQ&(V9Dbu#5-z)j&41w7m7&ZnS>foK>3h?re#76 z`5E6d^iDb7D#q`s0)|Q~L`TUi&+6qWORHr@$ckLot8!K6Uy|!(R#tg6ax2Xak}E%Q zyT9D|BzLgF8=G74lXtb%5}a42Vp>Z&t>ul|O>3D=a#0Y2{`=^$6x=g}7u$y9VtlTG z+ikG*AK&ZC(c&;S4dlSxEDR7i=vmfvl{Fc62oRDCbqAWTq@d8gfgZU7@NLB#}& zKsrI`2Jp^FY(PfH2JS=7;VAjzAjD6KWW{&)Ik~gXiT9pI=ouhMl12mPTnfy9DUbpq zojL+Jum`pxk~hWh-jjImYe5S50_Ks6&VW@Nuo2{(n*(cL5D5t?fTf6Jogjs5dIJ7y zVPW2Tp6u+MAOIVURjC4LPSz1YcEGEMB*3=CZmlsdL6nJ)$;q#X6gvKHu^VVifHFsu z$s`3%5fCWL`cub0oXfpQ!^7c_hcB8%LeRh`eYzl3>;RfZLUPI+742phnp#jA0ayZK z5%~ay`YuMP1$F&`l(Hf>09p)fg>wiH%lmAHy#=)$B|$qge(M3+Rv_&mS%*WPy%Us${$#6e)e&s&oO{=WEhvwn zwjwGtCctGsx?`IF)03|Hkxne`2?@H|um*NZPKr86Ey%#ebQg$KMtK(2`ZV5xg6?|V bdW8M}|Fo^AX`Xvq00000NkvXXu0mjfbeO`- literal 0 HcmV?d00001 diff --git a/intelmq/web/static/images/check.png b/intelmq/web/static/images/check.png new file mode 100644 index 0000000000000000000000000000000000000000..a3c5dc1e82ab57b71f40bf82dec51ff7d76c6839 GIT binary patch literal 3060 zcmdT`X;9PG7XK$9VHJvi2ndJ^vIYyXSum`c=pZ(N$R<$=$d;r86BZ$f2-dO)D2tFP zLf99BY=(e|J_}Y61lc4&f~a9B1R9YgKwkR3yqVYbP3L`kckZ3D{pOtCIUnwvn`cg+ z*rA}U006)a6w(b103fLf0_0#)5fD=qDityW7nGNr^jwwu?gyzYk4O3v06_Wq?+=t` zs;nb*YQ?&rk3EYEjU`=-2?0nX5 zTkFPhSi$hMa&tF(H@QQ`d!Y|poW3#}@>knmdI@}9g#ycz34ZK$O?kUgrZZ1*DIRXtHr&Wt98CN zK&adUf4GCuYAuRJQTlughJ;bUs4^H4?sKe6P6FST59JFvXT42Ls`@}nhM0p41v^zc zrSpC*``nk!mUiP2cv-yW60b%hvl<6tsM|s8WbL4ZK5cvCDFxI-iVo#Icz!P5%HamU zgV+FPu~^+n8(<{6sPttlfZxx!yCGpH>cl%+2FCbL#2v=MfRI9GS!NS4(4b(cG+q zD=}N8p{gwqehl9#FETsAe%GkRT68@)0>%lWzA{OEG6<~%Ji#i%YfF9;lx`5a`{vP| zbomp9Amj*fN~8>D=YVEXWNKf2dxZI{=Cmj}d1liF5j9p2{^dRS$0KLwwJH;BKij{eoT8>{Z>;~s0FS!7dywx>-Te=@nOY5B_6`^ac4gW?G1K)K)F*b?s|-1^(FBY zu6yB*y`3!x7sdQyQ*UT))>svztNnT(KlCMSnjOyk(p6v5LuKY-dogAq_Tdvu;{n{A zvibZnRS$qy+QU3n6$bLjB|9|)k7`Qxq2GpnB25A`pC+TsDDdNZo1!fp^O1?dbvm3$ zOIbdVhB$@K)g_aQWwssxYmj)srrO|ag#~)6aWmq57`Y{w#7s^rMsI+TCcrRu@7d zjAnm$L_COd=b3UXnBKQDhz{G&7%Zn7GbYlgZNEsK@ah*9^k~CYu76Wef7Z{6oE&Qf z?|iivELg%8F8Sy*dHIkQwvA`BupQ0quJNh~P~*JKAnSIpe|cYYL1XPrMv`#9F6Du* z%;xp}_7y`^aPJV}ES(S^@am+7WpM=r)0dH?Z+yBElsu;hNWY&PUP;h1xhIX5}7bNNkghavh! z+Ybke3?@Kkd#|)C*ltOLB?IE&E(|NkTgez`fSpbny1(FEmaY13(Z||Vo+6qRoV5S4 zT3cfv!$HyAH8;Aplf6e)fzdB-ECe?tZqx;%<77%0D`;rN9{2=7go$0*eqCAul~(Z( zC`p-OPS-pf^>Wjm6|#t!vm;kqZR`O6p6of$t+36EL@K0foMc^=DJnQxE(8JL%<^f} zt6R5%xpCCD$H#HB^(}Ozk^!){UawhU?P;M{2pxw7blfJB$BFDgV^?{Al1Xm_1Xhy- z>N;lxDV!>vXHpiDcRb4mV~WQG;4slfAM{)>D+u!SbAa;cp5o}@NQsg)fDsd@-*;~O z3)}mq0>U2a>e*^@)U>;EWb6%*4GWn8oq1V#d{aEXeA?OZ@CQRD56wZi)0h^_DZW?e zgWC;+)IYtlHMk$Mc3)9es*K1lM(&CQa0S9!b z1TCE2Q|+sB5ARt5+q^1~T)>EDXDHAyY$TG4TCE*XqP$z^*#Jvty}C!iVVj$RIM#Uu z#hbi7o_});8kJ+LQXasvf!3?cPnG$CCCCR_hgx;R@V$@ckU3B&> zXlW!P$+HVXp4N5i%GzwJ@(aGPYZAFb5r9M+GcbwHK@24mq_`Pb$$di#Vli6-L|H`Vr| z!f(o5>Uc+@VvX34qVod5V^0#NJdWmXLM)*HsRkvBMY30mEd?9><|C7jxkdyG7DmJ| ziQ({cs=pB-OVa*v%)jwROW81mxa%GL-e^=Ma0|V-nM`7RY!hH#>e35P(e10N7t(?Q zYuc=d?!)vT_x5>|U#))HH?XvDGT~FR1%CI^Cm3QrhM&G;dvl~p6-Y-V(Uli-S`+Ua zSvL>ck(o1eUTrC!uQVWsK+VEe%9^h(yLRRr_XJBolRmSea`^g@rCM$M07BJN3I|Jv zs~gw6LhcW#t#TY*Bl4XFkj}PM0mP!4ybni2#lpFAb`IoKAcDI#h-}khKaBfjGS`>2>60&2LNfDWB z_!AwxIUXF|j48vp=lC)79;?S`>ay0v81jJ2-g1G;W2SXyG`ImWdF_#|QUD~XWE)Xe z%$<*(rwX&%+rD|2-UnRh+sRMi*mJ65%QRib6vmlH zsEs~)g`;ax2LTaovN1tlktA03fesgUQc{qSjTQ$zrem!yejG(^WIoA?&5@)W`55pg fOYVVcs05PUn*HuN?=Vxkp#v!Q({2qem}~z8c!*k5 literal 0 HcmV?d00001 diff --git a/intelmq/web/static/images/check.svg b/intelmq/web/static/images/check.svg new file mode 100644 index 000000000..1b8f52969 --- /dev/null +++ b/intelmq/web/static/images/check.svg @@ -0,0 +1,122 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/intelmq/web/static/images/configuration.png b/intelmq/web/static/images/configuration.png new file mode 100644 index 0000000000000000000000000000000000000000..035ddf5736e716a182536e239eca12b26e3cb62e GIT binary patch literal 11566 zcmV+}Ez#16P)4Tx0C=38mUmQC*A|D*y?1({%`g-xL+`x}AiX!K(nMjH8DJ;_4l^{dA)*2i zMMMM@L4qO%jD{kyB8r88V8I@cAfUux6j4!mGqP56<>kGXm){>}eQTe+_dRFteb%}F zki7l5ymVL!fHa~vAmcQ z7uoQ$&mudEnVrUCi&%W-40ak@%snFBnkD3j81WZzQ5KhzE#g}u)=U+qaYg)A9Gk{r zW&(gBiR}UoD@nwrA|~;}Lfk~W6aXA4@hgu1iUph;f%sBx=^43vZeo&vuFKM+o7vhj z=-!;{RE|Jk6vSkuF!^k{TY6dsla~v?;+;QBMqFFEsL0l4w$|20=Ei1U73#lk{!NK{ zyGXBsKlcox^?kAZm0x;20E}5tZFYRI#qR~6V>1Bq_rKUQ4+0=5>RbE3SNEZb=OsxX z$gndp$O~ z2}Gii1cZ;QLyD0~q#kKOx{zMvCNhFdBkxcc6a_^`8KLY^-l*j$7HTzW9jX*njXHvA zNA;j?qDE0Os847zS_y4{wnO`%BhiWIY;+O265WVyLtjGQMvtT4U@#aOMh9bq@y0}9 zk}+#ArI`JgR?K_yPPlex4vr&>=Vw!U)NPjf5&f z3*i#sA>kE~NK_}<5`&3c;s#Leh59VbXchJ<=;OnXFBA zCP$M6>atgt3H=1Y2UgM2$qd#E`@bNxY<%q>JP#$vnwQ$&-=;lG9Rn zDQzh?DW=pqsT!$MQo~ZS(iCYk=|Jf;=~C&V(pRM?Ww0{ZG9EH)nL?REG8bjWC@3{{8fLrtcZP`{)0Q)gslWG!XGWpiX}WY5Ts&=8t7&4-psE2EvD z-J!jgQfv(`8kfN|tp+n)3B1%zTF<3EM z@qpqb#pxx~CH6~LONy7ASaM$pR?=4rQCg#PNU2Y0R#`>aOF2V%ukuCZX%(7^vr4i` zh00l#DOHN9qbgUmLiL>LGrBC@g`P^UqW92e)Rfe`)r4wwYW-^S>N@Jn)eF>H)gNgP zG#DBQ8WkGd8Z(-zngN>mn$4Q`weVUDtt72ITD@9x+B(`1+FP_cv?q1sb$oR4beeS@ z>XLPxbXV)v>)z7C=rQzC^!DrB(1-P{^po^!^al)J18W1W!G425L$sl-Ayeeqo|%5^b{6q}Sw=sg-G}X@ltlGZ`~qvjVd&v)|42%~|F( z=C>@!7M>RCEjle;S{hh#EDu=TwW3%BSZ%TDw)$voW6ig2v7WNgw28CXXEV&8GJ+VT zj4QTiTUXolwx@01*;(5O>`vJIW^ZJlVt>?ra;eTz&eDdZV-D&LOouv$5l6aXoZ~^q z5hpb#rc=Gs6K4%)wsWKNgo~a_vdb}-7p|tReAhPDIX64EwQlF#5qB^5V)uRz8IR>2 z)gF&M)jbnEn>}Z|ti0BEo%cq2`+4v59`;f8Vfi%q%=p^)uJ!HlBl(5;Rr@{h*Z1f9 zcLl%!z5%-e9xl^b##`1A2m*ZqcLhEQ(g|7}^kXn4I4HO#_-Tk)NPb9fC?zyD^l0dt zFxRlMum{U^mkXD7hf9XXgg1rHMYu zc#Ks{QOuo{IxBNlUR|ZQDs|PFSjkvs?8!KETtwW_xDU)gW<7H@-Y0%v{0z&DwTJbb z?aZ!VPjMVL<(!EGhlKKk$wY_5U5QgkPDzzX(_A-hHTPw*cXDm=TuNZd;gp5ch}70J zTv}Y(DV_{3h1Zj=lAe=3m|>7nlrgf}ZuRcfGkiaOVz}3Y2Bx^Z`;1P{p|fi z2b>SI)GF7O)V@E+J$SdytFFCXyT0-e=1|t5rw!o^z27pvZE93(ENT3Bn0I*ONXU_% zCYz?Fqe@51n&D<)^VG4JV>iBY|E{yesHLuz)>?8L92Xvc_I=#J{_+2=_${t8_!le8-Jehe15v28 zmBOpTuPtA9&j!stev|fQey;ef!rLS781H)DN4%ey&;Ee@Q1wyoW7j9YPY)N;78d>m z1DNytxvX;;001JnNkld7LFxmFK_jWoA)8K`nq_qkuG&isJ$WB1i+Wb+?L* zOKa-~(H>{emX@J=v>lnzc5GC7)KO6y8{FGLnbrnbWK9+~5K0z78c>R@*aV72ilQnr zU-Tcp`^$SGGTvILm09HZeB$%sMcjzEanHGDzb6_K6B9I>O>V#ac1}C(G#ZTtMNu#Z z13@$Ww&KB}C}=bqTaS&6z2M3#uUs}ZHnyzMXq;CR#Tn_E)|5N_E;`q2(rUFh<&;y{ zbI(0#wOTMfK2A{-TzKJyzmGmVQ(yt`65vSS^S~9r{Xh}6HNcL*5HJih($)?dsqIjg zc3t7(i!Y`q3dYCB8TP@Ekr9T5h9;?G4*CMm;$4ByA>==&u3=FWEnpm&54;q(tJ1^> zF48^CjtgL-(r$u2z_=Y68k#&dNdQGrFflPfQ516o&_9>}-VeMw9G^glYos>*9ZJXF z1Uw8p4Lkrm1dLVgJxnHo)oPVQ{BVc1bI>0&fyWTiCx8)zpgQpJ zx2Fx@w}=RC2CfD!2bKft()o`g0s#1P;O~I{AMV!|H<$$L0HdR$dW&YW%N27_fd()y z?Z1l5s*4`B7Mac0ZMOj*1KyhMIfe+r=T9e#nkHEZtp($DbaZr52bjb5`hi*SI$#gr z7&6Q621RAx1TlehgaYXlA4Z67B91*0+PxLH1}U2+rgmJX7Ul?GFtA2G0c;C=3HTZC z#&AA@6~A%HdV$-SYqY|>8{xXB3_{i;CV=gLe*yj#*eMCO;DH+kUW_#JwdvfZz!|{dWaLC-Sq9$&d>c3uxE`5$y}%~OKX3$+@jKPr zyHlTUMNX#P#K4>tPzxUDGtr=42keiKe;HZvGl#JJF3=1=2F=DQY=LI?e!yXA+aK5s zSXk435%5>QipsOSKgrna|F;GtZeNBJWkfysd+@O|nL-fept$?@tv4?=`uf~@xAYpGqWXs;uHIUS%3HoZ7RbeG^?%YLI0yhJ8KsNsl>DVT~Ytr^z;C}$O1D7I^@jYM}Sue0j z_|DXy&(W)QaE=2^g4yO#Or2rX%`@)jNP{=L3HkG5+m*oo1rDHI&KtG>UWr)!J(YVr z47??@T>@NH>5I+Ir-A=ec_&~_1atzk{y#v2U1j@q%GT|vz2SJu5xhsx%&qDKHrt|K zpgQP_fe(<0$@lzlXtNE{_+y_;3_lFdvD2tIM*!`?Fa2HWm8|Hh9Y^eYk8u6}PUqLA z-}8`NZ>VzsRUs0FVMpNX%Dq1k&c6r+k)pTIeLr%_OE#Mgm?MBHm`%Qg&d87Fjtken zi>$asO&oHfM;&xZ0ExZ@Q1~}KSleNFMl36jBKcL`9^N=weY+fP*za` z*q0n3jN;1sYk{KKY<>V>baZrhE*zYpNWVuT`D$N(5!%=syaXv&1@M=^o@svt@L$Q9 zLGjucA9xjT64KyrO50Vy7m?qP67#McDgi{c6eN;^9`?f(=xk(%Tnl1*Bht_9*) z@tx;5Kn?5z{F3sF^6wF;%@)Y3=K(%E9k2RTjL4S&7t`GVbQ!RFv( z>3+^?;Lp0;^HMT$-;s`Oj)=032wI2$o&t7E1kjul0aIZd+1LA}|1oF(B7{iD1kgY% zy{ggM3-?N7S}sWUwy8Hl)&ZP5=p2B}(lrM%H3I18d_MgzP{a^KIOnJRYLckM!KUOm zL&GmP2Lg}9t|$s;1RJrJrr+(5m}sC}|BJ}84)S1c0ek}?*ogG~t_J=&ZC8imCY<4P z?ILoP5agMC3Gx;;fW3idr}LMEK2*U(u`ITkBY+GZv|ZD0OzdbOg$*Rnm!$n4A+8XW zMrY|94g4XR)wTj20^Wd-_MWuujadGJWGi4C#RdK<^ntLy8Y!b7B6(@r|0NP9?nB-C z?HS&0jsPmqAbapEKS9V@nf7-J?XP00>E_w)n1T~Eo<>UKndAVDx3huQk^@A(<|r}; zX@qkPl!Iun@Bd!lHyz#$Bm(ApZ@E8A&OeBR_DK4_2^BZ@GnoL)DsMpfe|6l@ zgSZV@&PL_Sik{n9=HH80t`Xis9>M>NWN<57*FqxZNZ`%kT!FHY?+on-*DVeGaGw?e z&#HM3>kAHOO~Nyo0F0bR(2Vu52u4Iy4sQ(Y_9e@2gU9rr!u3YrX=s)2bI3Zv_Gkg< zH!9C;pe1KfkAUo-*e@KrG5tQ5tiwdYyrbs*OPzhDf)%ps(r?{5dn`M!}1>59D-)v+@>9@{A^Ra`F($@gKMP}8<5bvOVV}jv#+}p`7uVABY-Io zwe|-nYwZTJPAs_#h;Y`Cvw-6Q5sR9tSI?s5407`4gD6zo zL|)2IRIZEABo~@`MR*s%90w@DV#*#iYy0Ds-!F!1_9rWIMY_i9yl&M`FW}WYAiMs8 zbnkVk4+n*|pJOWPkDD!zCz{RXE->@c!eivB8aHpZ^|JD&m**OcxP6#9xJLAwLi;yS zPA6Z1;`{O5ol3pfX0N7{ABIdg_o0Qng@z+)`qxf$y*J@@qfZK5Um`G)JOjT*c_2Nb zo+PtWkQV+Z<-tD#+4}9C)vm95p~_(KUcV)0CA-ZNl#5feL;htzquFc@QBeYCQZ&#q zb_h8%7EvGWtb*IDK{l@=aqVPcw|f;~zljPq9Ex1Fam~QyD9ZL~qyV0S%)Kv@y>xFz z3fkqUR=|&ueg9ace~VBO$sZw8^FYd?;~L<brPcynHOapI`=Y z0L#7a(4L)j+pa{2=`_3g0ds*v$tmKVZD#kYfIkV>Y=WwI{-&mXEu=JFi}DG7l=knZ zeilCjd9b^`_ z$QirS0XEGxLE1h{jpe()CnDneAY$3~0{?)DL+p*%`ratpcWZJo$y($EyenOIIYQj( z@SJ7H)N{!gi=w!HC*^duF_f9?)UtY!I72vqsdNv@?6RL(W2%2ES)-nget~9VH&ZJX zlllrd{kjU9B9GusY1@|UK&rwXz^UZg0I?20eCEl>H*p*}F!XnocbIV%Lab>=R{cEI zp8#xrnFt0o4?PgOq3oVc+IF=MX2%z!-2WGlMM)1}>z&AXRn$6P0^Bhg`g( z^xnT~5nwh`7gLX5Q_FTU$N{q_@@*HPT|eOVha;uxCUS8{$Z`2@)`1c4`|XHk=tSjs z9mFxPHFF5kPi{?px)ZH2uy<}A(ie6{Ir~*&aV~*_L5>KnMxMxTP!>fi)7G0MGz}b} zDy!Swpz05wk7nz)kh~mJ^Y5fcorIQT$LF@=2-Wv+yG?*Eg!^_X9u+y4S#&2SO(#wg z*?o1^UqOxt)&-wxaqznk0dc@yPL7DRi)Mk=v3-cC+Ho}kH|SOu5V;g!W0wi&FY#)ze7;M(hZ=idCGw@2|A~OLB!v4_w_E_BdGm%zCri zy8A{X`2T%Ken#Ybm2Z4@9T9*$cGrb=PAy-7l(5$!H}HLZzDGN8P@qMn(0(mKSC}pW zF!G1VAyYeHoYz(W{|&7{b0n+XjHx0gwq1$x^)5n5mS0C9*Yl9q?-rD!S4R--h%7$q z$Ebkg4{F}S1AlaSZwG2j2%943P%Ij4CzN3^5*_~wamnQw{svGzFK&20T!}^+mHZ_LPY!{jZYO!#6+CGM&aql4)QHTUtwfUdC~%}n7k*Jtv?AzaM$8zCvE6yfga# z&JoBVRIQ&^g(0L2EkXgL1CR(VCmAOll|(Z0~mpw zWPZ0T%GR$_j&LnQgz$Kq_Wf>A!F&=WRqPv{w+&^dPCwR0olek`9d4GpWXTeWqVU!T z``(6%q8LuUb?2vj>%;*pm*yeOyPeGM1ZKBS0PjOe8Ym)mJTedGkq6l9^hvas;(Em1 z??m?XQ{+U*t&yAdMaV1mViZjz-ET7#7j51&fT{b-3^wy^=G;aueh5OkzoZ?VKxM#fulSYSpUA?=$~C zW_Y))9RWmF<2|%@uyjNI)#RG`3xKbNHYTXwB4x1pot(PlP;-cG$)LNU3fs<{iT;Ok zQ1AuBCC;LMB3PHk;~VKd9XZHsBml@%{Vx@Sb=y2UenMVTzZ25X3v$Wx0i{K)~ygbx1v%vI1X|= zK(4j73vzu%ltmbCRBs53`#9;!AE#_SCg= zn@*6|sBeWd_=tQjor38}+3FP{i~bZ@=`2t_p2g7f5of52GTK$^44k^}0@T86CxAGB zTcPBQYBzvb~@!z@d;jsRNU7dgQ%$)VPFFjW+o;O`3e>N#U+V)1_JQG@7D~B z+2w($&0gdR7zGjo3)yfpzX~=l8^|FPIf0jc?~KgTC<^?}H&U+A*ZqOBoB({_1qi8i ztp9td%?OHI*=&58oS`~h3pJ(#%)+0IqHfk-?jf%$u$ZV51%H~_^yLbki3HHgjC7lK zk}Frob7N_+Kz8vy2>B!F__gGW+?fI~Fm+toA4hSD<5HWGP`KH_Fke@o?*kEz&tB-k z40L9!6D>RoY!9EE+RjJp-pLKOreo8wY&&}Y`clBUfM>8p!8r0B`U4D~ru?oZfG5e` z#IAjr%^bkgzc0%8jZ2dJ>r|!Jp;-QSI`>f|0${M2Vx)WEV?t%Y^!gC~Cz-I9ph8R_ z*Y!Fwp*Z1Vb0h|;sqV85ssk9^srIHd$uh4Mew)a{H;M-CUFmliRk`{uIgZ{B#B7}j znIq!D^;Yf$}1X(BJiOV{b5soo$c@ z-DaM%T@MOvAQQrQ$c)+*EuQp%oJza0WSwC$bqXnuCnFpECKOA!D*e9^eWi0(%4N|8 z0bl!t^uLwvdtf?#W;$*zW)ZXx5^*t~-@nr(qJHOKo7e;Y3Y6@ybvoWcGqAb}#fZHy zUHhkKFbd=+_+GfaS8yLTLCAeCWpAMoFb~BSc0*Y}Cn9CD5$@3sxQ~~iAdwfhycT_h zYm}S;Wdes>yXR5zxZH<`_QnDG^81JJ@$qI-0(SydH=E6Nfsm>{d=)w1b51yaVLH~& z>^JfjB1FW%OXNu2s;T5>(76UrH>f&?>>YHt`9?a&2;%kt8kb3~G}Dzp57-}~__$-; zaf{#?b2BoN7En(3xG4ShN&qo)_H@L0owaDh#DO=o~ajy|GOf6 zV}ka@q^sjJhL)f0lI}6%^?}$ycUToF82H>cmFWU~o!igd5+&kEf!sNT*PV)NEX zqB81zpEDu27{Z@1H4VKNa9?jAC#sH+zs7Y#o9n9MWTKq;tUp0j3G9b`x&rmC;XaR( zYw!0W|E*mwLZ(>M>W%z+Q2yWnDAM?GBzJA1Hp2ctkU!Sc4;W$hl0VP@GHW4!kfGNs z;#mWOgk=4Kcc4{-jDbum|q7h;@4Q8u`nSxfN5UM^SR=1t`;~6|Q+PQe=OW zj`eDSnq5z%_cG$0w{Ul86BWT(4}-`kzx=B7yL~wK09i)&!v+tgtVlHwD}H;r=R7i- z-2`!&qbv8Ya#}T6dj+?@KOFPtSDql3b>FC9(A+!7A5x4Z%%1G?zMi2=DW_dGQ0CAr z2 zMttsk)(_T%eJ{m+s&c#|G#ZVz+f0M?Nz00e81#A*!RngxJJ7ibW9JjX>GALm#3j2?z-}&@Wm|?+!1&oZ0P!vUJ)-PPRaK>?gK?uOebA zWpXz{@Mv6tmT_5*Pav=0SJCR5D1Xo8VTUBLd?VT778}99|S&+s%ALwV#F>(37d{CRvks8=Zv7NNY$hfq7#b=&C1=XaH^i5*i#3Ke>tX?ZgWb~aZKzO#kMBi) zUPTY;iKxiK2<1mb44r9zIL$y5BzROVS1GO-95-oonBe6pZ_!}>GJR7+(SE+tQeYOL_(d1 zd zjJV6rWNufT!Z#p?n4MUwkiK#sgA?QL7eZ2K1KO?&_yzR|p`T3WUrKoixpV6JRWjql zUyJe#9%E|E{WmBF;DFG6Q2uI;@<&Wv``L|kTm=Ce2)cG`amtJ~lqbQ2Wv7O0V zRSAr&7ILWd3KSZRRXjj}nvWm?xtjcurFSC}ZV*k}`op^W-tPPT{@LFz1&e!<8)f$Zvi3h5P~?BLDG zbpf3)vyPkwH}mCu2k2_kq5*%BoE_^I_6&U^nnAw>K0{tDvVHm_oV=;@eg z=1hkng>x(&`zlHR*%A>qzKl}EMi8=2 zL|XLv62WwXXY&Gb37G~mX-`aTjz%89YTp}3+`-Ixr-7iC7ckPVMY2A6_^bdOg-pVy z(3h=jDsG9gckE=E37!y}kS&D#ozd(cMhfk{Na6ed zcZ%=&E3#5Lg^+_EfZ5^)=rzmLEc2sC;j0EkEEY~gYXqJ`;oS$&>{^GuB=Q-iXH8$f z;J%I{5%ndq(zg~ZYhQ_?ng7hx#7~Q~#mHT3&*AKc9yovz^>HfYUogYC9L#ngio8Nm4xe!)~h-V`Q=tcnk^N}!c z?Fb+a+$hL>_ZbFEN2URz@gfiP7C)fLdToSiaEkqN|YVub+CkJd} zBLGwParB1#g7N^KMb4txom^mIO=$NiRCz2ubI^hk7FBUpZjL_XYA)nwKS~b#z|=wz zoi-D}Q>fNIBqG?D2%r&O?AP@F{W}lj_mM&fQnFl$V#Y$P8RP;JX<4 z=aJLIC-s$$kpLiT)5}nn&maS5+rL1Lq_*Fv{}jMriFe zi>n`ymD}=c*+>ZhG7;>B5-|oLg6cJ+h`mPzZZo6Rf|z_0LDno=(LWVwlu}6|-j!O53$a zhM$d`NSCFJ^vvy0j^UDUp9$n!cmyeradi?%PxuqyZRE5uBQy5bgwQEQ;qN3}fRaYm zvJr%V4gI(?O$5uyM6eC@L{N1V$3Rd-qLs`&&!HeVA6tPUl^;R`6W_xNRL(~;e;pec z@_~WB9$u#ttRu_HE66i&J_@})N?Dt(%3){Z_WOaVc)h>9+wR`}zZNN-j#(Utia_{1 zOl%!xeide;4lpPIK$!?041;?q+1U~~%=1tJ#_G`49>zMQET)2uwb`5^*6#YM2Xg|Y zlba(!*68;qe`TydGvD!yo(5$$62SU|G|kShK{@sBL2lhske%M7{E_85Q0nz(QLf$F zD3_OsEE@*TAgW{ikD^b>ehKL?KHow!ei-=-_DOwvB=vLSWcv};g98}qE~rDCefNeX zD3$D7>KA{k@3sahl<%WVXpSQc`W|iJnZ^MO)x{$1vUaOWyH=rm!EYi(Za?G~cR~}!V_t>aly0TiV$@kh8%JuzLB45DI$OKSlmUX-D5Q^@d8=m3x z?_Lr(`+1Lz0ybn?la(^}qhP8jHwbJ&PB5{eI0tQDrsTDG=2?CZ0+GF2L7jsxP$GaC zP{`nM%HFzuzz(Jdr?p3Yz)URy(FrCAz~##)CN{`g2PsMYzuq>1poj507*qoM6N<$f*&i5Pyhe` literal 0 HcmV?d00001 diff --git a/intelmq/web/static/images/logo.png b/intelmq/web/static/images/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..fad627cc4627f70195e7bf798beb839857322e23 GIT binary patch literal 30358 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 literal 0 HcmV?d00001 diff --git a/intelmq/web/static/images/logo2.png b/intelmq/web/static/images/logo2.png new file mode 100644 index 0000000000000000000000000000000000000000..d5836acd5a852401db197169b12399fac91eb5be GIT binary patch literal 63765 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 LsHspRXCC@LP-?{9 literal 0 HcmV?d00001 diff --git a/intelmq/web/static/images/monitor.png b/intelmq/web/static/images/monitor.png new file mode 100644 index 0000000000000000000000000000000000000000..d74a2816e1ebab586b53310bdde4f40d9b9a345d GIT binary patch literal 3702 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 E0N^rZbN~PV literal 0 HcmV?d00001 diff --git a/intelmq/web/static/images/redrawicon-20.png b/intelmq/web/static/images/redrawicon-20.png new file mode 100644 index 0000000000000000000000000000000000000000..1b8d03d8aadc41402b82aa793b322d62401698e2 GIT binary patch literal 395 zcmV;60d)R}P)r1N(gD9O+X8+Y^*GkMo?@-UXlmtY(l!EdsxX! z5wMC;qlKU-DE?fy2h zVP3>?q}oPNRKxF*SrvNl<1WMJ1>&TlvK+05*{wUg!22-X2=gj@!%<}YOCskUA@7tr z-bDCcSWD!OV>FCcahwxP@r(YNFnf&ipu3W_=M7?pZFDCLmkQeTG8r>m300Kw2#W>X zC5Cb`^}o&IwXF5_!rA~P@wA|Oho4myw(&7iZB;C&cmii+A0WT8m;P?Wa%|y6%qaE1 p)-Z?>JPAf;vOeC`;RE~6xCSm#eiQXzze@lB002ovPDHLkV1jciuV?@O literal 0 HcmV?d00001 diff --git a/intelmq/web/static/images/saveicon-128.png b/intelmq/web/static/images/saveicon-128.png new file mode 100644 index 0000000000000000000000000000000000000000..b0dfd4daa5eaefb00a312e61070c52a90f844f1d GIT binary patch literal 627 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7uRSY)RhkE)4%caKYZ?lNlJ8G(24# zLn`LHy=`4|+d;s=@xoJUZIe8`RKFB`dxb3waphBk3N63xV6=#tmilwfpYZa0JNeE0 z3JtZkMvF_oF|ur!@BVztIlBgiZy(RBxptFX;J|NN>-8X+4{__yN`D;J#RM!VT|DXM=+ju_1BNhSm z1`Ea`oCyXu1pALN2lgFk+{uXM#?AZ%HQyL-^rJfT8{;Dk({Hj{*!^aB sd9qNCEkSO<^N6`!CgGvX)+_vbI5|pl`h_{R zYPtVA$otIcuikHsV7WtHCx3e$EzNwut-r&#AXeeo2a}7Xn+{Jjeepry_zcIa2-`hL z^6ZBX$jrVGdPd7tcFqx*L&kX*eOT&R=4pK3}&w!=J@Y^O-nn+{37? z0aiCU7`Oj<9&oL&|F}y;{M!rN`|D3t-zXF@HRRp@kHfA0ve9oHU|2DDy85}Sb4q9e E028x`qigh0tt$vYf-gSW?4sk8Dc<%xXZdiP3=Q&A;Y$ZE&S=Eeyv z|4+_0U~pbkB-voS;iI{>;~JqOQNax1!C}uC=QK=zKj(MTz1`Q{OXeNmOE6Rl@nXKy zuyCOx(hMcXuSE?Rp{9Trvka|u2!Q4wLSto{Be2!#lzq0U4lV`wtM~R73s`>P$ zM)3c!oZLOvyKlxp!53V-`xZLhcw)K8a#7$v`HPiG%Q zLb1=YHMN!sdKE$O2wp%>5&K*q7qB!ITG&{tpx}Ns6IdRb=i_0g9}GLQJ2T(R{)1nJ zt(fn*`<0|I;I*}6W_Ky2OW><5(XpASNr0nLV4Z!5jTonrMv{ghBj7gH2F2ED_7<=P zYyz0sgQR}$U}g(RgwHPU0X&zIU;NZ&L;L5Ymgm4Mv+se=&|gA`xkctTi`XKnjCI}J zZ$du-PR&g2ehu_9zba2q-@_d5z-y*2@fK3Vs#ETa|Ac=bVbeW4khB;2KJnE_s({0` w1Untx@pe;%kCM*ZebRY70)p#OdzW@LL07*qoM6N<$f_>bPTL1t6 literal 0 HcmV?d00001 diff --git a/intelmq/web/static/images/waiting.gif b/intelmq/web/static/images/waiting.gif new file mode 100644 index 0000000000000000000000000000000000000000..8de8135a2cbb1ec3783338ec94dbac52d23257e0 GIT binary patch literal 30263 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 literal 0 HcmV?d00001 diff --git a/intelmq/web/static/js/about.js b/intelmq/web/static/js/about.js new file mode 100644 index 000000000..104198a4c --- /dev/null +++ b/intelmq/web/static/js/about.js @@ -0,0 +1,55 @@ +// SPDX-FileCopyrightText: 2020 IntelMQ Team +// +// SPDX-License-Identifier: AGPL-3.0-or-later +'use strict'; + +function get_versions() { + let intelmq_version_element = document.getElementById('intelmq-version'); + // let intelmq_api_version_element = document.getElementById('intelmq-api-version'); + // let intelmq_manager_version_element = document.getElementById('intelmq-manager-version'); + + authenticatedGetJson(managementUrl('version')) + .done(function (data) { + intelmq_version_element.innerHTML = data.intelmq; + // intelmq_api_version_element.innerHTML = data['intelmq-api']; + // intelmq_manager_version_element.innerHTML = '3.2.0'; + }) + .fail(function (jqxhr, textStatus, error) { + let err = `${textStatus}, ${error}`; + console.error(`Request Failed: ${err}`); + alert('error getting version'); + }); +} +function get_debug() { + let section_element = document.getElementById('debugging'); + + authenticatedGetJson(managementUrl('debug')) + .done(function (data) { + for (const section in data) { + let section_heading = document.createElement("h3"); + section_heading.innerHTML = section; + section_element.appendChild(section_heading); + let table = document.createElement("table"); + let tbody = document.createElement("table"); + + for (const [key, value] of Object.entries(data[section])) { + let row = tbody.insertRow(-1); + let cell0 = row.insertCell(0); + cell0.innerHTML = `

${key}
`; + let cell1 = row.insertCell(1); + cell1.innerHTML = `
${value}
`; + } + table.appendChild(tbody); + section_element.appendChild(table); + } + $('#debugging-heading').removeClass('waiting'); + }) + .fail(function (jqxhr, textStatus, error) { + let err = `${textStatus}, ${error}`; + console.error(`Request Failed: ${err}`); + alert('Error getting debugging information. Do you have IntelMQ >= 2.2.0?'); + }); +} + +get_versions(); +get_debug(); diff --git a/intelmq/web/static/js/check.js b/intelmq/web/static/js/check.js new file mode 100644 index 000000000..656058df0 --- /dev/null +++ b/intelmq/web/static/js/check.js @@ -0,0 +1,28 @@ +// SPDX-FileCopyrightText: 2020 IntelMQ Team +// +// SPDX-License-Identifier: AGPL-3.0-or-later +'use strict'; + +let colors = {info: "alert-info", warning: "alert-warning", error: "alert-danger"}; +let statuses = {success: "No error found.", error: "Some issues have been found, please check the output."} + + +function get_check_output() { + let tableEl = document.getElementById('check-output-table'); + + authenticatedGetJson(managementUrl('check')) + .done(data => { + //data = {"status": "error","lines": [["info", "Reading configuration files."], ["info", "Checking runtime configuration."], ["info", "Checking pipeline configuration."], ["warning", "Bot 'cert-bund-avalanche-parser' has no 'description'."], ["warning", "Bot 'mailsend-output-cz' has no 'name'."], ["error", "Misconfiguration: No source queue for 'mailsend-output-cz'."], ["error", "Misconfiguration: No pipeline configuration found for 'vxvault-collector'."], ["error", "Misconfiguration: No pipeline configuration found for 'vxvault-parser'."], ["info", "Checking harmoization configuration."], ["info", "Checking for bots."]]}; + tableEl.innerHTML = `Status${statuses[data.status]}`; + for (let line of data.lines) { + tableEl.innerHTML += `${line[0]}${line[1]}`; + } + }) + .fail((jqxhr, textStatus, error) => { + let err = `${textStatus}, ${error}`; + console.error(`Request Failed: ${err}`); + alert('error getting check command output'); + }); +} + +get_check_output(); diff --git a/intelmq/web/static/js/config.js b/intelmq/web/static/js/config.js new file mode 100644 index 000000000..e69de29bb diff --git a/intelmq/web/static/js/configs.js b/intelmq/web/static/js/configs.js new file mode 100644 index 000000000..8dd3b1ea3 --- /dev/null +++ b/intelmq/web/static/js/configs.js @@ -0,0 +1,1029 @@ +// SPDX-FileCopyrightText: 2020 IntelMQ Team , 2020 Edvard Rejthar , 2021 Mikk Margus Möll +// +// SPDX-License-Identifier: AGPL-3.0-or-later +'use strict'; + +var NETWORK_OPTIONS = NETWORK_OPTIONS || {}; + +class VisModel { + constructor() { + + + this.defaults = {}; + this.nodes = {}; + this.bots = {}; + + this.network = null; + this.network_container = null; + this.network_data = {}; // we may update existing info in the network on the fly + this.bot_before_altering = null; + + this.positions = null; + this.options = NETWORK_OPTIONS; + } +} + +var app = new VisModel(); + +var popup = null; +var documentation = null; +var span = null; +var table = null; +var disabledKeys = ['group', 'name', 'module']; +var $manipulation, $saveButton; // jQuery of Vis control panel; elements reseted with network +var node = null; + +var $EDIT_DEFAULT_BUTTON = $("#editDefaults"); +var BORDER_TYPE_CLASSES = { + DEFAULT: 'info', + GENERIC: 'success', + RUNTIME: 'warning', +} +var BORDER_TYPES = { + DEFAULT: 'default', + GENERIC: 'generic', + RUNTIME: 'runtime', + OTHERS: 'default', +} + +var draggedElement = null; + +var warn_on_close_tab = false; + +$(window).on('hashchange', location.reload); + +$(window).on('beforeunload', () => warn_on_close_tab ? "If you have not saved your work you'll lose the changes you have made. Do you want to continue?" : undefined); + +function resize() { + // Resize body + let network_container = document.getElementById('network-container'); + network_container.style.height = `${window.innerHeight - network_container.offsetTop}px`; + network_container.style.overflowX = "auto"; + network_container.style.overflowY = "auto"; + + if (app.network !== null && app.network !== undefined) { + app.network.redraw(); + } + + load_html_elements(); +} + +function load_html_elements() { + // Load popup, span and table + app.network_container = document.getElementById('network-container'); + app.network_container.addEventListener('drop', handleDrop); + app.network_container.addEventListener('dragover', allowDrop); + popup = document.getElementById("network-popUp"); + documentation = document.getElementById("documentationButton"); + span = document.getElementById('network-popUp-title'); + table = document.getElementById("network-popUp-fields"); +} + + +function load_bots(config) { + // Build side menu + for (let bot_group of Object.keys(config).reverse()) { + let $bot_group = $("#templates > ul.side-menu > li").clone().prependTo("#side-menu").css("border-bottom-color", GROUP_COLORS[bot_group][0]); + $bot_group.find("> a").prepend(bot_group); + let group = config[bot_group]; + for (let bot_name in group) { + let bot = group[bot_name]; + let $bot = $bot_group.find("ul > li:first").clone().appendTo($("ul", $bot_group)) + .attr("title", bot.description) + .attr("data-name", bot_name) + .attr("data-group", bot_group) + .click(() => { + if ($('#network-popUp').is(':visible')) { + // just creating a new bot + fill_bot(undefined, bot_group, bot_name); + return false; + } + + // cycling amongst the bot instances + if (!$bot.data("cycled")) { + $bot.data("cycled", []); + } + let found = null; + for (let bot_node of Object.values(app.nodes)) { + if (bot_node.module === bot.module && $.inArray(bot_node.id, $bot.data("cycled")) === -1) { + $bot.data("cycled").push(bot_node.id); + found = bot_node.id; + break; + } + } + // not found or all bots cycled + if (!found && $bot.data("cycled").length) { + found = $bot.data("cycled")[0]; + $bot.data("cycled", [found]); // reset cycling + } + if (found) { + fitNode(found); + } else { + show_error(`No instance of the ${bot_name} found. Drag the label to the plan to create one.`); + } + return false; + }) + .on('dragstart', event => { // drag to create a new bot instance + app.network.addNodeMode(); + draggedElement = { + bot_name: bot_name, + bot_group: bot_group + }; + // necessary for firefox + event.originalEvent.dataTransfer.setData('text/plain', null); + }) + .find("a").prepend(bot_name); + + + if (app.bots[bot_group] === undefined) { + app.bots[bot_group] = {}; + } + + app.bots[bot_group][bot_name] = { + name: bot_name, + group: bot_group, + module: bot.module, + description: bot.description, + enabled: true, + parameters: bot.parameters, + run_mode: 'continuous' + }; + + for (let [parameter, value] of Object.entries(bot.parameters)) { + app.bots[bot_group][bot_name].parameters[parameter] = value; + } + } + $bot_group.find("ul li").first().remove(); // get rid of the HTML template + } + + $('#side-menu').metisMenu({restart: true}); + $EDIT_DEFAULT_BUTTON.click(e => { + create_form('Edit Defaults', $(e.target).attr("id"), undefined); + fill_editDefault(app.defaults); + }); + + if (getUrlParameter("configuration") !== "new") { + load_configuration(); + } else { + draw(); + resize(); + set_pending_change(); + } +} + +function fill_editDefault(data) { + table.innerHTML = ''; + insertBorder(BORDER_TYPES.DEFAULT); + for (let [key, value] of Object.entries(data)) { + insertKeyValue(key, value, BORDER_TYPES.DEFAULT, true); + } + + // to enable scroll bar + popup.setAttribute('class', "with-bot"); +} + +function handleDrop(event) { + // --- necessary for firefox + if (event.preventDefault) { + event.preventDefault(); + } + if (event.stopPropagation) { + event.stopPropagation(); + } + // --- + + let domPointer = app.network.interactionHandler.getPointer({x: event.clientX, y: event.clientY}); + let canvasPointer = app.network.manipulation.canvas.DOMtoCanvas(domPointer); + + let clickData = { + pointer: { + canvas: { + x: canvasPointer.x, + y: canvasPointer.y + } + } + }; + + app.network.manipulation.temporaryEventFunctions[0].boundFunction(clickData); + + fill_bot(undefined, draggedElement.bot_group, draggedElement.bot_name); +} + +function allowDrop(event) { + event.preventDefault(); +} + + +// Configuration files manipulation + +function save_data_on_files() { + if (!confirm("By clicking 'OK' you are replacing the configuration in your files by the one represented by the network on this page. Do you agree?")) { + return; + } + + app.nodes = remove_defaults(app.nodes); + + let reloadable = 0; + let alert_error = (file, jqxhr, textStatus, error) => { + show_error(`There was an error saving ${file}:\nStatus: ${textStatus}\nError: ${error}`); + }; + let saveSucceeded = (response) => { + if (++reloadable === 4) { + + } + if (response === 'success') { + return true; + } else { + alert(response); + return false; + } + } + + // can't parallelize these due to a race condition from them both touching runtime.yaml; TODO lock file in backend? + authenticatedAjax({type: "POST", url: `${RUNTIME_FILE}`, contentType: "application/json", data: generate_runtime_conf(app.nodes, app.defaults)}) + .done(saveSucceeded) + .fail(() => alert_error('runtime', ...arguments)) + .then(() => + authenticatedAjax({type: "POST", url: `${POSITIONS_FILE}`, contentType: "application/json", data: generate_positions_conf()}) + .done(saveSucceeded) + .fail(() => alert_error('positions', ...arguments) ) + ) + // all files were correctly saved + .then(unset_pending_change); +} + + +// Prepare data from configuration files to be used in Vis + +function convert_edges(nodes) { + let new_edges = [], roundness = {}; + for (let node of Object.values(nodes)) { + let from = node.bot_id; + let edge_map = node.parameters.destination_queues; + for (let path in edge_map) { + for (let to of edge_map[path]) { + let id = to_edge_id(from, to, path); + let new_edge = { + id, + from, + to: to.replace(/-queue$/, ''), + label: path === '_default' ? undefined : path, + }; + + // if there is multiple edges between nodes we have to distinguish them manually, see https://github.com/almende/vis/issues/1957 + let hash = new_edge.from + new_edge.to; + if (hash in roundness) { + roundness[hash] += 0.3; + } else { + roundness[hash] = 0; + } + if (roundness[hash]) { + new_edge.smooth = {type: "curvedCCW", roundness: roundness[hash]}; + } + + new_edges.push(new_edge); + } + } + } + + return new_edges; +} + +function convert_nodes(nodes, includePositions) { + let new_nodes = []; + + for (let node of nodes) { + let new_node = {}; + new_node.id = node.bot_id; + new_node.label = node.bot_id; + new_node.group = node.group; + + if (includePositions === true) { + try { + let {x, y} = app.positions[node.bot_id]; + new_node.x = x; + new_node.y = y; + } catch (err) { + console.error('positions in file are ignored:', err, node); + show_error('Saved positions are not valid or not complete. The configuration has possibly been modified outside of the IntelMQ-Manager.'); + includePositions = false; + } + } + + new_nodes.push(new_node); + } + + return new_nodes; +} + +function fill_bot(id, group, name) { + let bot; + table.innerHTML = ''; + + if (id === undefined) { + bot = app.bots[group][name]; + + name = bot.name.replace(/\ /g, '-').replace(/[^A-Za-z0-9-]/g, ''); + group = bot.group.replace(/\ /g, '-'); + let default_id = gen_new_id(`${name}-${group}`); + bot.bot_id = bot.id = default_id; + bot.defaults = {}; + + for (let [key, value] of Object.entries(app.defaults).filter(([key, value]) => !(key in bot.parameters))) { + bot.defaults[key] = value; + } + } else { + bot = app.nodes[id]; + } + + app.bot_before_altering = bot; + + insertKeyValue('id', bot.bot_id, 'id', false); + insertBorder(BORDER_TYPES.GENERIC); + for (let [key, value] of Object.entries(bot).filter(([key, value]) => STARTUP_KEYS.includes(key))) { + insertKeyValue(key, value, BORDER_TYPES.GENERIC, false); + } + insertBorder(BORDER_TYPES.RUNTIME); + for (let [key, value] of Object.entries(bot.parameters).filter(([key, value]) => key !== 'destination_queues')) { + insertKeyValue(key, value, BORDER_TYPES.RUNTIME, true); + } + + const modulename = bot.module.replace(/\./g, "-").replace(/_/g, "-"); + documentation.href = `https://intelmq.readthedocs.org/en/maintenance/user/bots.html#${modulename}`; + popup.setAttribute('class', "with-bot"); +} + +function insertBorder(border_type) { + let new_row = table.insertRow(-1); + let sectionCell1 = new_row.insertCell(0); + let sectionCell2 = new_row.insertCell(1); + let addButtonCell = new_row.insertCell(2); + + sectionCell1.setAttribute('id', 'border'); + sectionCell2.setAttribute('id', 'border'); + sectionCell1.innerHTML = border_type; + sectionCell2.innerHTML = border_type; + + switch (border_type) { + case BORDER_TYPES.GENERIC: + new_row.setAttribute('class', BORDER_TYPE_CLASSES.GENERIC); + break; + case BORDER_TYPES.RUNTIME: + new_row.setAttribute('class', BORDER_TYPE_CLASSES.RUNTIME); + $(addButtonCell).append($("#templates > .new-key-btn").clone().click(addNewKey)); + new_row.setAttribute('id', border_type); + break; + case BORDER_TYPES.DEFAULT: + new_row.setAttribute('class', BORDER_TYPE_CLASSES.DEFAULT); + $(addButtonCell).append($("#templates > .new-key-btn").clone().click(addNewDefaultKey)); + new_row.setAttribute('id', border_type); + break; + default: + new_row.setAttribute('class', BORDER_TYPE_CLASSES.OTHERS); + } +} + +function insertKeyValue(key, value, section, allowXButtons, insertAt) { + let new_row = table.insertRow(insertAt === undefined ? -1 : insertAt); + + let keyCell = new_row.insertCell(0); + let valueCell = new_row.insertCell(1); + let xButtonCell = new_row.insertCell(2); + let valueInput = document.createElement("input"); + + keyCell.setAttribute('class', 'node-key'); + keyCell.setAttribute('id', section) + valueCell.setAttribute('class', 'node-value'); + valueInput.setAttribute('type', 'text'); + valueInput.setAttribute('id', key); + + if (section === 'generic' && disabledKeys.includes(key) === true) { + valueInput.setAttribute('disabled', "true"); + } + + let parameter_func = (action_function, argument) => action_function(argument); + + if (allowXButtons === true) { + let xButton = document.createElement('button'); + let xButtonSpan = document.createElement('span'); + xButtonSpan.setAttribute('class', 'glyphicon glyphicon-remove-circle'); + xButton.setAttribute('class', 'btn btn-danger'); + xButton.setAttribute('title', 'delete parameter'); + xButton.addEventListener('click', () => parameter_func(deleteParameter, key)); + + xButton.appendChild(xButtonSpan); + xButtonCell.appendChild(xButton); + } + + valueCell.appendChild(valueInput); + + keyCell.innerHTML = key; + if (value !== null && typeof value === "object") { + value = JSON.stringify(value); + } + if (value !== null) { + valueInput.setAttribute('value', value); + } +} + +function resetToDefault(input_id) { + $(`#${input_id}`)[0].value = app.defaults[input_id]; +} + +function deleteParameter(input_id) { + let current_index = $(`#${input_id}`).closest('tr').index(); + table.deleteRow(current_index); +} + +function addNewKey() { + let $el = $("#templates .modal-add-new-key").clone(); + popupModal("Add key", $el, () => { + let current_index = $(`#${BORDER_TYPES.RUNTIME}`).index(); + let $key = $el.find("[name=newKeyInput]"); + let val = $el.find("[name=newValueInput]").val(); + + if (!PARAM_KEY_REGEX.test($key.val())) { + show_error("Parameter names can only be composed of numbers, letters, hiphens and underscores"); + $key.focus(); + return false; + } else { + // inserts new value and focus the field + insertKeyValue($key.val(), val, BORDER_TYPES.RUNTIME, true, current_index + 1); + // a bootstrap guru or somebody might want to rewrite this line without setTimeout + setTimeout(() => $('#network-popUp .new-key-btn').closest("tr").next("tr").find("input").focus(), 300); + } + }); +} +// same as above, with another border type +function addNewDefaultKey() { + let $el = $("#templates .modal-add-new-key").clone(); + popupModal("Add key", $el, () => { + let current_index = $(`#${BORDER_TYPES.RUNTIME}`).index(); + let $key = $el.find("[name=newKeyInput]"); + let val = $el.find("[name=newValueInput]").val(); + + if (!PARAM_KEY_REGEX.test($key.val())) { + show_error("Parameter names can only be composed of numbers, letters, hiphens and underscores"); + $key.focus(); + return false; + } else { + // inserts new value and focus the field + insertKeyValue($key.val(), val, BORDER_TYPES.DEFAULT, true, current_index + 1); + // a bootstrap guru or somebody might want to rewrite this line without setTimeout + setTimeout(() => $('#network-popUp .new-key-btn').closest("tr").next("tr").find("input").focus(), 300); + } + }); +} + +$(document).keydown(function (event) { + if (event.keyCode === 27) { + let $el; + if (($el = $("body > .modal:not([data-hiding])")).length) { + // close the most recent modal + $el.last().attr("data-hiding", true).modal('hide'); + setTimeout(() => $("body > .modal[data-hiding]").first().remove(), 300); + } else if ($('#network-popUp').is(':visible')) { + $('#network-popUp-cancel').click(); + } + } + if (event.keyCode === 13 && $('#network-popUp').is(':visible') && $('#network-popUp :focus').length) { + // till network popup is not unified with the popupModal function that can handle Enter by default, + // let's make it possible to hit "Ok" by Enter as in any standard form + $('#network-popUp-ok').click(); + } +}); + +function saveDefaults_tmp(data, callback) { + app.defaults = {}; + saveFormData(); + set_pending_change(); + clearPopUp(data, callback); +} + +function saveFormData() { + for (let i = 0; i < table.rows.length; i++) { + let keyCell = table.rows[i].cells[0]; + let valueCell = table.rows[i].cells[1]; + let valueInput = valueCell.getElementsByTagName('input')[0]; + + if (valueInput === undefined) + continue; + + let key = keyCell.innerText; + let value = null; + + try { + value = JSON.parse(valueInput.value); + } catch (err) { + value = valueInput.value; + } + + switch (keyCell.id) { + case 'id': + node.bot_id = value; + break; + case 'generic': + node[key] = value; + break; + case 'runtime': + node.parameters[key] = value; + break; + case 'border': + break; + case 'default': + app.defaults[key] = value; + break; + default: + node.defaults[key] = value; + } + } +} + +function saveData(data, callback) { + node = {parameters: {}, defaults: {}}; + + saveFormData(); + + // check inputs beeing valid + if (node.bot_id === '' && node.group === '') { + show_error('fields id and group must not be empty!'); + return; + } + + if (!BOT_ID_REGEX.test(node.bot_id)) { + show_error("Bot ID's can only be composed of numbers, letters and hyphens"); + return; + } + + let current_id = node.bot_id, old_id = app.bot_before_altering.bot_id; + + let old_bot = app.nodes[old_id]; + node.parameters.destination_queues = old_bot ? old_bot.parameters.destination_queues : {}; + + if (current_id !== old_id) { + if (current_id in app.nodes) { + alert("A bot with this ID already exists, please select a different ID"); + return; + } + + if (old_id in app.nodes) { + if (!confirm("You have edited the bot's ID. Proceed with the operation?")) { + return; + } + + app.positions[current_id] = app.positions[old_id]; + app.nodes[current_id] = node; + delete app.positions[old_id]; + + app.network_data.nodes.add(convert_nodes([node], true)); + + // recreate reverse edges + for (let edge_id of get_reverse_edges(old_id)) { + let [from, to, path] = from_edge_id(edge_id); + let list = app.nodes[from].parameters.destination_queues[path]; + let to_index = list.indexOf(`${old_id}-queue`); + + list[to_index] = `${current_id}-queue`; + + let new_edge_id = to_edge_id(from, current_id, path); + if (path === '_default') { + path = undefined; + } + + app.network_data.edges.remove({id: edge_id}); + app.network_data.edges.add({id: new_edge_id, from, to: current_id, label: path}); + } + + // recreate forward edges + for (let [path, path_l] of Object.entries(node.parameters.destination_queues)) { + for (let to of path_l) { + app.network_data.edges.add({ + id: to_edge_id(current_id, to, path), + from: current_id, + to: to.replace(/-queue$/, ''), + label: path === '_default' ? undefined : path + }); + } + } + + delete app.nodes[old_id]; + app.network_data.nodes.remove(old_id); + } + } + + + // switch parameters and defaults + if ('parameters' in node) { + for (let parameterKey in node.parameters) { + if ( + node.parameters[parameterKey] !== app.bot_before_altering.parameters[parameterKey] + && parameterKey in app.defaults + && node.parameters[parameterKey] === app.defaults[parameterKey] + ) { + swapToDefaults(node, parameterKey); + } + } + } + + if ('defaults' in node) { + for (let defaultsKey in node.defaults) { + if (node.defaults[defaultsKey] !== app.defaults[defaultsKey]) { + swapToParameters(node, defaultsKey); + } + } + } + + data.bot_id = node.bot_id; + data.id = node.bot_id; + data.label = node.bot_id; + data.group = node.group; + data.level = GROUP_LEVELS[data.group]; + data.title = JSON.stringify(node, undefined, 2).replace(/\n/g, '\n
').replace(/ /g, " "); + + app.nodes[node.bot_id] = node; + + set_pending_change(); + clearPopUp(data, callback); +} + +function swapToParameters(node, key) { + node.parameters[key] = node.defaults[key]; + delete node.defaults[key]; +} + +function swapToDefaults(node, key) { + node.defaults[key] = node.parameters[key]; + delete node.parameters[key]; +} + + +/** + * Popups a custom modal window containing the given body. + * @example popupModal("Title", $input, () => {$input.val();}) + */ +function popupModal(title, body, callback) { + let $el = $("#templates > .modal").clone().appendTo("body"); + $(".modal-title", $el).text(title); + $(".modal-body", $el).html(body); + $el.modal({keyboard: false}).on('shown.bs.modal', e => { + let $ee; + if (($ee = $('input,textarea,button', $(".modal-body", e.target)).first())) { + $ee.focus(); + } + }); + return $el.on('submit', 'form', e => { + if (callback() !== false) { + $(e.target).closest(".modal").modal('hide'); + } + return false; + }); +} + +function create_form(title, data, callback) { + span.innerHTML = title; + + let okButton = document.getElementById('network-popUp-ok'); + let cancelButton = document.getElementById('network-popUp-cancel'); + + if (data === $EDIT_DEFAULT_BUTTON.attr("id")) { + okButton.onclick = saveDefaults_tmp.bind(window, data, callback); + } else { + okButton.onclick = saveData.bind(window, data, callback); + } + + cancelButton.onclick = clearPopUp.bind(window, data, callback); + + table.innerHTML = "

Please select one of the bots on the left

"; + popup.style.display = 'block'; + popup.setAttribute('class', "without-bot"); +} + +function clearPopUp(data, callback) { + let okButton = document.getElementById('network-popUp-ok'); + let cancelButton = document.getElementById('network-popUp-cancel'); + okButton.onclick = null; + cancelButton.onclick = null; + + popup.style.display = 'none'; + span.innerHTML = ""; + + for (let i = table.rows.length - 1; i >= 0; i--) { + let position = table.rows[i].rowIndex; + + if (position >= CORE_FIELDS) { + table.deleteRow(position); + } else { + table.rows[i].setAttribute('value', ''); + } + } + + popup.setAttribute('class', "without-bot"); + if ((callback !== undefined) && (data.label !== 'new')) { + callback(data); + } +} + +function redrawNetwork() { + app.options.layout.randomSeed = Math.round(Math.random() * 1000000); + app.network.destroy(); + app.network = null; + initNetwork(false); + set_pending_change(); +} + +function draw() { + load_html_elements(); + + if (getUrlParameter("configuration") === "new") { + app.nodes = {}; + } + initNetwork(); + if (window.location.hash) { + let node = window.location.hash.substr(1); + setTimeout(() => { // doesnt work immediately, I don't know why. Maybe a js guru would bind to visjs onready if that exists or sth. + try { + fitNode(node); + } catch (e) { + show_error(`Bot instance ${node} not found in the current configuration.`); + } + }, 100); + + + } +} + +function fitNode(nodeId) { + app.network.fit({nodes: [nodeId]}); + app.network.selectNodes([nodeId], true); + app.network.manipulation.showManipulatorToolbar(); +} + +function initNetwork(includePositions = true) { + app.network_data = { + nodes: new vis.DataSet(convert_nodes(Object.values(app.nodes), includePositions)), + edges: new vis.DataSet(convert_edges(app.nodes)) + }; + + app.network = new vis.Network(app.network_container, app.network_data, app.options); + $manipulation = $(".vis-manipulation"); + + // rename some menu buttons (because we couldn't do that earlier) + app.network.options.locales.en.addNode = "Add Bot"; + app.network.options.locales.en.addEdge = "Add Queue"; + app.network.options.locales.en.editNode = "Edit Bot"; + app.network.options.locales.en.del = "Delete"; + + // 'Live' button (by default on when botnet is not too big) and 'Physics' button + // initially stopped + let reload_queues = (new Interval(load_live_info, RELOAD_QUEUES_EVERY * 1000, true)).stop(); + app.network.setOptions({physics: false}); + + // + // add custom button to the side menu + // + + $("#templates .network-right-menu").clone().insertAfter($manipulation); + let $nc = $("#network-container"); + $(".vis-live-toggle", $nc).click(e => { + $(e.target).toggleClass("running", !reload_queues.running); + reload_queues.toggle(!reload_queues.running); + }).click(); + let physics_running = true; + $(".vis-physics-toggle", $nc).click(e => { + $(e.target).toggleClass("running"); + app.network.setOptions({physics: (physics_running = !physics_running)}); + }); + + // 'Save Configuration' button blinks and lists all the bots that should be reloaded after successful save. + $saveButton = $("#vis-save", $nc); + $saveButton.children().on('click', save_data_on_files); + $saveButton.data("reloadables", []); + $saveButton.blinkOnce = function() { + $($saveButton).addClass('blinking-once'); + setTimeout(() => $($saveButton).removeClass('blinking-once'), 2000); + } + $saveButton.blinking = function (bot_id = null) { + $($saveButton).addClass('vis-save-blinking') + if (bot_id) { + $($saveButton).data("reloadables").push(bot_id); + } + }; + $saveButton.unblinking = function () { + $($saveButton).removeClass('vis-save-blinking'); + let promises = []; + let bots = $.unique($($saveButton).data("reloadables")); + for (let bot_id of bots) { + let url = managementUrl("bot", `action=reload&id=${bot_id}`); + promises.push(authenticatedGetJson(url)); + } + if (promises.length) { + Promise.all(promises).then(() => { + show_error(`Reloaded bots: ${bots.join(", ")}`); + bots.length = 0; + }); + } + }; + + let allow_blinking_once = false; // Save Configuration button will not blink when a button is clicked now automatically + // list of button callbacks in form ["button/settings name"] => function called when clicked receives true/false according to the clicked state + let callbacks = [ + ["live", val => reload_queues[val ? "start" : "stop"]()], + ["physics", val => app.network.setOptions({physics: val})], + ]; + for (let [name, fn] of callbacks) { + let $el = $(`.vis-${name}-toggle`, $nc).click(e => { + // button click will callback and blinks Save Configuration button few times + fn(settings[name] = !settings[name]); + $(e.target).toggleClass("running", settings[name]); + + if (allow_blinking_once) { + $saveButton.blinkOnce(); + } + }); + // initially turn on/off buttons according to the server-stored settings + settings[name] = !settings[name]; + $el.click(); + } + allow_blinking_once = true; + + // 'Clear Configuration' button + $("#vis-clear").children().on('click', event => window.location.assign('configs.html?configuration=new')); + + // 'Redraw Botnet' button + $("#vis-redraw").children().on('click', event => redrawNetwork()); + + // + // add custom menu buttons + // (done by extending self the visjs function, responsible for menu creation + // so that we are sure our buttons are persistent when vis menu changes) + // + app.network.manipulation._showManipulatorToolbar = app.network.manipulation.showManipulatorToolbar; + app.network.manipulation.showManipulatorToolbar = function () { + // call the parent function that builds the default menu + app.network.manipulation._showManipulatorToolbar.call(app.network.manipulation); + + // enable 'Edit defaults' button + $EDIT_DEFAULT_BUTTON.prop('disabled', false); + + // clicking on 'Add Bot', 'Add Queues' etc buttons disables 'Edit defaults' button + let fn = () => $EDIT_DEFAULT_BUTTON.prop('disabled', true); + $(".vis-add", $manipulation).on("pointerdown", fn); + let $el = $(".vis-edit", $manipulation); + if ($el.length) { // 'Edit Bot' button is visible only when there is a bot selected + $el.on("pointerdown", fn); + } + + // 'Monitor' and 'Duplicate' buttons appear when there is a single node selected + let nodes = app.network.getSelectedNodes(); + if (nodes.length === 1) { // a bot is focused + let bot = nodes[0]; + $("#templates .network-node-menu").clone().appendTo($manipulation); + $(".monitor-button", $manipulation).click((event) => { + return click_link(MONITOR_BOT_URL.format(bot), event); + }).find("a").attr("href", MONITOR_BOT_URL.format(bot)); + $(".duplicate-button", $manipulation).click(() => { + duplicateNode(app, bot); + }).insertBefore($(".vis-add").hide()); + + // insert start/stop buttons + $(".monitor-button", $manipulation).before(generate_control_buttons(bot, false, refresh_color, true)); + } else { + let edges = app.network.getSelectedEdges(); + if (edges.length === 1) { + $("#templates .network-edge-menu").clone().appendTo($manipulation); + $(".vis-edit", $manipulation).click(() => { + editPath(app, edges[0]); + }).insertBefore($(".vis-delete")); + } + } + // refresh shortcuts + // (it is so hard to click on the 'Add Node' button we rather register click event) + // We use 't' for 'Add bot' and 'Duplicate' because that's a common letter. + + let shortcuts = [ + ['t', 'add', 'addNodeMode'], + ['q', 'connect', 'addEdgeMode'], + ['d', 'delete', 'deleteSelected'], + ['e', 'edit', 'editNode'], + ]; + + for (let [letter, tag, callback_name] in shortcuts) { + $(`.vis-${tag} .vis-label`, $manipulation).attr('data-accesskey', letter).click(app.network[callback_name]); + } + + accesskeyfie(); + }; + // redraw immediately so that even the first click on the network is aware of that new monkeypatched function + app.network.manipulation.showManipulatorToolbar(); + + // double click action trigger editation + app.network.on("doubleClick", active => { + if (active.nodes.length === 1) { + let ev = document.createEvent('MouseEvent'); // vis-js button need to be clicked this hard way + ev.initEvent("pointerdown", true, true); + $(".vis-edit", $manipulation).get()[0].dispatchEvent(ev); + } + if (active.edges.length === 1) { + $(".vis-edit", $manipulation).click(); + } + }); + /* right button ready for any feature request: + app.network.on("oncontext", (active)=>{ + let nodeId = app.network.getNodeAt(active.pointer.DOM); + // what this should do? :) + }); + */ + +} + +// INTELMQ + +/* + * Application entry point + */ + +// Dynamically load available bots +load_file(BOTS_FILE, load_bots); + +// Dynamically adapt to fit screen +window.onresize = resize; + +/** + * This function fetches the current info and updates bot nodes on the graph + */ +function refresh_color(bot) { + if (bot_status_previous[bot] !== bot_status[bot]) { // status changed since last time + + // we use light colour if we expect bot will be running + // (when reloading from stopped state bot will not be running) + let col = GROUP_COLORS[app.nodes[bot].group][[ + BOT_STATUS_DEFINITION.running, + BOT_STATUS_DEFINITION.starting, + BOT_STATUS_DEFINITION.restarting, + bot_status_previous[bot] === BOT_STATUS_DEFINITION.running ? BOT_STATUS_DEFINITION.reloading : 0 + ].includes(bot_status[bot]) ? 0 : 1]; + + // change bot color if needed + if (app.network_data.nodes.get([bot])[0].color !== col) { + app.network_data.nodes.update({id: bot, color: col}); + } + + // we dash the border if the status has to be changed (not running or stopping) or is faulty (error, incomplete) + if ([BOT_STATUS_DEFINITION.running, BOT_STATUS_DEFINITION.stopped].indexOf(bot_status[bot]) === -1) { + app.network_data.nodes.update({id: bot, shapeProperties: {borderDashes: [5, 5]}}) + } else if ([BOT_STATUS_DEFINITION.running, BOT_STATUS_DEFINITION.stopped, undefined].indexOf(bot_status_previous[bot]) === -1) { + // we remove dash border since bot has been in a dash-border state and is no more + // (that means that bot wasn't either in a running, stopped or initially undefined state) + app.network_data.nodes.update({id: bot, shapeProperties: {borderDashes: false}}); + } + + bot_status_previous[bot] = bot_status[bot]; + } +} + +function load_live_info() { + $(".navbar").addClass('waiting'); + return authenticatedGetJson(managementUrl('queues-and-status')) + .done(data => { + let bot_queues; + [bot_queues, bot_status] = data; + + for (let [bot, bot_data] of Object.entries(bot_queues)) { + if ("source_queue" in bot_data) { + // we skip bots without source queue (collectors) + // Assume an empty internal queue if no data is given (The AMQP pipeline does not have/need internal queues) + let c = bot_data.source_queue[1] + (bot_data.internal_queue || 0); + let label = (c > 0) ? `${bot}\n${c}✉` : bot; + let appbot = app.network_data.nodes.get(bot); + if (appbot === null) { + show_error(`Non-existent bot ${bot} in pipelines.`); + } else if (label !== appbot.label) { + // update queue count on bot label + app.network_data.nodes.update({id: bot, label}); + } + } else { + // https://github.com/certtools/intelmq-manager/issues/158 + app.network_data.nodes.update({id: bot, label: bot}); + } + } + for (let bot in bot_status) { + // bots that are not running are grim coloured + refresh_color(bot); + } + }) + .fail(ajax_fail_callback('Error loading bot queues information')) + .always(() => { + $(".navbar").removeClass('waiting'); + this.blocking = false; + }); +} + +function set_pending_change(bot_id = null) { + $saveButton.blinking(bot_id); + warn_on_close_tab = true; +} + +function unset_pending_change() { + $saveButton.unblinking(); + warn_on_close_tab = false; +} diff --git a/intelmq/web/static/js/defaults.js b/intelmq/web/static/js/defaults.js new file mode 100644 index 000000000..7b6915833 --- /dev/null +++ b/intelmq/web/static/js/defaults.js @@ -0,0 +1,90 @@ +// SPDX-FileCopyrightText: 2020 IntelMQ Team , 2020 Edvard Rejthar , 2021 Mikk Margus Möll +// +// SPDX-License-Identifier: AGPL-3.0-or-later +'use strict'; + +function generate_defaults_conf(defaults) { + return JSON.stringify(sortObjectByPropertyName(defaults), undefined, 4); +} + +function read_defaults_conf(config) { + let global = {}; + + for (let key in config.global) { + try { + global[key] = JSON.parse(config.global[key]); + } catch (err) { + global[key] = config.global[key]; + } + } + + return global; +} + +function remove_defaults(nodes) { + for (let id in nodes) { + delete nodes[id].defaults; + } + + return nodes; +} + +function get_reverse_nodes(dest_bot_id) { + let out = []; + let dest_bot = app.nodes[dest_bot_id]; + if (dest_bot === undefined) { + // for example for newly configured bots + return out; + } + + let connected_nodes = app.network.getConnectedNodes(dest_bot_id); + let queue_id = `${dest_bot_id}-queue`; + let reverse_allowed_neighbors = REVERSE_ACCEPTED_NEIGHBORS[dest_bot.group]; + + for (let src_bot of connected_nodes.map(src_bot_id => app.nodes[src_bot_id]).filter(src_bot => reverse_allowed_neighbors.includes(src_bot.group))) { + for (let list of Object.values(src_bot.parameters.destination_queues)) { + if (list.includes(queue_id)) { + out.push(src_bot.bot_id); + break; + } + } + } + + return out; +} + +function get_reverse_edges(dest_bot_id) { + let out = [], queue_id = `${dest_bot_id}-queue`; + for (let edge_id of app.network.getConnectedEdges(dest_bot_id)) { + let [from, to, path] = from_edge_id(edge_id); + if (to === queue_id) { + out.push(edge_id); + } + } + + return out; +} + +function to_edge_id(from, to, path) { // e.g HTTP-Collector|JSON-Parser-queue|_default + return [from, to.replace(/-queue$/, ''), path].map(escape).join('|'); +} + +function from_edge_id(edge_id) { + let [from, to, path] = edge_id.split('|').map(unescape); + return [from, `${to}-queue`, path]; +} + +function gen_new_id(prefix) { + if (!(prefix in app.nodes)) { // no need to add numeric suffix + return prefix; + } + + let i = 1, new_id; + //reserve a new unique name + do { + new_id = `${prefix}-${++i}`; + } while (new_id in app.nodes); + + return new_id; + +} diff --git a/intelmq/web/static/js/management.js b/intelmq/web/static/js/management.js new file mode 100644 index 000000000..f8315ac0c --- /dev/null +++ b/intelmq/web/static/js/management.js @@ -0,0 +1,148 @@ +// SPDX-FileCopyrightText: 2020 IntelMQ Team +// +// SPDX-License-Identifier: AGPL-3.0-or-later +'use strict'; + +var BOT_STATUS_DEFINITION = BOT_STATUS_DEFINITION || {}; +var BOT_CLASS_DEFINITION = BOT_CLASS_DEFINITION || {}; +var bot_status = bot_status || {}; +var botnet_status = botnet_status || {}; +var reload_interval; + +$('#bot-table').dataTable({ + lengthMenu: [[5, 10, 25, -1], [5, 10, 25, "All"]], + pageLength: -1, + columns: ['bot_id', 'bot_status', 'actions'].map(data => {return {data}}), + createdRow: (row, data) => $("td:eq(2)", row).append(generate_control_buttons(data.bot_id, false, refresh_status)), + +}); + +window.onresize = function () { + $('#bot-table').dataTable().fnAdjustColumnSizing(); + $('#bot-table').dataTable().fnDraw(); +}; + +var $bt = $('#bot-table'); +$(function () { + load_file(RUNTIME_FILE, config => read_runtime_conf(config)); + + $bt.dataTable().fnClearTable(); + + // generate control buttons for every panel + $("#botnet-panels [data-botnet-group]").each(function () { + $(this).find("h4").data().waiting_count = 0; + $(".panel-body .panel-div", $(this)).after(generate_control_buttons(false, $(this).attr("data-botnet-group"), refresh_status, true)); + }); + + // fetch info from server + reload_interval = new Interval(() => { + $('#botnet-panels [data-botnet-group=botnet] [data-url=status]').click(); + }, RELOAD_STATE_EVERY * 1000, true).call_now(); + + // + $bt.on("click", 'tr td:first-child', event => click_link(MONITOR_BOT_URL.format(event.target.innerText), event)); +}); + + +function refresh_status(bot, finished) { + if (reload_interval) { + reload_interval.stop(); + } + + // Refresh bot table + let redraw_table = false; + let pending = false; // any bot is in an unknown state + for (let bot_id in bot_status) { + let class_ = BOT_CLASS_DEFINITION[bot_status[bot_id]]; + let status = bot_status[bot_id]; + let $bot = $(`tr[data-bot-id=${bot_id}]`, $bt); + if ($bot.length) { + // row exist, just update the status + if (!$bot.text() !== status) {// class of this bot changes (note that multiple statuses may share the same class ".warning") + for (let state of Object.values(BOT_CLASS_DEFINITION)) { // remove any other status-class + $bot.removeClass(state); + } + $bot.addClass(class_); + $("td:eq(1)", $bot).text(status); + } + } else { + $bt.dataTable().api().row.add({ + bot_id, + bot_status: status, + actions: "", + DT_RowClass: class_, + DT_RowAttr: {"data-bot-id": bot_id} + }); + redraw_table = true; + } + if (status === BOT_STATUS_DEFINITION.unknown) { + pending = true; + } + + } + if (finished) { + // If there is some unknown bots, we re-ask the server to get current information immediately, else re-start the fetching interval. + // (in case of botnets of 100 bots, intelmqctl returns 'unknown' state when bot couldn't start/stop in time) + if (pending) { + reload_interval.call_now(); + } else { + reload_interval.start(); + } + } + + // If there is a new row in the table, we ll redraw + if (redraw_table) { + $bt.dataTable().fnAdjustColumnSizing(); + $bt.dataTable().fnDraw(); + $('#botnet-panels [data-botnet-group]').show(); // showed on the first run + } + + + // Analyze botnet panels + let atLeastOneStopped = {}; + let atLeastOneRunning = {}; + for (let bot_id in bot_status) { // analyze all bots status + if (bot_status[bot_id] === BOT_STATUS_DEFINITION.stopped || bot_status[bot_id] === BOT_STATUS_DEFINITION.unknown) { + atLeastOneStopped.botnet = atLeastOneStopped[bot_definition[bot_id].groupname] = true; + } else if (bot_status[bot_id] === BOT_STATUS_DEFINITION.running) { + atLeastOneRunning.botnet = atLeastOneRunning[bot_definition[bot_id].groupname] = true; + } + } + let get_group_status = function (stopped, running) { + if (stopped && running || !stopped && !running) { + return BOT_STATUS_DEFINITION.incomplete; + } else if (stopped && !running) { + return BOT_STATUS_DEFINITION.stopped; + } else if (!stopped && running) { + return BOT_STATUS_DEFINITION.running; + } + }; + + // Highlight waiting icon of current panel if any operation is pending (we may click "start" and "stop", waiting both operations resolve) + let $el; + if (bot in botnet_status) { // bot button was clicked: highlight its panel (ex: Parsers) + $el = $(this).closest(".panel").find("h4"); + } else { // panel button was clicked + $el = $(`.panel[data-botnet-group=${bot_definition[bot].groupname}]`).find("h4"); + } + $el.toggleClass("waiting", ($el.data().waiting_count += (finished === 0) ? 1 : -1) > 0); + + // Refresh botnet panels + let waiting_total = 0; + $("#botnet-panels > [data-botnet-group]").each(function () { + waiting_total += $(this).find("h4").data().waiting_count; + let botnet = $(this).attr("data-botnet-group"); + botnet_status[botnet] = get_group_status(atLeastOneStopped[botnet], atLeastOneRunning[botnet]); + $('[data-role=control-status]', this).trigger("update"); + + // due to esthetics, fetch the status-info to the line above + if (($el = $(".control-buttons [data-role=control-status]", $(this)).clone())) { + if ($el.text()) { + $(".panel-div", $(this)).html("Status: " + ($el[0].outerHTML || 'Unknown')); + } + } + }); + + // Highlight "Whole Botnet Status" operation in any panel is pending + $('#botnet-panels [data-botnet-group=botnet] h4').toggleClass('waiting', waiting_total > 0); +} diff --git a/intelmq/web/static/js/monitor.js b/intelmq/web/static/js/monitor.js new file mode 100644 index 000000000..55f748e7a --- /dev/null +++ b/intelmq/web/static/js/monitor.js @@ -0,0 +1,601 @@ +// SPDX-FileCopyrightText: 2020 IntelMQ Team , 2020 Edvard Rejthar , 2021 Mikk Margus Möll +// +// SPDX-License-Identifier: AGPL-3.0-or-later +'use strict'; + +var ALL_BOTS = 'All Bots'; +var bot_logs = {}; +var bot_queues = {}; +var path_names = {}; +var reload_queues = null; +var reload_logs = null; +var app = app || {}; +var buffered_bot = null; + +var queue_overview = {}; // one-time queue overview to allow traversing +var $dq = $("#destination-queues"); + +load_configuration(() => { + // refresh parameters panel when ready + if (buffered_bot) { + refresh_configuration_info(buffered_bot); + } +}); + + + +$('#log-table').dataTable({ + lengthMenu: [[5, 10, 25, -1], [5, 10, 25, "All"]], + pageLength: 10, + order: [0, 'desc'], + autoWidth: false, + columns: ['date', 'bot_id', 'log_level', 'message', 'actions'].map(data => { return {data};}) +}); + +window.onresize = redraw; + +$(document).keydown(function (event) { + if ($("#message-playground").is(":focus")) { + if ($("[data-role=inject]").attr("data-checked") === "") { + // when entered a char for first time ever, mark the "inject message" checkbox + $("[data-role=inject]").prop("checked", true).attr("data-checked", true); + } + if (event.ctrlKey && event.keyCode === 13) { + // ctrl+enter submits + $("button[data-role=process]").click(); + } + } +}); + +function redraw() { + redraw_logs(); + redraw_queues(); +} + +function redraw_logs() { + $('#log-table').dataTable().fnClearTable(); + + if (bot_logs == {}) { + $('#log-table').dataTable().fnAdjustColumnSizing(); + $('#log-table').dataTable().fnDraw(); + return; + } + + for (let index in bot_logs) { + let log_row = $.extend(true, {}, bot_logs[index]); + let has_button = false; + + if (log_row.extended_message) { + var buttons_cell = ``; + has_button = true; + log_row.actions = buttons_cell; + } else if (log_row.message.length > MESSAGE_LENGTH) { + log_row.message = `${escape_html(log_row.message.slice(0, MESSAGE_LENGTH))}...`; + buttons_cell = ``; + has_button = true; + log_row.actions = buttons_cell; + } else { + log_row.actions = ''; + } + + + log_row.DT_RowClass = LEVEL_CLASS[log_row.log_level]; + + + $('#log-table').dataTable().fnAddData(log_row); + if (has_button) { + var extended_message_func = message_index => show_extended_message(message_index); + document.getElementById(`button-extended-message-${index}`).addEventListener('click', function (index) { + return function () { + extended_message_func(index) + } + }(index)) + } + } + + $('#log-table').dataTable().fnAdjustColumnSizing(); + $('#log-table').dataTable().fnDraw(); +} + +function redraw_queues() { + let bot_id = getUrlParameter('bot_id') || ALL_BOTS; + + let source_queue_element = document.getElementById('source-queue'); + let internal_queue_element = document.getElementById('internal-queue'); + //let destination_queues_element = document.getElementById('destination-queues'); + + source_queue_element.innerHTML = ''; + internal_queue_element.innerHTML = ''; + //destination_queues_element.innerHTML = ''; + + let bot_info = { + source_queues: {}, + destination_queues: {}, + fetched: true + }; + + if (bot_id === ALL_BOTS || !queue_overview.fetched) { + for (let [bot_name, bot] of Object.entries(bot_queues)) { + let source_queue = bot.source_queue; + let destination_queues = bot.destination_queues; + let internal_queue = bot.internal_queue; + + if (source_queue) { + bot_info.destination_queues[source_queue[0]] = source_queue; + bot_info.destination_queues[source_queue[0]].parent = bot_name; + } + + if (internal_queue !== undefined) { + let queue_name = `${bot_name}-queue-internal`; + bot_info.destination_queues[queue_name] = [queue_name, internal_queue]; + bot_info.destination_queues[queue_name].parent = bot_name; + } + } + } + + if (!queue_overview.fetched) { + // we build queue_overview only once; on bot detail, we spare this block + queue_overview = bot_info; + } + + if (bot_id !== ALL_BOTS) { + bot_info = bot_queues[bot_id]; + } + if (bot_info) { + if (bot_info.source_queue) { + let source_queue = source_queue_element.insertRow(); + let cell0 = source_queue.insertCell(0); + cell0.innerText = bot_info.source_queue[0]; + + let cell1 = source_queue.insertCell(1); + cell1.innerText = bot_info.source_queue[1]; + + let buttons_cell = source_queue.insertCell(2); + buttons_cell.appendChild(generateClearQueueButton(bot_info.source_queue[0])); + } + + if (bot_info.internal_queue !== undefined) { + let internal_queue = internal_queue_element.insertRow(); + let cell0 = internal_queue.insertCell(0); + cell0.innerText = 'internal-queue'; + + let cell1 = internal_queue.insertCell(1); + cell1.innerText = bot_info.internal_queue; + + let buttons_cell = internal_queue.insertCell(2); + buttons_cell.appendChild(generateClearQueueButton(`${bot_id}-queue-internal`)); + } + + let dst_queues = Object.values(bot_info.destination_queues).sort(); + + for (let bot of dst_queues) { + let [queue, count] = bot; + if ($(`tr:eq(${bot}) td:eq(0)`, $dq).text() === queue) { + // row exist, just update the count + $(`tr:eq(${bot}) td:eq(2)`, $dq).text(count); + } else { + // for some reason, dst_queues from server changed from the table + // let's find the table row + let o = $("tr td:first-child", $dq).filter(function () { + return $(this).text() === queue; + }); + if (o.length) { // successfully found + o.next().text(count); + } else { // not present in the table + // make unknown queue a new row + let $tr = $("").data("bot-id", queue_overview.destination_queues[queue].parent).appendTo($dq); + $("").appendTo($tr).text(queue).click(function () { + let selectBot = $(this).closest("tr").data("bot-id"); + if (selectBot) { + select_bot(selectBot, true); + } + }); + $("").appendTo($tr).text(""); + $("").appendTo($tr).text(count); + $("").appendTo($tr).html(generateClearQueueButton(queue)); // regenerate thrash button + } + refresh_path_names(); + } + } + } +} + +function generateClearQueueButton(queue_id) { + let spanHolder = document.createElement('span'); + spanHolder.className = 'fa fa-trash-o'; + + let clearQueueButton = document.createElement('button'); + clearQueueButton.queue = queue_id; + clearQueueButton.type = 'submit'; + clearQueueButton.class = 'btn btn-default'; + clearQueueButton.title = 'Clear'; + clearQueueButton.appendChild(spanHolder); + clearQueueButton.addEventListener("click", function (event) { + clearQueue(this.queue); + }); + + return clearQueueButton; +} + +function clearQueue(queue_id) { + authenticatedGetJson(managementUrl('clear', `id=${queue_id}`)) + .done(function (data) { + redraw_queues(); + $('#queues-panel-title').removeClass('waiting'); + }) + .fail(ajax_fail_callback(`Error clearing queue ${queue_id}`)); +} + +function load_bot_log() { + $('#logs-panel-title').addClass('waiting'); + + let number_of_lines = LOAD_X_LOG_LINES; + + let bot_id = getUrlParameter('bot_id') || ALL_BOTS; + let level = document.getElementById('log-level-indicator').value; + if(bot_id === ALL_BOTS) { + return; + } + // NOTE: The URL to fetch the log used to be "...?scope=log&...". + // It's now ".../getlog" instead of ".../log" because for some + // reason, the client (at least the Firefox versions I tested) did + // not even try to fetch the URL in the latter case. Switching from + // "log" to "getlog" made it work. + authenticatedGetJson(managementUrl('getlog', `id=${bot_id}&lines=${number_of_lines}&level=${level}`)) + .done(function (data) { + if(JSON.stringify(data) != JSON.stringify(bot_logs)) { // redraw only if content changed + bot_logs = data; + redraw_logs(); + } + }) + .fail(ajax_fail_callback('Error loading bot log information')) + .always(() => { + $('#logs-panel-title').removeClass('waiting'); + if (this instanceof Interval) { + this.blocking = false; + } + }); +} + +function load_bot_queues() { + $('#queues-panel-title').addClass('waiting'); + authenticatedGetJson(managementUrl('queues')) + .done(function (data) { + bot_queues = data; + redraw_queues(); + $('#queues-panel-title').removeClass('waiting'); + }) + .fail(ajax_fail_callback('Error loading bot queues information')) + .always(() => { + if (this instanceof Interval) { + this.blocking = false; + } + }); +} + +function select_bot(bot_id, history_push = false) { + if (history_push) { + window.history.pushState(null, null, MONITOR_BOT_URL.format(bot_id)); + } + + $("tr", $dq).remove(); // make destination table rebuild itself + + if (reload_queues) { + reload_queues.stop(); + } + + if (reload_logs) { + reload_logs.stop(); + } + + $('#monitor-target').text(bot_id); + + load_bot_queues(); + + reload_queues = new Interval(load_bot_queues, RELOAD_QUEUES_EVERY * 1000, true); + + $("#destination-queues-table").addClass('highlightHovering'); + if (bot_id !== ALL_BOTS) { + $("#logs-panel, #inspect-panel, #parameters-panel").css('display', 'block'); + $("#source-queue-table-div").css('display', 'block'); + $("#internal-queue-table-div").css('display', 'block'); + //$("#destination-queues-table").removeClass('highlightHovering'); + $("#destination-queues-table-div").removeClass().addClass('col-md-4'); // however, will be reset in refresh_path_names + $("#destination-queue-header").text("Destination Queues"); + + load_bot_log(); + reload_logs = new Interval(load_bot_log, RELOAD_LOGS_EVERY * 1000, true); + + // control buttons in inspect panel + $("#inspect-panel .panel-heading .control-buttons").remove(); + $("#inspect-panel .panel-heading").prepend(generate_control_buttons(bot_id, false, load_bot_log, true)); + + // connect to configuration panel + $('#monitor-target').append(` `); + + } else { + $("#logs-panel, #inspect-panel, #parameters-panel").css('display', 'none'); + $("#source-queue-table-div").css('display', 'none'); + $("#internal-queue-table-div").css('display', 'none'); + //$("#destination-queues-table").addClass('highlightHovering'); + $("#destination-queues-table-div").removeClass().addClass('col-md-12'); + $("#destination-queue-header").text("Queue"); + } + // refresh additional information + refresh_configuration_info(bot_id); +} + +function refresh_path_names() { + let parent = $dq.parent(); + if ($.isEmptyObject(path_names)) { + // expand the columns + //parent.find("col:eq(1)").css("visibility", "collapse"); + parent.find("col:eq(1)").css("display", "none"); + $("td:nth-child(2), th:nth-child(2)", parent).css("display", "none"); + + parent.find("th:eq(0)").removeClass().addClass("width-80"); + parent.find("th:eq(1)").removeClass(); + if ($("#destination-queues-table-div").hasClass('col-md-12')) { + // in full width display of all bots, there is no need of another hassling + return; + } + $("#destination-queues-table-div").removeClass("col-md-5").addClass("col-md-4"); + $("#internal-queue-table-div").removeClass("col-md-3").addClass("col-md-4"); + return; + } + + // fold the columns to make more space on the line due to the Path column + //parent.find("col:eq(1)").css("visibility", "inherit"); + //parent.find("col:eq(1)").css("display", "inherit"); + $("td:nth-child(2), th:nth-child(2)", parent).css("display", "revert"); + + + parent.find("th:eq(0)").removeClass().addClass("width-60"); + parent.find("th:eq(1)").addClass("width-20"); + $("#destination-queues-table-div").removeClass("col-md-4").addClass("col-md-5"); + $("#internal-queue-table-div").removeClass("col-md-4").addClass("col-md-3"); + + $("tr td:first-child", $dq).each(function () { + let path = path_names[$(this).text()] || null; + let $el = $(this).next("td"); + $el.text(path || "_default"); + if (!path) { + $el.css({color: "gray", "font-style": "italic"}); + } + }); +} + +/** + * Refresh information dependent on the loaded config files: parameters panel + named queues + * Only when configuration has already been loaded. + * @param {type} bot_id + * @returns {undefined} + */ +function refresh_configuration_info(bot_id) { + if (!app.nodes) { + // we're not yet ready, buffer the bot for later + buffered_bot = bot_id; + return; + } + + // search for named queue paths + path_names = {}; + + let bots = bot_id === ALL_BOTS ? Object.values(app.nodes) : [app.nodes[bot_id]]; + + for (let node of bots) { + for (let path in node.parameters.destination_queues) { + if (path !== '_default') { + for (let to of node.parameters.destination_queues[path]) { + path_names[to] = path; + } + } + } + } + + refresh_path_names(); + + // refresh parameters panel + let $panel = $("#parameters-panel .panel-body"); + $panel.text(""); + if (!app.nodes[bot_id] || !app.nodes[bot_id].parameters) { + $panel.text("Failed to fetch the information."); + return; + } + let params = app.nodes[bot_id].parameters; + for (let [key, param] of Object.entries(params)) { + if (typeof param !== 'string') { // display json/list instead of "[Object object]" + param = JSON.stringify(param); + } + let $el = $(`
  • ${escape_html(key)}: ${escape_html(param)}
  • `); + if (param && param.indexOf && param.indexOf(ALLOWED_PATH) === 0) { + let url = `${LOAD_CONFIG_SCRIPT}?file=${param}`; + authenticatedGetJson(url, data => { + let html = ""; + if (data.directory) { + html += `

    Directory ${escape_html(data.directory)}

    `; + } + + for (let file in data.files) { + let size = data.files[file].size ? `fetch ${escape_html(data.files[file].size)} B` : ""; + html += `

    File ${file}

    ${size}`; + if (data.files[file].contents) { + html += `
    ${escape_html(data.files[file].contents)}
    `; + } + } + $("
    ", {html: html}).appendTo($el); + }); + } + $el.appendTo($panel); + } + if (!Object.keys(params).length) { + $panel.text("No parameters."); + } +} +$("#parameters-panel").on("click", "a[data-role=fetchlink]", function () { + $.get($(this).attr("href"), data => { + $(this).after(`
    ${escape_html(data)}
    `).remove(); + }); + return false; +}); + +function show_extended_message(index) { + let modal_body = document.getElementById('modal-body'); + + let message = bot_logs[index].message; + + if (bot_logs[index].extended_message) { + message += '
    \n' + + bot_logs[index].extended_message.replace(/\n/g, '
    \n').replace(/ /g, ' '); + } + + modal_body.innerHTML = message; +} + +authenticatedGetJson(managementUrl('botnet', 'action=status')) + .done(function (data) { + let sidemenu = document.getElementById('side-menu'); + + let select_bot_func = function (bot_id) { + return function (event) { + event.preventDefault(); + select_bot(bot_id, true); + return false; + }; + }; + + // Insert link for special item 'All Bots' + let li_element = document.createElement('li'); + let link_element = document.createElement('a'); + link_element.innerText = ALL_BOTS; + link_element.setAttribute('href', `#${MONITOR_BOT_URL.format(ALL_BOTS)}`); + link_element.addEventListener('click', select_bot_func(ALL_BOTS)); + + li_element.appendChild(link_element); + sidemenu.appendChild(li_element); + + // Insert link for every bot + bot_status = data; + $(".control-buttons [data-role=control-status]").trigger("update"); + let bots_ids = Object.keys(data); + bots_ids.sort(); + + for (let index in bots_ids) { + let bot_id = bots_ids[index]; + li_element = document.createElement('li'); + link_element = document.createElement('a'); + + link_element.innerText = bot_id; + link_element.setAttribute('href', `#${MONITOR_BOT_URL.format(bot_id)}`); + link_element.addEventListener('click', select_bot_func(bot_id)); + + li_element.appendChild(link_element); + sidemenu.appendChild(li_element); + } + }) + .fail(ajax_fail_callback('Error loading botnet status')); + + + +$(document).ready(popState); +window.addEventListener("popstate", popState); +document.addEventListener('DOMContentLoaded', function () { + document.getElementById('log-level-indicator').addEventListener('change', load_bot_log); + + // Inspect panel functionality + let $insp = $("#inspect-panel"); + $("button[data-role=clear]", $insp).click(function () { + $("#message-playground").val(""); + $("#run-log").attr("rows", 3).val(""); + }); + $("button[data-role=get]", $insp).click(() => run_command("message get", "get")); + $("button[data-role=pop]", $insp).click(() => run_command("message pop", "pop")); + $("button[data-role=send]", $insp).click(() => run_command("message send", "send", $("#message-playground").val())); + $("button[data-role=process]", $insp).click(function () { + let msg; + if ($("[data-role=inject]", $insp).prop("checked")) { + if (!$("#message-playground").val()) { + show_error("Can't inject message from above – you didn't write any message"); + $("#message-playground").focus(); + return false; + } + msg = $("#message-playground").val(); + } + let dry = $("[data-role=dry]", $insp).prop("checked"); + let show = $("[data-role=show-sent]", $insp).prop("checked"); + run_command("process" + (show ? " --show-sent" : "") + (dry ? " --dryrun" : "") + (msg ? " --msg" : ""), "process", msg, dry, show); + }); +}); + +/** + * For purpose of better learning curve, we build intelmq command here at client + * (however we won't upload it on server, we prefer have a whitelisted set of commands due to security + * @param {string} bot + * @param {string} cmd + * @param {type} msg + * @param {type} dry + * @returns {undefined} + */ +function run_command(display_cmd, cmd, msg = "", dry = false, show = false) { + let bot_id = getUrlParameter('bot_id') || ALL_BOTS; + let tmp = msg ? `'${msg.replaceAll("'", "'\\''")}'` : ""; + $("#command-show").show().text(`${CONTROLLER_CMD} run ${bot_id} ${display_cmd} ${tmp}`); //XX dry are not syntax-correct + $("#run-log").val("loading..."); + $('#inspect-panel-title').addClass('waiting'); + let call = authenticatedAjax({ + method: "post", + data: {msg}, + url: managementUrl('run', `bot=${bot_id}&cmd=${cmd}&dry=${dry}&show=${show}`), + }).done(function (data) { + // Parses the received data to message part and to log-only part + let logs = []; + let msg = []; + let logging = logs; + for (let line of data.split("\n")) { + if (logging === logs) { + if (line === "{") { + logging = msg; + } + } else { + if (line === "}") { + msg.push(line); + logging = logs; + continue; + } + } + + logging.push(line); //write either to logs or msgs + } + if (msg.length) { // we won't rewrite an old message if nothing came + $("#message-playground").attr("rows", msg.length).val(msg.join("\n")); + } + $("#run-log").attr("rows", logs.length).val(logs.join("\n")); + }).fail(ajax_fail_callback('Error getting message')) + .always(() => { + $('#inspect-panel-title').removeClass('waiting'); + $("#run-log").data("call", null); + }); + + // informate user if there is a lag + $("#run-log").data("call", call); + setTimeout(() => { + if ($("#run-log").data("call") === call) { + $("#run-log").val("loading... or timeouting..."); + } + }, 3000); +} + + +/** + * Select correct bot when browsing in history or coming from an external link etc. + */ +function popState() { + $("#run-log").val(""); + let bot_id = getUrlParameter('bot_id') || ALL_BOTS; + if (typeof (bot_id) !== 'undefined') { + //window.history.replaceState(null, null, MONITOR_BOT_URL.format(bot_id)); + select_bot(bot_id); + } else { + select_bot(ALL_BOTS); + } +} diff --git a/intelmq/web/static/js/network-configuration.js b/intelmq/web/static/js/network-configuration.js new file mode 100644 index 000000000..4361cc116 --- /dev/null +++ b/intelmq/web/static/js/network-configuration.js @@ -0,0 +1,283 @@ +// SPDX-FileCopyrightText: 2020 IntelMQ Team , 2020 Edvard Rejthar , 2021 Mikk Margus Möll +// +// SPDX-License-Identifier: AGPL-3.0-or-later + +/** + * Big variable options, passed to vis library. + * There are also all the manipulation methods. + */ +'use strict'; + +var NETWORK_OPTIONS = { + physics: { + hierarchicalRepulsion: { + nodeDistance: 200, + springLength: 200 + }, + stabilization: { + enabled: true, + fit: true + }, + solver: 'hierarchicalRepulsion' + }, + interaction: { + tooltipDelay: 1000, + navigationButtons: true, + keyboard: { + bindToWindow: false + } + }, + nodes: { + font: { + size: 14, // px + face: 'arial', + align: 'center' + } + }, + edges: { + length: 200, + arrows: { + to: {enabled: true, scaleFactor: 1, type: 'arrow'} + }, + physics: true, + font: { + size: 14, // px + face: 'arial', + }, + color: { + inherit: false + }, + smooth: { + enabled: true, + type: 'continuous' + } + }, + groups: { + Collector: { + shape: 'box', + color: GROUP_COLORS['Collector'][0], + }, + Parser: { + shape: 'box', + color: GROUP_COLORS['Parser'][0] + }, + Expert: { + shape: 'box', + color: GROUP_COLORS['Expert'][0], + fontColor: "#FFFFFF" + }, + Output: { + shape: 'box', + color: GROUP_COLORS['Output'][0] + } + }, + + manipulation: { + enabled: true, + initiallyActive: true, + editEdge: false, + + addNode: (data, callback) => create_form("Add Node", data, callback), + editNode: function (data, callback) { + create_form("Edit Node", data, callback); + fill_bot(data.id, undefined, undefined); + }, + deleteNode: function (data, callback) { + callback(data); + let node_set = new Set(data.nodes); + + for (let edge_index of data.edges) { + let [from, to, path] = from_edge_id(edge_index); + if (!node_set.has(from)) { // otherwise handled by node deletion below + remove_edge(from, to, path); + } + } + + for (let node_name of data.nodes) { + delete app.nodes[node_name]; + } + set_pending_change(); + }, + addEdge: function (data, callback) { + if (data.from === data.to) { + show_error('This action would cause an infinite loop'); + return; + } + + if (data.path === undefined) + data.path = '_default'; + + let edit_needed = false; // there is path name clash + let occupied_values = new Set(); // prevent edges from overlapping + let roundness = 0; + + let edge_id = to_edge_id(data.from, data.to, data.path); + let source_paths = app.nodes[data.from].parameters.destination_queues; + for (let path_id in source_paths) { + if (source_paths[path_id].includes(`${data.to}-queue`)) { + let smooth = app.network_data.edges.get(edge_id).smooth; + occupied_values.add(smooth ? smooth.roundness : 0); + + if(path_id === data.path) { + show_error('There is already a link between those bots with the same path, rename.'); + edit_needed = true; + } + } + } + + if (occupied_values.size) { + while(occupied_values.has(roundness)) { + roundness += 0.3; + } + data.smooth = {type: 'curvedCCW', roundness}; + } + + let group_from = app.nodes[data.from].group; + let group_to = app.nodes[data.to].group; + let neighbors = ACCEPTED_NEIGHBORS[group_from]; + let available_neighbor = false; + + if (neighbors.includes(group_to)) { + data.id = edge_id; + callback(data); + available_neighbor = true; + let cautious = CAUTIOUS_NEIGHBORS[group_from] ?? []; + if (cautious.includes(group_to)) { + show_error(`Node type ${group_from} can connect to the ${group_to}, however it's not so common.`); + } + } + + if (!available_neighbor) { + if (neighbors.length === 0) { + show_error(`Node type ${group_from} can't connect to other nodes`); + } else { + show_error(`Node type ${group_from} can only connect to nodes of types: ${neighbors.join()}`); + } + return; + } + + add_edge(data.from, data.to, data.path); + + set_pending_change(data.from); + if (edit_needed) { + editPath(app, data.id, true); + } + }, + deleteEdge: function (data, callback) { + let [from, to, path] = from_edge_id(data.edges[0]); + let queue = app.nodes[from].parameters.destination_queues[path]; + remove_edge(from, to, path); + + set_pending_change(from); + callback(data); + } + }, + layout: { + hierarchical: false, + randomSeed: undefined + } +}; + +/** + * Setting path name of a queue. If path already exists between bots, dialog re-appears. + * If cancelled, previous path name is restored, or queue is deleted (if was just being added). + * As this is not a standard-vis function, it has to be a separate method. + * + * @param app + * @param edge id of the edge + * @param adding True if edge is just being added (and shall be removed if we fail to provide a unique path name). + */ +function editPath(app, edge, adding=false) { + let ok_clicked = false; + let [from, to, original_path] = from_edge_id(edge); + let nondefault_path = original_path === '_default' ? undefined : original_path; + let new_path, nondefault_new_path; + + let $input = $("", {placeholder: "_default", val: nondefault_path}); + popupModal("Set the edge name", $input, () => { + let in_val = $input.val(); + [new_path, nondefault_new_path] = (in_val && in_val !== '_default') ? [in_val, in_val] : ['_default', undefined]; + if (original_path === new_path) { + return; + } + + ok_clicked = true; + set_pending_change(); + }).on("hide.bs.modal", () => { + let from_queues = app.nodes[from].parameters.destination_queues[new_path] ?? []; + let duplicate_edge = from_queues.includes(to); + + if (duplicate_edge) { + if (ok_clicked) { + show_error(`Could not add the queue ${new_path}, there already is such queue.`); + return editPath(app, edge, adding); + } else if(adding) { + show_error(`Removing duplicate edge ${new_path}.`); + } else { + show_error("Keeping original path name."); + return; + } + } + + if (ok_clicked) { + let new_id = to_edge_id(from, to, new_path); + + remove_edge(from, to, original_path); + app.network_data.edges.remove({id: edge}); + + add_edge(from, to, new_path); + app.network_data.edges.add({id: new_id, from, to: to.replace(/-queue$/, ''), label: nondefault_new_path}); + } + }); +} + +/** + * As this is not a standard-vis function, it has to be a separate method. + */ +function duplicateNode(app, bot) { + let new_id = gen_new_id(bot); + + // deep copy old bot information + let node = $.extend(true, {}, app.nodes[bot]); + app.positions[new_id] = app.positions[bot]; + node.id = new_id; + node.bot_id = new_id; + app.nodes[new_id] = node; + // add to the Vis and focus + app.network_data.nodes.add(convert_nodes([node], true)); + for (let edge of app.network.getConnectedEdges(bot).map(edge => app.network_data.edges.get(edge))) { + let [old_from, old_to, path] = from_edge_id(edge.id); + if (edge.from === bot) { + edge.from = new_id; + } + else if (edge.to === bot) { + edge.to = new_id; + } + edge.id = to_edge_id(edge.from, edge.to, path); + app.network_data.edges.add(edge); + } + + app.network.selectNodes([new_id]); + app.network.focus(new_id); + set_pending_change(); +} + +function remove_edge(from, to, path) { + let queues = app.nodes[from].parameters.destination_queues; + let queue = queues[path]; + let to_index = queue.indexOf(to); + if (to_index !== -1) + queue.splice(to_index, 1); + + if (queue.length === 0) + delete queues[path]; +} + +function add_edge(from, to, path) { + if (!to.endsWith('-queue')) { + to += '-queue'; + } + let queues = app.nodes[from].parameters.destination_queues; + let queue = path in queues ? queues[path] : (queues[path] = []); + queue.push(to); +} diff --git a/intelmq/web/static/js/positions.js b/intelmq/web/static/js/positions.js new file mode 100644 index 000000000..b8236a35d --- /dev/null +++ b/intelmq/web/static/js/positions.js @@ -0,0 +1,24 @@ +// SPDX-FileCopyrightText: 2020 IntelMQ Team +// +// SPDX-License-Identifier: AGPL-3.0-or-later + +var app = app || {}; + +function generate_positions_conf() { + var new_positions = app.network.getPositions(); + new_positions = sortObjectByPropertyName(new_positions); + + new_positions.settings = settings; + return JSON.stringify(new_positions, undefined, 4); +} + +function read_positions_conf(config) { + if("settings" in config) { // reload settings + settings = config.settings; + if (settings.physics === null) { + settings.physics = Object.keys(app.nodes).length < 40; // disable physics by default when there are more then 40 bots + } + delete config.settings; + } + return config; +} diff --git a/intelmq/web/static/js/runtime.js b/intelmq/web/static/js/runtime.js new file mode 100644 index 000000000..5c447867a --- /dev/null +++ b/intelmq/web/static/js/runtime.js @@ -0,0 +1,93 @@ +// SPDX-FileCopyrightText: 2020 IntelMQ Team +// +// SPDX-License-Identifier: AGPL-3.0-or-later +'use strict'; + +var app = {}; // will be later redefined as a VisModel object or any other object (used in Configuration and Monitor tab) + +//TODO: add global +function generate_runtime_conf(nodes, defaults) { + + let tmp_nodes = nodes; + tmp_nodes.global = defaults; + + sortObjectByPropertyName(tmp_nodes); + for (let id in tmp_nodes) { + let node = tmp_nodes[id]; + delete node.id; + if ('parameters' in node) { + sortObjectByPropertyName(node.parameters); + } + sortObjectByPropertyName(node); + } + + return JSON.stringify(tmp_nodes, undefined, 4); +} + +function read_runtime_conf(config) { + bot_definition = config; + let nodes = {}; + for (let bot_id in config) { + if (bot_id != 'global') { + bot_definition[bot_id].groupname = GROUPNAME_TO_GROUP[bot_definition[bot_id].group]; // translate ex: `Parser` to `parsers` + let bot = config[bot_id]; + bot.bot_id = bot_id; + + if (!('enabled' in bot)) { + bot.enabled = true; + } + + if (!('run_mode' in bot)) { + bot.run_mode = 'continuous'; + } + + if (bot.parameters.destination_queues === undefined) { + bot.parameters.destination_queues = {}; + } + + nodes[bot_id] = bot; + } + } + + return nodes; +} + +function load_file(url, callback) { + let escaped_url = escape_html(url); + authenticatedGetJson(url) + .done(function (json) { + try { + callback(json); + } + catch(e) { + // don't bother to display error, I think the problem will be clearly seen with the resource itself, not within the processing + console.log(e); + show_error(`Failed to load config file properly ${escaped_url}.`, true); + } + }) + .fail(function (jqxhr, textStatus, error) { + let err = escape_html(`${textStatus}, ${error}`); + show_error(`Get an error ${err} when trying to obtain config file properly ${escaped_url}.`, true); + callback({}); + }); +} + + +// Configuration files fetching +function load_configuration(callback = () => {}) { + load_file(RUNTIME_FILE, (config) => { + app.defaults = read_defaults_conf(config); + app.nodes = read_runtime_conf(config); + if (typeof read_positions_conf !== "undefined") { // skipped on Monitor tab + load_file(POSITIONS_FILE, (config) => { + app.positions = read_positions_conf(config); + draw(); + resize(); + + callback(); + }); + } else { + callback(); + } + }); +} diff --git a/intelmq/web/static/js/sb-admin-2.js b/intelmq/web/static/js/sb-admin-2.js new file mode 100644 index 000000000..b4677aba4 --- /dev/null +++ b/intelmq/web/static/js/sb-admin-2.js @@ -0,0 +1,50 @@ +// SPDX-FileCopyrightText: 2020 IntelMQ Team +// +// SPDX-License-Identifier: AGPL-3.0-or-later +'use strict'; + +$(() => $('#side-menu').metisMenu()); + +//Loads the correct sidebar on window load, +//collapses the sidebar on window resize. +// Sets the min-height of #page-wrapper to window size + +function resize_handler() { + var window_height = (this.window.innerHeight > 0) ? this.window.innerHeight : this.screen.height; + var window_width = (this.window.innerWidth > 0) ? this.window.innerWidth : this.screen.width; + + // Resize body + var body = document.getElementsByTagName('body')[0]; + body.style.height = `${window_height}px`; + body.style.width = `${window_width}px`; + + var container = document.getElementById('page-wrapper-with-sidebar') || document.getElementById('page-wrapper'); + container.style.height = `${window_height - container.offsetTop}px`; + container.style.width = `${window_width - container.offsetLeft}px`; + container.style.overflowX = "auto"; + container.style.overflowY = "auto"; + + var title_height = (window_height * 0.10); + $('.page-header-text').css('font-size', `${title_height}px`); + $('.page-header-text').css('line-height', `${title_height * 2}px`); + + let topOffset = 50; + let width = window_width; + if (width < 768) { + $('div.navbar-collapse').addClass('collapse') + topOffset = 100; // 2-row-menu + } else { + $('div.navbar-collapse').removeClass('collapse') + } + + let height = window_height - topOffset; + if (height < 1) height = 1; + if (height > topOffset) { + $("#page-wrapper").css("min-height", `${height}px`); + } + + $('#side-menu').css('max-height', `${height}px`); + $('#side-menu').css('overflow', 'auto'); +} + +$(window).bind("load resize", resize_handler); diff --git a/intelmq/web/static/js/static.js b/intelmq/web/static/js/static.js new file mode 100644 index 000000000..4fc6c8e7c --- /dev/null +++ b/intelmq/web/static/js/static.js @@ -0,0 +1,600 @@ +// SPDX-FileCopyrightText: 2020 IntelMQ Team , 2020 Edvard Rejthar , 2021 Mikk Margus Möll +// +// SPDX-License-Identifier: AGPL-3.0-or-later +'use strict'; + +var CORE_FIELDS = 5; + +var ACCEPTED_NEIGHBORS = { + Collector: ['Parser', 'Expert', 'Output'], + Parser: ['Expert', 'Output'], + Expert: ['Parser', 'Expert', 'Output'], + Output: [] +} + +var REVERSE_ACCEPTED_NEIGHBORS = Object.fromEntries(Object.keys(ACCEPTED_NEIGHBORS).map(key => [key, []])); + +for (let [from, to_list] of Object.entries(ACCEPTED_NEIGHBORS)) { + for (let to of to_list) { + REVERSE_ACCEPTED_NEIGHBORS[to].push(from); + } +} + +var CAUTIOUS_NEIGHBORS = { + Collector: ['Expert'], + Expert: ['Parser'] +} + +var GROUP_LEVELS = { + Collector: 0, + Parser: 1, + Expert: 2, + Output: 3 +}; +var GROUPNAME_TO_GROUP = { + Collector: "collectors", + Parser: "parsers", + Expert: "experts", + Output: "outputs" +}; + +/** + * 1st value is default color of running bot, latter of a stopped bot + */ +var GROUP_COLORS = { + Collector: ['#ff6666', '#cc6666'], + Parser: ['#66ff66', '#66cc66'], + Expert: ['#66a3ff', '#66a3aa'], + Output: ['#ffff66', '#cccc66'] +} + +var LEVEL_CLASS = { + DEBUG: 'success', + INFO: 'info', + WARNING: 'warning', + ERROR: 'danger', + CRITICAL: 'danger' +} + +var STARTUP_KEYS = ['group', 'name', 'module', 'description', 'enabled', 'run_mode']; + +var BOT_ID_REGEX = /^[0-9a-zA-Z.-]+$/; +var PARAM_KEY_REGEX = /^[0-9a-zA-Z._-]+$/; + +var LOAD_CONFIG_SCRIPT = API + "config"; +var MANAGEMENT_SCRIPT = API + "controller"; + +var BOTS_FILE = API + "bots"; +var HARMONIZATION_FILE = API + "harmonization"; +var RUNTIME_FILE = API + "runtime"; +var POSITIONS_FILE = API + "positions"; + +var RELOAD_QUEUES_EVERY = 1; /* 1 seconds */ +var RELOAD_LOGS_EVERY = 3; /* 3 seconds */ +var RELOAD_STATE_EVERY = 3; /* 3 seconds */ +var LOAD_X_LOG_LINES = 30; + +var MESSAGE_LENGTH = 200; + +var MONITOR_BOT_URL = "monitor.html?bot_id={0}"; + +var page_is_exiting = false; + +var settings = { + physics: null, // by default, physics is on depending on bot count + live: true, // by default on +}; + +$(window).on('unload', () => page_is_exiting = true); + +function sortObjectByPropertyName(obj) { + return Object.keys(obj).sort().reduce((c, d) => (c[d] = obj[d], c), {}); +} + +// String formatting function usage "string {0}".format("1") => "string 1" +if (!String.prototype.format) { + String.prototype.format = function () { + let args = arguments; + return this.replace(/{(\d+)}/g, (match, number) => typeof args[number] === 'undefined' ? match : args[number]); + }; +} + +/* + * error reporting + */ +let lw_tips = new Set(); +$(function () { + let $lw = $("#log-window"); + let closeFn = () => { + $lw.hide(); + $(".contents", $lw).html(""); + lw_tips.clear(); // no tips displayed + return false; + }; + + $lw.on("click", e => { // clicking enlarges but not shrinks so that we may copy the text + let btn = $(e.target); + if (!btn.hasClass("extended")) { + btn.toggleClass("extended"); + + //$(".alert", this).prependTo(btn); + + $(document).on('keydown.close-log-window', event => { + if (event.key == "Escape") { + $(document).off('keydown.close-log-window'); + $lw.removeClass("extended"); + } + }); + } + }); + $("#log-window [role=close]").click(closeFn); +}); + +function show_error(string, permit_html=false) { + if (!permit_html) { + string = escape_html(string); + } + + let d = new Date(); + let time = new Date().toLocaleTimeString().replace(/:\d+ /, ' '); + let $lwc = $("#log-window .contents"); + let $el = $(`

    ${time} ${string}

    `); + let found = false; + $("p", $lwc).each((i, v) => { + if ($("span:eq(2)", $(v)).text() === $("span:eq(2)", $el).text()) { + // we've seen this message before + found = true; + // put it in front of the other errors + // only if the error window is not expanded (so that it does not shuffle when the user read the details) + if (!$(v).closest("#log-window").hasClass("extended")) { + $(v).prependTo($lwc); + } + //blink + let blink_e = v.children[0]; + $(blink_e, $(v)).text(time).stop().animate({opacity: 0.1}, 100, () => { + $(blink_e).animate({opacity: 1}, 100); + }); + // increment 'seen' counter + let counter = parseInt($("span:eq(1)", $(v)).text()) || 1; + $("span:eq(1)", $(v)).text(`${counter + 1}×`); + return false; + } + }); + if (!found) { + $("#log-window").show().find(".contents").prepend($el); + } + /*if(!page_is_exiting) { + alert(string); + }*/ +} + + +function ajax_fail_callback(str) { + return function (jqXHR, textStatus, message) { + if (textStatus === "timeout") { + // this is just a timeout, no other info needed + show_error(`${str} timeout`); + return; + } + if (jqXHR.status === 0) { // page refreshed before ajax finished + return; + } + + let command = "", tip = "", report = ""; + try { + let data = JSON.parse(jqXHR.responseText); + report = data.message; + command = ` ${escape_html(data.command)}`; + if (data.tip && !lw_tips.has(data.tip)) { + // display the tip if not yet displayed on the screen + lw_tips.add(data.tip); + tip = `
    TIP: ${escape_html(data.ip)}
    `; + } + if (message === "Internal Server Error") { + message = ""; // this is expected since we generated this in PHP when an error was spot, ignore + } + } catch (e) { + report = jqXHR.responseText; + } + if (report) { + // include full report but truncate the length to 2000 chars + // (since '.' is not matching newline characters, we're using '[\s\S]' so that even multiline string is shortened) + let report_text = escape_html(report.replace(/^(.{2000})[\s\S]+/, "$1...")); + report_text = report_text.replace(/(?:\r\n|\r|\n)/g, '
    '); + report = ` ${report_text}`; + } + + if (typeof message === 'object') { + message = JSON.stringify(message); + } + + show_error(`${str}:${report}${command}${tip} ${escape_html(message)}`, true); + }; +} + + +/** + * Handy interval class, waiting till AJAX request finishes (won't flood server if there is a lag). + */ +class Interval { + /** + * Class for managing intervals. + * Auto-delaying/boosting depending on server lag. + * Faking intervals by timeouts. + * + * @param {type} fn + * @param {type} delay + * @param {bool} blocking If true, the fn is an AJAX call. The fn will not be called again unless it calls `this.blocking = false` when AJAX is finished. + * You may want to include `.always(() => {this.blocking = false;})` after the AJAX call. (In 'this' should be instance of the Interval object.) + * + * (Note that we preferred that.blocking setter over method unblock() because interval function + * can be called from other sources than this class (ex: at first run) and a non-existent method would pose a problem.) + * @returns {Interval} + */ + constructor(fn, delay, ajax_wait) { + this.fn = fn; + this.delay = this._delay = delay; + this._delayed = function () { + this.time1 = +new Date(); + this.fn.call(this); + if (ajax_wait !== true && this.running) { + this.start(); + } + }.bind(this); + this.start(); + } + + start() { + this.stop(); + this.running = true; + this.instance = setTimeout(this._delayed, this._delay); + return this; + } + + stop() { + clearTimeout(this.instance); + this.running = false; + return this; + } + + /** + * Launch callback function now, reset and start the interval. + * @return {Interval} + */ + call_now() { + this.stop(); + this._delayed(); + this.start(); + return this; + } + + /** + * Start if stopped or vice versa. + * @param start If defined, true to be started or vice versa. + */ + toggle(start = null) { + if (start === null) { + this.toggle(!this.running); + } else if (start) { + this.start(); + } else { + this.stop(); + } + return this; + } + + set blocking(b) { + if (b === false) { + let rtt = +new Date() - this.time1; + if (rtt > this._delay / 3) { + if (this._delay < this.delay * 10) { + this._delay += 100; + } + } else if (rtt < this._delay / 4 && this._delay >= this.delay) { + this._delay -= 100; + } + if (this.running) { + this.start(); + } + } + } +} + +/** + * JS-click on a link that supports Ctrl+clicking for opening in a new tab. + * @param {string} url + * @returns {Boolean} False so that js-handled click is not followed further by the browser. + */ +function click_link(url, event) { + if (event && event.ctrlKey) { // we want open a new tab + let win = window.open(url, '_blank'); + if (win) { + win.focus(); + } else { // popups disabled + window.location = url; + } + } else { + window.location = url; + } + return false; +} + + +/** + * Control buttons to start/stop/... a bot, group or whole botnet + */ +var BOT_CLASS_DEFINITION = { + starting: 'warning', + running: 'success', + stopping: 'warning', + stopped: 'danger', + reloading: 'warning', + restarting: 'warning', + incomplete: 'warning', + error: 'danger', + disabled: 'ligth', + unknown: 'warning' +}; +var BOT_STATUS_DEFINITION = { + starting: 'starting', + running: 'running', + stopping: 'stopping', + stopped: 'stopped', + reloading: 'reloading', + restarting: 'restarting', + incomplete: 'incomplete', + error: 'error', + unknown: 'unknown' +}; + +var botnet_status = {}; // {group | true (for whole botnet) : BOT_STATUS_DEFINITION} +var bot_status = {}; // {bot-id : BOT_STATUS_DEFINITION} +var bot_status_previous = {}; // we need a shallow copy of bot_status, it's too slow to ask `app` every time +var bot_definition = {}; // {bot-id : runtime information (group, ...)}; only management.js uses this in time + +$(document).on("click", ".control-buttons button", e => { + let btn = $(e.target); + + let parent = btn.parent(); + if (parent.hasClass('btn')) { // clicked on glyphicon, shift up by one level + btn = parent; + parent = parent.parent(); + } + + let bot = parent.attr("data-bot-id"); + let botnet = parent.attr("data-botnet-group"); + let callback_fn = parent.data("callback_fn"); + let url; + if (bot) { + bot_status[bot] = btn.attr("data-status-definition"); + url = managementUrl("bot", `action=${btn.attr("data-url")}&id=${bot}`); + } else { + botnet_status[botnet] = btn.attr("data-status-definition"); + url = managementUrl('botnet', `action=${btn.attr("data-url")}&group=${botnet}`); + for (let bot_d of Object.values(bot_definition)) { + if (bot_d.groupname === botnet) { + bot_status[bot_d.bot_id] = btn.attr("data-status-definition"); + } + } + + } + + callback_fn.call(e.target, bot || botnet, 0); + btn.siblings("[data-role=control-status]").trigger("update"); + + authenticatedGetJson(url) + .done(data => { + if (bot) { // only restarting action returns an array of two values, the latter is important; otherwise, this is a string + bot_status[bot] = Array.isArray(data) ? data.slice(-1)[0] : data; + } else { // we received a {bot => status} object + Object.assign(bot_status, data); // merge to current list + } + }) + .fail(() => { + ajax_fail_callback(`Error ${bot_status[bot] || botnet_status[botnet]} bot${!bot ? "net" : ""}`).apply(null, arguments); + bot_status[bot] = BOT_STATUS_DEFINITION.error; + }).always(() => { + btn.siblings("[data-role=control-status]").trigger("update"); + callback_fn.call(e.target, bot || botnet, 1); + }); +}); + +/** + * Public method to include control buttons to DOM. + * @param {string|null} bot id + * @param {string|null} botnet Manipulate the whole botnet or a group. Possible values: "botnet", "collectors", "parsers", ... Parameter bot_id should be null. + * @param {bool} status_info If true, dynamic word containing current status is inserted. + * @param {fn} Fn (this = button clicked, bot-id|botnet, finished = 0|1) + * Launched when a button is clicked (finished 0) and callback after AJAX completed (finished 1). + * @returns {$jQuery} + */ +function generate_control_buttons(bot = null, botnet = null, callback_fn = null, status_info = false) { + let $el = $("#common-templates .control-buttons").clone() + .data("callback_fn", callback_fn || (() => { + })); + if (bot) { + $el.attr("data-bot-id", bot); + $el.attr("data-botnet-group", bot in bot_definition ? bot_definition[bot].groupname : null); // specify group (ignore in Monitor, not needed and might not be ready) + } else { + $el.attr("data-botnet-group", botnet); + } + if (status_info) { + $("", {"data-role": "control-status"}).bind("update", e => { + let btn = $(e.target); + let bot = btn.closest(".control-buttons").attr("data-bot-id"); + let botnet = btn.closest(".control-buttons").attr("data-botnet-group"); + let status = bot ? bot_status[bot] : botnet_status[botnet]; + btn.text(status).removeClass().addClass(`bg-${BOT_CLASS_DEFINITION[status]}`); + }).prependTo($el).trigger("update"); + } + return $el; +} + +/** + * Reads the parameter from URL + */ +function getUrlParameter(sParam) { + let sPageURL = decodeURIComponent(window.location.search.substring(1)), sURLVariables = sPageURL.split('&'), sParameterName, i; + for (let i = 0; i < sURLVariables.length; i++) { + let sParameterName = sURLVariables[i].split('='); + if (sParameterName[0] === sParam) { + return sParameterName[1] === undefined ? true : sParameterName[1]; + } + } +} + +/** + * Accesskeyfie + * Turns visible [data-accesskey] to elements with accesskey and shows the accesskey with an underscore if possible. + */ +function accesskeyfie() { + let seen = new Set(); + $("[data-accesskey]").attr("accesskey", ""); // reset all accesskeys. In Chrome, there might be only one accesskey 'e' on page. + $("[data-accesskey]:visible").each((i, v) => { + let btn = $(v); + let key = btn.attr("data-accesskey"); + if (seen.has(key)) { + return false; // already defined at current page state + } + seen.add(key); + btn.attr("accesskey", key); + // add underscore to the accesskeyed letter if possible (can work badly with elements having nested DOM children) + let t1 = escape_html(btn.text()); + let t2 = t1.replace(new RegExp(key, "i"), match => `${match}`); + if (t1 !== t2) { + btn.html(t2); + } + }); +} + + +/** + * Determine the URL for management commands. + */ +function managementUrl(cmd, params) { + let url = API + cmd; + if (params !== undefined) { + url += "?" + params; + } + return url; +} + + +/** + * Login/session handling + */ + + +function authenticatedGetJson(url) { + return authenticatedAjax({ + dataType: "json", + url, + }); +} + +function authenticatedAjax(settings) { + let token = sessionStorage.getItem("login_token"); + if (token !== null) { + settings.headers = { + Authorization: token + }; + } + return $.ajax(settings); +} + + + +// Intercept the login submit and send an Ajax request instead. +$(document).ready(function() { + updateLoginStatus(); + + $('#loginForm').submit(function(e) { + e.preventDefault(); + $.ajax({ + type: 'POST', + url: managementUrl("login"), + // Specifies exactly which data is sent. + data: { + username: $('#loginForm #username').val(), + password: $('#loginForm #password').val(), + }, + // Specifies which formart is expected as response. + dataType: "json", + // sets timeout to 3 seconds + timeout: 3000, + // Deletes the content of the password field when the request is + // finished. (after success and error callbacks are executed) + complete: () => $('#loginForm #password').val(""), + // Executes this if the request was successful. + }).done(data => { + // Check if login_token and username came back and store them in + // sessionStorage. + if (typeof data.login_token !== 'undefined' && + typeof data.username !== 'undefined') { + sessionStorage.setItem("login_token", data.login_token); + sessionStorage.setItem("username", data.username); + + $('#loginErrorField').text("") + $('#modalLoginForm').modal('hide'); + updateLoginStatus(); + window.location.reload(); + } else if (typeof data.error !== 'undefined') { + // If authentication failed, the returned error message is displayed. + $('#loginErrorField').text(data.error); + } else { + // Other error, display the response for easier debugging. + $('#loginErrorField').text("Login failed, server response was " + data); + } + }) + .fail(function(jqXHR, textStatus) { + if (typeof jqXHR.responseJSON !== 'undefined' && typeof jqXHR.responseJSON.errors !== 'undefined') { + let concatenated = ""; + for (let key in jqXHR.responseJSON.errors) { + concatenated += jqXHR.responseJSON.errors[key] + ". " + } + $('#loginErrorField').text("Login failed, server response was: " + concatenated); + } else { + $('#loginErrorField').text("Login failed with unknown reason. Please report this bug."); + console.log(jqXHR.responseText) + console.log(jqXHR.responseJson) + } + }); + }); + + $('#logOut').click(logout); +}); + +function logout() { + sessionStorage.removeItem("login_token"); + sessionStorage.removeItem("username"); + + updateLoginStatus(); +} + +function updateLoginStatus() { + let status = document.getElementById('login-status'); + let loginButton = document.getElementById('signUp'); + let logoutButton = document.getElementById('logOut'); + let username = sessionStorage.getItem("username"); + if (username !== null) { + status.textContent = `Logged in as: ${username}`; + loginButton.style.display = "none"; + logoutButton.style.removeProperty("display"); + } else { + status.textContent = "Not logged in"; + loginButton.style.removeProperty("display"); + logoutButton.style.display = "none"; + } +} + +var html_characters = [ + ['&', '&'], + ['<', '<'], + ['>', '>'], + ['"', '"'], + ["'", "'"], +]; + +function escape_html(text) { + return html_characters.reduce((s, [character, replacement]) => s.replaceAll(character, replacement), text); +} diff --git a/intelmq/web/static/less/management.less b/intelmq/web/static/less/management.less new file mode 100644 index 000000000..63b838145 --- /dev/null +++ b/intelmq/web/static/less/management.less @@ -0,0 +1,18 @@ +#botnet-panels > div.panel { + .panel-div { + margin-bottom: 16px; + } +} + +#botnet-status { + padding: 8px; +} + +#graph-container { + margin-top: 16px; + overflow: auto; +} + +#bot-table-panel { + overflow: auto; +} \ No newline at end of file diff --git a/intelmq/web/static/less/sb-admin-2.less b/intelmq/web/static/less/sb-admin-2.less new file mode 100644 index 000000000..908c0af64 --- /dev/null +++ b/intelmq/web/static/less/sb-admin-2.less @@ -0,0 +1,542 @@ +/*! + * Start Bootstrap - SB Admin 2 Bootstrap Admin Theme (http://startbootstrap.com) + * Code licensed under the Apache License v2.0. + * For details, see http://www.apache.org/licenses/LICENSE-2.0. + */ + +body { + background-color: #f8f8f8; + overflow: auto; +} + +@media(min-width:768px) { + body { + overflow: hidden; + } +} + +#page-wrapper { + margin: 0px; + padding: 0px; + min-height: 568px; + background-color: #fff; +} + +#page-wrapper-with-sidebar { + padding: 0px; + min-height: 568px; + background-color: #fff; +} + +@media(min-width:768px) { + #page-wrapper-with-sidebar { + position: inherit; + margin: 0 0 0 250px; + padding: 0px; + border-left: 1px solid #e7e7e7; + } +} + +.navbar-top-links li { + display: inline-block; +} + +.navbar-top-links li:last-child { + margin-right: 15px; +} + +.navbar-top-links li a { + padding: 15px; + min-height: 50px; +} + +.navbar-top-links .dropdown-menu li { + display: block; +} + +.navbar-top-links .dropdown-menu li:last-child { + margin-right: 0; +} + +.navbar-top-links .dropdown-menu li a { + padding: 3px 20px; + min-height: 0; +} + +.navbar-top-links .dropdown-menu li a div { + white-space: normal; +} + +.navbar-top-links .dropdown-messages, +.navbar-top-links .dropdown-tasks, +.navbar-top-links .dropdown-alerts { + width: 310px; + min-width: 0; +} + +.navbar-top-links .dropdown-messages { + margin-left: 5px; +} + +.navbar-top-links .dropdown-tasks { + margin-left: -59px; +} + +.navbar-top-links .dropdown-alerts { + margin-left: -123px; +} + +.navbar-top-links .dropdown-user { + right: 0; + left: auto; +} + +.sidebar .sidebar-nav.navbar-collapse { + padding-right: 0; + padding-left: 0; +} + +.sidebar .sidebar-search { + padding: 15px; +} + +.sidebar ul li { + border-bottom: 1px solid #e7e7e7; +} + +.sidebar ul li a.active { + background-color: #eee; +} + +.sidebar .arrow { + float: right; +} + +.sidebar .fa.arrow:before { + content: "\f104"; +} + +.sidebar .active>a>.fa.arrow:before { + content: "\f107"; +} + +.sidebar .nav-second-level li, +.sidebar .nav-third-level li { + border-bottom: 0!important; +} + +.sidebar .nav-second-level li a { + padding-left: 37px; +} + +.sidebar .nav-third-level li a { + padding-left: 52px; +} + +#customListItem{ + border-bottom: none; + padding-top: 10px; + padding-bottom: 10px; + text-align: center; +} + +@media(min-width:768px) { + .sidebar { + z-index: 1; + position: absolute; + width: 250px; + margin-top: 0px; + } + + .navbar-top-links .dropdown-messages, + .navbar-top-links .dropdown-tasks, + .navbar-top-links .dropdown-alerts { + margin-left: auto; + } +} + +.btn-outline { + color: inherit; + background-color: transparent; + transition: all .5s; +} + +.btn-primary.btn-outline { + color: #428bca; +} + +.btn-success.btn-outline { + color: #5cb85c; +} + +.btn-info.btn-outline { + color: #5bc0de; +} + +.btn-warning.btn-outline { + color: #f0ad4e; +} + +.btn-danger.btn-outline { + color: #d9534f; +} + +.btn-primary.btn-outline:hover, +.btn-success.btn-outline:hover, +.btn-info.btn-outline:hover, +.btn-warning.btn-outline:hover, +.btn-danger.btn-outline:hover { + color: #fff; +} + +.chat { + margin: 0; + padding: 0; + list-style: none; +} + +.chat li { + margin-bottom: 10px; + padding-bottom: 5px; + border-bottom: 1px dotted #999; +} + +.chat li.left .chat-body { + margin-left: 60px; +} + +.chat li.right .chat-body { + margin-right: 60px; +} + +.chat li .chat-body p { + margin: 0; +} + +.panel .slidedown .glyphicon, +.chat .glyphicon { + margin-right: 5px; +} + +.chat-panel .panel-body { + height: 350px; + overflow-y: scroll; +} + +.login-panel { + margin-top: 25%; +} + +.flot-chart { + display: block; + height: 400px; +} + +.flot-chart-content { + width: 100%; + height: 100%; +} + +table.dataTable thead .sorting, +table.dataTable thead .sorting_asc, +table.dataTable thead .sorting_desc { + background: transparent; +} + +table.dataTable thead .sorting_asc:after { + content: "\f0de"; + float: right; + font-family: fontawesome; +} + +table.dataTable thead .sorting_desc:after { + content: "\f0dd"; + float: right; + font-family: fontawesome; +} + +table.dataTable thead .sorting:after { + content: "\f0dc"; + float: right; + font-family: fontawesome; + color: rgba(50,50,50,.5); +} + +.highlightHovering td:first-child:hover { + font-weight: bold; + cursor: pointer; +} + +.btn-circle { + width: 30px; + height: 30px; + padding: 6px 0; + border-radius: 15px; + text-align: center; + font-size: 12px; + line-height: 1.428571429; +} + +.btn-circle.btn-lg { + width: 50px; + height: 50px; + padding: 10px 16px; + border-radius: 25px; + font-size: 18px; + line-height: 1.33; +} + +.btn-circle.btn-xl { + width: 70px; + height: 70px; + padding: 10px 16px; + border-radius: 35px; + font-size: 24px; + line-height: 1.33; +} + +.show-grid [class^=col-] { + padding-top: 10px; + padding-bottom: 10px; + border: 1px solid #ddd; + background-color: #eee!important; +} + +.show-grid { + margin: 15px 0; +} + +.huge { + font-size: 40px; +} + +.panel-green { + border-color: #5cb85c; +} + +.panel-green .panel-heading { + border-color: #5cb85c; + color: #fff; + background-color: #5cb85c; +} + +.panel-green a { + color: #5cb85c; +} + +.panel-green a:hover { + color: #3d8b3d; +} + +.panel-red { + border-color: #d9534f; +} + +.panel-red .panel-heading { + border-color: #d9534f; + color: #fff; + background-color: #d9534f; +} + +.panel-red a { + color: #d9534f; +} + +.panel-red a:hover { + color: #b52b27; +} + +.panel-yellow { + border-color: #f0ad4e; +} + +.panel-yellow .panel-heading { + border-color: #f0ad4e; + color: #fff; + background-color: #f0ad4e; +} + +.panel-yellow a { + color: #f0ad4e; +} + +.panel-yellow a:hover { + color: #df8a13; +} + +.jumbotron { + margin-bottom: 15px; + margin-top: 15px; + margin-left: auto; + margin-right: auto; + padding: 0px; + text-align: center; + height: 100%; + max-width: 90%; +} + +.jumbotron .page-header-text { + background-color: #000000; + background-size: contain; + max-width: 100%; +} + +.jumbotron .page-header-text span { + color: #ffffff; + text-align: center; + height: 100%; +} + +.jumbotron-row { + margin-top: 15px; +} + +.center-row { + text-align: center; +} + +.center-row-content { + overflow: auto; + display: inline-block; + float: none; + margin: auto; +} + +.header-img img { + height: 100px; + padding: 5px; +} + +.thumbnail img { + width: 128px; + height: 128px; + padding: 15px; +} + +.form-group { + margin-bottom: 45px; +} + +#bot-table td:first-child:hover { + font-weight: bold; + cursor: pointer; +} + +#network-popUp { + display:none; + position:absolute; + top:15%; + left:5%; + margin: auto; + z-index:299; + background-color: #FFFFFF; + border-style:solid; + border-width:3px; + border-color: #5394ed; + padding:10px; + width:90%; + text-align: center; +} + +@media(min-width:768px) { + #network-popUp { + left: 25%; + width: 50%; + } +} + +#network-popUp-fields { + background: #FFFFFF; + width: 100%; +} + +#network-popUp-fields input { + width: 100%; +} + +#network-popUp-fields td { + text-align: left; +} + +form { + display: inline-block; + margin-bottom: 10px; +} + +#border{ + text-align: center !important; + font-weight: bold; +} + +#network-popUp-title { + width: 100%; + font-size:28px; + display: inherit; +} + +#network-row { + display: none; + height: 90%; +} + +#network-row.col-xs-10 { + height: 100%; +} + +#network-row.col-xs-2 { + height: 100%; +} + +#network-tab { + height: 100%; +} + +.with-bot { + max-height: 75%; + overflow-y: auto; +} + +.without-bot { + +} + +#logs-panel { + margin-top: 15px; +} + +#queues-panel { + margin-top: 15px; +} + +#queues-panel .width-80 { + width: 80%; +} + +#queues-panel .width-20 { + width: 20%; +} + +.waiting { + background-image: url('../images/waiting.gif'); + background-repeat: no-repeat; + background-size: 16px; + background-position: right 10px center; +} + +.row { + margin: 0px; +} + +.navbar-config { + margin-right: 16px; +} + +.index-link:hover { + text-decoration: none; + box-shadow: 1px 1px 16px rgba(0, 0, 0, 1); +} + +.index-link { + display: block; + box-shadow: 1px 1px 16px rgba(0, 0, 0, 0.20); +} diff --git a/intelmq/web/static/less/style.less b/intelmq/web/static/less/style.less new file mode 100644 index 000000000..ec159bde1 --- /dev/null +++ b/intelmq/web/static/less/style.less @@ -0,0 +1,188 @@ +/* + * Navigation + */ +nav ul.nav.navbar-top-links li.active { + color: #555; + cursor: default; + background-color: #fff; + border: 1px solid #ddd; + border-bottom-color: transparent +} + +/* + * Common elements + */ +#common-templates { + display: none; +} + +#wrapper .navbar #log-window { + background-color: black; + color: white; + display: none; + float: right; + margin: 5px 5px; + padding: 5px; + width: 500px; + height: 44px; + overflow: auto; + resize: vertical; + position: absolute; + top: 0; + right: 0; + cursor: pointer; + + &.extended { + height: auto; + max-height: 100vh; + width: auto; + cursor: unset; + overflow:scroll; + } + + [role=close] { + float: right; + cursor: pointer; + } + + .command { + 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; + overflow: auto; + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; + } + + .alert a{ + text-decoration: underline; + display: inline-block; + padding: 4px; + border: 1px solid #ccc; + border-radius: 10px; + } +} + +.fa { + font-family: FontAwesome; +} + +.control-buttons [data-url=status] { + display: none; // this button is normally hidden, used only in script; may be revealed if found useful +} + +/* + * Management page + */ +#botnet-panels > .panel[data-botnet-group] { + display: none; // initially, all other panels are hidden + &[data-botnet-group=botnet] { + display: block; + } +} + +/* + * Monitor page + */ +#botnet-panels .panel .control-buttons [data-role=control-status] { + display: none; // this info is fetched out to line above +} + +#inspect-panel { + .control-buttons { + float: right; + } + + button[data-role="clear"] { + float: right; + } + + #command-show { + display: none; + } + + textarea { + resize: vertical; + } +} + +/* + * Config page + */ + +#templates { + display: none; +} + +#side-menu { +} + +#network-container { + + .control-buttons { + float: left; + + button { + height: 25px; + + span { + top: -2px; + } + } + } + + .monitor-button { + //background-image: url('../plugins/vis.js/img/network/rightArrow.png'); + //background-size: 24%; + div a { + color: black; + } + } + + .duplicate-button { + background-image: url('../plugins/vis.js/img/network/addNodeIcon.png'); + } + + .network-right-menu { + > div { + display: block; + } + + .vis-live-toggle, .vis-physics-toggle { + border-radius: 10px; + position: absolute; + right: 560px; + top: 35px; + white-space: nowrap; + padding: 5px 0 5px 5px; + cursor: pointer; + + &.running { + //padding: 4px 0 4px 4px; + //border:1px solid green; + background-color: #00D000; + } + } + + .vis-live-toggle .icon { + background-image: url("../images/monitor.png"); + background-repeat: no-repeat; + background-size: 30%; // this is a big image + padding-left: 30px; + padding-right: 15px; + position: relative; + z-index: 20; + } + + .vis-physics-toggle { + right: 480px; + } + } +} diff --git a/intelmq/web/static/plugins/bootstrap/bootstrap.css b/intelmq/web/static/plugins/bootstrap/bootstrap.css new file mode 100644 index 000000000..fcab41554 --- /dev/null +++ b/intelmq/web/static/plugins/bootstrap/bootstrap.css @@ -0,0 +1,6834 @@ +/*! + * Bootstrap v3.4.1 (https://getbootstrap.com/) + * Copyright 2011-2019 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; + -ms-text-size-adjust: 100%; + -webkit-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: none; + text-decoration: underline; + -webkit-text-decoration: underline dotted; + -moz-text-decoration: underline dotted; + text-decoration: underline dotted; +} +b, +strong { + font-weight: bold; +} +dfn { + font-style: italic; +} +h1 { + font-size: 2em; + margin: 0.67em 0; +} +mark { + background: #ff0; + color: #000; +} +small { + font-size: 80%; +} +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} +sup { + top: -0.5em; +} +sub { + bottom: -0.25em; +} +img { + border: 0; +} +svg:not(:root) { + overflow: hidden; +} +figure { + margin: 1em 40px; +} +hr { + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + height: 0; +} +pre { + overflow: auto; +} +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; +} +button, +input, +optgroup, +select, +textarea { + color: inherit; + font: inherit; + margin: 0; +} +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 { + border: 0; + padding: 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-appearance: textfield; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; +} +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} +legend { + border: 0; + padding: 0; +} +textarea { + overflow: auto; +} +optgroup { + font-weight: bold; +} +table { + border-collapse: collapse; + border-spacing: 0; +} +td, +th { + padding: 0; +} +/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */ +@media print { + *, + *:before, + *:after { + color: #000 !important; + text-shadow: none !important; + background: transparent !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^="#"]:after, + a[href^="javascript:"]:after { + content: ""; + } + pre, + blockquote { + border: 1px solid #999; + page-break-inside: avoid; + } + thead { + display: table-header-group; + } + tr, + img { + page-break-inside: avoid; + } + img { + max-width: 100% !important; + } + p, + h2, + h3 { + 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 th, + .table-bordered td { + 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-euro:before, +.glyphicon-eur: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; +} +*:before, +*:after { + -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: #333333; + background-color: #fff; +} +input, +button, +select, +textarea { + font-family: inherit; + font-size: inherit; + line-height: inherit; +} +a { + color: #337ab7; + text-decoration: none; +} +a:hover, +a:focus { + color: #23527c; + text-decoration: underline; +} +a:focus { + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +figure { + margin: 0; +} +img { + vertical-align: middle; +} +.img-responsive, +.thumbnail > img, +.thumbnail a > img, +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + display: block; + max-width: 100%; + height: auto; +} +.img-rounded { + border-radius: 6px; +} +.img-thumbnail { + padding: 4px; + line-height: 1.42857143; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 4px; + -webkit-transition: all 0.2s ease-in-out; + -o-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; + display: inline-block; + max-width: 100%; + height: auto; +} +.img-circle { + border-radius: 50%; +} +hr { + margin-top: 20px; + margin-bottom: 20px; + border: 0; + border-top: 1px solid #eeeeee; +} +.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, +h2 small, +h3 small, +h4 small, +h5 small, +h6 small, +.h1 small, +.h2 small, +.h3 small, +.h4 small, +.h5 small, +.h6 small, +h1 .small, +h2 .small, +h3 .small, +h4 .small, +h5 .small, +h6 .small, +.h1 .small, +.h2 .small, +.h3 .small, +.h4 .small, +.h5 .small, +.h6 .small { + font-weight: 400; + line-height: 1; + color: #777777; +} +h1, +.h1, +h2, +.h2, +h3, +.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, +.h4, +h5, +.h5, +h6, +.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: 0.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: #777777; +} +.text-primary { + color: #337ab7; +} +a.text-primary:hover, +a.text-primary:focus { + color: #286090; +} +.text-success { + color: #3c763d; +} +a.text-success:hover, +a.text-success:focus { + color: #2b542c; +} +.text-info { + color: #31708f; +} +a.text-info:hover, +a.text-info:focus { + color: #245269; +} +.text-warning { + color: #8a6d3b; +} +a.text-warning:hover, +a.text-warning:focus { + color: #66512c; +} +.text-danger { + color: #a94442; +} +a.text-danger:hover, +a.text-danger:focus { + color: #843534; +} +.bg-primary { + color: #fff; + background-color: #337ab7; +} +a.bg-primary:hover, +a.bg-primary:focus { + background-color: #286090; +} +.bg-success { + background-color: #dff0d8; +} +a.bg-success:hover, +a.bg-success:focus { + background-color: #c1e2b3; +} +.bg-info { + background-color: #d9edf7; +} +a.bg-info:hover, +a.bg-info:focus { + background-color: #afd9ee; +} +.bg-warning { + background-color: #fcf8e3; +} +a.bg-warning:hover, +a.bg-warning:focus { + background-color: #f7ecb5; +} +.bg-danger { + background-color: #f2dede; +} +a.bg-danger:hover, +a.bg-danger:focus { + background-color: #e4b9b9; +} +.page-header { + padding-bottom: 9px; + margin: 40px 0 20px; + border-bottom: 1px solid #eeeeee; +} +ul, +ol { + margin-top: 0; + margin-bottom: 10px; +} +ul ul, +ol ul, +ul ol, +ol ol { + margin-bottom: 0; +} +.list-unstyled { + padding-left: 0; + list-style: none; +} +.list-inline { + padding-left: 0; + list-style: none; + margin-left: -5px; +} +.list-inline > li { + display: inline-block; + padding-right: 5px; + padding-left: 5px; +} +dl { + margin-top: 0; + margin-bottom: 20px; +} +dt, +dd { + line-height: 1.42857143; +} +dt { + font-weight: 700; +} +dd { + margin-left: 0; +} +@media (min-width: 768px) { + .dl-horizontal dt { + float: left; + width: 160px; + clear: left; + text-align: right; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + .dl-horizontal dd { + margin-left: 180px; + } +} +abbr[title], +abbr[data-original-title] { + cursor: help; +} +.initialism { + font-size: 90%; + text-transform: uppercase; +} +blockquote { + padding: 10px 20px; + margin: 0 0 20px; + font-size: 17.5px; + border-left: 5px solid #eeeeee; +} +blockquote p:last-child, +blockquote ul:last-child, +blockquote ol:last-child { + margin-bottom: 0; +} +blockquote footer, +blockquote small, +blockquote .small { + display: block; + font-size: 80%; + line-height: 1.42857143; + color: #777777; +} +blockquote footer:before, +blockquote small: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 #eeeeee; + border-left: 0; +} +.blockquote-reverse footer:before, +blockquote.pull-right footer:before, +.blockquote-reverse small:before, +blockquote.pull-right small:before, +.blockquote-reverse .small:before, +blockquote.pull-right .small:before { + content: ""; +} +.blockquote-reverse footer:after, +blockquote.pull-right footer:after, +.blockquote-reverse small:after, +blockquote.pull-right small:after, +.blockquote-reverse .small: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, 0.25); + box-shadow: inset 0 -1px 0 rgba(0, 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: #333333; + 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; +} +.row-no-gutters { + margin-right: 0; + margin-left: 0; +} +.row-no-gutters [class*="col-"] { + padding-right: 0; + padding-left: 0; +} +.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 { + position: relative; + min-height: 1px; + padding-right: 15px; + padding-left: 15px; +} +.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 { + 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-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 { + 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-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 { + 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-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 { + 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; +} +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; +} +caption { + padding-top: 8px; + padding-bottom: 8px; + color: #777777; + text-align: left; +} +th { + text-align: left; +} +.table { + width: 100%; + max-width: 100%; + margin-bottom: 20px; +} +.table > thead > tr > th, +.table > tbody > tr > th, +.table > tfoot > tr > th, +.table > thead > tr > td, +.table > tbody > tr > td, +.table > tfoot > tr > td { + 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 > th, +.table > colgroup + thead > tr:first-child > th, +.table > thead:first-child > tr:first-child > th, +.table > caption + thead > tr:first-child > td, +.table > colgroup + thead > tr:first-child > td, +.table > thead:first-child > tr:first-child > td { + border-top: 0; +} +.table > tbody + tbody { + border-top: 2px solid #ddd; +} +.table .table { + background-color: #fff; +} +.table-condensed > thead > tr > th, +.table-condensed > tbody > tr > th, +.table-condensed > tfoot > tr > th, +.table-condensed > thead > tr > td, +.table-condensed > tbody > tr > td, +.table-condensed > tfoot > tr > td { + padding: 5px; +} +.table-bordered { + border: 1px solid #ddd; +} +.table-bordered > thead > tr > th, +.table-bordered > tbody > tr > th, +.table-bordered > tfoot > tr > th, +.table-bordered > thead > tr > td, +.table-bordered > tbody > tr > td, +.table-bordered > tfoot > tr > td { + border: 1px solid #ddd; +} +.table-bordered > thead > tr > th, +.table-bordered > thead > tr > td { + border-bottom-width: 2px; +} +.table-striped > tbody > tr:nth-of-type(odd) { + background-color: #f9f9f9; +} +.table-hover > tbody > tr:hover { + background-color: #f5f5f5; +} +.table > thead > tr > td.active, +.table > tbody > tr > td.active, +.table > tfoot > tr > td.active, +.table > thead > tr > th.active, +.table > tbody > tr > th.active, +.table > tfoot > tr > th.active, +.table > thead > tr.active > td, +.table > tbody > tr.active > td, +.table > tfoot > tr.active > td, +.table > thead > tr.active > th, +.table > tbody > tr.active > th, +.table > tfoot > tr.active > th { + background-color: #f5f5f5; +} +.table-hover > tbody > tr > td.active:hover, +.table-hover > tbody > tr > th.active:hover, +.table-hover > tbody > tr.active:hover > td, +.table-hover > tbody > tr:hover > .active, +.table-hover > tbody > tr.active:hover > th { + background-color: #e8e8e8; +} +.table > thead > tr > td.success, +.table > tbody > tr > td.success, +.table > tfoot > tr > td.success, +.table > thead > tr > th.success, +.table > tbody > tr > th.success, +.table > tfoot > tr > th.success, +.table > thead > tr.success > td, +.table > tbody > tr.success > td, +.table > tfoot > tr.success > td, +.table > thead > tr.success > th, +.table > tbody > tr.success > th, +.table > tfoot > tr.success > th { + background-color: #dff0d8; +} +.table-hover > tbody > tr > td.success:hover, +.table-hover > tbody > tr > th.success:hover, +.table-hover > tbody > tr.success:hover > td, +.table-hover > tbody > tr:hover > .success, +.table-hover > tbody > tr.success:hover > th { + background-color: #d0e9c6; +} +.table > thead > tr > td.info, +.table > tbody > tr > td.info, +.table > tfoot > tr > td.info, +.table > thead > tr > th.info, +.table > tbody > tr > th.info, +.table > tfoot > tr > th.info, +.table > thead > tr.info > td, +.table > tbody > tr.info > td, +.table > tfoot > tr.info > td, +.table > thead > tr.info > th, +.table > tbody > tr.info > th, +.table > tfoot > tr.info > th { + background-color: #d9edf7; +} +.table-hover > tbody > tr > td.info:hover, +.table-hover > tbody > tr > th.info:hover, +.table-hover > tbody > tr.info:hover > td, +.table-hover > tbody > tr:hover > .info, +.table-hover > tbody > tr.info:hover > th { + background-color: #c4e3f3; +} +.table > thead > tr > td.warning, +.table > tbody > tr > td.warning, +.table > tfoot > tr > td.warning, +.table > thead > tr > th.warning, +.table > tbody > tr > th.warning, +.table > tfoot > tr > th.warning, +.table > thead > tr.warning > td, +.table > tbody > tr.warning > td, +.table > tfoot > tr.warning > td, +.table > thead > tr.warning > th, +.table > tbody > tr.warning > th, +.table > tfoot > tr.warning > th { + background-color: #fcf8e3; +} +.table-hover > tbody > tr > td.warning:hover, +.table-hover > tbody > tr > th.warning:hover, +.table-hover > tbody > tr.warning:hover > td, +.table-hover > tbody > tr:hover > .warning, +.table-hover > tbody > tr.warning:hover > th { + background-color: #faf2cc; +} +.table > thead > tr > td.danger, +.table > tbody > tr > td.danger, +.table > tfoot > tr > td.danger, +.table > thead > tr > th.danger, +.table > tbody > tr > th.danger, +.table > tfoot > tr > th.danger, +.table > thead > tr.danger > td, +.table > tbody > tr.danger > td, +.table > tfoot > tr.danger > td, +.table > thead > tr.danger > th, +.table > tbody > tr.danger > th, +.table > tfoot > tr.danger > th { + background-color: #f2dede; +} +.table-hover > tbody > tr > td.danger:hover, +.table-hover > tbody > tr > th.danger:hover, +.table-hover > tbody > tr.danger:hover > td, +.table-hover > tbody > tr:hover > .danger, +.table-hover > tbody > tr.danger:hover > th { + background-color: #ebcccc; +} +.table-responsive { + min-height: 0.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 > thead > tr > th, + .table-responsive > .table > tbody > tr > th, + .table-responsive > .table > tfoot > tr > th, + .table-responsive > .table > thead > tr > td, + .table-responsive > .table > tbody > tr > td, + .table-responsive > .table > tfoot > tr > td { + white-space: nowrap; + } + .table-responsive > .table-bordered { + border: 0; + } + .table-responsive > .table-bordered > thead > tr > th:first-child, + .table-responsive > .table-bordered > tbody > tr > th:first-child, + .table-responsive > .table-bordered > tfoot > tr > th:first-child, + .table-responsive > .table-bordered > thead > tr > td:first-child, + .table-responsive > .table-bordered > tbody > tr > td:first-child, + .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; + } + .table-responsive > .table-bordered > thead > tr > th:last-child, + .table-responsive > .table-bordered > tbody > tr > th:last-child, + .table-responsive > .table-bordered > tfoot > tr > th:last-child, + .table-responsive > .table-bordered > thead > tr > td:last-child, + .table-responsive > .table-bordered > tbody > tr > td:last-child, + .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; + } + .table-responsive > .table-bordered > tbody > tr:last-child > th, + .table-responsive > .table-bordered > tfoot > tr:last-child > th, + .table-responsive > .table-bordered > tbody > tr:last-child > td, + .table-responsive > .table-bordered > tfoot > tr:last-child > td { + 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: #333333; + 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; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; +} +input[type="radio"], +input[type="checkbox"] { + margin: 4px 0 0; + margin-top: 1px \9; + line-height: normal; +} +input[type="radio"][disabled], +input[type="checkbox"][disabled], +input[type="radio"].disabled, +input[type="checkbox"].disabled, +fieldset[disabled] input[type="radio"], +fieldset[disabled] input[type="checkbox"] { + cursor: not-allowed; +} +input[type="file"] { + display: block; +} +input[type="range"] { + display: block; + width: 100%; +} +select[multiple], +select[size] { + height: auto; +} +input[type="file"]:focus, +input[type="radio"]:focus, +input[type="checkbox"]: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: #555555; +} +.form-control { + display: block; + width: 100%; + height: 34px; + padding: 6px 12px; + font-size: 14px; + line-height: 1.42857143; + color: #555555; + background-color: #fff; + background-image: none; + border: 1px solid #ccc; + border-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); + -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; + 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, -webkit-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, 0.6); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, 0.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: #eeeeee; + opacity: 1; +} +.form-control[disabled], +fieldset[disabled] .form-control { + cursor: not-allowed; +} +textarea.form-control { + height: auto; +} +@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[type="date"].input-sm, + input[type="time"].input-sm, + input[type="datetime-local"].input-sm, + input[type="month"].input-sm, + .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"] { + line-height: 30px; + } + input[type="date"].input-lg, + input[type="time"].input-lg, + input[type="datetime-local"].input-lg, + input[type="month"].input-lg, + .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"] { + line-height: 46px; + } +} +.form-group { + margin-bottom: 15px; +} +.radio, +.checkbox { + position: relative; + display: block; + margin-top: 10px; + margin-bottom: 10px; +} +.radio.disabled label, +.checkbox.disabled label, +fieldset[disabled] .radio label, +fieldset[disabled] .checkbox label { + cursor: not-allowed; +} +.radio label, +.checkbox label { + min-height: 20px; + padding-left: 20px; + margin-bottom: 0; + font-weight: 400; + cursor: pointer; +} +.radio input[type="radio"], +.radio-inline input[type="radio"], +.checkbox input[type="checkbox"], +.checkbox-inline input[type="checkbox"] { + position: absolute; + margin-top: 4px \9; + margin-left: -20px; +} +.radio + .radio, +.checkbox + .checkbox { + margin-top: -5px; +} +.radio-inline, +.checkbox-inline { + position: relative; + display: inline-block; + padding-left: 20px; + margin-bottom: 0; + font-weight: 400; + vertical-align: middle; + cursor: pointer; +} +.radio-inline.disabled, +.checkbox-inline.disabled, +fieldset[disabled] .radio-inline, +fieldset[disabled] .checkbox-inline { + cursor: not-allowed; +} +.radio-inline + .radio-inline, +.checkbox-inline + .checkbox-inline { + margin-top: 0; + margin-left: 10px; +} +.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; +} +textarea.input-sm, +select[multiple].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 textarea.form-control, +.form-group-sm select[multiple].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; +} +textarea.input-lg, +select[multiple].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 textarea.form-control, +.form-group-lg select[multiple].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; +} +.input-lg + .form-control-feedback, +.input-group-lg + .form-control-feedback, +.form-group-lg .form-control + .form-control-feedback { + width: 46px; + height: 46px; + line-height: 46px; +} +.input-sm + .form-control-feedback, +.input-group-sm + .form-control-feedback, +.form-group-sm .form-control + .form-control-feedback { + width: 30px; + height: 30px; + line-height: 30px; +} +.has-success .help-block, +.has-success .control-label, +.has-success .radio, +.has-success .checkbox, +.has-success .radio-inline, +.has-success .checkbox-inline, +.has-success.radio label, +.has-success.checkbox label, +.has-success.radio-inline label, +.has-success.checkbox-inline label { + color: #3c763d; +} +.has-success .form-control { + border-color: #3c763d; + -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); +} +.has-success .form-control:focus { + border-color: #2b542c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168; + box-shadow: inset 0 1px 1px rgba(0, 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 .help-block, +.has-warning .control-label, +.has-warning .radio, +.has-warning .checkbox, +.has-warning .radio-inline, +.has-warning .checkbox-inline, +.has-warning.radio label, +.has-warning.checkbox label, +.has-warning.radio-inline label, +.has-warning.checkbox-inline label { + color: #8a6d3b; +} +.has-warning .form-control { + border-color: #8a6d3b; + -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); +} +.has-warning .form-control:focus { + border-color: #66512c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b; + box-shadow: inset 0 1px 1px rgba(0, 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 .help-block, +.has-error .control-label, +.has-error .radio, +.has-error .checkbox, +.has-error .radio-inline, +.has-error .checkbox-inline, +.has-error.radio label, +.has-error.checkbox label, +.has-error.radio-inline label, +.has-error.checkbox-inline label { + color: #a94442; +} +.has-error .form-control { + border-color: #a94442; + -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); +} +.has-error .form-control:focus { + border-color: #843534; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483; + box-shadow: inset 0 1px 1px rgba(0, 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 .input-group-addon, + .form-inline .input-group .input-group-btn, + .form-inline .input-group .form-control { + width: auto; + } + .form-inline .input-group > .form-control { + width: 100%; + } + .form-inline .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio, + .form-inline .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio label, + .form-inline .checkbox label { + padding-left: 0; + } + .form-inline .radio input[type="radio"], + .form-inline .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; + } + .form-inline .has-feedback .form-control-feedback { + top: 0; + } +} +.form-horizontal .radio, +.form-horizontal .checkbox, +.form-horizontal .radio-inline, +.form-horizontal .checkbox-inline { + padding-top: 7px; + margin-top: 0; + margin-bottom: 0; +} +.form-horizontal .radio, +.form-horizontal .checkbox { + 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; + margin-bottom: 0; + font-weight: normal; + text-align: center; + white-space: nowrap; + vertical-align: middle; + -ms-touch-action: manipulation; + touch-action: manipulation; + cursor: pointer; + background-image: none; + border: 1px solid transparent; + padding: 6px 12px; + font-size: 14px; + line-height: 1.42857143; + border-radius: 4px; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.btn:focus, +.btn:active:focus, +.btn.active:focus, +.btn.focus, +.btn:active.focus, +.btn.active.focus { + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +.btn:hover, +.btn:focus, +.btn.focus { + 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, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); +} +.btn.disabled, +.btn[disabled], +fieldset[disabled] .btn { + cursor: not-allowed; + filter: alpha(opacity=65); + opacity: 0.65; + -webkit-box-shadow: none; + box-shadow: none; +} +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; + background-image: none; + border-color: #adadad; +} +.btn-default:active:hover, +.btn-default.active:hover, +.open > .dropdown-toggle.btn-default:hover, +.btn-default:active:focus, +.btn-default.active:focus, +.open > .dropdown-toggle.btn-default:focus, +.btn-default:active.focus, +.btn-default.active.focus, +.open > .dropdown-toggle.btn-default.focus { + color: #333; + background-color: #d4d4d4; + border-color: #8c8c8c; +} +.btn-default.disabled:hover, +.btn-default[disabled]:hover, +fieldset[disabled] .btn-default:hover, +.btn-default.disabled:focus, +.btn-default[disabled]:focus, +fieldset[disabled] .btn-default:focus, +.btn-default.disabled.focus, +.btn-default[disabled].focus, +fieldset[disabled] .btn-default.focus { + 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; + background-image: none; + border-color: #204d74; +} +.btn-primary:active:hover, +.btn-primary.active:hover, +.open > .dropdown-toggle.btn-primary:hover, +.btn-primary:active:focus, +.btn-primary.active:focus, +.open > .dropdown-toggle.btn-primary:focus, +.btn-primary:active.focus, +.btn-primary.active.focus, +.open > .dropdown-toggle.btn-primary.focus { + color: #fff; + background-color: #204d74; + border-color: #122b40; +} +.btn-primary.disabled:hover, +.btn-primary[disabled]:hover, +fieldset[disabled] .btn-primary:hover, +.btn-primary.disabled:focus, +.btn-primary[disabled]:focus, +fieldset[disabled] .btn-primary:focus, +.btn-primary.disabled.focus, +.btn-primary[disabled].focus, +fieldset[disabled] .btn-primary.focus { + 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; + background-image: none; + border-color: #398439; +} +.btn-success:active:hover, +.btn-success.active:hover, +.open > .dropdown-toggle.btn-success:hover, +.btn-success:active:focus, +.btn-success.active:focus, +.open > .dropdown-toggle.btn-success:focus, +.btn-success:active.focus, +.btn-success.active.focus, +.open > .dropdown-toggle.btn-success.focus { + color: #fff; + background-color: #398439; + border-color: #255625; +} +.btn-success.disabled:hover, +.btn-success[disabled]:hover, +fieldset[disabled] .btn-success:hover, +.btn-success.disabled:focus, +.btn-success[disabled]:focus, +fieldset[disabled] .btn-success:focus, +.btn-success.disabled.focus, +.btn-success[disabled].focus, +fieldset[disabled] .btn-success.focus { + 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; + background-image: none; + border-color: #269abc; +} +.btn-info:active:hover, +.btn-info.active:hover, +.open > .dropdown-toggle.btn-info:hover, +.btn-info:active:focus, +.btn-info.active:focus, +.open > .dropdown-toggle.btn-info:focus, +.btn-info:active.focus, +.btn-info.active.focus, +.open > .dropdown-toggle.btn-info.focus { + color: #fff; + background-color: #269abc; + border-color: #1b6d85; +} +.btn-info.disabled:hover, +.btn-info[disabled]:hover, +fieldset[disabled] .btn-info:hover, +.btn-info.disabled:focus, +.btn-info[disabled]:focus, +fieldset[disabled] .btn-info:focus, +.btn-info.disabled.focus, +.btn-info[disabled].focus, +fieldset[disabled] .btn-info.focus { + 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; + background-image: none; + border-color: #d58512; +} +.btn-warning:active:hover, +.btn-warning.active:hover, +.open > .dropdown-toggle.btn-warning:hover, +.btn-warning:active:focus, +.btn-warning.active:focus, +.open > .dropdown-toggle.btn-warning:focus, +.btn-warning:active.focus, +.btn-warning.active.focus, +.open > .dropdown-toggle.btn-warning.focus { + color: #fff; + background-color: #d58512; + border-color: #985f0d; +} +.btn-warning.disabled:hover, +.btn-warning[disabled]:hover, +fieldset[disabled] .btn-warning:hover, +.btn-warning.disabled:focus, +.btn-warning[disabled]:focus, +fieldset[disabled] .btn-warning:focus, +.btn-warning.disabled.focus, +.btn-warning[disabled].focus, +fieldset[disabled] .btn-warning.focus { + 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; + background-image: none; + border-color: #ac2925; +} +.btn-danger:active:hover, +.btn-danger.active:hover, +.open > .dropdown-toggle.btn-danger:hover, +.btn-danger:active:focus, +.btn-danger.active:focus, +.open > .dropdown-toggle.btn-danger:focus, +.btn-danger:active.focus, +.btn-danger.active.focus, +.open > .dropdown-toggle.btn-danger.focus { + color: #fff; + background-color: #ac2925; + border-color: #761c19; +} +.btn-danger.disabled:hover, +.btn-danger[disabled]:hover, +fieldset[disabled] .btn-danger:hover, +.btn-danger.disabled:focus, +.btn-danger[disabled]:focus, +fieldset[disabled] .btn-danger:focus, +.btn-danger.disabled.focus, +.btn-danger[disabled].focus, +fieldset[disabled] .btn-danger.focus { + 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:hover, +.btn-link:focus, +.btn-link:active { + border-color: transparent; +} +.btn-link:hover, +.btn-link:focus { + color: #23527c; + text-decoration: underline; + background-color: transparent; +} +.btn-link[disabled]:hover, +fieldset[disabled] .btn-link:hover, +.btn-link[disabled]:focus, +fieldset[disabled] .btn-link:focus { + color: #777777; + text-decoration: none; +} +.btn-lg, +.btn-group-lg > .btn { + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +.btn-sm, +.btn-group-sm > .btn { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-xs, +.btn-group-xs > .btn { + 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="submit"].btn-block, +input[type="reset"].btn-block, +input[type="button"].btn-block { + width: 100%; +} +.fade { + opacity: 0; + -webkit-transition: opacity 0.15s linear; + -o-transition: opacity 0.15s linear; + transition: opacity 0.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-property: height, visibility; + -o-transition-property: height, visibility; + transition-property: height, visibility; + -webkit-transition-duration: 0.35s; + -o-transition-duration: 0.35s; + transition-duration: 0.35s; + -webkit-transition-timing-function: ease; + -o-transition-timing-function: ease; + transition-timing-function: ease; +} +.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; +} +.dropup, +.dropdown { + 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; + background-clip: padding-box; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.15); + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + box-shadow: 0 6px 12px rgba(0, 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: #333333; + white-space: nowrap; +} +.dropdown-menu > li > a:hover, +.dropdown-menu > li > a:focus { + color: #262626; + text-decoration: none; + background-color: #f5f5f5; +} +.dropdown-menu > .active > a, +.dropdown-menu > .active > a:hover, +.dropdown-menu > .active > a:focus { + color: #fff; + text-decoration: none; + background-color: #337ab7; + outline: 0; +} +.dropdown-menu > .disabled > a, +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + color: #777777; +} +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + 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: #777777; + 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 > .btn, +.btn-group-vertical > .btn { + position: relative; + float: left; +} +.btn-group > .btn:hover, +.btn-group-vertical > .btn:hover, +.btn-group > .btn:focus, +.btn-group-vertical > .btn:focus, +.btn-group > .btn:active, +.btn-group-vertical > .btn:active, +.btn-group > .btn.active, +.btn-group-vertical > .btn.active { + 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, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 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="radio"], +[data-toggle="buttons"] > .btn-group > .btn input[type="radio"], +[data-toggle="buttons"] > .btn input[type="checkbox"], +[data-toggle="buttons"] > .btn-group > .btn input[type="checkbox"] { + 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; +} +textarea.input-group-lg > .form-control, +textarea.input-group-lg > .input-group-addon, +textarea.input-group-lg > .input-group-btn > .btn, +select[multiple].input-group-lg > .form-control, +select[multiple].input-group-lg > .input-group-addon, +select[multiple].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; +} +textarea.input-group-sm > .form-control, +textarea.input-group-sm > .input-group-addon, +textarea.input-group-sm > .input-group-btn > .btn, +select[multiple].input-group-sm > .form-control, +select[multiple].input-group-sm > .input-group-addon, +select[multiple].input-group-sm > .input-group-btn > .btn { + height: auto; +} +.input-group-addon, +.input-group-btn, +.input-group .form-control { + display: table-cell; +} +.input-group-addon:not(:first-child):not(:last-child), +.input-group-btn:not(:first-child):not(:last-child), +.input-group .form-control: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: #555555; + text-align: center; + background-color: #eeeeee; + 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="radio"], +.input-group-addon input[type="checkbox"] { + 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:not(:last-child):not(.dropdown-toggle), +.input-group-btn:last-child > .btn-group:not(:last-child) > .btn { + 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:last-child > .btn, +.input-group-btn:last-child > .btn-group > .btn, +.input-group-btn:last-child > .dropdown-toggle, +.input-group-btn:first-child > .btn:not(:first-child), +.input-group-btn:first-child > .btn-group:not(:first-child) > .btn { + 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:hover, +.input-group-btn > .btn:focus, +.input-group-btn > .btn:active { + 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:hover, +.nav > li > a:focus { + text-decoration: none; + background-color: #eeeeee; +} +.nav > li.disabled > a { + color: #777777; +} +.nav > li.disabled > a:hover, +.nav > li.disabled > a:focus { + color: #777777; + text-decoration: none; + cursor: not-allowed; + background-color: transparent; +} +.nav .open > a, +.nav .open > a:hover, +.nav .open > a:focus { + background-color: #eeeeee; + 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: #eeeeee #eeeeee #ddd; +} +.nav-tabs > li.active > a, +.nav-tabs > li.active > a:hover, +.nav-tabs > li.active > a:focus { + color: #555555; + 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:hover, +.nav-tabs.nav-justified > .active > a:focus { + 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:hover, + .nav-tabs.nav-justified > .active > a:focus { + 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:hover, +.nav-pills > li.active > a:focus { + 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:hover, +.nav-tabs-justified > .active > a:focus { + 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:hover, + .nav-tabs-justified > .active > a:focus { + 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; + border-top: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1); + -webkit-overflow-scrolling: touch; +} +.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-top .navbar-collapse, + .navbar-static-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + padding-right: 0; + padding-left: 0; + } +} +.navbar-fixed-top, +.navbar-fixed-bottom { + position: fixed; + right: 0; + left: 0; + z-index: 1030; +} +.navbar-fixed-top .navbar-collapse, +.navbar-fixed-bottom .navbar-collapse { + max-height: 340px; +} +@media (max-device-width: 480px) and (orientation: landscape) { + .navbar-fixed-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + max-height: 200px; + } +} +@media (min-width: 768px) { + .navbar-fixed-top, + .navbar-fixed-bottom { + 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; +} +.container > .navbar-header, +.container-fluid > .navbar-header, +.container > .navbar-collapse, +.container-fluid > .navbar-collapse { + margin-right: -15px; + margin-left: -15px; +} +@media (min-width: 768px) { + .container > .navbar-header, + .container-fluid > .navbar-header, + .container > .navbar-collapse, + .container-fluid > .navbar-collapse { + 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-brand { + float: left; + height: 50px; + padding: 15px 15px; + font-size: 18px; + line-height: 20px; +} +.navbar-brand:hover, +.navbar-brand:focus { + 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-right: 15px; + margin-top: 8px; + 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 > li > a, + .navbar-nav .open .dropdown-menu .dropdown-header { + padding: 5px 15px 5px 25px; + } + .navbar-nav .open .dropdown-menu > li > a { + line-height: 20px; + } + .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-nav .open .dropdown-menu > li > a:focus { + 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-right: -15px; + margin-left: -15px; + border-top: 1px solid transparent; + border-bottom: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + margin-top: 8px; + margin-bottom: 8px; +} +@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 .input-group-addon, + .navbar-form .input-group .input-group-btn, + .navbar-form .input-group .form-control { + width: auto; + } + .navbar-form .input-group > .form-control { + width: 100%; + } + .navbar-form .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .radio, + .navbar-form .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .radio label, + .navbar-form .checkbox label { + padding-left: 0; + } + .navbar-form .radio input[type="radio"], + .navbar-form .checkbox input[type="checkbox"] { + 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:hover, +.navbar-default .navbar-brand:focus { + 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:hover, +.navbar-default .navbar-nav > li > a:focus { + color: #333; + background-color: transparent; +} +.navbar-default .navbar-nav > .active > a, +.navbar-default .navbar-nav > .active > a:hover, +.navbar-default .navbar-nav > .active > a:focus { + color: #555; + background-color: #e7e7e7; +} +.navbar-default .navbar-nav > .disabled > a, +.navbar-default .navbar-nav > .disabled > a:hover, +.navbar-default .navbar-nav > .disabled > a:focus { + color: #ccc; + background-color: transparent; +} +.navbar-default .navbar-nav > .open > a, +.navbar-default .navbar-nav > .open > a:hover, +.navbar-default .navbar-nav > .open > a:focus { + 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:hover, + .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus { + color: #333; + background-color: transparent; + } + .navbar-default .navbar-nav .open .dropdown-menu > .active > a, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #555; + background-color: #e7e7e7; + } + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #ccc; + background-color: transparent; + } +} +.navbar-default .navbar-toggle { + border-color: #ddd; +} +.navbar-default .navbar-toggle:hover, +.navbar-default .navbar-toggle:focus { + 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-link { + color: #777; +} +.navbar-default .navbar-link:hover { + color: #333; +} +.navbar-default .btn-link { + color: #777; +} +.navbar-default .btn-link:hover, +.navbar-default .btn-link:focus { + color: #333; +} +.navbar-default .btn-link[disabled]:hover, +fieldset[disabled] .navbar-default .btn-link:hover, +.navbar-default .btn-link[disabled]:focus, +fieldset[disabled] .navbar-default .btn-link:focus { + color: #ccc; +} +.navbar-inverse { + background-color: #222; + border-color: #080808; +} +.navbar-inverse .navbar-brand { + color: #9d9d9d; +} +.navbar-inverse .navbar-brand:hover, +.navbar-inverse .navbar-brand:focus { + 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:hover, +.navbar-inverse .navbar-nav > li > a:focus { + color: #fff; + background-color: transparent; +} +.navbar-inverse .navbar-nav > .active > a, +.navbar-inverse .navbar-nav > .active > a:hover, +.navbar-inverse .navbar-nav > .active > a:focus { + color: #fff; + background-color: #080808; +} +.navbar-inverse .navbar-nav > .disabled > a, +.navbar-inverse .navbar-nav > .disabled > a:hover, +.navbar-inverse .navbar-nav > .disabled > a:focus { + color: #444; + background-color: transparent; +} +.navbar-inverse .navbar-nav > .open > a, +.navbar-inverse .navbar-nav > .open > a:hover, +.navbar-inverse .navbar-nav > .open > a:focus { + 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:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus { + color: #fff; + background-color: transparent; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #fff; + background-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #444; + background-color: transparent; + } +} +.navbar-inverse .navbar-toggle { + border-color: #333; +} +.navbar-inverse .navbar-toggle:hover, +.navbar-inverse .navbar-toggle:focus { + 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-link { + color: #9d9d9d; +} +.navbar-inverse .navbar-link:hover { + color: #fff; +} +.navbar-inverse .btn-link { + color: #9d9d9d; +} +.navbar-inverse .btn-link:hover, +.navbar-inverse .btn-link:focus { + color: #fff; +} +.navbar-inverse .btn-link[disabled]:hover, +fieldset[disabled] .navbar-inverse .btn-link:hover, +.navbar-inverse .btn-link[disabled]:focus, +fieldset[disabled] .navbar-inverse .btn-link:focus { + 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: #777777; +} +.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 > a:hover, +.pagination > li > span:hover, +.pagination > li > a:focus, +.pagination > li > span:focus { + z-index: 2; + color: #23527c; + background-color: #eeeeee; + border-color: #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 > .active > a, +.pagination > .active > span, +.pagination > .active > a:hover, +.pagination > .active > span:hover, +.pagination > .active > a:focus, +.pagination > .active > span:focus { + z-index: 3; + color: #fff; + cursor: default; + background-color: #337ab7; + border-color: #337ab7; +} +.pagination > .disabled > span, +.pagination > .disabled > span:hover, +.pagination > .disabled > span:focus, +.pagination > .disabled > a, +.pagination > .disabled > a:hover, +.pagination > .disabled > a:focus { + color: #777777; + 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:hover, +.pager li > a:focus { + text-decoration: none; + background-color: #eeeeee; +} +.pager .next > a, +.pager .next > span { + float: right; +} +.pager .previous > a, +.pager .previous > span { + float: left; +} +.pager .disabled > a, +.pager .disabled > a:hover, +.pager .disabled > a:focus, +.pager .disabled > span { + color: #777777; + cursor: not-allowed; + background-color: #fff; +} +.label { + display: inline; + padding: 0.2em 0.6em 0.3em; + font-size: 75%; + font-weight: 700; + line-height: 1; + color: #fff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: 0.25em; +} +a.label:hover, +a.label:focus { + color: #fff; + text-decoration: none; + cursor: pointer; +} +.label:empty { + display: none; +} +.btn .label { + position: relative; + top: -1px; +} +.label-default { + background-color: #777777; +} +.label-default[href]:hover, +.label-default[href]:focus { + background-color: #5e5e5e; +} +.label-primary { + background-color: #337ab7; +} +.label-primary[href]:hover, +.label-primary[href]:focus { + background-color: #286090; +} +.label-success { + background-color: #5cb85c; +} +.label-success[href]:hover, +.label-success[href]:focus { + background-color: #449d44; +} +.label-info { + background-color: #5bc0de; +} +.label-info[href]:hover, +.label-info[href]:focus { + background-color: #31b0d5; +} +.label-warning { + background-color: #f0ad4e; +} +.label-warning[href]:hover, +.label-warning[href]:focus { + background-color: #ec971f; +} +.label-danger { + background-color: #d9534f; +} +.label-danger[href]:hover, +.label-danger[href]:focus { + background-color: #c9302c; +} +.badge { + display: inline-block; + min-width: 10px; + padding: 3px 7px; + font-size: 12px; + font-weight: bold; + line-height: 1; + color: #fff; + text-align: center; + white-space: nowrap; + vertical-align: middle; + background-color: #777777; + border-radius: 10px; +} +.badge:empty { + display: none; +} +.btn .badge { + position: relative; + top: -1px; +} +.btn-xs .badge, +.btn-group-xs > .btn .badge { + top: 0; + padding: 1px 5px; +} +a.badge:hover, +a.badge:focus { + 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: #eeeeee; +} +.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 0.2s ease-in-out; + -o-transition: border 0.2s ease-in-out; + transition: border 0.2s ease-in-out; +} +.thumbnail > img, +.thumbnail a > img { + margin-right: auto; + margin-left: auto; +} +a.thumbnail:hover, +a.thumbnail:focus, +a.thumbnail.active { + border-color: #337ab7; +} +.thumbnail .caption { + padding: 9px; + color: #333333; +} +.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: bold; +} +.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, 0.1); + box-shadow: inset 0 1px 2px rgba(0, 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, 0.15); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -webkit-transition: width 0.6s ease; + -o-transition: width 0.6s ease; + transition: width 0.6s ease; +} +.progress-striped .progress-bar, +.progress-bar-striped { + 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); + 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); + 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); + -webkit-background-size: 40px 40px; + background-size: 40px 40px; +} +.progress.active .progress-bar, +.progress-bar.active { + -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, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + 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); + 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); +} +.progress-bar-info { + background-color: #5bc0de; +} +.progress-striped .progress-bar-info { + 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); + 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); + 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); +} +.progress-bar-warning { + background-color: #f0ad4e; +} +.progress-striped .progress-bar-warning { + 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); + 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); + 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); +} +.progress-bar-danger { + background-color: #d9534f; +} +.progress-striped .progress-bar-danger { + 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); + 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); + 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); +} +.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-left, +.media-right, +.media-body { + 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; +} +.list-group-item.disabled, +.list-group-item.disabled:hover, +.list-group-item.disabled:focus { + color: #777777; + cursor: not-allowed; + background-color: #eeeeee; +} +.list-group-item.disabled .list-group-item-heading, +.list-group-item.disabled:hover .list-group-item-heading, +.list-group-item.disabled:focus .list-group-item-heading { + color: inherit; +} +.list-group-item.disabled .list-group-item-text, +.list-group-item.disabled:hover .list-group-item-text, +.list-group-item.disabled:focus .list-group-item-text { + color: #777777; +} +.list-group-item.active, +.list-group-item.active:hover, +.list-group-item.active:focus { + z-index: 2; + color: #fff; + background-color: #337ab7; + border-color: #337ab7; +} +.list-group-item.active .list-group-item-heading, +.list-group-item.active:hover .list-group-item-heading, +.list-group-item.active:focus .list-group-item-heading, +.list-group-item.active .list-group-item-heading > small, +.list-group-item.active:hover .list-group-item-heading > small, +.list-group-item.active:focus .list-group-item-heading > small, +.list-group-item.active .list-group-item-heading > .small, +.list-group-item.active:hover .list-group-item-heading > .small, +.list-group-item.active:focus .list-group-item-heading > .small { + color: inherit; +} +.list-group-item.active .list-group-item-text, +.list-group-item.active:hover .list-group-item-text, +.list-group-item.active:focus .list-group-item-text { + color: #c7ddef; +} +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:hover, +button.list-group-item:hover, +a.list-group-item:focus, +button.list-group-item:focus { + color: #555; + text-decoration: none; + background-color: #f5f5f5; +} +button.list-group-item { + width: 100%; + text-align: left; +} +.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:hover, +button.list-group-item-success:hover, +a.list-group-item-success:focus, +button.list-group-item-success:focus { + color: #3c763d; + background-color: #d0e9c6; +} +a.list-group-item-success.active, +button.list-group-item-success.active, +a.list-group-item-success.active:hover, +button.list-group-item-success.active:hover, +a.list-group-item-success.active:focus, +button.list-group-item-success.active:focus { + 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:hover, +button.list-group-item-info:hover, +a.list-group-item-info:focus, +button.list-group-item-info:focus { + color: #31708f; + background-color: #c4e3f3; +} +a.list-group-item-info.active, +button.list-group-item-info.active, +a.list-group-item-info.active:hover, +button.list-group-item-info.active:hover, +a.list-group-item-info.active:focus, +button.list-group-item-info.active:focus { + 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:hover, +button.list-group-item-warning:hover, +a.list-group-item-warning:focus, +button.list-group-item-warning:focus { + color: #8a6d3b; + background-color: #faf2cc; +} +a.list-group-item-warning.active, +button.list-group-item-warning.active, +a.list-group-item-warning.active:hover, +button.list-group-item-warning.active:hover, +a.list-group-item-warning.active:focus, +button.list-group-item-warning.active:focus { + 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:hover, +button.list-group-item-danger:hover, +a.list-group-item-danger:focus, +button.list-group-item-danger:focus { + color: #a94442; + background-color: #ebcccc; +} +a.list-group-item-danger.active, +button.list-group-item-danger.active, +a.list-group-item-danger.active:hover, +button.list-group-item-danger.active:hover, +a.list-group-item-danger.active:focus, +button.list-group-item-danger.active:focus { + 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, 0.05); + box-shadow: 0 1px 1px rgba(0, 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 > a, +.panel-title > small, +.panel-title > .small, +.panel-title > small > a, +.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 > .table, +.panel > .table-responsive > .table, +.panel > .panel-collapse > .table { + margin-bottom: 0; +} +.panel > .table caption, +.panel > .table-responsive > .table caption, +.panel > .panel-collapse > .table caption { + padding-right: 15px; + padding-left: 15px; +} +.panel > .table:first-child, +.panel > .table-responsive:first-child > .table:first-child { + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel > .table:first-child > thead: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-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child { + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel > .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 td:first-child, +.panel > .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 td:first-child, +.panel > .table:first-child > thead:first-child > tr:first-child th: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 th:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child { + border-top-left-radius: 3px; +} +.panel > .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 td:last-child, +.panel > .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 td:last-child, +.panel > .table:first-child > thead:first-child > tr:first-child th: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 th:last-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child { + border-top-right-radius: 3px; +} +.panel > .table:last-child, +.panel > .table-responsive:last-child > .table:last-child { + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child { + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .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 td:first-child, +.panel > .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 td:first-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child { + border-bottom-left-radius: 3px; +} +.panel > .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 td:last-child, +.panel > .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 td:last-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child, +.panel > .table-responsive:last-child > .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 th, +.panel > .table > tbody:first-child > tr:first-child td { + border-top: 0; +} +.panel > .table-bordered, +.panel > .table-responsive > .table-bordered { + border: 0; +} +.panel > .table-bordered > thead > tr > th:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:first-child, +.panel > .table-bordered > tbody > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child, +.panel > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-bordered > thead > tr > td:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:first-child, +.panel > .table-bordered > tbody > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child, +.panel > .table-bordered > tfoot > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; +} +.panel > .table-bordered > thead > tr > th:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:last-child, +.panel > .table-bordered > tbody > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child, +.panel > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-bordered > thead > tr > td:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:last-child, +.panel > .table-bordered > tbody > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child, +.panel > .table-bordered > tfoot > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; +} +.panel > .table-bordered > thead > tr:first-child > td, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > td, +.panel > .table-bordered > tbody > tr:first-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td, +.panel > .table-bordered > thead > tr:first-child > th, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > th, +.panel > .table-bordered > tbody > tr:first-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th { + border-bottom: 0; +} +.panel > .table-bordered > tbody > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td, +.panel > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-bordered > tbody > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th, +.panel > .table-bordered > tfoot > tr:last-child > th, +.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 > .panel-body, +.panel-group .panel-heading + .panel-collapse > .list-group { + 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: #333333; + 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: #333333; +} +.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 iframe, +.embed-responsive embed, +.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, 0.05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); +} +.well blockquote { + border-color: #ddd; + border-color: rgba(0, 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: bold; + line-height: 1; + color: #000; + text-shadow: 0 1px 0 #fff; + filter: alpha(opacity=20); + opacity: 0.2; +} +.close:hover, +.close:focus { + color: #000; + text-decoration: none; + cursor: pointer; + filter: alpha(opacity=50); + opacity: 0.5; +} +button.close { + padding: 0; + cursor: pointer; + background: transparent; + border: 0; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; +} +.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-transform: translate(0, -25%); + -ms-transform: translate(0, -25%); + -o-transform: translate(0, -25%); + transform: translate(0, -25%); + -webkit-transition: -webkit-transform 0.3s ease-out; + -o-transition: -o-transform 0.3s ease-out; + transition: -webkit-transform 0.3s ease-out; + transition: transform 0.3s ease-out; + transition: transform 0.3s ease-out, -webkit-transform 0.3s ease-out, -o-transform 0.3s ease-out; +} +.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; + background-clip: padding-box; + border: 1px solid #999; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 6px; + -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); + box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); + outline: 0; +} +.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: 0.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, 0.5); + box-shadow: 0 5px 15px rgba(0, 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-style: normal; + font-weight: 400; + line-height: 1.42857143; + line-break: auto; + 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; + font-size: 12px; + filter: alpha(opacity=0); + opacity: 0; +} +.tooltip.in { + filter: alpha(opacity=90); + opacity: 0.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.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; +} +.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; +} +.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-style: normal; + font-weight: 400; + line-height: 1.42857143; + line-break: auto; + 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; + font-size: 14px; + background-color: #fff; + background-clip: padding-box; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); +} +.popover.top { + margin-top: -10px; +} +.popover.right { + margin-left: 10px; +} +.popover.bottom { + margin-top: 10px; +} +.popover.left { + margin-left: -10px; +} +.popover > .arrow { + border-width: 11px; +} +.popover > .arrow, +.popover > .arrow:after { + position: absolute; + display: block; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} +.popover > .arrow:after { + content: ""; + border-width: 10px; +} +.popover.top > .arrow { + bottom: -11px; + left: 50%; + margin-left: -11px; + border-top-color: #999999; + border-top-color: rgba(0, 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: #999999; + border-right-color: rgba(0, 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: #999999; + border-bottom-color: rgba(0, 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: #999999; + border-left-color: rgba(0, 0, 0, 0.25); +} +.popover.left > .arrow:after { + right: 1px; + bottom: -10px; + content: " "; + border-right-width: 0; + border-left-color: #fff; +} +.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; +} +.carousel { + position: relative; +} +.carousel-inner { + position: relative; + width: 100%; + overflow: hidden; +} +.carousel-inner > .item { + position: relative; + display: none; + -webkit-transition: 0.6s ease-in-out left; + -o-transition: 0.6s ease-in-out left; + transition: 0.6s ease-in-out left; +} +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + line-height: 1; +} +@media all and (transform-3d), (-webkit-transform-3d) { + .carousel-inner > .item { + -webkit-transition: -webkit-transform 0.6s ease-in-out; + -o-transition: -o-transform 0.6s ease-in-out; + transition: -webkit-transform 0.6s ease-in-out; + transition: transform 0.6s ease-in-out; + transition: transform 0.6s ease-in-out, -webkit-transform 0.6s ease-in-out, -o-transform 0.6s ease-in-out; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-perspective: 1000px; + perspective: 1000px; + } + .carousel-inner > .item.next, + .carousel-inner > .item.active.right { + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + left: 0; + } + .carousel-inner > .item.prev, + .carousel-inner > .item.active.left { + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + left: 0; + } + .carousel-inner > .item.next.left, + .carousel-inner > .item.prev.right, + .carousel-inner > .item.active { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + left: 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, 0.6); + background-color: rgba(0, 0, 0, 0); + filter: alpha(opacity=50); + opacity: 0.5; +} +.carousel-control.left { + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); + background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0.0001))); + background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 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, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); + background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, 0.0001)), to(rgba(0, 0, 0, 0.5))); + background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1); + background-repeat: repeat-x; +} +.carousel-control:hover, +.carousel-control:focus { + color: #fff; + text-decoration: none; + outline: 0; + filter: alpha(opacity=90); + opacity: 0.9; +} +.carousel-control .icon-prev, +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-left, +.carousel-control .glyphicon-chevron-right { + position: absolute; + top: 50%; + z-index: 5; + display: inline-block; + margin-top: -10px; +} +.carousel-control .icon-prev, +.carousel-control .glyphicon-chevron-left { + left: 50%; + margin-left: -10px; +} +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-right { + right: 50%; + margin-right: -10px; +} +.carousel-control .icon-prev, +.carousel-control .icon-next { + 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, 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-prev, + .carousel-control .icon-next { + 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; + } +} +.clearfix:before, +.clearfix:after, +.dl-horizontal dd:before, +.dl-horizontal dd:after, +.container:before, +.container:after, +.container-fluid:before, +.container-fluid:after, +.row:before, +.row:after, +.form-horizontal .form-group:before, +.form-horizontal .form-group:after, +.btn-toolbar:before, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:before, +.btn-group-vertical > .btn-group:after, +.nav:before, +.nav:after, +.navbar:before, +.navbar:after, +.navbar-header:before, +.navbar-header:after, +.navbar-collapse:before, +.navbar-collapse:after, +.pager:before, +.pager:after, +.panel-body:before, +.panel-body:after, +.modal-header:before, +.modal-header:after, +.modal-footer:before, +.modal-footer:after { + display: table; + content: " "; +} +.clearfix:after, +.dl-horizontal dd:after, +.container:after, +.container-fluid:after, +.row:after, +.form-horizontal .form-group:after, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:after, +.nav:after, +.navbar:after, +.navbar-header:after, +.navbar-collapse:after, +.pager:after, +.panel-body:after, +.modal-header:after, +.modal-footer: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-xs, +.visible-sm, +.visible-md, +.visible-lg { + display: none !important; +} +.visible-xs-block, +.visible-xs-inline, +.visible-xs-inline-block, +.visible-sm-block, +.visible-sm-inline, +.visible-sm-inline-block, +.visible-md-block, +.visible-md-inline, +.visible-md-inline-block, +.visible-lg-block, +.visible-lg-inline, +.visible-lg-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; + } + th.visible-xs, + td.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; + } + th.visible-sm, + td.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; + } + th.visible-md, + td.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; + } + th.visible-lg, + td.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; + } + th.visible-print, + td.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.css.map */ \ No newline at end of file diff --git a/intelmq/web/static/plugins/bootstrap/bootstrap.js b/intelmq/web/static/plugins/bootstrap/bootstrap.js new file mode 100644 index 000000000..170bd608f --- /dev/null +++ b/intelmq/web/static/plugins/bootstrap/bootstrap.js @@ -0,0 +1,2580 @@ +/*! + * Bootstrap v3.4.1 (https://getbootstrap.com/) + * Copyright 2011-2019 Twitter, Inc. + * Licensed under the MIT license + */ + +if (typeof jQuery === 'undefined') { + throw new Error('Bootstrap\'s JavaScript requires jQuery') +} + ++function ($) { + 'use strict'; + var version = $.fn.jquery.split(' ')[0].split('.') + if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] > 3)) { + throw new Error('Bootstrap\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4') + } +}(jQuery); + +/* ======================================================================== + * Bootstrap: transition.js v3.4.1 + * https://getbootstrap.com/docs/3.4/javascript/#transitions + * ======================================================================== + * Copyright 2011-2019 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // CSS TRANSITION SUPPORT (Shoutout: https://modernizr.com/) + // ============================================================ + + function transitionEnd() { + var el = document.createElement('bootstrap') + + var transEndEventNames = { + WebkitTransition : 'webkitTransitionEnd', + MozTransition : 'transitionend', + OTransition : 'oTransitionEnd otransitionend', + transition : 'transitionend' + } + + for (var name in transEndEventNames) { + if (el.style[name] !== undefined) { + return { end: transEndEventNames[name] } + } + } + + return false // explicit for ie8 ( ._.) + } + + // https://blog.alexmaccaw.com/css-transitions + $.fn.emulateTransitionEnd = function (duration) { + var called = false + var $el = this + $(this).one('bsTransitionEnd', function () { called = true }) + var callback = function () { if (!called) $($el).trigger($.support.transition.end) } + setTimeout(callback, duration) + return this + } + + $(function () { + $.support.transition = transitionEnd() + + if (!$.support.transition) return + + $.event.special.bsTransitionEnd = { + bindType: $.support.transition.end, + delegateType: $.support.transition.end, + handle: function (e) { + if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments) + } + } + }) + +}(jQuery); + +/* ======================================================================== + * Bootstrap: alert.js v3.4.1 + * https://getbootstrap.com/docs/3.4/javascript/#alerts + * ======================================================================== + * Copyright 2011-2019 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // ALERT CLASS DEFINITION + // ====================== + + var dismiss = '[data-dismiss="alert"]' + var Alert = function (el) { + $(el).on('click', dismiss, this.close) + } + + Alert.VERSION = '3.4.1' + + Alert.TRANSITION_DURATION = 150 + + Alert.prototype.close = function (e) { + var $this = $(this) + var selector = $this.attr('data-target') + + if (!selector) { + selector = $this.attr('href') + selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 + } + + selector = selector === '#' ? [] : selector + var $parent = $(document).find(selector) + + if (e) e.preventDefault() + + if (!$parent.length) { + $parent = $this.closest('.alert') + } + + $parent.trigger(e = $.Event('close.bs.alert')) + + if (e.isDefaultPrevented()) return + + $parent.removeClass('in') + + function removeElement() { + // detach from parent, fire event then clean up data + $parent.detach().trigger('closed.bs.alert').remove() + } + + $.support.transition && $parent.hasClass('fade') ? + $parent + .one('bsTransitionEnd', removeElement) + .emulateTransitionEnd(Alert.TRANSITION_DURATION) : + removeElement() + } + + + // ALERT PLUGIN DEFINITION + // ======================= + + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.alert') + + if (!data) $this.data('bs.alert', (data = new Alert(this))) + if (typeof option == 'string') data[option].call($this) + }) + } + + var old = $.fn.alert + + $.fn.alert = Plugin + $.fn.alert.Constructor = Alert + + + // ALERT NO CONFLICT + // ================= + + $.fn.alert.noConflict = function () { + $.fn.alert = old + return this + } + + + // ALERT DATA-API + // ============== + + $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close) + +}(jQuery); + +/* ======================================================================== + * Bootstrap: button.js v3.4.1 + * https://getbootstrap.com/docs/3.4/javascript/#buttons + * ======================================================================== + * Copyright 2011-2019 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // BUTTON PUBLIC CLASS DEFINITION + // ============================== + + var Button = function (element, options) { + this.$element = $(element) + this.options = $.extend({}, Button.DEFAULTS, options) + this.isLoading = false + } + + Button.VERSION = '3.4.1' + + Button.DEFAULTS = { + loadingText: 'loading...' + } + + Button.prototype.setState = function (state) { + var d = 'disabled' + var $el = this.$element + var val = $el.is('input') ? 'val' : 'html' + var data = $el.data() + + state += 'Text' + + if (data.resetText == null) $el.data('resetText', $el[val]()) + + // push to event loop to allow forms to submit + setTimeout($.proxy(function () { + $el[val](data[state] == null ? this.options[state] : data[state]) + + if (state == 'loadingText') { + this.isLoading = true + $el.addClass(d).attr(d, d).prop(d, true) + } else if (this.isLoading) { + this.isLoading = false + $el.removeClass(d).removeAttr(d).prop(d, false) + } + }, this), 0) + } + + Button.prototype.toggle = function () { + var changed = true + var $parent = this.$element.closest('[data-toggle="buttons"]') + + if ($parent.length) { + var $input = this.$element.find('input') + if ($input.prop('type') == 'radio') { + if ($input.prop('checked')) changed = false + $parent.find('.active').removeClass('active') + this.$element.addClass('active') + } else if ($input.prop('type') == 'checkbox') { + if (($input.prop('checked')) !== this.$element.hasClass('active')) changed = false + this.$element.toggleClass('active') + } + $input.prop('checked', this.$element.hasClass('active')) + if (changed) $input.trigger('change') + } else { + this.$element.attr('aria-pressed', !this.$element.hasClass('active')) + this.$element.toggleClass('active') + } + } + + + // BUTTON PLUGIN DEFINITION + // ======================== + + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.button') + var options = typeof option == 'object' && option + + if (!data) $this.data('bs.button', (data = new Button(this, options))) + + if (option == 'toggle') data.toggle() + else if (option) data.setState(option) + }) + } + + var old = $.fn.button + + $.fn.button = Plugin + $.fn.button.Constructor = Button + + + // BUTTON NO CONFLICT + // ================== + + $.fn.button.noConflict = function () { + $.fn.button = old + return this + } + + + // BUTTON DATA-API + // =============== + + $(document) + .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) { + var $btn = $(e.target).closest('.btn') + Plugin.call($btn, 'toggle') + if (!($(e.target).is('input[type="radio"], input[type="checkbox"]'))) { + // Prevent double click on radios, and the double selections (so cancellation) on checkboxes + e.preventDefault() + // The target component still receive the focus + if ($btn.is('input,button')) $btn.trigger('focus') + else $btn.find('input:visible,button:visible').first().trigger('focus') + } + }) + .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) { + $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type)) + }) + +}(jQuery); + +/* ======================================================================== + * Bootstrap: carousel.js v3.4.1 + * https://getbootstrap.com/docs/3.4/javascript/#carousel + * ======================================================================== + * Copyright 2011-2019 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // CAROUSEL CLASS DEFINITION + // ========================= + + var Carousel = function (element, options) { + this.$element = $(element) + this.$indicators = this.$element.find('.carousel-indicators') + this.options = options + this.paused = null + this.sliding = null + this.interval = null + this.$active = null + this.$items = null + + this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this)) + + this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element + .on('mouseenter.bs.carousel', $.proxy(this.pause, this)) + .on('mouseleave.bs.carousel', $.proxy(this.cycle, this)) + } + + Carousel.VERSION = '3.4.1' + + Carousel.TRANSITION_DURATION = 600 + + Carousel.DEFAULTS = { + interval: 5000, + pause: 'hover', + wrap: true, + keyboard: true + } + + Carousel.prototype.keydown = function (e) { + if (/input|textarea/i.test(e.target.tagName)) return + switch (e.which) { + case 37: this.prev(); break + case 39: this.next(); break + default: return + } + + e.preventDefault() + } + + Carousel.prototype.cycle = function (e) { + e || (this.paused = false) + + this.interval && clearInterval(this.interval) + + this.options.interval + && !this.paused + && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)) + + return this + } + + Carousel.prototype.getItemIndex = function (item) { + this.$items = item.parent().children('.item') + return this.$items.index(item || this.$active) + } + + Carousel.prototype.getItemForDirection = function (direction, active) { + var activeIndex = this.getItemIndex(active) + var willWrap = (direction == 'prev' && activeIndex === 0) + || (direction == 'next' && activeIndex == (this.$items.length - 1)) + if (willWrap && !this.options.wrap) return active + var delta = direction == 'prev' ? -1 : 1 + var itemIndex = (activeIndex + delta) % this.$items.length + return this.$items.eq(itemIndex) + } + + Carousel.prototype.to = function (pos) { + var that = this + var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active')) + + if (pos > (this.$items.length - 1) || pos < 0) return + + if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid" + if (activeIndex == pos) return this.pause().cycle() + + return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos)) + } + + Carousel.prototype.pause = function (e) { + e || (this.paused = true) + + if (this.$element.find('.next, .prev').length && $.support.transition) { + this.$element.trigger($.support.transition.end) + this.cycle(true) + } + + this.interval = clearInterval(this.interval) + + return this + } + + Carousel.prototype.next = function () { + if (this.sliding) return + return this.slide('next') + } + + Carousel.prototype.prev = function () { + if (this.sliding) return + return this.slide('prev') + } + + Carousel.prototype.slide = function (type, next) { + var $active = this.$element.find('.item.active') + var $next = next || this.getItemForDirection(type, $active) + var isCycling = this.interval + var direction = type == 'next' ? 'left' : 'right' + var that = this + + if ($next.hasClass('active')) return (this.sliding = false) + + var relatedTarget = $next[0] + var slideEvent = $.Event('slide.bs.carousel', { + relatedTarget: relatedTarget, + direction: direction + }) + this.$element.trigger(slideEvent) + if (slideEvent.isDefaultPrevented()) return + + this.sliding = true + + isCycling && this.pause() + + if (this.$indicators.length) { + this.$indicators.find('.active').removeClass('active') + var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)]) + $nextIndicator && $nextIndicator.addClass('active') + } + + var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid" + if ($.support.transition && this.$element.hasClass('slide')) { + $next.addClass(type) + if (typeof $next === 'object' && $next.length) { + $next[0].offsetWidth // force reflow + } + $active.addClass(direction) + $next.addClass(direction) + $active + .one('bsTransitionEnd', function () { + $next.removeClass([type, direction].join(' ')).addClass('active') + $active.removeClass(['active', direction].join(' ')) + that.sliding = false + setTimeout(function () { + that.$element.trigger(slidEvent) + }, 0) + }) + .emulateTransitionEnd(Carousel.TRANSITION_DURATION) + } else { + $active.removeClass('active') + $next.addClass('active') + this.sliding = false + this.$element.trigger(slidEvent) + } + + isCycling && this.cycle() + + return this + } + + + // CAROUSEL PLUGIN DEFINITION + // ========================== + + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.carousel') + var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option) + var action = typeof option == 'string' ? option : options.slide + + if (!data) $this.data('bs.carousel', (data = new Carousel(this, options))) + if (typeof option == 'number') data.to(option) + else if (action) data[action]() + else if (options.interval) data.pause().cycle() + }) + } + + var old = $.fn.carousel + + $.fn.carousel = Plugin + $.fn.carousel.Constructor = Carousel + + + // CAROUSEL NO CONFLICT + // ==================== + + $.fn.carousel.noConflict = function () { + $.fn.carousel = old + return this + } + + + // CAROUSEL DATA-API + // ================= + + var clickHandler = function (e) { + var $this = $(this) + var href = $this.attr('href') + if (href) { + href = href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7 + } + + var target = $this.attr('data-target') || href + var $target = $(document).find(target) + + if (!$target.hasClass('carousel')) return + + var options = $.extend({}, $target.data(), $this.data()) + var slideIndex = $this.attr('data-slide-to') + if (slideIndex) options.interval = false + + Plugin.call($target, options) + + if (slideIndex) { + $target.data('bs.carousel').to(slideIndex) + } + + e.preventDefault() + } + + $(document) + .on('click.bs.carousel.data-api', '[data-slide]', clickHandler) + .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler) + + $(window).on('load', function () { + $('[data-ride="carousel"]').each(function () { + var $carousel = $(this) + Plugin.call($carousel, $carousel.data()) + }) + }) + +}(jQuery); + +/* ======================================================================== + * Bootstrap: collapse.js v3.4.1 + * https://getbootstrap.com/docs/3.4/javascript/#collapse + * ======================================================================== + * Copyright 2011-2019 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + +/* jshint latedef: false */ + ++function ($) { + 'use strict'; + + // COLLAPSE PUBLIC CLASS DEFINITION + // ================================ + + var Collapse = function (element, options) { + this.$element = $(element) + this.options = $.extend({}, Collapse.DEFAULTS, options) + this.$trigger = $('[data-toggle="collapse"][href="#' + element.id + '"],' + + '[data-toggle="collapse"][data-target="#' + element.id + '"]') + this.transitioning = null + + if (this.options.parent) { + this.$parent = this.getParent() + } else { + this.addAriaAndCollapsedClass(this.$element, this.$trigger) + } + + if (this.options.toggle) this.toggle() + } + + Collapse.VERSION = '3.4.1' + + Collapse.TRANSITION_DURATION = 350 + + Collapse.DEFAULTS = { + toggle: true + } + + Collapse.prototype.dimension = function () { + var hasWidth = this.$element.hasClass('width') + return hasWidth ? 'width' : 'height' + } + + Collapse.prototype.show = function () { + if (this.transitioning || this.$element.hasClass('in')) return + + var activesData + var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing') + + if (actives && actives.length) { + activesData = actives.data('bs.collapse') + if (activesData && activesData.transitioning) return + } + + var startEvent = $.Event('show.bs.collapse') + this.$element.trigger(startEvent) + if (startEvent.isDefaultPrevented()) return + + if (actives && actives.length) { + Plugin.call(actives, 'hide') + activesData || actives.data('bs.collapse', null) + } + + var dimension = this.dimension() + + this.$element + .removeClass('collapse') + .addClass('collapsing')[dimension](0) + .attr('aria-expanded', true) + + this.$trigger + .removeClass('collapsed') + .attr('aria-expanded', true) + + this.transitioning = 1 + + var complete = function () { + this.$element + .removeClass('collapsing') + .addClass('collapse in')[dimension]('') + this.transitioning = 0 + this.$element + .trigger('shown.bs.collapse') + } + + if (!$.support.transition) return complete.call(this) + + var scrollSize = $.camelCase(['scroll', dimension].join('-')) + + this.$element + .one('bsTransitionEnd', $.proxy(complete, this)) + .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize]) + } + + Collapse.prototype.hide = function () { + if (this.transitioning || !this.$element.hasClass('in')) return + + var startEvent = $.Event('hide.bs.collapse') + this.$element.trigger(startEvent) + if (startEvent.isDefaultPrevented()) return + + var dimension = this.dimension() + + this.$element[dimension](this.$element[dimension]())[0].offsetHeight + + this.$element + .addClass('collapsing') + .removeClass('collapse in') + .attr('aria-expanded', false) + + this.$trigger + .addClass('collapsed') + .attr('aria-expanded', false) + + this.transitioning = 1 + + var complete = function () { + this.transitioning = 0 + this.$element + .removeClass('collapsing') + .addClass('collapse') + .trigger('hidden.bs.collapse') + } + + if (!$.support.transition) return complete.call(this) + + this.$element + [dimension](0) + .one('bsTransitionEnd', $.proxy(complete, this)) + .emulateTransitionEnd(Collapse.TRANSITION_DURATION) + } + + Collapse.prototype.toggle = function () { + this[this.$element.hasClass('in') ? 'hide' : 'show']() + } + + Collapse.prototype.getParent = function () { + return $(document).find(this.options.parent) + .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]') + .each($.proxy(function (i, element) { + var $element = $(element) + this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element) + }, this)) + .end() + } + + Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) { + var isOpen = $element.hasClass('in') + + $element.attr('aria-expanded', isOpen) + $trigger + .toggleClass('collapsed', !isOpen) + .attr('aria-expanded', isOpen) + } + + function getTargetFromTrigger($trigger) { + var href + var target = $trigger.attr('data-target') + || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7 + + return $(document).find(target) + } + + + // COLLAPSE PLUGIN DEFINITION + // ========================== + + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.collapse') + var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) + + if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false + if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) + if (typeof option == 'string') data[option]() + }) + } + + var old = $.fn.collapse + + $.fn.collapse = Plugin + $.fn.collapse.Constructor = Collapse + + + // COLLAPSE NO CONFLICT + // ==================== + + $.fn.collapse.noConflict = function () { + $.fn.collapse = old + return this + } + + + // COLLAPSE DATA-API + // ================= + + $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) { + var $this = $(this) + + if (!$this.attr('data-target')) e.preventDefault() + + var $target = getTargetFromTrigger($this) + var data = $target.data('bs.collapse') + var option = data ? 'toggle' : $this.data() + + Plugin.call($target, option) + }) + +}(jQuery); + +/* ======================================================================== + * Bootstrap: dropdown.js v3.4.1 + * https://getbootstrap.com/docs/3.4/javascript/#dropdowns + * ======================================================================== + * Copyright 2011-2019 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // DROPDOWN CLASS DEFINITION + // ========================= + + var backdrop = '.dropdown-backdrop' + var toggle = '[data-toggle="dropdown"]' + var Dropdown = function (element) { + $(element).on('click.bs.dropdown', this.toggle) + } + + Dropdown.VERSION = '3.4.1' + + function getParent($this) { + var selector = $this.attr('data-target') + + if (!selector) { + selector = $this.attr('href') + selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 + } + + var $parent = selector !== '#' ? $(document).find(selector) : null + + return $parent && $parent.length ? $parent : $this.parent() + } + + function clearMenus(e) { + if (e && e.which === 3) return + $(backdrop).remove() + $(toggle).each(function () { + var $this = $(this) + var $parent = getParent($this) + var relatedTarget = { relatedTarget: this } + + if (!$parent.hasClass('open')) return + + if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return + + $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget)) + + if (e.isDefaultPrevented()) return + + $this.attr('aria-expanded', 'false') + $parent.removeClass('open').trigger($.Event('hidden.bs.dropdown', relatedTarget)) + }) + } + + Dropdown.prototype.toggle = function (e) { + var $this = $(this) + + if ($this.is('.disabled, :disabled')) return + + var $parent = getParent($this) + var isActive = $parent.hasClass('open') + + clearMenus() + + if (!isActive) { + if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) { + // if mobile we use a backdrop because click events don't delegate + $(document.createElement('div')) + .addClass('dropdown-backdrop') + .insertAfter($(this)) + .on('click', clearMenus) + } + + var relatedTarget = { relatedTarget: this } + $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget)) + + if (e.isDefaultPrevented()) return + + $this + .trigger('focus') + .attr('aria-expanded', 'true') + + $parent + .toggleClass('open') + .trigger($.Event('shown.bs.dropdown', relatedTarget)) + } + + return false + } + + Dropdown.prototype.keydown = function (e) { + if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return + + var $this = $(this) + + e.preventDefault() + e.stopPropagation() + + if ($this.is('.disabled, :disabled')) return + + var $parent = getParent($this) + var isActive = $parent.hasClass('open') + + if (!isActive && e.which != 27 || isActive && e.which == 27) { + if (e.which == 27) $parent.find(toggle).trigger('focus') + return $this.trigger('click') + } + + var desc = ' li:not(.disabled):visible a' + var $items = $parent.find('.dropdown-menu' + desc) + + if (!$items.length) return + + var index = $items.index(e.target) + + if (e.which == 38 && index > 0) index-- // up + if (e.which == 40 && index < $items.length - 1) index++ // down + if (!~index) index = 0 + + $items.eq(index).trigger('focus') + } + + + // DROPDOWN PLUGIN DEFINITION + // ========================== + + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.dropdown') + + if (!data) $this.data('bs.dropdown', (data = new Dropdown(this))) + if (typeof option == 'string') data[option].call($this) + }) + } + + var old = $.fn.dropdown + + $.fn.dropdown = Plugin + $.fn.dropdown.Constructor = Dropdown + + + // DROPDOWN NO CONFLICT + // ==================== + + $.fn.dropdown.noConflict = function () { + $.fn.dropdown = old + return this + } + + + // APPLY TO STANDARD DROPDOWN ELEMENTS + // =================================== + + $(document) + .on('click.bs.dropdown.data-api', clearMenus) + .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() }) + .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle) + .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown) + .on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown) + +}(jQuery); + +/* ======================================================================== + * Bootstrap: modal.js v3.4.1 + * https://getbootstrap.com/docs/3.4/javascript/#modals + * ======================================================================== + * Copyright 2011-2019 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // MODAL CLASS DEFINITION + // ====================== + + var Modal = function (element, options) { + this.options = options + this.$body = $(document.body) + this.$element = $(element) + this.$dialog = this.$element.find('.modal-dialog') + this.$backdrop = null + this.isShown = null + this.originalBodyPad = null + this.scrollbarWidth = 0 + this.ignoreBackdropClick = false + this.fixedContent = '.navbar-fixed-top, .navbar-fixed-bottom' + + if (this.options.remote) { + this.$element + .find('.modal-content') + .load(this.options.remote, $.proxy(function () { + this.$element.trigger('loaded.bs.modal') + }, this)) + } + } + + Modal.VERSION = '3.4.1' + + Modal.TRANSITION_DURATION = 300 + Modal.BACKDROP_TRANSITION_DURATION = 150 + + Modal.DEFAULTS = { + backdrop: true, + keyboard: true, + show: true + } + + Modal.prototype.toggle = function (_relatedTarget) { + return this.isShown ? this.hide() : this.show(_relatedTarget) + } + + Modal.prototype.show = function (_relatedTarget) { + var that = this + var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget }) + + this.$element.trigger(e) + + if (this.isShown || e.isDefaultPrevented()) return + + this.isShown = true + + this.checkScrollbar() + this.setScrollbar() + this.$body.addClass('modal-open') + + this.escape() + this.resize() + + this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this)) + + this.$dialog.on('mousedown.dismiss.bs.modal', function () { + that.$element.one('mouseup.dismiss.bs.modal', function (e) { + if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true + }) + }) + + this.backdrop(function () { + var transition = $.support.transition && that.$element.hasClass('fade') + + if (!that.$element.parent().length) { + that.$element.appendTo(that.$body) // don't move modals dom position + } + + that.$element + .show() + .scrollTop(0) + + that.adjustDialog() + + if (transition) { + that.$element[0].offsetWidth // force reflow + } + + that.$element.addClass('in') + + that.enforceFocus() + + var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget }) + + transition ? + that.$dialog // wait for modal to slide in + .one('bsTransitionEnd', function () { + that.$element.trigger('focus').trigger(e) + }) + .emulateTransitionEnd(Modal.TRANSITION_DURATION) : + that.$element.trigger('focus').trigger(e) + }) + } + + Modal.prototype.hide = function (e) { + if (e) e.preventDefault() + + e = $.Event('hide.bs.modal') + + this.$element.trigger(e) + + if (!this.isShown || e.isDefaultPrevented()) return + + this.isShown = false + + this.escape() + this.resize() + + $(document).off('focusin.bs.modal') + + this.$element + .removeClass('in') + .off('click.dismiss.bs.modal') + .off('mouseup.dismiss.bs.modal') + + this.$dialog.off('mousedown.dismiss.bs.modal') + + $.support.transition && this.$element.hasClass('fade') ? + this.$element + .one('bsTransitionEnd', $.proxy(this.hideModal, this)) + .emulateTransitionEnd(Modal.TRANSITION_DURATION) : + this.hideModal() + } + + Modal.prototype.enforceFocus = function () { + $(document) + .off('focusin.bs.modal') // guard against infinite focus loop + .on('focusin.bs.modal', $.proxy(function (e) { + if (document !== e.target && + this.$element[0] !== e.target && + !this.$element.has(e.target).length) { + this.$element.trigger('focus') + } + }, this)) + } + + Modal.prototype.escape = function () { + if (this.isShown && this.options.keyboard) { + this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) { + e.which == 27 && this.hide() + }, this)) + } else if (!this.isShown) { + this.$element.off('keydown.dismiss.bs.modal') + } + } + + Modal.prototype.resize = function () { + if (this.isShown) { + $(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this)) + } else { + $(window).off('resize.bs.modal') + } + } + + Modal.prototype.hideModal = function () { + var that = this + this.$element.hide() + this.backdrop(function () { + that.$body.removeClass('modal-open') + that.resetAdjustments() + that.resetScrollbar() + that.$element.trigger('hidden.bs.modal') + }) + } + + Modal.prototype.removeBackdrop = function () { + this.$backdrop && this.$backdrop.remove() + this.$backdrop = null + } + + Modal.prototype.backdrop = function (callback) { + var that = this + var animate = this.$element.hasClass('fade') ? 'fade' : '' + + if (this.isShown && this.options.backdrop) { + var doAnimate = $.support.transition && animate + + this.$backdrop = $(document.createElement('div')) + .addClass('modal-backdrop ' + animate) + .appendTo(this.$body) + + this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) { + if (this.ignoreBackdropClick) { + this.ignoreBackdropClick = false + return + } + if (e.target !== e.currentTarget) return + this.options.backdrop == 'static' + ? this.$element[0].focus() + : this.hide() + }, this)) + + if (doAnimate) this.$backdrop[0].offsetWidth // force reflow + + this.$backdrop.addClass('in') + + if (!callback) return + + doAnimate ? + this.$backdrop + .one('bsTransitionEnd', callback) + .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : + callback() + + } else if (!this.isShown && this.$backdrop) { + this.$backdrop.removeClass('in') + + var callbackRemove = function () { + that.removeBackdrop() + callback && callback() + } + $.support.transition && this.$element.hasClass('fade') ? + this.$backdrop + .one('bsTransitionEnd', callbackRemove) + .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : + callbackRemove() + + } else if (callback) { + callback() + } + } + + // these following methods are used to handle overflowing modals + + Modal.prototype.handleUpdate = function () { + this.adjustDialog() + } + + Modal.prototype.adjustDialog = function () { + var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight + + this.$element.css({ + paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '', + paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : '' + }) + } + + Modal.prototype.resetAdjustments = function () { + this.$element.css({ + paddingLeft: '', + paddingRight: '' + }) + } + + Modal.prototype.checkScrollbar = function () { + var fullWindowWidth = window.innerWidth + if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8 + var documentElementRect = document.documentElement.getBoundingClientRect() + fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left) + } + this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth + this.scrollbarWidth = this.measureScrollbar() + } + + Modal.prototype.setScrollbar = function () { + var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10) + this.originalBodyPad = document.body.style.paddingRight || '' + var scrollbarWidth = this.scrollbarWidth + if (this.bodyIsOverflowing) { + this.$body.css('padding-right', bodyPad + scrollbarWidth) + $(this.fixedContent).each(function (index, element) { + var actualPadding = element.style.paddingRight + var calculatedPadding = $(element).css('padding-right') + $(element) + .data('padding-right', actualPadding) + .css('padding-right', parseFloat(calculatedPadding) + scrollbarWidth + 'px') + }) + } + } + + Modal.prototype.resetScrollbar = function () { + this.$body.css('padding-right', this.originalBodyPad) + $(this.fixedContent).each(function (index, element) { + var padding = $(element).data('padding-right') + $(element).removeData('padding-right') + element.style.paddingRight = padding ? padding : '' + }) + } + + Modal.prototype.measureScrollbar = function () { // thx walsh + var scrollDiv = document.createElement('div') + scrollDiv.className = 'modal-scrollbar-measure' + this.$body.append(scrollDiv) + var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth + this.$body[0].removeChild(scrollDiv) + return scrollbarWidth + } + + + // MODAL PLUGIN DEFINITION + // ======================= + + function Plugin(option, _relatedTarget) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.modal') + var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option) + + if (!data) $this.data('bs.modal', (data = new Modal(this, options))) + if (typeof option == 'string') data[option](_relatedTarget) + else if (options.show) data.show(_relatedTarget) + }) + } + + var old = $.fn.modal + + $.fn.modal = Plugin + $.fn.modal.Constructor = Modal + + + // MODAL NO CONFLICT + // ================= + + $.fn.modal.noConflict = function () { + $.fn.modal = old + return this + } + + + // MODAL DATA-API + // ============== + + $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) { + var $this = $(this) + var href = $this.attr('href') + var target = $this.attr('data-target') || + (href && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7 + + var $target = $(document).find(target) + var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data()) + + if ($this.is('a')) e.preventDefault() + + $target.one('show.bs.modal', function (showEvent) { + if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown + $target.one('hidden.bs.modal', function () { + $this.is(':visible') && $this.trigger('focus') + }) + }) + Plugin.call($target, option, this) + }) + +}(jQuery); + +/* ======================================================================== + * Bootstrap: tooltip.js v3.4.1 + * https://getbootstrap.com/docs/3.4/javascript/#tooltip + * Inspired by the original jQuery.tipsy by Jason Frame + * ======================================================================== + * Copyright 2011-2019 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + ++function ($) { + 'use strict'; + + var DISALLOWED_ATTRIBUTES = ['sanitize', 'whiteList', 'sanitizeFn'] + + var uriAttrs = [ + 'background', + 'cite', + 'href', + 'itemtype', + 'longdesc', + 'poster', + 'src', + 'xlink:href' + ] + + var ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i + + var DefaultWhitelist = { + // Global attributes allowed on any supplied element below. + '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN], + a: ['target', 'href', 'title', 'rel'], + area: [], + b: [], + br: [], + col: [], + code: [], + div: [], + em: [], + hr: [], + h1: [], + h2: [], + h3: [], + h4: [], + h5: [], + h6: [], + i: [], + img: ['src', 'alt', 'title', 'width', 'height'], + li: [], + ol: [], + p: [], + pre: [], + s: [], + small: [], + span: [], + sub: [], + sup: [], + strong: [], + u: [], + ul: [] + } + + /** + * A pattern that recognizes a commonly useful subset of URLs that are safe. + * + * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts + */ + var SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^&:/?#]*(?:[/?#]|$))/gi + + /** + * A pattern that matches safe data URLs. Only matches image, video and audio types. + * + * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts + */ + var DATA_URL_PATTERN = /^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[a-z0-9+/]+=*$/i + + function allowedAttribute(attr, allowedAttributeList) { + var attrName = attr.nodeName.toLowerCase() + + if ($.inArray(attrName, allowedAttributeList) !== -1) { + if ($.inArray(attrName, uriAttrs) !== -1) { + return Boolean(attr.nodeValue.match(SAFE_URL_PATTERN) || attr.nodeValue.match(DATA_URL_PATTERN)) + } + + return true + } + + var regExp = $(allowedAttributeList).filter(function (index, value) { + return value instanceof RegExp + }) + + // Check if a regular expression validates the attribute. + for (var i = 0, l = regExp.length; i < l; i++) { + if (attrName.match(regExp[i])) { + return true + } + } + + return false + } + + function sanitizeHtml(unsafeHtml, whiteList, sanitizeFn) { + if (unsafeHtml.length === 0) { + return unsafeHtml + } + + if (sanitizeFn && typeof sanitizeFn === 'function') { + return sanitizeFn(unsafeHtml) + } + + // IE 8 and below don't support createHTMLDocument + if (!document.implementation || !document.implementation.createHTMLDocument) { + return unsafeHtml + } + + var createdDocument = document.implementation.createHTMLDocument('sanitization') + createdDocument.body.innerHTML = unsafeHtml + + var whitelistKeys = $.map(whiteList, function (el, i) { return i }) + var elements = $(createdDocument.body).find('*') + + for (var i = 0, len = elements.length; i < len; i++) { + var el = elements[i] + var elName = el.nodeName.toLowerCase() + + if ($.inArray(elName, whitelistKeys) === -1) { + el.parentNode.removeChild(el) + + continue + } + + var attributeList = $.map(el.attributes, function (el) { return el }) + var whitelistedAttributes = [].concat(whiteList['*'] || [], whiteList[elName] || []) + + for (var j = 0, len2 = attributeList.length; j < len2; j++) { + if (!allowedAttribute(attributeList[j], whitelistedAttributes)) { + el.removeAttribute(attributeList[j].nodeName) + } + } + } + + return createdDocument.body.innerHTML + } + + // TOOLTIP PUBLIC CLASS DEFINITION + // =============================== + + var Tooltip = function (element, options) { + this.type = null + this.options = null + this.enabled = null + this.timeout = null + this.hoverState = null + this.$element = null + this.inState = null + + this.init('tooltip', element, options) + } + + Tooltip.VERSION = '3.4.1' + + Tooltip.TRANSITION_DURATION = 150 + + Tooltip.DEFAULTS = { + animation: true, + placement: 'top', + selector: false, + template: '', + trigger: 'hover focus', + title: '', + delay: 0, + html: false, + container: false, + viewport: { + selector: 'body', + padding: 0 + }, + sanitize : true, + sanitizeFn : null, + whiteList : DefaultWhitelist + } + + Tooltip.prototype.init = function (type, element, options) { + this.enabled = true + this.type = type + this.$element = $(element) + this.options = this.getOptions(options) + this.$viewport = this.options.viewport && $(document).find($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport)) + this.inState = { click: false, hover: false, focus: false } + + if (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!') + } + + var triggers = this.options.trigger.split(' ') + + for (var i = triggers.length; i--;) { + var trigger = triggers[i] + + if (trigger == 'click') { + this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this)) + } else if (trigger != 'manual') { + var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin' + var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout' + + this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this)) + this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this)) + } + } + + this.options.selector ? + (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) : + this.fixTitle() + } + + Tooltip.prototype.getDefaults = function () { + return Tooltip.DEFAULTS + } + + Tooltip.prototype.getOptions = function (options) { + var dataAttributes = this.$element.data() + + for (var dataAttr in dataAttributes) { + if (dataAttributes.hasOwnProperty(dataAttr) && $.inArray(dataAttr, DISALLOWED_ATTRIBUTES) !== -1) { + delete dataAttributes[dataAttr] + } + } + + options = $.extend({}, this.getDefaults(), dataAttributes, options) + + if (options.delay && typeof options.delay == 'number') { + options.delay = { + show: options.delay, + hide: options.delay + } + } + + if (options.sanitize) { + options.template = sanitizeHtml(options.template, options.whiteList, options.sanitizeFn) + } + + return options + } + + Tooltip.prototype.getDelegateOptions = function () { + var options = {} + var defaults = this.getDefaults() + + this._options && $.each(this._options, function (key, value) { + if (defaults[key] != value) options[key] = value + }) + + return options + } + + Tooltip.prototype.enter = function (obj) { + var self = obj instanceof this.constructor ? + obj : $(obj.currentTarget).data('bs.' + this.type) + + if (!self) { + self = new this.constructor(obj.currentTarget, this.getDelegateOptions()) + $(obj.currentTarget).data('bs.' + this.type, self) + } + + if (obj instanceof $.Event) { + self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true + } + + if (self.tip().hasClass('in') || self.hoverState == 'in') { + self.hoverState = 'in' + return + } + + clearTimeout(self.timeout) + + self.hoverState = 'in' + + if (!self.options.delay || !self.options.delay.show) return self.show() + + self.timeout = setTimeout(function () { + if (self.hoverState == 'in') self.show() + }, self.options.delay.show) + } + + Tooltip.prototype.isInStateTrue = function () { + for (var key in this.inState) { + if (this.inState[key]) return true + } + + return false + } + + Tooltip.prototype.leave = function (obj) { + var self = obj instanceof this.constructor ? + obj : $(obj.currentTarget).data('bs.' + this.type) + + if (!self) { + self = new this.constructor(obj.currentTarget, this.getDelegateOptions()) + $(obj.currentTarget).data('bs.' + this.type, self) + } + + if (obj instanceof $.Event) { + self.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false + } + + if (self.isInStateTrue()) return + + clearTimeout(self.timeout) + + self.hoverState = 'out' + + if (!self.options.delay || !self.options.delay.hide) return self.hide() + + self.timeout = setTimeout(function () { + if (self.hoverState == 'out') self.hide() + }, self.options.delay.hide) + } + + Tooltip.prototype.show = function () { + var e = $.Event('show.bs.' + this.type) + + if (this.hasContent() && this.enabled) { + this.$element.trigger(e) + + var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0]) + if (e.isDefaultPrevented() || !inDom) return + var that = this + + var $tip = this.tip() + + var tipId = this.getUID(this.type) + + this.setContent() + $tip.attr('id', tipId) + this.$element.attr('aria-describedby', tipId) + + if (this.options.animation) $tip.addClass('fade') + + var placement = typeof this.options.placement == 'function' ? + this.options.placement.call(this, $tip[0], this.$element[0]) : + this.options.placement + + var autoToken = /\s?auto?\s?/i + var autoPlace = autoToken.test(placement) + if (autoPlace) placement = placement.replace(autoToken, '') || 'top' + + $tip + .detach() + .css({ top: 0, left: 0, display: 'block' }) + .addClass(placement) + .data('bs.' + this.type, this) + + this.options.container ? $tip.appendTo($(document).find(this.options.container)) : $tip.insertAfter(this.$element) + this.$element.trigger('inserted.bs.' + this.type) + + var pos = this.getPosition() + var actualWidth = $tip[0].offsetWidth + var actualHeight = $tip[0].offsetHeight + + if (autoPlace) { + var orgPlacement = placement + var viewportDim = this.getPosition(this.$viewport) + + placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top' : + placement == 'top' && pos.top - actualHeight < viewportDim.top ? 'bottom' : + placement == 'right' && pos.right + actualWidth > viewportDim.width ? 'left' : + placement == 'left' && pos.left - actualWidth < viewportDim.left ? 'right' : + placement + + $tip + .removeClass(orgPlacement) + .addClass(placement) + } + + var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight) + + this.applyPlacement(calculatedOffset, placement) + + var complete = function () { + var prevHoverState = that.hoverState + that.$element.trigger('shown.bs.' + that.type) + that.hoverState = null + + if (prevHoverState == 'out') that.leave(that) + } + + $.support.transition && this.$tip.hasClass('fade') ? + $tip + .one('bsTransitionEnd', complete) + .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : + complete() + } + } + + Tooltip.prototype.applyPlacement = function (offset, placement) { + var $tip = this.tip() + var width = $tip[0].offsetWidth + var height = $tip[0].offsetHeight + + // manually read margins because getBoundingClientRect includes difference + var marginTop = parseInt($tip.css('margin-top'), 10) + var marginLeft = parseInt($tip.css('margin-left'), 10) + + // we must check for NaN for ie 8/9 + if (isNaN(marginTop)) marginTop = 0 + if (isNaN(marginLeft)) marginLeft = 0 + + offset.top += marginTop + offset.left += marginLeft + + // $.fn.offset doesn't round pixel values + // so we use setOffset directly with our own function B-0 + $.offset.setOffset($tip[0], $.extend({ + using: function (props) { + $tip.css({ + top: Math.round(props.top), + left: Math.round(props.left) + }) + } + }, offset), 0) + + $tip.addClass('in') + + // check to see if placing tip in new offset caused the tip to resize itself + var actualWidth = $tip[0].offsetWidth + var actualHeight = $tip[0].offsetHeight + + if (placement == 'top' && actualHeight != height) { + offset.top = offset.top + height - actualHeight + } + + var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight) + + if (delta.left) offset.left += delta.left + else offset.top += delta.top + + var isVertical = /top|bottom/.test(placement) + var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight + var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight' + + $tip.offset(offset) + this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical) + } + + Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) { + this.arrow() + .css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%') + .css(isVertical ? 'top' : 'left', '') + } + + Tooltip.prototype.setContent = function () { + var $tip = this.tip() + var title = this.getTitle() + + if (this.options.html) { + if (this.options.sanitize) { + title = sanitizeHtml(title, this.options.whiteList, this.options.sanitizeFn) + } + + $tip.find('.tooltip-inner').html(title) + } else { + $tip.find('.tooltip-inner').text(title) + } + + $tip.removeClass('fade in top bottom left right') + } + + Tooltip.prototype.hide = function (callback) { + var that = this + var $tip = $(this.$tip) + var e = $.Event('hide.bs.' + this.type) + + function complete() { + if (that.hoverState != 'in') $tip.detach() + if (that.$element) { // TODO: Check whether guarding this code with this `if` is really necessary. + that.$element + .removeAttr('aria-describedby') + .trigger('hidden.bs.' + that.type) + } + callback && callback() + } + + this.$element.trigger(e) + + if (e.isDefaultPrevented()) return + + $tip.removeClass('in') + + $.support.transition && $tip.hasClass('fade') ? + $tip + .one('bsTransitionEnd', complete) + .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : + complete() + + this.hoverState = null + + return this + } + + Tooltip.prototype.fixTitle = function () { + var $e = this.$element + if ($e.attr('title') || typeof $e.attr('data-original-title') != 'string') { + $e.attr('data-original-title', $e.attr('title') || '').attr('title', '') + } + } + + Tooltip.prototype.hasContent = function () { + return this.getTitle() + } + + Tooltip.prototype.getPosition = function ($element) { + $element = $element || this.$element + + var el = $element[0] + var isBody = el.tagName == 'BODY' + + var elRect = el.getBoundingClientRect() + if (elRect.width == null) { + // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093 + elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top }) + } + var isSvg = window.SVGElement && el instanceof window.SVGElement + // Avoid using $.offset() on SVGs since it gives incorrect results in jQuery 3. + // See https://github.com/twbs/bootstrap/issues/20280 + var elOffset = isBody ? { top: 0, left: 0 } : (isSvg ? null : $element.offset()) + var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() } + var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null + + return $.extend({}, elRect, scroll, outerDims, elOffset) + } + + Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) { + return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } : + placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } : + placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } : + /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width } + + } + + Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) { + var delta = { top: 0, left: 0 } + if (!this.$viewport) return delta + + var viewportPadding = this.options.viewport && this.options.viewport.padding || 0 + var viewportDimensions = this.getPosition(this.$viewport) + + if (/right|left/.test(placement)) { + var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll + var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight + if (topEdgeOffset < viewportDimensions.top) { // top overflow + delta.top = viewportDimensions.top - topEdgeOffset + } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow + delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset + } + } else { + var leftEdgeOffset = pos.left - viewportPadding + var rightEdgeOffset = pos.left + viewportPadding + actualWidth + if (leftEdgeOffset < viewportDimensions.left) { // left overflow + delta.left = viewportDimensions.left - leftEdgeOffset + } else if (rightEdgeOffset > viewportDimensions.right) { // right overflow + delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset + } + } + + return delta + } + + Tooltip.prototype.getTitle = function () { + var title + var $e = this.$element + var o = this.options + + title = $e.attr('data-original-title') + || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title) + + return title + } + + Tooltip.prototype.getUID = function (prefix) { + do prefix += ~~(Math.random() * 1000000) + while (document.getElementById(prefix)) + return prefix + } + + Tooltip.prototype.tip = function () { + if (!this.$tip) { + this.$tip = $(this.options.template) + if (this.$tip.length != 1) { + throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!') + } + } + return this.$tip + } + + Tooltip.prototype.arrow = function () { + return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')) + } + + Tooltip.prototype.enable = function () { + this.enabled = true + } + + Tooltip.prototype.disable = function () { + this.enabled = false + } + + Tooltip.prototype.toggleEnabled = function () { + this.enabled = !this.enabled + } + + Tooltip.prototype.toggle = function (e) { + var self = this + if (e) { + self = $(e.currentTarget).data('bs.' + this.type) + if (!self) { + self = new this.constructor(e.currentTarget, this.getDelegateOptions()) + $(e.currentTarget).data('bs.' + this.type, self) + } + } + + if (e) { + self.inState.click = !self.inState.click + if (self.isInStateTrue()) self.enter(self) + else self.leave(self) + } else { + self.tip().hasClass('in') ? self.leave(self) : self.enter(self) + } + } + + Tooltip.prototype.destroy = function () { + var that = this + clearTimeout(this.timeout) + this.hide(function () { + that.$element.off('.' + that.type).removeData('bs.' + that.type) + if (that.$tip) { + that.$tip.detach() + } + that.$tip = null + that.$arrow = null + that.$viewport = null + that.$element = null + }) + } + + Tooltip.prototype.sanitizeHtml = function (unsafeHtml) { + return sanitizeHtml(unsafeHtml, this.options.whiteList, this.options.sanitizeFn) + } + + // TOOLTIP PLUGIN DEFINITION + // ========================= + + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.tooltip') + var options = typeof option == 'object' && option + + if (!data && /destroy|hide/.test(option)) return + if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options))) + if (typeof option == 'string') data[option]() + }) + } + + var old = $.fn.tooltip + + $.fn.tooltip = Plugin + $.fn.tooltip.Constructor = Tooltip + + + // TOOLTIP NO CONFLICT + // =================== + + $.fn.tooltip.noConflict = function () { + $.fn.tooltip = old + return this + } + +}(jQuery); + +/* ======================================================================== + * Bootstrap: popover.js v3.4.1 + * https://getbootstrap.com/docs/3.4/javascript/#popovers + * ======================================================================== + * Copyright 2011-2019 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // POPOVER PUBLIC CLASS DEFINITION + // =============================== + + var Popover = function (element, options) { + this.init('popover', element, options) + } + + if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js') + + Popover.VERSION = '3.4.1' + + Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, { + placement: 'right', + trigger: 'click', + content: '', + template: '' + }) + + + // NOTE: POPOVER EXTENDS tooltip.js + // ================================ + + Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype) + + Popover.prototype.constructor = Popover + + Popover.prototype.getDefaults = function () { + return Popover.DEFAULTS + } + + Popover.prototype.setContent = function () { + var $tip = this.tip() + var title = this.getTitle() + var content = this.getContent() + + if (this.options.html) { + var typeContent = typeof content + + if (this.options.sanitize) { + title = this.sanitizeHtml(title) + + if (typeContent === 'string') { + content = this.sanitizeHtml(content) + } + } + + $tip.find('.popover-title').html(title) + $tip.find('.popover-content').children().detach().end()[ + typeContent === 'string' ? 'html' : 'append' + ](content) + } else { + $tip.find('.popover-title').text(title) + $tip.find('.popover-content').children().detach().end().text(content) + } + + $tip.removeClass('fade top bottom left right in') + + // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do + // this manually by checking the contents. + if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide() + } + + Popover.prototype.hasContent = function () { + return this.getTitle() || this.getContent() + } + + Popover.prototype.getContent = function () { + var $e = this.$element + var o = this.options + + return $e.attr('data-content') + || (typeof o.content == 'function' ? + o.content.call($e[0]) : + o.content) + } + + Popover.prototype.arrow = function () { + return (this.$arrow = this.$arrow || this.tip().find('.arrow')) + } + + + // POPOVER PLUGIN DEFINITION + // ========================= + + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.popover') + var options = typeof option == 'object' && option + + if (!data && /destroy|hide/.test(option)) return + if (!data) $this.data('bs.popover', (data = new Popover(this, options))) + if (typeof option == 'string') data[option]() + }) + } + + var old = $.fn.popover + + $.fn.popover = Plugin + $.fn.popover.Constructor = Popover + + + // POPOVER NO CONFLICT + // =================== + + $.fn.popover.noConflict = function () { + $.fn.popover = old + return this + } + +}(jQuery); + +/* ======================================================================== + * Bootstrap: scrollspy.js v3.4.1 + * https://getbootstrap.com/docs/3.4/javascript/#scrollspy + * ======================================================================== + * Copyright 2011-2019 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // SCROLLSPY CLASS DEFINITION + // ========================== + + function ScrollSpy(element, options) { + this.$body = $(document.body) + this.$scrollElement = $(element).is(document.body) ? $(window) : $(element) + this.options = $.extend({}, ScrollSpy.DEFAULTS, options) + this.selector = (this.options.target || '') + ' .nav li > a' + this.offsets = [] + this.targets = [] + this.activeTarget = null + this.scrollHeight = 0 + + this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this)) + this.refresh() + this.process() + } + + ScrollSpy.VERSION = '3.4.1' + + ScrollSpy.DEFAULTS = { + offset: 10 + } + + ScrollSpy.prototype.getScrollHeight = function () { + return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight) + } + + ScrollSpy.prototype.refresh = function () { + var that = this + var offsetMethod = 'offset' + var offsetBase = 0 + + this.offsets = [] + this.targets = [] + this.scrollHeight = this.getScrollHeight() + + if (!$.isWindow(this.$scrollElement[0])) { + offsetMethod = 'position' + offsetBase = this.$scrollElement.scrollTop() + } + + this.$body + .find(this.selector) + .map(function () { + var $el = $(this) + var href = $el.data('target') || $el.attr('href') + var $href = /^#./.test(href) && $(href) + + return ($href + && $href.length + && $href.is(':visible') + && [[$href[offsetMethod]().top + offsetBase, href]]) || null + }) + .sort(function (a, b) { return a[0] - b[0] }) + .each(function () { + that.offsets.push(this[0]) + that.targets.push(this[1]) + }) + } + + ScrollSpy.prototype.process = function () { + var scrollTop = this.$scrollElement.scrollTop() + this.options.offset + var scrollHeight = this.getScrollHeight() + var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height() + var offsets = this.offsets + var targets = this.targets + var activeTarget = this.activeTarget + var i + + if (this.scrollHeight != scrollHeight) { + this.refresh() + } + + if (scrollTop >= maxScroll) { + return activeTarget != (i = targets[targets.length - 1]) && this.activate(i) + } + + if (activeTarget && scrollTop < offsets[0]) { + this.activeTarget = null + return this.clear() + } + + for (i = offsets.length; i--;) { + activeTarget != targets[i] + && scrollTop >= offsets[i] + && (offsets[i + 1] === undefined || scrollTop < offsets[i + 1]) + && this.activate(targets[i]) + } + } + + ScrollSpy.prototype.activate = function (target) { + this.activeTarget = target + + this.clear() + + var selector = this.selector + + '[data-target="' + target + '"],' + + this.selector + '[href="' + target + '"]' + + var active = $(selector) + .parents('li') + .addClass('active') + + if (active.parent('.dropdown-menu').length) { + active = active + .closest('li.dropdown') + .addClass('active') + } + + active.trigger('activate.bs.scrollspy') + } + + ScrollSpy.prototype.clear = function () { + $(this.selector) + .parentsUntil(this.options.target, '.active') + .removeClass('active') + } + + + // SCROLLSPY PLUGIN DEFINITION + // =========================== + + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.scrollspy') + var options = typeof option == 'object' && option + + if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options))) + if (typeof option == 'string') data[option]() + }) + } + + var old = $.fn.scrollspy + + $.fn.scrollspy = Plugin + $.fn.scrollspy.Constructor = ScrollSpy + + + // SCROLLSPY NO CONFLICT + // ===================== + + $.fn.scrollspy.noConflict = function () { + $.fn.scrollspy = old + return this + } + + + // SCROLLSPY DATA-API + // ================== + + $(window).on('load.bs.scrollspy.data-api', function () { + $('[data-spy="scroll"]').each(function () { + var $spy = $(this) + Plugin.call($spy, $spy.data()) + }) + }) + +}(jQuery); + +/* ======================================================================== + * Bootstrap: tab.js v3.4.1 + * https://getbootstrap.com/docs/3.4/javascript/#tabs + * ======================================================================== + * Copyright 2011-2019 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // TAB CLASS DEFINITION + // ==================== + + var Tab = function (element) { + // jscs:disable requireDollarBeforejQueryAssignment + this.element = $(element) + // jscs:enable requireDollarBeforejQueryAssignment + } + + Tab.VERSION = '3.4.1' + + Tab.TRANSITION_DURATION = 150 + + Tab.prototype.show = function () { + var $this = this.element + var $ul = $this.closest('ul:not(.dropdown-menu)') + var selector = $this.data('target') + + if (!selector) { + selector = $this.attr('href') + selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 + } + + if ($this.parent('li').hasClass('active')) return + + var $previous = $ul.find('.active:last a') + var hideEvent = $.Event('hide.bs.tab', { + relatedTarget: $this[0] + }) + var showEvent = $.Event('show.bs.tab', { + relatedTarget: $previous[0] + }) + + $previous.trigger(hideEvent) + $this.trigger(showEvent) + + if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return + + var $target = $(document).find(selector) + + this.activate($this.closest('li'), $ul) + this.activate($target, $target.parent(), function () { + $previous.trigger({ + type: 'hidden.bs.tab', + relatedTarget: $this[0] + }) + $this.trigger({ + type: 'shown.bs.tab', + relatedTarget: $previous[0] + }) + }) + } + + Tab.prototype.activate = function (element, container, callback) { + var $active = container.find('> .active') + var transition = callback + && $.support.transition + && ($active.length && $active.hasClass('fade') || !!container.find('> .fade').length) + + function next() { + $active + .removeClass('active') + .find('> .dropdown-menu > .active') + .removeClass('active') + .end() + .find('[data-toggle="tab"]') + .attr('aria-expanded', false) + + element + .addClass('active') + .find('[data-toggle="tab"]') + .attr('aria-expanded', true) + + if (transition) { + element[0].offsetWidth // reflow for transition + element.addClass('in') + } else { + element.removeClass('fade') + } + + if (element.parent('.dropdown-menu').length) { + element + .closest('li.dropdown') + .addClass('active') + .end() + .find('[data-toggle="tab"]') + .attr('aria-expanded', true) + } + + callback && callback() + } + + $active.length && transition ? + $active + .one('bsTransitionEnd', next) + .emulateTransitionEnd(Tab.TRANSITION_DURATION) : + next() + + $active.removeClass('in') + } + + + // TAB PLUGIN DEFINITION + // ===================== + + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.tab') + + if (!data) $this.data('bs.tab', (data = new Tab(this))) + if (typeof option == 'string') data[option]() + }) + } + + var old = $.fn.tab + + $.fn.tab = Plugin + $.fn.tab.Constructor = Tab + + + // TAB NO CONFLICT + // =============== + + $.fn.tab.noConflict = function () { + $.fn.tab = old + return this + } + + + // TAB DATA-API + // ============ + + var clickHandler = function (e) { + e.preventDefault() + Plugin.call($(this), 'show') + } + + $(document) + .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler) + .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler) + +}(jQuery); + +/* ======================================================================== + * Bootstrap: affix.js v3.4.1 + * https://getbootstrap.com/docs/3.4/javascript/#affix + * ======================================================================== + * Copyright 2011-2019 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // AFFIX CLASS DEFINITION + // ====================== + + var Affix = function (element, options) { + this.options = $.extend({}, Affix.DEFAULTS, options) + + var target = this.options.target === Affix.DEFAULTS.target ? $(this.options.target) : $(document).find(this.options.target) + + this.$target = target + .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this)) + .on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this)) + + this.$element = $(element) + this.affixed = null + this.unpin = null + this.pinnedOffset = null + + this.checkPosition() + } + + Affix.VERSION = '3.4.1' + + Affix.RESET = 'affix affix-top affix-bottom' + + Affix.DEFAULTS = { + offset: 0, + target: window + } + + Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) { + var scrollTop = this.$target.scrollTop() + var position = this.$element.offset() + var targetHeight = this.$target.height() + + if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false + + if (this.affixed == 'bottom') { + if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom' + return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom' + } + + var initializing = this.affixed == null + var colliderTop = initializing ? scrollTop : position.top + var colliderHeight = initializing ? targetHeight : height + + if (offsetTop != null && scrollTop <= offsetTop) return 'top' + if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom' + + return false + } + + Affix.prototype.getPinnedOffset = function () { + if (this.pinnedOffset) return this.pinnedOffset + this.$element.removeClass(Affix.RESET).addClass('affix') + var scrollTop = this.$target.scrollTop() + var position = this.$element.offset() + return (this.pinnedOffset = position.top - scrollTop) + } + + Affix.prototype.checkPositionWithEventLoop = function () { + setTimeout($.proxy(this.checkPosition, this), 1) + } + + Affix.prototype.checkPosition = function () { + if (!this.$element.is(':visible')) return + + var height = this.$element.height() + var offset = this.options.offset + var offsetTop = offset.top + var offsetBottom = offset.bottom + var scrollHeight = Math.max($(document).height(), $(document.body).height()) + + if (typeof offset != 'object') offsetBottom = offsetTop = offset + if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element) + if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element) + + var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom) + + if (this.affixed != affix) { + if (this.unpin != null) this.$element.css('top', '') + + var affixType = 'affix' + (affix ? '-' + affix : '') + var e = $.Event(affixType + '.bs.affix') + + this.$element.trigger(e) + + if (e.isDefaultPrevented()) return + + this.affixed = affix + this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null + + this.$element + .removeClass(Affix.RESET) + .addClass(affixType) + .trigger(affixType.replace('affix', 'affixed') + '.bs.affix') + } + + if (affix == 'bottom') { + this.$element.offset({ + top: scrollHeight - height - offsetBottom + }) + } + } + + + // AFFIX PLUGIN DEFINITION + // ======================= + + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.affix') + var options = typeof option == 'object' && option + + if (!data) $this.data('bs.affix', (data = new Affix(this, options))) + if (typeof option == 'string') data[option]() + }) + } + + var old = $.fn.affix + + $.fn.affix = Plugin + $.fn.affix.Constructor = Affix + + + // AFFIX NO CONFLICT + // ================= + + $.fn.affix.noConflict = function () { + $.fn.affix = old + return this + } + + + // AFFIX DATA-API + // ============== + + $(window).on('load', function () { + $('[data-spy="affix"]').each(function () { + var $spy = $(this) + var data = $spy.data() + + data.offset = data.offset || {} + + if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom + if (data.offsetTop != null) data.offset.top = data.offsetTop + + Plugin.call($spy, data) + }) + }) + +}(jQuery); diff --git a/intelmq/web/static/plugins/bootstrap/bootstrap.min.css b/intelmq/web/static/plugins/bootstrap/bootstrap.min.css new file mode 100644 index 000000000..5b96335ff --- /dev/null +++ b/intelmq/web/static/plugins/bootstrap/bootstrap.min.css @@ -0,0 +1,6 @@ +/*! + * Bootstrap v3.4.1 (https://getbootstrap.com/) + * Copyright 2011-2019 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;-ms-text-size-adjust:100%;-webkit-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:none;text-decoration:underline;-webkit-text-decoration:underline dotted;-moz-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}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{border:0;padding: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-appearance:textfield;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}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^="#"]:after,a[href^="javascript:"]: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{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;display:inline-block;max-width:100%;height:auto}.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;list-style:none;margin-left:-5px}.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;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[data-original-title],abbr[title]{cursor:help}.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}.row-no-gutters{margin-right:0;margin-left:0}.row-no-gutters [class*=col-]{padding-right:0;padding-left:0}.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}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}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>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;-webkit-appearance:none;-moz-appearance:none;appearance:none}input[type=checkbox],input[type=radio]{margin:4px 0 0;margin-top:1px\9;line-height:normal}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}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=checkbox]:focus,input[type=file]: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,box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;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,-webkit-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}@media screen and (-webkit-min-device-pixel-ratio:0){input[type=date].form-control,input[type=datetime-local].form-control,input[type=month].form-control,input[type=time].form-control{line-height:34px}.input-group-sm input[type=date],.input-group-sm input[type=datetime-local],.input-group-sm input[type=month],.input-group-sm input[type=time],input[type=date].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm,input[type=time].input-sm{line-height:30px}.input-group-lg input[type=date],.input-group-lg input[type=datetime-local],.input-group-lg input[type=month],.input-group-lg input[type=time],input[type=date].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg,input[type=time].input-lg{line-height:46px}}.form-group{margin-bottom:15px}.checkbox,.radio{position:relative;display:block;margin-top:10px;margin-bottom:10px}.checkbox.disabled label,.radio.disabled label,fieldset[disabled] .checkbox label,fieldset[disabled] .radio label{cursor:not-allowed}.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.disabled,.radio-inline.disabled,fieldset[disabled] .checkbox-inline,fieldset[disabled] .radio-inline{cursor:not-allowed}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px}.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;margin-bottom:0;font-weight:400;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;background-image:none;border:1px solid transparent;padding:6px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.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);opacity:.65;-webkit-box-shadow:none;box-shadow:none}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;background-image:none;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.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;background-image:none;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.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;background-image:none;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.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;background-image:none;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.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;background-image:none;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.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;background-image:none;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.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-property:height,visibility;-o-transition-property:height,visibility;transition-property:height,visibility;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease}.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;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;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);-webkit-overflow-scrolling:touch}.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-fixed-top{position:fixed;right:0;left:0;z-index:1030}.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}}@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}.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-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-right:15px;margin-top:8px;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-right:-15px;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);margin-top:8px;margin-bottom:8px}@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-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-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-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-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-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-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>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>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>.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}.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}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-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{padding:0;cursor:pointer;background:0 0;border:0;-webkit-appearance:none;-moz-appearance:none;appearance:none}.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-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%);-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:-webkit-transform .3s ease-out;transition:transform .3s ease-out;transition:transform .3s ease-out,-webkit-transform .3s ease-out,-o-transform .3s ease-out}.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;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5);outline:0}.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-style:normal;font-weight:400;line-height:1.42857143;line-break:auto;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;font-size:12px;filter:alpha(opacity=0);opacity:0}.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.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}.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}.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-style:normal;font-weight:400;line-height:1.42857143;line-break:auto;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;font-size:14px;background-color:#fff;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)}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover>.arrow{border-width:11px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.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}.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}.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:-webkit-transform .6s ease-in-out;transition:transform .6s ease-in-out;transition:transform .6s ease-in-out,-webkit-transform .6s ease-in-out,-o-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{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0);left:0}.carousel-inner>.item.active.left,.carousel-inner>.item.prev{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0);left:0}.carousel-inner>.item.active,.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);left: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;outline:0;filter:alpha(opacity=90);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/intelmq/web/static/plugins/bootstrap/bootstrap.min.js b/intelmq/web/static/plugins/bootstrap/bootstrap.min.js new file mode 100644 index 000000000..eb0a8b410 --- /dev/null +++ b/intelmq/web/static/plugins/bootstrap/bootstrap.min.js @@ -0,0 +1,6 @@ +/*! + * Bootstrap v3.4.1 (https://getbootstrap.com/) + * Copyright 2011-2019 Twitter, Inc. + * Licensed under the MIT license + */ +if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");!function(t){"use strict";var e=jQuery.fn.jquery.split(" ")[0].split(".");if(e[0]<2&&e[1]<9||1==e[0]&&9==e[1]&&e[2]<1||3this.$items.length-1||t<0))return this.sliding?this.$element.one("slid.bs.carousel",function(){e.to(t)}):i==t?this.pause().cycle():this.slide(idocument.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&t?this.scrollbarWidth:"",paddingRight:this.bodyIsOverflowing&&!t?this.scrollbarWidth:""})},s.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:"",paddingRight:""})},s.prototype.checkScrollbar=function(){var t=window.innerWidth;if(!t){var e=document.documentElement.getBoundingClientRect();t=e.right-Math.abs(e.left)}this.bodyIsOverflowing=document.body.clientWidth
    ',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0},sanitize:!0,sanitizeFn:null,whiteList:t},m.prototype.init=function(t,e,i){if(this.enabled=!0,this.type=t,this.$element=g(e),this.options=this.getOptions(i),this.$viewport=this.options.viewport&&g(document).find(g.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 o=this.options.trigger.split(" "),n=o.length;n--;){var s=o[n];if("click"==s)this.$element.on("click."+this.type,this.options.selector,g.proxy(this.toggle,this));else if("manual"!=s){var a="hover"==s?"mouseenter":"focusin",r="hover"==s?"mouseleave":"focusout";this.$element.on(a+"."+this.type,this.options.selector,g.proxy(this.enter,this)),this.$element.on(r+"."+this.type,this.options.selector,g.proxy(this.leave,this))}}this.options.selector?this._options=g.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},m.prototype.getDefaults=function(){return m.DEFAULTS},m.prototype.getOptions=function(t){var e=this.$element.data();for(var i in e)e.hasOwnProperty(i)&&-1!==g.inArray(i,o)&&delete e[i];return(t=g.extend({},this.getDefaults(),e,t)).delay&&"number"==typeof t.delay&&(t.delay={show:t.delay,hide:t.delay}),t.sanitize&&(t.template=n(t.template,t.whiteList,t.sanitizeFn)),t},m.prototype.getDelegateOptions=function(){var i={},o=this.getDefaults();return this._options&&g.each(this._options,function(t,e){o[t]!=e&&(i[t]=e)}),i},m.prototype.enter=function(t){var e=t instanceof this.constructor?t:g(t.currentTarget).data("bs."+this.type);if(e||(e=new this.constructor(t.currentTarget,this.getDelegateOptions()),g(t.currentTarget).data("bs."+this.type,e)),t instanceof g.Event&&(e.inState["focusin"==t.type?"focus":"hover"]=!0),e.tip().hasClass("in")||"in"==e.hoverState)e.hoverState="in";else{if(clearTimeout(e.timeout),e.hoverState="in",!e.options.delay||!e.options.delay.show)return e.show();e.timeout=setTimeout(function(){"in"==e.hoverState&&e.show()},e.options.delay.show)}},m.prototype.isInStateTrue=function(){for(var t in this.inState)if(this.inState[t])return!0;return!1},m.prototype.leave=function(t){var e=t instanceof this.constructor?t:g(t.currentTarget).data("bs."+this.type);if(e||(e=new this.constructor(t.currentTarget,this.getDelegateOptions()),g(t.currentTarget).data("bs."+this.type,e)),t instanceof g.Event&&(e.inState["focusout"==t.type?"focus":"hover"]=!1),!e.isInStateTrue()){if(clearTimeout(e.timeout),e.hoverState="out",!e.options.delay||!e.options.delay.hide)return e.hide();e.timeout=setTimeout(function(){"out"==e.hoverState&&e.hide()},e.options.delay.hide)}},m.prototype.show=function(){var t=g.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(t);var e=g.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(t.isDefaultPrevented()||!e)return;var i=this,o=this.tip(),n=this.getUID(this.type);this.setContent(),o.attr("id",n),this.$element.attr("aria-describedby",n),this.options.animation&&o.addClass("fade");var s="function"==typeof this.options.placement?this.options.placement.call(this,o[0],this.$element[0]):this.options.placement,a=/\s?auto?\s?/i,r=a.test(s);r&&(s=s.replace(a,"")||"top"),o.detach().css({top:0,left:0,display:"block"}).addClass(s).data("bs."+this.type,this),this.options.container?o.appendTo(g(document).find(this.options.container)):o.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var l=this.getPosition(),h=o[0].offsetWidth,d=o[0].offsetHeight;if(r){var p=s,c=this.getPosition(this.$viewport);s="bottom"==s&&l.bottom+d>c.bottom?"top":"top"==s&&l.top-dc.width?"left":"left"==s&&l.left-ha.top+a.height&&(n.top=a.top+a.height-l)}else{var h=e.left-s,d=e.left+s+i;ha.right&&(n.left=a.left+a.width-d)}return n},m.prototype.getTitle=function(){var t=this.$element,e=this.options;return t.attr("data-original-title")||("function"==typeof e.title?e.title.call(t[0]):e.title)},m.prototype.getUID=function(t){for(;t+=~~(1e6*Math.random()),document.getElementById(t););return t},m.prototype.tip=function(){if(!this.$tip&&(this.$tip=g(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},m.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},m.prototype.enable=function(){this.enabled=!0},m.prototype.disable=function(){this.enabled=!1},m.prototype.toggleEnabled=function(){this.enabled=!this.enabled},m.prototype.toggle=function(t){var e=this;t&&((e=g(t.currentTarget).data("bs."+this.type))||(e=new this.constructor(t.currentTarget,this.getDelegateOptions()),g(t.currentTarget).data("bs."+this.type,e))),t?(e.inState.click=!e.inState.click,e.isInStateTrue()?e.enter(e):e.leave(e)):e.tip().hasClass("in")?e.leave(e):e.enter(e)},m.prototype.destroy=function(){var t=this;clearTimeout(this.timeout),this.hide(function(){t.$element.off("."+t.type).removeData("bs."+t.type),t.$tip&&t.$tip.detach(),t.$tip=null,t.$arrow=null,t.$viewport=null,t.$element=null})},m.prototype.sanitizeHtml=function(t){return n(t,this.options.whiteList,this.options.sanitizeFn)};var e=g.fn.tooltip;g.fn.tooltip=function i(o){return this.each(function(){var t=g(this),e=t.data("bs.tooltip"),i="object"==typeof o&&o;!e&&/destroy|hide/.test(o)||(e||t.data("bs.tooltip",e=new m(this,i)),"string"==typeof o&&e[o]())})},g.fn.tooltip.Constructor=m,g.fn.tooltip.noConflict=function(){return g.fn.tooltip=e,this}}(jQuery),function(n){"use strict";var s=function(t,e){this.init("popover",t,e)};if(!n.fn.tooltip)throw new Error("Popover requires tooltip.js");s.VERSION="3.4.1",s.DEFAULTS=n.extend({},n.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:''}),((s.prototype=n.extend({},n.fn.tooltip.Constructor.prototype)).constructor=s).prototype.getDefaults=function(){return s.DEFAULTS},s.prototype.setContent=function(){var t=this.tip(),e=this.getTitle(),i=this.getContent();if(this.options.html){var o=typeof i;this.options.sanitize&&(e=this.sanitizeHtml(e),"string"===o&&(i=this.sanitizeHtml(i))),t.find(".popover-title").html(e),t.find(".popover-content").children().detach().end()["string"===o?"html":"append"](i)}else t.find(".popover-title").text(e),t.find(".popover-content").children().detach().end().text(i);t.removeClass("fade top bottom left right in"),t.find(".popover-title").html()||t.find(".popover-title").hide()},s.prototype.hasContent=function(){return this.getTitle()||this.getContent()},s.prototype.getContent=function(){var t=this.$element,e=this.options;return t.attr("data-content")||("function"==typeof e.content?e.content.call(t[0]):e.content)},s.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var t=n.fn.popover;n.fn.popover=function e(o){return this.each(function(){var t=n(this),e=t.data("bs.popover"),i="object"==typeof o&&o;!e&&/destroy|hide/.test(o)||(e||t.data("bs.popover",e=new s(this,i)),"string"==typeof o&&e[o]())})},n.fn.popover.Constructor=s,n.fn.popover.noConflict=function(){return n.fn.popover=t,this}}(jQuery),function(s){"use strict";function n(t,e){this.$body=s(document.body),this.$scrollElement=s(t).is(document.body)?s(window):s(t),this.options=s.extend({},n.DEFAULTS,e),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",s.proxy(this.process,this)),this.refresh(),this.process()}function e(o){return this.each(function(){var t=s(this),e=t.data("bs.scrollspy"),i="object"==typeof o&&o;e||t.data("bs.scrollspy",e=new n(this,i)),"string"==typeof o&&e[o]()})}n.VERSION="3.4.1",n.DEFAULTS={offset:10},n.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},n.prototype.refresh=function(){var t=this,o="offset",n=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),s.isWindow(this.$scrollElement[0])||(o="position",n=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var t=s(this),e=t.data("target")||t.attr("href"),i=/^#./.test(e)&&s(e);return i&&i.length&&i.is(":visible")&&[[i[o]().top+n,e]]||null}).sort(function(t,e){return t[0]-e[0]}).each(function(){t.offsets.push(this[0]),t.targets.push(this[1])})},n.prototype.process=function(){var t,e=this.$scrollElement.scrollTop()+this.options.offset,i=this.getScrollHeight(),o=this.options.offset+i-this.$scrollElement.height(),n=this.offsets,s=this.targets,a=this.activeTarget;if(this.scrollHeight!=i&&this.refresh(),o<=e)return a!=(t=s[s.length-1])&&this.activate(t);if(a&&e=n[t]&&(n[t+1]===undefined||e .active"),n=i&&r.support.transition&&(o.length&&o.hasClass("fade")||!!e.find("> .fade").length);function s(){o.removeClass("active").find("> .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),t.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),n?(t[0].offsetWidth,t.addClass("in")):t.removeClass("fade"),t.parent(".dropdown-menu").length&&t.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),i&&i()}o.length&&n?o.one("bsTransitionEnd",s).emulateTransitionEnd(a.TRANSITION_DURATION):s(),o.removeClass("in")};var t=r.fn.tab;r.fn.tab=e,r.fn.tab.Constructor=a,r.fn.tab.noConflict=function(){return r.fn.tab=t,this};var i=function(t){t.preventDefault(),e.call(r(this),"show")};r(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',i).on("click.bs.tab.data-api",'[data-toggle="pill"]',i)}(jQuery),function(l){"use strict";var h=function(t,e){this.options=l.extend({},h.DEFAULTS,e);var i=this.options.target===h.DEFAULTS.target?l(this.options.target):l(document).find(this.options.target);this.$target=i.on("scroll.bs.affix.data-api",l.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",l.proxy(this.checkPositionWithEventLoop,this)),this.$element=l(t),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};function i(o){return this.each(function(){var t=l(this),e=t.data("bs.affix"),i="object"==typeof o&&o;e||t.data("bs.affix",e=new h(this,i)),"string"==typeof o&&e[o]()})}h.VERSION="3.4.1",h.RESET="affix affix-top affix-bottom",h.DEFAULTS={offset:0,target:window},h.prototype.getState=function(t,e,i,o){var n=this.$target.scrollTop(),s=this.$element.offset(),a=this.$target.height();if(null!=i&&"top"==this.affixed)return n<'col-sm-6'f>r>" + "t" + "<'row'<'col-sm-6'i><'col-sm-6'p>>", + "oLanguage": { + "sLengthMenu": "_MENU_ records per page" + } +}); + + +/* Default class modification */ +$.extend($.fn.dataTableExt.oStdClasses, { + "sWrapper": "dataTables_wrapper form-inline", + "sFilterInput": "form-control input-sm", + "sLengthSelect": "form-control input-sm" +}); + +// In 1.10 we use the pagination renderers to draw the Bootstrap paging, +// rather than custom plug-in +if ($.fn.dataTable.Api) { + $.fn.dataTable.defaults.renderer = 'bootstrap'; + $.fn.dataTable.ext.renderer.pageButton.bootstrap = function(settings, host, idx, buttons, page, pages) { + var api = new $.fn.dataTable.Api(settings); + var classes = settings.oClasses; + var lang = settings.oLanguage.oPaginate; + var btnDisplay, btnClass; + + var attach = function(container, buttons) { + var i, ien, node, button; + var clickHandler = function(e) { + e.preventDefault(); + if (e.data.action !== 'ellipsis') { + api.page(e.data.action).draw(false); + } + }; + + for (i = 0, ien = buttons.length; i < ien; i++) { + button = buttons[i]; + + if ($.isArray(button)) { + attach(container, button); + } else { + btnDisplay = ''; + btnClass = ''; + + switch (button) { + case 'ellipsis': + btnDisplay = '…'; + btnClass = 'disabled'; + break; + + case 'first': + btnDisplay = lang.sFirst; + btnClass = button + (page > 0 ? + '' : ' disabled'); + break; + + case 'previous': + btnDisplay = lang.sPrevious; + btnClass = button + (page > 0 ? + '' : ' disabled'); + break; + + case 'next': + btnDisplay = lang.sNext; + btnClass = button + (page < pages - 1 ? + '' : ' disabled'); + break; + + case 'last': + btnDisplay = lang.sLast; + btnClass = button + (page < pages - 1 ? + '' : ' disabled'); + break; + + default: + btnDisplay = button + 1; + btnClass = page === button ? + 'active' : ''; + break; + } + + if (btnDisplay) { + node = $('
  • ', { + 'class': classes.sPageButton + ' ' + btnClass, + 'aria-controls': settings.sTableId, + 'tabindex': settings.iTabIndex, + 'id': idx === 0 && typeof button === 'string' ? settings.sTableId + '_' + button : null + }) + .append($('', { + 'href': '#' + }) + .html(btnDisplay) + ) + .appendTo(container); + + settings.oApi._fnBindAction( + node, { + action: button + }, clickHandler + ); + } + } + } + }; + + attach( + $(host).empty().html('
      ').children('ul'), + buttons + ); + } +} else { + // Integration for 1.9- + $.fn.dataTable.defaults.sPaginationType = 'bootstrap'; + + /* API method to get paging information */ + $.fn.dataTableExt.oApi.fnPagingInfo = function(oSettings) { + return { + "iStart": oSettings._iDisplayStart, + "iEnd": oSettings.fnDisplayEnd(), + "iLength": oSettings._iDisplayLength, + "iTotal": oSettings.fnRecordsTotal(), + "iFilteredTotal": oSettings.fnRecordsDisplay(), + "iPage": oSettings._iDisplayLength === -1 ? 0 : Math.ceil(oSettings._iDisplayStart / oSettings._iDisplayLength), + "iTotalPages": oSettings._iDisplayLength === -1 ? 0 : Math.ceil(oSettings.fnRecordsDisplay() / oSettings._iDisplayLength) + }; + }; + + /* Bootstrap style pagination control */ + $.extend($.fn.dataTableExt.oPagination, { + "bootstrap": { + "fnInit": function(oSettings, nPaging, fnDraw) { + var oLang = oSettings.oLanguage.oPaginate; + var fnClickHandler = function(e) { + e.preventDefault(); + if (oSettings.oApi._fnPageChange(oSettings, e.data.action)) { + fnDraw(oSettings); + } + }; + + $(nPaging).append( + '' + ); + var els = $('a', nPaging); + $(els[0]).bind('click.DT', { + action: "previous" + }, fnClickHandler); + $(els[1]).bind('click.DT', { + action: "next" + }, fnClickHandler); + }, + + "fnUpdate": function(oSettings, fnDraw) { + var iListLength = 5; + var oPaging = oSettings.oInstance.fnPagingInfo(); + var an = oSettings.aanFeatures.p; + var i, ien, j, sClass, iStart, iEnd, iHalf = Math.floor(iListLength / 2); + + if (oPaging.iTotalPages < iListLength) { + iStart = 1; + iEnd = oPaging.iTotalPages; + } else if (oPaging.iPage <= iHalf) { + iStart = 1; + iEnd = iListLength; + } else if (oPaging.iPage >= (oPaging.iTotalPages - iHalf)) { + iStart = oPaging.iTotalPages - iListLength + 1; + iEnd = oPaging.iTotalPages; + } else { + iStart = oPaging.iPage - iHalf + 1; + iEnd = iStart + iListLength - 1; + } + + for (i = 0, ien = an.length; i < ien; i++) { + // Remove the middle elements + $('li:gt(0)', an[i]).filter(':not(:last)').remove(); + + // Add the new list items and their event handlers + for (j = iStart; j <= iEnd; j++) { + sClass = (j == oPaging.iPage + 1) ? 'class="active"' : ''; + $('
    • ' + j + '
    • ') + .insertBefore($('li:last', an[i])[0]) + .bind('click', function(e) { + e.preventDefault(); + oSettings._iDisplayStart = (parseInt($('a', this).text(), 10) - 1) * oPaging.iLength; + fnDraw(oSettings); + }); + } + + // Add / remove disabled classes from the static elements + if (oPaging.iPage === 0) { + $('li:first', an[i]).addClass('disabled'); + } else { + $('li:first', an[i]).removeClass('disabled'); + } + + if (oPaging.iPage === oPaging.iTotalPages - 1 || oPaging.iTotalPages === 0) { + $('li:last', an[i]).addClass('disabled'); + } else { + $('li:last', an[i]).removeClass('disabled'); + } + } + } + } + }); +} + + +/* + * TableTools Bootstrap compatibility + * Required TableTools 2.1+ + */ +if ($.fn.DataTable.TableTools) { + // Set the classes that TableTools uses to something suitable for Bootstrap + $.extend(true, $.fn.DataTable.TableTools.classes, { + "container": "DTTT btn-group", + "buttons": { + "normal": "btn btn-default", + "disabled": "disabled" + }, + "collection": { + "container": "DTTT_dropdown dropdown-menu", + "buttons": { + "normal": "", + "disabled": "disabled" + } + }, + "print": { + "info": "DTTT_print_info modal" + }, + "select": { + "row": "active" + } + }); + + // Have the collection use a bootstrap compatible dropdown + $.extend(true, $.fn.DataTable.TableTools.DEFAULTS.oTags, { + "collection": { + "container": "ul", + "button": "li", + "liner": "a" + } + }); +} diff --git a/intelmq/web/static/plugins/dataTables/jquery.dataTables.js b/intelmq/web/static/plugins/dataTables/jquery.dataTables.js new file mode 100644 index 000000000..88cdab91d --- /dev/null +++ b/intelmq/web/static/plugins/dataTables/jquery.dataTables.js @@ -0,0 +1,15243 @@ +/*! DataTables 1.10.16 + * ©2008-2017 SpryMedia Ltd - datatables.net/license + */ + +/** + * @summary DataTables + * @description Paginate, search and order HTML tables + * @version 1.10.16 + * @file jquery.dataTables.js + * @author SpryMedia Ltd + * @contact www.datatables.net + * @copyright Copyright 2008-2017 SpryMedia Ltd. + * + * This source file is free software, available under the following license: + * MIT license - http://datatables.net/license + * + * This source file is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details. + * + * For details please refer to: http://www.datatables.net + */ + +/*jslint evil: true, undef: true, browser: true */ +/*globals $,require,jQuery,define,_selector_run,_selector_opts,_selector_first,_selector_row_indexes,_ext,_Api,_api_register,_api_registerPlural,_re_new_lines,_re_html,_re_formatted_numeric,_re_escape_regex,_empty,_intVal,_numToDecimal,_isNumber,_isHtml,_htmlNumeric,_pluck,_pluck_order,_range,_stripHtml,_unique,_fnBuildAjax,_fnAjaxUpdate,_fnAjaxParameters,_fnAjaxUpdateDraw,_fnAjaxDataSrc,_fnAddColumn,_fnColumnOptions,_fnAdjustColumnSizing,_fnVisibleToColumnIndex,_fnColumnIndexToVisible,_fnVisbleColumns,_fnGetColumns,_fnColumnTypes,_fnApplyColumnDefs,_fnHungarianMap,_fnCamelToHungarian,_fnLanguageCompat,_fnBrowserDetect,_fnAddData,_fnAddTr,_fnNodeToDataIndex,_fnNodeToColumnIndex,_fnGetCellData,_fnSetCellData,_fnSplitObjNotation,_fnGetObjectDataFn,_fnSetObjectDataFn,_fnGetDataMaster,_fnClearTable,_fnDeleteIndex,_fnInvalidate,_fnGetRowElements,_fnCreateTr,_fnBuildHead,_fnDrawHead,_fnDraw,_fnReDraw,_fnAddOptionsHtml,_fnDetectHeader,_fnGetUniqueThs,_fnFeatureHtmlFilter,_fnFilterComplete,_fnFilterCustom,_fnFilterColumn,_fnFilter,_fnFilterCreateSearch,_fnEscapeRegex,_fnFilterData,_fnFeatureHtmlInfo,_fnUpdateInfo,_fnInfoMacros,_fnInitialise,_fnInitComplete,_fnLengthChange,_fnFeatureHtmlLength,_fnFeatureHtmlPaginate,_fnPageChange,_fnFeatureHtmlProcessing,_fnProcessingDisplay,_fnFeatureHtmlTable,_fnScrollDraw,_fnApplyToChildren,_fnCalculateColumnWidths,_fnThrottle,_fnConvertToWidth,_fnGetWidestNode,_fnGetMaxLenString,_fnStringToCss,_fnSortFlatten,_fnSort,_fnSortAria,_fnSortListener,_fnSortAttachListener,_fnSortingClasses,_fnSortData,_fnSaveState,_fnLoadState,_fnSettingsFromNode,_fnLog,_fnMap,_fnBindAction,_fnCallbackReg,_fnCallbackFire,_fnLengthOverflow,_fnRenderer,_fnDataSource,_fnRowAttributes*/ + +(function( factory ) { + "use strict"; + + if ( typeof define === 'function' && define.amd ) { + // AMD + define( ['jquery'], function ( $ ) { + return factory( $, window, document ); + } ); + } + else if ( typeof exports === 'object' ) { + // CommonJS + module.exports = function (root, $) { + if ( ! root ) { + // CommonJS environments without a window global must pass a + // root. This will give an error otherwise + root = window; + } + + if ( ! $ ) { + $ = typeof window !== 'undefined' ? // jQuery's factory checks for a global window + require('jquery') : + require('jquery')( root ); + } + + return factory( $, root, root.document ); + }; + } + else { + // Browser + factory( jQuery, window, document ); + } +} +(function( $, window, document, undefined ) { + "use strict"; + + /** + * DataTables is a plug-in for the jQuery Javascript library. It is a highly + * flexible tool, based upon the foundations of progressive enhancement, + * which will add advanced interaction controls to any HTML table. For a + * full list of features please refer to + * [DataTables.net](href="http://datatables.net). + * + * Note that the `DataTable` object is not a global variable but is aliased + * to `jQuery.fn.DataTable` and `jQuery.fn.dataTable` through which it may + * be accessed. + * + * @class + * @param {object} [init={}] Configuration object for DataTables. Options + * are defined by {@link DataTable.defaults} + * @requires jQuery 1.7+ + * + * @example + * // Basic initialisation + * $(document).ready( function { + * $('#example').dataTable(); + * } ); + * + * @example + * // Initialisation with configuration options - in this case, disable + * // pagination and sorting. + * $(document).ready( function { + * $('#example').dataTable( { + * "paginate": false, + * "sort": false + * } ); + * } ); + */ + var DataTable = function ( options ) + { + /** + * Perform a jQuery selector action on the table's TR elements (from the tbody) and + * return the resulting jQuery object. + * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on + * @param {object} [oOpts] Optional parameters for modifying the rows to be included + * @param {string} [oOpts.filter=none] Select TR elements that meet the current filter + * criterion ("applied") or all TR elements (i.e. no filter). + * @param {string} [oOpts.order=current] Order of the TR elements in the processed array. + * Can be either 'current', whereby the current sorting of the table is used, or + * 'original' whereby the original order the data was read into the table is used. + * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page + * ("current") or not ("all"). If 'current' is given, then order is assumed to be + * 'current' and filter is 'applied', regardless of what they might be given as. + * @returns {object} jQuery object, filtered by the given selector. + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Highlight every second row + * oTable.$('tr:odd').css('backgroundColor', 'blue'); + * } ); + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Filter to rows with 'Webkit' in them, add a background colour and then + * // remove the filter, thus highlighting the 'Webkit' rows only. + * oTable.fnFilter('Webkit'); + * oTable.$('tr', {"search": "applied"}).css('backgroundColor', 'blue'); + * oTable.fnFilter(''); + * } ); + */ + this.$ = function ( sSelector, oOpts ) + { + return this.api(true).$( sSelector, oOpts ); + }; + + + /** + * Almost identical to $ in operation, but in this case returns the data for the matched + * rows - as such, the jQuery selector used should match TR row nodes or TD/TH cell nodes + * rather than any descendants, so the data can be obtained for the row/cell. If matching + * rows are found, the data returned is the original data array/object that was used to + * create the row (or a generated array if from a DOM source). + * + * This method is often useful in-combination with $ where both functions are given the + * same parameters and the array indexes will match identically. + * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on + * @param {object} [oOpts] Optional parameters for modifying the rows to be included + * @param {string} [oOpts.filter=none] Select elements that meet the current filter + * criterion ("applied") or all elements (i.e. no filter). + * @param {string} [oOpts.order=current] Order of the data in the processed array. + * Can be either 'current', whereby the current sorting of the table is used, or + * 'original' whereby the original order the data was read into the table is used. + * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page + * ("current") or not ("all"). If 'current' is given, then order is assumed to be + * 'current' and filter is 'applied', regardless of what they might be given as. + * @returns {array} Data for the matched elements. If any elements, as a result of the + * selector, were not TR, TD or TH elements in the DataTable, they will have a null + * entry in the array. + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Get the data from the first row in the table + * var data = oTable._('tr:first'); + * + * // Do something useful with the data + * alert( "First cell is: "+data[0] ); + * } ); + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Filter to 'Webkit' and get all data for + * oTable.fnFilter('Webkit'); + * var data = oTable._('tr', {"search": "applied"}); + * + * // Do something with the data + * alert( data.length+" rows matched the search" ); + * } ); + */ + this._ = function ( sSelector, oOpts ) + { + return this.api(true).rows( sSelector, oOpts ).data(); + }; + + + /** + * Create a DataTables Api instance, with the currently selected tables for + * the Api's context. + * @param {boolean} [traditional=false] Set the API instance's context to be + * only the table referred to by the `DataTable.ext.iApiIndex` option, as was + * used in the API presented by DataTables 1.9- (i.e. the traditional mode), + * or if all tables captured in the jQuery object should be used. + * @return {DataTables.Api} + */ + this.api = function ( traditional ) + { + return traditional ? + new _Api( + _fnSettingsFromNode( this[ _ext.iApiIndex ] ) + ) : + new _Api( this ); + }; + + + /** + * Add a single new row or multiple rows of data to the table. Please note + * that this is suitable for client-side processing only - if you are using + * server-side processing (i.e. "bServerSide": true), then to add data, you + * must add it to the data source, i.e. the server-side, through an Ajax call. + * @param {array|object} data The data to be added to the table. This can be: + *
        + *
      • 1D array of data - add a single row with the data provided
      • + *
      • 2D array of arrays - add multiple rows in a single call
      • + *
      • object - data object when using mData
      • + *
      • array of objects - multiple data objects when using mData
      • + *
      + * @param {bool} [redraw=true] redraw the table or not + * @returns {array} An array of integers, representing the list of indexes in + * aoData ({@link DataTable.models.oSettings}) that have been added to + * the table. + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * // Global var for counter + * var giCount = 2; + * + * $(document).ready(function() { + * $('#example').dataTable(); + * } ); + * + * function fnClickAddRow() { + * $('#example').dataTable().fnAddData( [ + * giCount+".1", + * giCount+".2", + * giCount+".3", + * giCount+".4" ] + * ); + * + * giCount++; + * } + */ + this.fnAddData = function( data, redraw ) + { + var api = this.api( true ); + + /* Check if we want to add multiple rows or not */ + var rows = $.isArray(data) && ( $.isArray(data[0]) || $.isPlainObject(data[0]) ) ? + api.rows.add( data ) : + api.row.add( data ); + + if ( redraw === undefined || redraw ) { + api.draw(); + } + + return rows.flatten().toArray(); + }; + + + /** + * This function will make DataTables recalculate the column sizes, based on the data + * contained in the table and the sizes applied to the columns (in the DOM, CSS or + * through the sWidth parameter). This can be useful when the width of the table's + * parent element changes (for example a window resize). + * @param {boolean} [bRedraw=true] Redraw the table or not, you will typically want to + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable( { + * "sScrollY": "200px", + * "bPaginate": false + * } ); + * + * $(window).on('resize', function () { + * oTable.fnAdjustColumnSizing(); + * } ); + * } ); + */ + this.fnAdjustColumnSizing = function ( bRedraw ) + { + var api = this.api( true ).columns.adjust(); + var settings = api.settings()[0]; + var scroll = settings.oScroll; + + if ( bRedraw === undefined || bRedraw ) { + api.draw( false ); + } + else if ( scroll.sX !== "" || scroll.sY !== "" ) { + /* If not redrawing, but scrolling, we want to apply the new column sizes anyway */ + _fnScrollDraw( settings ); + } + }; + + + /** + * Quickly and simply clear a table + * @param {bool} [bRedraw=true] redraw the table or not + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...) + * oTable.fnClearTable(); + * } ); + */ + this.fnClearTable = function( bRedraw ) + { + var api = this.api( true ).clear(); + + if ( bRedraw === undefined || bRedraw ) { + api.draw(); + } + }; + + + /** + * The exact opposite of 'opening' a row, this function will close any rows which + * are currently 'open'. + * @param {node} nTr the table row to 'close' + * @returns {int} 0 on success, or 1 if failed (can't find the row) + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable; + * + * // 'open' an information row when a row is clicked on + * $('#example tbody tr').click( function () { + * if ( oTable.fnIsOpen(this) ) { + * oTable.fnClose( this ); + * } else { + * oTable.fnOpen( this, "Temporary row opened", "info_row" ); + * } + * } ); + * + * oTable = $('#example').dataTable(); + * } ); + */ + this.fnClose = function( nTr ) + { + this.api( true ).row( nTr ).child.hide(); + }; + + + /** + * Remove a row for the table + * @param {mixed} target The index of the row from aoData to be deleted, or + * the TR element you want to delete + * @param {function|null} [callBack] Callback function + * @param {bool} [redraw=true] Redraw the table or not + * @returns {array} The row that was deleted + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Immediately remove the first row + * oTable.fnDeleteRow( 0 ); + * } ); + */ + this.fnDeleteRow = function( target, callback, redraw ) + { + var api = this.api( true ); + var rows = api.rows( target ); + var settings = rows.settings()[0]; + var data = settings.aoData[ rows[0][0] ]; + + rows.remove(); + + if ( callback ) { + callback.call( this, settings, data ); + } + + if ( redraw === undefined || redraw ) { + api.draw(); + } + + return data; + }; + + + /** + * Restore the table to it's original state in the DOM by removing all of DataTables + * enhancements, alterations to the DOM structure of the table and event listeners. + * @param {boolean} [remove=false] Completely remove the table from the DOM + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * // This example is fairly pointless in reality, but shows how fnDestroy can be used + * var oTable = $('#example').dataTable(); + * oTable.fnDestroy(); + * } ); + */ + this.fnDestroy = function ( remove ) + { + this.api( true ).destroy( remove ); + }; + + + /** + * Redraw the table + * @param {bool} [complete=true] Re-filter and resort (if enabled) the table before the draw. + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Re-draw the table - you wouldn't want to do it here, but it's an example :-) + * oTable.fnDraw(); + * } ); + */ + this.fnDraw = function( complete ) + { + // Note that this isn't an exact match to the old call to _fnDraw - it takes + // into account the new data, but can hold position. + this.api( true ).draw( complete ); + }; + + + /** + * Filter the input based on data + * @param {string} sInput String to filter the table on + * @param {int|null} [iColumn] Column to limit filtering to + * @param {bool} [bRegex=false] Treat as regular expression or not + * @param {bool} [bSmart=true] Perform smart filtering or not + * @param {bool} [bShowGlobal=true] Show the input global filter in it's input box(es) + * @param {bool} [bCaseInsensitive=true] Do case-insensitive matching (true) or not (false) + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Sometime later - filter... + * oTable.fnFilter( 'test string' ); + * } ); + */ + this.fnFilter = function( sInput, iColumn, bRegex, bSmart, bShowGlobal, bCaseInsensitive ) + { + var api = this.api( true ); + + if ( iColumn === null || iColumn === undefined ) { + api.search( sInput, bRegex, bSmart, bCaseInsensitive ); + } + else { + api.column( iColumn ).search( sInput, bRegex, bSmart, bCaseInsensitive ); + } + + api.draw(); + }; + + + /** + * Get the data for the whole table, an individual row or an individual cell based on the + * provided parameters. + * @param {int|node} [src] A TR row node, TD/TH cell node or an integer. If given as + * a TR node then the data source for the whole row will be returned. If given as a + * TD/TH cell node then iCol will be automatically calculated and the data for the + * cell returned. If given as an integer, then this is treated as the aoData internal + * data index for the row (see fnGetPosition) and the data for that row used. + * @param {int} [col] Optional column index that you want the data of. + * @returns {array|object|string} If mRow is undefined, then the data for all rows is + * returned. If mRow is defined, just data for that row, and is iCol is + * defined, only data for the designated cell is returned. + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * // Row data + * $(document).ready(function() { + * oTable = $('#example').dataTable(); + * + * oTable.$('tr').click( function () { + * var data = oTable.fnGetData( this ); + * // ... do something with the array / object of data for the row + * } ); + * } ); + * + * @example + * // Individual cell data + * $(document).ready(function() { + * oTable = $('#example').dataTable(); + * + * oTable.$('td').click( function () { + * var sData = oTable.fnGetData( this ); + * alert( 'The cell clicked on had the value of '+sData ); + * } ); + * } ); + */ + this.fnGetData = function( src, col ) + { + var api = this.api( true ); + + if ( src !== undefined ) { + var type = src.nodeName ? src.nodeName.toLowerCase() : ''; + + return col !== undefined || type == 'td' || type == 'th' ? + api.cell( src, col ).data() : + api.row( src ).data() || null; + } + + return api.data().toArray(); + }; + + + /** + * Get an array of the TR nodes that are used in the table's body. Note that you will + * typically want to use the '$' API method in preference to this as it is more + * flexible. + * @param {int} [iRow] Optional row index for the TR element you want + * @returns {array|node} If iRow is undefined, returns an array of all TR elements + * in the table's body, or iRow is defined, just the TR element requested. + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Get the nodes from the table + * var nNodes = oTable.fnGetNodes( ); + * } ); + */ + this.fnGetNodes = function( iRow ) + { + var api = this.api( true ); + + return iRow !== undefined ? + api.row( iRow ).node() : + api.rows().nodes().flatten().toArray(); + }; + + + /** + * Get the array indexes of a particular cell from it's DOM element + * and column index including hidden columns + * @param {node} node this can either be a TR, TD or TH in the table's body + * @returns {int} If nNode is given as a TR, then a single index is returned, or + * if given as a cell, an array of [row index, column index (visible), + * column index (all)] is given. + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * $('#example tbody td').click( function () { + * // Get the position of the current data from the node + * var aPos = oTable.fnGetPosition( this ); + * + * // Get the data array for this row + * var aData = oTable.fnGetData( aPos[0] ); + * + * // Update the data array and return the value + * aData[ aPos[1] ] = 'clicked'; + * this.innerHTML = 'clicked'; + * } ); + * + * // Init DataTables + * oTable = $('#example').dataTable(); + * } ); + */ + this.fnGetPosition = function( node ) + { + var api = this.api( true ); + var nodeName = node.nodeName.toUpperCase(); + + if ( nodeName == 'TR' ) { + return api.row( node ).index(); + } + else if ( nodeName == 'TD' || nodeName == 'TH' ) { + var cell = api.cell( node ).index(); + + return [ + cell.row, + cell.columnVisible, + cell.column + ]; + } + return null; + }; + + + /** + * Check to see if a row is 'open' or not. + * @param {node} nTr the table row to check + * @returns {boolean} true if the row is currently open, false otherwise + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable; + * + * // 'open' an information row when a row is clicked on + * $('#example tbody tr').click( function () { + * if ( oTable.fnIsOpen(this) ) { + * oTable.fnClose( this ); + * } else { + * oTable.fnOpen( this, "Temporary row opened", "info_row" ); + * } + * } ); + * + * oTable = $('#example').dataTable(); + * } ); + */ + this.fnIsOpen = function( nTr ) + { + return this.api( true ).row( nTr ).child.isShown(); + }; + + + /** + * This function will place a new row directly after a row which is currently + * on display on the page, with the HTML contents that is passed into the + * function. This can be used, for example, to ask for confirmation that a + * particular record should be deleted. + * @param {node} nTr The table row to 'open' + * @param {string|node|jQuery} mHtml The HTML to put into the row + * @param {string} sClass Class to give the new TD cell + * @returns {node} The row opened. Note that if the table row passed in as the + * first parameter, is not found in the table, this method will silently + * return. + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable; + * + * // 'open' an information row when a row is clicked on + * $('#example tbody tr').click( function () { + * if ( oTable.fnIsOpen(this) ) { + * oTable.fnClose( this ); + * } else { + * oTable.fnOpen( this, "Temporary row opened", "info_row" ); + * } + * } ); + * + * oTable = $('#example').dataTable(); + * } ); + */ + this.fnOpen = function( nTr, mHtml, sClass ) + { + return this.api( true ) + .row( nTr ) + .child( mHtml, sClass ) + .show() + .child()[0]; + }; + + + /** + * Change the pagination - provides the internal logic for pagination in a simple API + * function. With this function you can have a DataTables table go to the next, + * previous, first or last pages. + * @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last" + * or page number to jump to (integer), note that page 0 is the first page. + * @param {bool} [bRedraw=true] Redraw the table or not + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * oTable.fnPageChange( 'next' ); + * } ); + */ + this.fnPageChange = function ( mAction, bRedraw ) + { + var api = this.api( true ).page( mAction ); + + if ( bRedraw === undefined || bRedraw ) { + api.draw(false); + } + }; + + + /** + * Show a particular column + * @param {int} iCol The column whose display should be changed + * @param {bool} bShow Show (true) or hide (false) the column + * @param {bool} [bRedraw=true] Redraw the table or not + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Hide the second column after initialisation + * oTable.fnSetColumnVis( 1, false ); + * } ); + */ + this.fnSetColumnVis = function ( iCol, bShow, bRedraw ) + { + var api = this.api( true ).column( iCol ).visible( bShow ); + + if ( bRedraw === undefined || bRedraw ) { + api.columns.adjust().draw(); + } + }; + + + /** + * Get the settings for a particular table for external manipulation + * @returns {object} DataTables settings object. See + * {@link DataTable.models.oSettings} + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * var oSettings = oTable.fnSettings(); + * + * // Show an example parameter from the settings + * alert( oSettings._iDisplayStart ); + * } ); + */ + this.fnSettings = function() + { + return _fnSettingsFromNode( this[_ext.iApiIndex] ); + }; + + + /** + * Sort the table by a particular column + * @param {int} iCol the data index to sort on. Note that this will not match the + * 'display index' if you have hidden data entries + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Sort immediately with columns 0 and 1 + * oTable.fnSort( [ [0,'asc'], [1,'asc'] ] ); + * } ); + */ + this.fnSort = function( aaSort ) + { + this.api( true ).order( aaSort ).draw(); + }; + + + /** + * Attach a sort listener to an element for a given column + * @param {node} nNode the element to attach the sort listener to + * @param {int} iColumn the column that a click on this node will sort on + * @param {function} [fnCallback] callback function when sort is run + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Sort on column 1, when 'sorter' is clicked on + * oTable.fnSortListener( document.getElementById('sorter'), 1 ); + * } ); + */ + this.fnSortListener = function( nNode, iColumn, fnCallback ) + { + this.api( true ).order.listener( nNode, iColumn, fnCallback ); + }; + + + /** + * Update a table cell or row - this method will accept either a single value to + * update the cell with, an array of values with one element for each column or + * an object in the same format as the original data source. The function is + * self-referencing in order to make the multi column updates easier. + * @param {object|array|string} mData Data to update the cell/row with + * @param {node|int} mRow TR element you want to update or the aoData index + * @param {int} [iColumn] The column to update, give as null or undefined to + * update a whole row. + * @param {bool} [bRedraw=true] Redraw the table or not + * @param {bool} [bAction=true] Perform pre-draw actions or not + * @returns {int} 0 on success, 1 on error + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell + * oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], $('tbody tr')[0] ); // Row + * } ); + */ + this.fnUpdate = function( mData, mRow, iColumn, bRedraw, bAction ) + { + var api = this.api( true ); + + if ( iColumn === undefined || iColumn === null ) { + api.row( mRow ).data( mData ); + } + else { + api.cell( mRow, iColumn ).data( mData ); + } + + if ( bAction === undefined || bAction ) { + api.columns.adjust(); + } + + if ( bRedraw === undefined || bRedraw ) { + api.draw(); + } + return 0; + }; + + + /** + * Provide a common method for plug-ins to check the version of DataTables being used, in order + * to ensure compatibility. + * @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the + * formats "X" and "X.Y" are also acceptable. + * @returns {boolean} true if this version of DataTables is greater or equal to the required + * version, or false if this version of DataTales is not suitable + * @method + * @dtopt API + * @deprecated Since v1.10 + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * alert( oTable.fnVersionCheck( '1.9.0' ) ); + * } ); + */ + this.fnVersionCheck = _ext.fnVersionCheck; + + + var _that = this; + var emptyInit = options === undefined; + var len = this.length; + + if ( emptyInit ) { + options = {}; + } + + this.oApi = this.internal = _ext.internal; + + // Extend with old style plug-in API methods + for ( var fn in DataTable.ext.internal ) { + if ( fn ) { + this[fn] = _fnExternApiFunc(fn); + } + } + + this.each(function() { + // For each initialisation we want to give it a clean initialisation + // object that can be bashed around + var o = {}; + var oInit = len > 1 ? // optimisation for single table case + _fnExtend( o, options, true ) : + options; + + /*global oInit,_that,emptyInit*/ + var i=0, iLen, j, jLen, k, kLen; + var sId = this.getAttribute( 'id' ); + var bInitHandedOff = false; + var defaults = DataTable.defaults; + var $this = $(this); + + + /* Sanity check */ + if ( this.nodeName.toLowerCase() != 'table' ) + { + _fnLog( null, 0, 'Non-table node initialisation ('+this.nodeName+')', 2 ); + return; + } + + /* Backwards compatibility for the defaults */ + _fnCompatOpts( defaults ); + _fnCompatCols( defaults.column ); + + /* Convert the camel-case defaults to Hungarian */ + _fnCamelToHungarian( defaults, defaults, true ); + _fnCamelToHungarian( defaults.column, defaults.column, true ); + + /* Setting up the initialisation object */ + _fnCamelToHungarian( defaults, $.extend( oInit, $this.data() ) ); + + + + /* Check to see if we are re-initialising a table */ + var allSettings = DataTable.settings; + for ( i=0, iLen=allSettings.length ; i').appendTo($this); + } + oSettings.nTHead = thead[0]; + + var tbody = $this.children('tbody'); + if ( tbody.length === 0 ) { + tbody = $('').appendTo($this); + } + oSettings.nTBody = tbody[0]; + + var tfoot = $this.children('tfoot'); + if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") ) { + // If we are a scrolling table, and no footer has been given, then we need to create + // a tfoot element for the caption element to be appended to + tfoot = $('').appendTo($this); + } + + if ( tfoot.length === 0 || tfoot.children().length === 0 ) { + $this.addClass( oClasses.sNoFooter ); + } + else if ( tfoot.length > 0 ) { + oSettings.nTFoot = tfoot[0]; + _fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot ); + } + + /* Check if there is data passing into the constructor */ + if ( oInit.aaData ) { + for ( i=0 ; i/g; + + // This is not strict ISO8601 - Date.parse() is quite lax, although + // implementations differ between browsers. + var _re_date = /^\d{2,4}[\.\/\-]\d{1,2}[\.\/\-]\d{1,2}([T ]{1}\d{1,2}[:\.]\d{2}([\.:]\d{2})?)?$/; + + // Escape regular expression special characters + var _re_escape_regex = new RegExp( '(\\' + [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ].join('|\\') + ')', 'g' ); + + // http://en.wikipedia.org/wiki/Foreign_exchange_market + // - \u20BD - Russian ruble. + // - \u20a9 - South Korean Won + // - \u20BA - Turkish Lira + // - \u20B9 - Indian Rupee + // - R - Brazil (R$) and South Africa + // - fr - Swiss Franc + // - kr - Swedish krona, Norwegian krone and Danish krone + // - \u2009 is thin space and \u202F is narrow no-break space, both used in many + // standards as thousands separators. + var _re_formatted_numeric = /[',$£€¥%\u2009\u202F\u20BD\u20a9\u20BArfk]/gi; + + + var _empty = function ( d ) { + return !d || d === true || d === '-' ? true : false; + }; + + + var _intVal = function ( s ) { + var integer = parseInt( s, 10 ); + return !isNaN(integer) && isFinite(s) ? integer : null; + }; + + // Convert from a formatted number with characters other than `.` as the + // decimal place, to a Javascript number + var _numToDecimal = function ( num, decimalPoint ) { + // Cache created regular expressions for speed as this function is called often + if ( ! _re_dic[ decimalPoint ] ) { + _re_dic[ decimalPoint ] = new RegExp( _fnEscapeRegex( decimalPoint ), 'g' ); + } + return typeof num === 'string' && decimalPoint !== '.' ? + num.replace( /\./g, '' ).replace( _re_dic[ decimalPoint ], '.' ) : + num; + }; + + + var _isNumber = function ( d, decimalPoint, formatted ) { + var strType = typeof d === 'string'; + + // If empty return immediately so there must be a number if it is a + // formatted string (this stops the string "k", or "kr", etc being detected + // as a formatted number for currency + if ( _empty( d ) ) { + return true; + } + + if ( decimalPoint && strType ) { + d = _numToDecimal( d, decimalPoint ); + } + + if ( formatted && strType ) { + d = d.replace( _re_formatted_numeric, '' ); + } + + return !isNaN( parseFloat(d) ) && isFinite( d ); + }; + + + // A string without HTML in it can be considered to be HTML still + var _isHtml = function ( d ) { + return _empty( d ) || typeof d === 'string'; + }; + + + var _htmlNumeric = function ( d, decimalPoint, formatted ) { + if ( _empty( d ) ) { + return true; + } + + var html = _isHtml( d ); + return ! html ? + null : + _isNumber( _stripHtml( d ), decimalPoint, formatted ) ? + true : + null; + }; + + + var _pluck = function ( a, prop, prop2 ) { + var out = []; + var i=0, ien=a.length; + + // Could have the test in the loop for slightly smaller code, but speed + // is essential here + if ( prop2 !== undefined ) { + for ( ; i') + .css( { + position: 'fixed', + top: 0, + left: $(window).scrollLeft()*-1, // allow for scrolling + height: 1, + width: 1, + overflow: 'hidden' + } ) + .append( + $('
      ') + .css( { + position: 'absolute', + top: 1, + left: 1, + width: 100, + overflow: 'scroll' + } ) + .append( + $('
      ') + .css( { + width: '100%', + height: 10 + } ) + ) + ) + .appendTo( 'body' ); + + var outer = n.children(); + var inner = outer.children(); + + // Numbers below, in order, are: + // inner.offsetWidth, inner.clientWidth, outer.offsetWidth, outer.clientWidth + // + // IE6 XP: 100 100 100 83 + // IE7 Vista: 100 100 100 83 + // IE 8+ Windows: 83 83 100 83 + // Evergreen Windows: 83 83 100 83 + // Evergreen Mac with scrollbars: 85 85 100 85 + // Evergreen Mac without scrollbars: 100 100 100 100 + + // Get scrollbar width + browser.barWidth = outer[0].offsetWidth - outer[0].clientWidth; + + // IE6/7 will oversize a width 100% element inside a scrolling element, to + // include the width of the scrollbar, while other browsers ensure the inner + // element is contained without forcing scrolling + browser.bScrollOversize = inner[0].offsetWidth === 100 && outer[0].clientWidth !== 100; + + // In rtl text layout, some browsers (most, but not all) will place the + // scrollbar on the left, rather than the right. + browser.bScrollbarLeft = Math.round( inner.offset().left ) !== 1; + + // IE8- don't provide height and width for getBoundingClientRect + browser.bBounding = n[0].getBoundingClientRect().width ? true : false; + + n.remove(); + } + + $.extend( settings.oBrowser, DataTable.__browser ); + settings.oScroll.iBarWidth = DataTable.__browser.barWidth; + } + + + /** + * Array.prototype reduce[Right] method, used for browsers which don't support + * JS 1.6. Done this way to reduce code size, since we iterate either way + * @param {object} settings dataTables settings object + * @memberof DataTable#oApi + */ + function _fnReduce ( that, fn, init, start, end, inc ) + { + var + i = start, + value, + isSet = false; + + if ( init !== undefined ) { + value = init; + isSet = true; + } + + while ( i !== end ) { + if ( ! that.hasOwnProperty(i) ) { + continue; + } + + value = isSet ? + fn( value, that[i], i, that ) : + that[i]; + + isSet = true; + i += inc; + } + + return value; + } + + /** + * Add a column to the list used for the table with default values + * @param {object} oSettings dataTables settings object + * @param {node} nTh The th element for this column + * @memberof DataTable#oApi + */ + function _fnAddColumn( oSettings, nTh ) + { + // Add column to aoColumns array + var oDefaults = DataTable.defaults.column; + var iCol = oSettings.aoColumns.length; + var oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, { + "nTh": nTh ? nTh : document.createElement('th'), + "sTitle": oDefaults.sTitle ? oDefaults.sTitle : nTh ? nTh.innerHTML : '', + "aDataSort": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol], + "mData": oDefaults.mData ? oDefaults.mData : iCol, + idx: iCol + } ); + oSettings.aoColumns.push( oCol ); + + // Add search object for column specific search. Note that the `searchCols[ iCol ]` + // passed into extend can be undefined. This allows the user to give a default + // with only some of the parameters defined, and also not give a default + var searchCols = oSettings.aoPreSearchCols; + searchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch, searchCols[ iCol ] ); + + // Use the default column options function to initialise classes etc + _fnColumnOptions( oSettings, iCol, $(nTh).data() ); + } + + + /** + * Apply options for a column + * @param {object} oSettings dataTables settings object + * @param {int} iCol column index to consider + * @param {object} oOptions object with sType, bVisible and bSearchable etc + * @memberof DataTable#oApi + */ + function _fnColumnOptions( oSettings, iCol, oOptions ) + { + var oCol = oSettings.aoColumns[ iCol ]; + var oClasses = oSettings.oClasses; + var th = $(oCol.nTh); + + // Try to get width information from the DOM. We can't get it from CSS + // as we'd need to parse the CSS stylesheet. `width` option can override + if ( ! oCol.sWidthOrig ) { + // Width attribute + oCol.sWidthOrig = th.attr('width') || null; + + // Style attribute + var t = (th.attr('style') || '').match(/width:\s*(\d+[pxem%]+)/); + if ( t ) { + oCol.sWidthOrig = t[1]; + } + } + + /* User specified column options */ + if ( oOptions !== undefined && oOptions !== null ) + { + // Backwards compatibility + _fnCompatCols( oOptions ); + + // Map camel case parameters to their Hungarian counterparts + _fnCamelToHungarian( DataTable.defaults.column, oOptions ); + + /* Backwards compatibility for mDataProp */ + if ( oOptions.mDataProp !== undefined && !oOptions.mData ) + { + oOptions.mData = oOptions.mDataProp; + } + + if ( oOptions.sType ) + { + oCol._sManualType = oOptions.sType; + } + + // `class` is a reserved word in Javascript, so we need to provide + // the ability to use a valid name for the camel case input + if ( oOptions.className && ! oOptions.sClass ) + { + oOptions.sClass = oOptions.className; + } + if ( oOptions.sClass ) { + th.addClass( oOptions.sClass ); + } + + $.extend( oCol, oOptions ); + _fnMap( oCol, oOptions, "sWidth", "sWidthOrig" ); + + /* iDataSort to be applied (backwards compatibility), but aDataSort will take + * priority if defined + */ + if ( oOptions.iDataSort !== undefined ) + { + oCol.aDataSort = [ oOptions.iDataSort ]; + } + _fnMap( oCol, oOptions, "aDataSort" ); + } + + /* Cache the data get and set functions for speed */ + var mDataSrc = oCol.mData; + var mData = _fnGetObjectDataFn( mDataSrc ); + var mRender = oCol.mRender ? _fnGetObjectDataFn( oCol.mRender ) : null; + + var attrTest = function( src ) { + return typeof src === 'string' && src.indexOf('@') !== -1; + }; + oCol._bAttrSrc = $.isPlainObject( mDataSrc ) && ( + attrTest(mDataSrc.sort) || attrTest(mDataSrc.type) || attrTest(mDataSrc.filter) + ); + oCol._setter = null; + + oCol.fnGetData = function (rowData, type, meta) { + var innerData = mData( rowData, type, undefined, meta ); + + return mRender && type ? + mRender( innerData, type, rowData, meta ) : + innerData; + }; + oCol.fnSetData = function ( rowData, val, meta ) { + return _fnSetObjectDataFn( mDataSrc )( rowData, val, meta ); + }; + + // Indicate if DataTables should read DOM data as an object or array + // Used in _fnGetRowElements + if ( typeof mDataSrc !== 'number' ) { + oSettings._rowReadObject = true; + } + + /* Feature sorting overrides column specific when off */ + if ( !oSettings.oFeatures.bSort ) + { + oCol.bSortable = false; + th.addClass( oClasses.sSortableNone ); // Have to add class here as order event isn't called + } + + /* Check that the class assignment is correct for sorting */ + var bAsc = $.inArray('asc', oCol.asSorting) !== -1; + var bDesc = $.inArray('desc', oCol.asSorting) !== -1; + if ( !oCol.bSortable || (!bAsc && !bDesc) ) + { + oCol.sSortingClass = oClasses.sSortableNone; + oCol.sSortingClassJUI = ""; + } + else if ( bAsc && !bDesc ) + { + oCol.sSortingClass = oClasses.sSortableAsc; + oCol.sSortingClassJUI = oClasses.sSortJUIAscAllowed; + } + else if ( !bAsc && bDesc ) + { + oCol.sSortingClass = oClasses.sSortableDesc; + oCol.sSortingClassJUI = oClasses.sSortJUIDescAllowed; + } + else + { + oCol.sSortingClass = oClasses.sSortable; + oCol.sSortingClassJUI = oClasses.sSortJUI; + } + } + + + /** + * Adjust the table column widths for new data. Note: you would probably want to + * do a redraw after calling this function! + * @param {object} settings dataTables settings object + * @memberof DataTable#oApi + */ + function _fnAdjustColumnSizing ( settings ) + { + /* Not interested in doing column width calculation if auto-width is disabled */ + if ( settings.oFeatures.bAutoWidth !== false ) + { + var columns = settings.aoColumns; + + _fnCalculateColumnWidths( settings ); + for ( var i=0 , iLen=columns.length ; i