Showing preview only (9,626K chars total). Download the full file or copy to clipboard to get everything.
Repository: Guezone/SECMON
Branch: master
Commit: 04915cc21f0e
Files: 282
Total size: 9.1 MB
Directory structure:
gitextract_dmivgmii/
├── .gitattributes
├── .gitignore
├── .gitlab-ci.yml
├── DOCS.md
├── Dockerfile
├── LICENSE
├── README.md
├── SECURITY.md
├── cve_poller.py
├── cve_template.html
├── cve_updater.py
├── docker/
│ ├── install.py
│ ├── secmon-ci.conf
│ └── secmon.conf
├── requirements.txt
├── rss_poller.py
├── rss_template.html
├── secmon.py
├── secmon.wsgi
├── secmon_lib.py
├── secmon_monitor.py
├── secmon_web.py
├── setup.py
├── static/
│ ├── css/
│ │ ├── dataTables.bootstrap.css
│ │ ├── main.css
│ │ ├── main2.css
│ │ ├── morris.css
│ │ ├── mycss.css
│ │ ├── sb-admin-2.css
│ │ ├── site.css
│ │ ├── timeline.css
│ │ ├── util.css
│ │ └── util2.css
│ ├── fonts/
│ │ ├── font-awesome-4.7.0/
│ │ │ ├── HELP-US-OUT.txt
│ │ │ ├── css/
│ │ │ │ └── font-awesome.css
│ │ │ ├── fonts/
│ │ │ │ └── FontAwesome.otf
│ │ │ ├── less/
│ │ │ │ ├── animated.less
│ │ │ │ ├── bordered-pulled.less
│ │ │ │ ├── core.less
│ │ │ │ ├── fixed-width.less
│ │ │ │ ├── font-awesome.less
│ │ │ │ ├── icons.less
│ │ │ │ ├── larger.less
│ │ │ │ ├── list.less
│ │ │ │ ├── mixins.less
│ │ │ │ ├── path.less
│ │ │ │ ├── rotated-flipped.less
│ │ │ │ ├── screen-reader.less
│ │ │ │ ├── stacked.less
│ │ │ │ └── variables.less
│ │ │ └── scss/
│ │ │ ├── _animated.scss
│ │ │ ├── _bordered-pulled.scss
│ │ │ ├── _core.scss
│ │ │ ├── _fixed-width.scss
│ │ │ ├── _icons.scss
│ │ │ ├── _larger.scss
│ │ │ ├── _list.scss
│ │ │ ├── _mixins.scss
│ │ │ ├── _path.scss
│ │ │ ├── _rotated-flipped.scss
│ │ │ ├── _screen-reader.scss
│ │ │ ├── _stacked.scss
│ │ │ ├── _variables.scss
│ │ │ └── font-awesome.scss
│ │ ├── montserrat/
│ │ │ └── OFL.txt
│ │ └── raleway/
│ │ └── OFL.txt
│ ├── js/
│ │ ├── demo/
│ │ │ ├── chart-area-demo.js
│ │ │ ├── chart-bar-demo.js
│ │ │ ├── chart-pie-demo.js
│ │ │ └── datatables-demo.js
│ │ ├── main.js
│ │ └── sb-admin-2.js
│ ├── scss/
│ │ ├── _buttons.scss
│ │ ├── _cards.scss
│ │ ├── _charts.scss
│ │ ├── _dropdowns.scss
│ │ ├── _error.scss
│ │ ├── _footer.scss
│ │ ├── _global.scss
│ │ ├── _login.scss
│ │ ├── _mixins.scss
│ │ ├── _navs.scss
│ │ ├── _utilities.scss
│ │ ├── _variables.scss
│ │ ├── navs/
│ │ │ ├── _global.scss
│ │ │ ├── _sidebar.scss
│ │ │ └── _topbar.scss
│ │ ├── sb-admin-2.scss
│ │ └── utilities/
│ │ ├── _animation.scss
│ │ ├── _background.scss
│ │ ├── _border.scss
│ │ ├── _display.scss
│ │ ├── _progress.scss
│ │ ├── _rotate.scss
│ │ └── _text.scss
│ └── vendor/
│ ├── animate/
│ │ └── animate.css
│ ├── bootstrap/
│ │ ├── css/
│ │ │ ├── bootstrap-grid.css
│ │ │ ├── bootstrap-reboot.css
│ │ │ └── bootstrap.css
│ │ ├── js/
│ │ │ ├── bootstrap.bundle.js
│ │ │ ├── bootstrap.js
│ │ │ ├── popper.js
│ │ │ └── tooltip.js
│ │ └── scss/
│ │ ├── _alert.scss
│ │ ├── _badge.scss
│ │ ├── _breadcrumb.scss
│ │ ├── _button-group.scss
│ │ ├── _buttons.scss
│ │ ├── _card.scss
│ │ ├── _carousel.scss
│ │ ├── _close.scss
│ │ ├── _code.scss
│ │ ├── _custom-forms.scss
│ │ ├── _dropdown.scss
│ │ ├── _forms.scss
│ │ ├── _functions.scss
│ │ ├── _grid.scss
│ │ ├── _images.scss
│ │ ├── _input-group.scss
│ │ ├── _jumbotron.scss
│ │ ├── _list-group.scss
│ │ ├── _media.scss
│ │ ├── _mixins.scss
│ │ ├── _modal.scss
│ │ ├── _nav.scss
│ │ ├── _navbar.scss
│ │ ├── _pagination.scss
│ │ ├── _popover.scss
│ │ ├── _print.scss
│ │ ├── _progress.scss
│ │ ├── _reboot.scss
│ │ ├── _root.scss
│ │ ├── _spinners.scss
│ │ ├── _tables.scss
│ │ ├── _toasts.scss
│ │ ├── _tooltip.scss
│ │ ├── _transitions.scss
│ │ ├── _type.scss
│ │ ├── _utilities.scss
│ │ ├── _variables.scss
│ │ ├── bootstrap-grid.scss
│ │ ├── bootstrap-reboot.scss
│ │ ├── bootstrap.scss
│ │ ├── mixins/
│ │ │ ├── _alert.scss
│ │ │ ├── _background-variant.scss
│ │ │ ├── _badge.scss
│ │ │ ├── _border-radius.scss
│ │ │ ├── _box-shadow.scss
│ │ │ ├── _breakpoints.scss
│ │ │ ├── _buttons.scss
│ │ │ ├── _caret.scss
│ │ │ ├── _clearfix.scss
│ │ │ ├── _deprecate.scss
│ │ │ ├── _float.scss
│ │ │ ├── _forms.scss
│ │ │ ├── _gradients.scss
│ │ │ ├── _grid-framework.scss
│ │ │ ├── _grid.scss
│ │ │ ├── _hover.scss
│ │ │ ├── _image.scss
│ │ │ ├── _list-group.scss
│ │ │ ├── _lists.scss
│ │ │ ├── _nav-divider.scss
│ │ │ ├── _pagination.scss
│ │ │ ├── _reset-text.scss
│ │ │ ├── _resize.scss
│ │ │ ├── _screen-reader.scss
│ │ │ ├── _size.scss
│ │ │ ├── _table-row.scss
│ │ │ ├── _text-emphasis.scss
│ │ │ ├── _text-hide.scss
│ │ │ ├── _text-truncate.scss
│ │ │ ├── _transition.scss
│ │ │ └── _visibility.scss
│ │ ├── utilities/
│ │ │ ├── _align.scss
│ │ │ ├── _background.scss
│ │ │ ├── _borders.scss
│ │ │ ├── _clearfix.scss
│ │ │ ├── _display.scss
│ │ │ ├── _embed.scss
│ │ │ ├── _flex.scss
│ │ │ ├── _float.scss
│ │ │ ├── _interactions.scss
│ │ │ ├── _overflow.scss
│ │ │ ├── _position.scss
│ │ │ ├── _screenreaders.scss
│ │ │ ├── _shadows.scss
│ │ │ ├── _sizing.scss
│ │ │ ├── _spacing.scss
│ │ │ ├── _stretched-link.scss
│ │ │ ├── _text.scss
│ │ │ └── _visibility.scss
│ │ └── vendor/
│ │ └── _rfs.scss
│ ├── chart.js/
│ │ ├── Chart.bundle.js
│ │ └── Chart.js
│ ├── css-hamburgers/
│ │ └── hamburgers.css
│ ├── datatables/
│ │ ├── dataTables.bootstrap4.css
│ │ ├── dataTables.bootstrap4.js
│ │ └── jquery.dataTables.js
│ ├── fontawesome-free/
│ │ ├── LICENSE.txt
│ │ ├── css/
│ │ │ ├── all.css
│ │ │ ├── brands.css
│ │ │ ├── fontawesome.css
│ │ │ ├── regular.css
│ │ │ ├── solid.css
│ │ │ ├── svg-with-js.css
│ │ │ └── v4-shims.css
│ │ ├── js/
│ │ │ ├── all.js
│ │ │ ├── brands.js
│ │ │ ├── conflict-detection.js
│ │ │ ├── fontawesome.js
│ │ │ ├── regular.js
│ │ │ ├── solid.js
│ │ │ └── v4-shims.js
│ │ ├── less/
│ │ │ ├── _animated.less
│ │ │ ├── _bordered-pulled.less
│ │ │ ├── _core.less
│ │ │ ├── _fixed-width.less
│ │ │ ├── _icons.less
│ │ │ ├── _larger.less
│ │ │ ├── _list.less
│ │ │ ├── _mixins.less
│ │ │ ├── _rotated-flipped.less
│ │ │ ├── _screen-reader.less
│ │ │ ├── _shims.less
│ │ │ ├── _stacked.less
│ │ │ ├── _variables.less
│ │ │ ├── brands.less
│ │ │ ├── fontawesome.less
│ │ │ ├── regular.less
│ │ │ ├── solid.less
│ │ │ └── v4-shims.less
│ │ ├── metadata/
│ │ │ ├── categories.yml
│ │ │ ├── icons.yml
│ │ │ ├── shims.yml
│ │ │ └── sponsors.yml
│ │ ├── package.json
│ │ └── scss/
│ │ ├── _animated.scss
│ │ ├── _bordered-pulled.scss
│ │ ├── _core.scss
│ │ ├── _fixed-width.scss
│ │ ├── _icons.scss
│ │ ├── _larger.scss
│ │ ├── _list.scss
│ │ ├── _mixins.scss
│ │ ├── _rotated-flipped.scss
│ │ ├── _screen-reader.scss
│ │ ├── _shims.scss
│ │ ├── _stacked.scss
│ │ ├── _variables.scss
│ │ ├── brands.scss
│ │ ├── fontawesome.scss
│ │ ├── regular.scss
│ │ ├── solid.scss
│ │ └── v4-shims.scss
│ ├── jquery/
│ │ ├── jquery.js
│ │ └── jquery.slim.js
│ ├── jquery-easing/
│ │ ├── jquery.easing.compatibility.js
│ │ └── jquery.easing.js
│ └── select2/
│ ├── select2.css
│ └── select2.js
└── templates/
├── about.html
├── base.html
├── by-product-vulns.html
├── config.html
├── cve-alerts.html
├── cve-updates.html
├── cyber-threats.html
├── errors.html
├── exploits.html
├── home.html
├── login.html
├── logs.html
├── product-card.html
├── product-mgmt.html
├── reports.html
├── result.html
├── rss-news.html
├── search.html
├── settings.html
├── tasks.html
└── vuln-mgmt.html
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitattributes
================================================
# Auto detect text files and perform LF normalization
* text=auto
================================================
FILE: .gitignore
================================================
SECMON-CVE-Report.xlsx
secmon.db
logs.txt
__pycache__/
stats.py
test.py
certs/
================================================
FILE: .gitlab-ci.yml
================================================
variables:
PRIVATE_REGISTRY_PASSWD: $PRIVATE_REGISTRY_PASSWD
PRIVATE_REGISTRY_USERNAME: $PRIVATE_REGISTRY_USERNAME
PRIVATE_REGISTRY_URL: $PRIVATE_REGISTRY_URL
DOCKER_HUB_PASSWD: $DOCKER_HUB_PASSWD
DOCKER_HUB_USERNAME: $DOCKER_HUB_USERNAME
FQDN: $SECMON_FQDN
SENDER: $SECMON_SENDER
SMTP_PASSWD: $SECMON_SMTP_PASSWD
SMTP_SRV: $SECMON_SMTP_SRV
GITHUB_USERNAME: $SECMON_GITHUB_USERNAME
GITHUB_API_KEY: $SECMON_GITHUB_API_KEY
WEB_USERNAME: $SECMON_WEB_USERNAME
WEB_PASSWD: $SECMON_WEB_PASSWD
stages:
- build
- vuln_scan
- malware_scan
- test
- release_image
Build-Image:
stage: build
script:
- docker login $PRIVATE_REGISTRY_URL -u $PRIVATE_REGISTRY_USERNAME -p $PRIVATE_REGISTRY_PASSWD
- docker pull $SECMON_REGISTRY_IMAGE_WITHOUT_TAG:latest || true
- docker build . -t $SECMON_REGISTRY_IMAGE_WITHOUT_TAG:$CI_COMMIT_REF_SLUG
- docker push $SECMON_REGISTRY_IMAGE_WITHOUT_TAG:$CI_COMMIT_REF_SLUG
allow_failure: false
Vuln-Scan:
stage: vuln_scan
variables:
ANCHORE_CLI_URL: "http://anchore-engine:8228/v1"
GIT_STRATEGY: none
image: docker.io/anchore/inline-scan:latest
services:
- name: docker.io/anchore/inline-scan:latest
alias: anchore-engine
command: ["start"]
script:
- anchore-cli system wait
- anchore-cli registry add $PRIVATE_REGISTRY_URL gitlab-ci-token "$CI_JOB_TOKEN" --skip-validate --insecure
- anchore-cli image add $SECMON_REGISTRY_IMAGE_WITHOUT_TAG:$CI_COMMIT_REF_SLUG
- anchore-cli image wait $SECMON_REGISTRY_IMAGE_WITHOUT_TAG:$CI_COMMIT_REF_SLUG
- anchore-cli image vuln $SECMON_REGISTRY_IMAGE_WITHOUT_TAG:$CI_COMMIT_REF_SLUG all
allow_failure: true
Malware-Scan:
stage: malware_scan
script:
- docker stop secmontest && docker rm secmontest || true
- docker login $PRIVATE_REGISTRY_URL -u $PRIVATE_REGISTRY_USERNAME -p $PRIVATE_REGISTRY_PASSWD
- docker run -i -t --name secmontest -d $SECMON_REGISTRY_IMAGE_WITHOUT_TAG:$CI_COMMIT_REF_SLUG
- docker cp . secmontest:/var/www/secmon
- docker exec secmontest bash -c 'apt update && apt install -y clamav && freshclam'
- docker exec secmontest bash -c 'cd /var/www/secmon ; python3 -c "import secmon_lib" ; python3 -c "from secmon_web import *" 2>/dev/null' || true
- docker exec secmontest clamscan --remove --infected -r /var/www /home /usr /etc /mnt /media /srv | tee scan-results.txt
- docker stop secmontest && docker rm secmontest
allow_failure: false
Test:
stage: test
script:
- docker stop secmontest && docker rm secmontest || true
- docker login $PRIVATE_REGISTRY_URL -u $PRIVATE_REGISTRY_USERNAME -p $PRIVATE_REGISTRY_PASSWD
- docker run -i -t --name secmontest -p 4443 -e SENDER=$SENDER -e GITHUB_USERNAME=$GITHUB_USERNAME -e GITHUB_API_KEY=$GITHUB_API_KEY -e WEB_USERNAME=$WEB_USERNAME -e WEB_PASSWD=$WEB_PASSWD -e FQDN=$FQDN -e SMTP_PASSWD=$SMTP_PASSWD -d $SECMON_REGISTRY_IMAGE_WITHOUT_TAG:$CI_COMMIT_REF_SLUG
- docker cp . secmontest:/var/www/secmon
- docker exec secmontest openssl req -newkey rsa:4096 -x509 -subj "/C=FR/ST=France/L=Paris/O=Test/CN=$FQDN" -sha512 -days 3650 -nodes -out /etc/ssl/secmon/secmon.crt -keyout /etc/ssl/secmon/secmon.key
- docker exec secmontest python3 /var/www/secmon/setup.py -login $SENDER -p $SMTP_PASSWD -server $SMTP_SRV -port '587' -tls yes -lang fr -sender $SENDER -r $SENDER -accept true -github_username $GITHUB_USERNAME -github_api_key $GITHUB_API_KEY -username $WEB_USERNAME -password $WEB_PASSWD
- docker exec secmontest nohup python3 /var/www/secmon/secmon.py >/dev/null 2>&1 &
- docker exec secmontest nohup python3 /var/www/secmon/cve_updater.py >/dev/null 2>&1 &
- docker exec secmontest cp /var/www/secmon/docker/secmon-ci.conf /etc/apache2/sites-enabled/secmon.conf
- docker exec secmontest chown -R www-data:www-data /var/www/secmon/
- docker exec secmontest chmod -R 744 /var/www/secmon/
- docker exec secmontest sed -i "s/{FQDN}/$FQDN/" /etc/apache2/sites-enabled/secmon.conf
- docker exec secmontest sed -i "s/Listen 443/Listen 4443/" /etc/apache2/ports.conf
- docker exec secmontest a2enmod ssl && docker exec secmontest service apache2 restart
- docker exec secmontest apt install -y wget
- docker exec secmontest wget -q -S -O - https://127.0.0.1:4443 --no-check-certificate | grep "SECMON - Login"
- docker stop secmontest && docker rm secmontest || true
allow_failure: false
Release-Image:
stage: release_image
script:
- docker login $PRIVATE_REGISTRY_URL -u $PRIVATE_REGISTRY_USERNAME -p $PRIVATE_REGISTRY_PASSWD
- docker tag $SECMON_REGISTRY_IMAGE_WITHOUT_TAG:$CI_COMMIT_REF_SLUG $SECMON_REGISTRY_IMAGE_WITHOUT_TAG:latest
- docker push $SECMON_REGISTRY_IMAGE_WITHOUT_TAG:latest
- docker login -u $DOCKER_HUB_USERNAME -p $DOCKER_HUB_PASSWD
- docker tag $SECMON_REGISTRY_IMAGE_WITHOUT_TAG:latest guezone/secmon:latest
- docker push guezone/secmon:latest
allow_failure: false
================================================
FILE: DOCS.md
================================================
# Table of contents
- [Table of contents](#table-of-contents)
- [Installation](#installation)
- [With docker](#with-docker)
- [Autosetup](#autosetup)
- [Automation](#automation)
- [Without docker](#without-docker)
- [Setup](#setup)
- [Automation](#automation-1)
- [Startup](#startup)
- [Configuration of the web service](#configuration-of-the-web-service)
- [Login](#login)
- [Configuration](#configuration)
- [Search products](#search-products)
- [Add your products](#add-your-products)
- [User interface](#user-interface)
- [CVE Module](#cve-module)
- [RSS Module](#rss-module)
- [Settings](#settings)
- [Upgrade](#upgrade)
- [Logging](#logging)
- [Useful logs](#useful-logs)
- [Error logs](#error-logs)
# Installation
Before installation, you must have drawn up :
- The list of products present in your infrastructure by their common name without version (ex: ```Apache;Microsoft Windows;CentOS```)
- The list of CPE product identifiers present on your infrastructure (ex: ```cpe:2.3:o:microsoft:windows_server_2008:r2:sp1:*:*:*:x64:*;cpe:2.3:o:apple:mac_os:-:*:*:*:*:*```)
**Note 1** : You can also upload a CSV file with one line per product via the web interface but I advise you to put the list at the installation.
**Note 2** : Product names (keywords) should not be too succinct (e.g. prefer to use 'Microsoft Office' instead of 'Office'). This could avoid false positives during alerts.
You will be able to search and add new products after installation via the web UI.
## With docker (recommanded)
With the docker installation, everything is automated. The script creates a self-signed certificate if you wish and configures apache. Obviously, you can change the configuration according to your needs.
The installation with Docker allows via a volume (-v option) to easily update SECMON with Git.
To update it, you will have to :
- Go to the folder where SECMON was cloned at installation
- Do a git pull to get the changes
The files will then be modified directly in your SECMON container.
### Autosetup
```bash
sudo git clone https://github.com/Guezone/SECMON && cd SECMON && mkdir certs && PWD=$(pwd)
sudo docker build . -t secmon:latest
sudo docker network create --driver=bridge --subnet=10.10.10.0/24 --gateway=10.10.10.254 SECMON_NET
sudo docker run -i -t --hostname secmonsrv --ip 10.10.10.100 --name secmon-srv -v $PWD/:/var/www/secmon -v $PWD/certs:/etc/ssl/secmon --network SECMON_NET --expose 80 --expose 443 -d secmon:latest
sudo docker exec -it secmon-srv python3 /var/www/secmon/docker/install.py
```
```
| SECMON - DockerAutoInstall |
1. Certificate :
Note 1 : You can delete this self signed cert and put your CA signed cert after install.
Enter the FQDN of the web server :secmon.demo.net
Note 2 : Don't forget to enter a good value for CN (FQDN of your server)
Generating a RSA private key
........................................................................++++
...................................................................................................................++++
writing new private key to '/etc/ssl/secmon/secmon.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:FR
State or Province Name (full name) [Some-State]:IDF
Locality Name (eg, city) []:Paris
Organization Name (eg, company) [Internet Widgits Pty Ltd]:SecmonDemo
Organizational Unit Name (eg, section) []:X
Common Name (e.g. server FQDN or YOUR name) []:secmon.demo.net
Email Address []:XXXXXXXXXXX@XXXX.XX
Your certificate is available on /etc/ssl/secmon !
----------------------------------------------------------------------------------------------------------------------
2. SECMON Install :
Sender email address : sender@mail.com
Sender email account password :XXXXXXXXXXXXXXXXXXXX
SMTP Server FQDN or IP :XXXX.XXXX.XXXX
SMTP used port :587
Using TLS SMTP auth ? (yes/no) :yes
Language (en/fr) :fr
SECMON email receivers (single or many seperated by ;):receiver1@mail.com;receiver2@mail.com
------------------------------------
SECMON setup script - Version 1.0.0
------------------------------------
SECMON is licensed by CC BY-NC-SA 4.0 license. Do you accept the terms of the license? (y/Y;n/N) : y
Do you want to use a Github API for exploit retrieval (y/Y;n/N) : y
Please enter your Github username : XXXXXXXXXXX
Please enter your Github API Token : XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Enter the username that can be used on the Web UI : demo_user
Enter the password (please choose a strong password !) : XXXXXXXX
Confirm the password : XXXXXXXX
RSS news database recording in progress...
Successful build database.
Please wait. A test message to receiver1@mail.com will be sent to test your configuration.
Please wait. A test message to receiver2@mail.com will be sent to test your configuration.
SECMON is now ready. Execute secmon.py now and automate it.
Executing secmon in background...
Executing cve_updater in background...
SECMON is successfully installed and configured !
----------------------------------------------------------------------------------------------------------------------
3. Apache configuration :
Considering dependency setenvif for ssl:
Module setenvif already enabled
Considering dependency mime for ssl:
Module mime already enabled
Considering dependency socache_shmcb for ssl:
Enabling module socache_shmcb.
Enabling module ssl.
See /usr/share/doc/apache2/README.Debian.gz on how to configure SSL and create self-signed certificates.
To activate the new configuration, you need to run:
service apache2 restart
[ ok ] Restarting Apache httpd web server: apache2.
Apache is successfully configured !
You can now access the web interface at the following address: https://secmon.demo.net
----------------------------------------------------------------------------------------------------------------------
```
### Automation
Edit the **host crontab** with **vi /etc/crontab** command, for example like this :
```bash
0 * * * * root docker exec secmon-srv python3 /var/www/secmon/secmon.py >> /var/log/secmon 2>&1
0 6 * * * root docker exec secmon-srv python3 /var/www/secmon/cve_updater.py >> /var/log/secmon-updates 2>&1
@reboot root docker start secmon-srv
@reboot root docker exec secmon-srv service apache2 start
@reboot root docker exec secmon-srv service ssh start
```
This configuration automates the retrieval of new CVE (and news) every 20 minutes and an update of the scores and associated products every day at 6am.
Now, you can login to SECMON with a giving URL.
## Without docker
### Setup
```bash
sudo apt update
sudo apt install -y python3 python3-pip apache2 libapache2-mod-wsgi-py3 git
sudo git clone https://github.com/Guezone/SECMON
cd SECMON
sudo pip3 install -r requirements.txt
sudo rm -Rf /var/www/html
sudo mkdir /var/www/secmon && sudo cp -r * /var/www/secmon/ && cd /var/www/secmon/
sudo python3 setup.py -sender sender@mail.com -p 'XXXXXXXXXXXXXXXX' -login [your SMTP login, often email address] -server srv.mail.com -port 587 -tls yes -lang fr -r 'receiver1@mail.com;receiver2@mail.com'
```
**Note :** Since a few time, the product list entry is only on web UI after install.
**Output :**
```bash
------------------------------------
SECMON setup script - Version 1.0.0
------------------------------------
SECMON is licensed by CC BY-NC-SA 4.0 license. Do you accept the terms of the license? (y/Y;n/N) : y
Let's go to add your products list for which you want to check the new CVEs.
Of course, you can add more with the web interface after installation !
Do you want to use a Github API for exploit retrieval (y/Y;n/N) : y
Please enter your Github username : XXXXXXXXXXX
Please enter your Github API Token : XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Enter the username that can be used on the Web UI : demo_user
Enter the password (please choose a strong password !) : XXXXXXXX
Confirm the password : XXXXXXXX
RSS news database recording in progress...
Successful build database.
Please wait. A test message to receiver1@mail.com will be sent to test your configuration.
Please wait. A test message to receiver2@mail.com will be sent to test your configuration.
SECMON is now ready. Execute secmon.py now and automate it.
```
### Automation
Edit your crontab with **sudo vi /etc/crontab** command, for example like this :
```bash
0 * * * * root python3 /var/www/secmon/secmon.py >> /var/log/secmon 2>&1
0 6 * * * root python3 /var/www/secmon/cve_updater.py >> /var/log/secmon-updates 2>&1
```
This configuration automates the retrieval of new CVE (and news) every 60 minutes and an update of the scores and associated products every day at 6am.
### Startup
Launch the main script of the application :
```bash
sudo python3 secmon.py
Cloning exploit-database repository <-- At the first launch only, there is a download of the exploit-db.com exploit database.
Clonage dans 'exploit-database'...
remote: Enumerating objects: 194, done.
remote: Counting objects: 100% (194/194), done.
remote: Compressing objects: 100% (163/163), done.
remote: Total 135299 (delta 72), reused 139 (delta 31), pack-reused 135105
Réception d'objets: 100% (135299/135299), 151.14 MiB | 3.94 MiB/s, fait.
Résolution des deltas: 100% (85326/85326), fait.
Extraction des fichiers: 100% (44380/44380), fait.
------------ CVE Module ------------
Starting at : 30/11/2020 23:09:30
------------------------------------
Configuration is good.
------------------------------------
Polling NVD RSS feed (keyword based search).
No new CVE matched with your keyword list.
------------------------------------
Polling NVD related to your product list (CPE based search).
No new CVE related to your (CPE) product list
------------------------------------
Finished at : 30/11/2020 23:09:38
------------------------------------
------------ RSS Module ------------
Starting at : 30/11/2020 23:09:38
------------------------------------
Configuration is good.
------------------------------------
No news. Goodbye.
------------------------------------
Finished at : 30/11/2020 23:09:44
------------------------------------
```
At this step, SECMON is properly configured and you can receive alerts about new CVE that affect your products as well as new "cyber" news.
You now need to update the list of available exploits for each CVE (exploit-db and Github) as well as your high security risk products.
**Note :** "high security risk" products are those that have :
- Critical and high vulnerabilities (based on the CVSS 3.0 score)
- Vulnerabilities where there are known exploits (Github or Exploit-DB)
To make this update :
```bash
sudo python3 cve_updater.py
------------ CVE Module - Update ------------
Starting at : 30/11/2020 23:34:06
---------------------------------------------
Refreshing exploit-database repo with latest exploits
From https://github.com/offensive-security/exploit-database
* branch master -> FETCH_HEAD
Already up to date.
Refreshing EDBID-CVE mapping
100% (43828 of 43828) |###############################################################################################| Elapsed Time: 0:00:00 Time: 0:00:00
Exploit found for CVE-2021-3156 from Exploit-DB
Exploit found for CVE-2014-8380 from Exploit-DB
Search Github Exploit for registered CVE...
Exploit found for CVE-2020-1590 from Github
Updating high risk product list....
New critical product : Microsoft Windows Server 2008 R2
Updating affected products and CVSS score related to your CVE list...
No CVE have been updated.
---------------------------------------------
Finished at : 30/11/2020 23:52:24
---------------------------------------------
```
**Note :** This operation can take a few minutes to a few hours.
### Configuration of the web service
You must then delete the Apache sites configured by default :
```bash
sudo rm /etc/apache2/sites-enabled/*
sudo rm /etc/apache2/sites-available/*
sudo a2enmod wsgi
sudo a2enmod ssl
```
Then, you have to create a new configuration file dedicated to SECMON (in ```/etc/apache2/sites-available/secmon.conf```) :
Here is an example of configuration for a "secure" basic configuration :
```bash
ServerName secmon.corp.net
<VirtualHost *:80>
ServerAdmin admin@mail.com
ServerName secmon.corp.net
ServerAlias www.secmon.corp.net
DocumentRoot /var/www/secmon
Redirect permanent / https://secmon.corp.net
<Directory /var/www/secmon>
WSGIProcessGroup secmon_web
WSGIPassAuthorization On
WSGIApplicationGroup %{GLOBAL}
Order deny,allow
Allow from all
</Directory>
ServerSignature off
ErrorLog ${APACHE_LOG_DIR}/error_secmon.log
CustomLog ${APACHE_LOG_DIR}/access_secmon.log combined
</VirtualHost>
<VirtualHost *:443>
WSGIScriptAlias / /var/www/secmon/secmon.wsgi
WSGIDaemonProcess secmon_web
DocumentRoot /var/www/secmon
ServerName secmon.corp.net
ServerAlias www.secmon.corp.net
<Directory /var/www/secmon>
WSGIProcessGroup secmon_web
WSGIPassAuthorization On
WSGIApplicationGroup %{GLOBAL}
Order deny,allow
Allow from all
</Directory>
ServerSignature Off
LogLevel info
ErrorLog ${APACHE_LOG_DIR}/error_secmon.log
CustomLog ${APACHE_LOG_DIR}/access_secmon.log combined
SSLProtocol -all +TLSv1.2 +TLSv1.3
SSLEngine on
SSLCertificateFile PATH/YOUR_CERT.crt
SSLCertificateKeyFile PATH/YOUR_PRIVATE_KEY.key
</VirtualHost>
```
**Note :** You can use a self-signed certificate or a certificate signed by a known CA. This configuration must be changed according to your settings and is an example.
```bash
sudo a2ensite secmon
Enabling site secmon.
To activate the new configuration, you need to run:
systemctl reload apache2
sudo systemctl reload apache2
cd /var/www/secmon && sudo chown -R www-data:www-data .
sudo chmod -R 744 .
```
# Login
Now you will be able to connect to the Web UI with the credentials entered during installation :

SECMON is now fully ready to use ! It's time for a ☕.
# Configuration
## Search products
SECMON accepts the "products" to be supervised in keywords or in CPE (Common Platform Enumeration).
The keywords are used when the CVE do not have a CPE filled in and this is particularly the case when it has just been published.
In SECMON's WEB UI, go to the **Settings -> Product management** tab. You have at your disposal a search section in order to find the CPE references by their common name (example for Windows Server 2019) :

CPEs allow greater accuracy down to the product version level. CPEs can only be found when they have been provided by the publisher, which is not always the case. You can still use previous versions to determine this.
Example :
```
The CPE search for Apache 2.4.46 does not find the correct CPE code but the CPE code for version 2.4.44 is "cpe: 2.3: a: apache: http_server: 2.4.44: *: *: *: *: *: *: * "
All you have to do is replace the correct fields with the correct version: "cpe: 2.3: a: apache: http_server: 2.4.46: *: *: *: *: *: *: *"
```
## Add your products
To add new products to your list, go to the **Settings -> Product management** tab then to the ** Manage product ** section. You then have the choice to add / delete a CPE or a keyword :

You can also import a list of products (CPE and keywords) into a CSV in the same tab. It must consist of a single command. Example file :
```csv
cpe:2.3:a:keepass:password_safe:*:*:*:*:*:*:*:*
cpe:2.3:o:microsoft:windows_10:2004:*:*:*:*:*:*:*
cpe:2.3:a:docker:docker:0.2.1:*:*:*:*:*:*:*
cpe:2.3:a:anydesk:anydesk:*:*:*:*:*:*:*:*
cpe:2.3:o:vmware:esxi:7.0:*:*:*:*:*:*:*
Microsoft Exchange
Microsoft Office
HPE
F5
BigIP
Extreme
```
**Note**: when you add a CPE reference, it may take several minutes or even several hours for all the CVEs to be recorded in the database. To follow the progress, go to the tab **Settings -> Tasks**. A good practice might be to set the keywords to match your CPE references ("Docker" as a keyword and "cpe:2.3:a:docker:docker:0.2.1:*:*:*:*:*:*"as a CPE).
## User interface
**Home**: dashboard allowing you to see the state of health of your fleet regarding vulnerabilities. Products with high security risks appear as well as the rate of corrected / read / unread vulnerabilities.
### CVE Module
**Search**: this page allows you to search for details about a CVE
**Vulnerability management**: this page allows you to put a stamp in order to know the status of the correction of your vulnerability. For better management, I encourage you to indicate when you became aware of a vulnerability and also when it is fixed. Once the alert has been sent by email, I also encourage you to check that the CVE concerns your product with the exact version. There may be false positives in particular on the search for CVE by keyword, you can also note the false on this page.
**Last CVE alerts**: this page allows you to view vulnerabilities by product and also to see the list of high risk products, ie those with exploitable vulnerabilities.
**Exploits**: allows you to search for exploits linked to a CVE and also to see the list of exploitable CVEs. The source of the information is based on Github and Exploit-DB.
**Last CVE updates**: Allows you to see if recent changes have been made to CVSS scores or affected products regarding your vulnerabilities.
### RSS Module
**Cybersecurity news**: this page allows you to view the latest information and articles identified by the tool.
### Settings
**Logs**: allows you to view the logs produced by the tool.
**Product management**: this page allows you to search for CPE references, add / remove products (keywords or CPE) to your list and display the list.
**SMTP Configuration**: allows you to change the SMTP configuration linked to sending CVE alerts or news.
**Tasks**: allows you to view the status of recent tasks which are heavy for SECMON. Today, only the addition of products appears here as it is a process that can be very long.
You can update your web UI password and also add users. To do this, click on the menu at the top right and then go to **Account settings**.
**Note** : It is currently impossible to reset passwords via a token and email as is usually the case.
# Upgrade
The installation of SECMON with Docker allows the use of a volume in order to have a "synchronisation" between the host and the container.
If you want to have the latest version of SECMON with the latest changes, go to the folder where SECMON was cloned (on the host) and run the following commands:
```
git pull origin
sudo chown -R www-data:www-data .
sudo chmod -R 744 .
sudo docker exec -it secmon-srv service apache2 restart
```
The files will be updated on the host side and in the container and SECMON will be updated.
If you are not using docker, you can do the same in the folder where the repository was cloned. However, you will need to copy the modified files to **/var/www/secmon** and also assign the correct rights. You will also have to restart the Apache service.
# Logging
## Useful logs
All useful SECMON logs are written to your **/var/www/secmon/logs.txt**. The format is not really standard but they are parsed automatically by Splunk for example.
Obviously, I encourage you to create alerts if you have a SIEM to manage critical vulnerabilities and high-risk products in your regular processes.
Here is an example of field extractions (Graylog compatible file):
**Note**: you can obviously reuse the **Grok patterns** contained in the file to extract fields on your log collection and analysis tools.
```json
{
"extractors": [
{
"title": "SECMON-Authentication-Extract",
"extractor_type": "grok",
"converters": [],
"order": 0,
"cursor_strategy": "cut",
"source_field": "message",
"target_field": "",
"extractor_config": {
"grok_pattern": "%{TIMESTAMP_ISO8601:timestamp} source_script=%{GREEDYDATA:script} server=\"%{IP:dst_ip}\" src_ip=\"%{IPV4:src_ip}\" username=\"%{USERNAME:username}\" auth_status=\"%{WORD:status}\" message=\"%{GREEDYDATA:msg}\""
},
"condition_type": "regex",
"condition_value": "auth_status"
},
{
"title": "SECMON-CVE-Extract",
"extractor_type": "grok",
"converters": [],
"order": 0,
"cursor_strategy": "cut",
"source_field": "message",
"target_field": "",
"extractor_config": {
"grok_pattern": "%{TIMESTAMP_ISO8601:timestamp} source_script=\"%{GREEDYDATA:script}\" server=\"%{IP:dst_ip}\" cve_id=\"%{GREEDYDATA:cve_id}\" type=\"%{WORD:type}\" matched_product=\"%{GREEDYDATA:matched_product}\" cvss_score=\"%{GREEDYDATA:cvss_score}\" severity=\"%{GREEDYDATA:severity}\" cve_date=\"%{GREEDYDATA:cve_date}\" cpes=\"%{GREEDYDATA:cpes}\" report=\"%{WORD:report}\" alert=\"%{WORD:alert}\" message=\"%{GREEDYDATA:msg}\""
},
"condition_type": "string",
"condition_value": "cve_id"
},
{
"title": "SECMON-Exploits-Extract",
"extractor_type": "grok",
"converters": [],
"order": 0,
"cursor_strategy": "cut",
"source_field": "message",
"target_field": "",
"extractor_config": {
"grok_pattern": "%{TIMESTAMP_ISO8601:timestamp} source_script=%{GREEDYDATA:script} server=\"%{IP:dst_ip}\" cve=\"%{GREEDYDATA:cve_id}\" exploit_source=\"%{GREEDYDATA:exploit_source}\" message=\"%{GREEDYDATA:msg}\""
},
"condition_type": "string",
"condition_value": "exploit"
},
{
"title": "SECMON-Tasks-Extract",
"extractor_type": "grok",
"converters": [],
"order": 0,
"cursor_strategy": "copy",
"source_field": "message",
"target_field": "",
"extractor_config": {
"grok_pattern": "%{TIMESTAMP_ISO8601:timestamp} source_script=%{GREEDYDATA:script} server=\"%{IP:dst_ip}\" task_id=\"%{INT:task_id}\" task_status=\"%{WORD:task_status}\" message=\"%{GREEDYDATA:msg}\""
},
"condition_type": "string",
"condition_value": "task_id"
},
{
"title": "SECMON-News-Extract",
"extractor_type": "grok",
"converters": [],
"order": 0,
"cursor_strategy": "cut",
"source_field": "message",
"target_field": "",
"extractor_config": {
"grok_pattern": "%{TIMESTAMP_ISO8601:timestamp} source_script=%{GREEDYDATA:script} server=\"%{IP:dst_ip}\" feed=\"%{GREEDYDATA:feed}\" feed_url=\"%{URI:feed_url}\" news_title=\"%{GREEDYDATA:news_title}\" news_url=\"%{URI:news_url}\" mail=\"%{WORD:mail}\""
},
"condition_type": "string",
"condition_value": "rss_poller"
},
{
"title": "SECMON-HighRiskProducts-Extract",
"extractor_type": "grok",
"converters": [],
"order": 0,
"cursor_strategy": "cut",
"source_field": "message",
"target_field": "",
"extractor_config": {
"grok_pattern": "%{TIMESTAMP_ISO8601:timestamp} source_script=%{GREEDYDATA:script} server=\"%{IP:dst_ip}\" cpe=\"%{GREEDYDATA:cpe}\" hname=\"%{GREEDYDATA:hname}\" message=\"%{GREEDYDATA:msg}\""
},
"condition_type": "string",
"condition_value": "A new critical product"
}
],
"version": "4.0.5"
}
```
## Error logs
The error logs generated by the pollers will be located where you redirect the standard output in your cron configuration.
Error logs related to your web interface will be available in the Apache error file (or other depending on your usage). The errors are normally formatted.
Feel free to file an issue on Github if you see an error.
================================================
FILE: Dockerfile
================================================
FROM debian:latest
MAINTAINER Aubin Custodio (Guezone)
RUN apt update && apt upgrade -y && apt install -y vim apache2 nano python3 git python3-pip libapache2-mod-wsgi-py3 net-tools dnsutils openssh-server openssl python3-dev libffi-dev
RUN service apache2 stop
RUN rm /etc/apache2/sites-enabled/* && rm /etc/apache2/sites-available/*
RUN mkdir /etc/ssl/secmon/ && mkdir /var/www/secmon/
COPY ./requirements.txt /tmp
RUN cd /tmp && pip3 install -r requirements.txt && rm -Rf /var/www/html
EXPOSE 80
EXPOSE 443
EXPOSE 22
================================================
FILE: LICENSE
================================================
Attribution-NonCommercial-ShareAlike 4.0 International
=======================================================================
Creative Commons Corporation ("Creative Commons") is not a law firm and
does not provide legal services or legal advice. Distribution of
Creative Commons public licenses does not create a lawyer-client or
other relationship. Creative Commons makes its licenses and related
information available on an "as-is" basis. Creative Commons gives no
warranties regarding its licenses, any material licensed under their
terms and conditions, or any related information. Creative Commons
disclaims all liability for damages resulting from their use to the
fullest extent possible.
Using Creative Commons Public Licenses
Creative Commons public licenses provide a standard set of terms and
conditions that creators and other rights holders may use to share
original works of authorship and other material subject to copyright
and certain other rights specified in the public license below. The
following considerations are for informational purposes only, are not
exhaustive, and do not form part of our licenses.
Considerations for licensors: Our public licenses are
intended for use by those authorized to give the public
permission to use material in ways otherwise restricted by
copyright and certain other rights. Our licenses are
irrevocable. Licensors should read and understand the terms
and conditions of the license they choose before applying it.
Licensors should also secure all rights necessary before
applying our licenses so that the public can reuse the
material as expected. Licensors should clearly mark any
material not subject to the license. This includes other CC-
licensed material, or material used under an exception or
limitation to copyright. More considerations for licensors:
wiki.creativecommons.org/Considerations_for_licensors
Considerations for the public: By using one of our public
licenses, a licensor grants the public permission to use the
licensed material under specified terms and conditions. If
the licensor's permission is not necessary for any reason--for
example, because of any applicable exception or limitation to
copyright--then that use is not regulated by the license. Our
licenses grant only permissions under copyright and certain
other rights that a licensor has authority to grant. Use of
the licensed material may still be restricted for other
reasons, including because others have copyright or other
rights in the material. A licensor may make special requests,
such as asking that all changes be marked or described.
Although not required by our licenses, you are encouraged to
respect those requests where reasonable. More considerations
for the public:
wiki.creativecommons.org/Considerations_for_licensees
=======================================================================
Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International
Public License
By exercising the Licensed Rights (defined below), You accept and agree
to be bound by the terms and conditions of this Creative Commons
Attribution-NonCommercial-ShareAlike 4.0 International Public License
("Public License"). To the extent this Public License may be
interpreted as a contract, You are granted the Licensed Rights in
consideration of Your acceptance of these terms and conditions, and the
Licensor grants You such rights in consideration of benefits the
Licensor receives from making the Licensed Material available under
these terms and conditions.
Section 1 -- Definitions.
a. Adapted Material means material subject to Copyright and Similar
Rights that is derived from or based upon the Licensed Material
and in which the Licensed Material is translated, altered,
arranged, transformed, or otherwise modified in a manner requiring
permission under the Copyright and Similar Rights held by the
Licensor. For purposes of this Public License, where the Licensed
Material is a musical work, performance, or sound recording,
Adapted Material is always produced where the Licensed Material is
synched in timed relation with a moving image.
b. Adapter's License means the license You apply to Your Copyright
and Similar Rights in Your contributions to Adapted Material in
accordance with the terms and conditions of this Public License.
c. BY-NC-SA Compatible License means a license listed at
creativecommons.org/compatiblelicenses, approved by Creative
Commons as essentially the equivalent of this Public License.
d. Copyright and Similar Rights means copyright and/or similar rights
closely related to copyright including, without limitation,
performance, broadcast, sound recording, and Sui Generis Database
Rights, without regard to how the rights are labeled or
categorized. For purposes of this Public License, the rights
specified in Section 2(b)(1)-(2) are not Copyright and Similar
Rights.
e. Effective Technological Measures means those measures that, in the
absence of proper authority, may not be circumvented under laws
fulfilling obligations under Article 11 of the WIPO Copyright
Treaty adopted on December 20, 1996, and/or similar international
agreements.
f. Exceptions and Limitations means fair use, fair dealing, and/or
any other exception or limitation to Copyright and Similar Rights
that applies to Your use of the Licensed Material.
g. License Elements means the license attributes listed in the name
of a Creative Commons Public License. The License Elements of this
Public License are Attribution, NonCommercial, and ShareAlike.
h. Licensed Material means the artistic or literary work, database,
or other material to which the Licensor applied this Public
License.
i. Licensed Rights means the rights granted to You subject to the
terms and conditions of this Public License, which are limited to
all Copyright and Similar Rights that apply to Your use of the
Licensed Material and that the Licensor has authority to license.
j. Licensor means the individual(s) or entity(ies) granting rights
under this Public License.
k. NonCommercial means not primarily intended for or directed towards
commercial advantage or monetary compensation. For purposes of
this Public License, the exchange of the Licensed Material for
other material subject to Copyright and Similar Rights by digital
file-sharing or similar means is NonCommercial provided there is
no payment of monetary compensation in connection with the
exchange.
l. Share means to provide material to the public by any means or
process that requires permission under the Licensed Rights, such
as reproduction, public display, public performance, distribution,
dissemination, communication, or importation, and to make material
available to the public including in ways that members of the
public may access the material from a place and at a time
individually chosen by them.
m. Sui Generis Database Rights means rights other than copyright
resulting from Directive 96/9/EC of the European Parliament and of
the Council of 11 March 1996 on the legal protection of databases,
as amended and/or succeeded, as well as other essentially
equivalent rights anywhere in the world.
n. You means the individual or entity exercising the Licensed Rights
under this Public License. Your has a corresponding meaning.
Section 2 -- Scope.
a. License grant.
1. Subject to the terms and conditions of this Public License,
the Licensor hereby grants You a worldwide, royalty-free,
non-sublicensable, non-exclusive, irrevocable license to
exercise the Licensed Rights in the Licensed Material to:
a. reproduce and Share the Licensed Material, in whole or
in part, for NonCommercial purposes only; and
b. produce, reproduce, and Share Adapted Material for
NonCommercial purposes only.
2. Exceptions and Limitations. For the avoidance of doubt, where
Exceptions and Limitations apply to Your use, this Public
License does not apply, and You do not need to comply with
its terms and conditions.
3. Term. The term of this Public License is specified in Section
6(a).
4. Media and formats; technical modifications allowed. The
Licensor authorizes You to exercise the Licensed Rights in
all media and formats whether now known or hereafter created,
and to make technical modifications necessary to do so. The
Licensor waives and/or agrees not to assert any right or
authority to forbid You from making technical modifications
necessary to exercise the Licensed Rights, including
technical modifications necessary to circumvent Effective
Technological Measures. For purposes of this Public License,
simply making modifications authorized by this Section 2(a)
(4) never produces Adapted Material.
5. Downstream recipients.
a. Offer from the Licensor -- Licensed Material. Every
recipient of the Licensed Material automatically
receives an offer from the Licensor to exercise the
Licensed Rights under the terms and conditions of this
Public License.
b. Additional offer from the Licensor -- Adapted Material.
Every recipient of Adapted Material from You
automatically receives an offer from the Licensor to
exercise the Licensed Rights in the Adapted Material
under the conditions of the Adapter's License You apply.
c. No downstream restrictions. You may not offer or impose
any additional or different terms or conditions on, or
apply any Effective Technological Measures to, the
Licensed Material if doing so restricts exercise of the
Licensed Rights by any recipient of the Licensed
Material.
6. No endorsement. Nothing in this Public License constitutes or
may be construed as permission to assert or imply that You
are, or that Your use of the Licensed Material is, connected
with, or sponsored, endorsed, or granted official status by,
the Licensor or others designated to receive attribution as
provided in Section 3(a)(1)(A)(i).
b. Other rights.
1. Moral rights, such as the right of integrity, are not
licensed under this Public License, nor are publicity,
privacy, and/or other similar personality rights; however, to
the extent possible, the Licensor waives and/or agrees not to
assert any such rights held by the Licensor to the limited
extent necessary to allow You to exercise the Licensed
Rights, but not otherwise.
2. Patent and trademark rights are not licensed under this
Public License.
3. To the extent possible, the Licensor waives any right to
collect royalties from You for the exercise of the Licensed
Rights, whether directly or through a collecting society
under any voluntary or waivable statutory or compulsory
licensing scheme. In all other cases the Licensor expressly
reserves any right to collect such royalties, including when
the Licensed Material is used other than for NonCommercial
purposes.
Section 3 -- License Conditions.
Your exercise of the Licensed Rights is expressly made subject to the
following conditions.
a. Attribution.
1. If You Share the Licensed Material (including in modified
form), You must:
a. retain the following if it is supplied by the Licensor
with the Licensed Material:
i. identification of the creator(s) of the Licensed
Material and any others designated to receive
attribution, in any reasonable manner requested by
the Licensor (including by pseudonym if
designated);
ii. a copyright notice;
iii. a notice that refers to this Public License;
iv. a notice that refers to the disclaimer of
warranties;
v. a URI or hyperlink to the Licensed Material to the
extent reasonably practicable;
b. indicate if You modified the Licensed Material and
retain an indication of any previous modifications; and
c. indicate the Licensed Material is licensed under this
Public License, and include the text of, or the URI or
hyperlink to, this Public License.
2. You may satisfy the conditions in Section 3(a)(1) in any
reasonable manner based on the medium, means, and context in
which You Share the Licensed Material. For example, it may be
reasonable to satisfy the conditions by providing a URI or
hyperlink to a resource that includes the required
information.
3. If requested by the Licensor, You must remove any of the
information required by Section 3(a)(1)(A) to the extent
reasonably practicable.
b. ShareAlike.
In addition to the conditions in Section 3(a), if You Share
Adapted Material You produce, the following conditions also apply.
1. The Adapter's License You apply must be a Creative Commons
license with the same License Elements, this version or
later, or a BY-NC-SA Compatible License.
2. You must include the text of, or the URI or hyperlink to, the
Adapter's License You apply. You may satisfy this condition
in any reasonable manner based on the medium, means, and
context in which You Share Adapted Material.
3. You may not offer or impose any additional or different terms
or conditions on, or apply any Effective Technological
Measures to, Adapted Material that restrict exercise of the
rights granted under the Adapter's License You apply.
Section 4 -- Sui Generis Database Rights.
Where the Licensed Rights include Sui Generis Database Rights that
apply to Your use of the Licensed Material:
a. for the avoidance of doubt, Section 2(a)(1) grants You the right
to extract, reuse, reproduce, and Share all or a substantial
portion of the contents of the database for NonCommercial purposes
only;
b. if You include all or a substantial portion of the database
contents in a database in which You have Sui Generis Database
Rights, then the database in which You have Sui Generis Database
Rights (but not its individual contents) is Adapted Material,
including for purposes of Section 3(b); and
c. You must comply with the conditions in Section 3(a) if You Share
all or a substantial portion of the contents of the database.
For the avoidance of doubt, this Section 4 supplements and does not
replace Your obligations under this Public License where the Licensed
Rights include other Copyright and Similar Rights.
Section 5 -- Disclaimer of Warranties and Limitation of Liability.
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
c. The disclaimer of warranties and limitation of liability provided
above shall be interpreted in a manner that, to the extent
possible, most closely approximates an absolute disclaimer and
waiver of all liability.
Section 6 -- Term and Termination.
a. This Public License applies for the term of the Copyright and
Similar Rights licensed here. However, if You fail to comply with
this Public License, then Your rights under this Public License
terminate automatically.
b. Where Your right to use the Licensed Material has terminated under
Section 6(a), it reinstates:
1. automatically as of the date the violation is cured, provided
it is cured within 30 days of Your discovery of the
violation; or
2. upon express reinstatement by the Licensor.
For the avoidance of doubt, this Section 6(b) does not affect any
right the Licensor may have to seek remedies for Your violations
of this Public License.
c. For the avoidance of doubt, the Licensor may also offer the
Licensed Material under separate terms or conditions or stop
distributing the Licensed Material at any time; however, doing so
will not terminate this Public License.
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
License.
Section 7 -- Other Terms and Conditions.
a. The Licensor shall not be bound by any additional or different
terms or conditions communicated by You unless expressly agreed.
b. Any arrangements, understandings, or agreements regarding the
Licensed Material not stated herein are separate from and
independent of the terms and conditions of this Public License.
Section 8 -- Interpretation.
a. For the avoidance of doubt, this Public License does not, and
shall not be interpreted to, reduce, limit, restrict, or impose
conditions on any use of the Licensed Material that could lawfully
be made without permission under this Public License.
b. To the extent possible, if any provision of this Public License is
deemed unenforceable, it shall be automatically reformed to the
minimum extent necessary to make it enforceable. If the provision
cannot be reformed, it shall be severed from this Public License
without affecting the enforceability of the remaining terms and
conditions.
c. No term or condition of this Public License will be waived and no
failure to comply consented to unless expressly agreed to by the
Licensor.
d. Nothing in this Public License constitutes or may be interpreted
as a limitation upon, or waiver of, any privileges and immunities
that apply to the Licensor or You, including from the legal
processes of any jurisdiction or authority.
=======================================================================
Creative Commons is not a party to its public
licenses. Notwithstanding, Creative Commons may elect to apply one of
its public licenses to material it publishes and in those instances
will be considered the “Licensor.” The text of the Creative Commons
public licenses is dedicated to the public domain under the CC0 Public
Domain Dedication. Except for the limited purpose of indicating that
material is shared under a Creative Commons public license or as
otherwise permitted by the Creative Commons policies published at
creativecommons.org/policies, Creative Commons does not authorize the
use of the trademark "Creative Commons" or any other trademark or logo
of Creative Commons without its prior written consent including,
without limitation, in connection with any unauthorized modifications
to any of its public licenses or any other arrangements,
understandings, or agreements concerning use of licensed material. For
the avoidance of doubt, this paragraph does not form part of the
public licenses.
Creative Commons may be contacted at creativecommons.org.
================================================
FILE: README.md
================================================
# SECMON - Infosec Watching Tool <center><img src="https://github.com/Guezone/SECMON/blob/master/img/logo.jpg" data-canonical-src="https://github.com/Guezone/SECMON/blob/master/img/logo.png" width="30" height="30" /></center>
[](https://www.python.org/)    -red) 

# Description
SECMON is a **web-based tool** for the automation of **infosec watching** and **vulnerability management** with a web interface.
A demo is available [here](https://secmon.guezone.info/). A Discord channel is available [here](https://discord.gg/cXzvb4fKzE)
## Features
- **Mail alerting** when a **new CVE** is published and which concerns your product list
- **Mail alerting** when a "cyber-security" news are published: new threats, recent attacks, events, etc.
- Visualize the **high security risk products** present on your IT infrastructure
- Download CVE **Excel report** by date range
- Display **top cybersecurity subject** (**Light cyber landscape**)
- Logs **easy to integrate in a SIEM** (verified on **Splunk** and **Graylog**)
- View the **latest CVE** and **latest news related to cyber security are published**
- Assign a buffer of **management status of a CVE**
- Search all the **details of a CVE**
- Check if there is an **exploit** on **Github or Exploit-DB** concerning a CVE
- Search for **vulnerabilities for a specified product**
- **Manage your product list**: search/add/delete a product, display your referenced product list
- **Monitor the sources** used by pollers
Email alerts can be sent in English or French. SECMON web UI now support multi user account.
CVE are polled using two methods of collection/correspondence:
- **Keyword-based** : allows you to be proactive on the retrieval of CVE by leaving a little bit of precision (no version check, just word matching) on the affected products (ex: "VMWare", "Apache").
- **CPE based** (Common Platform Enumeration) : allows the retrieval of CVE that only concern the product version entered (e.g. "Windows 10 1909", "Apache 2.4.38")
## Requirements
SECMON requires registration on Github API for exploits retrieval. It also requires :
- OS : Linux-based system (tested on Debian 10)
- Environnement : Python 3 (tested on Python 3.9 and Python 3.8)
- A valid Github API key
**WARNING** : Web UI credentials are hashed (SHA512 with salt), on the other hand, the Github API connection credentials and the application session key are neither encrypted nor hashed. All data is stored in an unencrypted sqlite database. A few advices :
- Allow access to this machine only to persons who are authorized to do so.
- Isolate the host machine from the rest.
- Use a dedicated server/VM or Docker container.
## Some screenshots

<p align="center"><i>Example of email alerts (CVE and RSS)</i></p>

<p align="center"><i>Vulnerability management page</i></p>

<p align="center"><i>CVE details</i></p>

<p align="center"><i>Exploit search</i></p>

<p align="center"><i>Cyber threats top subject</i></p>

<p align="center"><i>Product search</i></p>

<p align="center"><i>Product list</i></p>
# Installation
[Read the docs](DOCS.md)
# Thanks
Thanks to <a href="https://github.com/andreafioraldi" target='_blank'>@andreafioraldi</a> for <a href="https://github.com/andreafioraldi/cve_searchsploit" target='_blank'>cve_searchsploit</a> Python module.
Thanks to <a href="https://github.com/konsav" target='_blank'>@konsav</a> for <a href="https://github.com/konsav/email-templates" target='_blank'>HTML/CSS email template.</a>
Thanks to <a href="https://github.com/rodolfo-mendes" target='_blank'>@rodolfo-mendes</a> for <a href="https://github.com/rodolfo-mendes/sbadmin2-flask-template" target='_blank'>the sbadmin2 (Bootstrap) template adapted to Flask.</a>
Thanks to Florent Chatain for the first web security auditing.
# License
**SECMON** (by Aubin Custodio - Guezone) is licensed under **CC BY-NC-SA 4.0**.
This license allows you to **use** SECMON, to **improve it** and to make it live **by mentioning the author** but **without using it for commercial purposes**. As the infosec watching process is quite difficult and time consuming, it should only be used to help companies and/or users **to secure their IT infrastructure** and to know the current cyber security world.
# Changelog
**2.0 :**
- Modification of the log format
- Reporting method (generation via dates)
- Web UI - new boostrap template
- Work on the Docker automation part
**2.1 :**
- Add a multi-user support on Web UI
- Improved auto docker configuration (to improve updates with git and volume)
- Added a **Cyber Threats** section that highlights the top cyber topics reported in the RSS module
- Update of README and DOCS (docker, update & screenshots part)
- Prioritisation of the CPE polling method over the keyword method
# Roadmap
## Features
- [x] Automate the deployment with docker
- [x] First security auditing (front-end only)
- [x] Write the logs in a standard format and plan to send them to a third party of SIEM type.
- [X] Write user documentation for the Web UI
- [ ] Create script to allow CPE scanning on Windows and Linux based system
- [ ] Add new sources of cyber-news
- [ ] Create a REST API for calling in other applications
- [ ] Send CVE daily update report (new high risk product, CVSS changes, affected product changes, new exploitable CVE)
- [ ] SECMON-Open-API (free and open API to get 0-day, viral vulns & data breach news)
- [ ] Others Vuln Database polling
## Reliability improvement
- [X] NIST API rate complete management (partial correction)
- [ ] Product unification (product = CPE + Keyword)
- [X] Keyword management to be case unsensitive
================================================
FILE: SECURITY.md
================================================
## Reporting a Vulnerability
Please report (suspected) security vulnerabilities via the dedicated "bugs-vulnérabilités" Discord channel ([Discord server link](https://discord.gg/cXzvb4fKzE)). You will receive a response from
us within few days. If the issue is confirmed, we will release a patch as soon
as possible depending on complexity but historically within a few days.
================================================
FILE: cve_poller.py
================================================
# -*- coding: utf-8 -*-
"""
SECMON - Source code of the SECMON CVE poller script.
"""
__author__ = "Aubin Custodio"
__copyright__ = "Copyright 2021, SECMON"
__credits__ = ["Aubin Custodio","Guezone"]
__license__ = "CC BY-NC-SA 4.0"
__version__ = "2.1"
__maintainer__ = "Aubin Custodio"
__email__ = "custodio.aubin@outlook.com"
import base64, os, smtplib, re, requests, time, sqlite3, feedparser, colorama, warnings
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
from datetime import datetime, timedelta
from bs4 import BeautifulSoup
from secmon_lib import getParsedCpe, translateText, getUserLanguage, getCpeList, pollCveIdFromCpe, writeCveTypeLog, writeMgmtTasksLog,handleException
warnings.filterwarnings("ignore", category=DeprecationWarning)
sender, receiver, smtp_login, smtp_password, smtpsrv, port, tls, keywords = '','','','','','','',''
script_path = os.path.abspath(__file__)
dir_path = script_path.replace("cve_poller.py","")
log_file = dir_path+"logs.txt"
class bcolors:
HEADER = '\033[95m'
OKBLUE = '\033[94m'
OKGREEN = '\033[92m'
WARNING = '\033[93m'
FAIL = '\033[91m'
ENDC = '\033[0m'
BOLD = '\033[1m'
UNDERLINE = '\033[4m'
def checkConfig(sender, receiver, smtp_login, smtp_password, smtpsrv, port, tls,keywords):
script_path = os.path.abspath(__file__)
dir_path = script_path.replace("cve_poller.py","")
con = sqlite3.connect(dir_path+'secmon.db')
cur = con.cursor()
cur.execute("SELECT sender FROM config")
db_result_tuple = cur.fetchone()
for value in db_result_tuple:
sender = value
cur.execute("SELECT smtp_login FROM config")
db_result_tuple = cur.fetchone()
for value in db_result_tuple:
smtp_login = value
cur.execute("SELECT smtp_password FROM config")
db_result_tuple = cur.fetchone()
for value in db_result_tuple:
b = value.encode("UTF-8")
bytes_password = base64.b64decode(b)
smtp_password = bytes_password.decode("UTF-8")
cur.execute("SELECT smtpsrv FROM config")
db_result_tuple = cur.fetchone()
for value in db_result_tuple:
smtpsrv = value
cur.execute("SELECT port FROM config")
db_result_tuple = cur.fetchone()
for value in db_result_tuple:
port = value
cur.execute("SELECT receiver FROM config")
db_result_tuple = cur.fetchone()
for value in db_result_tuple:
receivers = value.split(";")
cur.execute("SELECT tls FROM config")
db_result_tuple = cur.fetchone()
for value in db_result_tuple:
tls = value
cur.execute("SELECT language FROM config")
db_result_tuple = cur.fetchone()
for value in db_result_tuple:
language = value
cur.execute("SELECT receiver FROM config")
db_result_tuple = cur.fetchone()
for value in db_result_tuple:
receivers = value.split(";")
cur.execute("SELECT keyword FROM keyword_list")
db_result_list = cur.fetchall()
keywords = []
for db_result_tuple in db_result_list:
for result in db_result_tuple:
keywords.append(result)
if all(value != '' for value in [sender, receivers, smtp_login, smtp_password, smtpsrv, str(port), tls, language]):
print(bcolors.OKGREEN+"Configuration is good."+bcolors.ENDC)
cvePoller(sender, receivers, smtp_login, smtp_password, smtpsrv, port, tls, keywords, language)
else:
print(bcolors.FAIL+"Error in the config."+bcolors.ENDC)
exit()
def cvePoller(sender, receivers, smtp_login, smtp_password, smtpsrv, port, tls, keywords, language):
print("------------------------------------")
summary, url = "",""
cve_rss = []
current_feed = feedparser.parse("https://nvd.nist.gov/feeds/xml/cve/misc/nvd-rss.xml")
for entries in current_feed.entries:
title = entries.title
summary = entries.summary
cve_id = re.findall('CVE-\d{4}-\d{4,7}',title)
cve_id = cve_id[0]
cve_rss.append(cve_id+"(=)"+summary)
summary, url = "",""
con = sqlite3.connect(dir_path+'secmon.db')
cur = con.cursor()
dest_language = getUserLanguage()
now_date = str(datetime.now()).split(" ")[0].split("-")
idx_date = now_date[2]+"/"+now_date[1]+"/"+now_date[0]
time.sleep(10)
# CPE
new_cve_list = []
cur.execute("SELECT cpe FROM cpe_list")
db_result_list = cur.fetchall()
cpes = getCpeList()
if cpes != []:
print(bcolors.HEADER+"Polling NVD related to your product list (CPE based search)."+bcolors.ENDC+"\n")
for cpe in cpes:
time.sleep(30)
cve_ids = pollCveIdFromCpe(cpe)
cpe = cpe.replace("\n","").replace(" ","")
for cve_id in cve_ids:
cur.execute("SELECT CVE_ID FROM CVE_DATA WHERE CVE_ID = (?);", (cve_id,))
db_result_list = cur.fetchall()
db_result_str = ""
for db_result_tuple in db_result_list:
for result in db_result_tuple:
db_result_str+=result
if cve_id not in db_result_str:
time.sleep(10)
nvd_base_url = "https://services.nvd.nist.gov/rest/json/cve/1.0/"
nvd_query = nvd_base_url+cve_id
nvd_response = requests.get(url=nvd_query)
nvd_data = nvd_response.json()
if 'result' in nvd_data.keys():
if 'reference_data' in nvd_data['result']['CVE_Items'][0]['cve']['references']:
nvd_links = nvd_data['result']['CVE_Items'][0]['cve']['references']['reference_data']
cve_sources = ""
for link in nvd_links:
cve_sources += (link['url']+"\n")
else:
cve_sources = "N/A"
key_match = cpe
cve_score = ""
fr_society = " (constructeur/éditeur)"
en_society = " (builder/publisher)"
if not "impact" in nvd_data['result']['CVE_Items'][0].keys():
cve_score = "N/A"
try:
webpage = requests.get("https://nvd.nist.gov/vuln/detail/{}".format(cve_id))
soup = BeautifulSoup(webpage.content, 'html.parser')
cve_cna_score = soup.find(id='Cvss3CnaCalculatorAnchor')
cve_cna_score = cve_cna_score.get_text()
if cve_cna_score != "":
if language == "fr" or language=="FR":
cve_score = cve_cna_score + fr_society
else:
cve_score = cve_cna_score + en_society
else:
cve_score = "N/A"
except:
cve_score = "N/A"
else:
try:
cve_score = nvd_data['result']['CVE_Items'][0]['impact']['baseMetricV3']['cvssV3']['baseScore']
except:
cve_score = "N/A"
published_date = nvd_data['result']['CVE_Items'][0]['publishedDate']
formatted_date = published_date.split("T")[0]
formatted_date = datetime.strptime(formatted_date,"%Y-%m-%d")
date_2_days_ago = datetime.now() - timedelta(days=7)
if (date_2_days_ago<=formatted_date) and (formatted_date<=datetime.now()):
cve_date_status = "Potentially new CVE"
else:
cve_date_status = "Potentially an update"
cve_date = published_date.split("T")[0]
if language == "fr" or language == "FR":
fr_date = cve_date.split("-")
cve_date = fr_date[2]+"/"+fr_date[1]+"/"+fr_date[0]
if (cve_score=="N/A"):
cve_status = cve_date_status+" - "+"Not yet rated (No score, no CPE)"
else:
cve_status = cve_date_status+" - "+"Valid evaluation"
cve_cpe = ""
if "configurations" in nvd_data['result']['CVE_Items'][0].keys():
if nvd_data['result']['CVE_Items'][0]['configurations']['nodes']:
for node in nvd_data['result']['CVE_Items'][0]['configurations']['nodes']:
if 'cpe_match' in node.keys():
for cpe_node in node['cpe_match']:
cve_cpe += (cpe_node['cpe23Uri']+'\n')
if cve_cpe == "":
cve_cpe = "N/A"
cve_description = nvd_data['result']['CVE_Items'][0]['cve']['description']['description_data'][0]['value']
if language == "fr" or language=="FR":
try:
cve_description = translateText(dest_language,cve_description)
except:
pass
if not "/" in cve_date:
cve_date = cve_date.split("-")[2]+"/"+cve_date.split("-")[1]+"/"+cve_date.split("-")[0]
try:
cve_status = translateText(dest_language,cve_status).replace("nouveau", "une nouvelle").replace("évalué","évaluée")
except:
pass
nvd_link = 'https://nvd.nist.gov/vuln/detail/'+cve_id
else:
cve_description = "N/A"
date = str(datetime.now()).split(" ")[0].split("-")
cve_date = date[2]+"/"+date[1]+"/"+date[0]
cve_score = "N/A"
cve_sources = "N/A"
cve_status = "N/A"
cve_cpe = "N/A"
nvd_link = 'https://nvd.nist.gov/vuln/detail/'+cve_id
status = "Unread"
if cve_id not in new_cve_list:
cur.execute("INSERT INTO CVE_DATA (CVE_ID,KEYWORD,STATUS,CVE_SCORE,CVE_DATE,CVE_DESCRIPTION,CVE_EVAL,CVE_CPE,CVE_SOURCES,EXPLOIT_FIND,INDEXING_DATE) VALUES (?,?,?,?,?,?,?,?,?,?,?);", (cve_id,key_match,status,str(cve_score).split(" ")[0],cve_date,cve_description,cve_status,cve_cpe,cve_sources,"False",idx_date))
con.commit()
report="updated"
print("New CVE detected -> "+cve_id)
try:
sendAlert(smtp_login, smtp_password, smtpsrv, port, tls, sender, receivers, cve_id, cve_sources, str(cve_score).split(" ")[0], cve_status, cve_cpe, cve_date, cve_description, language,key_match)
alert = "sent"
except Exception as e:
handleException(e)
alert = "unsent"
new_cve_list.append(cve_id)
writeCveTypeLog("cve_poller",cve_id,"new",key_match,str(cve_score).split(" ")[0],cve_date,cve_cpe,report,alert)
if not new_cve_list:
print(bcolors.HEADER+"No new CVE related to your (CPE) product list."+bcolors.ENDC)
print("------------------------------------")
else:
timestamp = datetime.now().strftime("%d/%m/%Y %H:%M:%S")
print(bcolors.OKGREEN+"Database was updated with new CVE."+bcolors.ENDC)
print("------------------------------------")
# RSS
new_cve_list = []
print(bcolors.HEADER+"Polling NVD RSS feed (keyword based search)."+bcolors.ENDC+"\n")
for cve in cve_rss:
cve_id = cve.split("(=)")[0]
summary = cve.split("(=)")[1]
for key in keywords:
if bool(re.fullmatch(r'[A-Z0-9-._]{4,}',key)) == True or bool(re.fullmatch(r'\w{1,3}',key)) == True:
if key in summary:
key_match = key
cur.execute("SELECT CVE_ID FROM CVE_DATA WHERE CVE_ID = (?);", (cve_id,))
db_result_list = cur.fetchall()
db_result_str = ""
for db_result_tuple in db_result_list:
for result in db_result_tuple:
db_result_str+=result
if cve_id not in db_result_str:
time.sleep(15)
nvd_base_url = "https://services.nvd.nist.gov/rest/json/cve/1.0/"
nvd_query = nvd_base_url+cve_id
nvd_response = requests.get(url=nvd_query)
nvd_data = nvd_response.json()
if 'result' in nvd_data.keys():
if 'reference_data' in nvd_data['result']['CVE_Items'][0]['cve']['references']:
nvd_links = nvd_data['result']['CVE_Items'][0]['cve']['references']['reference_data']
cve_sources = ""
for link in nvd_links:
cve_sources += (link['url']+"\n")
else:
cve_sources = "N/A"
cve_score = ""
fr_society = " (constructeur/éditeur)"
en_society = " (builder/publisher)"
if not "impact" in nvd_data['result']['CVE_Items'][0].keys():
cve_score = "N/A"
try:
webpage = requests.get("https://nvd.nist.gov/vuln/detail/{}".format(cve_id))
soup = BeautifulSoup(webpage.content, 'html.parser')
cve_cna_score = soup.find(id='Cvss3CnaCalculatorAnchor')
cve_cna_score = cve_cna_score.get_text()
if cve_cna_score != "":
if language == "fr" or language=="FR":
cve_score = cve_cna_score + fr_society
else:
cve_score = cve_cna_score + en_society
else:
cve_score = "N/A"
except:
cve_score = "N/A"
else:
try:
cve_score = nvd_data['result']['CVE_Items'][0]['impact']['baseMetricV3']['cvssV3']['baseScore']
except:
cve_score = "N/A"
published_date = nvd_data['result']['CVE_Items'][0]['publishedDate']
formatted_date = published_date.split("T")[0]
formatted_date = datetime.strptime(formatted_date,"%Y-%m-%d")
date_2_days_ago = datetime.now() - timedelta(days=7)
if (date_2_days_ago<=formatted_date) and (formatted_date<=datetime.now()):
cve_date_status = "Potentially new CVE"
else:
cve_date_status = "Potentially an update"
cve_date = published_date.split("T")[0]
if language == "fr" or language == "FR":
fr_date = cve_date.split("-")
cve_date = fr_date[2]+"/"+fr_date[1]+"/"+fr_date[0]
if (cve_score=="N/A"):
cve_status = cve_date_status+" - "+"Not yet rated (No score, no CPE)"
else:
cve_status = cve_date_status+" - "+"Valid evaluation"
cve_cpe = ""
if "configurations" in nvd_data['result']['CVE_Items'][0].keys():
if nvd_data['result']['CVE_Items'][0]['configurations']['nodes']:
for node in nvd_data['result']['CVE_Items'][0]['configurations']['nodes']:
if 'cpe_match' in node.keys():
for cpe_node in node['cpe_match']:
cve_cpe += (cpe_node['cpe23Uri']+'\n')
if cve_cpe == "":
cve_cpe = "N/A"
cve_description = nvd_data['result']['CVE_Items'][0]['cve']['description']['description_data'][0]['value']
nvd_link = 'https://nvd.nist.gov/vuln/detail/'+cve_id
if language == "fr" or language=="FR":
try:
cve_description = translateText(dest_language,cve_description)
except:
pass
if not "/" in cve_date:
cve_date = cve_date.split("-")[2]+"/"+cve_date.split("-")[1]+"/"+cve_date.split("-")[0]
try:
cve_status = translateText(dest_language,cve_status).replace("nouveau", "une nouvelle").replace("évalué","évaluée")
except:
pass
else:
cve_description = summary
date = str(datetime.now()).split(" ")[0].split("-")
cve_date = date[2]+"/"+date[1]+"/"+date[0]
cve_score = "N/A"
cve_sources = "N/A"
cve_status = "N/A"
cve_cpe = "N/A"
nvd_link = 'https://nvd.nist.gov/vuln/detail/'+cve_id
status = "Unread"
if cve_id not in new_cve_list:
cur.execute("INSERT INTO CVE_DATA (CVE_ID,KEYWORD,STATUS,CVE_SCORE,CVE_DATE,CVE_DESCRIPTION,CVE_EVAL,CVE_CPE,CVE_SOURCES,EXPLOIT_FIND,INDEXING_DATE) VALUES (?,?,?,?,?,?,?,?,?,?,?);", (cve_id,key_match,status,str(cve_score).split(" ")[0],cve_date,cve_description,cve_status,cve_cpe,cve_sources,"False",idx_date))
con.commit()
print("New CVE detected -> "+cve_id)
report="updated"
try:
sendAlert(smtp_login, smtp_password, smtpsrv, port, tls, sender, receivers, cve_id, cve_sources, str(cve_score).split(" ")[0], cve_status, cve_cpe, cve_date, cve_description, language,key_match)
alert = "sent"
except Exception as e:
handleException(e)
alert = "unsent"
new_cve_list.append(cve_id)
writeCveTypeLog("cve_poller",cve_id,"new",key_match,str(cve_score).split(" ")[0],cve_date,cve_cpe,report,alert)
else:
if bool(re.search(key,summary,re.IGNORECASE)) == True:
key_match = key
cur.execute("SELECT CVE_ID FROM CVE_DATA WHERE CVE_ID = (?);", (cve_id,))
db_result_list = cur.fetchall()
db_result_str = ""
for db_result_tuple in db_result_list:
for result in db_result_tuple:
db_result_str+=result
if cve_id not in db_result_str:
time.sleep(15)
nvd_base_url = "https://services.nvd.nist.gov/rest/json/cve/1.0/"
nvd_query = nvd_base_url+cve_id
nvd_response = requests.get(url=nvd_query)
nvd_data = nvd_response.json()
if 'result' in nvd_data.keys():
if 'reference_data' in nvd_data['result']['CVE_Items'][0]['cve']['references']:
nvd_links = nvd_data['result']['CVE_Items'][0]['cve']['references']['reference_data']
cve_sources = ""
for link in nvd_links:
cve_sources += (link['url']+"\n")
else:
cve_sources = "N/A"
cve_score = ""
fr_society = " (constructeur/éditeur)"
en_society = " (builder/publisher)"
if not "impact" in nvd_data['result']['CVE_Items'][0].keys():
cve_score = "N/A"
try:
webpage = requests.get("https://nvd.nist.gov/vuln/detail/{}".format(cve_id))
soup = BeautifulSoup(webpage.content, 'html.parser')
cve_cna_score = soup.find(id='Cvss3CnaCalculatorAnchor')
cve_cna_score = cve_cna_score.get_text()
if cve_cna_score != "":
if language == "fr" or language=="FR":
cve_score = cve_cna_score + fr_society
else:
cve_score = cve_cna_score + en_society
else:
cve_score = "N/A"
except:
cve_score = "N/A"
else:
try:
cve_score = nvd_data['result']['CVE_Items'][0]['impact']['baseMetricV3']['cvssV3']['baseScore']
except:
cve_score = "N/A"
published_date = nvd_data['result']['CVE_Items'][0]['publishedDate']
formatted_date = published_date.split("T")[0]
formatted_date = datetime.strptime(formatted_date,"%Y-%m-%d")
date_2_days_ago = datetime.now() - timedelta(days=7)
if (date_2_days_ago<=formatted_date) and (formatted_date<=datetime.now()):
cve_date_status = "Potentially new CVE"
else:
cve_date_status = "Potentially an update"
cve_date = published_date.split("T")[0]
if language == "fr" or language == "FR":
fr_date = cve_date.split("-")
cve_date = fr_date[2]+"/"+fr_date[1]+"/"+fr_date[0]
if (cve_score=="N/A"):
cve_status = cve_date_status+" - "+"Not yet rated (No score, no CPE)"
else:
cve_status = cve_date_status+" - "+"Valid evaluation"
cve_cpe = ""
if "configurations" in nvd_data['result']['CVE_Items'][0].keys():
if nvd_data['result']['CVE_Items'][0]['configurations']['nodes']:
for node in nvd_data['result']['CVE_Items'][0]['configurations']['nodes']:
if 'cpe_match' in node.keys():
for cpe_node in node['cpe_match']:
cve_cpe += (cpe_node['cpe23Uri']+'\n')
if cve_cpe == "":
cve_cpe = "N/A"
cve_description = nvd_data['result']['CVE_Items'][0]['cve']['description']['description_data'][0]['value']
nvd_link = 'https://nvd.nist.gov/vuln/detail/'+cve_id
if language == "fr" or language=="FR":
try:
cve_description = translateText(dest_language,cve_description)
except:
pass
if not "/" in cve_date:
cve_date = cve_date.split("-")[2]+"/"+cve_date.split("-")[1]+"/"+cve_date.split("-")[0]
try:
cve_status = translateText(dest_language,cve_status).replace("nouveau", "une nouvelle").replace("évalué","évaluée")
except:
pass
else:
cve_description = summary
date = str(datetime.now()).split(" ")[0].split("-")
cve_date = date[2]+"/"+date[1]+"/"+date[0]
cve_score = "N/A"
cve_sources = "N/A"
cve_status = "N/A"
cve_cpe = "N/A"
nvd_link = 'https://nvd.nist.gov/vuln/detail/'+cve_id
status = "Unread"
if cve_id not in new_cve_list:
cur.execute("INSERT INTO CVE_DATA (CVE_ID,KEYWORD,STATUS,CVE_SCORE,CVE_DATE,CVE_DESCRIPTION,CVE_EVAL,CVE_CPE,CVE_SOURCES,EXPLOIT_FIND,INDEXING_DATE) VALUES (?,?,?,?,?,?,?,?,?,?,?);", (cve_id,key_match,status,str(cve_score).split(" ")[0],cve_date,cve_description,cve_status,cve_cpe,cve_sources,"False",idx_date))
con.commit()
print("New CVE detected -> "+cve_id)
report="updated"
try:
sendAlert(smtp_login, smtp_password, smtpsrv, port, tls, sender, receivers, cve_id, cve_sources, str(cve_score).split(" ")[0], cve_status, cve_cpe, cve_date, cve_description, language,key_match)
alert = "sent"
except Exception as e:
handleException(e)
alert = "unsent"
new_cve_list.append(cve_id)
writeCveTypeLog("cve_poller",cve_id,"new",key_match,str(cve_score).split(" ")[0],cve_date,cve_cpe,report,alert)
if not new_cve_list:
print(bcolors.HEADER+"No new CVE matched with your keyword list."+bcolors.ENDC)
print("------------------------------------")
timestamp = datetime.now().strftime("%d/%m/%Y %H:%M:%S")
print(bcolors.OKBLUE+"Finished at : "+timestamp+bcolors.ENDC)
print("------------------------------------")
else:
print(bcolors.OKGREEN+"Database was updated with new CVE."+bcolors.ENDC)
timestamp = datetime.now().strftime("%d/%m/%Y %H:%M:%S")
print("------------------------------------")
print(bcolors.OKBLUE+"Finished at : "+timestamp+bcolors.ENDC)
print("------------------------------------")
def sendAlert(smtp_login, smtp_password, smtpsrv, port, tls, sender, receivers, cve_id, cve_sources, cve_score, cve_status, cve_cpe, cve_date, cve_description, language,key_match):
body = ""
nvd_url = "https://nvd.nist.gov/vuln/detail/"+cve_id
for receiver in receivers:
with open(dir_path+'cve_template.html', 'r') as template:
html_code = template.read()
if "cpe" in key_match:
key_match = getParsedCpe(key_match)
if language == "fr" or language=="FR":
html_code = html_code.replace("Responsive HTML email templates","Alerte")
html_code = html_code.replace("$CVE",cve_id+" (Produit : {})".format(key_match))
try:
cve_description = translateText(dest_language,cve_description)
except:
pass
html_code = html_code.replace("$DESCRIPTION", cve_description.replace("u'","").replace("u ``",""))
if not "/" in cve_date:
cve_date = cve_date.split("-")[2]+"/"+cve_date.split("-")[1]+"/"+cve_date.split("-")[0]
html_code = html_code.replace("$DATE", cve_date)
html_code = html_code.replace("$SCORE", str(cve_score))
try:
cve_status = translateText(dest_language,cve_status).replace("nouveau", "une nouvelle").replace("évalué","évaluée")
except:
pass
html_code = html_code.replace("$STATUS", cve_status)
html_code = html_code.replace("$CPE", cve_cpe)
html_code = html_code.replace("$SOURCES", cve_sources)
html_code = html_code.replace("See more details", "Voir plus de détails")
html_code = html_code.replace("Publication date", "Date de publication")
html_code = html_code.replace("Status", "Statut")
html_code = html_code.replace("CPE/Product", "CPE/Produit")
html_code = html_code.replace("CVSS Score (V3)", "Score CVSS (V3)")
html_code = html_code.replace("This email was sent by", "Cet email a été envoyé par")
html_code = html_code.replace("CVE module", "Module CVE")
body = html_code.replace("URL OF THE NEWS",nvd_url)
else:
html_code = html_code.replace("Responsive HTML email templates","Alert")
html_code = html_code.replace("$CVE",cve_id+" (Product : {})".format(key_match))
html_code = html_code.replace("$DESCRIPTION", cve_description.replace("u'","").replace("u ``",""))
html_code = html_code.replace("$DATE", cve_date)
html_code = html_code.replace("$SCORE", str(cve_score))
html_code = html_code.replace("$STATUS", cve_status)
html_code = html_code.replace("$CPE", cve_cpe)
html_code = html_code.replace("$SOURCES", cve_sources)
body = html_code.replace("URL OF THE NEWS",nvd_url)
print(bcolors.HEADER+"Sending alert at {}...".format(receiver)+bcolors.ENDC)
try:
smtpserver = smtplib.SMTP(smtpsrv,port)
msg = MIMEMultipart()
msg['Subject'] = 'SECMON - CVE'
msg['From'] = sender
msg['To'] = receiver
msg.attach(MIMEText(body, 'html'))
except Exception as e:
handleException(e)
print(bcolors.FAIL+"Failed to send alert at {}.".format(receiver)+bcolors.ENDC)
exit()
try:
if tls == "yes":
smtpserver.ehlo()
smtpserver.starttls()
smtpserver.login(smtp_login, smtp_password)
smtpserver.sendmail(sender, receiver, msg.as_string())
print(bcolors.HEADER+"Alert was sent at {}\n".format(receiver)+bcolors.ENDC)
elif tls == "no":
smtpserver.login(smtp_login, smtp_password)
smtpserver.sendmail(sender, receiver, msg.as_string())
print(bcolors.HEADER+"Alert was sent at {}\n".format(receiver)+bcolors.ENDC)
except Exception as e:
handleException(e)
print(bcolors.FAIL+"An error occurred during authentication with the SMTP server. Check the configuration and try again."+bcolors.ENDC)
exit()
def main():
colorama.init()
print("------------ CVE Module ------------")
timestamp = datetime.now().strftime("%d/%m/%Y %H:%M:%S")
print(bcolors.OKBLUE+"Starting at : "+timestamp+bcolors.ENDC)
print("------------------------------------")
checkConfig(sender, receiver, smtp_login, smtp_password, smtpsrv, port, tls,keywords)
main()
================================================
FILE: cve_template.html
================================================
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0;">
<meta name="format-detection" content="telephone=yes"/>
<style type="text/css">span.preheader { display: none !important; } </style>
<style>
body { margin: 0; padding: 0; min-width: 100%; width: 100% !important; height: 100% !important;}
body, table, td, div, p, a { -webkit-font-smoothing: antialiased; text-size-adjust: 100%; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; line-height: 100%; }
table, td { mso-table-lspace: 0pt; mso-table-rspace: 0pt; border-collapse: collapse !important; border-spacing: 0; }
img { border: 0; line-height: 100%; outline: none; text-decoration: none; -ms-interpolation-mode: bicubic; }
#outlook a { padding: 0; }
.ReadMsgBody { width: 100%; } .ExternalClass { width: 100%; }
.ExternalClass, .ExternalClass p, .ExternalClass span, .ExternalClass font, .ExternalClass td, .ExternalClass div { line-height: 100%; }
@media all and (min-width: 560px) {
.container { border-radius: 8px; -webkit-border-radius: 8px; -moz-border-radius: 8px; -khtml-border-radius: 8px; }
}
a, a:hover {
color: #FFFFFF;
}
.footer a, .footer a:hover {
color: #828999;
}
</style><title>SECMON - CVE</title><link rel="icon" href="https://github.com/Guezone/SECMON" />
</head>
<body topmargin="0" rightmargin="0" bottommargin="0" leftmargin="0" marginwidth="0" marginheight="0" width="100%" style="border-collapse: collapse; border-spacing: 0; margin: 0; padding: 0; width: 100%; height: 100%; -webkit-font-smoothing: antialiased; text-size-adjust: 100%; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; line-height: 100%;
background-color: #222222;
color: #FFFFFF;"
bgcolor="#222222"
text="#FFFFFF">
<span class="preheader">$CVE : $DESCRIPTION</span>
<table width="100%" align="center" border="0" cellpadding="0" cellspacing="0" style="border-collapse: collapse; border-spacing: 0; margin: 0; padding: 0; width: 100%;" class="background"><tr><td align="center" valign="top" style="border-collapse: collapse; border-spacing: 0; margin: 0; padding: 0;"
bgcolor="#222222">
<table border="0" cellpadding="0" cellspacing="0" align="center"
width="500" style="border-collapse: collapse; border-spacing: 0; padding: 0; width: inherit;
max-width: 500px;" class="wrapper">
<tr>
<td align="center" valign="top" style="border-collapse: collapse; border-spacing: 0; margin: 0; padding: 0; padding-left: 6.25%; padding-right: 6.25%; width: 87.5%;
padding-top: 20px;
padding-bottom: 20px;">
<a target="_blank" style="text-decoration: none;"
href="https://github.com/Guezone/SECMON"><img border="0" vspace="0" hspace="0"
src="https://guezone.info/projets/secmon/logo.png"
width="50" height="50"
alt="Logo" title="Logo" style="
color: #FFFFFF;
font-size: 10px; margin: 0; padding: 0; outline: none; text-decoration: none; -ms-interpolation-mode: bicubic; border: none; display: block;" /></a>
</td>
</tr>
<tr>
<td align="center" valign="top" style="border-collapse: collapse; border-spacing: 0; margin: 0; padding: 0; padding-left: 6.25%; padding-right: 6.25%; width: 87.5%; font-size: 14px; font-weight: 400; line-height: 150%; letter-spacing: 2px;
padding-bottom: 0;
color: #FFFFFF;
font-family: sans-serif;" class="supheader">
CVE module
</td>
</tr>
<tr>
<td align="center" valign="top" style="border-collapse: collapse; border-spacing: 0; margin: 0; padding: 0; padding-left: 6.25%; padding-right: 6.25%; width: 87.5%; font-size: 24px; font-weight: bold; line-height: 130%;
padding-top: 5px;
color: #FFFFFF;
font-family: sans-serif;" class="header">
Responsive HTML email templates
</td>
</tr>
<tr>
<td align="center" valign="top" style="border-collapse: collapse; border-spacing: 0; margin: 0; padding: 0; padding-left: 6.25%; padding-right: 6.25%; width: 87.5%; font-size: 17px; font-weight: 400; line-height: 160%;
padding-top: 15px;
color: #FFFFFF;
font-family: sans-serif;" class="paragraph">
<strong>CVE : </strong> $CVE <br><br>
<strong>Description :</strong> $DESCRIPTION <br><br>
<strong>Publication date : </strong> $DATE <br><br>
<strong>CVSS Score (V3) : </strong> $SCORE <br><br>
<strong>Status : </strong>$STATUS<br><br>
<strong>CPE/Product : </strong> $CPE<br><br>
<strong>Sources :</strong> $SOURCES <br><br>
</td>
</tr>
<tr>
<td align="center" valign="top" style="border-collapse: collapse; border-spacing: 0; margin: 0; padding: 0; padding-left: 6.25%; padding-right: 6.25%; width: 87.5%;
padding-top: 25px;
padding-bottom: 5px;" class="button"><a
href="https://github.com/Guezone/SECMON" target="_blank" style="text-decoration: underline;">
<table border="0" cellpadding="0" cellspacing="0" align="center" style="max-width: 240px; min-width: 120px; border-collapse: collapse; border-spacing: 0; padding: 0;"><tr><td align="center" valign="middle" style="padding: 12px 24px; margin: 0; text-decoration: underline; border-collapse: collapse; border-spacing: 0; border-radius: 4px; -webkit-border-radius: 4px; -moz-border-radius: 4px; -khtml-border-radius: 4px;"
bgcolor="#E9703E"><a target="_blank" style="text-decoration: underline;
color: #FFFFFF; font-family: sans-serif; font-size: 17px; font-weight: 400; line-height: 120%;"
href="URL OF THE NEWS">
See more details
</a>
</td></tr></table></a>
</td>
</tr>
<tr>
<td align="center" valign="top" style="border-collapse: collapse; border-spacing: 0; margin: 0; padding: 0; padding-left: 6.25%; padding-right: 6.25%; width: 87.5%;
padding-top: 30px;" class="line"><hr
color="#565F73" align="center" width="100%" size="1" noshade style="margin: 0; padding: 0;" />
</td>
</tr>
<tr>
<td align="center" valign="top" style="border-collapse: collapse; border-spacing: 0; margin: 0; padding: 0; padding-left: 6.25%; padding-right: 6.25%; width: 87.5%; font-size: 13px; font-weight: 400; line-height: 150%;
padding-top: 10px;
padding-bottom: 20px;
color: #828999;
font-family: sans-serif;" class="footer">
This email was sent by <a href="https://github.com/Guezone/SECMON" target="_blank" style="text-decoration: underline; color: #828999; font-family: sans-serif; font-size: 13px; font-weight: 400; line-height: 150%;">SECMON</a>.
</td>
</tr>
</table>
</td></tr></table>
</body>
</html>
================================================
FILE: cve_updater.py
================================================
# -*- coding: utf-8 -*-
"""
SECMON - Source code of the SECMON updater script.
"""
__author__ = "Aubin Custodio"
__copyright__ = "Copyright 2021, SECMON"
__credits__ = ["Aubin Custodio","Guezone"]
__license__ = "CC BY-NC-SA 4.0"
__version__ = "2.1"
__maintainer__ = "Aubin Custodio"
__email__ = "custodio.aubin@outlook.com"
from secmon_lib import writeNewExploitFoundLog, getUnexploitableCveIdList,getGithubAPISettings,getRegisteredCveInfos, get_db_connection, getUnregisteredCveInfos, getFormatedProductList, getCveByProduct, writeNewHighRiskProductLog, writeCveTypeLog
from datetime import datetime
import os,requests,time
import cve_searchsploit as CS
script_path = os.path.abspath(__file__)
dir_path = script_path.replace("cve_updater.py","")
log_file = dir_path+"logs.txt"
print("------------ CVE Module - Update ------------")
timestamp = datetime.now().strftime("%d/%m/%Y %H:%M:%S")
print("Starting at : "+timestamp)
print("---------------------------------------------")
CS.update_db()
con = get_db_connection()
cur = con.cursor()
cve_list = getUnexploitableCveIdList()
for cve in cve_list:
exploitdb_exploits = CS.edbid_from_cve(cve)
if len(exploitdb_exploits) > 0:
cur.execute("UPDATE CVE_DATA SET EXPLOIT_FIND = (?) WHERE CVE_ID = (?)", ("True",cve))
con.commit()
print("Exploit found for "+cve+" from Exploit-DB")
writeNewExploitFoundLog("cve_updater","exploit-db",cve,f"New(s) exploit found for {cve} from Exploit-DB !")
print("\nSearch Github Exploit for registered CVE...")
cve_list = getUnexploitableCveIdList()
user,key = getGithubAPISettings()
con = get_db_connection()
cur = con.cursor()
if user == "None" or key == "None":
print("No Github API configuration found.")
else:
for cve in cve_list:
time.sleep(30)
github_query = "https://api.github.com/search/repositories?q=exploit+"+cve
github_response = requests.get(url=github_query,auth=(user,key))
github_data = github_response.json()
if "items" in github_data.keys():
if len(github_data['items']) > 0:
cur.execute("UPDATE CVE_DATA SET EXPLOIT_FIND = (?) WHERE CVE_ID = (?)", ("True",cve))
con.commit()
print("Exploit found for "+cve+" from Github")
writeNewExploitFoundLog("cve_updater","github",cve,f"New exploit found for {cve} from Github !")
print("\nUpdating high risk product list....")
plist = getFormatedProductList()
con = get_db_connection()
cur = con.cursor()
critical_product = []
old_critical_product = []
cur.execute("SELECT hname FROM high_risk_products;")
db_result_list = cur.fetchall()
for db_result_tuple in db_result_list:
for result in db_result_tuple:
if result not in old_critical_product:
old_critical_product.append(result)
for product in plist:
if "cpe" in product[1]:
target_product = product[1]
else:
target_product = product[0]
critical_cve, high_cve, medium_cve, low_cve, na_cve, exploitable_cve = getCveByProduct(target_product, True)
if exploitable_cve != []:
if product[0] not in old_critical_product:
critical_product.append(product)
print("New critical product : "+product[0])
cur.execute("INSERT INTO high_risk_products (cpe,hname) VALUES (?,?);", (product[1],product[0]))
writeNewHighRiskProductLog("cve_updater",product[1],f"A new critical product was discovered. ({product[1]})")
con.commit()
print("\nUpdating affected products and CVSS score related to your CVE list...")
con = get_db_connection()
cur = con.cursor()
req = cur.execute("SELECT CVE_ID FROM CVE_DATA")
indb_cve_list = []
changelog = []
for tup in req:
for cve in tup:
indb_cve_list.append(cve)
for cve in indb_cve_list:
try:
try:
before_update = getRegisteredCveInfos(cve, full=True)
time.sleep(5)
after_update = getUnregisteredCveInfos(cve)
except:
continue
for cpe in before_update['cve_cpe']:
if cpe == '':
before_update['cve_cpe'].remove(cpe)
for item in before_update.keys():
if item == "cve_score":
if str(after_update[item]) != str(before_update[item]):
writeCveTypeLog("cve_updater",cve,"update","N/A",str(after_update[item]),"N/A","N/A","N/A","N/A","The CVSS Score was changed from {} to {}.".format(str(before_update[item]), str(after_update[item])))
changelog.append(cve+" - There has been a change in the CVSS score : {} TO {}\n".format(str(before_update[item]), str(after_update[item])))
print(cve+" - There has been a change in the CVSS score : {} TO {}\n".format(str(before_update[item]), str(after_update[item])))
cur.execute("UPDATE CVE_DATA SET CVE_SCORE = (?) WHERE CVE_ID = (?)", (str(after_update[item]),cve))
con.commit()
elif item == "cve_cpe":
if after_update[item] != before_update[item]:
change = ""
diff = list(set(after_update[item])-set(before_update[item]))
if diff == []:
change = "removed"
diff = list(set(before_update[item])-set(after_update[item]))
cpe_diff = ""
for elem in diff:
if len(diff) == 1 or elem == diff[-1]:
cpe_diff += elem
else:
cpe_diff = cpe_diff+elem+" AND "
else:
change = "added"
cpe_diff = ""
for elem in diff:
if len(diff) == 1 or elem == diff[-1]:
cpe_diff += elem
else:
cpe_diff = cpe_diff+elem+" AND "
writeCveTypeLog("cve_updater",cve,"update","N/A",str(after_update[item]),"N/A","N/A","N/A","N/A","The following products have been {} : {} \n".format(change,cpe_diff))
changelog.append(cve+" - The following products have been {} : {} \n".format(change,cpe_diff))
print(cve+" - The following products have been {} : {} \n".format(change,cpe_diff))
new_cpe = ""
for cpe in after_update[item]:
new_cpe+=(cpe+"\n")
cur.execute("UPDATE CVE_DATA SET CVE_CPE = (?) WHERE CVE_ID = (?)", (new_cpe,cve))
con.commit()
except:
continue
if changelog == []:
print("No CVE have been updated. \n")
timestamp = datetime.now().strftime("%d/%m/%Y %H:%M:%S")
print("---------------------------------------------")
print("Finished at : "+timestamp)
print("---------------------------------------------")
================================================
FILE: docker/install.py
================================================
from time import sleep
import os
from getpass import getpass
print("| SECMON - DockerAutoInstall |")
print("1. Certificate : ")
print("Note 1 : You can delete this self signed cert and put your CA signed cert after install. ")
sleep(2)
fqdn = input("Enter the FQDN of the web server :")
print("Note 2 : Don't forget to enter a good value for CN (FQDN of your server)")
sleep(2)
os.system("openssl req -newkey rsa:4096 -x509 -sha512 -days 3650 -nodes -out /etc/ssl/secmon/secmon.crt -keyout /etc/ssl/secmon/secmon.key")
print("Your certificate is available on /etc/ssl/secmon ! ")
print("----------------------------------------------------------------------------------------------------------------------")
print("2. SECMON Install : ")
sender = input("Sender email address :")
smtp_login = input("SMTP account login :")
smtp_password = getpass("SMTP email account password :")
smtpsrv = input("SMTP Server FQDN or IP :")
smtpport = input("SMTP used port :")
tls = input("Using TLS SMTP auth ? (yes/no) :")
lang = input("Language (en/fr) :")
receivers = input("SECMON email receivers (single or many seperated by ;):")
os.system(f"chown -R www-data:www-data /var/www/secmon && chmod -R 744 /var/www/secmon")
os.system(f"python3 /var/www/secmon/setup.py -login '{smtp_login}' -p '{smtp_password}' -server '{smtpsrv}' -port '{smtpport}' -tls '{tls}' -lang '{lang}' -sender '{sender}' -r '{receivers}'")
print("Executing secmon in background...")
os.system("nohup python3 /var/www/secmon/secmon.py >/dev/null 2>&1 &")
print("Executing cve_updater in background...")
os.system("nohup python3 /var/www/secmon/cve_updater.py >/dev/null 2>&1 &")
print("SECMON is successfully installed and configured !")
print("----------------------------------------------------------------------------------------------------------------------")
print("3. Apache configuration : ")
f = open("/var/www/secmon/docker/secmon.conf").read()
os.system("chown -R www-data:www-data /var/www/secmon/ && chmod -R 744 /var/www/secmon/")
content = f.replace("{FQDN}",fqdn)
f = open("/etc/apache2/sites-enabled/secmon.conf","w")
f.write(content)
f.close()
os.system("a2enmod ssl && service apache2 restart")
print("Apache is successfully configured !")
print(f"You can now access the web interface at the following address: https://{fqdn}")
print("----------------------------------------------------------------------------------------------------------------------")
================================================
FILE: docker/secmon-ci.conf
================================================
ServerName {FQDN}
<VirtualHost *:4443>
WSGIScriptAlias / /var/www/secmon/secmon.wsgi
WSGIDaemonProcess secmon_web
DocumentRoot /var/www/secmon
ServerName {FQDN}
ServerAlias www.{FQDN}
<Directory /var/www/secmon>
WSGIProcessGroup secmon_web
WSGIPassAuthorization On
WSGIApplicationGroup %{GLOBAL}
Order deny,allow
Allow from all
</Directory>
ServerSignature Off
LogLevel info
ErrorLog ${APACHE_LOG_DIR}/error_secmon.log
CustomLog ${APACHE_LOG_DIR}/access_secmon.log combined
SSLProtocol -all +TLSv1.2 +TLSv1.3
SSLEngine on
SSLCertificateFile /etc/ssl/secmon/secmon.crt
SSLCertificateKeyFile /etc/ssl/secmon/secmon.key
</VirtualHost>
================================================
FILE: docker/secmon.conf
================================================
ServerName {FQDN}
<VirtualHost *:80>
ServerAdmin admin@mail.com
ServerName {FQDN}
ServerAlias www.{FQDN}
DocumentRoot /var/www/secmon
Redirect permanent / https://{FQDN}
<Directory /var/www/secmon>
WSGIProcessGroup secmon_web
WSGIPassAuthorization On
WSGIApplicationGroup %{GLOBAL}
Order deny,allow
Allow from all
</Directory>
ServerSignature off
ErrorLog ${APACHE_LOG_DIR}/error_secmon.log
CustomLog ${APACHE_LOG_DIR}/access_secmon.log combined
</VirtualHost>
<VirtualHost *:443>
WSGIScriptAlias / /var/www/secmon/secmon.wsgi
WSGIDaemonProcess secmon_web
DocumentRoot /var/www/secmon
ServerName {FQDN}
ServerAlias www.{FQDN}
<Directory /var/www/secmon>
WSGIProcessGroup secmon_web
WSGIPassAuthorization On
WSGIApplicationGroup %{GLOBAL}
Order deny,allow
Allow from all
</Directory>
ServerSignature Off
LogLevel info
ErrorLog ${APACHE_LOG_DIR}/error_secmon.log
CustomLog ${APACHE_LOG_DIR}/access_secmon.log combined
SSLProtocol -all +TLSv1.2 +TLSv1.3
SSLEngine on
SSLCertificateFile /etc/ssl/secmon/secmon.crt
SSLCertificateKeyFile /etc/ssl/secmon/secmon.key
</VirtualHost>
================================================
FILE: requirements.txt
================================================
Jinja2==3.0.1
Werkzeug==2.0
Flask_SQLAlchemy==2.4.4
requests==2.22.0
colorama==0.4.3
tweepy==3.8.0
openpyxl==3.0.5
git+https://github.com/Guezone/cve_searchsploit
Flask==2.0.3
deep_translator==1.3.2
feedparser==6.0.8
beautifulsoup4==4.9.3
flask_simplelogin==0.0.7
python-dateutil
PyGithub
traceback-with-variables==2.0.4
================================================
FILE: rss_poller.py
================================================
# -*- coding: utf-8 -*-
"""
SECMON - Source code of the SECMON rss poller script.
"""
__author__ = "Aubin Custodio"
__copyright__ = "Copyright 2021, SECMON"
__credits__ = ["Aubin Custodio","Guezone"]
__license__ = "CC BY-NC-SA 4.0"
__version__ = "2.1"
__maintainer__ = "Aubin Custodio"
__email__ = "custodio.aubin@outlook.com"
import base64, os, smtplib, re, requests, sqlite3, feedparser, colorama
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from datetime import datetime, timedelta
from secmon_lib import translateText, getUserLanguage, writeMgmtTasksLog, writeNewRssNewLog,handleException
rss_feeds = [
'https://cyware.com/allnews/feed',
'https://www.cshub.com/rss/categories/attacks',
'https://www.schneier.com/feed/atom/',
'https://www.cshub.com/rss/categories/threat-defense',
'https://www.cshub.com/rss/categories/malware',
'https://www.fortiguard.com/rss/ir.xml',
'https://nakedsecurity.sophos.com/feed/',
'https://www.techrepublic.com/rssfeeds/topic/security/?feedType=rssfeeds',
'https://www.cert.ssi.gouv.fr/feed/',
'https://us-cert.cisa.gov/ncas/all.xml',
'https://www.zataz.com/feed/',
]
sender, receiver, smtp_login, smtp_password, smtpsrv, port, tls, keywords = '','','','','','','',''
script_path = os.path.abspath(__file__)
dir_path = script_path.replace("rss_poller.py","")
log_file = dir_path+"logs.txt"
class bcolors:
HEADER = '\033[95m'
OKBLUE = '\033[94m'
OKGREEN = '\033[92m'
WARNING = '\033[93m'
FAIL = '\033[91m'
ENDC = '\033[0m'
BOLD = '\033[1m'
UNDERLINE = '\033[4m'
def parseRSSSource(source):
if "us-cert.cisa" in source or "cyware.com" in source:
new_source = source.replace("https://","").split(".")[0]
else:
new_source = source.replace("https://","").replace("www.","").split(".")[0]
return new_source
def checkConfig(sender, receivers, smtp_login, smtp_password, smtpsrv, port, tls,rss_feeds):
script_path = os.path.abspath(__file__)
dir_path = script_path.replace("rss_poller.py","")
con = sqlite3.connect(dir_path+'secmon.db')
cur = con.cursor()
cur.execute("SELECT sender FROM config")
db_result_tuple = cur.fetchone()
for value in db_result_tuple:
sender = value
cur.execute("SELECT smtp_login FROM config")
db_result_tuple = cur.fetchone()
for value in db_result_tuple:
smtp_login = value
cur.execute("SELECT smtp_password FROM config")
db_result_tuple = cur.fetchone()
for value in db_result_tuple:
b = value.encode("UTF-8")
bytes_password = base64.b64decode(b)
smtp_password = bytes_password.decode("UTF-8")
cur.execute("SELECT smtpsrv FROM config")
db_result_tuple = cur.fetchone()
for value in db_result_tuple:
smtpsrv = value
cur.execute("SELECT port FROM config")
db_result_tuple = cur.fetchone()
for value in db_result_tuple:
port = value
cur.execute("SELECT receiver FROM config")
db_result_tuple = cur.fetchone()
for value in db_result_tuple:
receivers = value.split(";")
cur.execute("SELECT tls FROM config")
db_result_tuple = cur.fetchone()
for value in db_result_tuple:
tls = value
cur.execute("SELECT language FROM config")
db_result_tuple = cur.fetchone()
for value in db_result_tuple:
language = value
cur.execute("SELECT receiver FROM config")
db_result_tuple = cur.fetchone()
for value in db_result_tuple:
receivers = value.split(";")
cur.execute("SELECT keyword FROM keyword_list")
db_result_list = cur.fetchall()
keywords = []
for db_result_tuple in db_result_list:
for result in db_result_tuple:
keywords.append(result)
if all(value != '' for value in [sender, receivers, smtp_login, smtp_password, smtpsrv, str(port), tls, language]):
print(bcolors.OKGREEN+"Configuration is good."+bcolors.ENDC)
rssPoller(sender, receivers, smtp_login, smtp_password, smtpsrv, port, tls, language, rss_feeds)
else:
print(bcolors.FAIL+"Error in the config."+bcolors.ENDC)
def rssPoller(sender, receivers, smtp_login, smtp_password, smtpsrv, port, tls, language, rss_feeds):
print("------------------------------------")
summary, url = "",""
new = False
con = sqlite3.connect(dir_path+'secmon.db')
cur = con.cursor()
for rss_feed in rss_feeds:
current_feed = feedparser.parse(rss_feed)
for entries in current_feed.entries:
url = entries.link
cur.execute("SELECT RSS_URL FROM RSS_DATA WHERE RSS_URL = (?);", (url,))
db_result_list = cur.fetchall()
db_result_str = ""
for db_result_tuple in db_result_list:
for result in db_result_tuple:
db_result_str+=result
if url not in db_result_str:
new = True
title = entries.title
summary = entries.summary
if summary == "":
summary+="Empty summary."
dest_language = getUserLanguage()
try:
title = translateText(dest_language,title)
summary = translateText(dest_language,summary)
except:
pass
cur.execute("INSERT INTO RSS_DATA (RSS_URL, title, rss_f, summary) VALUES (?,?,?,?);", (url,title,rss_feed,summary))
con.commit()
try:
sendAlert(smtp_login, smtp_password, smtpsrv, port, tls, sender, receivers, title, summary, url, language, rss_feed)
mail = "sent"
except Exception as e:
handleException(e)
mail = "unsent"
writeNewRssNewLog("rss_poller",parseRSSSource(rss_feed),rss_feed,title,url,mail)
if new == True:
print(bcolors.OKGREEN+"Database was updated. Goodbye."+bcolors.ENDC)
else:
print(bcolors.OKGREEN+"No news. Goodbye."+bcolors.ENDC)
print("------------------------------------")
timestamp = datetime.now().strftime("%d/%m/%Y %H:%M:%S")
print(bcolors.OKBLUE+"Finished at : "+timestamp+bcolors.ENDC)
print("------------------------------------")
def sendAlert(smtp_login, smtp_password, smtpsrv, port, tls, sender, receivers, title, summary, url, language, rss_feed):
body = ""
for receiver in receivers:
with open(dir_path+'rss_template.html', 'r') as template:
html_code = template.read()
html_code = html_code.replace("$SOURCE", parseRSSSource(rss_feed))
if language == "fr" or language=="FR":
html_code = html_code.replace("See more details", "Voir plus de détails")
html_code = html_code.replace("This email was sent by", "Cet email a été envoyé par")
html_code = html_code.replace("Notification", "Information")
html_code = html_code.replace("RSS module", "Module RSS")
html_code = html_code.replace("$TITLE", title)
html_code = html_code.replace("$SUMMARY", summary)
html_code = html_code.replace("Title", "Titre")
html_code = html_code.replace("Summary", "Résumé")
body = html_code.replace("URL OF THE NEWS",url)
else:
html_code = html_code.replace("$TITLE", title)
html_code = html_code.replace("Notification", "News")
html_code = html_code.replace("$SUMMARY", summary)
body = html_code.replace("URL OF THE NEWS",url)
print(bcolors.HEADER+"Sending news at {}...".format(receiver)+bcolors.ENDC)
try:
smtpserver = smtplib.SMTP(smtpsrv,port)
msg = MIMEMultipart()
msg['Subject'] = 'SECMON - RSS'
msg['From'] = sender
msg['To'] = receiver
msg.attach(MIMEText(body, 'html'))
except Exception as e:
handleException(e)
print(bcolors.FAIL+"Failed to send news at {}.".format(receiver)+bcolors.ENDC)
exit()
try:
if tls == "yes":
smtpserver.ehlo()
smtpserver.starttls()
smtpserver.login(smtp_login, smtp_password)
smtpserver.sendmail(sender, receiver, msg.as_string())
print(bcolors.HEADER+"News was sent at {}\n".format(receiver)+bcolors.ENDC)
elif tls == "no":
smtpserver.login(smtp_login, smtp_password)
smtpserver.sendmail(sender, receiver, msg.as_string())
print(bcolors.HEADER+"News was sent at {}\n".format(receiver)+bcolors.ENDC)
except Exception as e:
handleException(e)
print(bcolors.FAIL+"An error occurred during authentication with the SMTP server. Check the configuration and try again."+bcolors.ENDC)
exit()
def main():
print()
colorama.init()
print("------------ RSS Module ------------")
timestamp = datetime.now().strftime("%d/%m/%Y %H:%M:%S")
print(bcolors.OKBLUE+"Starting at : "+timestamp+bcolors.ENDC)
print("------------------------------------")
checkConfig(sender, receiver, smtp_login, smtp_password, smtpsrv, port, tls,rss_feeds)
main()
================================================
FILE: rss_template.html
================================================
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0;">
<meta name="format-detection" content="telephone=yes"/>
<style type="text/css">span.preheader { display: none !important; } </style>
<style>
body { margin: 0; padding: 0; min-width: 100%; width: 100% !important; height: 100% !important;}
body, table, td, div, p, a { -webkit-font-smoothing: antialiased; text-size-adjust: 100%; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; line-height: 100%; }
table, td { mso-table-lspace: 0pt; mso-table-rspace: 0pt; border-collapse: collapse !important; border-spacing: 0; }
img { border: 0; line-height: 100%; outline: none; text-decoration: none; -ms-interpolation-mode: bicubic; }
#outlook a { padding: 0; }
.ReadMsgBody { width: 100%; } .ExternalClass { width: 100%; }
.ExternalClass, .ExternalClass p, .ExternalClass span, .ExternalClass font, .ExternalClass td, .ExternalClass div { line-height: 100%; }
@media all and (min-width: 560px) {
.container { border-radius: 8px; -webkit-border-radius: 8px; -moz-border-radius: 8px; -khtml-border-radius: 8px; }
}
a, a:hover {
color: #FFFFFF;
}
.footer a, .footer a:hover {
color: #828999;
}
</style><title>SECMON - RSS</title><link rel="icon" href="https://github.com/Guezone/SECMON" />
</head>
<body topmargin="0" rightmargin="0" bottommargin="0" leftmargin="0" marginwidth="0" marginheight="0" width="100%" style="border-collapse: collapse; border-spacing: 0; margin: 0; padding: 0; width: 100%; height: 100%; -webkit-font-smoothing: antialiased; text-size-adjust: 100%; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; line-height: 100%;
background-color: #222222;
color: #FFFFFF;"
bgcolor="#222222"
text="#FFFFFF">
<span class="preheader">$SUMMARY</span>
<table width="100%" align="center" border="0" cellpadding="0" cellspacing="0" style="border-collapse: collapse; border-spacing: 0; margin: 0; padding: 0; width: 100%;" class="background"><tr><td align="center" valign="top" style="border-collapse: collapse; border-spacing: 0; margin: 0; padding: 0;"
bgcolor="#222222">
<table border="0" cellpadding="0" cellspacing="0" align="center"
width="500" style="border-collapse: collapse; border-spacing: 0; padding: 0; width: inherit;
max-width: 500px;" class="wrapper">
<tr>
<td align="center" valign="top" style="border-collapse: collapse; border-spacing: 0; margin: 0; padding: 0; padding-left: 6.25%; padding-right: 6.25%; width: 87.5%;
padding-top: 20px;
padding-bottom: 20px;">
<a target="_blank" style="text-decoration: none;"
href="https://github.com/Guezone/SECMON"><img border="0" vspace="0" hspace="0"
src="https://guezone.info/projets/secmon/logo.png"
width="50" height="50"
alt="Logo" title="Logo" style="
color: #FFFFFF;
font-size: 10px; margin: 0; padding: 0; outline: none; text-decoration: none; -ms-interpolation-mode: bicubic; border: none; display: block;" /></a>
</td>
</tr>
<tr>
<td align="center" valign="top" style="border-collapse: collapse; border-spacing: 0; margin: 0; padding: 0; padding-left: 6.25%; padding-right: 6.25%; width: 87.5%; font-size: 14px; font-weight: 400; line-height: 150%; letter-spacing: 2px;
padding-bottom: 0;
color: #FFFFFF;
font-family: sans-serif;" class="supheader">
RSS module
</td>
</tr>
<tr>
<td align="center" valign="top" style="border-collapse: collapse; border-spacing: 0; margin: 0; padding: 0; padding-left: 6.25%; padding-right: 6.25%; width: 87.5%; font-size: 24px; font-weight: bold; line-height: 130%;
padding-top: 5px;
color: #FFFFFF;
font-family: sans-serif;" class="header">
Notification
</td>
</tr>
<tr>
<td align="center" valign="top" style="border-collapse: collapse; border-spacing: 0; margin: 0; padding: 0; padding-left: 6.25%; padding-right: 6.25%; width: 87.5%; font-size: 17px; font-weight: 400; line-height: 160%;
padding-top: 15px;
color: #FFFFFF;
font-family: sans-serif;" class="paragraph">
<strong>Title : </strong> $TITLE <br><br>
<strong>Source : </strong> $SOURCE <br><br>
<strong>Summary :</strong> $SUMMARY <br>
</td>
</tr>
<tr>
<td align="center" valign="top" style="border-collapse: collapse; border-spacing: 0; margin: 0; padding: 0; padding-left: 6.25%; padding-right: 6.25%; width: 87.5%;
padding-top: 25px;
padding-bottom: 5px;" class="button"><a
href="https://github.com/Guezone/SECMON" target="_blank" style="text-decoration: underline;">
<table border="0" cellpadding="0" cellspacing="0" align="center" style="max-width: 240px; min-width: 120px; border-collapse: collapse; border-spacing: 0; padding: 0;"><tr><td align="center" valign="middle" style="padding: 12px 24px; margin: 0; text-decoration: underline; border-collapse: collapse; border-spacing: 0; border-radius: 4px; -webkit-border-radius: 4px; -moz-border-radius: 4px; -khtml-border-radius: 4px;"
bgcolor="#E9703E"><a target="_blank" style="text-decoration: underline;
color: #FFFFFF; font-family: sans-serif; font-size: 17px; font-weight: 400; line-height: 120%;"
href="URL OF THE NEWS">
See more details
</a>
</td></tr></table></a>
</td>
</tr>
<tr>
<td align="center" valign="top" style="border-collapse: collapse; border-spacing: 0; margin: 0; padding: 0; padding-left: 6.25%; padding-right: 6.25%; width: 87.5%;
padding-top: 30px;" class="line"><hr
color="#565F73" align="center" width="100%" size="1" noshade style="margin: 0; padding: 0;" />
</td>
</tr>
<tr>
<td align="center" valign="top" style="border-collapse: collapse; border-spacing: 0; margin: 0; padding: 0; padding-left: 6.25%; padding-right: 6.25%; width: 87.5%; font-size: 13px; font-weight: 400; line-height: 150%;
padding-top: 10px;
padding-bottom: 20px;
color: #828999;
font-family: sans-serif;" class="footer">
This email was sent by <a href="https://github.com/Guezone/SECMON" target="_blank" style="text-decoration: underline; color: #828999; font-family: sans-serif; font-size: 13px; font-weight: 400; line-height: 150%;">SECMON</a>.
</td>
</tr>
</table>
</td></tr></table>
</body>
</html>
================================================
FILE: secmon.py
================================================
# -*- coding: utf-8 -*-
"""
SECMON - Launcher of poller script.
"""
__author__ = "Aubin Custodio"
__copyright__ = "Copyright 2021, SECMON"
__credits__ = ["Aubin Custodio","Guezone"]
__license__ = "CC BY-NC-SA 4.0"
__version__ = "2.1"
__maintainer__ = "Aubin Custodio"
__email__ = "custodio.aubin@outlook.com"
import cve_poller
import rss_poller
================================================
FILE: secmon.wsgi
================================================
import sys
sys.path.insert(0, "/var/www/secmon")
from secmon_web import app as application
================================================
FILE: secmon_lib.py
================================================
# -*- coding: utf-8 -*-
"""
SECMON - Library for SECMON python web backend.
"""
__author__ = "Aubin Custodio"
__copyright__ = "Copyright 2021, SECMON"
__credits__ = ["Aubin Custodio","Guezone"]
__license__ = "CC BY-NC-SA 4.0"
__version__ = "2.1"
__maintainer__ = "Aubin Custodio"
__email__ = "custodio.aubin@outlook.com"
from flask import Flask, url_for, render_template, send_from_directory, request, flash, redirect, safe_join, session, url_for, session, abort
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from time import sleep
from dateutil.relativedelta import relativedelta
from openpyxl import Workbook
from openpyxl.styles import Font, Color, Alignment, Border, Side, colors, PatternFill
from openpyxl.utils import get_column_letter
from openpyxl.worksheet.dimensions import ColumnDimension
from deep_translator import GoogleTranslator, MyMemoryTranslator
import jinja2.exceptions, sqlite3,requests, feedparser, re, smtplib, os, tweepy, base64, time, socket, random
from datetime import datetime, timedelta
from werkzeug.security import generate_password_hash, check_password_hash
from flask_sqlalchemy import sqlalchemy, SQLAlchemy
from flask_simplelogin import is_logged_in
from bs4 import BeautifulSoup
import cve_searchsploit as CS
import secmon_monitor,traceback
from multiprocessing import Process, Queue
from datetime import *
from github import Github
from traceback_with_variables import print_exc
rss_feeds = [
'https://cyware.com/allnews/feed',
'https://www.cshub.com/rss/categories/attacks',
'https://www.schneier.com/feed/atom/',
'https://www.cshub.com/rss/categories/threat-defense',
'https://www.cshub.com/rss/categories/malware',
'https://www.fortiguard.com/rss/ir.xml',
'https://nakedsecurity.sophos.com/feed/',
'https://www.techrepublic.com/rssfeeds/topic/security/?feedType=rssfeeds',
'https://www.cert.ssi.gouv.fr/feed/',
'https://us-cert.cisa.gov/ncas/all.xml',
'https://www.zataz.com/feed/',
]
messages = {
'login_success': 'Login success.',
'login_failure': 'Bad Username, bad password or bad request.',
'logout': 'You have been successfully logged out.',
'login_required': 'Please sign-in.',
'access_denied': 'Access denied.',
'auth_error': 'Error: {0}'
}
def sortWordsByOccurrences(word_stats):
word_stats.sort(key = lambda x: x[1])
return word_stats[::-1]
def getTopThreats():
git_key,git_username = getGithubAPISettings()
git_access = Github(git_key)
mcafee_repo = git_access.get_repo("advanced-threat-research/Yara-Rules")
contents = mcafee_repo.get_contents("")
yara_list = []
while contents:
file_content = contents.pop(0)
if file_content.type == "dir":
contents.extend(mcafee_repo.get_contents(file_content.path))
else:
if ".yar" in str(file_content) and not "Eicar" in str(file_content):
threat = str(file_content).replace('ContentFile(path="',"").replace('.yar")',"").split("/")[0],str(file_content).replace('ContentFile(path="',"").replace('.yar")',"").split("/")[1].split("_",1)[1]
yara_list.append([threat[0].title().replace("_","").replace("Apt","APT"),threat[1].title().replace("_","")])
return yara_list
def getNewsTopSubject():
top_words = []
fr_common_words = ["de","la","le","et","les","des","en","un","du","une","que","est","pour","qui","dans","a","par","plus","pas","au","sur","ne","se","Le","ce","il","sont","La","Les","ou","avec","son","Il","aux","d'un","En","cette","d'une","ont","ses","mais","comme","on","tout","nous","sa","Mais","fait","été","aussi","leur","bien","peut","ces","y","deux","A","ans","l","encore","n'est","marché","d","Pour","donc","cours","qu'il","moins","sans","C'est","Et","si","entre","Un","Ce","faire","elle","c'est","peu","vous","Une","prix","On","dont","lui","également","Dans","effet","pays","cas","De","millions","Belgique","BEF","mois","leurs","taux","années","temps","groupe","ainsi","toujours","société","depuis","tous","soit","faut","Bruxelles","fois","quelques","sera","entreprises","F","contre","francs","je","n'a","Nous","Cette","dernier","était","Si","s'est","chez","L","monde","alors","sous","actions","autres","Au","ils","reste","trois","non","notre","doit","nouveau","milliards","avant","exemple","compte","belge","premier","s","nouvelle","Elle","l'on","terme","avait","produits","cela","d'autres","fin","niveau","bénéfice","toute","travail","partie","trop","hausse","secteur","part","beaucoup","Je","valeur","croissance","rapport","USD","aujourd'hui","année","base","Bourse","lors","vers","souvent","vie","l'entreprise","autre","peuvent","bon","surtout","toutes","nombre","fonds","point","grande","jour","va","avoir","nos","quelque","place","grand","personnes","plusieurs","certains","d'affaires","permet","politique","cet","chaque","chiffre","pourrait","devrait","produit","l'année","Par","rien","mieux","celui","qualité","France","Ils","Ces","s'agit","vente","jamais","production","action","baisse","Avec","résultats","Des","votre","risque","début","banque","an","voir","avons","qu'un","qu'","elles","moment","qu'on","question","pouvoir","titre","doute","long","petit","d'ailleurs","notamment","FB","droit","qu'elle","heures","cependant","service","Etats-Unis","qu'ils","l'action","jours","celle","demande","belges","ceux","services","bonne","seront","économique","raison","car","situation","Depuis","entreprise","me","nouvelles","n'y","possible","toutefois","tant","nouveaux","selon","parce","dit","seul","qu'une","sociétés","vient","jusqu'","quatre","marchés","mise","seulement","Van","semble","clients","Tout","Cela","serait","fort","frais","lieu","gestion","font","quand","capital","gouvernement","projet","grands","réseau","l'autre","données","prendre","plan","points","outre","pourtant","Ainsi","ni","type","Europe","pendant","Comme","mesure","actuellement","public","dire","important","mis","partir","parfois","nom","n'ont","veut","présent","passé","forme","autant","développement","mettre","grandes","vue","investisseurs","D","trouve","maison","mal","l'an","moyen","choix","doivent","NLG","direction","Sur","simple","période","enfants","dollars","personnel","assez","programme","général","banques","eux","semaine","président","personne","européenne","moyenne","tard","loi","petite","certaines","savoir","loin","explique","plupart","jeunes","cinq","contrat","Banque","valeurs","seule","rendement","nombreux","fonction","offre","client","activités","eu","environ","ministre","cadre","sens","étaient","sécurité","recherche","Paris","sorte","décembre","Son","suite","davantage","ensuite","janvier","donne","vrai","cause","d'abord","conditions","suis","juin","peine","certain","septembre","sommes","famille","l'indice","pris","laquelle","directeur","qu'en","propose","gens","derniers","étant","fut","chose","portefeuille","obligations","afin","différents","technique","Aujourd'hui","ailleurs","P","l'ensemble","américain","ventes","Selon","rue","livre","octobre","vraiment","sein","Or","dollar","Enfin","haut","Plus","petits","porte","tel","durée","domaine","aurait","jeune","présente","passe","PC","lorsque","choses","puis","Vous","aucun","l'un","n'en","tandis","coup","existe","propre","carte","crise","importante","atteint","revenus","montant","forte","ici","s'il","Quant","vu","rapidement","j'ai","ville","etc","mars","s'en","mon","premiers","bas","marque","véritable","ligne","longtemps","propres","devant","passer","départ","pu","total","série","quoi","particulier","concurrence","élevé","position","connu","principe","tendance","court","n","pages","évidemment","résultat","aura","parmi","Sans","américaine","face","trouver","durant","femmes","construction","désormais","distribution","telle","difficile","autour","européen","pratique","centre","vendre","juillet","mai","région","sociale","filiale","film","h","besoin","mode","Pas","représente","réalité","femme","vaut","Tél","aucune","hommes","donner","titres","l'Europe","nombreuses","différentes","moyens","formation","chiffres","Générale","dix","prochain","l'Etat","genre","bureau","communication","participation","gros","pourquoi","estime","devient","réalisé","création","novembre","l'évolution","pourra","semaines","consommation","faible","terrain","site","droits","moitié","puisque","Du","reprise","compris","projets","avril","vont","call","donné","simplement","six","firme","perte","Bien","Philippe","sait","prend","vite","via","stratégie","vos","jeu","J'","petites","marketing","presque","Michel","manque","réaliser","financiers","Car","Comment","voiture","chef","constitue","Internet","J'ai","enfin","net","charge","nature","second","payer","actuel","Elles","investissements","dispose","financier","d'achat","membres","date","avaient","gamme","revanche","comment","décision","l'avenir","tour","actionnaires","s'y","solution","créer","l'économie","concerne","l'époque","belle","lequel","tél","seconde","version","Pays-Bas","cher","chacun","lire","techniques","décidé","mouvement","conseil","nécessaire","meilleur","double","sujet","généralement","restent","celles","politiques","malgré","confiance","homme","d'actions","Certains","ayant","papier","commerce","Région","Wallonie","Windows","termes","met","contraire","informations","l'industrie","trimestre","E","différence","certaine","formule","jusqu'au","voit","programmes","actuelle","permis","dossier","Quand","l'heure","guerre","acheter","rendre","février","ma","l'emploi","main","voire","bons","technologie","européens","Sa","éléments","unique","l'eau","venir","générale","courant","suffit","l'ordre","conserver","maximum","force","fax","Que","largement","milliard","soient","Pierre","devenir","l'Union","franc","minimum","mort","responsable","possibilité","presse","affaires","longue","travers","M","BBL","relativement","moi","Deux","présence","européennes","devraient","groupes","ensemble","santé","New","pense","bénéfices","but","compagnie","publique","coeur","revenu","mesures","table","nettement","questions","d'avoir","permettre","l'homme","Chez","retour","qu'elles","C","majorité","potentiel","moindre","récemment","secteurs","réduction","large","traitement","perdu","étrangers","parents","l'une","fond","capacité","vitesse","activité","l'exercice","l'objet","quel","tient","taille","éviter","risques","Jean","Pourtant","Allemagne","parler","propos","quant","signifie","voie","jouer","prévoit","blanc","noir","parti","logiciel","continue","Notre","bois","meilleure","l'argent","perspectives","développer","celui-ci","oeuvre","structure","suivre","tiers","prise","professionnels","raisons","néanmoins","preuve","social","bénéficiaire","couleurs","mondial","Cet","maintenant","essentiellement","prévu","Japon","prévisions","centrale","Alors","international","yeux","PME","l'a","ait","bonnes","opérations","pied","l'art","pourraient","Londres","juge","devra","uniquement","corps","divers","Parmi","numéro","réduire","Tous","texte","tenu","budget","l'étranger","pression","mes","n'était","style","économiques","Jacques","montre","population","analystes","S","processus","placement","classique","dividende","rester","publics","fortement","plein","wallonne","DEM","Express","faudra","travailler","Crédit","directement","prime","Flandre","crédit","monnaie","précise","appel","Autre","travaux","l'occasion","juste","Chaque","put","tableau","terre","permettent","devenu","rouge","mémoire","partenaires","rapide","travailleurs","joue","objectif","salle","parle","musique","milieu","d'entreprise","autorités","chute","régime","d'autant","liste","opération","bout","performances","électronique","haute","responsables","lancé","voitures","patron","Malgré","affiche","situe","B","l'image","études","Microsoft","condition","retrouve","Aux","revient","Belgacom","route","Ensuite","Luxembourg","campagne","comptes","hors","culture","Commission","d'entre","possibilités","semestre","actifs","finalement","internationale","l'achat","monétaire","passage","of","justice","page","tels","poids","celle-ci","commercial","entendu","l'investisseur","mondiale","accord","diverses","totalement","fil","clair","vin","biens","euro","York","parfaitement","viennent","division","réseaux","principal","lancer","supérieur","atteindre","référence","téléphone","management","vins","proche","collection","fiscale","Ceci","informatique","investissement","volume","matériel","publicité","train","coupon","progression","tenir","protection","l'aide","couleur","nouvel","Lorsque","change","changement","garantie","somme","Belge","plaisir","fils","laisse","importants","privé","ses","besoins","oeuvres","américains","relations","peau","moteur","augmentation","suivi","volonté","beau","bancaire","laisser","bureaux","principalement","intéressant","logiciels","sommet","l'activité","d'en","vivre","élevés","Robert","contrats","oublier","performance","réponse","d'exploitation","concept","obtenir","poste","attendre","lignes","consiste","augmenté","vert","Ou","figure","mot","développé","l'histoire","magasins","collaboration","répondre","TVA","holding","G","livres","convient","fonctions","fera","pouvait","million","Paul","britannique","d'entreprises","voix","Grande-Bretagne","disque","affaire","minutes","quelle","contexte","limite","mains","commun","réduit","Pourquoi","particuliers","verre","wallon","d'Etat","allemand","effets","Chine","meilleurs","rend","applications","d'ici","procédure","l'opération","devait","profit","méthode","pose","commence","idée","l'Internet","d'eau","créé","nuit","Nord","capitaux","options","consommateur","cartes","soi","métier","probablement","aller","d'investissement","facile","International","importantes","Marc","capitale","devise","prochaine","transport","Street","demander","utilisateurs","l'affaire","image","l'idée","propriétaire","facilement","publiques","croire","disponible","Louis","d'or","veulent","Charleroi","Ne","consommateurs","devises","difficultés","sort","national","machines","annoncé","choisi","découvrir","soutien","avez","perdre","cuisine","telles","D'autres","travaille","R","ouvert","phase","certainement","télévision","pratiquement","annuel","bord","paiement","Bank","institutions","seuls","arrive","constate","marques","nationale","regard","représentent","Belges","état","Qui","libre","rachat","Toutefois","portes","sortir","commandes","permettant","manager","fiscal","cinéma","histoire","zone","sauf","avantages","l'information","voici","dur","effectivement","puisse","réel","The","puissance","fixe","Belgium","contact","époque","rythme","principaux","vendu","utilisé","étude","Leur","sensible","Bref","rencontre","L'entreprise","spécialistes","brut","mauvais","néerlandais","supplémentaire","mots","reprises","nécessaires","Non","soir","Prix","machine","penser","CD","parts","comprend","fusion","acquis","totale","voyage","logique","l'échéance","concurrents","idées","trouvé","dette","Sud","réellement","financement","disponibles","vieux","lance","marge","dirigeants","avis","changer","conséquence","sociales","supérieure","Certes","faisant","ordinateur","partenaire","warrant","fabrication","redressement","suffisamment","délégué","pourront","poursuit","chemin","emplois","l'environnement","réalise","FRF","évolution","Cour","automobile","Premier","ancien","note","parties","pension","professionnel","assure","garder","Rien","Actuellement","DE","S'il","l'administration","Guy","est-il","IBM","climat","d'acheter","SICAV","département","sept","partout","immobilier","lancement","rating","réussi","patrimoine","feu","expérience","Anvers","anciens","graphique","Fortis","faveur","retrouver","droite","responsabilité","commande","Kredietbank","d'argent","direct","l'inflation","n'avait","utiliser","tonnes","l'origine","connaissance","acheté","Ici","américaines","clairement","semblent","biais","futur","neuf","chance","faillite","km","équipe","musée","compagnies","documents","pertes","sortie","m'a","seraient","d'autre","choisir","l'instant","tellement","industriel","précompte","d'Europe","immédiatement","avantage","qu'au","constituent","déchets","sport","van","demeure","garde","maisons","Solvay","conséquences","KB","l'offre","active","dépenses","donnent","employés","sites","élections","détient","n'importe","obligation","fruits","véhicule","l'égard","Conseil","investi","mission","profiter","visite","comprendre","professionnelle","affirme","l'intérieur","Wall","charges","privée","rares","succession","liberté","rentabilité","suivant","efficace","assurer","images","agences","impossible","m","John","enfant","fournisseurs","photo","salaires","Avant","compter","l'Est","disposition","formes","bénéficiaires","lesquels","maintenir","précisément","couple","enregistré","recul","offrir","peur","hauteur","centres","voulu","industrielle","positif","Luc","administrateur","intéressante","commerciale","interne","pleine","passant","vision","GSM","faits","retard","certes","l'air","lundi","Outre","porter","écrit","cesse","locaux","délai","trouvent","classiques","commencé","réalisée","Alain","vigueur","gagner","Celui-ci","Philips","ceux-ci","favorable","pouvoirs","participations","annonce","génération","élément","devenue","touche","conseils","devoir","mer","souligne","respectivement","rapports","vacances","lieux","naturellement","d'y","lorsqu'il","statut","USA","ceci","destiné","défaut","objectifs","récente","saison","d'art","industriels","Suisse","catégorie","complexe","huit","l'obligation","fisc","obtenu","repris","occupe","sérieux","émis","Quelques","comportement","limité","vingt","conjoncture","gauche","marche","d'origine","l'utilisateur","ordre","mobilier","parcours","perspective","normes","recours","l'esprit","Communauté","annuelle","T","lecteur","objets","fabricant","niveaux","Entre","réalisation","amateurs","conséquent","présenter","Celle-ci","vise","types","détail","mauvaise","professeur","progressé","signe","passée","approche","p","Reste","return","jardin","l'espace","flamand","Namur","bilan","Vif","sensiblement","Trois","utilise","commune","dimanche","option","partis","analyse","films","surface","warrants","GBP","prises","secret","historique","journée","l'ancien","Pendant","allemande","d'assurance","André","fille","l'importance","proposer","avions","x","augmenter","parc","Delhaize","the","Lors","limitée","appareils","villes","au-dessus","diminution","prochaines","servir","Bernard","commission","faiblesse","plus-value","souhaite","internationales","producteur","producteurs","code","belles","cabinet","fonctionnement","FF","gérer","cm","mouvements","pratiques","régions","dossiers","meilleures","Parce","entrée","vendredi","actif","sociaux","supplémentaires","café","message","physique","Société","communes","dizaine","faute","sélection","source","facteurs","milliers","soleil","tirer","concernant","Bourses","fallait","sentiment","bénéficier","débat","l'Allemagne","élevée","ouvrage","police","pouvez","attention","a-t-il","bel","constructeurs","contribuable","moderne","passion","primes","in","suit","auquel","dépasse","spécialisée","bruxellois","déclaration","multiples","quartier","vidéo","dépend","l'école","liquidités","correction","CA","comité","Web","cherche","filiales","Sous","signé","leader","calcul","gaz","D'abord","Rens","artistes","déficit","cadres","fédéral","probable","remboursement","and","efforts","restaurant","Toutes","couverture","domicile","soins","devront","luxe","complet","danger","indispensable","syndicats","comporte","faite","juridique","langue","rendez-vous","d'informations","demandé","respect","continuer","l'organisation","lesquelles","local","l'impression","n'existe","rare","restructuration","automatiquement","plat","boursier","sol","c'était","cotées","décide","L'action","Cependant","Certaines","matériaux","ordinateurs","tradition","V","progressivement","capable","classe","familiale","réserve","fonctionne","solutions","LA","fabricants","paie","Finances","l'été","réelle","changé","masse","unités","considéré","fer","auront","noms","riche","Patrick","proposé","salon","territoire","fixé","magasin","candidats","marges","asiatique","inférieur","réaction","fleurs","l'effet","record","tribunal","recettes","poursuivre","dessous","portant","Aussi","Sabena","acteurs","dehors","constructeur","l'auteur","relation","offrent","spectaculaire","LUF","produire","confort","familles","investir","reprend","sert","montrer","mérite","places","Soit","judiciaire","textes","quasi","SNCB","jeux","permettra","étudiants","membre","photos","positions","sud","Cockerill","lendemain","cent","gagné","japonais","l'absence","mark","pointe","solide","Voici","anglais","n'ai","présentent","décisions","législation","médias","victimes","écran","nécessairement","découverte","l'assuré","club","environnement","noter","crée","exportations","négociations","Jan","répond","BEL","entier","business","peinture","s'était","voisins","faibles","location","nord","promotion","technologies","auraient","caisse","entend","simples","maladie","menu","chances","commerciaux","printemps","Benelux","poser","Asie","l'utilisation","usage","PIB","actionnaire","prennent","résistance","Dow","II","surprise","Etats","mariage","nécessité","Puis","cote","Plusieurs","beauté","exclusivement","lettre","payé","rendu","s'ils","software","utile","gestionnaires","bénéficie","procédé","vaste","crois","normal","Centre","construire","démarche","emprunts","naissance","D'autant","Co","d'information","distance","tourner","Club","attendant","quantité","roi","l'assureur","tourne","ajoute","bancaires","ajouter","géant","automatique","faux","attend","litres","présenté","argent","confirme","indépendants","l'ordinateur","énorme","destinés","l'avantage","véhicules","ressources","standard","auparavant","construit","Quelle","principales","quelqu'un","disposer","global","écoles","Quel","réputation","fameux","rappelle","conseille","heure","veille","difficulté","l'état","limites","commerciales","samedi","palais","vend","vit","Tractebel","connaissent","reprendre","village","emploi","amis","budgétaire","croit","mises","souci","contient","habitants","Weekend","bras","beaux","bruxelloise","faisait","introduit","intérieur","outils","précis","chercheurs","taxe","salaire","transactions","Christian","chambre","portée","réflexion","AG","C'était","d'emploi","hasard","matin","assureurs","réforme","Beaucoup","fournir","recherches","liés","tenue","proposent","aide","ferme","l'enfant","l'or","secondes","CGER","contenu","quotidien","flamande","centaines","course","billet","critique","l'arrivée","naturel","principale","support","week-end","Dehaene","Gand","chargé","économies","Nos","augmente","guide","proposition","laissé","spécialiste","francophones","importance","vent","conception","préférence","spectacle","avenir","d'entrée","grave","commencer","d'années","diminuer","chercher","bonheur","dizaines","LE","d'environ","exactement","outil","scénario","Jones","coups","émissions","éventuellement","Royale","l'agence","soumis","d'exercice","lecture","monter","Grand","central","exigences","assuré","contacts","consacré","l'attention","d'administration","due","faut-il","réussite","échéance","recevoir","tableaux","arriver","évident","PS","art","Italie","amélioration","auteurs","estimé","quinze","Russie","demain","précédent","vendeur","événements","autrement","experts","fortes","furent","possibles","circonstances","placer","publication","l'écran","réserves","sauce","venu","Charles","collaborateurs","implique","l'assurance","obligataire","établi","CD-Rom","H","forcément","l'essentiel","l'enseignement","remarquable","vol","Claude","tourisme","internationaux","directe","compétences","conseiller","facteur","l'est","plastique","rarement","Royal","affiché","lutte","relative","actuels","envie","l'équipe","ministres","secrétaire","capitalisation","langage","positive","circulation","convaincre","notion","visage","vouloir","ajoutée","caractéristiques","Eric","Union","paix","puisqu'il","courrier","disposent","développe","présentation","barre","comparaison","déterminer","firmes","fournisseur","informatiques","luxembourgeois","achats","solde","Serge","globale","propriété","stratégique","Renault","partage","porté","sources","Kong","cour","destinée","N","absolument","branche","l'objectif","ouvre","plans","productivité","Résultat","améliorer","d'obtenir","joué","Parlement","dépit","fichiers","personnalité","constitué","gestionnaire","né","profession","qualités","conscience","médecin","celles-ci","design","décor","faudrait","participer","appelle","forces","suisse","appareil","conduite","D'une","longueur","tarifs","vérité","lien","locales","francophone","clubs","correspond","coupons","d'émission","estiment","défi","protéger","réalisés","d'emplois","d'éviter","l'ouverture","méthodes","revenir","superbe","volontiers","document","nommé","tente","financer","scientifique","Georges","travaillent","l'investissement","lié","zones","aime","lettres","ouverte","Hong","L'année","murs","philosophie","rappeler","utilisés","suivante","d'année","représentant","traduit","remettre","situé","différente","longs","économie","discours","distributeur","domaines","l'introduction","régional","faites","italien","restera","usine","Group","l'informatique","personnage","portent","attendu","l'option","Jean-Pierre","articles","changements","fallu","léger","mener","propriétaires","spécifique","récupérer","voyages","procéder","locale","médecins","privés","transmission","concurrent","courte","quart","baisser","pieds","publié","Ford","menace","réunion","transfert","composé","dimension","personnages","ralentissement","conclusion","l'usage","agents","parfum","rémunération","difficiles","l'entrée","mettent","pierre","proches","réglementation","salles","grimpé","prochains","prévue","électrique","dynamique","exposition","installé","plancher","distributeurs","déclare","connue","n'avons","préparation","réalisées","beurre","opérateurs","achat","province","spécifiques","Albert","l'usine","l'existence","renforcer","téléphonique","comptable","effectuer","trafic","degré","l'ont","définitivement","humain","optique","remarque","talent","appelé","modifier","définition","peintre","respecter","stade","statistiques","certificats","s'attend","limiter","livraison","placements","raconte","volumes","immobiliers","Fax","anciennes","chevaux","médicaments","Peter","feuilles","football","identique","pouvons","remise","structures","tenter","accords","cotisations","indice","neutre","Mon","constituer","d'accord","montrent","placé","loyer","proximité","voient","épouse","Canada","entrer","postes","précision","cité","concours","patrons","populaire","pétrole","négatif","allemands","d'activité","roman","victime","italienne","ménages","repas","PetroFina","langues","tendances","D'autre","pire","prudence","savent","Néanmoins","conduit","mille","rénovation","égard","Américains","exercice","l'étude","s'impose","avance","effectué","fortune","fournit","lecteurs","Morgan","découvert","l'inverse","différent","emploie","bleu","royal","technologique","télécommunications","Amsterdam","fiscales","indique","information","lourd","signal","Ed","Mieux","aider","ancienne","apporte","nette","prestations","publicitaires","sensibles","communauté","l'émission","lit","volatilité","étape","assurance","jusqu'en","lancée","résoudre","garanti","modification","revue","spéciale","www","chacune","l'analyse","différences","messages","priorité","recommandation","récent","charme","dividendes","Olivier","passent","finale","immeubles","logement","pourcentage","rire","stabilité","difficilement","défense","l'ancienne","magazine","D'un","Y","eaux","jeunesse","l'intention","continuent","révolution","étonnant","organisation","constater","dos","emprunt","oui","éditions","Daniel","sel","utilisée","compartiment","publicitaire","EN","article","bande","capacités","centrales","considérée","milieux","occasion","quasiment","pouvant","Vermeulen-Raemdonck","visiteurs","chambres","considérablement","demi","découvre","essentiel","broker","dettes","mardi","reconnaissance","salariés","formules","grosse","heureux","perd","radio","allait","multimédia","partiellement","seules","Gérard","Oui","Securities","toucher","jugement","l'oeuvre","considérer","remplacer","couvrir","précieux","segment","dessins","espace","indices","refuse","chefs","exemples","rejoint","spécialisé","l'amour","l'exportation","objet","précédente","rose","versions","d'études","destination","Encore","deviennent","ET","l'Italie","personnelle","plats","vingtaine","l'expérience","virus","Faut-il","chasse","longues","Toute","bases","cotée","final","monnaies","travaillé","apporter","aspects","disparu","David","Management","port","racheter","relever","Celui","ING","catalogue","centaine","chaleur","profil","représentants","SA","conclu","réside","scientifiques","Chambre","secondaire","Fin","serveur","XIXe","exige","grimper","immeuble","l'Université","montants","paysage","vendus","ton","assurances","catégories","dure","décote","soutenir","édition","dangereux","agréable","voulait","combien","d'application","disparition","optimiste","plus-values","tomber","erreur","l'augmentation","situations","spécialisés","subi","suivent","Jusqu'au","classement","l'exemple","norme","rentable","sang","socialiste","tombe","Justice","attitude","mines","qu'aux","liée","plantes","vague","General","l'immobilier","légumes","Ceux-ci","conflit","excellent","licence","travailleur","appris","est-elle","gagne","mari","préparer","purement","située","vérifier","Jean-Luc","gain","métal","surfaces","L'objectif","d'épargne","douze","expliquer","lorsqu'on","meubles","yen","chaussures","créée","institution","l'accent","solidarité","Maastricht","basée","journal","soin","sourire","Guerre","bouteilles","flexibilité","maintient","appartient","moments","rouges","L'an","basé","devons","installations","Bacob","association","d'obligations","format","City","Page","disques","modem","mélange","ordinaire","vide","chimique","disent","pharmaceutique","d'assurances","numérique","porteur","répartition","blanche","composants","future","parvient","évoque","Durant","calme","cru","Electrabel","culturel","grosses","baissé","lois","moteurs","principes","trente","éventuelle","Peu","prévoir","tours","Pentium","acheteur","dimensions","fonctionnaires","organisé","rencontré","russe","savoir-faire","établissements","Fédération","Toujours","créativité","top","application","dépasser","importe","jaune","l'application","marqué","mécanique","socialistes","tranche","Quelles","envisage","traiter","Surtout","acheteurs","chinois","claire","l'Institut","vécu","Objectif","bail","demandes","diversification","montré","renseignements","souscription","Tokyo","entendre","tests","Siemens","filles","unité","Bekaert","Dr","UCB","composition","resté","sinon","agence","fini","modifications","Cash","industrielles","obtient","permanence","restaurants","réels","échange","florins","l'accord","terrains","émergents","atouts","offrant","LES","bouche","champ","chaud","l'annonce","monte","preneur","présents","quitte","tarif","facture","fiscaux","modeste","processeur","Fund","avenue","compétition","relevé","tenté","Est-ce","Musée","W","bijoux","différentiel","déclaré","institutionnels","l'employeur","traité","Intel","traditionnels","victoire","connus","correctement","pub","Dominique","Tant","accessible","rencontrer","stocks","Art","espérer","jouent","menée","nécessite","provenant","utilisent","affichent","délais","inférieure","sent","spécial","Amérique","acquérir","album","idéal","l'écart","véritables","associé","candidat","connaissances","l'énergie","signes","cheveux","conserve","stress","d'Anvers","d'action","directeurs","donnée","endroit","l'emprunt","l'impact","der","traditionnelle","Martin","ciel","convention","obligataires","prouver","Espagne","O","Petit","Source","dessin","humaine","l'huile","lait","Seule","Thierry","boursiers","continent","destinées","flamands","néerlandaise","pensions","commencent","considérable","nationales","nul","s'adresse","conjoint","crédits","militaire","morceaux","privatisation","repose","sommeil","traditionnel","PSC","Seul","capables","combat","finances","puissant","s'agissait","Bill","Renseignements","physiques","Richard","allant","créations","toile","évidence","convaincu","excellente","or","retraite","théorie","transformer","Tour","transaction","visant","Deutsche","Mons","attentes","cycle","détails","Votre","héros","l'artiste","l'université","sérieusement","uns","Ceux","considération","impose","propositions","Autrement","cap","forts","l'Afrique","usines","Afin","Quels","aisément","ressemble","risquent","totalité","imaginer","originale","intégré","intéressantes","l'extérieur","loyers","auxquels","circuit","indépendant","intérieure","jus","maintien","cotisation","l'Asie","moyennes","quitter","stable","CVP","Compaq","galerie","liens","souffle","GIB","apprendre","concert","l'exception","l'échelle","liquide","nez","noire","température","transparence","école","champion","diminué","désir","ressort","voulons","équipé","alimentaire","den","organisations","présidence","raisonnable","ratio","recommande","utilisant","accepter","accepté","cache","chocolat","chuté","comparer","courts","figurent","passagers","prison","viande","associés","esprit","froid","jeudi","liées","revu","satisfaction","satisfaire","test","tiennent","vraie","contrairement","dépassé","extérieur","qu'avec","ami","American","Etat","complémentaire","déclarations","réactions","Fonds","artiste","conclure","déduction","remis","L'indice","déterminée","fiscalité","grand-chose","humaines","réponses","équipes","ITL","Michael","Systems","aspect","commercialisation","manger","RTBF","engagé","obligé","proportion","signature","étranger","imposé","s'applique","silence","vote","Afrique","Mobistar","cible","contemporain","fondateur","Jean-Claude","communiquer","d'investir","existent","majeure","ouvrir","électroniques","JPY","TGV","compétitivité","erreurs","notation","rang","Apple","GB","accident","certificat","exceptionnel","http","proprement","riches","Barco","Quoi","violence","adapté","bénéficient","récession","sentir","armes","arrivé","crainte","garanties","l'automne","ménage","officiellement","ouvriers","Autant","discussion","rejoindre","époux","citoyens","concernés","d'inflation","définir","L'idée","Paribas","Telecom","d'aller","fabrique","feront","née","oblige","patients","pensent","responsabilités","SP","doublé","fraude","l'article","organise","Henri","conclut","désire","l'appareil","l'association","l'installation","législateur","écrans","choc","gratuit","mobile","naturelle","dialogue","révision","familial","lourde","poche","décider","négociation","tort","Maison","Trésor","constante","cotation","déterminé","l'instar","managers","opté","transformation","Life","anniversaire","compétence","géographique","I","mandat","réservé","établir","Business","fins","richesse","CAD","commente","intermédiaire","l'univers","retrouvé","sciences","Sun","banquier","former","monté","parfait","veux","René","investit","l'oeil","n'aurait","parvenir","vieille","Di","collections","dirige","fonctionner","mauvaises","tapis","venus","Contrairement","Suez","piste","pistes","tensions","campagnes","investis","proposés","sac","tabac","bataille","britanniques","fine","liégeois","partenariat","privées","remplir","supérieurs","Beaux-Arts","Christie's","laser","restauration","Dutroux","chimie","rendent","textile","Brabant","Colruyt","James","National","Quatre","préalable","souvenir","venue","Communal","avocat","comparable","consolidé","critiques","interdit","l'initiative","mine","quotidienne","rigueur","réduite","tissu","Invest","pain","participants","procédures","profondeur","retrouvent","rues","taxation","Mexique","asiatiques","conducteur","demandent","environs","fermeture","gris","rumeurs","accueille","amoureux","d'augmenter","défendre","l'immeuble","pure","souffre","créneau","d'énergie","journaux","s'explique","seuil","Jeux","Office","auteur","cash-flow","fichier","foi","instruments","quelles","séance","véritablement","Yves","attirer","civil","civile","d'aujourd'hui","eau","l'épargne","station","courbe","hectares","influence","ingénieurs","tables","vivent","Exemple","L'un","blancs","couche","cuir","devenus","extraordinaire","patient","peux","aient","animaux","associations","d'utiliser","foie","initiative","l'Amérique","poursuite","survie","Face","K","apparemment","consultant","expansion","l'exposition","séjour","champagne","commentaires","complexes","cylindres","décennie","rendements","retenu","sais","sujets","cuivre","offert","réagir","sec","varie","Fondation","artistique","communications","monétaires","métaux","permanente","positifs","électriques","Ph","basse","concentration","investisseur","provoqué","doux","stations","coin","modifié","avocats","estimations","original","souplesse","Attention","Frank","Hainaut","Suite","annuels","cellule","clause","exemplaires","malheureusement","minute","normale","Frédéric","NT","Sud-Est","atout","latine","logements","pilotes","susceptibles","Roger","XVIIIe","ordres","remarquer","actuelles","bouteille","constat","opportunités","prépare","vendeurs","accrue","fruit","g","jugé","l'amélioration","loisirs","pur","trentaine","bus","gendarmerie","air","alimentaires","coté","modernes","préciser","réussir","laissent","parfaite","spécialement","évoluer","Dewaay","Désormais","Groupe","maladies","négligeable","tension","Lion","chansons","dite","festival","négative","préféré","restant","Cera","adopté","coopération","distingue","douceur","retirer","technologiques","Editions","Parfois","bruit","comptant","démocratie","exception","mercredi","offres","sucre","vedette","évolue","British","Leurs","compromis","hauts","élevées","émission","Faire","attendue","d'appel","jusqu'ici","lourds","quels","soirée","événement","alternative","chimiques","conférence","quitté","serveurs","Brésil","CD-ROM","correspondant","l'avis","locataire","matériau","périodes","utilisées","ai","d'emblée","l'aspect","morale","équilibre","Sony","fixer","gratuitement","trait","Trop","adultes","consacrer","d'importance","normalement","parole","prochainement","suscite","verra","clé","mesurer","notes","potentiels","relatives","Flamands","Francfort","L'homme","Palais","Plan","République","l'armée","transports","Portugal","couvert","joueurs","Malheureusement","coupe","dispositions","effort","endroits","aides","contribution","insiste","s'inscrit","souhaitent","communal","impact","progresser","Sambre","US","administrateurs","d'ordre","deviendra","dégager","formations","l'ouvrage","souscrire","cellules","facilité","gras","militaires","passés","quinzaine","souvient","Se","automobiles","bref","confortable","essentielle","officiel","vive","vols","Marcel","Top","combinaison","distinction","définitive","japonaise","liaison","tissus","cadeau","canadien","distribué","existants","ordinaires","servi","surveillance","l'architecture","l'aéroport","médecine","n'aura","n'étaient","revoir","récentes","voies","L'obligation","Rappelons","comptabilité","fabriquer","fasse","intéressants","peintures","quartiers","valable","étapes","bénéficié","couvre","diminue","envers","introduire","missions","s'attendre","Petrofina","apparition","coffre","digne","fibres","initiatives","littérature","rembourser","retrait","Bundesbank","D'ailleurs","Ma","Pascal","Pologne","consacre","employeur","favorables","l'approche","manquent","assurée","battre","chantier","conclusions","consulter","craindre","d'utilisation","vivant","Chacun","internes","apprend","liégeoise","observe","provenance","sortes","Marie","cessé","céder","estimée","marchandises","Poste","balance","copie","cuisson","négocier","spéciaux","traite","Bruges","hollandais","peut-on","porteurs","régler","soutenue","suivie","Stanley","accueillir","médical","notoriété","provoquer","sensibilité","su","vocation","L'investisseur","for","impression","l'ampleur","séduit","conflits","imposable","journalistes","manifeste","provoque","wallons","éditeurs","EUR","canal","fondamentale","futurs","graves","mené","mur","pommes","racheté","remonte","solides","suffisante","chargée","chers","discussions","garantit","indicateurs","provient","soutenu","sportif","systématiquement","zéro","comptent","recette","récit","subir","évolué","Johan","accorde","faciliter","hausses","Macintosh","Services","d'imposition","débuts","garantir","portefeuilles","susceptible","universités","Glaverbel","Sotheby's","actes","brasserie","caractéristique","cherchent","cp","favoriser","justement","prudent","stock","échelle","énormément","Standard","compose","couronne","exceptionnelle","flux","j'étais","justifier","réfugiés","t","téléphoniques","Monsieur","Ville","accepte","inspiré","l'ombre","pollution","situent","allemandes","boissons","douce","gouvernements","intervention","motifs","primaire","World","entrepreneurs","l'efficacité","représentation","Thomas","apparaissent","complémentaires","cycliques","franchement","instrument","rayon","Food","Roi","conversion","partager","retenue","simplicité","Comité","confirmé","devaient","expériences","front","jeter","logistique","reconnu","Affaires","Heureusement","comédie","historiques","imposer","l'actionnaire","obligatoire","recourir","références","traces","témoigne","GBL","Java","Vu","acte","appliquer","catastrophe","conduire","contribué","fais","intervenir","mettant","pilote","plafond","remplacement","tire","Berlin","Vincent","portable","profonde","refusé","repos","béton","fermé","juges","parlementaires","prévention","Donc","d'électricité","dispositif","forment","neige","suffisant","Louvain","TV","diffusion","fédération","lentement","prenant","souris","tu","contenter","douleur","intervient","j'avais","look","manoeuvre","parquet","poussé","arguments","billets","consacrée","dirigeant","décoration","holdings","justifie","levier","majeur","midi","recyclage","robe","Entre-temps","appels","directive","initial","intéressés","pousser","pouvaient","secrets","surpris","univers","d'avis","poisson","spécialisées","séduire","verser","d'investissements","générations","nettoyage","ouverts","réductions","vélo","Anne","Compagnie","Souvent","d'Amsterdam","explique-t-il","l'abri","l'intégration","officielle","résolution","Service","courses","l'exploitation","pari","pousse","revendre","trace","abonnés","craint","croissant","juger","régionale","symbole","touristes","Rome","actives","communautaire","contraintes","journaliste","traditionnelles","variable","amour","atelier","budgets","budgétaires","clef","d'ores","détriment","nationaux","paquet","relatif","Francis","Rupo","d'enfants","diesel","gare","l'acquisition","parlent","rapporte","regarder","éventuel","Clabecq","carrés","psychologique","rupture","téléphonie","Air","Danemark","Sauf","citoyen","four","permettrait","puissent","rapides","Marketing","Tendances","dit-il","développements","enregistre","envoyé","intermédiaires","l'issue","liquidité","réagi","Allemands","L'autre","Louise","connues","consolidation","créateur","idéale","l'espoir","profité","prévus","résulte","similaire","Boeing","Didier","Dieu","MB","Willy","agir","coins","constaté","d'eux","danse","occidentale","optimistes","pensée","professionnelles","Computer","San","Tournai","appliquée","chanson","déroule","franchir","liquidation","morts","nouveauté","prestigieux","suppression","Laurent","Mercedes","existantes","pleinement","simultanément","établissement","cercle","corruption","discipline","familiales","l'avant","laboratoire","livrer","montée","participe","Personne","adresse","finance","génie","leasing","versement","bits","concernées","dents","inclus","maximale","précédemment","routes","variations","équipements","Declerck","chemins","constituée","d'effectuer","globalement","libres","proposant","souligner","Bon","ambitions","croissante","décennies","fou","l'influence","littéralement","motivation","rubrique","souvenirs","surprises","vendue","Celles-ci","bébé","plainte","stockage","écrire","énergie","Spector","annonceurs","d'olive","débats","ferait","grain","sont-ils","séparation","tournant","vendues","Compte","Cools","Volvo","accessoires","constitution","consultants","dommages","occupé","s'appelle","échanges","Seconde","adresses","efficacité","fixée","frappe","l'apparition","monopole","panneaux","restée","sentiments","terminé","utiles","Bruno","Seuls","appliqué","donnant","fondamentaux","fréquemment","l'aventure","métiers","planche","royale","suppose","Inc","Moins","fourni","japonaises","mm","payés","profond","programmation","résolument","L'Europe","d'amour","d'ouvrir","golf","poudre","","","proposées","étoiles","PRL","attaché","concevoir","dommage","l'opinion","main-d'oeuvre","récents","stratégiques","vitesses","Peugeot","Philip","apprécié","connexion","hommage","jardins","remonter","supplément","Canal","Tessenderlo","cheval","entretien","inutile","l'Espagne","laissant","mécanisme","nouveautés","placés","repli","régionales","régionaux","souple","symbolique","troubles","évaluer","Aucun","Mac","Régions","cession","confie","moyennant","numéros","portrait","établie","cinquantaine","d'assurer","peuple","promis","retenir","réception","sexe","utilisation","visiblement","X","acteur","créateurs","dites","déposer","expositions","handicap","lourdes","plastiques","procure","proviennent","sous-jacente","Ni","Quick","Virgin","auxquelles","banquiers","baptisé","finit","venait","volant","Fiat","Joseph","Lyonnais","enseignants","geste","l'UCL","sérieuse","Mignon","Royaume-Uni","Vers","classes","doigts","encadré","froide","niche","prévision","servent","Baudouin","Nicolas","Smeets","arrivée","domestique","envisager","espaces","filet","inflation","posé","promouvoir","roues","Assurances","Capital","immense","incontestablement","lot","pharmacie","restructurations","sportive","L'ensemble","ci-dessus","d'activités","engagements","humains","introduction","organisée","Delvaux","assiste","couverts","franchise","L'histoire","annuellement","arrivent","causes","pierres","valent","volet","Hanart","Karel","Lotus","intention","l'acheteur","manifestement","prendra","profondément","relance","suivantes","suspension","commissions","divisions","développée","employé","fourchette","qu'est","s'occupe","vendent","Clinton","Jean-Marie","Maurice","Nationale","compenser","d'octobre","essayer","fondé","formidable","graphiques","professeurs","tester","George","Histoire","boutique","caméra","d'avance","fondée","heureusement","label","montagne","pensons","plate-forme","temporaire","tombé","tribunaux","évite","BMW","Monde","PB","condamné","culturelle","d'air","entre-temps","entrées","installer","perception","sauver","thé","Fermé","Peut-on","Unilever","accompagné","externe","franchi","jadis","manifestation","miracle","moral","refus","réunit","révéler","s'installe","Etienne","Evidemment","bateau","conseillé","d'écart","décrit","fréquence","l'occurrence","s'adresser","taxes","Company","concentrer","consultation","dorénavant","dynamisme","installée","profite","réunions","amateur","avoirs","calculé","d'atteindre","estimation","exerce","bloc","circuits","couper","courante","d'améliorer","d'instruction","effectués","fameuse","intéressé","montage","prévues","subsides","séduction","traités","trouvera","équipés","Aucune","ingénieur","réclame","rémunérations","tentent","tournent","égale","émetteurs","Prenons","agent","attentif","d'aide","d'oeil","existant","fluctuations","gré","l'administrateur","médicament","partiel","permanent","s'installer","situés","sportifs","vertu","Intranet","L'évolution","Quelque","allons","appartements","duquel","kilos","sicav","toit","versées","chaussée","d'huile","futures","individuelle","manifestations","raisonnement","sports","Christophe","DES","absolue","appelée","contente","d'idées","d'investisseurs","intense","money","répondent","tranches","Waterloo","assurent","calculer","choisit","citer","doté","fixes","inférieurs","mensuel","promoteurs","relais","sorti","télé","voisin","Corée","Lynch","dit-on","hiver","l'Association","l'ULB","naturelles","preuves","présentés","souffert","Qu'est-ce","attendent","camions","camp","contenant","curieux","détente","effectue","géants","l'endroit","l'intermédiaire","légale","n'étant","prestation","publiés","rente","réalisent","ski","soigneusement","vif","Cie","conviction","doubler","morceau","racines","tenant","universitaires","visiter","Center","Global","démarrage","entamé","fondamental","l'intervention","magique","procurer","records","universitaire","vrais","L'une","ateliers","avion","confronté","contribuables","doigt","drame","féminin","habitudes","l'immédiat","lutter","pétrolier","supérieures","vois","AEX","Bell","afficher","confirmer","conservé","d'offrir","détour","fusions","l'avons","l'équilibre","lever","malades","ouvrages","paradis","prouve","prévoient","remplacé","spéculation","Rwanda","concernent","départements","dérivés","identiques","marquée","n'avaient","prince","produisent","résidence","voulez","L'opération","Turquie","allocations","démontrer","enregistrée","individuelles","oublié","parking","proposée","Commerce","Guide","Tom","comprenant","débuté","engagement","fit","légal","participé","passées","présentant","présentes","quantités","échapper","Maystadt","Software","acquisitions","affirment","alentours","assureur","autonomie","canaux","inverse","l'adresse","l'automobile","modes","signaler","signée","Goldman","Notons","cancer","carnet","convergence","foule","indispensables","intégrée","nucléaire","opérateur","paiements","palette","pence","priori","promesses","tentative","Belgian","Corporation","Dutch","Tel","aérienne","boutiques","craignent","débiteur","entités","ouverture","procureur","puisqu'elle","sommets","supporter","traitements","voyageurs","Bureau","anglaise","argument","d'établir","imaginé","l'appui","mécanismes","personnelles","privilégié","satisfait","science","terrasse","tiré","trésorerie","télécoms","D'ici","chaude","coupé","esthétique","inscrit","poissons","refuser","s'effectue","tennis","Moi","Unix","appartement","clavier","démontre","organismes","pressions","regroupe","secours","sous-traitance","théorique","accessibles","courants","d'été","judiciaires","l'innovation","l'opérateur","précédentes","réaliste","aventure","d'Internet","effectifs","gains","l'opposition","l'unité","musées","rock","Coupe","Netscape","bain","déposé","espoirs","majoritaire","semblait","Digital","accorder","attire","d'échange","feuille","initiale","installation","krach","malade","opérationnel","pauvres","pont","préserver","publier","rechercher","recrutement","représenter","révélé","sanctions","traditionnellement","vapeur","Cobepa","Salon","confier","considérés","cultures","hypothécaire","illustre","introduite","l'échec","menus","multinationales","paient","pareil","problématique","quarantaine","rentrée","soutient","terminée","voudrait","carré","exemplaire","lorsqu'ils","nulle","posent","pratiquer","sida","versements","visites","étions","étrange","CBR","berline","cash","distinguer","durs","défend","efficaces","essence","exclu","jolie","photographe","propriétés","veau","DU","Journal","Nobel","Vieux","atteinte","chapitre","concertation","dégage","extérieurs","médicale","pareille","patience","recueillis","substance","transforme","voile","échec","Léopold","enthousiasme","fédérale","gloire","préparations","transmettre","visiteur","éd","Ajouter","Brederode","Européens","Jean-Louis","Tony","apporté","d'importantes","l'acier","libéralisation","observateurs","panique","présentée","réserver","signer","tendre","to","touristique","Récemment","brillant","conventions","décret","généreux","industries","joie","stars","égal","Sachs","continué","dessert","espagnol","est-ce","légende","passera","rapprochement","salariale","scolaire","Monétaire","assurément","contraint","coton","curiosité","entité","entré","l'architecte","libéraux","logo","parlementaire","parviennent","portables","provisoirement","routier","réservée","tourné","veiller","FN","Hoogovens","XVIIe","arbres","communs","employeurs","exercices","faisons","l'alimentation","magazines","maintenu","roses","répondu","spécialité","Citibank","Moscou","Times","accidents","adapter","amené","avoue","collectif","d'évaluation","dessus","indépendante","l'institution","l'établissement","peintres","rappel","réalisations","s'avérer","architectes","comprise","essentielles","examen","fidélité","héritiers","l'actualité","préférable","relancer","s'adapter","s'engage","sable","semestriels","significative","suisses","Grande","Nouveau","cadeaux","comportements","constamment","contribuer","d'images","offerts","périphérie","varient","Michelin","caisses","conscient","cédé","effectuées","faisaient","personnalités","s'engager","syndicat","Arbed","OPA","abandonné","cents","destin","drogue","fines","identité","invités","l'événement","modalités","négatifs","paru","répertoire","s'intéresse","Disney","Isabelle","Japonais","Roland","William","annoncée","champignons","défis","générer","russes","situer","supprimer","élu","Jean-Paul","Spa","accordé","acquise","courtier","d'attente","foulée","noirs","résister","section","signaux","sombre","susciter","compartiments","correspondance","créances","discret","dépassent","florin","formé","frappé","papiers","représentait","saurait","versé","absence","d'Or","d'acquérir","d'avenir","degrés","envoyer","joli","occupent","on-line","percée","priorités","processeurs","restés","résume","soie","travaillant","économistes","Etant","affirmer","ambitieux","cerveau","consensus","coordination","d'options","l'appel","magistrats","qualifié","rangs","tournée","Alcatel","Toyota","anonyme","c","cassation","cf (usually cf.)","confusion","discrétion","fondamentalement","initialement","installés","l'assemblée","l'entretien","l'émetteur","maman","nuances","paraissent","parfums","saine","vedettes","DM","Nikkei","dirigée","duo","enseigne","indiqué","kg","lourdement","module","prononcer","réalisateur","réformes","star","équivalent","Danone","Site","adopter","commis","couches","explication","joint-venture","malaise","pantalon","pomme","reine","sacs","saumon","soeur","toiles","échéant","Agusta","bond","courir","expert","glace","l'enseigne","multiplier","pluie","salons","teint","European","Finalement","Maintenant","adaptée","diriger","gérant","répartis","saveurs","souscrit","substances","vieilles","vraisemblablement","élaboré","émettre","certitude","champions","cotés","cyclique","détenteurs","explications","fonctionnent","générales","invite","l'expression","pauvre","successeur","zinc","Big","Claes","Six","brochure","cave","codes","configuration","d'enregistrement","fragile","féminine","issus","magnifique","maintenance","manuel","qu'a","recommandé","spectaculaires","subit","traduction","évidente","Conséquence","Fabrimétal","KBC","adaptés","chronique","d'IBM","enregistrés","fibre","jazz","jusque","louer","médiatique","peser","rentables","réussit","s'élevait","saisir","semble-t-il","visible","Financial","Singapour","absolu","blanches","boulevard","commissaire","comprennent","créent","faculté","histoires","individus","issue","multiplient","prétexte","quotidiens","réfléchir","satellites","souffrent","standards","Washington","commercialise","directs","diversité","gratuite","l'Office","logiquement","ouvertes","renoncer","calculs","compléter","couples","d'entrer","d'esprit","d'importants","l'acte","organiser","payant","paysages","récupération","slogan","Electric","PVC","administratives","arts","avancé","carrément","changes","crédibilité","déplacement","l'avance","parvenu","relatifs","revues","veste","Celle","FGTB","Moody's","assurés","créés","d'éléments","immédiat","jambes","litre","mousse","prestige","sentent","souhait","touché","élus","Belle","Telinfo","abrite","considérables","d'urgence","disait","faillites","oeil","religieux","rédaction","séries","terres","vice-président","MHz","System","XXe","cure","dirigé","don","enregistrer","juridiques","pouce","précises","prétend","réunis","salade","trouvait","évaluation","Cinq","Fort","confié","cuire","indicateur","l'avait","origines","parlé","remet","spéciales","terrible","témoignent","étonnante","Buffett","Catherine","Research","SAP","Véronique","achetée","généraux","imposée","l'organisme","l'édition","mention","merveille","opposition","réorganisation","satellite","scanner","Milan","Notamment","a-t-elle","acier","ch","conteste","créanciers","d'acier","intégrés","l'habitude","multiplication","panier","pharmaceutiques","quelconque","rayons","spectateurs","transformé","troupes","Madame","Tandis","effectuée","fromage","géré","interlocuteur","législatives","motif","métalliques","placée","réclamation","schéma","surplus","transition","trio","Coca-Cola","Motors","Proximus","Wallons","atteignent","bleus","chair","conforme","costume","d'accueil","intentions","l'horizon","l'électricité","manqué","sortent","subsiste","supermarchés","D'Ieteren","Européenne","Lorsqu'on","amélioré","avantageux","d'applications","engagée","espoir","exceptions","fausse","l'expansion","l'équivalent","plage","plaide","poivre","CHF","Livres","cadastral","chips","comptait","craintes","d'ordinateurs","durable","démocratique","exceptionnels","factures","fonctionnaire","fondation","indépendance","inventé","issu","maturité","mobilité","musiciens","organisme","recommandations","spéculatif","suscité","titulaire","traverse","évolutions","BD","Fed","calendrier","collective","disposant","dévaluation","l'honneur","pauvreté","poursuivi","qualifier","savait","suédois","termine","traduire","valait","CSC","Forges","Hugo","Max","VVPR","appartiennent","confrontés","demeurent","divorce","dramatique","déductibles","efficacement","existence","fermeté","imagine","intégrer","larges","locataires","orienté","pensé","variété","administrations","aériennes","complexité","entrent","exercer","photographie","sauvage","terminer","venant","Corp","amortissements","champs","déplacer","désigné","déterminant","opportunité","piano","remontée","s'agisse","étroite","AT","Difficile","Dix","Recticel","bar","concerné","constructions","l'identité","merveilleux","min","moindres","réunir","survivre","ultime","étudié","Lambert","RC","caractérise","choisie","distribuer","décidément","limités","livré","luxembourgeoise","modules","progresse","promet","redresser","tombée","bains","d'hommes","dessine","enfance","finition","jury","mythe","optimale","pair","plateau","poussée","resteront","Zaventem","assurance-vie","composée","d'entretien","décident","hélas","instant","jet","laine","mobiles","parcs","préoccupations","ramener","représenté","soudain","éditeur","José","L'auteur","Morris","Nasdaq","administrative","autorise","banking","humour","jouit","l'actuel","market","n'ait","organisateurs","peint","s'annonce","s'assurer","sculptures","superbes","équipée","ASBL","CMB","Gates","bronze","catholique","citron","contributions","couture","disquette","démarrer","excellence","fatigue","imprimantes","industrie","l'aménagement","l'effort","l'encontre","laboratoires","menées","meuble","mondiaux","réduits","sont-elles","sous-traitants","talents","Christine","Henry","administratif","administration","ailes","aérien","carrosserie","d'économie","découvertes","exclure","hautes","hiérarchie","impressionnant","massivement","métro","possession","remporté","strictement","suédoise","utilisateur","vais","émises","étage","d'arbitrage","devez","expliquent","file","hebdomadaire","intéresse","l'hiver","l'élaboration","marbre","performant","personnels","prévenir","suivants","verte","viendra","Angleterre","Association","Hongrie","L'affaire","Louvain-la-Neuve","OS","apportent","automne","bourgmestre","branches","carton","contraste","courage","d'analyse","datant","dépendra","feux","importations","plantations","sidérurgie","signale","FMI","Jean-Michel","Léon","Super","UN","Venise","adaptation","allure","attachés","exploite","folie","instance","naturels","olympique","populaires","reprenant","valorisation","villa","villages","Est-il","Renaissance","Shell","Vienne","architecture","authentique","autonome","complicité","d'au","d'ouverture","dépendance","dépense","fiable","invention","lancés","partagent","rencontres","renouvellement","évoluent","Akzo","Combien","Marché","Xavier","ampleur","analyses","bandes","canard","collectionneurs","compliqué","culturelles","d'avril","donnera","déplacements","fermer","jugée","l'aise","médaille","notaire","peut-il","privilégier","prototype","regain","regarde","wallonnes","Emile","Volkswagen","accru","caoutchouc","cinquante","communautaires","conjoncturel","créant","durer","délicat","exigent","précédents","renforce","s'ouvre","évalué","Lille","débute","définitif","engagés","exploiter","fur","positives","réparation","soupe","transferts","Ostende","Propos","Victor","limitées","nourriture","offertes","ramené","reculé","remédier","similaires","triste","écarts","Data","Industries","abaissé","boire","break","chien","consacrés","cours-bénéfice","fuite","gigantesque","imprimante","l'Ouest","l'emballage","l'église","remplace","salariaux","spectacles","vache","velours","étudie","ABN","Auparavant","Cité","Continent","Guido","Meuse","Mo","Question","d'exemple","dotée","défini","définit","délicate","démission","extérieure","interventions","jouant","l'engagement","n'ayant","noires","obligés","Bruxellois","Mark","Motorola","accéder","affichait","chemise","espagnole","fleur","gardé","habitation","huile","l'accueil","légales","multiplié","revers","architecte","assister","axes","concerts","contemporains","discuter","dose","détiennent","folle","l'éditeur","magie","pompe","provisions","rapidité","témoignages","Cap","Festival","Finlande","NDLR","contribue","demandeurs","démonstration","exact","numériques","participent","poignée","puissants","spécialités","G-Banque","III","Livre","Peeters","SICAFI","Technology","applique","copies","flacon","lunettes","mixte","nullement","plante","provisoire","publie","puissante","regrette","s'ajoute","stratégies","typique","vocale","Anhyp","Brothers","brokers","concentre","diagnostic","faciles","gestes","guise","hardware","opérer","orientée","passionné","refusent","scénarios","suffisent","vagues","écart","Chrysler","Sénat","Via","ambiance","appartenant","assisté","attrayant","bagages","blocs","d'essai","d'histoire","d'étude","déduire","forfait","manquer","restait","surprenant","sérénité","vertus","écouter","DKK","Dirk","Gevaert","HP","Santé","Wim","accueilli","affichés","affronter","appeler","coloris","composent","contiennent","contrepartie","fondamentales","impressionnante","largeur","peaux","proportions","reconversion","revente","significatif","écrite","énormes","J'aime","Network","aiment","cherché","chinoise","décharge","député","essais","indiquent","infrastructures","jouets","musicale","mutation","obstacle","partant","perdent","étudiant","J'avais","Sinon","accordée","adjoint","débarrasser","débit","dégustation","déjeuner","glisse","individu","l'éducation","l'électronique","organisées","produite","prétendre","quotidiennement","s'étend","secondaires","soucieux","sous-évaluation","verts","écologique","émet","Hollywood","Legrand","Lorsqu'il","Pro","améliorée","bat","e-mail","excessive","favorise","joueur","l'OCDE","marks","office","phrase","promenade","prometteur","stimuler","séances","tiendra","valoir","Martine","Québec","acquisition","augmentent","baisses","distribue","dus","massif","médiocre","obtenus","rentrer","sales","semblable","transmis","Julie","Place","ZAR","bouquet","ceinture","coalition","comptables","corporate","d'actifs","d'attendre","différemment","dits","italiens","journées","l'assurance-vie","linguistique","marchands","n'avoir","opinion","originales","registre","requis","synergies","tunnel","vogue","Malaisie","charbon","emballages","esprits","examiner","fléchi","l'outil","librement","mentalité","miroir","occidentaux","parité","progressive","sensation","sonore","supports","synonyme","vinaigre","Début","Euro","Hollandais","alliance","barres","chargés","d'habitants","dois","fier","gouverneur","l'atelier","l'humour","n'avez","origine","payée","pétroliers","signalé","variation","Né","Point","XVIe","aliments","caméras","comportant","consultance","contemporaine","déclin","effectif","invité","j'en","l'actif","licenciement","match","millénaire","salarié","studio","tenus","triple","équipement","étoile","Bob","Californie","Devant","Smet","abonnement","baptisée","commerces","creux","facilite","flamandes","jurisprudence","l'ai","l'attitude","noyau","portraits","prononcé","publications","puce","qu'aujourd'hui","sinistre","terminal","Dexia","Mes","augmentations","batterie","cinéaste","compare","guides","inconvénients","instances","l'avion","retourner","sympathique","évaluée","L'Etat","achetant","bailleur","bonus","colonne","compensation","conseillers","continu","courbes","déclarer","enregistrées","généré","innovations","ira","jusqu'aux","lente","occuper","pesé","pot","quarts","épreuve","Bois","Congo","Courtrai","Powerfin","admet","attribuer","championnat","cités","comble","conquérir","d'encre","d'oeuvres","d'office","devenues","excessif","incertitudes","intitulé","l'évaluation","périphériques","réclamer","réelles","s'étaient","Ecolo","Nivelles","Qu'il","Travail","allures","camps","dues","exclus","grandeur","homard","illustré","inévitable","inévitablement","l'équipement","mariés","modération","ont-ils","positivement","profits","quarante","sculpture","spots","stage","universelle","vainqueur","édité","étendue","Arts","Communications","Media","Novell","Poor's","Stéphane","Word","changent","communiqué","conversation","d'artistes","effective","interlocuteurs","l'Administration","l'ambiance","n'aime","patronales","permettront","pneus","qualifiés","religion","souffrir","évoqué","Chirac","Chris","Forest","Herman","Hubert","Opel","Parti","SEK","Terre","Vie","alternatives","anversoise","bateaux","battu","brillante","d'introduire","désert","entrepreneur","essayé","interface","intégralement","j'aime","lu","modifie","personnellement","systématique","Arthur","Park","admis","blocage","calls","développent","individuel","l'ONU","l'appréciation","modestes","multinationale","out","parlant","porcelaine","pénétrer","respecte","soupapes","spéculateurs","étudier","Nestlé","abus","combler","conservation","donation","fiabilité","l'exclusion","m'ont","parcourir","parisien","remarquables","retournement","returns","EASDAQ","Kodak","PDG","collecte","d'alcool","déception","détérioration","l'avoir","l'échange","lorsqu'elle","palme","phases","privatisations","répéter","s'imposer","valu","","","","","voulais","Almanij","Infos","Procter","Smith","Tubize","actuariel","australien","croient","d'intervention","d'objets","encourager","fiscalement","hautement","l'assiette","marchand","néerlandaises","plaintes","reproche","retient","sillage","soldats","témoins","urbain","FEB","L'économie","adopte","boutons","chuter","conjoints","convaincus","coopérative","correspondent","director","n'hésite","niches","savez","stables","tend","vain","CV","Gamble","L'art","Quinze","Servais","Seules","apport","chauffage","commercialiser","d'attirer","d'existence","d'organisation","dangers","foyer","ingrédients","négocie","révolutionnaire","score","sidérurgique","techniciens","voyageur","Brown","Corluy","Herstal","Horta","L'avenir","attiré","com","conférences","constatation","d'Amérique","douzaine","duration","détenir","indemnités","lion","nuits","plomb","soumise","sportives","verres","attribué","corriger","d'hiver","domestiques","faille","foot","home","indemnité","romantique","simulation","Brussels","L'avantage","Swissair","autrefois","choisis","communales","d'Angleterre","dessinée","disponibilité","détenu","engager","exceptionnelles","figurer","habitant","hollandaise","immédiate","intégration","média","électeurs","Amro","DOS","Moniteur","Parc","acceptable","apprécier","centre-ville","d'elle","envisagé","fantaisie","habituellement","posséder","pourrez","tentatives","touches","visibilité","Creyf's","Heineken","Régie","Sterk","Tchéquie","analyser","autorisé","complets","contrainte","costumes","d'agir","doucement","démarré","eut","posée","raffinement","rond","sidérurgiste","ABB","Ensemble","L'offre","Me","accroissement","ajouté","assiette","autoroutes","batteries","d'Asie","dame","disciplines","décrocher","essai","essaie","fréquent","génétique","inconnu","l'avocat","majeurs","multimédias","plume","probabilité","préavis","publiée","scandale","spot","sérieuses","tomates","égales","Coup","Die","L'investissement","animé","bleue","d'utilisateurs","danoise","essentiels","fondateurs","fonde","l'Atlantique","l'épreuve","maquillage","mexicaine","oeufs","opérationnelle","prestigieuse","renforcé","rumeur","soigner","témoin","Blok","Golf","Nouvelle","Prudential","Tonneau","Wavre","affichée","attendus","ballon","bouton","chanteur","chiens","d'écrire","entrepris","exprimé","nomination","perfection","photographies","renommée","sous-évaluée","universel","vives","BT","Eaux","Jacobs","Raymond","axée","cacher","défauts","l'aube","l'octroi","méritent","occidentales","planning","rage","testé","Barbara","Britanniques","Interbrew","Technologies","Visa","acquiert","adulte","affichant","agricole","annonces","anversois","atteignait","cabinets","centenaire","confection","culturels","d'aucuns","destinations","doutes","développant","ha","l'ASBL","l'autorisation","l'émotion","masque","méfiance","officiels","outre-Atlantique","panne","perdue","pouces","protégé","rires","sacré","silhouette","soeurs","virtuelle","vues","écrits","épreuves","Impossible","Madrid","appelés","candidature","chargement","documentation","dominante","députés","indications","l'indépendance","leaders","listes","mince","opte","énergétique","étendu","Ci-dessus","L'exercice","University","aisé","concepts","d'achats","d'agences","d'alarme","disquettes","domine","développés","envoie","exercé","existante","fauteuil","habitations","italiennes","modifiée","nets","puces","réclament","tomate","tons","CERA","Campo","Val","aluminium","assumer","confortables","d'ajouter","dates","démarre","exotiques","expose","hall","l'aluminium","l'enregistrement","licences","navigation","opter","rapprocher","émotions","Bertrand","CPAS","CompuServe","Jamais","Jo","Klein","Swiss","acquéreur","courtiers","doublement","défaire","l'Ecole","libération","lin","percevoir","perdus","plonger","poésie","process","s'accompagne","saisi","signification","songe","séparément","tentation","trou","variables","Collignon","Los","accusé","affecté","apparu","complément","créatif","exposé","financé","incite","investissent","limitation","montagnes","onze","originaux","ouvrier","partagé","professions","préalablement","tonne","trajet","visent","L'industrie","Magritte","Power","St","balle","chercheur","communale","compression","crises","d'articles","démontré","détention","détermination","endettement","gel","inchangé","incontournable","l'enfance","l'once","l'écriture","lent","modernisation","organes","promotions","présentées","relief","remboursé","rencontrent","sage","Monnaie","accuse","axe","distances","dépréciation","détenteur","fournissent","gendarmes","horaires","imposables","intercommunales","lancent","multitude","particularité","partisans","provinces","quelques-uns","reviennent","s'améliorer","vernis","volontaire","ambition","baux","d'apprendre","directives","dis","délégation","détecter","détermine","exprimer","individuels","l'unanimité","localisation","miel","optiques","passif","performants","piles","politiciens","poussent","privilégie","restreint","souligné","supporte","vallée","ventre","éthique","Anglais","Assubel","Frans","L'utilisateur","Saint","Supposons","VLD","activement","analogue","bassin","boulot","chapeau","claires","connaissait","consortium","culte","d'administrateur","dégradation","hypothécaires","l'exécution","l'incertitude","lumineux","maux","perles","porte-parole","privilégiée","privilégiés","qualifiée","réagit","résumé","Australie","Axa","Etre","Fernand","Jules","L'activité","Lui","apparence","ci-contre","comédiens","connecter","continuera","convertibles","correcte","dessiné","durées","enjeux","incapable","libellées","millier","populations","épargne","évoquent","CLT","Mobile","capot","charger","communiste","comparables","congé","correct","d'inventaire","gagnant","intérimaire","l'UEM","l'autorité","l'envie","libéral","liquides","orientale","passait","policiers","redoutable","solidité","traitées","Bond","Mme","SME","affiches","attente","basés","comparé","consommer","d'armes","inconvénient","jette","maigre","masculin","négocié","profitent","vaches","vitrine","Avis","Finance","Hotel","Index","administratifs","allaient","avancée","compétitions","confiée","contenir","d'Art","d'opérations","description","dormir","exclusif","gouvernementale","joliment","l'Intérieur","mailing","modérée","pénal","raisins","rempli","royaume","sanction","spéculative","terminaux","Chanel","Grand-Duché","Leo","accélération","analyste","bourse","coupable","d'expérience","d'honneur","fabriqués","mettra","morte","paye","prudents","récolte","réduites","s'intéresser","saisons","sexuelle","sondage","strict","tenues","tranquille","agit","briques","concernée","d'envoyer","d'occupation","débiteurs","illustrations","paroles","passager","payées","piscine","plages","rapporter","Gillette","S'ils","banlieue","commander","commentaire","composer","d'appareils","distribués","détenus","fabuleux","génocide","hésité","indication","indiquer","industrialisés","l'imagination","l'individu","l'évidence","minimale","musical","nerveux","plaisirs","pop","positionner","rassurer","réalités","réservés","sons","séminaires","trésors","uniforme","vis","Blue","Boston","Ch","Gold","Lisbonne","Nul","SNCI","VW","affiliés","appréciation","avancées","cafés","casser","chat","compatible","d'Afrique","d'actualité","franchisés","l'apport","lots","moules","mécaniques","papa","préparé","qu'auparavant","souhaité","traits","éventuels","Cannes","Chicago","Chinois","Lee","cou","d'espace","d'expansion","d'offres","d'évaluer","discrimination","dépassant","expliqué","externes","fédérations","metteur","mobiliers","paire","peseta","polices","productions","préoccupation","rappellent","rentrées","réparties","spécialisation","statuts","traditions","truffe","éliminer","étroit","Hélas","Napoléon","Onkelinx","audio","av","baroque","brique","carburant","conducteurs","docteur","délocalisation","désirent","e","estimons","flotte","harmonie","l'écrivain","livrent","marquer","obstacles","rapporté","s'ajoutent","sobre","tandem","timing","travaillons","électorale","établis","Avermaete","Baudoux","Caisse","Elisabeth","Picasso","Proton","abandonner","assiettes","axé","civilisation","compréhension","confirmation","crime","d'énormes","diversifier","dresse","extension","fantastique","ignore","incendie","levé","minoritaires","négliger","pacte","panneau","pratiquent","raisonnables","retenus","retombées","revenue","sponsoring","étages","Bayer","Contre","Inutile","McDonald's","Nike","Pr","aborde","adoptée","bouger","cassettes","certification","exigeant","frein","fréquente","imposées","l'infrastructure","manipulation","optimisme","pourvu","profondes","rassemble","retiré","shopping","stabilisation","vertes","volontairement","établit","Dior","accompagnée","admettre","aurez","automatiques","concret","constant","d'organiser","drogues","fourneaux","influencer","interprétation","intime","magistrat","occupée","prouvé","recommander","sélectionner","séparer","tube","voyager","écrivain","équivaut","étroitement","évoquer","AUD","Age","Design","Oracle","Petite","accueil","approuvé","boom","construite","continuité","cotait","dresser","décors","gravité","l'Eglise","légers","menaces","mondialisation","passionnés","s'exprimer","stricte","styles","superficie","tas","terroir","versée","Dernier","Total","applicable","avancer","boisson","camion","commercialisé","composantes","concrétiser","conservateur","dames","diable","diffuser","fixés","formulaire","freiner","l'enthousiasme","l'élément","mourir","oublie","placées","péril","raffinage","rapproche","remarqué","rendue","résiste","réunies","sponsors","transférer","verse","Budget","Denis","Hoechst","Hotels","Pfizer","RNIS","Walter","averti","conseillons","disposé","défunt","failli","grammes","libérer","nickel","popularité","pratiqués","rassembler","regards","requiert","spécifiquement","successives","théoriquement","timide","volontaires","Barcelone","Dell","Ligue","Mettre","Simon","TEXTE","Zurich","associée","ci-dessous","connaissons","d'apporter","douter","fabriqué","figures","finesse","innovation","jeté","justesse","l'endettement","mémoires","neuve","pile","plaque","promesse","pénétration","rouler","répondant","s'agira","sachant","situait","Chili","Florence","Information","Qu'en","acceptent","accélérer","adaptées","adeptes","adolescents","attendait","d'émettre","foire","habitués","incontestable","interview","l'attente","l'indique","ndlr","noix","oiseaux","permettait","qu'aucun","qualification","rachats","rendant","réputé","syndicale","tombent","touristiques","valoriser","voler","écu","Alexandre","Dupont","Environ","atteints","clarté","compact","concurrentiel","décroché","enseignement","herbes","intelligent","licenciements","négatives","rédigé","répercussions","salariales","tempérament","tutelle","varier","verdure","Cologne","PNB","SOMMAIRE","aisée","bijou","bénéficiant","combattre","d'humour","donnait","exacte","exposés","expression","fonctionnant","gérés","impérativement","indépendantes","l'opportunité","levée","lorsqu'un","non-ferreux","nostalgie","nourrir","pratiqué","richesses","robot","saisie","Andersen","King","aborder","assortie","brutalement","brute","disparaissent","engendre","heureuse","injection","jaunes","l'intelligence","montent","nuance","officielles","physiquement","prudente","refaire","segments","supposer","synthétique","vieillissement","échéances","Autres","Bonne","Dupuis","Elio","J'étais","TENDANCES","cassette","colonnes","d'impression","dépression","fouet","judicieux","l'actuelle","l'entrepreneur","lac","portait","riz","sauvages","secrétariat","situées","solaire","soucis","souscripteur","séparés","transparent","truc","typiquement","Blanc","Café","Généralement","KLM","United","améliore","annoncer","assemblée","cahier","chanter","compétitif","concession","connais","crédible","d'accéder","d'équipement","dangereuse","destruction","envisagée","glisser","grimpe","infrastructure","insuffisant","isolé","minorité","passionnant","possédait","recommandée","régimes","s'interroger","s'offrir","syndical","trouble","Angeles","Barings","Défense","Equity","L'agence","Merrill","Mouscron","Spitaels","Xerox","abouti","adéquate","archives","attribue","boeuf","directes","directions","filets","fleuve","indéniable","interrogées","l'alcool","observer","prescription","revendications","rude","successifs","tri","trimestriels","télécommunication","Communication","Eddy","Hasselt","L'expérience","aboutir","anticipé","arrivés","cohérence","collaborateur","compositeur","cravate","d'excellents","d'outils","dons","indirectement","interviennent","l'Histoire","l'estimation","multiplie","qualifie","retenues","réalisme","suffisait","variétés","échappe","Antoine","Communautés","Hauspie","Larry","Petercam","Seulement","Sofina","accessoire","aimé","bébés","canadienne","cuisinier","d'imposer","détenue","existait","explosion","flexible","licencié","livraisons","malheur","militants","minime","notions","opposé","organisés","particules","ratios","reprennent","semblables","tournage","trous","Holding","IP","L'accord","Las","Pékin","artistiques","avancés","cosmétiques","fournis","héritage","implantation","l'adoption","originaire","partielle","passions","proposera","recherché","renforcement","sexualité","suites","téléphones","témoignage","vignes","vitamines","Code","Général","Inde","Johnson","Mobutu","Multimédia","Méditerranée","Notes","Vendredi","amoureuse","brevet","consomme","cristal","créées","d'image","descendre","décline","entame","faim","freins","inspire","l'explosion","maritime","menacé","pervers","poursuivent","savons","sols","sorties","soumettre","strictes","venues","Chantal","Exchange","Galerie","Hans","Maroc","Nathalie","Nombre","PJ","arme","bombe","bouge","chantiers","chic","extraits","gants","informer","insuffisante","l'unique","liaisons","limitent","nourrit","précautions","rencontrés","renforcée","résolu","s'ajouter","s'occuper","surveiller","trimestres","échappé","éclairage","élargir","Bosnie","Lyon","Nicole","Primo","Tintin","accompli","comportent","considérées","croyait","di","définie","enseignes","estimer","exiger","fiches","forcé","forfaitaire","gourmand","identifier","joint","l'extension","massive","millésime","minoritaire","plaques","restants","s'imposent","stabiliser","virage","vraies","éventail","Belcofi","Vlaams","audacieux","aventures","banal","communautés","douche","détection","exprime","honoraires","jugés","l'avenue","littéraire","marginal","montres","peloton","procédés","protocole","rendus","renoncé","subissent","suggestions","sépare","turbo","voulaient","Faute","Stock","achetées","agricoles","circulent","confirment","coucher","d'aluminium","détenues","extérieures","finement","fondre","fous","horaire","imposés","inciter","l'adaptation","l'employé","mondiales","médicaux","occidental","occupait","offerte","orientés","prévaut","pureté","reposer","tendresse","élégance","ISO","NC","Sport","XEU","alliances","amont","annoncent","appliquées","appréciable","appréciée","artisans","assis","brasseur","clairs","cubes","d'afficher","d'auteur","d'avion","divisé","débourser","décevants","emprunte","fermement","générosité","horizon","l'Emploi","l'accroissement","l'envoi","l'examen","originalité","parent","plongée","scission","sondages","soumises","surprenante","triomphe","vides","virtuel","émise","Botanique","Busquin","Consulting","Jean-Marc","L'exemple","RAM","Vietnam","Young","achetés","africains","apprécie","attaque","bruits","cabine","clichés","criminalité","densité","exclusive","extrait","facilités","fixation","gastronomie","inconnue","investie","l'agent","l'humanité","maintenue","mythique","piliers","psychologie","raconter","récompense","résidentiel","saint","signés","situant","songer","thérapie","touchent","tromper","échappent","équivalente","America","Avenue","Dont","Explorer","Jeune","Lux","Malines","Vos","artificielle","assistée","branché","brutale","clos","complice","compétent","emprunté","enthousiaste","entourage","fierté","formats","genres","loue","marié","mentalités","ministre-président","peines","poupe","prolonger","pénale","queue","ressemblent","rotation","savoureux","sensations","tuer","Faites","Federal","Hewlett-Packard","Investment","Jack","Johnny","Lernout","Retour","Réserve","boule","chaise","disposons","délit","démarches","entouré","informé","l'élégance","loué","majoré","n'hésitent","pessimisme","planification","pompes","puts","syndicales","triangle","vitres","épargnants","First","Mozart","Real","Rotterdam","albums","amener","appellent","baron","brevets","carbone","carnets","combine","consolider","cycles","d'accepter","d'épuration","diamant","douloureux","dépendent","développées","frigo","l'Hexagone","masculine","modernité","nucléaires","ouvrant","pavillon","recevra","restrictions","revirement","rétrospective","solitaire","spontanément","stages","tubes","Ackermans","Ben","Entreprises","Institute","L'argent","Warner","calculée","chasseurs","circonstance","cite","commandé","concurrencer","conditionnement","d'escompte","d'ordinateur","disposait","exceptionnellement","favorablement","fiables","frapper","fédéraux","grossesse","généralisée","inquiétant","l'UE","l'anglais","m'en","n'avais","précieuse","précieuses","prévoyons","rejet","résiduelle","réuni","seconds","solitude","trésor","épais","BASF","Européen","Roumanie","Sept","Telenet","ad","approfondie","catalogues","center","circulaire","colle","composés","conce
gitextract_dmivgmii/
├── .gitattributes
├── .gitignore
├── .gitlab-ci.yml
├── DOCS.md
├── Dockerfile
├── LICENSE
├── README.md
├── SECURITY.md
├── cve_poller.py
├── cve_template.html
├── cve_updater.py
├── docker/
│ ├── install.py
│ ├── secmon-ci.conf
│ └── secmon.conf
├── requirements.txt
├── rss_poller.py
├── rss_template.html
├── secmon.py
├── secmon.wsgi
├── secmon_lib.py
├── secmon_monitor.py
├── secmon_web.py
├── setup.py
├── static/
│ ├── css/
│ │ ├── dataTables.bootstrap.css
│ │ ├── main.css
│ │ ├── main2.css
│ │ ├── morris.css
│ │ ├── mycss.css
│ │ ├── sb-admin-2.css
│ │ ├── site.css
│ │ ├── timeline.css
│ │ ├── util.css
│ │ └── util2.css
│ ├── fonts/
│ │ ├── font-awesome-4.7.0/
│ │ │ ├── HELP-US-OUT.txt
│ │ │ ├── css/
│ │ │ │ └── font-awesome.css
│ │ │ ├── fonts/
│ │ │ │ └── FontAwesome.otf
│ │ │ ├── less/
│ │ │ │ ├── animated.less
│ │ │ │ ├── bordered-pulled.less
│ │ │ │ ├── core.less
│ │ │ │ ├── fixed-width.less
│ │ │ │ ├── font-awesome.less
│ │ │ │ ├── icons.less
│ │ │ │ ├── larger.less
│ │ │ │ ├── list.less
│ │ │ │ ├── mixins.less
│ │ │ │ ├── path.less
│ │ │ │ ├── rotated-flipped.less
│ │ │ │ ├── screen-reader.less
│ │ │ │ ├── stacked.less
│ │ │ │ └── variables.less
│ │ │ └── scss/
│ │ │ ├── _animated.scss
│ │ │ ├── _bordered-pulled.scss
│ │ │ ├── _core.scss
│ │ │ ├── _fixed-width.scss
│ │ │ ├── _icons.scss
│ │ │ ├── _larger.scss
│ │ │ ├── _list.scss
│ │ │ ├── _mixins.scss
│ │ │ ├── _path.scss
│ │ │ ├── _rotated-flipped.scss
│ │ │ ├── _screen-reader.scss
│ │ │ ├── _stacked.scss
│ │ │ ├── _variables.scss
│ │ │ └── font-awesome.scss
│ │ ├── montserrat/
│ │ │ └── OFL.txt
│ │ └── raleway/
│ │ └── OFL.txt
│ ├── js/
│ │ ├── demo/
│ │ │ ├── chart-area-demo.js
│ │ │ ├── chart-bar-demo.js
│ │ │ ├── chart-pie-demo.js
│ │ │ └── datatables-demo.js
│ │ ├── main.js
│ │ └── sb-admin-2.js
│ ├── scss/
│ │ ├── _buttons.scss
│ │ ├── _cards.scss
│ │ ├── _charts.scss
│ │ ├── _dropdowns.scss
│ │ ├── _error.scss
│ │ ├── _footer.scss
│ │ ├── _global.scss
│ │ ├── _login.scss
│ │ ├── _mixins.scss
│ │ ├── _navs.scss
│ │ ├── _utilities.scss
│ │ ├── _variables.scss
│ │ ├── navs/
│ │ │ ├── _global.scss
│ │ │ ├── _sidebar.scss
│ │ │ └── _topbar.scss
│ │ ├── sb-admin-2.scss
│ │ └── utilities/
│ │ ├── _animation.scss
│ │ ├── _background.scss
│ │ ├── _border.scss
│ │ ├── _display.scss
│ │ ├── _progress.scss
│ │ ├── _rotate.scss
│ │ └── _text.scss
│ └── vendor/
│ ├── animate/
│ │ └── animate.css
│ ├── bootstrap/
│ │ ├── css/
│ │ │ ├── bootstrap-grid.css
│ │ │ ├── bootstrap-reboot.css
│ │ │ └── bootstrap.css
│ │ ├── js/
│ │ │ ├── bootstrap.bundle.js
│ │ │ ├── bootstrap.js
│ │ │ ├── popper.js
│ │ │ └── tooltip.js
│ │ └── scss/
│ │ ├── _alert.scss
│ │ ├── _badge.scss
│ │ ├── _breadcrumb.scss
│ │ ├── _button-group.scss
│ │ ├── _buttons.scss
│ │ ├── _card.scss
│ │ ├── _carousel.scss
│ │ ├── _close.scss
│ │ ├── _code.scss
│ │ ├── _custom-forms.scss
│ │ ├── _dropdown.scss
│ │ ├── _forms.scss
│ │ ├── _functions.scss
│ │ ├── _grid.scss
│ │ ├── _images.scss
│ │ ├── _input-group.scss
│ │ ├── _jumbotron.scss
│ │ ├── _list-group.scss
│ │ ├── _media.scss
│ │ ├── _mixins.scss
│ │ ├── _modal.scss
│ │ ├── _nav.scss
│ │ ├── _navbar.scss
│ │ ├── _pagination.scss
│ │ ├── _popover.scss
│ │ ├── _print.scss
│ │ ├── _progress.scss
│ │ ├── _reboot.scss
│ │ ├── _root.scss
│ │ ├── _spinners.scss
│ │ ├── _tables.scss
│ │ ├── _toasts.scss
│ │ ├── _tooltip.scss
│ │ ├── _transitions.scss
│ │ ├── _type.scss
│ │ ├── _utilities.scss
│ │ ├── _variables.scss
│ │ ├── bootstrap-grid.scss
│ │ ├── bootstrap-reboot.scss
│ │ ├── bootstrap.scss
│ │ ├── mixins/
│ │ │ ├── _alert.scss
│ │ │ ├── _background-variant.scss
│ │ │ ├── _badge.scss
│ │ │ ├── _border-radius.scss
│ │ │ ├── _box-shadow.scss
│ │ │ ├── _breakpoints.scss
│ │ │ ├── _buttons.scss
│ │ │ ├── _caret.scss
│ │ │ ├── _clearfix.scss
│ │ │ ├── _deprecate.scss
│ │ │ ├── _float.scss
│ │ │ ├── _forms.scss
│ │ │ ├── _gradients.scss
│ │ │ ├── _grid-framework.scss
│ │ │ ├── _grid.scss
│ │ │ ├── _hover.scss
│ │ │ ├── _image.scss
│ │ │ ├── _list-group.scss
│ │ │ ├── _lists.scss
│ │ │ ├── _nav-divider.scss
│ │ │ ├── _pagination.scss
│ │ │ ├── _reset-text.scss
│ │ │ ├── _resize.scss
│ │ │ ├── _screen-reader.scss
│ │ │ ├── _size.scss
│ │ │ ├── _table-row.scss
│ │ │ ├── _text-emphasis.scss
│ │ │ ├── _text-hide.scss
│ │ │ ├── _text-truncate.scss
│ │ │ ├── _transition.scss
│ │ │ └── _visibility.scss
│ │ ├── utilities/
│ │ │ ├── _align.scss
│ │ │ ├── _background.scss
│ │ │ ├── _borders.scss
│ │ │ ├── _clearfix.scss
│ │ │ ├── _display.scss
│ │ │ ├── _embed.scss
│ │ │ ├── _flex.scss
│ │ │ ├── _float.scss
│ │ │ ├── _interactions.scss
│ │ │ ├── _overflow.scss
│ │ │ ├── _position.scss
│ │ │ ├── _screenreaders.scss
│ │ │ ├── _shadows.scss
│ │ │ ├── _sizing.scss
│ │ │ ├── _spacing.scss
│ │ │ ├── _stretched-link.scss
│ │ │ ├── _text.scss
│ │ │ └── _visibility.scss
│ │ └── vendor/
│ │ └── _rfs.scss
│ ├── chart.js/
│ │ ├── Chart.bundle.js
│ │ └── Chart.js
│ ├── css-hamburgers/
│ │ └── hamburgers.css
│ ├── datatables/
│ │ ├── dataTables.bootstrap4.css
│ │ ├── dataTables.bootstrap4.js
│ │ └── jquery.dataTables.js
│ ├── fontawesome-free/
│ │ ├── LICENSE.txt
│ │ ├── css/
│ │ │ ├── all.css
│ │ │ ├── brands.css
│ │ │ ├── fontawesome.css
│ │ │ ├── regular.css
│ │ │ ├── solid.css
│ │ │ ├── svg-with-js.css
│ │ │ └── v4-shims.css
│ │ ├── js/
│ │ │ ├── all.js
│ │ │ ├── brands.js
│ │ │ ├── conflict-detection.js
│ │ │ ├── fontawesome.js
│ │ │ ├── regular.js
│ │ │ ├── solid.js
│ │ │ └── v4-shims.js
│ │ ├── less/
│ │ │ ├── _animated.less
│ │ │ ├── _bordered-pulled.less
│ │ │ ├── _core.less
│ │ │ ├── _fixed-width.less
│ │ │ ├── _icons.less
│ │ │ ├── _larger.less
│ │ │ ├── _list.less
│ │ │ ├── _mixins.less
│ │ │ ├── _rotated-flipped.less
│ │ │ ├── _screen-reader.less
│ │ │ ├── _shims.less
│ │ │ ├── _stacked.less
│ │ │ ├── _variables.less
│ │ │ ├── brands.less
│ │ │ ├── fontawesome.less
│ │ │ ├── regular.less
│ │ │ ├── solid.less
│ │ │ └── v4-shims.less
│ │ ├── metadata/
│ │ │ ├── categories.yml
│ │ │ ├── icons.yml
│ │ │ ├── shims.yml
│ │ │ └── sponsors.yml
│ │ ├── package.json
│ │ └── scss/
│ │ ├── _animated.scss
│ │ ├── _bordered-pulled.scss
│ │ ├── _core.scss
│ │ ├── _fixed-width.scss
│ │ ├── _icons.scss
│ │ ├── _larger.scss
│ │ ├── _list.scss
│ │ ├── _mixins.scss
│ │ ├── _rotated-flipped.scss
│ │ ├── _screen-reader.scss
│ │ ├── _shims.scss
│ │ ├── _stacked.scss
│ │ ├── _variables.scss
│ │ ├── brands.scss
│ │ ├── fontawesome.scss
│ │ ├── regular.scss
│ │ ├── solid.scss
│ │ └── v4-shims.scss
│ ├── jquery/
│ │ ├── jquery.js
│ │ └── jquery.slim.js
│ ├── jquery-easing/
│ │ ├── jquery.easing.compatibility.js
│ │ └── jquery.easing.js
│ └── select2/
│ ├── select2.css
│ └── select2.js
└── templates/
├── about.html
├── base.html
├── by-product-vulns.html
├── config.html
├── cve-alerts.html
├── cve-updates.html
├── cyber-threats.html
├── errors.html
├── exploits.html
├── home.html
├── login.html
├── logs.html
├── product-card.html
├── product-mgmt.html
├── reports.html
├── result.html
├── rss-news.html
├── search.html
├── settings.html
├── tasks.html
└── vuln-mgmt.html
SYMBOL INDEX (1398 symbols across 27 files)
FILE: cve_poller.py
class bcolors (line 26) | class bcolors:
function checkConfig (line 36) | def checkConfig(sender, receiver, smtp_login, smtp_password, smtpsrv, po...
function cvePoller (line 102) | def cvePoller(sender, receivers, smtp_login, smtp_password, smtpsrv, por...
function sendAlert (line 489) | def sendAlert(smtp_login, smtp_password, smtpsrv, port, tls, sender, rec...
function main (line 562) | def main():
FILE: rss_poller.py
class bcolors (line 35) | class bcolors:
function parseRSSSource (line 44) | def parseRSSSource(source):
function checkConfig (line 51) | def checkConfig(sender, receivers, smtp_login, smtp_password, smtpsrv, p...
function rssPoller (line 117) | def rssPoller(sender, receivers, smtp_login, smtp_password, smtpsrv, por...
function sendAlert (line 164) | def sendAlert(smtp_login, smtp_password, smtpsrv, port, tls, sender, rec...
function main (line 213) | def main():
FILE: secmon_lib.py
function sortWordsByOccurrences (line 55) | def sortWordsByOccurrences(word_stats):
function getTopThreats (line 58) | def getTopThreats():
function getNewsTopSubject (line 74) | def getNewsTopSubject():
function handleException (line 108) | def handleException(error):
function generateCveReport (line 114) | def generateCveReport(start_date,end_date,isFull):
function writeCveTypeLog (line 211) | def writeCveTypeLog(source_script,cve_id,temporal_type,matched_product,c...
function writeNewExploitFoundLog (line 243) | def writeNewExploitFoundLog(source_script,exploit_source,cve,message):
function writeNewHighRiskProductLog (line 253) | def writeNewHighRiskProductLog(source_script,cpe,message):
function writeAuthLog (line 266) | def writeAuthLog(source_script,username,auth_status,msg,src_ip):
function getTasks (line 275) | def getTasks():
function writeMgmtTasksLog (line 285) | def writeMgmtTasksLog(source_script,message):
function writeNewRssNewLog (line 296) | def writeNewRssNewLog(source_script,feed,feed_url,news_title,news_url,ma...
function translateText (line 305) | def translateText(lang,text):
function getGithubAPISettings (line 318) | def getGithubAPISettings():
function getUserLanguage (line 334) | def getUserLanguage():
function searchExploit (line 344) | def searchExploit(cve, sleeping):
function pollCveIdFromCpe (line 387) | def pollCveIdFromCpe(cpe):
function getSecretKey (line 431) | def getSecretKey():
function getHighRiskProducts (line 441) | def getHighRiskProducts(dentype):
function returnUsername (line 471) | def returnUsername():
function deleteProduct (line 484) | def deleteProduct(ptype, key_or_cpe):
function registerNewCve (line 530) | def registerNewCve(cve_id,reason,product):
function addProduct (line 639) | def addProduct(ptype, key_or_cpe):
function getProductsStats (line 717) | def getProductsStats():
function getCveByProduct (line 732) | def getCveByProduct(product,sleeping):
function getParsedCpe (line 788) | def getParsedCpe(cpe):
function getProductInfos (line 812) | def getProductInfos(product):
function getFormatedProductList (line 850) | def getFormatedProductList():
function showProducts (line 894) | def showProducts(ptype_search):
function mailTester (line 966) | def mailTester(smtp_login, smtp_password, smtpsrv, port, tls, sender, re...
function get_db_connection (line 1035) | def get_db_connection():
function removeHTMLtags (line 1042) | def removeHTMLtags(text):
function changeCVEState (line 1045) | def changeCVEState(action, cve):
function getRegisteredCveInfos (line 1074) | def getRegisteredCveInfos(cve,full):
function getUnregisteredCveInfos (line 1136) | def getUnregisteredCveInfos(cve):
function getCpeList (line 1326) | def getCpeList():
function getKeywordsList (line 1335) | def getKeywordsList():
function getRegisteredCveStats (line 1344) | def getRegisteredCveStats():
function getRegisteredCveStatus (line 1370) | def getRegisteredCveStatus():
function getRegisteredCve (line 1432) | def getRegisteredCve():
function getUnexploitableCveIdList (line 1482) | def getUnexploitableCveIdList():
function getExploitableCveIdList (line 1492) | def getExploitableCveIdList():
FILE: secmon_monitor.py
class bcolors (line 29) | class bcolors:
function checkConfig (line 40) | def checkConfig(sender, receiver, smtp_login, smtp_password, smtpsrv, po...
function checkRssFeeds (line 105) | def checkRssFeeds(rss_feeds,dir_path, chk_result):
function checkFileSize (line 127) | def checkFileSize(dir_path, chk_result):
function main (line 161) | def main(dir_path):
FILE: secmon_web.py
function secmon_auth (line 26) | def secmon_auth(user):
function make_session_permanent (line 54) | def make_session_permanent():
function redirectUnloggedUser (line 60) | def redirectUnloggedUser(unauthorizedressource):
function home (line 66) | def home():
function settings (line 83) | def settings():
function vuln_mgmt (line 155) | def vuln_mgmt():
function rssNews (line 176) | def rssNews():
function cveAlerts (line 204) | def cveAlerts():
function topCyberSubject (line 243) | def topCyberSubject():
function cveUpdates (line 248) | def cveUpdates():
function search (line 273) | def search():
function exploits (line 297) | def exploits():
function cveExploits (line 324) | def cveExploits(cve_id):
function getLowCVE (line 331) | def getLowCVE():
function getMediumCVE (line 369) | def getMediumCVE():
function getHighCVE (line 406) | def getHighCVE():
function getCriticalCVE (line 443) | def getCriticalCVE():
function config (line 479) | def config():
function reports (line 525) | def reports():
function logs (line 557) | def logs():
function cveInfos (line 580) | def cveInfos(cve_id):
function byProductVulns (line 591) | def byProductVulns():
function about (line 616) | def about():
function tasks (line 620) | def tasks():
function psearch (line 625) | def psearch():
function serveStaticResource (line 733) | def serveStaticResource(resource):
function handle_exception (line 737) | def handle_exception(error):
FILE: setup.py
function handleException (line 39) | def handleException(error):
function mailTester (line 45) | def mailTester(smtp_login, smtp_passwd, server, port, tls, sender, recei...
function buildRSSList (line 110) | def buildRSSList(rss_feeds):
function configBuilder (line 132) | def configBuilder(smtp_login, smtp_passwd, smtpsrv, port, tls, sender, r...
function main (line 187) | def main():
FILE: static/js/demo/chart-area-demo.js
function number_format (line 5) | function number_format(number, decimals, dec_point, thousands_sep) {
FILE: static/js/demo/chart-bar-demo.js
function number_format (line 5) | function number_format(number, decimals, dec_point, thousands_sep) {
FILE: static/js/main.js
function validate (line 29) | function validate (input) {
function showValidate (line 42) | function showValidate(input) {
function hideValidate (line 48) | function hideValidate(input) {
FILE: static/vendor/bootstrap/js/bootstrap.bundle.js
function _defineProperties (line 14) | function _defineProperties(target, props) {
function _createClass (line 24) | function _createClass(Constructor, protoProps, staticProps) {
function _defineProperty (line 30) | function _defineProperty(obj, key, value) {
function ownKeys (line 45) | function ownKeys(object, enumerableOnly) {
function _objectSpread2 (line 59) | function _objectSpread2(target) {
function _inheritsLoose (line 79) | function _inheritsLoose(subClass, superClass) {
function toType (line 101) | function toType(obj) {
function getSpecialTransitionEndEvent (line 109) | function getSpecialTransitionEndEvent() {
function transitionEndEmulator (line 123) | function transitionEndEmulator(duration) {
function setTransitionEndSupport (line 138) | function setTransitionEndSupport() {
function Alert (line 287) | function Alert(element) {
function Button (line 449) | function Button(element) {
function Carousel (line 691) | function Carousel(element, config) {
function Collapse (line 1239) | function Collapse(element, config) {
function microtaskDebounce (line 1584) | function microtaskDebounce(fn) {
function taskDebounce (line 1598) | function taskDebounce(fn) {
function isFunction (line 1631) | function isFunction(functionToCheck) {
function getStyleComputedProperty (line 1643) | function getStyleComputedProperty(element, property) {
function getParentNode (line 1660) | function getParentNode(element) {
function getScrollParent (line 1674) | function getScrollParent(element) {
function getReferenceNode (line 1709) | function getReferenceNode(reference) {
function isIE (line 1723) | function isIE(version) {
function getOffsetParent (line 1740) | function getOffsetParent(element) {
function isOffsetContainer (line 1769) | function isOffsetContainer(element) {
function getRoot (line 1785) | function getRoot(node) {
function findCommonOffsetParent (line 1801) | function findCommonOffsetParent(element1, element2) {
function getScroll (line 1845) | function getScroll(element) {
function includeScroll (line 1869) | function includeScroll(rect, element) {
function getBordersSize (line 1892) | function getBordersSize(styles, axis) {
function getSize (line 1899) | function getSize(axis, body, html, computedStyle) {
function getWindowSizes (line 1903) | function getWindowSizes(document) {
function defineProperties (line 1921) | function defineProperties(target, props) {
function getClientRect (line 1978) | function getClientRect(offsets) {
function getBoundingClientRect (line 1992) | function getBoundingClientRect(element) {
function getOffsetRectRelativeToArbitraryNode (line 2041) | function getOffsetRectRelativeToArbitraryNode(children, parent) {
function getViewportOffsetRectRelativeToArtbitraryNode (line 2093) | function getViewportOffsetRectRelativeToArtbitraryNode(element) {
function isFixed (line 2122) | function isFixed(element) {
function getFixedPositionOffsetParent (line 2145) | function getFixedPositionOffsetParent(element) {
function getBoundaries (line 2168) | function getBoundaries(popper, reference, padding, boundariesElement) {
function getArea (line 2222) | function getArea(_ref) {
function computeAutoPlacement (line 2238) | function computeAutoPlacement(placement, refRect, popper, reference, bou...
function getReferenceOffsets (line 2299) | function getReferenceOffsets(state, popper, reference) {
function getOuterSizes (line 2313) | function getOuterSizes(element) {
function getOppositePlacement (line 2332) | function getOppositePlacement(placement) {
function getPopperOffsets (line 2349) | function getPopperOffsets(popper, referenceOffsets, placement) {
function find (line 2387) | function find(arr, check) {
function findIndex (line 2406) | function findIndex(arr, prop, value) {
function runModifiers (line 2431) | function runModifiers(modifiers, data, ends) {
function update (line 2461) | function update() {
function isModifierEnabled (line 2513) | function isModifierEnabled(modifiers, modifierName) {
function getSupportedPropertyName (line 2528) | function getSupportedPropertyName(property) {
function destroy (line 2547) | function destroy() {
function getWindow (line 2577) | function getWindow(element) {
function attachToScrollParents (line 2582) | function attachToScrollParents(scrollParent, event, callback, scrollPare...
function setupEventListeners (line 2599) | function setupEventListeners(reference, options, state, updateBound) {
function enableEventListeners (line 2619) | function enableEventListeners() {
function removeEventListeners (line 2631) | function removeEventListeners(reference, state) {
function disableEventListeners (line 2655) | function disableEventListeners() {
function isNumeric (line 2669) | function isNumeric(n) {
function setStyles (line 2681) | function setStyles(element, styles) {
function setAttributes (line 2700) | function setAttributes(element, attributes) {
function applyStyle (line 2720) | function applyStyle(data) {
function applyStyleOnLoad (line 2749) | function applyStyleOnLoad(reference, popper, options, modifierOptions, s...
function getRoundedOffsets (line 2786) | function getRoundedOffsets(data, shouldRound) {
function computeStyle (line 2825) | function computeStyle(data, options) {
function isModifierRequired (line 2926) | function isModifierRequired(modifiers, requestingName, requestedName) {
function arrow (line 2951) | function arrow(data, options) {
function getOppositeVariation (line 3033) | function getOppositeVariation(variation) {
function clockwise (line 3088) | function clockwise(placement) {
function flip (line 3109) | function flip(data, options) {
function keepTogether (line 3206) | function keepTogether(data) {
function toValue (line 3240) | function toValue(str, measurement, popperOffsets, referenceOffsets) {
function parseOffset (line 3292) | function parseOffset(offset, popperOffsets, referenceOffsets, basePlacem...
function offset (line 3368) | function offset(data, _ref) {
function preventOverflow (line 3409) | function preventOverflow(data, options) {
function shift (line 3480) | function shift(data) {
function hide (line 3513) | function hide(data) {
function inner (line 3551) | function inner(data) {
function Popper (line 4018) | function Popper(reference, popper) {
function Dropdown (line 4236) | function Dropdown(element, config) {
function Modal (line 4734) | function Modal(element, config) {
function allowedAttribute (line 5330) | function allowedAttribute(attr, allowedAttributeList) {
function sanitizeHtml (line 5354) | function sanitizeHtml(unsafeHtml, whiteList, sanitizeFn) {
function Tooltip (line 5481) | function Tooltip(element, config) {
function Popover (line 6157) | function Popover() {
function ScrollSpy (line 6331) | function ScrollSpy(element, config) {
function Tab (line 6615) | function Tab(element) {
function Toast (line 6843) | function Toast(element, config) {
FILE: static/vendor/bootstrap/js/bootstrap.js
function _defineProperties (line 15) | function _defineProperties(target, props) {
function _createClass (line 25) | function _createClass(Constructor, protoProps, staticProps) {
function _defineProperty (line 31) | function _defineProperty(obj, key, value) {
function ownKeys (line 46) | function ownKeys(object, enumerableOnly) {
function _objectSpread2 (line 60) | function _objectSpread2(target) {
function _inheritsLoose (line 80) | function _inheritsLoose(subClass, superClass) {
function toType (line 102) | function toType(obj) {
function getSpecialTransitionEndEvent (line 110) | function getSpecialTransitionEndEvent() {
function transitionEndEmulator (line 124) | function transitionEndEmulator(duration) {
function setTransitionEndSupport (line 139) | function setTransitionEndSupport() {
function Alert (line 288) | function Alert(element) {
function Button (line 450) | function Button(element) {
function Carousel (line 692) | function Carousel(element, config) {
function Collapse (line 1240) | function Collapse(element, config) {
function Dropdown (line 1623) | function Dropdown(element, config) {
function Modal (line 2121) | function Modal(element, config) {
function allowedAttribute (line 2717) | function allowedAttribute(attr, allowedAttributeList) {
function sanitizeHtml (line 2741) | function sanitizeHtml(unsafeHtml, whiteList, sanitizeFn) {
function Tooltip (line 2868) | function Tooltip(element, config) {
function Popover (line 3544) | function Popover() {
function ScrollSpy (line 3718) | function ScrollSpy(element, config) {
function Tab (line 4002) | function Tab(element) {
function Toast (line 4230) | function Toast(element, config) {
FILE: static/vendor/bootstrap/js/popper.js
function microtaskDebounce (line 56) | function microtaskDebounce(fn) {
function taskDebounce (line 80) | function taskDebounce(fn) {
function isFunction (line 117) | function isFunction(functionToCheck) {
function getStyleComputedProperty (line 129) | function getStyleComputedProperty(element, property) {
function getParentNode (line 145) | function getParentNode(element) {
function getScrollParent (line 159) | function getScrollParent(element) {
function getOffsetParent (line 186) | function getOffsetParent(element) {
function isOffsetContainer (line 204) | function isOffsetContainer(element) {
function getRoot (line 220) | function getRoot(node) {
function findCommonOffsetParent (line 236) | function findCommonOffsetParent(element1, element2) {
function getScroll (line 280) | function getScroll(element) {
function includeScroll (line 304) | function includeScroll(rect, element) {
function getBordersSize (line 327) | function getBordersSize(styles, axis) {
function getSize (line 349) | function getSize(axis, body, html, computedStyle) {
function getWindowSizes (line 353) | function getWindowSizes() {
function defineProperties (line 371) | function defineProperties(target, props) {
function getClientRect (line 428) | function getClientRect(offsets) {
function getBoundingClientRect (line 442) | function getBoundingClientRect(element) {
function getOffsetRectRelativeToArbitraryNode (line 491) | function getOffsetRectRelativeToArbitraryNode(children, parent) {
function getViewportOffsetRectRelativeToArtbitraryNode (line 536) | function getViewportOffsetRectRelativeToArtbitraryNode(element) {
function isFixed (line 563) | function isFixed(element) {
function getBoundaries (line 584) | function getBoundaries(popper, reference, padding, boundariesElement) {
function getArea (line 633) | function getArea(_ref) {
function computeAutoPlacement (line 649) | function computeAutoPlacement(placement, refRect, popper, reference, bou...
function getReferenceOffsets (line 709) | function getReferenceOffsets(state, popper, reference) {
function getOuterSizes (line 721) | function getOuterSizes(element) {
function getOppositePlacement (line 739) | function getOppositePlacement(placement) {
function getPopperOffsets (line 756) | function getPopperOffsets(popper, referenceOffsets, placement) {
function find (line 794) | function find(arr, check) {
function findIndex (line 813) | function findIndex(arr, prop, value) {
function runModifiers (line 838) | function runModifiers(modifiers, data, ends) {
function update (line 867) | function update() {
function isModifierEnabled (line 916) | function isModifierEnabled(modifiers, modifierName) {
function getSupportedPropertyName (line 931) | function getSupportedPropertyName(property) {
function destroy (line 950) | function destroy() {
function attachToScrollParents (line 972) | function attachToScrollParents(scrollParent, event, callback, scrollPare...
function setupEventListeners (line 989) | function setupEventListeners(reference, options, state, updateBound) {
function enableEventListeners (line 1009) | function enableEventListeners() {
function removeEventListeners (line 1021) | function removeEventListeners(reference, state) {
function disableEventListeners (line 1045) | function disableEventListeners() {
function isNumeric (line 1059) | function isNumeric(n) {
function setStyles (line 1071) | function setStyles(element, styles) {
function setAttributes (line 1090) | function setAttributes(element, attributes) {
function applyStyle (line 1110) | function applyStyle(data) {
function applyStyleOnLoad (line 1139) | function applyStyleOnLoad(reference, popper, options, modifierOptions, s...
function computeStyle (line 1164) | function computeStyle(data, options) {
function isModifierRequired (line 1261) | function isModifierRequired(modifiers, requestingName, requestedName) {
function arrow (line 1286) | function arrow(data, options) {
function getOppositeVariation (line 1365) | function getOppositeVariation(variation) {
function clockwise (line 1420) | function clockwise(placement) {
function flip (line 1441) | function flip(data, options) {
function keepTogether (line 1531) | function keepTogether(data) {
function toValue (line 1565) | function toValue(str, measurement, popperOffsets, referenceOffsets) {
function parseOffset (line 1617) | function parseOffset(offset, popperOffsets, referenceOffsets, basePlacem...
function offset (line 1693) | function offset(data, _ref) {
function preventOverflow (line 1734) | function preventOverflow(data, options) {
function shift (line 1785) | function shift(data) {
function hide (line 1818) | function hide(data) {
function inner (line 1856) | function inner(data) {
function Popper (line 2301) | function Popper(reference, popper) {
FILE: static/vendor/bootstrap/js/tooltip.js
function isFunction (line 40) | function isFunction(functionToCheck) {
function defineProperties (line 52) | function defineProperties(target, props) {
function Tooltip (line 134) | function Tooltip(reference, options) {
FILE: static/vendor/chart.js/Chart.bundle.js
function commonjsRequire (line 15) | function commonjsRequire () {
function createCommonjsModule (line 19) | function createCommonjsModule(fn, module) {
function getCjsExportFromNamespace (line 23) | function getCjsExportFromNamespace (n) {
function comparativeDistance (line 352) | function comparativeDistance(x, y) {
function buildGraph (line 1075) | function buildGraph() {
function deriveBFS (line 1093) | function deriveBFS(fromModel) {
function link (line 1118) | function link(from, to) {
function wrapConversion (line 1124) | function wrapConversion(toModel, graph) {
function wrapRaw (line 1163) | function wrapRaw(fn) {
function wrapRounded (line 1184) | function wrapRounded(fn) {
function getRgba (line 1408) | function getRgba(string) {
function getHsla (line 1477) | function getHsla(string) {
function getHwb (line 1493) | function getHwb(string) {
function getRgb (line 1509) | function getRgb(string) {
function getHsl (line 1514) | function getHsl(string) {
function getAlpha (line 1519) | function getAlpha(string) {
function hexString (line 1533) | function hexString(rgba, a) {
function rgbString (line 1545) | function rgbString(rgba, alpha) {
function rgbaString (line 1552) | function rgbaString(rgba, alpha) {
function percentString (line 1560) | function percentString(rgba, alpha) {
function percentaString (line 1571) | function percentaString(rgba, alpha) {
function hslString (line 1578) | function hslString(hsla, alpha) {
function hslaString (line 1585) | function hslaString(hsla, alpha) {
function hwbString (line 1595) | function hwbString(hwb, alpha) {
function keyword (line 1603) | function keyword(rgb) {
function scale (line 1608) | function scale(num, min, max) {
function hexDouble (line 1612) | function hexDouble(num) {
function toFontString (line 3002) | function toFontString(font) {
function interpolate (line 3275) | function interpolate(start, view, model, ease) {
function listenArrayEvents (line 3555) | function listenArrayEvents(array, listener) {
function unlistenArrayEvents (line 3596) | function unlistenArrayEvents(array, listener) {
function clipArc (line 4131) | function clipArc(ctx, arc) {
function drawFullCircleBorders (line 4153) | function drawFullCircleBorders(ctx, vm, arc, inner) {
function drawBorder (line 4180) | function drawBorder(ctx, vm, arc) {
function xRange (line 4447) | function xRange(mouseX) {
function yRange (line 4452) | function yRange(mouseY) {
function isVertical (line 4528) | function isVertical(vm) {
function getBarBounds (line 4538) | function getBarBounds(vm) {
function swap (line 4563) | function swap(orig, v1, v2) {
function parseBorderSkipped (line 4567) | function parseBorderSkipped(vm) {
function parseBorderWidth (line 4587) | function parseBorderWidth(vm, maxW, maxH) {
function boundingRects (line 4609) | function boundingRects(vm) {
function inRange (line 4631) | function inRange(vm, x, y) {
function computeMinSampleSize (line 4769) | function computeMinSampleSize(scale, pixels) {
function computeFitCategoryTraits (line 4792) | function computeFitCategoryTraits(index, ruler, options) {
function computeFlexCategoryTraits (line 4825) | function computeFlexCategoryTraits(index, ruler, options) {
function scaleClip (line 5791) | function scaleClip(scale, halfBorderWidth) {
function defaultClip (line 5802) | function defaultClip(xScale, yScale, borderWidth) {
function toClip (line 5815) | function toClip(value) {
function capControlPoint (line 6039) | function capControlPoint(pt, min, max) {
function capControlPoint (line 6596) | function capControlPoint(pt, min, max) {
function getRelativePosition (line 6699) | function getRelativePosition(e, chart) {
function parseVisibleItems (line 6715) | function parseVisibleItems(chart, handler) {
function getIntersectItems (line 6736) | function getIntersectItems(chart, position) {
function getNearestItems (line 6756) | function getNearestItems(chart, position, intersect, distanceMetric) {
function getDistanceMetricForAxis (line 6784) | function getDistanceMetricForAxis(axis) {
function indexMode (line 6795) | function indexMode(chart, e, options) {
function filterByPosition (line 6995) | function filterByPosition(array, position) {
function sortByWeight (line 7001) | function sortByWeight(array, reverse) {
function wrapBoxes (line 7011) | function wrapBoxes(boxes) {
function setLayoutDims (line 7028) | function setLayoutDims(layouts, params) {
function buildLayoutBoxes (line 7041) | function buildLayoutBoxes(boxes) {
function getCombinedMax (line 7057) | function getCombinedMax(maxPadding, chartArea, a, b) {
function updateDims (line 7061) | function updateDims(chartArea, params, layout) {
function handleMaxPadding (line 7093) | function handleMaxPadding(chartArea) {
function getMargins (line 7107) | function getMargins(horizontal, chartArea) {
function fitBoxes (line 7123) | function fitBoxes(boxes, chartArea, params) {
function placeBoxes (line 7152) | function placeBoxes(boxes, chartArea, params) {
function readUsedSize (line 7435) | function readUsedSize(element, property) {
function initCanvas (line 7446) | function initCanvas(canvas, config) {
function addListener (line 7521) | function addListener(node, type, listener) {
function removeListener (line 7525) | function removeListener(node, type, listener) {
function createEvent (line 7529) | function createEvent(type, chart, x, y, nativeEvent) {
function fromNativeEvent (line 7539) | function fromNativeEvent(event, chart) {
function throttled (line 7545) | function throttled(fn, thisArg) {
function createDiv (line 7563) | function createDiv(cls) {
function createResizer (line 7570) | function createResizer(handler) {
function watchForRender (line 7603) | function watchForRender(node, handler) {
function unwatchForRender (line 7625) | function unwatchForRender(node) {
function addResizeListener (line 7640) | function addResizeListener(node, listener, chart) {
function removeResizeListener (line 7677) | function removeResizeListener(node) {
function injectCSS (line 7694) | function injectCSS(rootNode, css) {
function pushOrConcat (line 8293) | function pushOrConcat(base, toPush) {
function splitNewlines (line 8312) | function splitNewlines(str) {
function createTooltipItem (line 8325) | function createTooltipItem(element) {
function getBaseModel (line 8350) | function getBaseModel(tooltipOpts) {
function getTooltipSize (line 8405) | function getTooltipSize(tooltip, model) {
function determineAlignment (line 8473) | function determineAlignment(tooltip, size) {
function getBackgroundPoint (line 8546) | function getBackgroundPoint(vm, size, alignment, chart) {
function getAlignedX (line 8597) | function getAlignedX(vm, align) {
function getBeforeAfterBodyLines (line 8608) | function getBeforeAfterBodyLines(callback) {
function mergeScaleConfig (line 9175) | function mergeScaleConfig(/* config objects ... */) {
function mergeConfig (line 9215) | function mergeConfig(/* config objects ... */) {
function initConfig (line 9234) | function initConfig(config) {
function updateConfig (line 9251) | function updateConfig(chart) {
function nextAvailableScaleId (line 9272) | function nextAvailableScaleId(axesOpts, prefix, index) {
function positionIsHorizontal (line 9285) | function positionIsHorizontal(position) {
function compare2Level (line 9289) | function compare2Level(l1, l2) {
function parseMaxStyle (line 10675) | function parseMaxStyle(styleValue, node, parentProperty) {
function isConstrainedValue (line 10695) | function isConstrainedValue(value) {
function getConstraintDimension (line 10706) | function getConstraintDimension(domNode, maxStyle, percentageProperty) {
function abstract (line 10900) | function abstract() {
function DateAdapter (line 10924) | function DateAdapter(options) {
function sample (line 11154) | function sample(arr, numItems) {
function getPixelForGridLine (line 11166) | function getPixelForGridLine(scale, index, offsetGridLines) {
function garbageCollect (line 11193) | function garbageCollect(caches, length) {
function computeLabelSizes (line 11211) | function computeLabelSizes(ctx, tickFonts, ticks, caches) {
function getTickMarkLength (line 11265) | function getTickMarkLength(options) {
function getScaleLabelHeight (line 11269) | function getScaleLabelHeight(options) {
function parseFontOptions (line 11282) | function parseFontOptions(options, nestedOpts) {
function parseTickFontOptions (line 11293) | function parseTickFontOptions(options) {
function nonSkipped (line 11300) | function nonSkipped(ticksToFilter) {
function getEvenSpacing (line 11312) | function getEvenSpacing(arr) {
function calculateSpacing (line 11328) | function calculateSpacing(majorIndices, ticks, axisLength, ticksLimit) {
function getMajorIndices (line 11349) | function getMajorIndices(ticks) {
function skipMajors (line 11360) | function skipMajors(ticks, majorIndices, spacing) {
function skip (line 11378) | function skip(ticks, spacing, majorStart, majorEnd) {
function generateTicks (line 12665) | function generateTicks(generationOptions, dataRange) {
function getOrCreateStack (line 12916) | function getOrCreateStack(stacks, stacked, meta) {
function stackData (line 12934) | function stackData(scale, stacks, meta, data) {
function updateMinMax (line 12962) | function updateMinMax(scale, meta, data) {
function generateTicks$1 (line 13078) | function generateTicks$1(generationOptions, dataRange) {
function nonNegativeOrDefault (line 13128) | function nonNegativeOrDefault(value, defaultValue) {
function IDMatches (line 13139) | function IDMatches(meta) {
function getTickBackdropHeight (line 13426) | function getTickBackdropHeight(opts) {
function measureLabelSize (line 13435) | function measureLabelSize(ctx, lineHeight, label) {
function determineLimits (line 13449) | function determineLimits(angle, pos, size, min, max) {
function fitWithPointLabels (line 13471) | function fitWithPointLabels(scale) {
function getTextAlignForAngle (line 13551) | function getTextAlignForAngle(angle) {
function fillText (line 13561) | function fillText(ctx, text, position, lineHeight) {
function adjustPointPositionForLabelHeight (line 13575) | function adjustPointPositionForLabelHeight(angle, textSize, position) {
function drawPointLabels (line 13583) | function drawPointLabels(scale) {
function drawRadiusLine (line 13614) | function drawRadiusLine(scale, gridLineOpts, radius, index) {
function numberOrZero (line 13653) | function numberOrZero(param) {
function sorter (line 13982) | function sorter(a, b) {
function arrayUnique (line 13986) | function arrayUnique(items) {
function getMin (line 14002) | function getMin(options) {
function getMax (line 14006) | function getMax(options) {
function buildLookupTable (line 14025) | function buildLookupTable(timestamps, min, max, distribution) {
function lookup (line 14061) | function lookup(table, key, value) {
function interpolate$1 (line 14093) | function interpolate$1(table, skey, sval, tkey) {
function toTimestamp (line 14107) | function toTimestamp(scale, input) {
function parse (line 14143) | function parse(scale, input) {
function determineUnitForAutoTicks (line 14164) | function determineUnitForAutoTicks(minUnit, min, max, capacity) {
function determineUnitForFormatting (line 14183) | function determineUnitForFormatting(scale, numTicks, minUnit, min, max) {
function determineMajorUnit (line 14196) | function determineMajorUnit(unit) {
function generate (line 14210) | function generate(scale, min, max, capacity) {
function computeOffsets (line 14251) | function computeOffsets(table, ticks, min, max, options) {
function setMajorTicks (line 14274) | function setMajorTicks(scale, ticks, map, majorUnit) {
function ticksFromTimestamps (line 14289) | function ticksFromTimestamps(scale, values, majorUnit) {
function hooks (line 14698) | function hooks () {
function setHookCallback (line 14704) | function setHookCallback (callback) {
function isArray (line 14708) | function isArray(input) {
function isObject (line 14712) | function isObject(input) {
function isObjectEmpty (line 14718) | function isObjectEmpty(obj) {
function isUndefined (line 14732) | function isUndefined(input) {
function isNumber (line 14736) | function isNumber(input) {
function isDate (line 14740) | function isDate(input) {
function map (line 14744) | function map(arr, fn) {
function hasOwnProp (line 14752) | function hasOwnProp(a, b) {
function extend (line 14756) | function extend(a, b) {
function createUTC (line 14774) | function createUTC (input, format, locale, strict) {
function defaultParsingFlags (line 14778) | function defaultParsingFlags() {
function getParsingFlags (line 14798) | function getParsingFlags(m) {
function isValid (line 14823) | function isValid(m) {
function createInvalid (line 14857) | function createInvalid (flags) {
function copyConfig (line 14873) | function copyConfig(to, from) {
function Moment (line 14923) | function Moment(config) {
function isMoment (line 14938) | function isMoment (obj) {
function absFloor (line 14942) | function absFloor (number) {
function toInt (line 14951) | function toInt(argumentForCoercion) {
function compareArrays (line 14963) | function compareArrays(array1, array2, dontConvert) {
function warn (line 14977) | function warn(msg) {
function deprecate (line 14984) | function deprecate(msg, fn) {
function deprecateSimple (line 15016) | function deprecateSimple(name, msg) {
function isFunction (line 15029) | function isFunction(input) {
function set (line 15033) | function set (config) {
function mergeConfigs (line 15052) | function mergeConfigs(parentConfig, childConfig) {
function Locale (line 15078) | function Locale(config) {
function calendar (line 15109) | function calendar (key, mom, now) {
function longDateFormat (line 15123) | function longDateFormat (key) {
function invalidDate (line 15140) | function invalidDate () {
function ordinal (line 15147) | function ordinal (number) {
function relativeTime (line 15168) | function relativeTime (number, withoutSuffix, string, isFuture) {
function pastFuture (line 15175) | function pastFuture (diff, output) {
function addUnitAlias (line 15182) | function addUnitAlias (unit, shorthand) {
function normalizeUnits (line 15187) | function normalizeUnits(units) {
function normalizeObjectUnits (line 15191) | function normalizeObjectUnits(inputObject) {
function addUnitPriority (line 15210) | function addUnitPriority(unit, priority) {
function getPrioritizedUnits (line 15214) | function getPrioritizedUnits(unitsObj) {
function zeroFill (line 15225) | function zeroFill(number, targetLength, forceSign) {
function addFormatToken (line 15245) | function addFormatToken (token, padded, ordinal, callback) {
function removeFormattingTokens (line 15267) | function removeFormattingTokens(input) {
function makeFormatFunction (line 15274) | function makeFormatFunction(format) {
function formatMoment (line 15295) | function formatMoment(m, format) {
function expandFormat (line 15306) | function expandFormat(format, locale) {
function addRegexToken (line 15349) | function addRegexToken (token, regex, strictRegex) {
function getParseRegexForToken (line 15355) | function getParseRegexForToken (token, config) {
function unescapeFormat (line 15364) | function unescapeFormat(s) {
function regexEscape (line 15370) | function regexEscape(s) {
function addParseToken (line 15376) | function addParseToken (token, callback) {
function addWeekParseToken (line 15391) | function addWeekParseToken (token, callback) {
function addTimeToArrayFromToken (line 15398) | function addTimeToArrayFromToken(token, input, config) {
function daysInYear (line 15458) | function daysInYear(year) {
function isLeapYear (line 15462) | function isLeapYear(year) {
function getIsLeapYear (line 15476) | function getIsLeapYear () {
function makeGetSet (line 15480) | function makeGetSet (unit, keepTime) {
function get (line 15492) | function get (mom, unit) {
function set$1 (line 15497) | function set$1 (mom, unit, value) {
function stringGet (line 15510) | function stringGet (units) {
function stringSet (line 15519) | function stringSet (units, value) {
function mod (line 15535) | function mod(n, x) {
function daysInMonth (line 15556) | function daysInMonth(year, month) {
function localeMonths (line 15616) | function localeMonths (m, format) {
function localeMonthsShort (line 15626) | function localeMonthsShort (m, format) {
function handleStrictParse (line 15635) | function handleStrictParse(monthName, format, strict) {
function localeMonthsParse (line 15676) | function localeMonthsParse (monthName, format, strict) {
function setMonth (line 15716) | function setMonth (mom, value) {
function getSetMonth (line 15741) | function getSetMonth (value) {
function getDaysInMonth (line 15751) | function getDaysInMonth () {
function monthsShortRegex (line 15756) | function monthsShortRegex (isStrict) {
function monthsRegex (line 15776) | function monthsRegex (isStrict) {
function computeMonthsParse (line 15795) | function computeMonthsParse () {
function createDate (line 15829) | function createDate (y, m, d, h, M, s, ms) {
function createUTCDate (line 15847) | function createUTCDate (y) {
function firstWeekOffset (line 15866) | function firstWeekOffset(year, dow, doy) {
function dayOfYearFromWeeks (line 15876) | function dayOfYearFromWeeks(year, week, weekday, dow, doy) {
function weekOfYear (line 15899) | function weekOfYear(mom, dow, doy) {
function weeksInYear (line 15921) | function weeksInYear(year, dow, doy) {
function localeWeek (line 15957) | function localeWeek (mom) {
function localeFirstDayOfWeek (line 15966) | function localeFirstDayOfWeek () {
function localeFirstDayOfYear (line 15970) | function localeFirstDayOfYear () {
function getSetWeek (line 15976) | function getSetWeek (input) {
function getSetISOWeek (line 15981) | function getSetISOWeek (input) {
function parseWeekday (line 16047) | function parseWeekday(input, locale) {
function parseIsoWeekday (line 16064) | function parseIsoWeekday(input, locale) {
function shiftWeekdays (line 16072) | function shiftWeekdays (ws, n) {
function localeWeekdays (line 16077) | function localeWeekdays (m, format) {
function localeWeekdaysShort (line 16085) | function localeWeekdaysShort (m) {
function localeWeekdaysMin (line 16091) | function localeWeekdaysMin (m) {
function handleStrictParse$1 (line 16096) | function handleStrictParse$1(weekdayName, format, strict) {
function localeWeekdaysParse (line 16160) | function localeWeekdaysParse (weekdayName, format, strict) {
function getSetDayOfWeek (line 16202) | function getSetDayOfWeek (input) {
function getSetLocaleDayOfWeek (line 16215) | function getSetLocaleDayOfWeek (input) {
function getSetISODayOfWeek (line 16223) | function getSetISODayOfWeek (input) {
function weekdaysRegex (line 16241) | function weekdaysRegex (isStrict) {
function weekdaysShortRegex (line 16261) | function weekdaysShortRegex (isStrict) {
function weekdaysMinRegex (line 16281) | function weekdaysMinRegex (isStrict) {
function computeWeekdaysParse (line 16301) | function computeWeekdaysParse () {
function hFormat (line 16344) | function hFormat() {
function kFormat (line 16348) | function kFormat() {
function meridiem (line 16374) | function meridiem (token, lowercase) {
function matchMeridiem (line 16392) | function matchMeridiem (isStrict, locale) {
function localeIsPM (line 16452) | function localeIsPM (input) {
function localeMeridiem (line 16459) | function localeMeridiem (hours, minutes, isLower) {
function normalizeLocale (line 16501) | function normalizeLocale(key) {
function chooseLocale (line 16508) | function chooseLocale(names) {
function loadLocale (line 16532) | function loadLocale(name) {
function getSetGlobalLocale (line 16550) | function getSetGlobalLocale (key, values) {
function defineLocale (line 16575) | function defineLocale (name, config) {
function updateLocale (line 16627) | function updateLocale(name, config) {
function getLocale (line 16656) | function getLocale (key) {
function listLocales (line 16679) | function listLocales() {
function checkOverflow (line 16683) | function checkOverflow (m) {
function defaults (line 16714) | function defaults(a, b, c) {
function currentDateArray (line 16724) | function currentDateArray(config) {
function configFromArray (line 16737) | function configFromArray (config) {
function dayOfYearFromWeekInfo (line 16806) | function dayOfYearFromWeekInfo(config) {
function configFromISO (line 16901) | function configFromISO(config) {
function extractFromRFC2822Strings (line 16956) | function extractFromRFC2822Strings(yearStr, monthStr, dayStr, hourStr, m...
function untruncateYear (line 16972) | function untruncateYear(yearStr) {
function preprocessRFC2822 (line 16982) | function preprocessRFC2822(s) {
function checkWeekday (line 16987) | function checkWeekday(weekdayStr, parsedInput, config) {
function calculateOffset (line 17014) | function calculateOffset(obsOffset, militaryOffset, numOffset) {
function configFromRFC2822 (line 17028) | function configFromRFC2822(config) {
function configFromString (line 17049) | function configFromString(config) {
function configFromStringAndFormat (line 17092) | function configFromStringAndFormat(config) {
function meridiemFixWrap (line 17164) | function meridiemFixWrap (locale, hour, meridiem) {
function configFromStringAndArray (line 17190) | function configFromStringAndArray(config) {
function configFromObject (line 17234) | function configFromObject(config) {
function createFromConfig (line 17247) | function createFromConfig (config) {
function prepareConfig (line 17258) | function prepareConfig (config) {
function configFromInput (line 17291) | function configFromInput(config) {
function createLocalOrUTC (line 17314) | function createLocalOrUTC (input, format, locale, strict, isUTC) {
function createLocal (line 17338) | function createLocal (input, format, locale, strict) {
function pickBy (line 17371) | function pickBy(fn, moments) {
function min (line 17389) | function min () {
function max (line 17395) | function max () {
function isDurationValid (line 17407) | function isDurationValid(m) {
function isValid$1 (line 17429) | function isValid$1() {
function createInvalid$1 (line 17433) | function createInvalid$1() {
function Duration (line 17437) | function Duration (duration) {
function isDuration (line 17474) | function isDuration (obj) {
function absRound (line 17478) | function absRound (number) {
function offset (line 17488) | function offset (token, separator) {
function offsetFromString (line 17519) | function offsetFromString(matcher, string) {
function cloneWithOffset (line 17536) | function cloneWithOffset(input, model) {
function getDateOffset (line 17550) | function getDateOffset (m) {
function getSetOffset (line 17574) | function getSetOffset (input, keepLocalTime, keepMinutes) {
function getSetZone (line 17612) | function getSetZone (input, keepLocalTime) {
function setOffsetToUTC (line 17626) | function setOffsetToUTC (keepLocalTime) {
function setOffsetToLocal (line 17630) | function setOffsetToLocal (keepLocalTime) {
function setOffsetToParsedOffset (line 17642) | function setOffsetToParsedOffset () {
function hasAlignedHourOffset (line 17657) | function hasAlignedHourOffset (input) {
function isDaylightSavingTime (line 17666) | function isDaylightSavingTime () {
function isDaylightSavingTimeShifted (line 17673) | function isDaylightSavingTimeShifted () {
function isLocal (line 17694) | function isLocal () {
function isUtcOffset (line 17698) | function isUtcOffset () {
function isUtc (line 17702) | function isUtc () {
function createDuration (line 17714) | function createDuration (input, key) {
function parseIso (line 17778) | function parseIso (inp, sign) {
function positiveMomentsDifference (line 17787) | function positiveMomentsDifference(base, other) {
function momentsDifference (line 17801) | function momentsDifference(base, other) {
function createAdder (line 17820) | function createAdder(direction, name) {
function addSubtract (line 17837) | function addSubtract (mom, duration, isAdding, updateOffset) {
function getCalendarFormat (line 17866) | function getCalendarFormat(myMoment, now) {
function calendar$1 (line 17876) | function calendar$1 (time, formats) {
function clone (line 17888) | function clone () {
function isAfter (line 17892) | function isAfter (input, units) {
function isBefore (line 17905) | function isBefore (input, units) {
function isBetween (line 17918) | function isBetween (from, to, units, inclusivity) {
function isSame (line 17929) | function isSame (input, units) {
function isSameOrAfter (line 17944) | function isSameOrAfter (input, units) {
function isSameOrBefore (line 17948) | function isSameOrBefore (input, units) {
function diff (line 17952) | function diff (input, units, asFloat) {
function monthDiff (line 17986) | function monthDiff (a, b) {
function toString (line 18010) | function toString () {
function toISOString (line 18014) | function toISOString(keepOffset) {
function inspect (line 18040) | function inspect () {
function format (line 18058) | function format (inputString) {
function from (line 18066) | function from (time, withoutSuffix) {
function fromNow (line 18076) | function fromNow (withoutSuffix) {
function to (line 18080) | function to (time, withoutSuffix) {
function toNow (line 18090) | function toNow (withoutSuffix) {
function locale (line 18097) | function locale (key) {
function localeData (line 18122) | function localeData () {
function mod$1 (line 18132) | function mod$1(dividend, divisor) {
function localStartOfDate (line 18136) | function localStartOfDate(y, m, d) {
function utcStartOfDate (line 18146) | function utcStartOfDate(y, m, d) {
function startOf (line 18156) | function startOf (units) {
function endOf (line 18204) | function endOf (units) {
function valueOf (line 18252) | function valueOf () {
function unix (line 18256) | function unix () {
function toDate (line 18260) | function toDate () {
function toArray (line 18264) | function toArray () {
function toObject (line 18269) | function toObject () {
function toJSON (line 18282) | function toJSON () {
function isValid$2 (line 18287) | function isValid$2 () {
function parsingFlags (line 18291) | function parsingFlags () {
function invalidAt (line 18295) | function invalidAt () {
function creationData (line 18299) | function creationData() {
function addWeekYearFormatToken (line 18319) | function addWeekYearFormatToken (token, getter) {
function getSetWeekYear (line 18360) | function getSetWeekYear (input) {
function getSetISOWeekYear (line 18369) | function getSetISOWeekYear (input) {
function getISOWeeksInYear (line 18374) | function getISOWeeksInYear () {
function getWeeksInYear (line 18378) | function getWeeksInYear () {
function getSetWeekYearHelper (line 18383) | function getSetWeekYearHelper(input, week, weekday, dow, doy) {
function setWeekAll (line 18396) | function setWeekAll(weekYear, week, weekday, dow, doy) {
function getSetQuarter (line 18427) | function getSetQuarter (input) {
function getSetDayOfYear (line 18485) | function getSetDayOfYear (input) {
function parseMs (line 18584) | function parseMs(input, array) {
function getZoneAbbr (line 18602) | function getZoneAbbr () {
function getZoneName (line 18606) | function getZoneName () {
function createUnix (line 18688) | function createUnix (input) {
function createInZone (line 18692) | function createInZone () {
function preParsePostFormat (line 18696) | function preParsePostFormat (string) {
function get$1 (line 18733) | function get$1 (format, index, field, setter) {
function listMonthsImpl (line 18739) | function listMonthsImpl (format, index, field) {
function listWeekdaysImpl (line 18767) | function listWeekdaysImpl (localeSorted, format, index, field) {
function listMonths (line 18803) | function listMonths (format, index) {
function listMonthsShort (line 18807) | function listMonthsShort (format, index) {
function listWeekdays (line 18811) | function listWeekdays (localeSorted, format, index) {
function listWeekdaysShort (line 18815) | function listWeekdaysShort (localeSorted, format, index) {
function listWeekdaysMin (line 18819) | function listWeekdaysMin (localeSorted, format, index) {
function abs (line 18842) | function abs () {
function addSubtract$1 (line 18859) | function addSubtract$1 (duration, input, value, direction) {
function add$1 (line 18870) | function add$1 (input, value) {
function subtract$1 (line 18875) | function subtract$1 (input, value) {
function absCeil (line 18879) | function absCeil (number) {
function bubble (line 18887) | function bubble () {
function daysToMonths (line 18934) | function daysToMonths (days) {
function monthsToDays (line 18940) | function monthsToDays (months) {
function as (line 18945) | function as (units) {
function valueOf$1 (line 18980) | function valueOf$1 () {
function makeAs (line 18992) | function makeAs (alias) {
function clone$1 (line 19008) | function clone$1 () {
function get$2 (line 19012) | function get$2 (units) {
function makeGetter (line 19017) | function makeGetter(name) {
function weeks (line 19031) | function weeks () {
function substituteTimeAgo (line 19046) | function substituteTimeAgo(string, number, withoutSuffix, isFuture, loca...
function relativeTime$1 (line 19050) | function relativeTime$1 (posNegDuration, withoutSuffix, locale) {
function getSetRelativeTimeRounding (line 19078) | function getSetRelativeTimeRounding (roundingFunction) {
function getSetRelativeTimeThreshold (line 19090) | function getSetRelativeTimeThreshold (threshold, limit) {
function humanize (line 19104) | function humanize (withSuffix) {
function sign (line 19121) | function sign(x) {
function toISOString$1 (line 19125) | function toISOString$1() {
function decodeFill (line 19401) | function decodeFill(el, index, count) {
function computeLinearBoundary (line 19450) | function computeLinearBoundary(source) {
function computeCircularBoundary (line 19492) | function computeCircularBoundary(source) {
function computeBoundary (line 19521) | function computeBoundary(source) {
function resolveTarget (line 19530) | function resolveTarget(sources, index, propagate) {
function createMapper (line 19561) | function createMapper(source) {
function isDrawable (line 19576) | function isDrawable(point) {
function drawArea (line 19580) | function drawArea(ctx, curve0, curve1, len0, len1) {
function doFill (line 19612) | function doFill(ctx, points, mapper, view, color, loop) {
function getBoxWidth (line 19826) | function getBoxWidth(labelOpts, fontSize) {
function createNewLegendAndAttach (line 20298) | function createNewLegendAndAttach(chart, legendOpts) {
function createNewTitleBlockAndAttach (line 20542) | function createNewTitleBlockAndAttach(chart, titleOpts) {
FILE: static/vendor/chart.js/Chart.js
function createCommonjsModule (line 15) | function createCommonjsModule(fn, module) {
function getCjsExportFromNamespace (line 19) | function getCjsExportFromNamespace (n) {
function comparativeDistance (line 348) | function comparativeDistance(x, y) {
function buildGraph (line 1071) | function buildGraph() {
function deriveBFS (line 1089) | function deriveBFS(fromModel) {
function link (line 1114) | function link(from, to) {
function wrapConversion (line 1120) | function wrapConversion(toModel, graph) {
function wrapRaw (line 1159) | function wrapRaw(fn) {
function wrapRounded (line 1180) | function wrapRounded(fn) {
function getRgba (line 1404) | function getRgba(string) {
function getHsla (line 1473) | function getHsla(string) {
function getHwb (line 1489) | function getHwb(string) {
function getRgb (line 1505) | function getRgb(string) {
function getHsl (line 1510) | function getHsl(string) {
function getAlpha (line 1515) | function getAlpha(string) {
function hexString (line 1529) | function hexString(rgba, a) {
function rgbString (line 1541) | function rgbString(rgba, alpha) {
function rgbaString (line 1548) | function rgbaString(rgba, alpha) {
function percentString (line 1556) | function percentString(rgba, alpha) {
function percentaString (line 1567) | function percentaString(rgba, alpha) {
function hslString (line 1574) | function hslString(hsla, alpha) {
function hslaString (line 1581) | function hslaString(hsla, alpha) {
function hwbString (line 1591) | function hwbString(hwb, alpha) {
function keyword (line 1599) | function keyword(rgb) {
function scale (line 1604) | function scale(num, min, max) {
function hexDouble (line 1608) | function hexDouble(num) {
function toFontString (line 2998) | function toFontString(font) {
function interpolate (line 3271) | function interpolate(start, view, model, ease) {
function listenArrayEvents (line 3551) | function listenArrayEvents(array, listener) {
function unlistenArrayEvents (line 3592) | function unlistenArrayEvents(array, listener) {
function clipArc (line 4127) | function clipArc(ctx, arc) {
function drawFullCircleBorders (line 4149) | function drawFullCircleBorders(ctx, vm, arc, inner) {
function drawBorder (line 4176) | function drawBorder(ctx, vm, arc) {
function xRange (line 4443) | function xRange(mouseX) {
function yRange (line 4448) | function yRange(mouseY) {
function isVertical (line 4524) | function isVertical(vm) {
function getBarBounds (line 4534) | function getBarBounds(vm) {
function swap (line 4559) | function swap(orig, v1, v2) {
function parseBorderSkipped (line 4563) | function parseBorderSkipped(vm) {
function parseBorderWidth (line 4583) | function parseBorderWidth(vm, maxW, maxH) {
function boundingRects (line 4605) | function boundingRects(vm) {
function inRange (line 4627) | function inRange(vm, x, y) {
function computeMinSampleSize (line 4765) | function computeMinSampleSize(scale, pixels) {
function computeFitCategoryTraits (line 4788) | function computeFitCategoryTraits(index, ruler, options) {
function computeFlexCategoryTraits (line 4821) | function computeFlexCategoryTraits(index, ruler, options) {
function scaleClip (line 5787) | function scaleClip(scale, halfBorderWidth) {
function defaultClip (line 5798) | function defaultClip(xScale, yScale, borderWidth) {
function toClip (line 5811) | function toClip(value) {
function capControlPoint (line 6035) | function capControlPoint(pt, min, max) {
function capControlPoint (line 6592) | function capControlPoint(pt, min, max) {
function getRelativePosition (line 6695) | function getRelativePosition(e, chart) {
function parseVisibleItems (line 6711) | function parseVisibleItems(chart, handler) {
function getIntersectItems (line 6732) | function getIntersectItems(chart, position) {
function getNearestItems (line 6752) | function getNearestItems(chart, position, intersect, distanceMetric) {
function getDistanceMetricForAxis (line 6780) | function getDistanceMetricForAxis(axis) {
function indexMode (line 6791) | function indexMode(chart, e, options) {
function filterByPosition (line 6991) | function filterByPosition(array, position) {
function sortByWeight (line 6997) | function sortByWeight(array, reverse) {
function wrapBoxes (line 7007) | function wrapBoxes(boxes) {
function setLayoutDims (line 7024) | function setLayoutDims(layouts, params) {
function buildLayoutBoxes (line 7037) | function buildLayoutBoxes(boxes) {
function getCombinedMax (line 7053) | function getCombinedMax(maxPadding, chartArea, a, b) {
function updateDims (line 7057) | function updateDims(chartArea, params, layout) {
function handleMaxPadding (line 7089) | function handleMaxPadding(chartArea) {
function getMargins (line 7103) | function getMargins(horizontal, chartArea) {
function fitBoxes (line 7119) | function fitBoxes(boxes, chartArea, params) {
function placeBoxes (line 7148) | function placeBoxes(boxes, chartArea, params) {
function readUsedSize (line 7431) | function readUsedSize(element, property) {
function initCanvas (line 7442) | function initCanvas(canvas, config) {
function addListener (line 7517) | function addListener(node, type, listener) {
function removeListener (line 7521) | function removeListener(node, type, listener) {
function createEvent (line 7525) | function createEvent(type, chart, x, y, nativeEvent) {
function fromNativeEvent (line 7535) | function fromNativeEvent(event, chart) {
function throttled (line 7541) | function throttled(fn, thisArg) {
function createDiv (line 7559) | function createDiv(cls) {
function createResizer (line 7566) | function createResizer(handler) {
function watchForRender (line 7599) | function watchForRender(node, handler) {
function unwatchForRender (line 7621) | function unwatchForRender(node) {
function addResizeListener (line 7636) | function addResizeListener(node, listener, chart) {
function removeResizeListener (line 7673) | function removeResizeListener(node) {
function injectCSS (line 7690) | function injectCSS(rootNode, css) {
function pushOrConcat (line 8289) | function pushOrConcat(base, toPush) {
function splitNewlines (line 8308) | function splitNewlines(str) {
function createTooltipItem (line 8321) | function createTooltipItem(element) {
function getBaseModel (line 8346) | function getBaseModel(tooltipOpts) {
function getTooltipSize (line 8401) | function getTooltipSize(tooltip, model) {
function determineAlignment (line 8469) | function determineAlignment(tooltip, size) {
function getBackgroundPoint (line 8542) | function getBackgroundPoint(vm, size, alignment, chart) {
function getAlignedX (line 8593) | function getAlignedX(vm, align) {
function getBeforeAfterBodyLines (line 8604) | function getBeforeAfterBodyLines(callback) {
function mergeScaleConfig (line 9171) | function mergeScaleConfig(/* config objects ... */) {
function mergeConfig (line 9211) | function mergeConfig(/* config objects ... */) {
function initConfig (line 9230) | function initConfig(config) {
function updateConfig (line 9247) | function updateConfig(chart) {
function nextAvailableScaleId (line 9268) | function nextAvailableScaleId(axesOpts, prefix, index) {
function positionIsHorizontal (line 9281) | function positionIsHorizontal(position) {
function compare2Level (line 9285) | function compare2Level(l1, l2) {
function parseMaxStyle (line 10671) | function parseMaxStyle(styleValue, node, parentProperty) {
function isConstrainedValue (line 10691) | function isConstrainedValue(value) {
function getConstraintDimension (line 10702) | function getConstraintDimension(domNode, maxStyle, percentageProperty) {
function abstract (line 10896) | function abstract() {
function DateAdapter (line 10920) | function DateAdapter(options) {
function sample (line 11150) | function sample(arr, numItems) {
function getPixelForGridLine (line 11162) | function getPixelForGridLine(scale, index, offsetGridLines) {
function garbageCollect (line 11189) | function garbageCollect(caches, length) {
function computeLabelSizes (line 11207) | function computeLabelSizes(ctx, tickFonts, ticks, caches) {
function getTickMarkLength (line 11261) | function getTickMarkLength(options) {
function getScaleLabelHeight (line 11265) | function getScaleLabelHeight(options) {
function parseFontOptions (line 11278) | function parseFontOptions(options, nestedOpts) {
function parseTickFontOptions (line 11289) | function parseTickFontOptions(options) {
function nonSkipped (line 11296) | function nonSkipped(ticksToFilter) {
function getEvenSpacing (line 11308) | function getEvenSpacing(arr) {
function calculateSpacing (line 11324) | function calculateSpacing(majorIndices, ticks, axisLength, ticksLimit) {
function getMajorIndices (line 11345) | function getMajorIndices(ticks) {
function skipMajors (line 11356) | function skipMajors(ticks, majorIndices, spacing) {
function skip (line 11374) | function skip(ticks, spacing, majorStart, majorEnd) {
function generateTicks (line 12661) | function generateTicks(generationOptions, dataRange) {
function getOrCreateStack (line 12912) | function getOrCreateStack(stacks, stacked, meta) {
function stackData (line 12930) | function stackData(scale, stacks, meta, data) {
function updateMinMax (line 12958) | function updateMinMax(scale, meta, data) {
function generateTicks$1 (line 13074) | function generateTicks$1(generationOptions, dataRange) {
function nonNegativeOrDefault (line 13124) | function nonNegativeOrDefault(value, defaultValue) {
function IDMatches (line 13135) | function IDMatches(meta) {
function getTickBackdropHeight (line 13422) | function getTickBackdropHeight(opts) {
function measureLabelSize (line 13431) | function measureLabelSize(ctx, lineHeight, label) {
function determineLimits (line 13445) | function determineLimits(angle, pos, size, min, max) {
function fitWithPointLabels (line 13467) | function fitWithPointLabels(scale) {
function getTextAlignForAngle (line 13547) | function getTextAlignForAngle(angle) {
function fillText (line 13557) | function fillText(ctx, text, position, lineHeight) {
function adjustPointPositionForLabelHeight (line 13571) | function adjustPointPositionForLabelHeight(angle, textSize, position) {
function drawPointLabels (line 13579) | function drawPointLabels(scale) {
function drawRadiusLine (line 13610) | function drawRadiusLine(scale, gridLineOpts, radius, index) {
function numberOrZero (line 13649) | function numberOrZero(param) {
function sorter (line 13978) | function sorter(a, b) {
function arrayUnique (line 13982) | function arrayUnique(items) {
function getMin (line 13998) | function getMin(options) {
function getMax (line 14002) | function getMax(options) {
function buildLookupTable (line 14021) | function buildLookupTable(timestamps, min, max, distribution) {
function lookup (line 14057) | function lookup(table, key, value) {
function interpolate$1 (line 14089) | function interpolate$1(table, skey, sval, tkey) {
function toTimestamp (line 14103) | function toTimestamp(scale, input) {
function parse (line 14139) | function parse(scale, input) {
function determineUnitForAutoTicks (line 14160) | function determineUnitForAutoTicks(minUnit, min, max, capacity) {
function determineUnitForFormatting (line 14179) | function determineUnitForFormatting(scale, numTicks, minUnit, min, max) {
function determineMajorUnit (line 14192) | function determineMajorUnit(unit) {
function generate (line 14206) | function generate(scale, min, max, capacity) {
function computeOffsets (line 14247) | function computeOffsets(table, ticks, min, max, options) {
function setMajorTicks (line 14270) | function setMajorTicks(scale, ticks, map, majorUnit) {
function ticksFromTimestamps (line 14285) | function ticksFromTimestamps(scale, values, majorUnit) {
function decodeFill (line 14797) | function decodeFill(el, index, count) {
function computeLinearBoundary (line 14846) | function computeLinearBoundary(source) {
function computeCircularBoundary (line 14888) | function computeCircularBoundary(source) {
function computeBoundary (line 14917) | function computeBoundary(source) {
function resolveTarget (line 14926) | function resolveTarget(sources, index, propagate) {
function createMapper (line 14957) | function createMapper(source) {
function isDrawable (line 14972) | function isDrawable(point) {
function drawArea (line 14976) | function drawArea(ctx, curve0, curve1, len0, len1) {
function doFill (line 15008) | function doFill(ctx, points, mapper, view, color, loop) {
function getBoxWidth (line 15222) | function getBoxWidth(labelOpts, fontSize) {
function createNewLegendAndAttach (line 15694) | function createNewLegendAndAttach(chart, legendOpts) {
function createNewTitleBlockAndAttach (line 15938) | function createNewTitleBlockAndAttach(chart, titleOpts) {
FILE: static/vendor/datatables/jquery.dataTables.js
function _fnHungarianMap (line 1655) | function _fnHungarianMap ( o )
function _fnCamelToHungarian (line 1693) | function _fnCamelToHungarian ( src, user, force )
function _fnLanguageCompat (line 1732) | function _fnLanguageCompat( lang )
function _fnCompatOpts (line 1794) | function _fnCompatOpts ( init )
function _fnCompatCols (line 1835) | function _fnCompatCols ( init )
function _fnBrowserDetect (line 1855) | function _fnBrowserDetect( settings )
function _fnReduce (line 1935) | function _fnReduce ( that, fn, init, start, end, inc )
function _fnAddColumn (line 1969) | function _fnAddColumn( oSettings, nTh )
function _fnColumnOptions (line 2001) | function _fnColumnOptions( oSettings, iCol, oOptions )
function _fnAdjustColumnSizing (line 2132) | function _fnAdjustColumnSizing ( settings )
function _fnVisibleToColumnIndex (line 2164) | function _fnVisibleToColumnIndex( oSettings, iMatch )
function _fnColumnIndexToVisible (line 2182) | function _fnColumnIndexToVisible( oSettings, iMatch )
function _fnVisbleColumns (line 2197) | function _fnVisbleColumns( oSettings )
function _fnGetColumns (line 2220) | function _fnGetColumns( oSettings, sParam )
function _fnColumnTypes (line 2239) | function _fnColumnTypes ( settings )
function _fnApplyColumnDefs (line 2310) | function _fnApplyColumnDefs( oSettings, aoColDefs, aoCols, fn )
function _fnAddData (line 2390) | function _fnAddData ( oSettings, aDataIn, nTr, anTds )
function _fnAddTr (line 2440) | function _fnAddTr( settings, trs )
function _fnNodeToDataIndex (line 2463) | function _fnNodeToDataIndex( oSettings, n )
function _fnNodeToColumnIndex (line 2477) | function _fnNodeToColumnIndex( oSettings, iRow, n )
function _fnGetCellData (line 2492) | function _fnGetCellData( settings, rowIdx, colIdx, type )
function _fnSetCellData (line 2540) | function _fnSetCellData( settings, rowIdx, colIdx, val )
function _fnSplitObjNotation (line 2562) | function _fnSplitObjNotation( str )
function _fnGetObjectDataFn (line 2577) | function _fnGetObjectDataFn( mSource )
function _fnSetObjectDataFn (line 2702) | function _fnSetObjectDataFn( mSource )
function _fnGetDataMaster (line 2821) | function _fnGetDataMaster ( settings )
function _fnClearTable (line 2832) | function _fnClearTable( settings )
function _fnDeleteIndex (line 2848) | function _fnDeleteIndex( a, iTarget, splice )
function _fnInvalidate (line 2887) | function _fnInvalidate( settings, rowIdx, src, colIdx )
function _fnGetRowElements (line 2965) | function _fnGetRowElements( settings, row, colIdx, d )
function _fnCreateTr (line 3074) | function _fnCreateTr ( oSettings, iRow, nTrIn, anTds )
function _fnRowAttributes (line 3159) | function _fnRowAttributes( settings, row )
function _fnBuildHead (line 3199) | function _fnBuildHead( oSettings )
function _fnDrawHead (line 3285) | function _fnDrawHead( oSettings, aoSource, bIncludeHidden )
function _fnDraw (line 3383) | function _fnDraw( oSettings )
function _fnReDraw (line 3524) | function _fnReDraw( settings, holdPosition )
function _fnAddOptionsHtml (line 3562) | function _fnAddOptionsHtml ( oSettings )
function _fnDetectHeader (line 3718) | function _fnDetectHeader ( aLayout, nThead )
function _fnGetUniqueThs (line 3793) | function _fnGetUniqueThs ( oSettings, nHeader, aLayout )
function _fnBuildAjax (line 3830) | function _fnBuildAjax( oSettings, data, fn )
function _fnAjaxUpdate (line 3963) | function _fnAjaxUpdate( settings )
function _fnAjaxParameters (line 3994) | function _fnAjaxParameters( settings )
function _fnAjaxUpdateDraw (line 4102) | function _fnAjaxUpdateDraw ( settings, json )
function _fnAjaxDataSrc (line 4152) | function _fnAjaxDataSrc ( oSettings, json )
function _fnFeatureHtmlFilter (line 4175) | function _fnFeatureHtmlFilter ( settings )
function _fnFilterComplete (line 4271) | function _fnFilterComplete ( oSettings, oInput, iForce )
function _fnFilterCustom (line 4324) | function _fnFilterCustom( settings )
function _fnFilterColumn (line 4361) | function _fnFilterColumn ( settings, searchStr, colIdx, regex, smart, ca...
function _fnFilter (line 4394) | function _fnFilter( settings, input, force, regex, smart, caseInsensitive )
function _fnFilterCreateSearch (line 4450) | function _fnFilterCreateSearch( search, regex, smart, caseInsensitive )
function _fnFilterData (line 4492) | function _fnFilterData ( settings )
function _fnSearchToCamel (line 4565) | function _fnSearchToCamel ( obj )
function _fnSearchToHung (line 4584) | function _fnSearchToHung ( obj )
function _fnFeatureHtmlInfo (line 4600) | function _fnFeatureHtmlInfo ( settings )
function _fnUpdateInfo (line 4634) | function _fnUpdateInfo ( settings )
function _fnInfoMacros (line 4672) | function _fnInfoMacros ( settings, str )
function _fnInitialise (line 4699) | function _fnInitialise ( settings )
function _fnInitComplete (line 4783) | function _fnInitComplete ( settings, json )
function _fnLengthChange (line 4798) | function _fnLengthChange ( settings, val )
function _fnFeatureHtmlLength (line 4816) | function _fnFeatureHtmlLength ( settings )
function _fnFeatureHtmlPaginate (line 4882) | function _fnFeatureHtmlPaginate ( settings )
function _fnPageChange (line 4943) | function _fnPageChange ( settings, action, redraw )
function _fnFeatureHtmlProcessing (line 5016) | function _fnFeatureHtmlProcessing ( settings )
function _fnProcessingDisplay (line 5033) | function _fnProcessingDisplay ( settings, show )
function _fnFeatureHtmlTable (line 5048) | function _fnFeatureHtmlTable ( settings )
function _fnScrollDraw (line 5206) | function _fnScrollDraw ( settings )
function _fnApplyToChildren (line 5489) | function _fnApplyToChildren( fn, an1, an2 )
function _fnCalculateColumnWidths (line 5528) | function _fnCalculateColumnWidths ( oSettings )
function _fnConvertToWidth (line 5766) | function _fnConvertToWidth ( width, parent )
function _fnGetWidestNode (line 5790) | function _fnGetWidestNode( settings, colIdx )
function _fnGetMaxLenString (line 5811) | function _fnGetMaxLenString( settings, colIdx )
function _fnStringToCss (line 5836) | function _fnStringToCss( s )
function _fnSortFlatten (line 5856) | function _fnSortFlatten ( settings )
function _fnSort (line 5928) | function _fnSort ( oSettings )
function _fnSortAria (line 6054) | function _fnSortAria ( settings )
function _fnSortListener (line 6109) | function _fnSortListener ( settings, colIdx, append, callback )
function _fnSortAttachListener (line 6193) | function _fnSortAttachListener ( settings, attachTo, colIdx, callback )
function _fnSortingClasses (line 6231) | function _fnSortingClasses( settings )
function _fnSortData (line 6264) | function _fnSortData( settings, idx )
function _fnSaveState (line 6307) | function _fnSaveState ( settings )
function _fnLoadState (line 6343) | function _fnLoadState ( settings, oInit, callback )
function _fnSettingsFromNode (line 6445) | function _fnSettingsFromNode ( table )
function _fnLog (line 6464) | function _fnLog( settings, level, msg, tn )
function _fnMap (line 6507) | function _fnMap( ret, src, name, mappedName )
function _fnExtend (line 6549) | function _fnExtend( out, extender, breakRefs )
function _fnBindAction (line 6585) | function _fnBindAction( n, oData, fn )
function _fnCallbackReg (line 6614) | function _fnCallbackReg( oSettings, sStore, fn, sName )
function _fnCallbackFire (line 6640) | function _fnCallbackFire( settings, callbackArr, eventName, args )
function _fnLengthOverflow (line 6662) | function _fnLengthOverflow ( settings )
function _fnRenderer (line 6687) | function _fnRenderer( settings, type )
function _fnDataSource (line 6716) | function _fnDataSource ( settings )
function _numbers (line 14494) | function _numbers ( page, pages ) {
function _addNumericSort (line 14799) | function _addNumericSort ( decimalPlace ) {
function _fnExternApiFunc (line 15054) | function _fnExternApiFunc (fn)
FILE: static/vendor/fontawesome-free/js/all.js
function bunker (line 35) | function bunker(fn) {
function _defineProperty (line 45) | function _defineProperty(obj, key, value) {
function _objectSpread (line 60) | function _objectSpread(target) {
function defineIcons (line 86) | function defineIcons(prefix, icons) {
function bunker (line 608) | function bunker(fn) {
function _defineProperty (line 618) | function _defineProperty(obj, key, value) {
function _objectSpread (line 633) | function _objectSpread(target) {
function defineIcons (line 659) | function defineIcons(prefix, icons) {
function bunker (line 884) | function bunker(fn) {
function _defineProperty (line 894) | function _defineProperty(obj, key, value) {
function _objectSpread (line 909) | function _objectSpread(target) {
function defineIcons (line 935) | function defineIcons(prefix, icons) {
function _typeof (line 1981) | function _typeof(obj) {
function _classCallCheck (line 1995) | function _classCallCheck(instance, Constructor) {
function _defineProperties (line 2001) | function _defineProperties(target, props) {
function _createClass (line 2011) | function _createClass(Constructor, protoProps, staticProps) {
function _defineProperty (line 2017) | function _defineProperty(obj, key, value) {
function _objectSpread (line 2032) | function _objectSpread(target) {
function _slicedToArray (line 2051) | function _slicedToArray(arr, i) {
function _toConsumableArray (line 2055) | function _toConsumableArray(arr) {
function _arrayWithoutHoles (line 2059) | function _arrayWithoutHoles(arr) {
function _arrayWithHoles (line 2067) | function _arrayWithHoles(arr) {
function _iterableToArray (line 2071) | function _iterableToArray(iter) {
function _iterableToArrayLimit (line 2075) | function _iterableToArrayLimit(arr, i) {
function _nonIterableSpread (line 2101) | function _nonIterableSpread() {
function _nonIterableRest (line 2105) | function _nonIterableRest() {
function getAttrConfig (line 2197) | function getAttrConfig(attr) {
function coerce (line 2205) | function coerce(val) {
function domready (line 2276) | function domready (fn) {
function asyncFlush (line 2293) | function asyncFlush() {
function asyncCall (line 2304) | function asyncCall(callback, arg) {
function invokeResolver (line 2313) | function invokeResolver(resolver, promise) {
function invokeCallback (line 2329) | function invokeCallback(subscriber) {
function handleThenable (line 2357) | function handleThenable(promise, value) {
function resolve (line 2400) | function resolve(promise, value) {
function fulfill (line 2406) | function fulfill(promise, value) {
function reject (line 2414) | function reject(promise, reason) {
function publish (line 2422) | function publish(promise) {
function publishFulfillment (line 2426) | function publishFulfillment(promise) {
function publishRejection (line 2431) | function publishRejection(promise) {
function notifyRejectionHandled (line 2440) | function notifyRejectionHandled(promise) {
function P (line 2448) | function P(resolver) {
function resolver (line 2507) | function resolver(index) {
function isReserved (line 2580) | function isReserved(name) {
function bunker (line 2584) | function bunker(fn) {
function insertCss (line 2593) | function insertCss(css) {
function nextUniqueId (line 2617) | function nextUniqueId() {
function toArray (line 2627) | function toArray(obj) {
function classArray (line 2636) | function classArray(node) {
function getIconName (line 2645) | function getIconName(familyPrefix, cls) {
function htmlEscape (line 2656) | function htmlEscape(str) {
function joinAttributes (line 2659) | function joinAttributes(attributes) {
function joinStyles (line 2664) | function joinStyles(styles) {
function transformIsMeaningful (line 2669) | function transformIsMeaningful(transform) {
function transformForSvg (line 2672) | function transformForSvg(_ref) {
function transformForCss (line 2694) | function transformForCss(_ref2) {
function fillBlack (line 2724) | function fillBlack(abstract) {
function deGroup (line 2734) | function deGroup(abstract) {
function makeIconMasking (line 2742) | function makeIconMasking (_ref) {
function makeIconStandard (line 2815) | function makeIconStandard (_ref) {
function asIcon (line 2856) | function asIcon (_ref) {
function asSymbol (line 2883) | function asSymbol (_ref) {
function makeInlineSvgAbstract (line 2905) | function makeInlineSvgAbstract(params) {
function makeLayersTextAbstract (line 2976) | function makeLayersTextAbstract(params) {
function makeLayersCounterAbstract (line 3033) | function makeLayersCounterAbstract(params) {
function toHex (line 3143) | function toHex(unicode) {
function defineIcons (line 3154) | function defineIcons(prefix, icons) {
function byUnicode (line 3235) | function byUnicode(prefix, unicode) {
function byLigature (line 3238) | function byLigature(prefix, ligature) {
function byOldName (line 3241) | function byOldName(name) {
function getCanonicalIcon (line 3256) | function getCanonicalIcon(values) {
function iconFromMapping (line 3275) | function iconFromMapping(mapping, prefix, iconName) {
function toHtml (line 3285) | function toHtml(abstractNodes) {
function isWatched (line 3301) | function isWatched(node) {
function getMutator (line 3306) | function getMutator() {
function performOperationSync (line 3365) | function performOperationSync(op) {
function perform (line 3369) | function perform(mutations, callback) {
function disableObservation (line 3391) | function disableObservation() {
function enableObservation (line 3394) | function enableObservation() {
function observe (line 3398) | function observe(options) {
function disconnect (line 3449) | function disconnect() {
function styleParser (line 3454) | function styleParser (node) {
function classParser (line 3475) | function classParser (node) {
function transformParser (line 3563) | function transformParser (node) {
function symbolParser (line 3567) | function symbolParser (node) {
function attributesParser (line 3572) | function attributesParser (node) {
function maskParser (line 3595) | function maskParser (node) {
function blankMeta (line 3607) | function blankMeta() {
function parseMeta (line 3624) | function parseMeta(node) {
function MissingIcon (line 3652) | function MissingIcon(error) {
function asFoundIcon (line 3731) | function asFoundIcon(icon) {
function findIcon (line 3780) | function findIcon(iconName, prefix) {
function generateSvgReplacementMutation (line 3810) | function generateSvgReplacementMutation(node, nodeMeta) {
function generateLayersText (line 3846) | function generateLayersText(node, nodeMeta) {
function generateMutation (line 3875) | function generateMutation(node) {
function onTree (line 3885) | function onTree(root) {
function onNode (line 3955) | function onNode(node) {
function replaceForPosition (line 3964) | function replaceForPosition(node, position) {
function replace (line 4039) | function replace(node) {
function processable (line 4043) | function processable(node) {
function searchPseudoElements (line 4047) | function searchPseudoElements (root) {
function css (line 4067) | function css () {
function Library (line 4087) | function Library() {
function ensureCss (line 4135) | function ensureCss() {
function apiObject (line 4143) | function apiObject(val, abstractCreator) {
function findIconDefinition (line 4165) | function findIconDefinition(iconLookup) {
function resolveIcons (line 4173) | function resolveIcons(next) {
function bootstrap (line 4416) | function bootstrap() {
FILE: static/vendor/fontawesome-free/js/brands.js
function bunker (line 35) | function bunker(fn) {
function _defineProperty (line 45) | function _defineProperty(obj, key, value) {
function _objectSpread (line 60) | function _objectSpread(target) {
function defineIcons (line 86) | function defineIcons(prefix, icons) {
FILE: static/vendor/fontawesome-free/js/conflict-detection.js
function _typeof (line 11) | function _typeof(obj) {
function _defineProperty (line 25) | function _defineProperty(obj, key, value) {
function _objectSpread (line 40) | function _objectSpread(target) {
function domready (line 94) | function domready (fn) {
function report (line 99) | function report (_ref) {
function createCommonjsModule (line 167) | function createCommonjsModule(fn, module) {
function safeAdd (line 183) | function safeAdd(x, y) {
function bitRotateLeft (line 197) | function bitRotateLeft(num, cnt) {
function md5cmn (line 213) | function md5cmn(q, a, b, x, s, t) {
function md5ff (line 230) | function md5ff(a, b, c, d, x, s, t) {
function md5gg (line 247) | function md5gg(a, b, c, d, x, s, t) {
function md5hh (line 264) | function md5hh(a, b, c, d, x, s, t) {
function md5ii (line 281) | function md5ii(a, b, c, d, x, s, t) {
function binlMD5 (line 293) | function binlMD5(x, len) {
function binl2rstr (line 392) | function binl2rstr(input) {
function rstr2binl (line 412) | function rstr2binl(input) {
function rstrMD5 (line 437) | function rstrMD5(s) {
function rstrHMACMD5 (line 449) | function rstrHMACMD5(key, data) {
function rstr2hex (line 477) | function rstr2hex(input) {
function str2rstrUTF8 (line 498) | function str2rstrUTF8(input) {
function rawMD5 (line 509) | function rawMD5(s) {
function hexMD5 (line 520) | function hexMD5(s) {
function rawHMACMD5 (line 532) | function rawHMACMD5(k, d) {
function hexHMACMD5 (line 544) | function hexHMACMD5(k, d) {
function md5 (line 559) | function md5(string, key, raw) {
function md5ForNode (line 583) | function md5ForNode(node) {
function pollUntil (line 610) | function pollUntil(_ref) {
function detectWebfontConflicts (line 652) | function detectWebfontConflicts() {
function detectSvgConflicts (line 771) | function detectSvgConflicts(currentScript) {
function setDoneResults (line 851) | function setDoneResults(_ref2) {
function conflictDetection (line 860) | function conflictDetection() {
function bunker (line 978) | function bunker(fn) {
FILE: static/vendor/fontawesome-free/js/fontawesome.js
function _typeof (line 8) | function _typeof(obj) {
function _classCallCheck (line 22) | function _classCallCheck(instance, Constructor) {
function _defineProperties (line 28) | function _defineProperties(target, props) {
function _createClass (line 38) | function _createClass(Constructor, protoProps, staticProps) {
function _defineProperty (line 44) | function _defineProperty(obj, key, value) {
function _objectSpread (line 59) | function _objectSpread(target) {
function _slicedToArray (line 78) | function _slicedToArray(arr, i) {
function _toConsumableArray (line 82) | function _toConsumableArray(arr) {
function _arrayWithoutHoles (line 86) | function _arrayWithoutHoles(arr) {
function _arrayWithHoles (line 94) | function _arrayWithHoles(arr) {
function _iterableToArray (line 98) | function _iterableToArray(iter) {
function _iterableToArrayLimit (line 102) | function _iterableToArrayLimit(arr, i) {
function _nonIterableSpread (line 128) | function _nonIterableSpread() {
function _nonIterableRest (line 132) | function _nonIterableRest() {
function getAttrConfig (line 224) | function getAttrConfig(attr) {
function coerce (line 232) | function coerce(val) {
function domready (line 303) | function domready (fn) {
function asyncFlush (line 320) | function asyncFlush() {
function asyncCall (line 331) | function asyncCall(callback, arg) {
function invokeResolver (line 340) | function invokeResolver(resolver, promise) {
function invokeCallback (line 356) | function invokeCallback(subscriber) {
function handleThenable (line 384) | function handleThenable(promise, value) {
function resolve (line 427) | function resolve(promise, value) {
function fulfill (line 433) | function fulfill(promise, value) {
function reject (line 441) | function reject(promise, reason) {
function publish (line 449) | function publish(promise) {
function publishFulfillment (line 453) | function publishFulfillment(promise) {
function publishRejection (line 458) | function publishRejection(promise) {
function notifyRejectionHandled (line 467) | function notifyRejectionHandled(promise) {
function P (line 475) | function P(resolver) {
function resolver (line 534) | function resolver(index) {
function isReserved (line 607) | function isReserved(name) {
function bunker (line 611) | function bunker(fn) {
function insertCss (line 620) | function insertCss(css) {
function nextUniqueId (line 644) | function nextUniqueId() {
function toArray (line 654) | function toArray(obj) {
function classArray (line 663) | function classArray(node) {
function getIconName (line 672) | function getIconName(familyPrefix, cls) {
function htmlEscape (line 683) | function htmlEscape(str) {
function joinAttributes (line 686) | function joinAttributes(attributes) {
function joinStyles (line 691) | function joinStyles(styles) {
function transformIsMeaningful (line 696) | function transformIsMeaningful(transform) {
function transformForSvg (line 699) | function transformForSvg(_ref) {
function transformForCss (line 721) | function transformForCss(_ref2) {
function fillBlack (line 751) | function fillBlack(abstract) {
function deGroup (line 761) | function deGroup(abstract) {
function makeIconMasking (line 769) | function makeIconMasking (_ref) {
function makeIconStandard (line 842) | function makeIconStandard (_ref) {
function asIcon (line 883) | function asIcon (_ref) {
function asSymbol (line 910) | function asSymbol (_ref) {
function makeInlineSvgAbstract (line 932) | function makeInlineSvgAbstract(params) {
function makeLayersTextAbstract (line 1003) | function makeLayersTextAbstract(params) {
function makeLayersCounterAbstract (line 1060) | function makeLayersCounterAbstract(params) {
function toHex (line 1170) | function toHex(unicode) {
function defineIcons (line 1181) | function defineIcons(prefix, icons) {
function byUnicode (line 1262) | function byUnicode(prefix, unicode) {
function byLigature (line 1265) | function byLigature(prefix, ligature) {
function byOldName (line 1268) | function byOldName(name) {
function getCanonicalIcon (line 1283) | function getCanonicalIcon(values) {
function iconFromMapping (line 1302) | function iconFromMapping(mapping, prefix, iconName) {
function toHtml (line 1312) | function toHtml(abstractNodes) {
function isWatched (line 1328) | function isWatched(node) {
function getMutator (line 1333) | function getMutator() {
function performOperationSync (line 1392) | function performOperationSync(op) {
function perform (line 1396) | function perform(mutations, callback) {
function disableObservation (line 1418) | function disableObservation() {
function enableObservation (line 1421) | function enableObservation() {
function observe (line 1425) | function observe(options) {
function disconnect (line 1476) | function disconnect() {
function styleParser (line 1481) | function styleParser (node) {
function classParser (line 1502) | function classParser (node) {
function transformParser (line 1590) | function transformParser (node) {
function symbolParser (line 1594) | function symbolParser (node) {
function attributesParser (line 1599) | function attributesParser (node) {
function maskParser (line 1622) | function maskParser (node) {
function blankMeta (line 1634) | function blankMeta() {
function parseMeta (line 1651) | function parseMeta(node) {
function MissingIcon (line 1679) | function MissingIcon(error) {
function asFoundIcon (line 1758) | function asFoundIcon(icon) {
function findIcon (line 1807) | function findIcon(iconName, prefix) {
function generateSvgReplacementMutation (line 1837) | function generateSvgReplacementMutation(node, nodeMeta) {
function generateLayersText (line 1873) | function generateLayersText(node, nodeMeta) {
function generateMutation (line 1902) | function generateMutation(node) {
function onTree (line 1912) | function onTree(root) {
function onNode (line 1982) | function onNode(node) {
function replaceForPosition (line 1991) | function replaceForPosition(node, position) {
function replace (line 2066) | function replace(node) {
function processable (line 2070) | function processable(node) {
function searchPseudoElements (line 2074) | function searchPseudoElements (root) {
function css (line 2094) | function css () {
function Library (line 2114) | function Library() {
function ensureCss (line 2162) | function ensureCss() {
function apiObject (line 2170) | function apiObject(val, abstractCreator) {
function findIconDefinition (line 2192) | function findIconDefinition(iconLookup) {
function resolveIcons (line 2200) | function resolveIcons(next) {
function bootstrap (line 2443) | function bootstrap() {
FILE: static/vendor/fontawesome-free/js/regular.js
function bunker (line 35) | function bunker(fn) {
function _defineProperty (line 45) | function _defineProperty(obj, key, value) {
function _objectSpread (line 60) | function _objectSpread(target) {
function defineIcons (line 86) | function defineIcons(prefix, icons) {
FILE: static/vendor/fontawesome-free/js/solid.js
function bunker (line 35) | function bunker(fn) {
function _defineProperty (line 45) | function _defineProperty(obj, key, value) {
function _objectSpread (line 60) | function _objectSpread(target) {
function defineIcons (line 86) | function defineIcons(prefix, icons) {
FILE: static/vendor/fontawesome-free/js/v4-shims.js
function bunker (line 38) | function bunker(fn) {
FILE: static/vendor/jquery-easing/jquery.easing.js
function bounceOut (line 36) | function bounceOut(x) {
FILE: static/vendor/jquery/jquery.js
function DOMEval (line 103) | function DOMEval( code, node, doc ) {
function toType (line 133) | function toType( obj ) {
function isArrayLike (line 503) | function isArrayLike( obj ) {
function Sizzle (line 755) | function Sizzle( selector, context, results, seed ) {
function createCache (line 903) | function createCache() {
function markFunction (line 923) | function markFunction( fn ) {
function assert (line 932) | function assert( fn ) {
function addHandle (line 956) | function addHandle( attrs, handler ) {
function siblingCheck (line 971) | function siblingCheck( a, b ) {
function createInputPseudo (line 997) | function createInputPseudo( type ) {
function createButtonPseudo (line 1008) | function createButtonPseudo( type ) {
function createDisabledPseudo (line 1019) | function createDisabledPseudo( disabled ) {
function createPositionalPseudo (line 1075) | function createPositionalPseudo( fn ) {
function testContext (line 1098) | function testContext( context ) {
function setFilters (line 2309) | function setFilters() {}
function toSelector (line 2383) | function toSelector( tokens ) {
function addCombinator (line 2393) | function addCombinator( matcher, combinator, base ) {
function elementMatcher (line 2460) | function elementMatcher( matchers ) {
function multipleContexts (line 2474) | function multipleContexts( selector, contexts, results ) {
function condense (line 2483) | function condense( unmatched, map, filter, context, xml ) {
function setMatcher (line 2504) | function setMatcher( preFilter, selector, matcher, postFilter, postFinde...
function matcherFromTokens (line 2604) | function matcherFromTokens( tokens ) {
function matcherFromGroupMatchers (line 2667) | function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
function nodeName (line 3025) | function nodeName( elem, name ) {
function winnow (line 3035) | function winnow( elements, qualifier, not ) {
function sibling (line 3330) | function sibling( cur, dir ) {
function createOptions (line 3423) | function createOptions( options ) {
function Identity (line 3648) | function Identity( v ) {
function Thrower (line 3651) | function Thrower( ex ) {
function adoptValue (line 3655) | function adoptValue( value, resolve, reject, noValue ) {
function resolve (line 3748) | function resolve( depth, deferred, handler, special ) {
function completed (line 4113) | function completed() {
function fcamelCase (line 4208) | function fcamelCase( _all, letter ) {
function camelCase (line 4215) | function camelCase( string ) {
function Data (line 4232) | function Data() {
function getData (line 4401) | function getData( data ) {
function dataAttr (line 4426) | function dataAttr( elem, key, data ) {
function adjustCSS (line 4738) | function adjustCSS( elem, prop, valueParts, tween ) {
function getDefaultDisplay (line 4806) | function getDefaultDisplay( elem ) {
function showHide (line 4829) | function showHide( elements, show ) {
function getAll (line 4961) | function getAll( context, tag ) {
function setGlobalEval (line 4986) | function setGlobalEval( elems, refElements ) {
function buildFragment (line 5002) | function buildFragment( elems, context, scripts, selection, ignored ) {
function returnTrue (line 5097) | function returnTrue() {
function returnFalse (line 5101) | function returnFalse() {
function expectSync (line 5111) | function expectSync( elem, type ) {
function safeActiveElement (line 5118) | function safeActiveElement() {
function on (line 5124) | function on( elem, types, selector, data, fn, one ) {
function leverageNative (line 5612) | function leverageNative( el, type, expectSync ) {
function manipulationTarget (line 5976) | function manipulationTarget( elem, content ) {
function disableScript (line 5987) | function disableScript( elem ) {
function restoreScript (line 5991) | function restoreScript( elem ) {
function cloneCopyEvent (line 6001) | function cloneCopyEvent( src, dest ) {
function fixInput (line 6034) | function fixInput( src, dest ) {
function domManip (line 6047) | function domManip( collection, args, callback, ignored ) {
function remove (line 6139) | function remove( elem, selector, keepData ) {
function computeStyleTests (line 6453) | function computeStyleTests() {
function roundPixelMeasures (line 6497) | function roundPixelMeasures( measure ) {
function curCSS (line 6571) | function curCSS( elem, name, computed ) {
function addGetHookIf (line 6624) | function addGetHookIf( conditionFn, hookFn ) {
function vendorPropName (line 6649) | function vendorPropName( name ) {
function finalPropName (line 6664) | function finalPropName( name ) {
function setPositiveNumber (line 6690) | function setPositiveNumber( _elem, value, subtract ) {
function boxModelAdjustment (line 6702) | function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, ...
function getWidthOrHeight (line 6770) | function getWidthOrHeight( elem, dimension, extra ) {
function Tween (line 7146) | function Tween( elem, options, prop, end, easing ) {
function schedule (line 7269) | function schedule() {
function createFxNow (line 7282) | function createFxNow() {
function genFx (line 7290) | function genFx( type, includeWidth ) {
function createTween (line 7310) | function createTween( value, prop, animation ) {
function defaultPrefilter (line 7324) | function defaultPrefilter( elem, props, opts ) {
function propFilter (line 7496) | function propFilter( props, specialEasing ) {
function Animation (line 7533) | function Animation( elem, properties, options ) {
function stripAndCollapse (line 8248) | function stripAndCollapse( value ) {
function getClass (line 8254) | function getClass( elem ) {
function classesToArray (line 8258) | function classesToArray( value ) {
function buildParams (line 8885) | function buildParams( prefix, obj, traditional, add ) {
function addToPrefiltersOrTransports (line 9039) | function addToPrefiltersOrTransports( structure ) {
function inspectPrefiltersOrTransports (line 9073) | function inspectPrefiltersOrTransports( structure, options, originalOpti...
function ajaxExtend (line 9102) | function ajaxExtend( target, src ) {
function ajaxHandleResponses (line 9122) | function ajaxHandleResponses( s, jqXHR, responses ) {
function ajaxConvert (line 9180) | function ajaxConvert( s, response, jqXHR, isSuccess ) {
function done (line 9696) | function done( status, nativeStatusText, responses, headers ) {
FILE: static/vendor/jquery/jquery.slim.js
function DOMEval (line 103) | function DOMEval( code, node, doc ) {
function toType (line 133) | function toType( obj ) {
function isArrayLike (line 503) | function isArrayLike( obj ) {
function Sizzle (line 755) | function Sizzle( selector, context, results, seed ) {
function createCache (line 903) | function createCache() {
function markFunction (line 923) | function markFunction( fn ) {
function assert (line 932) | function assert( fn ) {
function addHandle (line 956) | function addHandle( attrs, handler ) {
function siblingCheck (line 971) | function siblingCheck( a, b ) {
function createInputPseudo (line 997) | function createInputPseudo( type ) {
function createButtonPseudo (line 1008) | function createButtonPseudo( type ) {
function createDisabledPseudo (line 1019) | function createDisabledPseudo( disabled ) {
function createPositionalPseudo (line 1075) | function createPositionalPseudo( fn ) {
function testContext (line 1098) | function testContext( context ) {
function setFilters (line 2309) | function setFilters() {}
function toSelector (line 2383) | function toSelector( tokens ) {
function addCombinator (line 2393) | function addCombinator( matcher, combinator, base ) {
function elementMatcher (line 2460) | function elementMatcher( matchers ) {
function multipleContexts (line 2474) | function multipleContexts( selector, contexts, results ) {
function condense (line 2483) | function condense( unmatched, map, filter, context, xml ) {
function setMatcher (line 2504) | function setMatcher( preFilter, selector, matcher, postFilter, postFinde...
function matcherFromTokens (line 2604) | function matcherFromTokens( tokens ) {
function matcherFromGroupMatchers (line 2667) | function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
function nodeName (line 3025) | function nodeName( elem, name ) {
function winnow (line 3035) | function winnow( elements, qualifier, not ) {
function sibling (line 3330) | function sibling( cur, dir ) {
function createOptions (line 3423) | function createOptions( options ) {
function Identity (line 3648) | function Identity( v ) {
function Thrower (line 3651) | function Thrower( ex ) {
function adoptValue (line 3655) | function adoptValue( value, resolve, reject, noValue ) {
function resolve (line 3748) | function resolve( depth, deferred, handler, special ) {
function completed (line 4113) | function completed() {
function fcamelCase (line 4208) | function fcamelCase( _all, letter ) {
function camelCase (line 4215) | function camelCase( string ) {
function Data (line 4232) | function Data() {
function getData (line 4401) | function getData( data ) {
function dataAttr (line 4426) | function dataAttr( elem, key, data ) {
function adjustCSS (line 4738) | function adjustCSS( elem, prop, valueParts, tween ) {
function getDefaultDisplay (line 4806) | function getDefaultDisplay( elem ) {
function showHide (line 4829) | function showHide( elements, show ) {
function getAll (line 4961) | function getAll( context, tag ) {
function setGlobalEval (line 4986) | function setGlobalEval( elems, refElements ) {
function buildFragment (line 5002) | function buildFragment( elems, context, scripts, selection, ignored ) {
function returnTrue (line 5097) | function returnTrue() {
function returnFalse (line 5101) | function returnFalse() {
function expectSync (line 5111) | function expectSync( elem, type ) {
function safeActiveElement (line 5118) | function safeActiveElement() {
function on (line 5124) | function on( elem, types, selector, data, fn, one ) {
function leverageNative (line 5612) | function leverageNative( el, type, expectSync ) {
function manipulationTarget (line 5976) | function manipulationTarget( elem, content ) {
function disableScript (line 5987) | function disableScript( elem ) {
function restoreScript (line 5991) | function restoreScript( elem ) {
function cloneCopyEvent (line 6001) | function cloneCopyEvent( src, dest ) {
function fixInput (line 6034) | function fixInput( src, dest ) {
function domManip (line 6047) | function domManip( collection, args, callback, ignored ) {
function remove (line 6139) | function remove( elem, selector, keepData ) {
function computeStyleTests (line 6453) | function computeStyleTests() {
function roundPixelMeasures (line 6497) | function roundPixelMeasures( measure ) {
function curCSS (line 6571) | function curCSS( elem, name, computed ) {
function addGetHookIf (line 6624) | function addGetHookIf( conditionFn, hookFn ) {
function vendorPropName (line 6649) | function vendorPropName( name ) {
function finalPropName (line 6664) | function finalPropName( name ) {
function setPositiveNumber (line 6690) | function setPositiveNumber( _elem, value, subtract ) {
function boxModelAdjustment (line 6702) | function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, ...
function getWidthOrHeight (line 6770) | function getWidthOrHeight( elem, dimension, extra ) {
function stripAndCollapse (line 7455) | function stripAndCollapse( value ) {
function getClass (line 7461) | function getClass( elem ) {
function classesToArray (line 7465) | function classesToArray( value ) {
function buildParams (line 8086) | function buildParams( prefix, obj, traditional, add ) {
FILE: static/vendor/select2/select2.js
function hasProp (line 67) | function hasProp(obj, prop) {
function normalize (line 79) | function normalize(name, baseName) {
function makeRequire (line 191) | function makeRequire(relName, forceSync) {
function makeNormalize (line 208) | function makeNormalize(relName) {
function makeLoad (line 214) | function makeLoad(depName) {
function callDep (line 220) | function callDep(name) {
function splitPrefix (line 237) | function splitPrefix(name) {
function makeConfig (line 290) | function makeConfig(name) {
function BaseConstructor (line 505) | function BaseConstructor () {
function getMethods (line 522) | function getMethods (theClass) {
function DecoratedClass (line 548) | function DecoratedClass () {
function ctr (line 566) | function ctr () {
function Results (line 778) | function Results ($element, options, dataAdapter) {
function BaseSelection (line 1329) | function BaseSelection ($element, options) {
function SingleSelection (line 1489) | function SingleSelection () {
function MultipleSelection (line 1588) | function MultipleSelection ($element, options) {
function Placeholder (line 1696) | function Placeholder (decorated, $element, options) {
function AllowClear (line 1747) | function AllowClear () { }
function Search (line 1846) | function Search (decorated, $element, options) {
function EventRelay (line 2067) | function EventRelay () { }
function Translation (line 2114) | function Translation (dict) {
function BaseAdapter (line 2997) | function BaseAdapter ($element, options) {
function SelectAdapter (line 3040) | function SelectAdapter ($element, options) {
function ArrayAdapter (line 3326) | function ArrayAdapter ($element, options) {
function onlyItem (line 3361) | function onlyItem (item) {
function AjaxAdapter (line 3406) | function AjaxAdapter ($element, options) {
function request (line 3467) | function request () {
function Tags (line 3514) | function Tags (decorated, $element, options) {
function wrapper (line 3553) | function wrapper (obj, child) {
function Tokenizer (line 3643) | function Tokenizer (decorated, $element, options) {
function createAndSelect (line 3663) | function createAndSelect (data) {
function select (line 3686) | function select (data) {
function MinimumInputLength (line 3760) | function MinimumInputLength (decorated, $e, options) {
function MaximumInputLength (line 3791) | function MaximumInputLength (decorated, $e, options) {
function MaximumSelectionLength (line 3823) | function MaximumSelectionLength (decorated, $e, options) {
function Dropdown (line 3856) | function Dropdown ($element, options) {
function Search (line 3899) | function Search () { }
function HidePlaceholder (line 4000) | function HidePlaceholder (decorated, $element, options, dataAdapter) {
function InfiniteScroll (line 4043) | function InfiniteScroll (decorated, $element, options, dataAdapter) {
function AttachBody (line 4134) | function AttachBody (decorated, $element, options) {
function countResults (line 4356) | function countResults (data) {
function MinimumResultsForSearch (line 4372) | function MinimumResultsForSearch (decorated, $element, options, dataAdap...
function SelectOnClose (line 4396) | function SelectOnClose () { }
function CloseOnSelect (line 4447) | function CloseOnSelect () { }
function Defaults (line 4576) | function Defaults () {
function stripDiacritics (line 4823) | function stripDiacritics (text) {
function matcher (line 4832) | function matcher (params, data) {
function Options (line 4927) | function Options (options, $element) {
function syncCssClasses (line 5660) | function syncCssClasses ($dest, $src, adapter) {
function _containerAdapter (line 5706) | function _containerAdapter (clazz) {
function ContainerCSS (line 5710) | function ContainerCSS () { }
function _dropdownAdapter (line 5763) | function _dropdownAdapter (clazz) {
function DropdownCSS (line 5767) | function DropdownCSS () { }
function InitSelection (line 5818) | function InitSelection (decorated, $element, options) {
function InputData (line 5861) | function InputData (decorated, $element, options) {
function getSelected (line 5879) | function getSelected (data, selectedIds) {
function oldMatcher (line 5989) | function oldMatcher (matcher) {
function Query (line 6032) | function Query (decorated, $element, options) {
function AttachContainer (line 6059) | function AttachContainer (decorated, $element, options) {
function StopPropagation (line 6078) | function StopPropagation () { }
function StopPropagation (line 6117) | function StopPropagation () { }
function handler (line 6244) | function handler(event) {
function nullLowestDelta (line 6357) | function nullLowestDelta() {
function shouldAdjustOldDeltas (line 6361) | function shouldAdjustOldDeltas(orgEvent, absDelta) {
Copy disabled (too large)
Download .json
Condensed preview — 282 files, each showing path, character count, and a content snippet. Download the .json file for the full structured content (10,690K chars).
[
{
"path": ".gitattributes",
"chars": 66,
"preview": "# Auto detect text files and perform LF normalization\n* text=auto\n"
},
{
"path": ".gitignore",
"chars": 79,
"preview": "SECMON-CVE-Report.xlsx\nsecmon.db\nlogs.txt\n__pycache__/\nstats.py\ntest.py\ncerts/\n"
},
{
"path": ".gitlab-ci.yml",
"chars": 4888,
"preview": "variables:\n PRIVATE_REGISTRY_PASSWD: $PRIVATE_REGISTRY_PASSWD\n PRIVATE_REGISTRY_USERNAME: $PRIVATE_REGISTRY_USERNAME\n "
},
{
"path": "DOCS.md",
"chars": 24205,
"preview": "# Table of contents\n- [Table of contents](#table-of-contents)\n- [Installation](#installation)\n - [With docker](#with-do"
},
{
"path": "Dockerfile",
"chars": 520,
"preview": "FROM debian:latest\nMAINTAINER Aubin Custodio (Guezone)\nRUN apt update && apt upgrade -y && apt install -y vim apache2 na"
},
{
"path": "LICENSE",
"chars": 20844,
"preview": "Attribution-NonCommercial-ShareAlike 4.0 International\n\n================================================================"
},
{
"path": "README.md",
"chars": 6866,
"preview": "# SECMON - Infosec Watching Tool <center><img src=\"https://github.com/Guezone/SECMON/blob/master/img/logo.jpg\" data-cano"
},
{
"path": "SECURITY.md",
"chars": 377,
"preview": "## Reporting a Vulnerability\n\nPlease report (suspected) security vulnerabilities via the dedicated \"bugs-vulnérabilités\""
},
{
"path": "cve_poller.py",
"chars": 24709,
"preview": "# -*- coding: utf-8 -*-\n\"\"\" \nSECMON - Source code of the SECMON CVE poller script.\n\"\"\"\n__author__ = \"Aubin Custodio\"\n__c"
},
{
"path": "cve_template.html",
"chars": 6492,
"preview": "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n\t<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">\n"
},
{
"path": "cve_updater.py",
"chars": 6032,
"preview": "# -*- coding: utf-8 -*-\n\"\"\" \nSECMON - Source code of the SECMON updater script.\n\"\"\"\n__author__ = \"Aubin Custodio\"\n__copy"
},
{
"path": "docker/install.py",
"chars": 2438,
"preview": "from time import sleep\nimport os\nfrom getpass import getpass\nprint(\"| SECMON - DockerAutoInstall |\")\nprint(\"1. Certifica"
},
{
"path": "docker/secmon-ci.conf",
"chars": 773,
"preview": "ServerName {FQDN}\n<VirtualHost *:4443>\n WSGIScriptAlias / /var/www/secmon/secmon.wsgi\n WSGIDaemonProcess secmo"
},
{
"path": "docker/secmon.conf",
"chars": 1324,
"preview": "ServerName {FQDN}\n<VirtualHost *:80>\n ServerAdmin admin@mail.com\n ServerName {FQDN}\n ServerAlias www.{FQD"
},
{
"path": "requirements.txt",
"chars": 321,
"preview": "Jinja2==3.0.1\nWerkzeug==2.0\nFlask_SQLAlchemy==2.4.4\nrequests==2.22.0\ncolorama==0.4.3\ntweepy==3.8.0\nopenpyxl==3.0.5\ngit+h"
},
{
"path": "rss_poller.py",
"chars": 8246,
"preview": "# -*- coding: utf-8 -*-\n\"\"\" \nSECMON - Source code of the SECMON rss poller script.\n\"\"\"\n__author__ = \"Aubin Custodio\"\n__c"
},
{
"path": "rss_template.html",
"chars": 6245,
"preview": "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n\t<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">\n"
},
{
"path": "secmon.py",
"chars": 348,
"preview": "# -*- coding: utf-8 -*-\n\"\"\" \nSECMON - Launcher of poller script.\n\"\"\"\n__author__ = \"Aubin Custodio\"\n__copyright__ = \"Copy"
},
{
"path": "secmon.wsgi",
"chars": 91,
"preview": "import sys\nsys.path.insert(0, \"/var/www/secmon\")\nfrom secmon_web import app as application\n"
},
{
"path": "secmon_lib.py",
"chars": 260802,
"preview": "# -*- coding: utf-8 -*-\n\"\"\" \nSECMON - Library for SECMON python web backend.\n\"\"\"\n__author__ = \"Aubin Custodio\"\n__copyrig"
},
{
"path": "secmon_monitor.py",
"chars": 6437,
"preview": "# -*- coding: utf-8 -*-\n\"\"\" \nSECMON - Source code of the SECMON monitoring script.\n\"\"\"\n__author__ = \"Aubin Custodio\"\n__c"
},
{
"path": "secmon_web.py",
"chars": 28787,
"preview": "# -*- coding: utf-8 -*-\n\"\"\" \nSECMON - Source code of the SECMON python web backend.\n\"\"\"\n__author__ = \"Aubin Custodio\"\n__"
},
{
"path": "setup.py",
"chars": 13673,
"preview": "# -*- coding: utf-8 -*-\n\"\"\" \nSECMON - Source code of the SECMON setup script.\n\"\"\"\n__author__ = \"Aubin Custodio\"\n__copyri"
},
{
"path": "static/css/dataTables.bootstrap.css",
"chars": 7655,
"preview": "div.dataTables_length label {\n\tfont-weight: normal;\n\ttext-align: left;\n\twhite-space: nowrap;\n\tpadding-left: 5px;\n}\ndiv.d"
},
{
"path": "static/css/main.css",
"chars": 1720397,
"preview": "<?xml version=\"1.0\" standalone=\"no\"?>\n<!--\nFont Awesome Free 5.12.1 by @fontawesome - https://fontawesome.com\nLicense - "
},
{
"path": "static/css/main2.css",
"chars": 9729,
"preview": "\n\n\n\n/*//////////////////////////////////////////////////////////////////\n[ FONT ]*/\n\n@font-face {\n font-family: Montser"
},
{
"path": "static/css/morris.css",
"chars": 433,
"preview": ".morris-hover{position:absolute;z-index:1000}.morris-hover.morris-default-style{border-radius:10px;padding:6px;color:#66"
},
{
"path": "static/css/mycss.css",
"chars": 5691,
"preview": ".loader {\n margin: 100px auto;\n font-size: 25px;\n width: 1em;\n height: 1em;\n border-radius: 50%;\n position: relati"
},
{
"path": "static/css/sb-admin-2.css",
"chars": 209525,
"preview": "/*!\n * Start Bootstrap - SB Admin 2 v4.1.1 (https://startbootstrap.com/themes/sb-admin-2)\n * Copyright 2013-2020 Start B"
},
{
"path": "static/css/site.css",
"chars": 35729,
"preview": "/*!\n * Bootstrap v3.0.0\n *\n * Copyright 2013 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache"
},
{
"path": "static/css/timeline.css",
"chars": 3423,
"preview": ".timeline {\n position: relative;\n padding: 20px 0 20px;\n list-style: none;\n}\n\n.timeline:before {\n content: \""
},
{
"path": "static/css/util.css",
"chars": 83821,
"preview": "/*[ FONT SIZE ]\n///////////////////////////////////////////////////////////\n*/\n.fs-1 {font-size: 1px;}\n.fs-2 {font-size:"
},
{
"path": "static/css/util2.css",
"chars": 83821,
"preview": "/*[ FONT SIZE ]\n///////////////////////////////////////////////////////////\n*/\n.fs-1 {font-size: 1px;}\n.fs-2 {font-size:"
},
{
"path": "static/fonts/font-awesome-4.7.0/HELP-US-OUT.txt",
"chars": 323,
"preview": "I hope you love Font Awesome. If you've found it useful, please do me a favor and check out my latest project,\nFort Awes"
},
{
"path": "static/fonts/font-awesome-4.7.0/css/font-awesome.css",
"chars": 37414,
"preview": "/*!\n * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome\n * License - http://fontawesome.io/lice"
},
{
"path": "static/fonts/font-awesome-4.7.0/less/animated.less",
"chars": 713,
"preview": "// Animated Icons\n// --------------------------\n\n.@{fa-css-prefix}-spin {\n -webkit-animation: fa-spin 2s infinite linea"
},
{
"path": "static/fonts/font-awesome-4.7.0/less/bordered-pulled.less",
"chars": 585,
"preview": "// Bordered & Pulled\n// -------------------------\n\n.@{fa-css-prefix}-border {\n padding: .2em .25em .15em;\n border: sol"
},
{
"path": "static/fonts/font-awesome-4.7.0/less/core.less",
"chars": 452,
"preview": "// Base Class Definition\n// -------------------------\n\n.@{fa-css-prefix} {\n display: inline-block;\n font: normal norma"
},
{
"path": "static/fonts/font-awesome-4.7.0/less/fixed-width.less",
"chars": 119,
"preview": "// Fixed Width Icons\n// -------------------------\n.@{fa-css-prefix}-fw {\n width: (18em / 14);\n text-align: center;\n}\n"
},
{
"path": "static/fonts/font-awesome-4.7.0/less/font-awesome.less",
"chars": 495,
"preview": "/*!\n * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome\n * License - http://fontawesome.io/lice"
},
{
"path": "static/fonts/font-awesome-4.7.0/less/icons.less",
"chars": 49712,
"preview": "/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen\n readers do not read off random characters th"
},
{
"path": "static/fonts/font-awesome-4.7.0/less/larger.less",
"chars": 370,
"preview": "// Icon Sizes\n// -------------------------\n\n/* makes the font 33% larger relative to the icon container */\n.@{fa-css-pre"
},
{
"path": "static/fonts/font-awesome-4.7.0/less/list.less",
"chars": 377,
"preview": "// List Icons\n// -------------------------\n\n.@{fa-css-prefix}-ul {\n padding-left: 0;\n margin-left: @fa-li-width;\n lis"
},
{
"path": "static/fonts/font-awesome-4.7.0/less/mixins.less",
"chars": 1603,
"preview": "// Mixins\n// --------------------------\n\n.fa-icon() {\n display: inline-block;\n font: normal normal normal @fa-font-siz"
},
{
"path": "static/fonts/font-awesome-4.7.0/less/path.less",
"chars": 771,
"preview": "/* FONT PATH\n * -------------------------- */\n\n@font-face {\n font-family: 'FontAwesome';\n src: url('@{fa-font-path}/fo"
},
{
"path": "static/fonts/font-awesome-4.7.0/less/rotated-flipped.less",
"chars": 622,
"preview": "// Rotated & Flipped Icons\n// -------------------------\n\n.@{fa-css-prefix}-rotate-90 { .fa-icon-rotate(90deg, 1); }\n.@"
},
{
"path": "static/fonts/font-awesome-4.7.0/less/screen-reader.less",
"chars": 118,
"preview": "// Screen Readers\n// -------------------------\n\n.sr-only { .sr-only(); }\n.sr-only-focusable { .sr-only-focusable(); }\n"
},
{
"path": "static/fonts/font-awesome-4.7.0/less/stacked.less",
"chars": 476,
"preview": "// Stacked Icons\n// -------------------------\n\n.@{fa-css-prefix}-stack {\n position: relative;\n display: inline-block;\n"
},
{
"path": "static/fonts/font-awesome-4.7.0/less/variables.less",
"chars": 22563,
"preview": "// Variables\n// --------------------------\n\n@fa-font-path: \"../fonts\";\n@fa-font-size-base: 14px;\n@fa-line-heigh"
},
{
"path": "static/fonts/font-awesome-4.7.0/scss/_animated.scss",
"chars": 715,
"preview": "// Spinning Icons\n// --------------------------\n\n.#{$fa-css-prefix}-spin {\n -webkit-animation: fa-spin 2s infinite line"
},
{
"path": "static/fonts/font-awesome-4.7.0/scss/_bordered-pulled.scss",
"chars": 592,
"preview": "// Bordered & Pulled\n// -------------------------\n\n.#{$fa-css-prefix}-border {\n padding: .2em .25em .15em;\n border: so"
},
{
"path": "static/fonts/font-awesome-4.7.0/scss/_core.scss",
"chars": 459,
"preview": "// Base Class Definition\n// -------------------------\n\n.#{$fa-css-prefix} {\n display: inline-block;\n font: normal norm"
},
{
"path": "static/fonts/font-awesome-4.7.0/scss/_fixed-width.scss",
"chars": 120,
"preview": "// Fixed Width Icons\n// -------------------------\n.#{$fa-css-prefix}-fw {\n width: (18em / 14);\n text-align: center;\n}\n"
},
{
"path": "static/fonts/font-awesome-4.7.0/scss/_icons.scss",
"chars": 50498,
"preview": "/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen\n readers do not read off random characters th"
},
{
"path": "static/fonts/font-awesome-4.7.0/scss/_larger.scss",
"chars": 375,
"preview": "// Icon Sizes\n// -------------------------\n\n/* makes the font 33% larger relative to the icon container */\n.#{$fa-css-pr"
},
{
"path": "static/fonts/font-awesome-4.7.0/scss/_list.scss",
"chars": 378,
"preview": "// List Icons\n// -------------------------\n\n.#{$fa-css-prefix}-ul {\n padding-left: 0;\n margin-left: $fa-li-width;\n li"
},
{
"path": "static/fonts/font-awesome-4.7.0/scss/_mixins.scss",
"chars": 1637,
"preview": "// Mixins\n// --------------------------\n\n@mixin fa-icon() {\n display: inline-block;\n font: normal normal normal #{$fa-"
},
{
"path": "static/fonts/font-awesome-4.7.0/scss/_path.scss",
"chars": 783,
"preview": "/* FONT PATH\n * -------------------------- */\n\n@font-face {\n font-family: 'FontAwesome';\n src: url('#{$fa-font-path}/f"
},
{
"path": "static/fonts/font-awesome-4.7.0/scss/_rotated-flipped.scss",
"chars": 672,
"preview": "// Rotated & Flipped Icons\n// -------------------------\n\n.#{$fa-css-prefix}-rotate-90 { @include fa-icon-rotate(90deg, "
},
{
"path": "static/fonts/font-awesome-4.7.0/scss/_screen-reader.scss",
"chars": 134,
"preview": "// Screen Readers\n// -------------------------\n\n.sr-only { @include sr-only(); }\n.sr-only-focusable { @include sr-only-f"
},
{
"path": "static/fonts/font-awesome-4.7.0/scss/_stacked.scss",
"chars": 482,
"preview": "// Stacked Icons\n// -------------------------\n\n.#{$fa-css-prefix}-stack {\n position: relative;\n display: inline-block;"
},
{
"path": "static/fonts/font-awesome-4.7.0/scss/_variables.scss",
"chars": 22644,
"preview": "// Variables\n// --------------------------\n\n$fa-font-path: \"../fonts\" !default;\n$fa-font-size-base: 14px !defau"
},
{
"path": "static/fonts/font-awesome-4.7.0/scss/font-awesome.scss",
"chars": 430,
"preview": "/*!\n * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome\n * License - http://fontawesome.io/lice"
},
{
"path": "static/fonts/montserrat/OFL.txt",
"chars": 4392,
"preview": "Copyright 2011 The Montserrat Project Authors (https://github.com/JulietaUla/Montserrat)\n\nThis Font Software is licensed"
},
{
"path": "static/fonts/raleway/OFL.txt",
"chars": 4555,
"preview": "Copyright (c) 2010, Matt McInerney (matt@pixelspread.com),\nCopyright (c) 2011, Pablo Impallari (www.impallari.com|impall"
},
{
"path": "static/js/demo/chart-area-demo.js",
"chars": 3569,
"preview": "// Set new default font family and font color to mimic Bootstrap's default styling\nChart.defaults.global.defaultFontFami"
},
{
"path": "static/js/demo/chart-bar-demo.js",
"chars": 3189,
"preview": "// Set new default font family and font color to mimic Bootstrap's default styling\nChart.defaults.global.defaultFontFami"
},
{
"path": "static/js/demo/chart-pie-demo.js",
"chars": 1057,
"preview": "// Set new default font family and font color to mimic Bootstrap's default styling\nChart.defaults.global.defaultFontFami"
},
{
"path": "static/js/demo/datatables-demo.js",
"chars": 103,
"preview": "// Call the dataTables jQuery plugin\n$(document).ready(function() {\n $('#dataTable').DataTable();\n});\n"
},
{
"path": "static/js/main.js",
"chars": 1363,
"preview": "\n(function ($) {\n \"use strict\";\n\n /*==================================================================\n [ Valid"
},
{
"path": "static/js/sb-admin-2.js",
"chars": 2078,
"preview": "(function($) {\n \"use strict\"; // Start of use strict\n\n // Toggle the side navigation\n $(\"#sidebarToggle, #sidebarTogg"
},
{
"path": "static/scss/_buttons.scss",
"chars": 980,
"preview": ".btn-circle {\n border-radius: 100%;\n height: 2.5rem;\n width: 2.5rem;\n font-size: 1rem;\n display: inline-flex;\n ali"
},
{
"path": "static/scss/_cards.scss",
"chars": 733,
"preview": "// Custom Card Styling\n\n.card {\n .card-header {\n // Format Dropdowns in Card Headings\n .dropdown {\n line-hei"
},
{
"path": "static/scss/_charts.scss",
"chars": 454,
"preview": "// Area Chart\n.chart-area {\n position: relative;\n height: 10rem;\n width: 100%;\n @include media-breakpoint-up(md) {\n "
},
{
"path": "static/scss/_dropdowns.scss",
"chars": 356,
"preview": "// Custom Dropdown Styling\n\n.dropdown {\n .dropdown-menu {\n font-size: $dropdown-font-size;\n .dropdown-header {\n "
},
{
"path": "static/scss/_error.scss",
"chars": 1139,
"preview": "// Lucas Bebber's Glitch Effect\n// Tutorial and CSS from CSS Tricks\n// https://css-tricks.com/glitch-effect-text-images-"
},
{
"path": "static/scss/_footer.scss",
"chars": 196,
"preview": "footer.sticky-footer {\n padding: 2rem 0;\n flex-shrink: 0;\n .copyright {\n line-height: 1;\n font-size: 0.8rem;\n "
},
{
"path": "static/scss/_global.scss",
"chars": 886,
"preview": "// Global component styles\n\nhtml {\n position: relative;\n min-height: 100%;\n}\n\nbody {\n height: 100%;\n}\n\na {\n &:focus "
},
{
"path": "static/scss/_login.scss",
"chars": 893,
"preview": "// Pulling these images from Unsplash\n// Toshi the dog from https://unsplash.com/@charlesdeluvio - what a funny dog...\n\n"
},
{
"path": "static/scss/_mixins.scss",
"chars": 1,
"preview": "\n"
},
{
"path": "static/scss/_navs.scss",
"chars": 85,
"preview": "@import \"navs/global.scss\";\n@import \"navs/topbar.scss\";\n@import \"navs/sidebar.scss\";\n"
},
{
"path": "static/scss/_utilities.scss",
"chars": 239,
"preview": "@import \"utilities/animation.scss\";\n@import \"utilities/background.scss\";\n@import \"utilities/display.scss\";\n@import \"util"
},
{
"path": "static/scss/_variables.scss",
"chars": 2477,
"preview": "// Override Bootstrap default variables here\n// Do not edit any of the files in /vendor/bootstrap/scss/!\n\n// Color Varia"
},
{
"path": "static/scss/navs/_global.scss",
"chars": 911,
"preview": "// Global styles for both custom sidebar and topbar compoments\n\n.sidebar,\n.topbar {\n .nav-item {\n // Customize Dropd"
},
{
"path": "static/scss/navs/_sidebar.scss",
"chars": 7721,
"preview": "// Sidebar\n.sidebar {\n width: $sidebar-collapsed-width;\n min-height: 100vh;\n .nav-item {\n position: relative;\n "
},
{
"path": "static/scss/navs/_topbar.scss",
"chars": 2796,
"preview": "// Topbar\n.topbar {\n height: $topbar-base-height;\n #sidebarToggleTop {\n height: 2.5rem;\n width: 2.5rem;\n &:ho"
},
{
"path": "static/scss/sb-admin-2.scss",
"chars": 504,
"preview": "// Import Custom SB Admin 2 Variables (Overrides Default Bootstrap Variables)\n@import \"variables.scss\";\n\n// Import Boots"
},
{
"path": "static/scss/utilities/_animation.scss",
"chars": 596,
"preview": "// Animation Utilities\n\n// Grow In Animation\n\n@keyframes growIn {\n 0% {\n transform: scale(0.9);\n opacity: 0;\n }\n"
},
{
"path": "static/scss/utilities/_background.scss",
"chars": 389,
"preview": "// Background Gradient Utilities\n\n@each $color, $value in $theme-colors {\n .bg-gradient-#{$color} {\n background-colo"
},
{
"path": "static/scss/utilities/_border.scss",
"chars": 190,
"preview": "@each $color, $value in $theme-colors {\n @each $position in ['left', 'bottom'] {\n .border-#{$position}-#{$color} {\n "
},
{
"path": "static/scss/utilities/_display.scss",
"chars": 64,
"preview": "// Overflow Hidden\n.o-hidden {\n overflow: hidden !important;\n}\n"
},
{
"path": "static/scss/utilities/_progress.scss",
"chars": 34,
"preview": ".progress-sm {\n height: .5rem;\n}\n"
},
{
"path": "static/scss/utilities/_rotate.scss",
"chars": 90,
"preview": ".rotate-15 {\n transform: rotate(15deg);\n}\n\n.rotate-n-15 {\n transform: rotate(-15deg);\n}\n"
},
{
"path": "static/scss/utilities/_text.scss",
"chars": 699,
"preview": "// Grayscale Text Utilities\n\n.text-xs {\n font-size: .7rem;\n}\n\n.text-lg {\n font-size: 1.2rem;\n}\n\n.text-gray-100 {\n col"
},
{
"path": "static/vendor/animate/animate.css",
"chars": 23848,
"preview": "@charset \"UTF-8\";\n\n/*!\n * animate.css -http://daneden.me/animate\n * Version - 3.5.2\n * Licensed under the MIT license - "
},
{
"path": "static/vendor/bootstrap/css/bootstrap-grid.css",
"chars": 29140,
"preview": "@-ms-viewport {\n width: device-width;\n}\n\nhtml {\n box-sizing: border-box;\n -ms-overflow-style: scrollbar;\n}\n\n*,\n*::bef"
},
{
"path": "static/vendor/bootstrap/css/bootstrap-reboot.css",
"chars": 4486,
"preview": "html {\n box-sizing: border-box;\n font-family: sans-serif;\n line-height: 1.15;\n -webkit-text-size-adjust: 100%;\n -ms"
},
{
"path": "static/vendor/bootstrap/css/bootstrap.css",
"chars": 156884,
"preview": "/*!\n * Bootstrap v4.0.0-beta (https://getbootstrap.com)\n * Copyright 2011-2017 The Bootstrap Authors\n * Copyright 2011-2"
},
{
"path": "static/vendor/bootstrap/js/bootstrap.bundle.js",
"chars": 229199,
"preview": "/*!\n * Bootstrap v4.5.0 (https://getbootstrap.com/)\n * Copyright 2011-2020 The Bootstrap Authors (https://github.com/t"
},
{
"path": "static/vendor/bootstrap/js/bootstrap.js",
"chars": 136323,
"preview": "/*!\n * Bootstrap v4.5.0 (https://getbootstrap.com/)\n * Copyright 2011-2020 The Bootstrap Authors (https://github.com/t"
},
{
"path": "static/vendor/bootstrap/js/popper.js",
"chars": 81668,
"preview": "/**!\n * @fileOverview Kickass library to create and place poppers near their reference elements.\n * @version 1.12.5\n * @"
},
{
"path": "static/vendor/bootstrap/js/tooltip.js",
"chars": 17285,
"preview": "/**!\n * @fileOverview Kickass library to create and place poppers near their reference elements.\n * @version 1.1.5\n * @l"
},
{
"path": "static/vendor/bootstrap/scss/_alert.scss",
"chars": 1148,
"preview": "//\n// Base styles\n//\n\n.alert {\n position: relative;\n padding: $alert-padding-y $alert-padding-x;\n margin-bottom: $ale"
},
{
"path": "static/vendor/bootstrap/scss/_badge.scss",
"chars": 1121,
"preview": "// Base class\n//\n// Requires one of the contextual, color modifier classes for `color` and\n// `background-color`.\n\n.badg"
},
{
"path": "static/vendor/bootstrap/scss/_breadcrumb.scss",
"chars": 1353,
"preview": ".breadcrumb {\n display: flex;\n flex-wrap: wrap;\n padding: $breadcrumb-padding-y $breadcrumb-padding-x;\n margin-botto"
},
{
"path": "static/vendor/bootstrap/scss/_button-group.scss",
"chars": 3626,
"preview": "// stylelint-disable selector-no-qualifying-type\n\n// Make the div behave like a button\n.btn-group,\n.btn-group-vertical {"
},
{
"path": "static/vendor/bootstrap/scss/_buttons.scss",
"chars": 2685,
"preview": "// stylelint-disable selector-no-qualifying-type\n\n//\n// Base styles\n//\n\n.btn {\n display: inline-block;\n font-family: $"
},
{
"path": "static/vendor/bootstrap/scss/_card.scss",
"chars": 5691,
"preview": "//\n// Base styles\n//\n\n.card {\n position: relative;\n display: flex;\n flex-direction: column;\n min-width: 0; // See ht"
},
{
"path": "static/vendor/bootstrap/scss/_carousel.scss",
"chars": 4794,
"preview": "// Notes on the classes:\n//\n// 1. .carousel.pointer-event should ideally be pan-y (to allow for users to scroll vertical"
},
{
"path": "static/vendor/bootstrap/scss/_close.scss",
"chars": 940,
"preview": ".close {\n float: right;\n @include font-size($close-font-size);\n font-weight: $close-font-weight;\n line-height: 1;\n "
},
{
"path": "static/vendor/bootstrap/scss/_code.scss",
"chars": 1012,
"preview": "// Inline code\ncode {\n @include font-size($code-font-size);\n color: $code-color;\n word-wrap: break-word;\n\n // Stream"
},
{
"path": "static/vendor/bootstrap/scss/_custom-forms.scss",
"chars": 15525,
"preview": "// Embedded icons from Open Iconic.\n// Released under MIT and copyright 2014 Waybury.\n// https://useiconic.com/open\n\n\n//"
},
{
"path": "static/vendor/bootstrap/scss/_dropdown.scss",
"chars": 4414,
"preview": "// The dropdown wrapper (`<div>`)\n.dropup,\n.dropright,\n.dropdown,\n.dropleft {\n position: relative;\n}\n\n.dropdown-toggle "
},
{
"path": "static/vendor/bootstrap/scss/_forms.scss",
"chars": 9242,
"preview": "// stylelint-disable selector-no-qualifying-type\n\n//\n// Textual form controls\n//\n\n.form-control {\n display: block;\n wi"
},
{
"path": "static/vendor/bootstrap/scss/_functions.scss",
"chars": 4129,
"preview": "// Bootstrap functions\n//\n// Utility mixins and functions for evaluating source code across our variables, maps, and mix"
},
{
"path": "static/vendor/bootstrap/scss/_grid.scss",
"chars": 1824,
"preview": "// Container widths\n//\n// Set the container width, and override it for fixed navbars in media queries.\n\n@if $enable-grid"
},
{
"path": "static/vendor/bootstrap/scss/_images.scss",
"chars": 1157,
"preview": "// Responsive images (ensure images don't scale beyond their parents)\n//\n// This is purposefully opt-in via an explicit "
},
{
"path": "static/vendor/bootstrap/scss/_input-group.scss",
"chars": 5804,
"preview": "// stylelint-disable selector-no-qualifying-type\n\n//\n// Base styles\n//\n\n.input-group {\n position: relative;\n display: "
},
{
"path": "static/vendor/bootstrap/scss/_jumbotron.scss",
"chars": 405,
"preview": ".jumbotron {\n padding: $jumbotron-padding ($jumbotron-padding / 2);\n margin-bottom: $jumbotron-padding;\n color: $jumb"
},
{
"path": "static/vendor/bootstrap/scss/_list-group.scss",
"chars": 3872,
"preview": "// Base class\n//\n// Easily usable on <ul>, <ol>, or <div>.\n\n.list-group {\n display: flex;\n flex-direction: column;\n\n "
},
{
"path": "static/vendor/bootstrap/scss/_media.scss",
"chars": 83,
"preview": ".media {\n display: flex;\n align-items: flex-start;\n}\n\n.media-body {\n flex: 1;\n}\n"
},
{
"path": "static/vendor/bootstrap/scss/_mixins.scss",
"chars": 1050,
"preview": "// Toggles\n//\n// Used in conjunction with global variables to enable certain theme features.\n\n// Vendor\n@import \"vendor/"
},
{
"path": "static/vendor/bootstrap/scss/_modal.scss",
"chars": 6364,
"preview": "// .modal-open - body class for killing the scroll\n// .modal - container to scroll within\n// .modal-dialo"
},
{
"path": "static/vendor/bootstrap/scss/_nav.scss",
"chars": 2143,
"preview": "// Base class\n//\n// Kickstart any navigation component with a set of style resets. Works with\n// `<nav>`s, `<ul>`s or `<"
},
{
"path": "static/vendor/bootstrap/scss/_navbar.scss",
"chars": 7399,
"preview": "// Contents\n//\n// Navbar\n// Navbar brand\n// Navbar nav\n// Navbar text\n// Navbar divider\n// Responsive navbar\n// Navbar p"
},
{
"path": "static/vendor/bootstrap/scss/_pagination.scss",
"chars": 1801,
"preview": ".pagination {\n display: flex;\n @include list-unstyled();\n @include border-radius();\n}\n\n.page-link {\n position: relat"
},
{
"path": "static/vendor/bootstrap/scss/_popover.scss",
"chars": 4705,
"preview": ".popover {\n position: absolute;\n top: 0;\n left: 0;\n z-index: $zindex-popover;\n display: block;\n max-width: $popove"
},
{
"path": "static/vendor/bootstrap/scss/_print.scss",
"chars": 3033,
"preview": "// stylelint-disable declaration-no-important, selector-no-qualifying-type\n\n// Source: https://github.com/h5bp/main.css/"
},
{
"path": "static/vendor/bootstrap/scss/_progress.scss",
"chars": 1171,
"preview": "// Disable animation if transitions are disabled\n@if $enable-transitions {\n @keyframes progress-bar-stripes {\n from "
},
{
"path": "static/vendor/bootstrap/scss/_reboot.scss",
"chars": 11383,
"preview": "// stylelint-disable at-rule-no-vendor-prefix, declaration-no-important, selector-no-qualifying-type, property-no-vendor"
},
{
"path": "static/vendor/bootstrap/scss/_root.scss",
"chars": 627,
"preview": "// Do not forget to update getting-started/theming.md!\n:root {\n // Custom variable values only support SassScript insid"
},
{
"path": "static/vendor/bootstrap/scss/_spinners.scss",
"chars": 1072,
"preview": "//\n// Rotating border\n//\n\n@keyframes spinner-border {\n to { transform: rotate(360deg); }\n}\n\n.spinner-border {\n display"
},
{
"path": "static/vendor/bootstrap/scss/_tables.scss",
"chars": 3544,
"preview": "//\n// Basic Bootstrap table\n//\n\n.table {\n width: 100%;\n margin-bottom: $spacer;\n color: $table-color;\n background-co"
},
{
"path": "static/vendor/bootstrap/scss/_toasts.scss",
"chars": 990,
"preview": ".toast {\n max-width: $toast-max-width;\n overflow: hidden; // cheap rounded corners on nested items\n @include font-siz"
},
{
"path": "static/vendor/bootstrap/scss/_tooltip.scss",
"chars": 2512,
"preview": "// Base class\n.tooltip {\n position: absolute;\n z-index: $zindex-tooltip;\n display: block;\n margin: $tooltip-margin;\n"
},
{
"path": "static/vendor/bootstrap/scss/_transitions.scss",
"chars": 261,
"preview": ".fade {\n @include transition($transition-fade);\n\n &:not(.show) {\n opacity: 0;\n }\n}\n\n.collapse {\n &:not(.show) {\n "
},
{
"path": "static/vendor/bootstrap/scss/_type.scss",
"chars": 2248,
"preview": "// stylelint-disable declaration-no-important, selector-list-comma-newline-after\n\n//\n// Headings\n//\n\nh1, h2, h3, h4, h5,"
},
{
"path": "static/vendor/bootstrap/scss/_utilities.scss",
"chars": 536,
"preview": "@import \"utilities/align\";\n@import \"utilities/background\";\n@import \"utilities/borders\";\n@import \"utilities/clearfix\";\n@i"
},
{
"path": "static/vendor/bootstrap/scss/_variables.scss",
"chars": 48621,
"preview": "// Variables\n//\n// Variables should follow the `$component-state-property-size` formula for\n// consistent naming. Ex: $n"
},
{
"path": "static/vendor/bootstrap/scss/bootstrap-grid.scss",
"chars": 572,
"preview": "/*!\n * Bootstrap Grid v4.5.0 (https://getbootstrap.com/)\n * Copyright 2011-2020 The Bootstrap Authors\n * Copyright 2011-"
},
{
"path": "static/vendor/bootstrap/scss/bootstrap-reboot.scss",
"chars": 411,
"preview": "/*!\n * Bootstrap Reboot v4.5.0 (https://getbootstrap.com/)\n * Copyright 2011-2020 The Bootstrap Authors\n * Copyright 201"
},
{
"path": "static/vendor/bootstrap/scss/bootstrap.scss",
"chars": 920,
"preview": "/*!\n * Bootstrap v4.5.0 (https://getbootstrap.com/)\n * Copyright 2011-2020 The Bootstrap Authors\n * Copyright 2011-2020 "
},
{
"path": "static/vendor/bootstrap/scss/mixins/_alert.scss",
"chars": 242,
"preview": "@mixin alert-variant($background, $border, $color) {\n color: $color;\n @include gradient-bg($background);\n border-colo"
},
{
"path": "static/vendor/bootstrap/scss/mixins/_background-variant.scss",
"chars": 695,
"preview": "// stylelint-disable declaration-no-important\n\n// Contextual backgrounds\n\n@mixin bg-variant($parent, $color, $ignore-war"
},
{
"path": "static/vendor/bootstrap/scss/mixins/_badge.scss",
"chars": 320,
"preview": "@mixin badge-variant($bg) {\n color: color-yiq($bg);\n background-color: $bg;\n\n @at-root a#{&} {\n @include hover-foc"
},
{
"path": "static/vendor/bootstrap/scss/mixins/_border-radius.scss",
"chars": 1822,
"preview": "// stylelint-disable property-blacklist\n// Single side border-radius\n\n// Helper function to replace negative values with"
},
{
"path": "static/vendor/bootstrap/scss/mixins/_box-shadow.scss",
"chars": 532,
"preview": "@mixin box-shadow($shadow...) {\n @if $enable-shadows {\n $result: ();\n\n @if (length($shadow) == 1) {\n // We c"
},
{
"path": "static/vendor/bootstrap/scss/mixins/_breakpoints.scss",
"chars": 4482,
"preview": "// Breakpoint viewport sizes and media queries.\n//\n// Breakpoints are defined as a map of (name: minimum width), order f"
},
{
"path": "static/vendor/bootstrap/scss/mixins/_buttons.scss",
"chars": 3525,
"preview": "// Button variants\n//\n// Easily pump out default styles, as well as :hover, :focus, :active,\n// and disabled options for"
},
{
"path": "static/vendor/bootstrap/scss/mixins/_caret.scss",
"chars": 1422,
"preview": "@mixin caret-down() {\n border-top: $caret-width solid;\n border-right: $caret-width solid transparent;\n border-bottom:"
},
{
"path": "static/vendor/bootstrap/scss/mixins/_clearfix.scss",
"chars": 93,
"preview": "@mixin clearfix() {\n &::after {\n display: block;\n clear: both;\n content: \"\";\n }\n}\n"
},
{
"path": "static/vendor/bootstrap/scss/mixins/_deprecate.scss",
"chars": 613,
"preview": "// Deprecate mixin\n//\n// This mixin can be used to deprecate mixins or functions.\n// `$enable-deprecation-messages` is a"
},
{
"path": "static/vendor/bootstrap/scss/mixins/_float.scss",
"chars": 392,
"preview": "// stylelint-disable declaration-no-important\n\n@mixin float-left() {\n float: left !important;\n @include deprecate(\"The"
},
{
"path": "static/vendor/bootstrap/scss/mixins/_forms.scss",
"chars": 5105,
"preview": "// Form control focus state\n//\n// Generate a customized focus state and for any input with the specified color,\n// which"
},
{
"path": "static/vendor/bootstrap/scss/mixins/_gradients.scss",
"chars": 2050,
"preview": "// Gradients\n\n@mixin gradient-bg($color) {\n @if $enable-gradients {\n background: $color linear-gradient(180deg, mix("
},
{
"path": "static/vendor/bootstrap/scss/mixins/_grid-framework.scss",
"chars": 2163,
"preview": "// Framework grid generation\n//\n// Used only by Bootstrap to generate the correct number of grid classes given\n// any va"
},
{
"path": "static/vendor/bootstrap/scss/mixins/_grid.scss",
"chars": 1969,
"preview": "/// Grid system\n//\n// Generate semantic grid columns with these mixins.\n\n@mixin make-container($gutter: $grid-gutter-wid"
},
{
"path": "static/vendor/bootstrap/scss/mixins/_hover.scss",
"chars": 757,
"preview": "// Hover mixin and `$enable-hover-media-query` are deprecated.\n//\n// Originally added during our alphas and maintained d"
},
{
"path": "static/vendor/bootstrap/scss/mixins/_image.scss",
"chars": 1161,
"preview": "// Image Mixins\n// - Responsive image\n// - Retina image\n\n\n// Responsive image\n//\n// Keep images from scaling beyond the "
},
{
"path": "static/vendor/bootstrap/scss/mixins/_list-group.scss",
"chars": 433,
"preview": "// List Groups\n\n@mixin list-group-item-variant($state, $background, $color) {\n .list-group-item-#{$state} {\n color: "
},
{
"path": "static/vendor/bootstrap/scss/mixins/_lists.scss",
"chars": 170,
"preview": "// Lists\n\n// Unstyled keeps list items block level, just removes default browser padding and list-style\n@mixin list-unst"
},
{
"path": "static/vendor/bootstrap/scss/mixins/_nav-divider.scss",
"chars": 369,
"preview": "// Horizontal dividers\n//\n// Dividers (basically an hr) within dropdowns and nav lists\n\n@mixin nav-divider($color: $nav-"
},
{
"path": "static/vendor/bootstrap/scss/mixins/_pagination.scss",
"chars": 462,
"preview": "// Pagination\n\n@mixin pagination-size($padding-y, $padding-x, $font-size, $line-height, $border-radius) {\n .page-link {"
},
{
"path": "static/vendor/bootstrap/scss/mixins/_reset-text.scss",
"chars": 481,
"preview": "@mixin reset-text() {\n font-family: $font-family-base;\n // We deliberately do NOT reset font-size or word-wrap.\n font"
},
{
"path": "static/vendor/bootstrap/scss/mixins/_resize.scss",
"chars": 202,
"preview": "// Resize anything\n\n@mixin resizable($direction) {\n overflow: auto; // Per CSS3 UI, `resize` only applies when `overflo"
},
{
"path": "static/vendor/bootstrap/scss/mixins/_screen-reader.scss",
"chars": 811,
"preview": "// Only display content to screen readers\n//\n// See: https://a11yproject.com/posts/how-to-hide-content/\n// See: https://"
},
{
"path": "static/vendor/bootstrap/scss/mixins/_size.scss",
"chars": 148,
"preview": "// Sizing shortcuts\n\n@mixin size($width, $height: $width) {\n width: $width;\n height: $height;\n @include deprecate(\"`s"
},
{
"path": "static/vendor/bootstrap/scss/mixins/_table-row.scss",
"chars": 794,
"preview": "// Tables\n\n@mixin table-row-variant($state, $background, $border: null) {\n // Exact selectors below required to overrid"
},
{
"path": "static/vendor/bootstrap/scss/mixins/_text-emphasis.scss",
"chars": 474,
"preview": "// stylelint-disable declaration-no-important\n\n// Typography\n\n@mixin text-emphasis-variant($parent, $color, $ignore-warn"
},
{
"path": "static/vendor/bootstrap/scss/mixins/_text-hide.scss",
"chars": 326,
"preview": "// CSS image replacement\n@mixin text-hide($ignore-warning: false) {\n // stylelint-disable-next-line font-family-no-miss"
},
{
"path": "static/vendor/bootstrap/scss/mixins/_text-truncate.scss",
"chars": 168,
"preview": "// Text truncate\n// Requires inline-block or block for proper styling\n\n@mixin text-truncate() {\n overflow: hidden;\n te"
},
{
"path": "static/vendor/bootstrap/scss/mixins/_transition.scss",
"chars": 675,
"preview": "// stylelint-disable property-blacklist\n@mixin transition($transition...) {\n @if length($transition) == 0 {\n $transi"
},
{
"path": "static/vendor/bootstrap/scss/mixins/_visibility.scss",
"chars": 189,
"preview": "// stylelint-disable declaration-no-important\n\n// Visibility\n\n@mixin invisible($visibility) {\n visibility: $visibility "
},
{
"path": "static/vendor/bootstrap/scss/utilities/_align.scss",
"chars": 420,
"preview": "// stylelint-disable declaration-no-important\n\n.align-baseline { vertical-align: baseline !important; } // Browser de"
},
{
"path": "static/vendor/bootstrap/scss/utilities/_background.scss",
"chars": 409,
"preview": "// stylelint-disable declaration-no-important\n\n@each $color, $value in $theme-colors {\n @include bg-variant(\".bg-#{$col"
},
{
"path": "static/vendor/bootstrap/scss/utilities/_borders.scss",
"chars": 1765,
"preview": "// stylelint-disable property-blacklist, declaration-no-important\n\n//\n// Border\n//\n\n.border { border: $border-wi"
},
{
"path": "static/vendor/bootstrap/scss/utilities/_clearfix.scss",
"chars": 37,
"preview": ".clearfix {\n @include clearfix();\n}\n"
},
{
"path": "static/vendor/bootstrap/scss/utilities/_display.scss",
"chars": 519,
"preview": "// stylelint-disable declaration-no-important\n\n//\n// Utilities for common `display` values\n//\n\n@each $breakpoint in map-"
},
{
"path": "static/vendor/bootstrap/scss/utilities/_embed.scss",
"chars": 846,
"preview": "// Credit: Nicolas Gallagher and SUIT CSS.\n\n.embed-responsive {\n position: relative;\n display: block;\n width: 100%;\n "
},
{
"path": "static/vendor/bootstrap/scss/utilities/_flex.scss",
"chars": 2769,
"preview": "// stylelint-disable declaration-no-important\n\n// Flex variation\n//\n// Custom styles for additional flex alignment optio"
},
{
"path": "static/vendor/bootstrap/scss/utilities/_float.scss",
"chars": 376,
"preview": "// stylelint-disable declaration-no-important\n\n@each $breakpoint in map-keys($grid-breakpoints) {\n @include media-break"
},
{
"path": "static/vendor/bootstrap/scss/utilities/_interactions.scss",
"chars": 142,
"preview": "// stylelint-disable declaration-no-important\n\n@each $value in $user-selects {\n .user-select-#{$value} { user-select: $"
},
{
"path": "static/vendor/bootstrap/scss/utilities/_overflow.scss",
"chars": 133,
"preview": "// stylelint-disable declaration-no-important\n\n@each $value in $overflows {\n .overflow-#{$value} { overflow: $value !im"
},
{
"path": "static/vendor/bootstrap/scss/utilities/_position.scss",
"chars": 484,
"preview": "// stylelint-disable declaration-no-important\n\n// Common values\n@each $position in $positions {\n .position-#{$position}"
},
{
"path": "static/vendor/bootstrap/scss/utilities/_screenreaders.scss",
"chars": 115,
"preview": "//\n// Screenreaders\n//\n\n.sr-only {\n @include sr-only();\n}\n\n.sr-only-focusable {\n @include sr-only-focusable();\n}\n"
},
{
"path": "static/vendor/bootstrap/scss/utilities/_shadows.scss",
"chars": 249,
"preview": "// stylelint-disable declaration-no-important\n\n.shadow-sm { box-shadow: $box-shadow-sm !important; }\n.shadow { box-shado"
},
{
"path": "static/vendor/bootstrap/scss/utilities/_sizing.scss",
"chars": 498,
"preview": "// stylelint-disable declaration-no-important\n\n// Width and height\n\n@each $prop, $abbrev in (width: w, height: h) {\n @e"
},
{
"path": "static/vendor/bootstrap/scss/utilities/_spacing.scss",
"chars": 2101,
"preview": "// stylelint-disable declaration-no-important\n\n// Margin and Padding\n\n@each $breakpoint in map-keys($grid-breakpoints) {"
},
{
"path": "static/vendor/bootstrap/scss/utilities/_stretched-link.scss",
"chars": 431,
"preview": "//\n// Stretched link\n//\n\n.stretched-link {\n &::after {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;"
},
{
"path": "static/vendor/bootstrap/scss/utilities/_text.scss",
"chars": 1959,
"preview": "// stylelint-disable declaration-no-important\n\n//\n// Text\n//\n\n.text-monospace { font-family: $font-family-monospace !imp"
},
{
"path": "static/vendor/bootstrap/scss/utilities/_visibility.scss",
"chars": 174,
"preview": "// stylelint-disable declaration-no-important\n\n//\n// Visibility utilities\n//\n\n.visible {\n visibility: visible !importan"
},
{
"path": "static/vendor/bootstrap/scss/vendor/_rfs.scss",
"chars": 6473,
"preview": "// stylelint-disable property-blacklist, scss/dollar-variable-default\n\n// SCSS RFS mixin\n//\n// Automated font-resizing\n/"
},
{
"path": "static/vendor/chart.js/Chart.bundle.js",
"chars": 578945,
"preview": "/*!\n * Chart.js v2.9.3\n * https://www.chartjs.org\n * (c) 2019 Chart.js Contributors\n * Released under the MIT License\n *"
},
{
"path": "static/vendor/chart.js/Chart.js",
"chars": 428067,
"preview": "/*!\n * Chart.js v2.9.3\n * https://www.chartjs.org\n * (c) 2019 Chart.js Contributors\n * Released under the MIT License\n *"
},
{
"path": "static/vendor/css-hamburgers/hamburgers.css",
"chars": 24060,
"preview": "/*!\n * Hamburgers\n * @description Tasty CSS-animated hamburgers\n * @author Jonathan Suh @jonsuh\n * @site https://jonsuh."
},
{
"path": "static/vendor/datatables/dataTables.bootstrap4.css",
"chars": 5994,
"preview": "table.dataTable {\n clear: both;\n margin-top: 6px !important;\n margin-bottom: 6px !important;\n max-width: none !impor"
},
{
"path": "static/vendor/datatables/dataTables.bootstrap4.js",
"chars": 4701,
"preview": "/*! DataTables Bootstrap 4 integration\n * ©2011-2017 SpryMedia Ltd - datatables.net/license\n */\n\n/**\n * DataTables integ"
},
{
"path": "static/vendor/datatables/jquery.dataTables.js",
"chars": 449237,
"preview": "/*! DataTables 1.10.21\n * ©2008-2020 SpryMedia Ltd - datatables.net/license\n */\n\n/**\n * @summary DataTables\n * @desc"
},
{
"path": "static/vendor/fontawesome-free/LICENSE.txt",
"chars": 1548,
"preview": "Font Awesome Free License\n-------------------------\n\nFont Awesome Free is free, open source, and GPL friendly. You can u"
},
{
"path": "static/vendor/fontawesome-free/css/all.css",
"chars": 73117,
"preview": "/*!\n * Font Awesome Free 5.13.1 by @fontawesome - https://fontawesome.com\n * License - https://fontawesome.com/license/f"
}
]
// ... and 82 more files (download for full content)
About this extraction
This page contains the full source code of the Guezone/SECMON GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 282 files (9.1 MB), approximately 2.4M tokens, and a symbol index with 1398 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.