pull/5/head
InfoSec 2018-11-03 10:29:41 +08:00
parent 9de644a985
commit 3966c3efc4
1119 changed files with 169253 additions and 0 deletions

View File

@ -0,0 +1,3 @@
*.js linguist-language=python
*.css linguist-language=python
*.html linguist-language=python

View File

@ -0,0 +1,6 @@
*.pyc
.idea/
tests/
fuxi/views/modules/scanner/pocsuite_plugin/
logs/
instance/

View File

@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View File

@ -0,0 +1,100 @@
# Fuxi-Scanner
[![Travis](https://img.shields.io/badge/Python-2.6%7C2.7-blue.svg)](https://www.python.org/)
[![GitHub license](https://img.shields.io/github/license/jeffzh3ng/Fuxi-Scanner.svg)](https://github.com/jeffzh3ng/Fuxi-Scanner/blob/master/LICENSE)
[![GitHub stars](https://img.shields.io/github/stars/jeffzh3ng/Fuxi-Scanner.svg)](https://github.com/jeffzh3ng/Fuxi-Scanner/stargazers)
### README English | [中文](doc/README.zh.md)
Fuxi Scanner is an open source network security vulnerability scanner, it comes with multiple functions.
- Vulnerability detection & management
- Authentication Tester
- IT asset discovery & management
- Port scanner
- Subdomain scanner
- Acunetix Scanner (Integrate Acunetix API)
## Screenshots
![fuxi_dashboard.png](doc/images/fuxi_dashboard.png)
## Installation
[Documentation](doc/INSTALL.en.md)
## Usage
### Vulnerability Scanner
The scanner module integrate an open-sourced remote vulnerability testing and PoC development framework - [Pocsuite](https://github.com/knownsec/Pocsuite)
Like Metasploit, it is a development kit for pentesters to develope their own exploits. Based on Pocsuite, you can write the most core code of PoC/Exp without caring about the resulting output etc. There are at least several hundred people writing PoC/Exp based on Pocsuite up to date.
You can acquiring PoC scripts from [Seebug community](https://www.seebug.org/)
The target can be IP, network segment or URL.
![fuxi_poc_new_scan.png](doc/images/fuxi_poc_new_scan.png)
You can manage plugins in the Plugin Manager modules. The plugin must conform to the [PoC Coding Style](https://github.com/knownsec/Pocsuite/blob/master/docs/CODING.md)
![fuxi_poc_plugin_management.png](doc/images/fuxi_poc_plugin_management.png)
### Asset Management
IT Asset Registration:
![fuxi_asset_new.png](doc/images/fuxi_asset_new.png)
Automatic Service Discovery:
![fuxi_asset_server_search.png](doc/images/fuxi_asset_service_search.png)
You can scan the vulnerability by searching and filtering out specific services
### Authentication Tester
This is an auth tester with [hydra](https://github.com/vanhauser-thc/thc-hydra)
Currently this tool supports the following protocols: Asterisk, AFP, Cisco AAA, Cisco auth, Cisco enable, CVS, Firebird, FTP, HTTP-FORM-GET, HTTP-FORM-POST, HTTP-GET, HTTP-HEAD, HTTP-POST, HTTP-PROXY, HTTPS-FORM-GET, HTTPS-FORM-POST, HTTPS-GET, HTTPS-HEAD, HTTPS-POST, HTTP-Proxy, ICQ, IMAP, IRC, LDAP, MS-SQL, MYSQL, NCP, NNTP, Oracle Listener, Oracle SID, Oracle, PC-Anywhere, PCNFS, POP3, POSTGRES, RDP, Rexec, Rlogin, Rsh, RTSP, SAP/R3, SIP, SMB, SMTP, SMTP Enum, SNMP v1+v2+v3, SOCKS5, SSH (v1 and v2), SSHKEY, Subversion, Teamspeak (TS2), Telnet, VMware-Auth, VNC and XMPP. (55)
![fuxi_auth_new_scan.png](doc/images/fuxi_auth_new_scan.png)
### Subdomain Scanner
It helps penetration testers and bug hunters collect and gather subdomains for the domain they are targeting
You can improved wordlist in settings for finding more subdomains
![fuxi_domain_new_scan.png](doc/images/fuxi_domain_new_scan.png)
![fuxi_poc_list.png](doc/images/fuxi_domain_list.png)
### Acunetix Scanner
This module delivers scanning tasks by integrate Acunetix Web Vulnerability Scanner API
![fuxi_acunetix_new_scan.png](doc/images/fuxi_acunetix_new_scan.png)
You can scan multiple websites at the same time
### Port Scanner
Port scanner allows you to discover which TCP ports are open on your target host.
Port scanning is usually done in the initial phase of a penetration test in order to discover all network entry points into the target system
![fuxi_port_scanner.png](doc/images/fuxi_port_scanner.png)
### Settings
![fuxi_settings.png](doc/images/fuxi_settings.png)
## Links
- Homepage: [https://fuxi-scanner.com](https://fuxi-scanner.com)
- Download: [.tar](https://github.com/jeffzh3ng/Fuxi-Scanner/tarball/master) or [.zip](https://github.com/jeffzh3ng/Fuxi-Scanner/zipball/master)
- E-mail: [jeffzh3ng@gmail.com](mailto:jeffzh3ng@gmail.com)
- Telegram: [jeffzhang](https://t.me/jeffzhang)

View File

@ -0,0 +1,276 @@
# Installation
You can download the latest tarball by clicking [here](https://github.com/jeffzh3ng/Fuxi-Scanner/tarball/master) or latest zipball by clicking [here](https://github.com/jeffzh3ng/Fuxi-Scanner/zipball/master).
Preferably, you can download fuxi-scanner by cloning the Git repository:
```bash
git clone --depth 1 https://github.com/jeffzh3ng/Fuxi-Scanner.git fuxi-scanner
```
Fuxi Scanner works out of the box with [Python](https://www.python.org/) version 2.6.x and 2.7.x on any platform.
## Environment Setup
This guide should get you going on `Ubuntu` system.
### Install the base dev packages
```bash
sudo apt update
sudo apt install python python-dev python-pip python-setuptools nmap hydra curl
cd fuxi-scanner
sudo python -m pip install pip==9.0.3
sudo pip install -r requirements.txt
```
### Install MongoDB Community Edition (Ubuntu)
#### Import the public key used by the package management system.
The Ubuntu package management tools (i.e. dpkg and apt) ensure package consistency and authenticity by requiring that distributors sign packages with GPG keys.
Issue the following command to import the MongoDB public GPG Key:
```bash
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 2930ADAE8CAF5059EE73BB4B58712A2291FA4AD5
```
#### Create a list file for MongoDB.
Create the /etc/apt/sources.list.d/mongodb-org-3.6.list list file using the command appropriate for your version of Ubuntu:
Ubuntu 14.04
```bash
echo "deb https://repo.mongodb.org/apt/ubuntu trusty/mongodb-org/3.6 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.6.list
```
Ubuntu 16.04
```bash
echo "deb https://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/3.6 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.6.list
```
#### Reload local package database.
Issue the following command to reload the local package database:
```bash
sudo apt-get update
```
#### Install the MongoDB packages.
Install the latest stable version of MongoDB.
Issue the following command:
```bash
sudo apt-get install -y mongodb-org
```
#### Run MongoDB Community Edition
Start MongoDB.
Issue the following command to start mongod:
```bash
sudo service mongod start
```
Connect to the instance.
```bash
mongo
```
Create the user administrator.
In the admin database, add a user with the [userAdminAnyDatabase](https://docs.mongodb.com/manual/reference/built-in-roles/#userAdminAnyDatabase) role
```bash
use admin
db.createUser(
{
user: "admin",
pwd: "14b3xfY1wd",
roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
}
)
```
Add Scanner Users
The following operation creates a user in the reporting database with the specified name, password, and roles
```bash
use fuxi
db.createUser(
{
user: "fuxi_scanner",
pwd: "W94MRYDqOZ",
roles: [
{ role: "readWrite", db: "fuxi"},
]
}
)
```
Enable Auth
```bash
sudo vi /etc/mongod.conf
security:
authorization: "enabled"
```
```bash
sudo service mongod restart
sudo systemctl enable mongod.service
```
To authenticate after connecting
```bash
jeffzhang@ubuntu:~$ mongo
MongoDB shell version v3.6.5
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.6.5
> use fuxi
switched to db fuxi
> db.auth("fuxi_scanner", "W94MRYDqOZ")
1
```
## Configuration Handling
`fuxi-scanner` configuration files are located in the `fuxi-scanner/instance/` directory.
### Full Example Configuration
```python
import os
basedir = os.path.abspath(os.path.dirname(__file__))
class Config:
def __init__(self):
pass
WEB_USER = 'admin' #Web Auth User
WEB_PASSWORD = 'xHmRu4sJxZ' #Web Auth Password
POCSUITE_PATH = basedir + '/../fuxi/views/modules/scanner/pocsuite_plugin/'
AWVS_REPORT_PATH = basedir + '/../fuxi/static/download/' # static file download
WEB_HOST = '127.0.0.1' #Web Server Host
WEB_PORT = 5000 #Web Server Port
UPDATE_URL = "https://fuxi.hook.ga/update" #check update
VERSION = '1.2.0' #scanner version
AWVS_URL = 'https://192.168.56.2:3443' #Acunetix Web Vulnerability Scanner Url
AWVS_API_KEY = "" #Acunetix Web Vulnerability Scanner API Key
class ProductionConfig(Config):
DB_HOST = '127.0.0.1' #MongoDB Host
DB_PORT = 27017 #MongoDB Port (int)
DB_NAME = 'fuxi' #MongoDB Name
DB_USERNAME = 'fuxi_scanner' #MongoDB User
DB_PASSWORD = 'W94MRYDqOZ' #MongoDB Password
CONFIG_NAME = 'fuxi' #Scanner config name
PLUGIN_DB = 'dev_plugin_info' #Plugin collection
TASKS_DB = 'dev_tasks' #Scan tasks collection
VULNERABILITY_DB = 'dev_vuldb' #Vulnerability collection
ASSET_DB = 'dev_asset' #Asset collection
CONFIG_DB = 'dev_config' #Scanner config collection
SERVER_DB = 'dev_server' #Asset server collection
SUBDOMAIN_DB = 'dev_subdomain' #Subdomain server collection
DOMAIN_DB = 'dev_domain' #Domain server collection
PORT_DB = 'dev_port_scanner' #Port scan collection
AUTH_DB = 'dev_auth_tester' #Auth tester tasks collection
ACUNETIX_DB = 'dev_acunetix' #Acunetix scanner tasks collection
WEEKPASSWD_DB = 'dev_week_passwd' #Week password collection
```
## Using Fuxi-Scanner
### Running tests
```bash
sudo service mongod restart
cd fuxi-scanner
python migration/start.py
python fuxi_scanner.py
* Running on http://127.0.0.1:5000
```
Done! Open your browser to `http://127.0.0.1:5000` to see it working
### Run it as background process
```bash
./run.sh start # start
./run.sh restart # restart
./run.sh stop # stop
```
## Using Caddy (Optional)
[Caddy](https://caddyserver.com/), sometimes clarified as the Caddy web server, is an open source, HTTP/2-enabled web server written in Go. It uses the Go standard library for its HTTP functionality.
One of Caddy's most notable features is enabling HTTPS by default.
### Install Caddy
- PLATFORM: Linux 64
- PLUGINS: None
- TELEMETRY: Off
- LICENSE: Personal (free)
```bash
curl https://getcaddy.com | bash -s personal
```
### Using Caddy
[USER GUIDE](https://caddyserver.com/tutorial)
Create caddy folder
```bash
sudo mkdir /etc/caddy
sudo touch /etc/caddy/caddy.config
sudo chown -R root:www-data /etc/caddy
sudo vi /etc/caddy/caddy.config
```
The HTTP Caddyfile
[Caddyfile Syntax](https://caddyserver.com/docs/caddyfile)
```config
www.example.com {
log /var/log/caddy_fuxi.log
proxy / 127.0.0.1:5000 {
transparent
}
}
```
Create SSL certificates folder
```bash
sudo mkdir /etc/ssl/caddy
sudo chown -R www-data:root /etc/ssl/caddy
sudo chmod 0770 /etc/ssl/caddy
```
Start Caddy
```bash
sudo caddy -conf /etc/caddy/caddy.config
```
---- The End ----

View File

@ -0,0 +1,270 @@
# 安装手册
你可以直接下载最新 [tar](https://github.com/jeffzh3ng/Fuxi-Scanner/tarball/master) 或者 [zip](https://github.com/jeffzh3ng/Fuxi-Scanner/zipball/master) 包
也可以通过 `Github` 仓库获取
```bash
git clone --depth 1 https://github.com/jeffzh3ng/Fuxi-Scanner.git fuxi-scanner
```
伏羲依赖于 Python 2.7 or Python 2.6 环境
## 运行环境
安装过程演示环境为 `Ubuntu 16.04` 操作系统,其他 `Linux` 发行版可以参考
### 安装基础依赖包
```bash
sudo apt update
sudo apt install python python-dev python-pip python-setuptools nmap hydra curl
cd fuxi-scanner
sudo python -m pip install pip==9.0.3
sudo pip install -r requirements.txt
```
### 安装 MongoDB 社区版 (Ubuntu)
#### 导入Key
```bash
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 2930ADAE8CAF5059EE73BB4B58712A2291FA4AD5
```
#### 创建源文件
Ubuntu 14.04
```bash
echo "deb https://repo.mongodb.org/apt/ubuntu trusty/mongodb-org/3.6 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.6.list
```
Ubuntu 16.04
```bash
echo "deb https://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/3.6 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.6.list
```
#### 更新软件包列表
```bash
sudo apt-get update
```
#### 安装 MongoDB.
```bash
sudo apt-get install -y mongodb-org
```
#### 运行
Start MongoDB.
```bash
sudo service mongod start
```
连接到数据库
```bash
mongo
```
创建管理员用户
```bash
use admin
db.createUser(
{
user: "admin",
pwd: "14b3xfY1wd",
roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
}
)
```
创建扫描器用户
The following operation creates a user in the reporting database with the specified name, password, and roles
```bash
use fuxi
db.createUser(
{
user: "fuxi_scanner",
pwd: "W94MRYDqOZ",
roles: [
{ role: "readWrite", db: "fuxi"},
]
}
)
```
开启认证
```bash
sudo vi /etc/mongod.conf
```
增加以下配置
```bash
security:
authorization: "enabled"
```
重启数据库服务,设置开机启动
```bash
sudo service mongod restart
sudo systemctl enable mongod.service
```
测试认证连接
```bash
jeffzhang@ubuntu:~$ mongo
MongoDB shell version v3.6.5
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.6.5
> use fuxi
switched to db fuxi
> db.auth("fuxi_scanner", "W94MRYDqOZ")
1
```
返回`1`代表用户认证成功
## 扫描器配置
`fuxi-scanner` configuration files are located in the `fuxi-scanner/instance/` directory.
### 配置文件解析
```python
import os
basedir = os.path.abspath(os.path.dirname(__file__))
class Config:
def __init__(self):
pass
WEB_USER = 'admin' #Web Auth User
WEB_PASSWORD = 'xHmRu4sJxZ' #Web Auth Password
POCSUITE_PATH = basedir + '/../fuxi/views/modules/scanner/pocsuite_plugin/'
AWVS_REPORT_PATH = basedir + '/../fuxi/static/download/' # static file download
WEB_HOST = '127.0.0.1' #Web Server Host
WEB_PORT = 5000 #Web Server Port
UPDATE_URL = "https://fuxi.hook.ga/update" #check update
VERSION = '1.2.0' #scanner version
AWVS_URL = 'https://192.168.56.2:3443' #Acunetix Web Vulnerability Scanner Url
AWVS_API_KEY = "" #Acunetix Web Vulnerability Scanner API Key
class ProductionConfig(Config):
DB_HOST = '127.0.0.1' #MongoDB Host
DB_PORT = 27017 #MongoDB Port (int)
DB_NAME = 'fuxi' #MongoDB Name
DB_USERNAME = 'fuxi_scanner' #MongoDB User
DB_PASSWORD = 'W94MRYDqOZ' #MongoDB Password
CONFIG_NAME = 'fuxi' #Scanner config name
PLUGIN_DB = 'dev_plugin_info' #Plugin collection
TASKS_DB = 'dev_tasks' #Scan tasks collection
VULNERABILITY_DB = 'dev_vuldb' #Vulnerability collection
ASSET_DB = 'dev_asset' #Asset collection
CONFIG_DB = 'dev_config' #Scanner config collection
SERVER_DB = 'dev_server' #Asset server collection
SUBDOMAIN_DB = 'dev_subdomain' #Subdomain server collection
DOMAIN_DB = 'dev_domain' #Domain server collection
PORT_DB = 'dev_port_scanner' #Port scan collection
AUTH_DB = 'dev_auth_tester' #Auth tester tasks collection
ACUNETIX_DB = 'dev_acunetix' #Acunetix scanner tasks collection
WEEKPASSWD_DB = 'dev_week_passwd' #Week password collection
```
注意修改扫描器web服务监听的IP默认监听本地数据库名称、数据库用户、密码`AWVS` 扫描器路径以及 `API Key`
## 开始使用
### 运行测试
```bash
sudo service mongod restart
cd fuxi-scanner
python migration/start.py
python fuxi_scanner.py
* Running on http://127.0.0.1:5000
```
一定要记得开启数据库,未报错,说明可以正常运行,打开浏览器访问`http://127.0.0.1:5000`
### 后台运行
```bash
./run.sh start # start
./run.sh restart # restart
./run.sh stop # stop
```
## 使用 Caddy 进行代理 (建议)
[Caddy](https://caddyserver.com/) 服务器或稱Caddy Web是一个开源的使用 Golang 编写,支持 HTTP/2 的 Web 服务端。它使用 Golang 标准库提供 HTTP 功能。
Caddy 一个显著的特性是默认启用 HTTPS。它是第一个无需额外配置即可提供 HTTPS 特性的 Web 服务器。
### 安装
- PLATFORM: Linux 64
- PLUGINS: None
- TELEMETRY: Off
- LICENSE: Personal (free)
```bash
curl https://getcaddy.com | bash -s personal
```
### 使用
[Caddy 官方用户手册](https://caddyserver.com/tutorial)
创建 caddy 文件夹
```bash
sudo mkdir /etc/caddy
sudo touch /etc/caddy/caddy.config
sudo chown -R root:www-data /etc/caddy
sudo vi /etc/caddy/caddy.config
```
编写 Caddyfile 配置文件:
[配置文件语法说明](https://caddyserver.com/docs/caddyfile)
```config
www.example.com {
log /var/log/caddy_fuxi.log
proxy / 127.0.0.1:5000 {
transparent
}
}
```
创建 SSL 证书路径
```bash
sudo mkdir /etc/ssl/caddy
sudo chown -R www-data:root /etc/ssl/caddy
sudo chmod 0770 /etc/ssl/caddy
```
开始使用 Caddy
```bash
sudo caddy -conf /etc/caddy/caddy.config
```
---- The End ----

View File

@ -0,0 +1,108 @@
# 伏羲
[![Travis](https://img.shields.io/badge/Python-2.6%7C2.7-blue.svg)](https://www.python.org/)
[![GitHub license](https://img.shields.io/github/license/jeffzh3ng/Fuxi-Scanner.svg)](https://github.com/jeffzh3ng/Fuxi-Scanner/blob/master/LICENSE)
[![GitHub stars](https://img.shields.io/github/stars/jeffzh3ng/Fuxi-Scanner.svg)](https://github.com/jeffzh3ng/Fuxi-Scanner/stargazers)
### README [English](../README.md) | 中文
伏羲是一款开源的网络安全检测工具,适用于中小型企业对企业信息系统进行安全巡航检测
本系统通过模块化提供多种安全功能
- 基于插件的漏洞扫描功能
- 持续化漏洞管理
- 多种协议的弱口令检测
- 企业子域名收集
- 企业 IT 资产管理及服务发现
- 端口扫描
- AWVS(Acunetix Web Vulnerability Scanner) 接口调用
其他功能敬请期待...
## 截图
![fuxi_dashboard.png](images/fuxi_dashboard.png)
## 安装
[安装手册](INSTALL.zh.md)
## 使用
### 漏洞扫描功能
该模块主要设计初衷是为了对互联网新爆发的安全漏洞进行快速响应及风险排查,以及对已发现的漏洞修复情况进行追踪,该模块可以和资产服务发现模块结合使用,进行快速应急响应
该模块通过调用知道创宇开源扫描器 Pocsuite 进行扫描,具备编码能力的可以根据模版快速开发插件,不具备插件编写能力的可以通过[SeeBug 社区](https://www.seebug.org/)获取
本项目不提供漏洞插件,互联网上有项目提供了很多的 Pocsuite 插件可以在Github上进行搜索建议不要执着于插件数量不要当成漏扫使用哦
扫描任务周期可以选择单次、每日、周及每月,扫描对象可以是单个 IP、网段或者 Url
![fuxi_poc_new_scan.png](images/fuxi_poc_new_scan.png)
扫描插件通过插件模块中新增插件进行上传,插件必须符合 [PoC 编写规范及要求说明](https://github.com/knownsec/Pocsuite/blob/master/docs/CODING.md)
![fuxi_poc_plugin_management.png](images/fuxi_poc_plugin_management.png)
### 资产管理功能
该模块具备资产管理,资产服务发现功能
企业安全人员可以根据信息系统对IT资产进行划分创建不同的资产库通过资产库可以灵活的创建扫描漏洞任务
![fuxi_asset_new.png](images/fuxi_asset_new.png)
资产服务发现模块通过调用 `Nmap` 对资产库主机进行端口扫描,并将结果入库,企业安全人员可以通过关键字搜索功能筛选出符合条件的服务添加到漏洞扫描任务中
![fuxi_asset_server_search.png](images/fuxi_asset_service_search.png)
搜索使用右上角搜索框,不要使用服务列表中的筛选功能
### 认证安全检测
后端调用[hydra](https://github.com/vanhauser-thc/thc-hydra)进行扫描目前支持55种常见协议
Asterisk, AFP, Cisco AAA, Cisco auth, Cisco enable, CVS, Firebird, FTP, HTTP-FORM-GET, HTTP-FORM-POST, HTTP-GET, HTTP-HEAD, HTTP-POST, HTTP-PROXY, HTTPS-FORM-GET, HTTPS-FORM-POST, HTTPS-GET, HTTPS-HEAD, HTTPS-POST, HTTP-Proxy, ICQ, IMAP, IRC, LDAP, MS-SQL, MYSQL, NCP, NNTP, Oracle Listener, Oracle SID, Oracle, PC-Anywhere, PCNFS, POP3, POSTGRES, RDP, Rexec, Rlogin, Rsh, RTSP, SAP/R3, SIP, SMB, SMTP, SMTP Enum, SNMP v1+v2+v3, SOCKS5, SSH (v1 and v2), SSHKEY, Subversion, Teamspeak (TS2), Telnet, VMware-Auth, VNC and XMPP.
扫描任务周期可以选择单次、每日、周及每月,扫描对象可以是单个 IP、网段或者 Url
![fuxi_auth_new_scan.png](images/fuxi_auth_new_scan.png)
该功能采用模块化方式实现,具备开发能力可以自由添加其他协议破解插件,具体实现会在 [WiKi]() 进行公布
### 子域名收集模块
通过基于字典的暴力猜解方式收集企业子域名,可以在系统高级设置配置字典,项目`tests`文件夹下提供了一份域名字典
![fuxi_domain_new_scan.png](images/fuxi_domain_new_scan.png)
![fuxi_poc_list.png](images/fuxi_domain_list.png)
### Acunetix Scanner 接口调用
AWVS 11 不能同时添加多个 URL 地址,该模块通过调用 AWVS 接口进行批量扫描,需在`instance/config.py`配置`AWVS`接口地址及`Key`
![fuxi_acunetix_new_scan.png](images/fuxi_acunetix_new_scan.png)
目前支持任务删除,报告批量下载功能
### 端口扫描
一个端口扫描的辅助功能,用于临时的端口探测,存货主机发现,等等
![fuxi_port_scanner.png](images/fuxi_port_scanner.png)
### 系统设置
各模块扫描线程数,子域名字典配置,端口配置
![fuxi_settings.png](images/fuxi_settings.png)
## 相关链接
- 项目主页: [https://fuxi-scanner.com](https://fuxi-scanner.com)
- 下载: [.tar](https://github.com/jeffzh3ng/Fuxi-Scanner/tarball/master) or [.zip](https://github.com/jeffzh3ng/Fuxi-Scanner/zipball/master)
- 邮箱: [jeffzh3ng@gmail.com](mailto:jeffzh3ng@gmail.com)
- Telegram: [jeffzhang](https://t.me/jeffzhang)

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

View File

@ -0,0 +1,8 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author : jeffzhang
# @Time : 18-5-9
# @File : __init__.py
# @Desc : ""

View File

@ -0,0 +1,42 @@
from flask import Flask, render_template
from string import digits, ascii_lowercase
from random import sample
from fuxi.views.authenticate import login_check, authenticate
from fuxi.views.index import index
from fuxi.views.vul_scanner import vul_scanner
from fuxi.views.asset_management import asset_management
from fuxi.views.plugin_management import plugin_management
from fuxi.views.settings import settings
from fuxi.views.dashboard import dashboard
from fuxi.views.port_scanner import port_scanner
from fuxi.views.subdomain_brute import subdomain_brute
from fuxi.views.acunetix_scanner import acunetix_scanner
from fuxi.views.auth_tester import auth_tester
app = Flask(__name__)
app.config['SECRET_KEY'] = ''.join(sample(digits + ascii_lowercase, 10))
app.register_blueprint(authenticate)
app.register_blueprint(index)
app.register_blueprint(vul_scanner)
app.register_blueprint(asset_management)
app.register_blueprint(plugin_management)
app.register_blueprint(settings)
app.register_blueprint(dashboard)
app.register_blueprint(port_scanner)
app.register_blueprint(subdomain_brute)
app.register_blueprint(acunetix_scanner)
app.register_blueprint(auth_tester)
@app.errorhandler(404)
@login_check
def page_not_fount(e):
return render_template('404.html'), 404
@app.errorhandler(500)
@login_check
def internal_server_error(e):
return render_template('500.html'), 500

View File

@ -0,0 +1,388 @@
/*
* The MIT License
* Copyright (c) 2012 Matias Meno <m@tias.me>
*/
@-webkit-keyframes passing-through {
0% {
opacity: 0;
-webkit-transform: translateY(40px);
-moz-transform: translateY(40px);
-ms-transform: translateY(40px);
-o-transform: translateY(40px);
transform: translateY(40px); }
30%, 70% {
opacity: 1;
-webkit-transform: translateY(0px);
-moz-transform: translateY(0px);
-ms-transform: translateY(0px);
-o-transform: translateY(0px);
transform: translateY(0px); }
100% {
opacity: 0;
-webkit-transform: translateY(-40px);
-moz-transform: translateY(-40px);
-ms-transform: translateY(-40px);
-o-transform: translateY(-40px);
transform: translateY(-40px); } }
@-moz-keyframes passing-through {
0% {
opacity: 0;
-webkit-transform: translateY(40px);
-moz-transform: translateY(40px);
-ms-transform: translateY(40px);
-o-transform: translateY(40px);
transform: translateY(40px); }
30%, 70% {
opacity: 1;
-webkit-transform: translateY(0px);
-moz-transform: translateY(0px);
-ms-transform: translateY(0px);
-o-transform: translateY(0px);
transform: translateY(0px); }
100% {
opacity: 0;
-webkit-transform: translateY(-40px);
-moz-transform: translateY(-40px);
-ms-transform: translateY(-40px);
-o-transform: translateY(-40px);
transform: translateY(-40px); } }
@keyframes passing-through {
0% {
opacity: 0;
-webkit-transform: translateY(40px);
-moz-transform: translateY(40px);
-ms-transform: translateY(40px);
-o-transform: translateY(40px);
transform: translateY(40px); }
30%, 70% {
opacity: 1;
-webkit-transform: translateY(0px);
-moz-transform: translateY(0px);
-ms-transform: translateY(0px);
-o-transform: translateY(0px);
transform: translateY(0px); }
100% {
opacity: 0;
-webkit-transform: translateY(-40px);
-moz-transform: translateY(-40px);
-ms-transform: translateY(-40px);
-o-transform: translateY(-40px);
transform: translateY(-40px); } }
@-webkit-keyframes slide-in {
0% {
opacity: 0;
-webkit-transform: translateY(40px);
-moz-transform: translateY(40px);
-ms-transform: translateY(40px);
-o-transform: translateY(40px);
transform: translateY(40px); }
30% {
opacity: 1;
-webkit-transform: translateY(0px);
-moz-transform: translateY(0px);
-ms-transform: translateY(0px);
-o-transform: translateY(0px);
transform: translateY(0px); } }
@-moz-keyframes slide-in {
0% {
opacity: 0;
-webkit-transform: translateY(40px);
-moz-transform: translateY(40px);
-ms-transform: translateY(40px);
-o-transform: translateY(40px);
transform: translateY(40px); }
30% {
opacity: 1;
-webkit-transform: translateY(0px);
-moz-transform: translateY(0px);
-ms-transform: translateY(0px);
-o-transform: translateY(0px);
transform: translateY(0px); } }
@keyframes slide-in {
0% {
opacity: 0;
-webkit-transform: translateY(40px);
-moz-transform: translateY(40px);
-ms-transform: translateY(40px);
-o-transform: translateY(40px);
transform: translateY(40px); }
30% {
opacity: 1;
-webkit-transform: translateY(0px);
-moz-transform: translateY(0px);
-ms-transform: translateY(0px);
-o-transform: translateY(0px);
transform: translateY(0px); } }
@-webkit-keyframes pulse {
0% {
-webkit-transform: scale(1);
-moz-transform: scale(1);
-ms-transform: scale(1);
-o-transform: scale(1);
transform: scale(1); }
10% {
-webkit-transform: scale(1.1);
-moz-transform: scale(1.1);
-ms-transform: scale(1.1);
-o-transform: scale(1.1);
transform: scale(1.1); }
20% {
-webkit-transform: scale(1);
-moz-transform: scale(1);
-ms-transform: scale(1);
-o-transform: scale(1);
transform: scale(1); } }
@-moz-keyframes pulse {
0% {
-webkit-transform: scale(1);
-moz-transform: scale(1);
-ms-transform: scale(1);
-o-transform: scale(1);
transform: scale(1); }
10% {
-webkit-transform: scale(1.1);
-moz-transform: scale(1.1);
-ms-transform: scale(1.1);
-o-transform: scale(1.1);
transform: scale(1.1); }
20% {
-webkit-transform: scale(1);
-moz-transform: scale(1);
-ms-transform: scale(1);
-o-transform: scale(1);
transform: scale(1); } }
@keyframes pulse {
0% {
-webkit-transform: scale(1);
-moz-transform: scale(1);
-ms-transform: scale(1);
-o-transform: scale(1);
transform: scale(1); }
10% {
-webkit-transform: scale(1.1);
-moz-transform: scale(1.1);
-ms-transform: scale(1.1);
-o-transform: scale(1.1);
transform: scale(1.1); }
20% {
-webkit-transform: scale(1);
-moz-transform: scale(1);
-ms-transform: scale(1);
-o-transform: scale(1);
transform: scale(1); } }
.dropzone, .dropzone * {
box-sizing: border-box; }
.dropzone {
min-height: 150px;
border: 2px solid rgba(0, 0, 0, 0.3);
background: white;
padding: 20px 20px; }
.dropzone.dz-clickable {
cursor: pointer; }
.dropzone.dz-clickable * {
cursor: default; }
.dropzone.dz-clickable .dz-message, .dropzone.dz-clickable .dz-message * {
cursor: pointer; }
.dropzone.dz-started .dz-message {
display: none; }
.dropzone.dz-drag-hover {
border-style: solid; }
.dropzone.dz-drag-hover .dz-message {
opacity: 0.5; }
.dropzone .dz-message {
text-align: center;
margin: 2em 0; }
.dropzone .dz-preview {
position: relative;
display: inline-block;
vertical-align: top;
margin: 16px;
min-height: 100px; }
.dropzone .dz-preview:hover {
z-index: 1000; }
.dropzone .dz-preview:hover .dz-details {
opacity: 1; }
.dropzone .dz-preview.dz-file-preview .dz-image {
border-radius: 20px;
background: #999;
background: linear-gradient(to bottom, #eee, #ddd); }
.dropzone .dz-preview.dz-file-preview .dz-details {
opacity: 1; }
.dropzone .dz-preview.dz-image-preview {
background: white; }
.dropzone .dz-preview.dz-image-preview .dz-details {
-webkit-transition: opacity 0.2s linear;
-moz-transition: opacity 0.2s linear;
-ms-transition: opacity 0.2s linear;
-o-transition: opacity 0.2s linear;
transition: opacity 0.2s linear; }
.dropzone .dz-preview .dz-remove {
font-size: 14px;
text-align: center;
display: block;
cursor: pointer;
border: none; }
.dropzone .dz-preview .dz-remove:hover {
text-decoration: underline; }
.dropzone .dz-preview:hover .dz-details {
opacity: 1; }
.dropzone .dz-preview .dz-details {
z-index: 20;
position: absolute;
top: 0;
left: 0;
opacity: 0;
font-size: 13px;
min-width: 100%;
max-width: 100%;
padding: 2em 1em;
text-align: center;
color: rgba(0, 0, 0, 0.9);
line-height: 150%; }
.dropzone .dz-preview .dz-details .dz-size {
margin-bottom: 1em;
font-size: 16px; }
.dropzone .dz-preview .dz-details .dz-filename {
white-space: nowrap; }
.dropzone .dz-preview .dz-details .dz-filename:hover span {
border: 1px solid rgba(200, 200, 200, 0.8);
background-color: rgba(255, 255, 255, 0.8); }
.dropzone .dz-preview .dz-details .dz-filename:not(:hover) {
overflow: hidden;
text-overflow: ellipsis; }
.dropzone .dz-preview .dz-details .dz-filename:not(:hover) span {
border: 1px solid transparent; }
.dropzone .dz-preview .dz-details .dz-filename span, .dropzone .dz-preview .dz-details .dz-size span {
background-color: rgba(255, 255, 255, 0.4);
padding: 0 0.4em;
border-radius: 3px; }
.dropzone .dz-preview:hover .dz-image img {
-webkit-transform: scale(1.05, 1.05);
-moz-transform: scale(1.05, 1.05);
-ms-transform: scale(1.05, 1.05);
-o-transform: scale(1.05, 1.05);
transform: scale(1.05, 1.05);
-webkit-filter: blur(8px);
filter: blur(8px); }
.dropzone .dz-preview .dz-image {
border-radius: 20px;
overflow: hidden;
width: 120px;
height: 120px;
position: relative;
display: block;
z-index: 10; }
.dropzone .dz-preview .dz-image img {
display: block; }
.dropzone .dz-preview.dz-success .dz-success-mark {
-webkit-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);
-moz-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);
-ms-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);
-o-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);
animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1); }
.dropzone .dz-preview.dz-error .dz-error-mark {
opacity: 1;
-webkit-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);
-moz-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);
-ms-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);
-o-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);
animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1); }
.dropzone .dz-preview .dz-success-mark, .dropzone .dz-preview .dz-error-mark {
pointer-events: none;
opacity: 0;
z-index: 500;
position: absolute;
display: block;
top: 50%;
left: 50%;
margin-left: -27px;
margin-top: -27px; }
.dropzone .dz-preview .dz-success-mark svg, .dropzone .dz-preview .dz-error-mark svg {
display: block;
width: 54px;
height: 54px; }
.dropzone .dz-preview.dz-processing .dz-progress {
opacity: 1;
-webkit-transition: all 0.2s linear;
-moz-transition: all 0.2s linear;
-ms-transition: all 0.2s linear;
-o-transition: all 0.2s linear;
transition: all 0.2s linear; }
.dropzone .dz-preview.dz-complete .dz-progress {
opacity: 0;
-webkit-transition: opacity 0.4s ease-in;
-moz-transition: opacity 0.4s ease-in;
-ms-transition: opacity 0.4s ease-in;
-o-transition: opacity 0.4s ease-in;
transition: opacity 0.4s ease-in; }
.dropzone .dz-preview:not(.dz-processing) .dz-progress {
-webkit-animation: pulse 6s ease infinite;
-moz-animation: pulse 6s ease infinite;
-ms-animation: pulse 6s ease infinite;
-o-animation: pulse 6s ease infinite;
animation: pulse 6s ease infinite; }
.dropzone .dz-preview .dz-progress {
opacity: 1;
z-index: 1000;
pointer-events: none;
position: absolute;
height: 16px;
left: 50%;
top: 50%;
margin-top: -8px;
width: 80px;
margin-left: -40px;
background: rgba(255, 255, 255, 0.9);
-webkit-transform: scale(1);
border-radius: 8px;
overflow: hidden; }
.dropzone .dz-preview .dz-progress .dz-upload {
background: #333;
background: linear-gradient(to bottom, #666, #444);
position: absolute;
top: 0;
left: 0;
bottom: 0;
width: 0;
-webkit-transition: width 300ms ease-in-out;
-moz-transition: width 300ms ease-in-out;
-ms-transition: width 300ms ease-in-out;
-o-transition: width 300ms ease-in-out;
transition: width 300ms ease-in-out; }
.dropzone .dz-preview.dz-error .dz-error-message {
display: block; }
.dropzone .dz-preview.dz-error:hover .dz-error-message {
opacity: 1;
pointer-events: auto; }
.dropzone .dz-preview .dz-error-message {
pointer-events: none;
z-index: 1000;
position: absolute;
display: block;
display: none;
opacity: 0;
-webkit-transition: opacity 0.3s ease;
-moz-transition: opacity 0.3s ease;
-ms-transition: opacity 0.3s ease;
-o-transition: opacity 0.3s ease;
transition: opacity 0.3s ease;
border-radius: 8px;
font-size: 13px;
top: 130px;
left: -10px;
width: 140px;
background: #be2626;
background: linear-gradient(to bottom, #be2626, #a92222);
padding: 0.5em 1.2em;
color: white; }
.dropzone .dz-preview .dz-error-message:after {
content: '';
position: absolute;
top: -6px;
left: 64px;
width: 0;
height: 0;
border-left: 6px solid transparent;
border-right: 6px solid transparent;
border-bottom: 6px solid #be2626; }

View File

@ -0,0 +1,86 @@
/*
* Bootstrap Duallistbox - v3.0.5
* A responsive dual listbox widget optimized for Twitter Bootstrap. It works on all modern browsers and on touch devices.
* http://www.virtuosoft.eu/code/bootstrap-duallistbox/
*
* Made by István Ujj-Mészáros
* Under Apache License v2.0 License
*/
.bootstrap-duallistbox-container .buttons {
width: 100%;
margin-bottom: -1px;
}
.bootstrap-duallistbox-container label {
display: block;
}
.bootstrap-duallistbox-container .info {
display: inline-block;
margin-bottom: 5px;
font-size: 11px;
}
.bootstrap-duallistbox-container .clear1,
.bootstrap-duallistbox-container .clear2 {
display: none;
font-size: 10px;
}
.bootstrap-duallistbox-container .box1.filtered .clear1,
.bootstrap-duallistbox-container .box2.filtered .clear2 {
display: inline-block;
}
.bootstrap-duallistbox-container .move,
.bootstrap-duallistbox-container .remove {
width: 60%;
}
.bootstrap-duallistbox-container .btn-group .btn {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
.bootstrap-duallistbox-container select {
border-top-left-radius: 0;
border-top-right-radius: 0;
}
.bootstrap-duallistbox-container .moveall,
.bootstrap-duallistbox-container .removeall {
width: 40%;
}
.bootstrap-duallistbox-container.bs2compatible .btn-group > .btn + .btn {
margin-left: 0;
}
.bootstrap-duallistbox-container select {
width: 100%;
height: 300px;
padding: 0;
}
.bootstrap-duallistbox-container .filter {
display: inline-block;
width: 100%;
height: 31px;
margin: 0 0 5px 0;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.bootstrap-duallistbox-container .filter.placeholder {
color: #aaa;
}
.bootstrap-duallistbox-container.moveonselect .move,
.bootstrap-duallistbox-container.moveonselect .remove {
display:none;
}
.bootstrap-duallistbox-container.moveonselect .moveall,
.bootstrap-duallistbox-container.moveonselect .removeall {
width: 100%;
}

View File

@ -0,0 +1 @@
.multiselect-container{position:absolute;list-style-type:none;margin:0;padding:0}.multiselect-container .input-group{margin:5px}.multiselect-container>li{padding:0}.multiselect-container>li>a.multiselect-all label{font-weight:700}.multiselect-container>li.multiselect-group label{margin:0;padding:3px 20px 3px 20px;height:100%;font-weight:700}.multiselect-container>li.multiselect-group-clickable label{cursor:pointer}.multiselect-container>li>a{padding:0}.multiselect-container>li>a>label{margin:0;height:100%;cursor:pointer;font-weight:400;padding:3px 20px 3px 40px}.multiselect-container>li>a>label.radio,.multiselect-container>li>a>label.checkbox{margin:0}.multiselect-container>li>a>label>input[type=checkbox]{margin-bottom:5px}.btn-group>.btn-group:nth-child(2)>.multiselect.btn{border-top-left-radius:4px;border-bottom-left-radius:4px}.form-inline .multiselect-container label.checkbox,.form-inline .multiselect-container label.radio{padding:3px 20px 3px 40px}.form-inline .multiselect-container li a label.checkbox input[type=checkbox],.form-inline .multiselect-container li a label.radio input[type=radio]{margin-left:-20px;margin-right:0}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,720 @@
/*
* Bootstrap Duallistbox - v3.0.5
* A responsive dual listbox widget optimized for Twitter Bootstrap. It works on all modern browsers and on touch devices.
* http://www.virtuosoft.eu/code/bootstrap-duallistbox/
*
* Made by István Ujj-Mészáros
* Under Apache License v2.0 License
*/
;(function ($, window, document, undefined) {
// Create the defaults once
var pluginName = 'bootstrapDualListbox',
defaults = {
bootstrap2Compatible: false,
filterTextClear: 'show all',
filterPlaceHolder: 'Filter',
moveSelectedLabel: 'Move selected',
moveAllLabel: 'Move all',
removeSelectedLabel: 'Remove selected',
removeAllLabel: 'Remove all',
moveOnSelect: true, // true/false (forced true on androids, see the comment later)
preserveSelectionOnMove: false, // 'all' / 'moved' / false
selectedListLabel: false, // 'string', false
nonSelectedListLabel: false, // 'string', false
helperSelectNamePostfix: '_helper', // 'string_of_postfix' / false
selectorMinimalHeight: 100,
showFilterInputs: true, // whether to show filter inputs
nonSelectedFilter: '', // string, filter the non selected options
selectedFilter: '', // string, filter the selected options
infoText: 'Showing all {0}', // text when all options are visible / false for no info text
infoTextFiltered: '<span class="label label-warning">Filtered</span> {0} from {1}', // when not all of the options are visible due to the filter
infoTextEmpty: 'Empty list', // when there are no options present in the list
filterOnValues: false // filter by selector's values, boolean
, buttonClass: 'btn-white btn-bold'//ACE
},
// Selections are invisible on android if the containing select is styled with CSS
// http://code.google.com/p/android/issues/detail?id=16922
isBuggyAndroid = /android/i.test(navigator.userAgent.toLowerCase());
// The actual plugin constructor
function BootstrapDualListbox(element, options) {
this.element = $(element);
// jQuery has an extend method which merges the contents of two or
// more objects, storing the result in the first object. The first object
// is generally empty as we don't want to alter the default options for
// future instances of the plugin
this.settings = $.extend({}, defaults, options);
this._defaults = defaults;
this._name = pluginName;
this.init();
}
function triggerChangeEvent(dualListbox) {
dualListbox.element.trigger('change');
}
function updateSelectionStates(dualListbox) {
dualListbox.element.find('option').each(function(index, item) {
var $item = $(item);
if (typeof($item.data('original-index')) === 'undefined') {
$item.data('original-index', dualListbox.elementCount++);
}
if (typeof($item.data('_selected')) === 'undefined') {
$item.data('_selected', false);
}
});
}
function changeSelectionState(dualListbox, original_index, selected) {
dualListbox.element.find('option').each(function(index, item) {
var $item = $(item);
if ($item.data('original-index') === original_index) {
$item.prop('selected', selected);
}
});
}
function formatString(s, args) {
return s.replace(/\{(\d+)\}/g, function(match, number) {
return typeof args[number] !== 'undefined' ? args[number] : match;
});
}
function refreshInfo(dualListbox) {
if (!dualListbox.settings.infoText) {
return;
}
var visible1 = dualListbox.elements.select1.find('option').length,
visible2 = dualListbox.elements.select2.find('option').length,
all1 = dualListbox.element.find('option').length - dualListbox.selectedElements,
all2 = dualListbox.selectedElements,
content = '';
if (all1 === 0) {
content = dualListbox.settings.infoTextEmpty;
} else if (visible1 === all1) {
content = formatString(dualListbox.settings.infoText, [visible1, all1]);
} else {
content = formatString(dualListbox.settings.infoTextFiltered, [visible1, all1]);
}
dualListbox.elements.info1.html(content);
dualListbox.elements.box1.toggleClass('filtered', !(visible1 === all1 || all1 === 0));
if (all2 === 0) {
content = dualListbox.settings.infoTextEmpty;
} else if (visible2 === all2) {
content = formatString(dualListbox.settings.infoText, [visible2, all2]);
} else {
content = formatString(dualListbox.settings.infoTextFiltered, [visible2, all2]);
}
dualListbox.elements.info2.html(content);
dualListbox.elements.box2.toggleClass('filtered', !(visible2 === all2 || all2 === 0));
}
function refreshSelects(dualListbox) {
dualListbox.selectedElements = 0;
dualListbox.elements.select1.empty();
dualListbox.elements.select2.empty();
dualListbox.element.find('option').each(function(index, item) {
var $item = $(item);
if ($item.prop('selected')) {
dualListbox.selectedElements++;
dualListbox.elements.select2.append($item.clone(true).prop('selected', $item.data('_selected')));
} else {
dualListbox.elements.select1.append($item.clone(true).prop('selected', $item.data('_selected')));
}
});
if (dualListbox.settings.showFilterInputs) {
filter(dualListbox, 1);
filter(dualListbox, 2);
}
refreshInfo(dualListbox);
}
function filter(dualListbox, selectIndex) {
if (!dualListbox.settings.showFilterInputs) {
return;
}
saveSelections(dualListbox, selectIndex);
dualListbox.elements['select'+selectIndex].empty().scrollTop(0);
var regex = new RegExp($.trim(dualListbox.elements['filterInput'+selectIndex].val()), 'gi'),
allOptions = dualListbox.element.find('option'),
options = dualListbox.element;
if (selectIndex === 1) {
options = allOptions.not(':selected');
} else {
options = options.find('option:selected');
}
options.each(function(index, item) {
var $item = $(item),
isFiltered = true;
if (item.text.match(regex) || (dualListbox.settings.filterOnValues && $item.attr('value').match(regex) ) ) {
isFiltered = false;
dualListbox.elements['select'+selectIndex].append($item.clone(true).prop('selected', $item.data('_selected')));
}
allOptions.eq($item.data('original-index')).data('filtered'+selectIndex, isFiltered);
});
refreshInfo(dualListbox);
}
function saveSelections(dualListbox, selectIndex) {
var options = dualListbox.element.find('option');
dualListbox.elements['select'+selectIndex].find('option').each(function(index, item) {
var $item = $(item);
options.eq($item.data('original-index')).data('_selected', $item.prop('selected'));
});
}
function sortOptions(select) {
select.find('option').sort(function(a, b) {
return ($(a).data('original-index') > $(b).data('original-index')) ? 1 : -1;
}).appendTo(select);
}
function clearSelections(dualListbox) {
dualListbox.elements.select1.find('option').each(function() {
dualListbox.element.find('option').data('_selected', false);
});
}
function move(dualListbox) {
if (dualListbox.settings.preserveSelectionOnMove === 'all' && !dualListbox.settings.moveOnSelect) {
saveSelections(dualListbox, 1);
saveSelections(dualListbox, 2);
} else if (dualListbox.settings.preserveSelectionOnMove === 'moved' && !dualListbox.settings.moveOnSelect) {
saveSelections(dualListbox, 1);
}
dualListbox.elements.select1.find('option:selected').each(function(index, item) {
var $item = $(item);
if (!$item.data('filtered1')) {
changeSelectionState(dualListbox, $item.data('original-index'), true);
}
});
refreshSelects(dualListbox);
triggerChangeEvent(dualListbox);
sortOptions(dualListbox.elements.select2);
}
function remove(dualListbox) {
if (dualListbox.settings.preserveSelectionOnMove === 'all' && !dualListbox.settings.moveOnSelect) {
saveSelections(dualListbox, 1);
saveSelections(dualListbox, 2);
} else if (dualListbox.settings.preserveSelectionOnMove === 'moved' && !dualListbox.settings.moveOnSelect) {
saveSelections(dualListbox, 2);
}
dualListbox.elements.select2.find('option:selected').each(function(index, item) {
var $item = $(item);
if (!$item.data('filtered2')) {
changeSelectionState(dualListbox, $item.data('original-index'), false);
}
});
refreshSelects(dualListbox);
triggerChangeEvent(dualListbox);
sortOptions(dualListbox.elements.select1);
}
function moveAll(dualListbox) {
if (dualListbox.settings.preserveSelectionOnMove === 'all' && !dualListbox.settings.moveOnSelect) {
saveSelections(dualListbox, 1);
saveSelections(dualListbox, 2);
} else if (dualListbox.settings.preserveSelectionOnMove === 'moved' && !dualListbox.settings.moveOnSelect) {
saveSelections(dualListbox, 1);
}
dualListbox.element.find('option').each(function(index, item) {
var $item = $(item);
if (!$item.data('filtered1')) {
$item.prop('selected', true);
}
});
refreshSelects(dualListbox);
triggerChangeEvent(dualListbox);
}
function removeAll(dualListbox) {
if (dualListbox.settings.preserveSelectionOnMove === 'all' && !dualListbox.settings.moveOnSelect) {
saveSelections(dualListbox, 1);
saveSelections(dualListbox, 2);
} else if (dualListbox.settings.preserveSelectionOnMove === 'moved' && !dualListbox.settings.moveOnSelect) {
saveSelections(dualListbox, 2);
}
dualListbox.element.find('option').each(function(index, item) {
var $item = $(item);
if (!$item.data('filtered2')) {
$item.prop('selected', false);
}
});
refreshSelects(dualListbox);
triggerChangeEvent(dualListbox);
}
function bindEvents(dualListbox) {
dualListbox.elements.form.submit(function(e) {
if (dualListbox.elements.filterInput1.is(':focus')) {
e.preventDefault();
dualListbox.elements.filterInput1.focusout();
} else if (dualListbox.elements.filterInput2.is(':focus')) {
e.preventDefault();
dualListbox.elements.filterInput2.focusout();
}
});
dualListbox.element.on('bootstrapDualListbox.refresh', function(e, mustClearSelections){
dualListbox.refresh(mustClearSelections);
});
dualListbox.elements.filterClear1.on('click', function() {
dualListbox.setNonSelectedFilter('', true);
});
dualListbox.elements.filterClear2.on('click', function() {
dualListbox.setSelectedFilter('', true);
});
dualListbox.elements.moveButton.on('click', function() {
move(dualListbox);
});
dualListbox.elements.moveAllButton.on('click', function() {
moveAll(dualListbox);
});
dualListbox.elements.removeButton.on('click', function() {
remove(dualListbox);
});
dualListbox.elements.removeAllButton.on('click', function() {
removeAll(dualListbox);
});
dualListbox.elements.filterInput1.on('change keyup', function() {
filter(dualListbox, 1);
});
dualListbox.elements.filterInput2.on('change keyup', function() {
filter(dualListbox, 2);
});
}
BootstrapDualListbox.prototype = {
init: function () {
// Add the custom HTML template
this.container = $('' +
'<div class="bootstrap-duallistbox-container">' +
' <div class="box1">' +
' <label></label>' +
' <span class="info-container">' +
' <span class="info"></span>' +
' <button type="button" class="btn clear1 pull-right"></button>' +
' </span>' +
' <input class="filter" type="text">' +
' <div class="btn-group buttons">' +
' <button type="button" class="btn moveall">' +
' <i></i>' +
' <i></i>' +
' </button>' +
' <button type="button" class="btn move">' +
' <i></i>' +
' </button>' +
' </div>' +
' <select multiple="multiple"></select>' +
' </div>' +
' <div class="box2">' +
' <label></label>' +
' <span class="info-container">' +
' <span class="info"></span>' +
' <button type="button" class="btn clear2 pull-right"></button>' +
' </span>' +
' <input class="filter" type="text">' +
' <div class="btn-group buttons">' +
' <button type="button" class="btn remove">' +
' <i></i>' +
' </button>' +
' <button type="button" class="btn removeall">' +
' <i></i>' +
' <i></i>' +
' </button>' +
' </div>' +
' <select multiple="multiple"></select>' +
' </div>' +
'</div>')
.insertBefore(this.element);
// Cache the inner elements
this.elements = {
originalSelect: this.element,
box1: $('.box1', this.container),
box2: $('.box2', this.container),
filterInput1: $('.box1 .filter', this.container),
filterInput2: $('.box2 .filter', this.container),
filterClear1: $('.box1 .clear1', this.container),
filterClear2: $('.box2 .clear2', this.container),
label1: $('.box1 > label', this.container),
label2: $('.box2 > label', this.container),
info1: $('.box1 .info', this.container),
info2: $('.box2 .info', this.container),
select1: $('.box1 select', this.container),
select2: $('.box2 select', this.container),
moveButton: $('.box1 .move', this.container),
removeButton: $('.box2 .remove', this.container),
moveAllButton: $('.box1 .moveall', this.container),
removeAllButton: $('.box2 .removeall', this.container),
form: $($('.box1 .filter', this.container)[0].form)
};
// Set select IDs
this.originalSelectName = this.element.attr('name') || '';
var select1Id = 'bootstrap-duallistbox-nonselected-list_' + this.originalSelectName,
select2Id = 'bootstrap-duallistbox-selected-list_' + this.originalSelectName;
this.elements.select1.attr('id', select1Id);
this.elements.select2.attr('id', select2Id);
this.elements.label1.attr('for', select1Id);
this.elements.label2.attr('for', select2Id);
// Apply all settings
this.selectedElements = 0;
this.elementCount = 0;
this.setBootstrap2Compatible(this.settings.bootstrap2Compatible);
this.setFilterTextClear(this.settings.filterTextClear);
this.setFilterPlaceHolder(this.settings.filterPlaceHolder);
this.setMoveSelectedLabel(this.settings.moveSelectedLabel);
this.setMoveAllLabel(this.settings.moveAllLabel);
this.setRemoveSelectedLabel(this.settings.removeSelectedLabel);
this.setRemoveAllLabel(this.settings.removeAllLabel);
this.setMoveOnSelect(this.settings.moveOnSelect);
this.setPreserveSelectionOnMove(this.settings.preserveSelectionOnMove);
this.setSelectedListLabel(this.settings.selectedListLabel);
this.setNonSelectedListLabel(this.settings.nonSelectedListLabel);
this.setHelperSelectNamePostfix(this.settings.helperSelectNamePostfix);
this.setSelectOrMinimalHeight(this.settings.selectorMinimalHeight);
updateSelectionStates(this);
this.setShowFilterInputs(this.settings.showFilterInputs);
this.setNonSelectedFilter(this.settings.nonSelectedFilter);
this.setSelectedFilter(this.settings.selectedFilter);
this.setInfoText(this.settings.infoText);
this.setInfoTextFiltered(this.settings.infoTextFiltered);
this.setInfoTextEmpty(this.settings.infoTextEmpty);
this.setFilterOnValues(this.settings.filterOnValues);
// Hide the original select
this.element.hide();
bindEvents(this);
refreshSelects(this);
return this.element;
},
setBootstrap2Compatible: function(value, refresh) {
this.settings.bootstrap2Compatible = value;
if (value) {
this.container.removeClass('row').addClass('row-fluid bs2compatible');
this.container.find('.box1, .box2').removeClass('col-md-6').addClass('span6');
this.container.find('.clear1, .clear2').removeClass('btn-default btn-xs').addClass('btn-mini');
this.container.find('input, select').removeClass('form-control');
this.container.find('.btn').removeClass('btn-default');
this.container.find('.moveall > i, .move > i').removeClass('fa fa-arrow-right').addClass('icon-arrow-right');//ACE
this.container.find('.removeall > i, .remove > i').removeClass('fa fa-arrow-left').addClass('icon-arrow-left');//ACE
} else {
this.container.removeClass('row-fluid bs2compatible').addClass('row');
this.container.find('.box1, .box2').removeClass('span6').addClass('col-md-6');
this.container.find('.clear1, .clear2').removeClass('btn-mini').addClass('btn-default btn-xs');
this.container.find('input, select').addClass('form-control');
this.container.find('.btn').addClass(this.settings.buttonClass)//ACE;//s.addClass('btn-default');
this.container.find('.moveall > i, .move > i').removeClass('icon-arrow-right').addClass('fa fa-arrow-right');//ACE
this.container.find('.removeall > i, .remove > i').removeClass('icon-arrow-left').addClass('fa fa-arrow-left');//ACE
}
if (refresh) {
refreshSelects(this);
}
return this.element;
},
setFilterTextClear: function(value, refresh) {
this.settings.filterTextClear = value;
this.elements.filterClear1.html(value);
this.elements.filterClear2.html(value);
if (refresh) {
refreshSelects(this);
}
return this.element;
},
setFilterPlaceHolder: function(value, refresh) {
this.settings.filterPlaceHolder = value;
this.elements.filterInput1.attr('placeholder', value);
this.elements.filterInput2.attr('placeholder', value);
if (refresh) {
refreshSelects(this);
}
return this.element;
},
setMoveSelectedLabel: function(value, refresh) {
this.settings.moveSelectedLabel = value;
this.elements.moveButton.attr('title', value);
if (refresh) {
refreshSelects(this);
}
return this.element;
},
setMoveAllLabel: function(value, refresh) {
this.settings.moveAllLabel = value;
this.elements.moveAllButton.attr('title', value);
if (refresh) {
refreshSelects(this);
}
return this.element;
},
setRemoveSelectedLabel: function(value, refresh) {
this.settings.removeSelectedLabel = value;
this.elements.removeButton.attr('title', value);
if (refresh) {
refreshSelects(this);
}
return this.element;
},
setRemoveAllLabel: function(value, refresh) {
this.settings.removeAllLabel = value;
this.elements.removeAllButton.attr('title', value);
if (refresh) {
refreshSelects(this);
}
return this.element;
},
setMoveOnSelect: function(value, refresh) {
if (isBuggyAndroid) {
value = true;
}
this.settings.moveOnSelect = value;
if (this.settings.moveOnSelect) {
this.container.addClass('moveonselect');
var self = this;
this.elements.select1.on('change', function() {
move(self);
});
this.elements.select2.on('change', function() {
remove(self);
});
} else {
this.container.removeClass('moveonselect');
this.elements.select1.off('change');
this.elements.select2.off('change');
}
if (refresh) {
refreshSelects(this);
}
return this.element;
},
setPreserveSelectionOnMove: function(value, refresh) {
// We are forcing to move on select and disabling preserveSelectionOnMove on Android
if (isBuggyAndroid) {
value = false;
}
this.settings.preserveSelectionOnMove = value;
if (refresh) {
refreshSelects(this);
}
return this.element;
},
setSelectedListLabel: function(value, refresh) {
this.settings.selectedListLabel = value;
if (value) {
this.elements.label2.show().html(value);
} else {
this.elements.label2.hide().html(value);
}
if (refresh) {
refreshSelects(this);
}
return this.element;
},
setNonSelectedListLabel: function(value, refresh) {
this.settings.nonSelectedListLabel = value;
if (value) {
this.elements.label1.show().html(value);
} else {
this.elements.label1.hide().html(value);
}
if (refresh) {
refreshSelects(this);
}
return this.element;
},
setHelperSelectNamePostfix: function(value, refresh) {
this.settings.helperSelectNamePostfix = value;
if (value) {
this.elements.select1.attr('name', this.originalSelectName + value + '1');
this.elements.select2.attr('name', this.originalSelectName + value + '2');
} else {
this.elements.select1.removeAttr('name');
this.elements.select2.removeAttr('name');
}
if (refresh) {
refreshSelects(this);
}
return this.element;
},
setSelectOrMinimalHeight: function(value, refresh) {
this.settings.selectorMinimalHeight = value;
var height = this.element.height();
if (this.element.height() < value) {
height = value;
}
this.elements.select1.height(height);
this.elements.select2.height(height);
if (refresh) {
refreshSelects(this);
}
return this.element;
},
setShowFilterInputs: function(value, refresh) {
if (!value) {
this.setNonSelectedFilter('');
this.setSelectedFilter('');
refreshSelects(this);
this.elements.filterInput1.hide();
this.elements.filterInput2.hide();
} else {
this.elements.filterInput1.show();
this.elements.filterInput2.show();
}
this.settings.showFilterInputs = value;
if (refresh) {
refreshSelects(this);
}
return this.element;
},
setNonSelectedFilter: function(value, refresh) {
if (this.settings.showFilterInputs) {
this.settings.nonSelectedFilter = value;
this.elements.filterInput1.val(value);
if (refresh) {
refreshSelects(this);
}
return this.element;
}
},
setSelectedFilter: function(value, refresh) {
if (this.settings.showFilterInputs) {
this.settings.selectedFilter = value;
this.elements.filterInput2.val(value);
if (refresh) {
refreshSelects(this);
}
return this.element;
}
},
setInfoText: function(value, refresh) {
this.settings.infoText = value;
if (refresh) {
refreshSelects(this);
}
return this.element;
},
setInfoTextFiltered: function(value, refresh) {
this.settings.infoTextFiltered = value;
if (refresh) {
refreshSelects(this);
}
return this.element;
},
setInfoTextEmpty: function(value, refresh) {
this.settings.infoTextEmpty = value;
if (refresh) {
refreshSelects(this);
}
return this.element;
},
setFilterOnValues: function(value, refresh) {
this.settings.filterOnValues = value;
if (refresh) {
refreshSelects(this);
}
return this.element;
},
getContainer: function() {
return this.container;
},
refresh: function(mustClearSelections) {
updateSelectionStates(this);
if (!mustClearSelections) {
saveSelections(this, 1);
saveSelections(this, 2);
} else {
clearSelections(this);
}
refreshSelects(this);
},
destroy: function() {
this.container.remove();
this.element.show();
$.data(this, 'plugin_' + pluginName, null);
return this.element;
}
};
// A really lightweight plugin wrapper around the constructor,
// preventing against multiple instantiations
$.fn[ pluginName ] = function (options) {
var args = arguments;
// Is the first parameter an object (options), or was omitted, instantiate a new instance of the plugin.
if (options === undefined || typeof options === 'object') {
return this.each(function () {
// If this is not a select
if (!$(this).is('select')) {
$(this).find('select').each(function(index, item) {
// For each nested select, instantiate the Dual List Box
$(item).bootstrapDualListbox(options);
});
} else if (!$.data(this, 'plugin_' + pluginName)) {
// Only allow the plugin to be instantiated once so we check that the element has no plugin instantiation yet
// if it has no instance, create a new one, pass options to our plugin constructor,
// and store the plugin instance in the elements jQuery data object.
$.data(this, 'plugin_' + pluginName, new BootstrapDualListbox(this, options));
}
});
// If the first parameter is a string and it doesn't start with an underscore or "contains" the `init`-function,
// treat this as a call to a public method.
} else if (typeof options === 'string' && options[0] !== '_' && options !== 'init') {
// Cache the method call to make it possible to return a value
var returns;
this.each(function () {
var instance = $.data(this, 'plugin_' + pluginName);
// Tests that there's already a plugin-instance and checks that the requested public method exists
if (instance instanceof BootstrapDualListbox && typeof instance[options] === 'function') {
// Call the method of our plugin instance, and pass it the supplied arguments.
returns = instance[options].apply(instance, Array.prototype.slice.call(args, 1));
}
});
// If the earlier cached method gives a value back return the value,
// otherwise return this to preserve chainability.
return returns !== undefined ? returns : this;
}
};
})(jQuery, window, document);

View File

@ -0,0 +1,27 @@
(function () {
"use strict";
var treeviewMenu = $('.app-menu');
// Toggle Sidebar
$('[data-toggle="sidebar"]').click(function(event) {
event.preventDefault();
$('.app').toggleClass('sidenav-toggled');
});
// Activate sidebar treeview toggle
$("[data-toggle='treeview']").click(function(event) {
event.preventDefault();
if(!$(this).parent().hasClass('is-expanded')) {
treeviewMenu.find("[data-toggle='treeview']").parent().removeClass('is-expanded');
}
$(this).parent().toggleClass('is-expanded');
});
// Set initial active toggle
$("[data-toggle='treeview.'].is-expanded").parent().toggleClass('is-expanded');
//Activate bootstrip tooltips
$("[data-toggle='tooltip']").tooltip();
})();

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,67 @@
/*
* FeedEk jQuery RSS/ATOM Feed Plugin v3.0 with YQL API
* http://jquery-plugins.net/FeedEk/FeedEk.html https://github.com/enginkizil/FeedEk
* Author : Engin KIZIL http://www.enginkizil.com
*/
(function ($) {
$.fn.FeedEk = function (opt) {
var def = $.extend({
MaxCount: 5,
ShowDesc: true,
ShowPubDate: true,
DescCharacterLimit: 0,
TitleLinkTarget: "_blank",
DateFormat: "",
DateFormatLang:"en"
}, opt);
var id = $(this).attr("id"), i, s = "", dt;
$("#" + id).empty();
if (def.FeedUrl == undefined) return;
var YQLstr = 'SELECT channel.item FROM feednormalizer WHERE output="rss_2.0" AND url ="' + def.FeedUrl + '" LIMIT ' + def.MaxCount;
$.ajax({
url: "https://query.yahooapis.com/v1/public/yql?q=" + encodeURIComponent(YQLstr) + "&format=json&diagnostics=false&callback=?",
dataType: "json",
success: function (data) {
$("#" + id).empty();
if (!(data.query.results.rss instanceof Array)) {
data.query.results.rss = [data.query.results.rss];
}
$.each(data.query.results.rss, function (e, itm) {
s += '<li class="light-green"><div style="line-height:25px"><a href="' + itm.channel.item.link + '" target="' + def.TitleLinkTarget + '" >' + itm.channel.item.title + '</a></div>';
if (def.ShowPubDate){
dt = new Date(itm.channel.item.pubDate);
s += '<div>';
if ($.trim(def.DateFormat).length > 0) {
try {
moment.lang(def.DateFormatLang);
s += moment(dt).format(def.DateFormat);
}
catch (e){s += dt.toLocaleDateString();}
}
else {
s += dt.toLocaleDateString();
}
s += '</div>';
}
if (def.ShowDesc) {
s += '<div>';
if (def.DescCharacterLimit > 0 && itm.channel.item.description.length > def.DescCharacterLimit) {
s += itm.channel.item.description.substring(0, def.DescCharacterLimit) + '...';
}
else {
s += itm.channel.item.description;
}
s += '</div>';
}
});
$("#" + id).append('<ul>' + s + '</ul>');
}
});
};
})(jQuery);

View File

@ -0,0 +1,8 @@
/*!
DataTables Bootstrap 3 integration
©2011-2015 SpryMedia Ltd - datatables.net/license
*/
(function(b){"function"===typeof define&&define.amd?define(["jquery","datatables.net"],function(a){return b(a,window,document)}):"object"===typeof exports?module.exports=function(a,d){a||(a=window);if(!d||!d.fn.dataTable)d=require("datatables.net")(a,d).$;return b(d,a,a.document)}:b(jQuery,window,document)})(function(b,a,d,m){var f=b.fn.dataTable;b.extend(!0,f.defaults,{dom:"<'row'<'col-sm-12 col-md-6'l><'col-sm-12 col-md-6'f>><'row'<'col-sm-12'tr>><'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
renderer:"bootstrap"});b.extend(f.ext.classes,{sWrapper:"dataTables_wrapper container-fluid dt-bootstrap4",sFilterInput:"form-control form-control-sm",sLengthSelect:"form-control form-control-sm",sProcessing:"dataTables_processing card",sPageButton:"paginate_button page-item"});f.ext.renderer.pageButton.bootstrap=function(a,h,r,s,j,n){var o=new f.Api(a),t=a.oClasses,k=a.oLanguage.oPaginate,u=a.oLanguage.oAria.paginate||{},e,g,p=0,q=function(d,f){var l,h,i,c,m=function(a){a.preventDefault();!b(a.currentTarget).hasClass("disabled")&&
o.page()!=a.data.action&&o.page(a.data.action).draw("page")};l=0;for(h=f.length;l<h;l++)if(c=f[l],b.isArray(c))q(d,c);else{g=e="";switch(c){case "ellipsis":e="&#x2026;";g="disabled";break;case "first":e=k.sFirst;g=c+(0<j?"":" disabled");break;case "previous":e=k.sPrevious;g=c+(0<j?"":" disabled");break;case "next":e=k.sNext;g=c+(j<n-1?"":" disabled");break;case "last":e=k.sLast;g=c+(j<n-1?"":" disabled");break;default:e=c+1,g=j===c?"active":""}e&&(i=b("<li>",{"class":t.sPageButton+" "+g,id:0===r&&
"string"===typeof c?a.sTableId+"_"+c:null}).append(b("<a>",{href:"#","aria-controls":a.sTableId,"aria-label":u[c],"data-dt-idx":p,tabindex:a.iTabIndex,"class":"page-link"}).html(e)).appendTo(d),a.oApi._fnBindAction(i,{action:c},m),p++)}},i;try{i=b(h).find(d.activeElement).data("dt-idx")}catch(v){}q(b(h).empty().html('<ul class="pagination"/>').children("ul"),s);i!==m&&b(h).find("[data-dt-idx="+i+"]").focus()};return f});

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,164 @@
/*!
DataTables 1.10.16
©2008-2017 SpryMedia Ltd - datatables.net/license
*/
(function(h){"function"===typeof define&&define.amd?define(["jquery"],function(E){return h(E,window,document)}):"object"===typeof exports?module.exports=function(E,G){E||(E=window);G||(G="undefined"!==typeof window?require("jquery"):require("jquery")(E));return h(G,E,E.document)}:h(jQuery,window,document)})(function(h,E,G,k){function X(a){var b,c,d={};h.each(a,function(e){if((b=e.match(/^([^A-Z]+?)([A-Z])/))&&-1!=="a aa ai ao as b fn i m o s ".indexOf(b[1]+" "))c=e.replace(b[0],b[2].toLowerCase()),
d[c]=e,"o"===b[1]&&X(a[e])});a._hungarianMap=d}function I(a,b,c){a._hungarianMap||X(a);var d;h.each(b,function(e){d=a._hungarianMap[e];if(d!==k&&(c||b[d]===k))"o"===d.charAt(0)?(b[d]||(b[d]={}),h.extend(!0,b[d],b[e]),I(a[d],b[d],c)):b[d]=b[e]})}function Ca(a){var b=m.defaults.oLanguage,c=a.sZeroRecords;!a.sEmptyTable&&(c&&"No data available in table"===b.sEmptyTable)&&F(a,a,"sZeroRecords","sEmptyTable");!a.sLoadingRecords&&(c&&"Loading..."===b.sLoadingRecords)&&F(a,a,"sZeroRecords","sLoadingRecords");
a.sInfoThousands&&(a.sThousands=a.sInfoThousands);(a=a.sDecimal)&&cb(a)}function db(a){A(a,"ordering","bSort");A(a,"orderMulti","bSortMulti");A(a,"orderClasses","bSortClasses");A(a,"orderCellsTop","bSortCellsTop");A(a,"order","aaSorting");A(a,"orderFixed","aaSortingFixed");A(a,"paging","bPaginate");A(a,"pagingType","sPaginationType");A(a,"pageLength","iDisplayLength");A(a,"searching","bFilter");"boolean"===typeof a.sScrollX&&(a.sScrollX=a.sScrollX?"100%":"");"boolean"===typeof a.scrollX&&(a.scrollX=
a.scrollX?"100%":"");if(a=a.aoSearchCols)for(var b=0,c=a.length;b<c;b++)a[b]&&I(m.models.oSearch,a[b])}function eb(a){A(a,"orderable","bSortable");A(a,"orderData","aDataSort");A(a,"orderSequence","asSorting");A(a,"orderDataType","sortDataType");var b=a.aDataSort;"number"===typeof b&&!h.isArray(b)&&(a.aDataSort=[b])}function fb(a){if(!m.__browser){var b={};m.__browser=b;var c=h("<div/>").css({position:"fixed",top:0,left:-1*h(E).scrollLeft(),height:1,width:1,overflow:"hidden"}).append(h("<div/>").css({position:"absolute",
top:1,left:1,width:100,overflow:"scroll"}).append(h("<div/>").css({width:"100%",height:10}))).appendTo("body"),d=c.children(),e=d.children();b.barWidth=d[0].offsetWidth-d[0].clientWidth;b.bScrollOversize=100===e[0].offsetWidth&&100!==d[0].clientWidth;b.bScrollbarLeft=1!==Math.round(e.offset().left);b.bBounding=c[0].getBoundingClientRect().width?!0:!1;c.remove()}h.extend(a.oBrowser,m.__browser);a.oScroll.iBarWidth=m.__browser.barWidth}function gb(a,b,c,d,e,f){var g,j=!1;c!==k&&(g=c,j=!0);for(;d!==
e;)a.hasOwnProperty(d)&&(g=j?b(g,a[d],d,a):a[d],j=!0,d+=f);return g}function Da(a,b){var c=m.defaults.column,d=a.aoColumns.length,c=h.extend({},m.models.oColumn,c,{nTh:b?b:G.createElement("th"),sTitle:c.sTitle?c.sTitle:b?b.innerHTML:"",aDataSort:c.aDataSort?c.aDataSort:[d],mData:c.mData?c.mData:d,idx:d});a.aoColumns.push(c);c=a.aoPreSearchCols;c[d]=h.extend({},m.models.oSearch,c[d]);ja(a,d,h(b).data())}function ja(a,b,c){var b=a.aoColumns[b],d=a.oClasses,e=h(b.nTh);if(!b.sWidthOrig){b.sWidthOrig=
e.attr("width")||null;var f=(e.attr("style")||"").match(/width:\s*(\d+[pxem%]+)/);f&&(b.sWidthOrig=f[1])}c!==k&&null!==c&&(eb(c),I(m.defaults.column,c),c.mDataProp!==k&&!c.mData&&(c.mData=c.mDataProp),c.sType&&(b._sManualType=c.sType),c.className&&!c.sClass&&(c.sClass=c.className),c.sClass&&e.addClass(c.sClass),h.extend(b,c),F(b,c,"sWidth","sWidthOrig"),c.iDataSort!==k&&(b.aDataSort=[c.iDataSort]),F(b,c,"aDataSort"));var g=b.mData,j=Q(g),i=b.mRender?Q(b.mRender):null,c=function(a){return"string"===
typeof a&&-1!==a.indexOf("@")};b._bAttrSrc=h.isPlainObject(g)&&(c(g.sort)||c(g.type)||c(g.filter));b._setter=null;b.fnGetData=function(a,b,c){var d=j(a,b,k,c);return i&&b?i(d,b,a,c):d};b.fnSetData=function(a,b,c){return R(g)(a,b,c)};"number"!==typeof g&&(a._rowReadObject=!0);a.oFeatures.bSort||(b.bSortable=!1,e.addClass(d.sSortableNone));a=-1!==h.inArray("asc",b.asSorting);c=-1!==h.inArray("desc",b.asSorting);!b.bSortable||!a&&!c?(b.sSortingClass=d.sSortableNone,b.sSortingClassJUI=""):a&&!c?(b.sSortingClass=
d.sSortableAsc,b.sSortingClassJUI=d.sSortJUIAscAllowed):!a&&c?(b.sSortingClass=d.sSortableDesc,b.sSortingClassJUI=d.sSortJUIDescAllowed):(b.sSortingClass=d.sSortable,b.sSortingClassJUI=d.sSortJUI)}function Y(a){if(!1!==a.oFeatures.bAutoWidth){var b=a.aoColumns;Ea(a);for(var c=0,d=b.length;c<d;c++)b[c].nTh.style.width=b[c].sWidth}b=a.oScroll;(""!==b.sY||""!==b.sX)&&ka(a);r(a,null,"column-sizing",[a])}function Z(a,b){var c=la(a,"bVisible");return"number"===typeof c[b]?c[b]:null}function $(a,b){var c=
la(a,"bVisible"),c=h.inArray(b,c);return-1!==c?c:null}function aa(a){var b=0;h.each(a.aoColumns,function(a,d){d.bVisible&&"none"!==h(d.nTh).css("display")&&b++});return b}function la(a,b){var c=[];h.map(a.aoColumns,function(a,e){a[b]&&c.push(e)});return c}function Fa(a){var b=a.aoColumns,c=a.aoData,d=m.ext.type.detect,e,f,g,j,i,h,l,q,t;e=0;for(f=b.length;e<f;e++)if(l=b[e],t=[],!l.sType&&l._sManualType)l.sType=l._sManualType;else if(!l.sType){g=0;for(j=d.length;g<j;g++){i=0;for(h=c.length;i<h;i++){t[i]===
k&&(t[i]=B(a,i,e,"type"));q=d[g](t[i],a);if(!q&&g!==d.length-1)break;if("html"===q)break}if(q){l.sType=q;break}}l.sType||(l.sType="string")}}function hb(a,b,c,d){var e,f,g,j,i,n,l=a.aoColumns;if(b)for(e=b.length-1;0<=e;e--){n=b[e];var q=n.targets!==k?n.targets:n.aTargets;h.isArray(q)||(q=[q]);f=0;for(g=q.length;f<g;f++)if("number"===typeof q[f]&&0<=q[f]){for(;l.length<=q[f];)Da(a);d(q[f],n)}else if("number"===typeof q[f]&&0>q[f])d(l.length+q[f],n);else if("string"===typeof q[f]){j=0;for(i=l.length;j<
i;j++)("_all"==q[f]||h(l[j].nTh).hasClass(q[f]))&&d(j,n)}}if(c){e=0;for(a=c.length;e<a;e++)d(e,c[e])}}function M(a,b,c,d){var e=a.aoData.length,f=h.extend(!0,{},m.models.oRow,{src:c?"dom":"data",idx:e});f._aData=b;a.aoData.push(f);for(var g=a.aoColumns,j=0,i=g.length;j<i;j++)g[j].sType=null;a.aiDisplayMaster.push(e);b=a.rowIdFn(b);b!==k&&(a.aIds[b]=f);(c||!a.oFeatures.bDeferRender)&&Ga(a,e,c,d);return e}function ma(a,b){var c;b instanceof h||(b=h(b));return b.map(function(b,e){c=Ha(a,e);return M(a,
c.data,e,c.cells)})}function B(a,b,c,d){var e=a.iDraw,f=a.aoColumns[c],g=a.aoData[b]._aData,j=f.sDefaultContent,i=f.fnGetData(g,d,{settings:a,row:b,col:c});if(i===k)return a.iDrawError!=e&&null===j&&(J(a,0,"Requested unknown parameter "+("function"==typeof f.mData?"{function}":"'"+f.mData+"'")+" for row "+b+", column "+c,4),a.iDrawError=e),j;if((i===g||null===i)&&null!==j&&d!==k)i=j;else if("function"===typeof i)return i.call(g);return null===i&&"display"==d?"":i}function ib(a,b,c,d){a.aoColumns[c].fnSetData(a.aoData[b]._aData,
d,{settings:a,row:b,col:c})}function Ia(a){return h.map(a.match(/(\\.|[^\.])+/g)||[""],function(a){return a.replace(/\\\./g,".")})}function Q(a){if(h.isPlainObject(a)){var b={};h.each(a,function(a,c){c&&(b[a]=Q(c))});return function(a,c,f,g){var j=b[c]||b._;return j!==k?j(a,c,f,g):a}}if(null===a)return function(a){return a};if("function"===typeof a)return function(b,c,f,g){return a(b,c,f,g)};if("string"===typeof a&&(-1!==a.indexOf(".")||-1!==a.indexOf("[")||-1!==a.indexOf("("))){var c=function(a,
b,f){var g,j;if(""!==f){j=Ia(f);for(var i=0,n=j.length;i<n;i++){f=j[i].match(ba);g=j[i].match(U);if(f){j[i]=j[i].replace(ba,"");""!==j[i]&&(a=a[j[i]]);g=[];j.splice(0,i+1);j=j.join(".");if(h.isArray(a)){i=0;for(n=a.length;i<n;i++)g.push(c(a[i],b,j))}a=f[0].substring(1,f[0].length-1);a=""===a?g:g.join(a);break}else if(g){j[i]=j[i].replace(U,"");a=a[j[i]]();continue}if(null===a||a[j[i]]===k)return k;a=a[j[i]]}}return a};return function(b,e){return c(b,e,a)}}return function(b){return b[a]}}function R(a){if(h.isPlainObject(a))return R(a._);
if(null===a)return function(){};if("function"===typeof a)return function(b,d,e){a(b,"set",d,e)};if("string"===typeof a&&(-1!==a.indexOf(".")||-1!==a.indexOf("[")||-1!==a.indexOf("("))){var b=function(a,d,e){var e=Ia(e),f;f=e[e.length-1];for(var g,j,i=0,n=e.length-1;i<n;i++){g=e[i].match(ba);j=e[i].match(U);if(g){e[i]=e[i].replace(ba,"");a[e[i]]=[];f=e.slice();f.splice(0,i+1);g=f.join(".");if(h.isArray(d)){j=0;for(n=d.length;j<n;j++)f={},b(f,d[j],g),a[e[i]].push(f)}else a[e[i]]=d;return}j&&(e[i]=e[i].replace(U,
""),a=a[e[i]](d));if(null===a[e[i]]||a[e[i]]===k)a[e[i]]={};a=a[e[i]]}if(f.match(U))a[f.replace(U,"")](d);else a[f.replace(ba,"")]=d};return function(c,d){return b(c,d,a)}}return function(b,d){b[a]=d}}function Ja(a){return D(a.aoData,"_aData")}function na(a){a.aoData.length=0;a.aiDisplayMaster.length=0;a.aiDisplay.length=0;a.aIds={}}function oa(a,b,c){for(var d=-1,e=0,f=a.length;e<f;e++)a[e]==b?d=e:a[e]>b&&a[e]--; -1!=d&&c===k&&a.splice(d,1)}function ca(a,b,c,d){var e=a.aoData[b],f,g=function(c,d){for(;c.childNodes.length;)c.removeChild(c.firstChild);
c.innerHTML=B(a,b,d,"display")};if("dom"===c||(!c||"auto"===c)&&"dom"===e.src)e._aData=Ha(a,e,d,d===k?k:e._aData).data;else{var j=e.anCells;if(j)if(d!==k)g(j[d],d);else{c=0;for(f=j.length;c<f;c++)g(j[c],c)}}e._aSortData=null;e._aFilterData=null;g=a.aoColumns;if(d!==k)g[d].sType=null;else{c=0;for(f=g.length;c<f;c++)g[c].sType=null;Ka(a,e)}}function Ha(a,b,c,d){var e=[],f=b.firstChild,g,j,i=0,n,l=a.aoColumns,q=a._rowReadObject,d=d!==k?d:q?{}:[],t=function(a,b){if("string"===typeof a){var c=a.indexOf("@");
-1!==c&&(c=a.substring(c+1),R(a)(d,b.getAttribute(c)))}},m=function(a){if(c===k||c===i)j=l[i],n=h.trim(a.innerHTML),j&&j._bAttrSrc?(R(j.mData._)(d,n),t(j.mData.sort,a),t(j.mData.type,a),t(j.mData.filter,a)):q?(j._setter||(j._setter=R(j.mData)),j._setter(d,n)):d[i]=n;i++};if(f)for(;f;){g=f.nodeName.toUpperCase();if("TD"==g||"TH"==g)m(f),e.push(f);f=f.nextSibling}else{e=b.anCells;f=0;for(g=e.length;f<g;f++)m(e[f])}if(b=b.firstChild?b:b.nTr)(b=b.getAttribute("id"))&&R(a.rowId)(d,b);return{data:d,cells:e}}
function Ga(a,b,c,d){var e=a.aoData[b],f=e._aData,g=[],j,i,n,l,q;if(null===e.nTr){j=c||G.createElement("tr");e.nTr=j;e.anCells=g;j._DT_RowIndex=b;Ka(a,e);l=0;for(q=a.aoColumns.length;l<q;l++){n=a.aoColumns[l];i=c?d[l]:G.createElement(n.sCellType);i._DT_CellIndex={row:b,column:l};g.push(i);if((!c||n.mRender||n.mData!==l)&&(!h.isPlainObject(n.mData)||n.mData._!==l+".display"))i.innerHTML=B(a,b,l,"display");n.sClass&&(i.className+=" "+n.sClass);n.bVisible&&!c?j.appendChild(i):!n.bVisible&&c&&i.parentNode.removeChild(i);
n.fnCreatedCell&&n.fnCreatedCell.call(a.oInstance,i,B(a,b,l),f,b,l)}r(a,"aoRowCreatedCallback",null,[j,f,b])}e.nTr.setAttribute("role","row")}function Ka(a,b){var c=b.nTr,d=b._aData;if(c){var e=a.rowIdFn(d);e&&(c.id=e);d.DT_RowClass&&(e=d.DT_RowClass.split(" "),b.__rowc=b.__rowc?qa(b.__rowc.concat(e)):e,h(c).removeClass(b.__rowc.join(" ")).addClass(d.DT_RowClass));d.DT_RowAttr&&h(c).attr(d.DT_RowAttr);d.DT_RowData&&h(c).data(d.DT_RowData)}}function jb(a){var b,c,d,e,f,g=a.nTHead,j=a.nTFoot,i=0===
h("th, td",g).length,n=a.oClasses,l=a.aoColumns;i&&(e=h("<tr/>").appendTo(g));b=0;for(c=l.length;b<c;b++)f=l[b],d=h(f.nTh).addClass(f.sClass),i&&d.appendTo(e),a.oFeatures.bSort&&(d.addClass(f.sSortingClass),!1!==f.bSortable&&(d.attr("tabindex",a.iTabIndex).attr("aria-controls",a.sTableId),La(a,f.nTh,b))),f.sTitle!=d[0].innerHTML&&d.html(f.sTitle),Ma(a,"header")(a,d,f,n);i&&da(a.aoHeader,g);h(g).find(">tr").attr("role","row");h(g).find(">tr>th, >tr>td").addClass(n.sHeaderTH);h(j).find(">tr>th, >tr>td").addClass(n.sFooterTH);
if(null!==j){a=a.aoFooter[0];b=0;for(c=a.length;b<c;b++)f=l[b],f.nTf=a[b].cell,f.sClass&&h(f.nTf).addClass(f.sClass)}}function ea(a,b,c){var d,e,f,g=[],j=[],i=a.aoColumns.length,n;if(b){c===k&&(c=!1);d=0;for(e=b.length;d<e;d++){g[d]=b[d].slice();g[d].nTr=b[d].nTr;for(f=i-1;0<=f;f--)!a.aoColumns[f].bVisible&&!c&&g[d].splice(f,1);j.push([])}d=0;for(e=g.length;d<e;d++){if(a=g[d].nTr)for(;f=a.firstChild;)a.removeChild(f);f=0;for(b=g[d].length;f<b;f++)if(n=i=1,j[d][f]===k){a.appendChild(g[d][f].cell);
for(j[d][f]=1;g[d+i]!==k&&g[d][f].cell==g[d+i][f].cell;)j[d+i][f]=1,i++;for(;g[d][f+n]!==k&&g[d][f].cell==g[d][f+n].cell;){for(c=0;c<i;c++)j[d+c][f+n]=1;n++}h(g[d][f].cell).attr("rowspan",i).attr("colspan",n)}}}}function N(a){var b=r(a,"aoPreDrawCallback","preDraw",[a]);if(-1!==h.inArray(!1,b))C(a,!1);else{var b=[],c=0,d=a.asStripeClasses,e=d.length,f=a.oLanguage,g=a.iInitDisplayStart,j="ssp"==y(a),i=a.aiDisplay;a.bDrawing=!0;g!==k&&-1!==g&&(a._iDisplayStart=j?g:g>=a.fnRecordsDisplay()?0:g,a.iInitDisplayStart=
-1);var g=a._iDisplayStart,n=a.fnDisplayEnd();if(a.bDeferLoading)a.bDeferLoading=!1,a.iDraw++,C(a,!1);else if(j){if(!a.bDestroying&&!kb(a))return}else a.iDraw++;if(0!==i.length){f=j?a.aoData.length:n;for(j=j?0:g;j<f;j++){var l=i[j],q=a.aoData[l];null===q.nTr&&Ga(a,l);l=q.nTr;if(0!==e){var t=d[c%e];q._sRowStripe!=t&&(h(l).removeClass(q._sRowStripe).addClass(t),q._sRowStripe=t)}r(a,"aoRowCallback",null,[l,q._aData,c,j]);b.push(l);c++}}else c=f.sZeroRecords,1==a.iDraw&&"ajax"==y(a)?c=f.sLoadingRecords:
f.sEmptyTable&&0===a.fnRecordsTotal()&&(c=f.sEmptyTable),b[0]=h("<tr/>",{"class":e?d[0]:""}).append(h("<td />",{valign:"top",colSpan:aa(a),"class":a.oClasses.sRowEmpty}).html(c))[0];r(a,"aoHeaderCallback","header",[h(a.nTHead).children("tr")[0],Ja(a),g,n,i]);r(a,"aoFooterCallback","footer",[h(a.nTFoot).children("tr")[0],Ja(a),g,n,i]);d=h(a.nTBody);d.children().detach();d.append(h(b));r(a,"aoDrawCallback","draw",[a]);a.bSorted=!1;a.bFiltered=!1;a.bDrawing=!1}}function S(a,b){var c=a.oFeatures,d=c.bFilter;
c.bSort&&lb(a);d?fa(a,a.oPreviousSearch):a.aiDisplay=a.aiDisplayMaster.slice();!0!==b&&(a._iDisplayStart=0);a._drawHold=b;N(a);a._drawHold=!1}function mb(a){var b=a.oClasses,c=h(a.nTable),c=h("<div/>").insertBefore(c),d=a.oFeatures,e=h("<div/>",{id:a.sTableId+"_wrapper","class":b.sWrapper+(a.nTFoot?"":" "+b.sNoFooter)});a.nHolding=c[0];a.nTableWrapper=e[0];a.nTableReinsertBefore=a.nTable.nextSibling;for(var f=a.sDom.split(""),g,j,i,n,l,q,k=0;k<f.length;k++){g=null;j=f[k];if("<"==j){i=h("<div/>")[0];
n=f[k+1];if("'"==n||'"'==n){l="";for(q=2;f[k+q]!=n;)l+=f[k+q],q++;"H"==l?l=b.sJUIHeader:"F"==l&&(l=b.sJUIFooter);-1!=l.indexOf(".")?(n=l.split("."),i.id=n[0].substr(1,n[0].length-1),i.className=n[1]):"#"==l.charAt(0)?i.id=l.substr(1,l.length-1):i.className=l;k+=q}e.append(i);e=h(i)}else if(">"==j)e=e.parent();else if("l"==j&&d.bPaginate&&d.bLengthChange)g=nb(a);else if("f"==j&&d.bFilter)g=ob(a);else if("r"==j&&d.bProcessing)g=pb(a);else if("t"==j)g=qb(a);else if("i"==j&&d.bInfo)g=rb(a);else if("p"==
j&&d.bPaginate)g=sb(a);else if(0!==m.ext.feature.length){i=m.ext.feature;q=0;for(n=i.length;q<n;q++)if(j==i[q].cFeature){g=i[q].fnInit(a);break}}g&&(i=a.aanFeatures,i[j]||(i[j]=[]),i[j].push(g),e.append(g))}c.replaceWith(e);a.nHolding=null}function da(a,b){var c=h(b).children("tr"),d,e,f,g,j,i,n,l,q,k;a.splice(0,a.length);f=0;for(i=c.length;f<i;f++)a.push([]);f=0;for(i=c.length;f<i;f++){d=c[f];for(e=d.firstChild;e;){if("TD"==e.nodeName.toUpperCase()||"TH"==e.nodeName.toUpperCase()){l=1*e.getAttribute("colspan");
q=1*e.getAttribute("rowspan");l=!l||0===l||1===l?1:l;q=!q||0===q||1===q?1:q;g=0;for(j=a[f];j[g];)g++;n=g;k=1===l?!0:!1;for(j=0;j<l;j++)for(g=0;g<q;g++)a[f+g][n+j]={cell:e,unique:k},a[f+g].nTr=d}e=e.nextSibling}}}function ra(a,b,c){var d=[];c||(c=a.aoHeader,b&&(c=[],da(c,b)));for(var b=0,e=c.length;b<e;b++)for(var f=0,g=c[b].length;f<g;f++)if(c[b][f].unique&&(!d[f]||!a.bSortCellsTop))d[f]=c[b][f].cell;return d}function sa(a,b,c){r(a,"aoServerParams","serverParams",[b]);if(b&&h.isArray(b)){var d={},
e=/(.*?)\[\]$/;h.each(b,function(a,b){var c=b.name.match(e);c?(c=c[0],d[c]||(d[c]=[]),d[c].push(b.value)):d[b.name]=b.value});b=d}var f,g=a.ajax,j=a.oInstance,i=function(b){r(a,null,"xhr",[a,b,a.jqXHR]);c(b)};if(h.isPlainObject(g)&&g.data){f=g.data;var n=h.isFunction(f)?f(b,a):f,b=h.isFunction(f)&&n?n:h.extend(!0,b,n);delete g.data}n={data:b,success:function(b){var c=b.error||b.sError;c&&J(a,0,c);a.json=b;i(b)},dataType:"json",cache:!1,type:a.sServerMethod,error:function(b,c){var d=r(a,null,"xhr",
[a,null,a.jqXHR]);-1===h.inArray(!0,d)&&("parsererror"==c?J(a,0,"Invalid JSON response",1):4===b.readyState&&J(a,0,"Ajax error",7));C(a,!1)}};a.oAjaxData=b;r(a,null,"preXhr",[a,b]);a.fnServerData?a.fnServerData.call(j,a.sAjaxSource,h.map(b,function(a,b){return{name:b,value:a}}),i,a):a.sAjaxSource||"string"===typeof g?a.jqXHR=h.ajax(h.extend(n,{url:g||a.sAjaxSource})):h.isFunction(g)?a.jqXHR=g.call(j,b,i,a):(a.jqXHR=h.ajax(h.extend(n,g)),g.data=f)}function kb(a){return a.bAjaxDataGet?(a.iDraw++,C(a,
!0),sa(a,tb(a),function(b){ub(a,b)}),!1):!0}function tb(a){var b=a.aoColumns,c=b.length,d=a.oFeatures,e=a.oPreviousSearch,f=a.aoPreSearchCols,g,j=[],i,n,l,k=V(a);g=a._iDisplayStart;i=!1!==d.bPaginate?a._iDisplayLength:-1;var t=function(a,b){j.push({name:a,value:b})};t("sEcho",a.iDraw);t("iColumns",c);t("sColumns",D(b,"sName").join(","));t("iDisplayStart",g);t("iDisplayLength",i);var pa={draw:a.iDraw,columns:[],order:[],start:g,length:i,search:{value:e.sSearch,regex:e.bRegex}};for(g=0;g<c;g++)n=b[g],
l=f[g],i="function"==typeof n.mData?"function":n.mData,pa.columns.push({data:i,name:n.sName,searchable:n.bSearchable,orderable:n.bSortable,search:{value:l.sSearch,regex:l.bRegex}}),t("mDataProp_"+g,i),d.bFilter&&(t("sSearch_"+g,l.sSearch),t("bRegex_"+g,l.bRegex),t("bSearchable_"+g,n.bSearchable)),d.bSort&&t("bSortable_"+g,n.bSortable);d.bFilter&&(t("sSearch",e.sSearch),t("bRegex",e.bRegex));d.bSort&&(h.each(k,function(a,b){pa.order.push({column:b.col,dir:b.dir});t("iSortCol_"+a,b.col);t("sSortDir_"+
a,b.dir)}),t("iSortingCols",k.length));b=m.ext.legacy.ajax;return null===b?a.sAjaxSource?j:pa:b?j:pa}function ub(a,b){var c=ta(a,b),d=b.sEcho!==k?b.sEcho:b.draw,e=b.iTotalRecords!==k?b.iTotalRecords:b.recordsTotal,f=b.iTotalDisplayRecords!==k?b.iTotalDisplayRecords:b.recordsFiltered;if(d){if(1*d<a.iDraw)return;a.iDraw=1*d}na(a);a._iRecordsTotal=parseInt(e,10);a._iRecordsDisplay=parseInt(f,10);d=0;for(e=c.length;d<e;d++)M(a,c[d]);a.aiDisplay=a.aiDisplayMaster.slice();a.bAjaxDataGet=!1;N(a);a._bInitComplete||
ua(a,b);a.bAjaxDataGet=!0;C(a,!1)}function ta(a,b){var c=h.isPlainObject(a.ajax)&&a.ajax.dataSrc!==k?a.ajax.dataSrc:a.sAjaxDataProp;return"data"===c?b.aaData||b[c]:""!==c?Q(c)(b):b}function ob(a){var b=a.oClasses,c=a.sTableId,d=a.oLanguage,e=a.oPreviousSearch,f=a.aanFeatures,g='<input type="search" class="'+b.sFilterInput+'"/>',j=d.sSearch,j=j.match(/_INPUT_/)?j.replace("_INPUT_",g):j+g,b=h("<div/>",{id:!f.f?c+"_filter":null,"class":b.sFilter}).append(h("<label/>").append(j)),f=function(){var b=!this.value?
"":this.value;b!=e.sSearch&&(fa(a,{sSearch:b,bRegex:e.bRegex,bSmart:e.bSmart,bCaseInsensitive:e.bCaseInsensitive}),a._iDisplayStart=0,N(a))},g=null!==a.searchDelay?a.searchDelay:"ssp"===y(a)?400:0,i=h("input",b).val(e.sSearch).attr("placeholder",d.sSearchPlaceholder).on("keyup.DT search.DT input.DT paste.DT cut.DT",g?Na(f,g):f).on("keypress.DT",function(a){if(13==a.keyCode)return!1}).attr("aria-controls",c);h(a.nTable).on("search.dt.DT",function(b,c){if(a===c)try{i[0]!==G.activeElement&&i.val(e.sSearch)}catch(d){}});
return b[0]}function fa(a,b,c){var d=a.oPreviousSearch,e=a.aoPreSearchCols,f=function(a){d.sSearch=a.sSearch;d.bRegex=a.bRegex;d.bSmart=a.bSmart;d.bCaseInsensitive=a.bCaseInsensitive};Fa(a);if("ssp"!=y(a)){vb(a,b.sSearch,c,b.bEscapeRegex!==k?!b.bEscapeRegex:b.bRegex,b.bSmart,b.bCaseInsensitive);f(b);for(b=0;b<e.length;b++)wb(a,e[b].sSearch,b,e[b].bEscapeRegex!==k?!e[b].bEscapeRegex:e[b].bRegex,e[b].bSmart,e[b].bCaseInsensitive);xb(a)}else f(b);a.bFiltered=!0;r(a,null,"search",[a])}function xb(a){for(var b=
m.ext.search,c=a.aiDisplay,d,e,f=0,g=b.length;f<g;f++){for(var j=[],i=0,n=c.length;i<n;i++)e=c[i],d=a.aoData[e],b[f](a,d._aFilterData,e,d._aData,i)&&j.push(e);c.length=0;h.merge(c,j)}}function wb(a,b,c,d,e,f){if(""!==b){for(var g=[],j=a.aiDisplay,d=Oa(b,d,e,f),e=0;e<j.length;e++)b=a.aoData[j[e]]._aFilterData[c],d.test(b)&&g.push(j[e]);a.aiDisplay=g}}function vb(a,b,c,d,e,f){var d=Oa(b,d,e,f),f=a.oPreviousSearch.sSearch,g=a.aiDisplayMaster,j,e=[];0!==m.ext.search.length&&(c=!0);j=yb(a);if(0>=b.length)a.aiDisplay=
g.slice();else{if(j||c||f.length>b.length||0!==b.indexOf(f)||a.bSorted)a.aiDisplay=g.slice();b=a.aiDisplay;for(c=0;c<b.length;c++)d.test(a.aoData[b[c]]._sFilterRow)&&e.push(b[c]);a.aiDisplay=e}}function Oa(a,b,c,d){a=b?a:Pa(a);c&&(a="^(?=.*?"+h.map(a.match(/"[^"]+"|[^ ]+/g)||[""],function(a){if('"'===a.charAt(0))var b=a.match(/^"(.*)"$/),a=b?b[1]:a;return a.replace('"',"")}).join(")(?=.*?")+").*$");return RegExp(a,d?"i":"")}function yb(a){var b=a.aoColumns,c,d,e,f,g,j,i,h,l=m.ext.type.search;c=!1;
d=0;for(f=a.aoData.length;d<f;d++)if(h=a.aoData[d],!h._aFilterData){j=[];e=0;for(g=b.length;e<g;e++)c=b[e],c.bSearchable?(i=B(a,d,e,"filter"),l[c.sType]&&(i=l[c.sType](i)),null===i&&(i=""),"string"!==typeof i&&i.toString&&(i=i.toString())):i="",i.indexOf&&-1!==i.indexOf("&")&&(va.innerHTML=i,i=Wb?va.textContent:va.innerText),i.replace&&(i=i.replace(/[\r\n]/g,"")),j.push(i);h._aFilterData=j;h._sFilterRow=j.join(" ");c=!0}return c}function zb(a){return{search:a.sSearch,smart:a.bSmart,regex:a.bRegex,
caseInsensitive:a.bCaseInsensitive}}function Ab(a){return{sSearch:a.search,bSmart:a.smart,bRegex:a.regex,bCaseInsensitive:a.caseInsensitive}}function rb(a){var b=a.sTableId,c=a.aanFeatures.i,d=h("<div/>",{"class":a.oClasses.sInfo,id:!c?b+"_info":null});c||(a.aoDrawCallback.push({fn:Bb,sName:"information"}),d.attr("role","status").attr("aria-live","polite"),h(a.nTable).attr("aria-describedby",b+"_info"));return d[0]}function Bb(a){var b=a.aanFeatures.i;if(0!==b.length){var c=a.oLanguage,d=a._iDisplayStart+
1,e=a.fnDisplayEnd(),f=a.fnRecordsTotal(),g=a.fnRecordsDisplay(),j=g?c.sInfo:c.sInfoEmpty;g!==f&&(j+=" "+c.sInfoFiltered);j+=c.sInfoPostFix;j=Cb(a,j);c=c.fnInfoCallback;null!==c&&(j=c.call(a.oInstance,a,d,e,f,g,j));h(b).html(j)}}function Cb(a,b){var c=a.fnFormatNumber,d=a._iDisplayStart+1,e=a._iDisplayLength,f=a.fnRecordsDisplay(),g=-1===e;return b.replace(/_START_/g,c.call(a,d)).replace(/_END_/g,c.call(a,a.fnDisplayEnd())).replace(/_MAX_/g,c.call(a,a.fnRecordsTotal())).replace(/_TOTAL_/g,c.call(a,
f)).replace(/_PAGE_/g,c.call(a,g?1:Math.ceil(d/e))).replace(/_PAGES_/g,c.call(a,g?1:Math.ceil(f/e)))}function ga(a){var b,c,d=a.iInitDisplayStart,e=a.aoColumns,f;c=a.oFeatures;var g=a.bDeferLoading;if(a.bInitialised){mb(a);jb(a);ea(a,a.aoHeader);ea(a,a.aoFooter);C(a,!0);c.bAutoWidth&&Ea(a);b=0;for(c=e.length;b<c;b++)f=e[b],f.sWidth&&(f.nTh.style.width=v(f.sWidth));r(a,null,"preInit",[a]);S(a);e=y(a);if("ssp"!=e||g)"ajax"==e?sa(a,[],function(c){var f=ta(a,c);for(b=0;b<f.length;b++)M(a,f[b]);a.iInitDisplayStart=
d;S(a);C(a,!1);ua(a,c)},a):(C(a,!1),ua(a))}else setTimeout(function(){ga(a)},200)}function ua(a,b){a._bInitComplete=!0;(b||a.oInit.aaData)&&Y(a);r(a,null,"plugin-init",[a,b]);r(a,"aoInitComplete","init",[a,b])}function Qa(a,b){var c=parseInt(b,10);a._iDisplayLength=c;Ra(a);r(a,null,"length",[a,c])}function nb(a){for(var b=a.oClasses,c=a.sTableId,d=a.aLengthMenu,e=h.isArray(d[0]),f=e?d[0]:d,d=e?d[1]:d,e=h("<select/>",{name:c+"_length","aria-controls":c,"class":b.sLengthSelect}),g=0,j=f.length;g<j;g++)e[0][g]=
new Option("number"===typeof d[g]?a.fnFormatNumber(d[g]):d[g],f[g]);var i=h("<div><label/></div>").addClass(b.sLength);a.aanFeatures.l||(i[0].id=c+"_length");i.children().append(a.oLanguage.sLengthMenu.replace("_MENU_",e[0].outerHTML));h("select",i).val(a._iDisplayLength).on("change.DT",function(){Qa(a,h(this).val());N(a)});h(a.nTable).on("length.dt.DT",function(b,c,d){a===c&&h("select",i).val(d)});return i[0]}function sb(a){var b=a.sPaginationType,c=m.ext.pager[b],d="function"===typeof c,e=function(a){N(a)},
b=h("<div/>").addClass(a.oClasses.sPaging+b)[0],f=a.aanFeatures;d||c.fnInit(a,b,e);f.p||(b.id=a.sTableId+"_paginate",a.aoDrawCallback.push({fn:function(a){if(d){var b=a._iDisplayStart,i=a._iDisplayLength,h=a.fnRecordsDisplay(),l=-1===i,b=l?0:Math.ceil(b/i),i=l?1:Math.ceil(h/i),h=c(b,i),k,l=0;for(k=f.p.length;l<k;l++)Ma(a,"pageButton")(a,f.p[l],l,h,b,i)}else c.fnUpdate(a,e)},sName:"pagination"}));return b}function Sa(a,b,c){var d=a._iDisplayStart,e=a._iDisplayLength,f=a.fnRecordsDisplay();0===f||-1===
e?d=0:"number"===typeof b?(d=b*e,d>f&&(d=0)):"first"==b?d=0:"previous"==b?(d=0<=e?d-e:0,0>d&&(d=0)):"next"==b?d+e<f&&(d+=e):"last"==b?d=Math.floor((f-1)/e)*e:J(a,0,"Unknown paging action: "+b,5);b=a._iDisplayStart!==d;a._iDisplayStart=d;b&&(r(a,null,"page",[a]),c&&N(a));return b}function pb(a){return h("<div/>",{id:!a.aanFeatures.r?a.sTableId+"_processing":null,"class":a.oClasses.sProcessing}).html(a.oLanguage.sProcessing).insertBefore(a.nTable)[0]}function C(a,b){a.oFeatures.bProcessing&&h(a.aanFeatures.r).css("display",
b?"block":"none");r(a,null,"processing",[a,b])}function qb(a){var b=h(a.nTable);b.attr("role","grid");var c=a.oScroll;if(""===c.sX&&""===c.sY)return a.nTable;var d=c.sX,e=c.sY,f=a.oClasses,g=b.children("caption"),j=g.length?g[0]._captionSide:null,i=h(b[0].cloneNode(!1)),n=h(b[0].cloneNode(!1)),l=b.children("tfoot");l.length||(l=null);i=h("<div/>",{"class":f.sScrollWrapper}).append(h("<div/>",{"class":f.sScrollHead}).css({overflow:"hidden",position:"relative",border:0,width:d?!d?null:v(d):"100%"}).append(h("<div/>",
{"class":f.sScrollHeadInner}).css({"box-sizing":"content-box",width:c.sXInner||"100%"}).append(i.removeAttr("id").css("margin-left",0).append("top"===j?g:null).append(b.children("thead"))))).append(h("<div/>",{"class":f.sScrollBody}).css({position:"relative",overflow:"auto",width:!d?null:v(d)}).append(b));l&&i.append(h("<div/>",{"class":f.sScrollFoot}).css({overflow:"hidden",border:0,width:d?!d?null:v(d):"100%"}).append(h("<div/>",{"class":f.sScrollFootInner}).append(n.removeAttr("id").css("margin-left",
0).append("bottom"===j?g:null).append(b.children("tfoot")))));var b=i.children(),k=b[0],f=b[1],t=l?b[2]:null;if(d)h(f).on("scroll.DT",function(){var a=this.scrollLeft;k.scrollLeft=a;l&&(t.scrollLeft=a)});h(f).css(e&&c.bCollapse?"max-height":"height",e);a.nScrollHead=k;a.nScrollBody=f;a.nScrollFoot=t;a.aoDrawCallback.push({fn:ka,sName:"scrolling"});return i[0]}function ka(a){var b=a.oScroll,c=b.sX,d=b.sXInner,e=b.sY,b=b.iBarWidth,f=h(a.nScrollHead),g=f[0].style,j=f.children("div"),i=j[0].style,n=j.children("table"),
j=a.nScrollBody,l=h(j),q=j.style,t=h(a.nScrollFoot).children("div"),m=t.children("table"),o=h(a.nTHead),p=h(a.nTable),s=p[0],r=s.style,u=a.nTFoot?h(a.nTFoot):null,x=a.oBrowser,T=x.bScrollOversize,Xb=D(a.aoColumns,"nTh"),O,K,P,w,Ta=[],y=[],z=[],A=[],B,C=function(a){a=a.style;a.paddingTop="0";a.paddingBottom="0";a.borderTopWidth="0";a.borderBottomWidth="0";a.height=0};K=j.scrollHeight>j.clientHeight;if(a.scrollBarVis!==K&&a.scrollBarVis!==k)a.scrollBarVis=K,Y(a);else{a.scrollBarVis=K;p.children("thead, tfoot").remove();
u&&(P=u.clone().prependTo(p),O=u.find("tr"),P=P.find("tr"));w=o.clone().prependTo(p);o=o.find("tr");K=w.find("tr");w.find("th, td").removeAttr("tabindex");c||(q.width="100%",f[0].style.width="100%");h.each(ra(a,w),function(b,c){B=Z(a,b);c.style.width=a.aoColumns[B].sWidth});u&&H(function(a){a.style.width=""},P);f=p.outerWidth();if(""===c){r.width="100%";if(T&&(p.find("tbody").height()>j.offsetHeight||"scroll"==l.css("overflow-y")))r.width=v(p.outerWidth()-b);f=p.outerWidth()}else""!==d&&(r.width=
v(d),f=p.outerWidth());H(C,K);H(function(a){z.push(a.innerHTML);Ta.push(v(h(a).css("width")))},K);H(function(a,b){if(h.inArray(a,Xb)!==-1)a.style.width=Ta[b]},o);h(K).height(0);u&&(H(C,P),H(function(a){A.push(a.innerHTML);y.push(v(h(a).css("width")))},P),H(function(a,b){a.style.width=y[b]},O),h(P).height(0));H(function(a,b){a.innerHTML='<div class="dataTables_sizing" style="height:0;overflow:hidden;">'+z[b]+"</div>";a.style.width=Ta[b]},K);u&&H(function(a,b){a.innerHTML='<div class="dataTables_sizing" style="height:0;overflow:hidden;">'+
A[b]+"</div>";a.style.width=y[b]},P);if(p.outerWidth()<f){O=j.scrollHeight>j.offsetHeight||"scroll"==l.css("overflow-y")?f+b:f;if(T&&(j.scrollHeight>j.offsetHeight||"scroll"==l.css("overflow-y")))r.width=v(O-b);(""===c||""!==d)&&J(a,1,"Possible column misalignment",6)}else O="100%";q.width=v(O);g.width=v(O);u&&(a.nScrollFoot.style.width=v(O));!e&&T&&(q.height=v(s.offsetHeight+b));c=p.outerWidth();n[0].style.width=v(c);i.width=v(c);d=p.height()>j.clientHeight||"scroll"==l.css("overflow-y");e="padding"+
(x.bScrollbarLeft?"Left":"Right");i[e]=d?b+"px":"0px";u&&(m[0].style.width=v(c),t[0].style.width=v(c),t[0].style[e]=d?b+"px":"0px");p.children("colgroup").insertBefore(p.children("thead"));l.scroll();if((a.bSorted||a.bFiltered)&&!a._drawHold)j.scrollTop=0}}function H(a,b,c){for(var d=0,e=0,f=b.length,g,j;e<f;){g=b[e].firstChild;for(j=c?c[e].firstChild:null;g;)1===g.nodeType&&(c?a(g,j,d):a(g,d),d++),g=g.nextSibling,j=c?j.nextSibling:null;e++}}function Ea(a){var b=a.nTable,c=a.aoColumns,d=a.oScroll,
e=d.sY,f=d.sX,g=d.sXInner,j=c.length,i=la(a,"bVisible"),n=h("th",a.nTHead),l=b.getAttribute("width"),k=b.parentNode,t=!1,m,o,p=a.oBrowser,d=p.bScrollOversize;(m=b.style.width)&&-1!==m.indexOf("%")&&(l=m);for(m=0;m<i.length;m++)o=c[i[m]],null!==o.sWidth&&(o.sWidth=Db(o.sWidthOrig,k),t=!0);if(d||!t&&!f&&!e&&j==aa(a)&&j==n.length)for(m=0;m<j;m++)i=Z(a,m),null!==i&&(c[i].sWidth=v(n.eq(m).width()));else{j=h(b).clone().css("visibility","hidden").removeAttr("id");j.find("tbody tr").remove();var s=h("<tr/>").appendTo(j.find("tbody"));
j.find("thead, tfoot").remove();j.append(h(a.nTHead).clone()).append(h(a.nTFoot).clone());j.find("tfoot th, tfoot td").css("width","");n=ra(a,j.find("thead")[0]);for(m=0;m<i.length;m++)o=c[i[m]],n[m].style.width=null!==o.sWidthOrig&&""!==o.sWidthOrig?v(o.sWidthOrig):"",o.sWidthOrig&&f&&h(n[m]).append(h("<div/>").css({width:o.sWidthOrig,margin:0,padding:0,border:0,height:1}));if(a.aoData.length)for(m=0;m<i.length;m++)t=i[m],o=c[t],h(Eb(a,t)).clone(!1).append(o.sContentPadding).appendTo(s);h("[name]",
j).removeAttr("name");o=h("<div/>").css(f||e?{position:"absolute",top:0,left:0,height:1,right:0,overflow:"hidden"}:{}).append(j).appendTo(k);f&&g?j.width(g):f?(j.css("width","auto"),j.removeAttr("width"),j.width()<k.clientWidth&&l&&j.width(k.clientWidth)):e?j.width(k.clientWidth):l&&j.width(l);for(m=e=0;m<i.length;m++)k=h(n[m]),g=k.outerWidth()-k.width(),k=p.bBounding?Math.ceil(n[m].getBoundingClientRect().width):k.outerWidth(),e+=k,c[i[m]].sWidth=v(k-g);b.style.width=v(e);o.remove()}l&&(b.style.width=
v(l));if((l||f)&&!a._reszEvt)b=function(){h(E).on("resize.DT-"+a.sInstance,Na(function(){Y(a)}))},d?setTimeout(b,1E3):b(),a._reszEvt=!0}function Db(a,b){if(!a)return 0;var c=h("<div/>").css("width",v(a)).appendTo(b||G.body),d=c[0].offsetWidth;c.remove();return d}function Eb(a,b){var c=Fb(a,b);if(0>c)return null;var d=a.aoData[c];return!d.nTr?h("<td/>").html(B(a,c,b,"display"))[0]:d.anCells[b]}function Fb(a,b){for(var c,d=-1,e=-1,f=0,g=a.aoData.length;f<g;f++)c=B(a,f,b,"display")+"",c=c.replace(Yb,
""),c=c.replace(/&nbsp;/g," "),c.length>d&&(d=c.length,e=f);return e}function v(a){return null===a?"0px":"number"==typeof a?0>a?"0px":a+"px":a.match(/\d$/)?a+"px":a}function V(a){var b,c,d=[],e=a.aoColumns,f,g,j,i;b=a.aaSortingFixed;c=h.isPlainObject(b);var n=[];f=function(a){a.length&&!h.isArray(a[0])?n.push(a):h.merge(n,a)};h.isArray(b)&&f(b);c&&b.pre&&f(b.pre);f(a.aaSorting);c&&b.post&&f(b.post);for(a=0;a<n.length;a++){i=n[a][0];f=e[i].aDataSort;b=0;for(c=f.length;b<c;b++)g=f[b],j=e[g].sType||
"string",n[a]._idx===k&&(n[a]._idx=h.inArray(n[a][1],e[g].asSorting)),d.push({src:i,col:g,dir:n[a][1],index:n[a]._idx,type:j,formatter:m.ext.type.order[j+"-pre"]})}return d}function lb(a){var b,c,d=[],e=m.ext.type.order,f=a.aoData,g=0,j,i=a.aiDisplayMaster,h;Fa(a);h=V(a);b=0;for(c=h.length;b<c;b++)j=h[b],j.formatter&&g++,Gb(a,j.col);if("ssp"!=y(a)&&0!==h.length){b=0;for(c=i.length;b<c;b++)d[i[b]]=b;g===h.length?i.sort(function(a,b){var c,e,g,j,i=h.length,k=f[a]._aSortData,m=f[b]._aSortData;for(g=
0;g<i;g++)if(j=h[g],c=k[j.col],e=m[j.col],c=c<e?-1:c>e?1:0,0!==c)return"asc"===j.dir?c:-c;c=d[a];e=d[b];return c<e?-1:c>e?1:0}):i.sort(function(a,b){var c,g,j,i,k=h.length,m=f[a]._aSortData,o=f[b]._aSortData;for(j=0;j<k;j++)if(i=h[j],c=m[i.col],g=o[i.col],i=e[i.type+"-"+i.dir]||e["string-"+i.dir],c=i(c,g),0!==c)return c;c=d[a];g=d[b];return c<g?-1:c>g?1:0})}a.bSorted=!0}function Hb(a){for(var b,c,d=a.aoColumns,e=V(a),a=a.oLanguage.oAria,f=0,g=d.length;f<g;f++){c=d[f];var j=c.asSorting;b=c.sTitle.replace(/<.*?>/g,
"");var i=c.nTh;i.removeAttribute("aria-sort");c.bSortable&&(0<e.length&&e[0].col==f?(i.setAttribute("aria-sort","asc"==e[0].dir?"ascending":"descending"),c=j[e[0].index+1]||j[0]):c=j[0],b+="asc"===c?a.sSortAscending:a.sSortDescending);i.setAttribute("aria-label",b)}}function Ua(a,b,c,d){var e=a.aaSorting,f=a.aoColumns[b].asSorting,g=function(a,b){var c=a._idx;c===k&&(c=h.inArray(a[1],f));return c+1<f.length?c+1:b?null:0};"number"===typeof e[0]&&(e=a.aaSorting=[e]);c&&a.oFeatures.bSortMulti?(c=h.inArray(b,
D(e,"0")),-1!==c?(b=g(e[c],!0),null===b&&1===e.length&&(b=0),null===b?e.splice(c,1):(e[c][1]=f[b],e[c]._idx=b)):(e.push([b,f[0],0]),e[e.length-1]._idx=0)):e.length&&e[0][0]==b?(b=g(e[0]),e.length=1,e[0][1]=f[b],e[0]._idx=b):(e.length=0,e.push([b,f[0]]),e[0]._idx=0);S(a);"function"==typeof d&&d(a)}function La(a,b,c,d){var e=a.aoColumns[c];Va(b,{},function(b){!1!==e.bSortable&&(a.oFeatures.bProcessing?(C(a,!0),setTimeout(function(){Ua(a,c,b.shiftKey,d);"ssp"!==y(a)&&C(a,!1)},0)):Ua(a,c,b.shiftKey,d))})}
function wa(a){var b=a.aLastSort,c=a.oClasses.sSortColumn,d=V(a),e=a.oFeatures,f,g;if(e.bSort&&e.bSortClasses){e=0;for(f=b.length;e<f;e++)g=b[e].src,h(D(a.aoData,"anCells",g)).removeClass(c+(2>e?e+1:3));e=0;for(f=d.length;e<f;e++)g=d[e].src,h(D(a.aoData,"anCells",g)).addClass(c+(2>e?e+1:3))}a.aLastSort=d}function Gb(a,b){var c=a.aoColumns[b],d=m.ext.order[c.sSortDataType],e;d&&(e=d.call(a.oInstance,a,b,$(a,b)));for(var f,g=m.ext.type.order[c.sType+"-pre"],j=0,i=a.aoData.length;j<i;j++)if(c=a.aoData[j],
c._aSortData||(c._aSortData=[]),!c._aSortData[b]||d)f=d?e[j]:B(a,j,b,"sort"),c._aSortData[b]=g?g(f):f}function xa(a){if(a.oFeatures.bStateSave&&!a.bDestroying){var b={time:+new Date,start:a._iDisplayStart,length:a._iDisplayLength,order:h.extend(!0,[],a.aaSorting),search:zb(a.oPreviousSearch),columns:h.map(a.aoColumns,function(b,d){return{visible:b.bVisible,search:zb(a.aoPreSearchCols[d])}})};r(a,"aoStateSaveParams","stateSaveParams",[a,b]);a.oSavedState=b;a.fnStateSaveCallback.call(a.oInstance,a,
b)}}function Ib(a,b,c){var d,e,f=a.aoColumns,b=function(b){if(b&&b.time){var g=r(a,"aoStateLoadParams","stateLoadParams",[a,b]);if(-1===h.inArray(!1,g)&&(g=a.iStateDuration,!(0<g&&b.time<+new Date-1E3*g)&&!(b.columns&&f.length!==b.columns.length))){a.oLoadedState=h.extend(!0,{},b);b.start!==k&&(a._iDisplayStart=b.start,a.iInitDisplayStart=b.start);b.length!==k&&(a._iDisplayLength=b.length);b.order!==k&&(a.aaSorting=[],h.each(b.order,function(b,c){a.aaSorting.push(c[0]>=f.length?[0,c[1]]:c)}));b.search!==
k&&h.extend(a.oPreviousSearch,Ab(b.search));if(b.columns){d=0;for(e=b.columns.length;d<e;d++)g=b.columns[d],g.visible!==k&&(f[d].bVisible=g.visible),g.search!==k&&h.extend(a.aoPreSearchCols[d],Ab(g.search))}r(a,"aoStateLoaded","stateLoaded",[a,b])}}c()};if(a.oFeatures.bStateSave){var g=a.fnStateLoadCallback.call(a.oInstance,a,b);g!==k&&b(g)}else c()}function ya(a){var b=m.settings,a=h.inArray(a,D(b,"nTable"));return-1!==a?b[a]:null}function J(a,b,c,d){c="DataTables warning: "+(a?"table id="+a.sTableId+
" - ":"")+c;d&&(c+=". For more information about this error, please see http://datatables.net/tn/"+d);if(b)E.console&&console.log&&console.log(c);else if(b=m.ext,b=b.sErrMode||b.errMode,a&&r(a,null,"error",[a,d,c]),"alert"==b)alert(c);else{if("throw"==b)throw Error(c);"function"==typeof b&&b(a,d,c)}}function F(a,b,c,d){h.isArray(c)?h.each(c,function(c,d){h.isArray(d)?F(a,b,d[0],d[1]):F(a,b,d)}):(d===k&&(d=c),b[c]!==k&&(a[d]=b[c]))}function Jb(a,b,c){var d,e;for(e in b)b.hasOwnProperty(e)&&(d=b[e],
h.isPlainObject(d)?(h.isPlainObject(a[e])||(a[e]={}),h.extend(!0,a[e],d)):a[e]=c&&"data"!==e&&"aaData"!==e&&h.isArray(d)?d.slice():d);return a}function Va(a,b,c){h(a).on("click.DT",b,function(b){a.blur();c(b)}).on("keypress.DT",b,function(a){13===a.which&&(a.preventDefault(),c(a))}).on("selectstart.DT",function(){return!1})}function z(a,b,c,d){c&&a[b].push({fn:c,sName:d})}function r(a,b,c,d){var e=[];b&&(e=h.map(a[b].slice().reverse(),function(b){return b.fn.apply(a.oInstance,d)}));null!==c&&(b=h.Event(c+
".dt"),h(a.nTable).trigger(b,d),e.push(b.result));return e}function Ra(a){var b=a._iDisplayStart,c=a.fnDisplayEnd(),d=a._iDisplayLength;b>=c&&(b=c-d);b-=b%d;if(-1===d||0>b)b=0;a._iDisplayStart=b}function Ma(a,b){var c=a.renderer,d=m.ext.renderer[b];return h.isPlainObject(c)&&c[b]?d[c[b]]||d._:"string"===typeof c?d[c]||d._:d._}function y(a){return a.oFeatures.bServerSide?"ssp":a.ajax||a.sAjaxSource?"ajax":"dom"}function ha(a,b){var c=[],c=Kb.numbers_length,d=Math.floor(c/2);b<=c?c=W(0,b):a<=d?(c=W(0,
c-2),c.push("ellipsis"),c.push(b-1)):(a>=b-1-d?c=W(b-(c-2),b):(c=W(a-d+2,a+d-1),c.push("ellipsis"),c.push(b-1)),c.splice(0,0,"ellipsis"),c.splice(0,0,0));c.DT_el="span";return c}function cb(a){h.each({num:function(b){return za(b,a)},"num-fmt":function(b){return za(b,a,Wa)},"html-num":function(b){return za(b,a,Aa)},"html-num-fmt":function(b){return za(b,a,Aa,Wa)}},function(b,c){x.type.order[b+a+"-pre"]=c;b.match(/^html\-/)&&(x.type.search[b+a]=x.type.search.html)})}function Lb(a){return function(){var b=
[ya(this[m.ext.iApiIndex])].concat(Array.prototype.slice.call(arguments));return m.ext.internal[a].apply(this,b)}}var m=function(a){this.$=function(a,b){return this.api(!0).$(a,b)};this._=function(a,b){return this.api(!0).rows(a,b).data()};this.api=function(a){return a?new s(ya(this[x.iApiIndex])):new s(this)};this.fnAddData=function(a,b){var c=this.api(!0),d=h.isArray(a)&&(h.isArray(a[0])||h.isPlainObject(a[0]))?c.rows.add(a):c.row.add(a);(b===k||b)&&c.draw();return d.flatten().toArray()};this.fnAdjustColumnSizing=
function(a){var b=this.api(!0).columns.adjust(),c=b.settings()[0],d=c.oScroll;a===k||a?b.draw(!1):(""!==d.sX||""!==d.sY)&&ka(c)};this.fnClearTable=function(a){var b=this.api(!0).clear();(a===k||a)&&b.draw()};this.fnClose=function(a){this.api(!0).row(a).child.hide()};this.fnDeleteRow=function(a,b,c){var d=this.api(!0),a=d.rows(a),e=a.settings()[0],h=e.aoData[a[0][0]];a.remove();b&&b.call(this,e,h);(c===k||c)&&d.draw();return h};this.fnDestroy=function(a){this.api(!0).destroy(a)};this.fnDraw=function(a){this.api(!0).draw(a)};
this.fnFilter=function(a,b,c,d,e,h){e=this.api(!0);null===b||b===k?e.search(a,c,d,h):e.column(b).search(a,c,d,h);e.draw()};this.fnGetData=function(a,b){var c=this.api(!0);if(a!==k){var d=a.nodeName?a.nodeName.toLowerCase():"";return b!==k||"td"==d||"th"==d?c.cell(a,b).data():c.row(a).data()||null}return c.data().toArray()};this.fnGetNodes=function(a){var b=this.api(!0);return a!==k?b.row(a).node():b.rows().nodes().flatten().toArray()};this.fnGetPosition=function(a){var b=this.api(!0),c=a.nodeName.toUpperCase();
return"TR"==c?b.row(a).index():"TD"==c||"TH"==c?(a=b.cell(a).index(),[a.row,a.columnVisible,a.column]):null};this.fnIsOpen=function(a){return this.api(!0).row(a).child.isShown()};this.fnOpen=function(a,b,c){return this.api(!0).row(a).child(b,c).show().child()[0]};this.fnPageChange=function(a,b){var c=this.api(!0).page(a);(b===k||b)&&c.draw(!1)};this.fnSetColumnVis=function(a,b,c){a=this.api(!0).column(a).visible(b);(c===k||c)&&a.columns.adjust().draw()};this.fnSettings=function(){return ya(this[x.iApiIndex])};
this.fnSort=function(a){this.api(!0).order(a).draw()};this.fnSortListener=function(a,b,c){this.api(!0).order.listener(a,b,c)};this.fnUpdate=function(a,b,c,d,e){var h=this.api(!0);c===k||null===c?h.row(b).data(a):h.cell(b,c).data(a);(e===k||e)&&h.columns.adjust();(d===k||d)&&h.draw();return 0};this.fnVersionCheck=x.fnVersionCheck;var b=this,c=a===k,d=this.length;c&&(a={});this.oApi=this.internal=x.internal;for(var e in m.ext.internal)e&&(this[e]=Lb(e));this.each(function(){var e={},g=1<d?Jb(e,a,!0):
a,j=0,i,e=this.getAttribute("id"),n=!1,l=m.defaults,q=h(this);if("table"!=this.nodeName.toLowerCase())J(null,0,"Non-table node initialisation ("+this.nodeName+")",2);else{db(l);eb(l.column);I(l,l,!0);I(l.column,l.column,!0);I(l,h.extend(g,q.data()));var t=m.settings,j=0;for(i=t.length;j<i;j++){var o=t[j];if(o.nTable==this||o.nTHead.parentNode==this||o.nTFoot&&o.nTFoot.parentNode==this){var s=g.bRetrieve!==k?g.bRetrieve:l.bRetrieve;if(c||s)return o.oInstance;if(g.bDestroy!==k?g.bDestroy:l.bDestroy){o.oInstance.fnDestroy();
break}else{J(o,0,"Cannot reinitialise DataTable",3);return}}if(o.sTableId==this.id){t.splice(j,1);break}}if(null===e||""===e)this.id=e="DataTables_Table_"+m.ext._unique++;var p=h.extend(!0,{},m.models.oSettings,{sDestroyWidth:q[0].style.width,sInstance:e,sTableId:e});p.nTable=this;p.oApi=b.internal;p.oInit=g;t.push(p);p.oInstance=1===b.length?b:q.dataTable();db(g);g.oLanguage&&Ca(g.oLanguage);g.aLengthMenu&&!g.iDisplayLength&&(g.iDisplayLength=h.isArray(g.aLengthMenu[0])?g.aLengthMenu[0][0]:g.aLengthMenu[0]);
g=Jb(h.extend(!0,{},l),g);F(p.oFeatures,g,"bPaginate bLengthChange bFilter bSort bSortMulti bInfo bProcessing bAutoWidth bSortClasses bServerSide bDeferRender".split(" "));F(p,g,["asStripeClasses","ajax","fnServerData","fnFormatNumber","sServerMethod","aaSorting","aaSortingFixed","aLengthMenu","sPaginationType","sAjaxSource","sAjaxDataProp","iStateDuration","sDom","bSortCellsTop","iTabIndex","fnStateLoadCallback","fnStateSaveCallback","renderer","searchDelay","rowId",["iCookieDuration","iStateDuration"],
["oSearch","oPreviousSearch"],["aoSearchCols","aoPreSearchCols"],["iDisplayLength","_iDisplayLength"]]);F(p.oScroll,g,[["sScrollX","sX"],["sScrollXInner","sXInner"],["sScrollY","sY"],["bScrollCollapse","bCollapse"]]);F(p.oLanguage,g,"fnInfoCallback");z(p,"aoDrawCallback",g.fnDrawCallback,"user");z(p,"aoServerParams",g.fnServerParams,"user");z(p,"aoStateSaveParams",g.fnStateSaveParams,"user");z(p,"aoStateLoadParams",g.fnStateLoadParams,"user");z(p,"aoStateLoaded",g.fnStateLoaded,"user");z(p,"aoRowCallback",
g.fnRowCallback,"user");z(p,"aoRowCreatedCallback",g.fnCreatedRow,"user");z(p,"aoHeaderCallback",g.fnHeaderCallback,"user");z(p,"aoFooterCallback",g.fnFooterCallback,"user");z(p,"aoInitComplete",g.fnInitComplete,"user");z(p,"aoPreDrawCallback",g.fnPreDrawCallback,"user");p.rowIdFn=Q(g.rowId);fb(p);var u=p.oClasses;h.extend(u,m.ext.classes,g.oClasses);q.addClass(u.sTable);p.iInitDisplayStart===k&&(p.iInitDisplayStart=g.iDisplayStart,p._iDisplayStart=g.iDisplayStart);null!==g.iDeferLoading&&(p.bDeferLoading=
!0,e=h.isArray(g.iDeferLoading),p._iRecordsDisplay=e?g.iDeferLoading[0]:g.iDeferLoading,p._iRecordsTotal=e?g.iDeferLoading[1]:g.iDeferLoading);var v=p.oLanguage;h.extend(!0,v,g.oLanguage);v.sUrl&&(h.ajax({dataType:"json",url:v.sUrl,success:function(a){Ca(a);I(l.oLanguage,a);h.extend(true,v,a);ga(p)},error:function(){ga(p)}}),n=!0);null===g.asStripeClasses&&(p.asStripeClasses=[u.sStripeOdd,u.sStripeEven]);var e=p.asStripeClasses,x=q.children("tbody").find("tr").eq(0);-1!==h.inArray(!0,h.map(e,function(a){return x.hasClass(a)}))&&
(h("tbody tr",this).removeClass(e.join(" ")),p.asDestroyStripes=e.slice());e=[];t=this.getElementsByTagName("thead");0!==t.length&&(da(p.aoHeader,t[0]),e=ra(p));if(null===g.aoColumns){t=[];j=0;for(i=e.length;j<i;j++)t.push(null)}else t=g.aoColumns;j=0;for(i=t.length;j<i;j++)Da(p,e?e[j]:null);hb(p,g.aoColumnDefs,t,function(a,b){ja(p,a,b)});if(x.length){var w=function(a,b){return a.getAttribute("data-"+b)!==null?b:null};h(x[0]).children("th, td").each(function(a,b){var c=p.aoColumns[a];if(c.mData===
a){var d=w(b,"sort")||w(b,"order"),e=w(b,"filter")||w(b,"search");if(d!==null||e!==null){c.mData={_:a+".display",sort:d!==null?a+".@data-"+d:k,type:d!==null?a+".@data-"+d:k,filter:e!==null?a+".@data-"+e:k};ja(p,a)}}})}var T=p.oFeatures,e=function(){if(g.aaSorting===k){var a=p.aaSorting;j=0;for(i=a.length;j<i;j++)a[j][1]=p.aoColumns[j].asSorting[0]}wa(p);T.bSort&&z(p,"aoDrawCallback",function(){if(p.bSorted){var a=V(p),b={};h.each(a,function(a,c){b[c.src]=c.dir});r(p,null,"order",[p,a,b]);Hb(p)}});
z(p,"aoDrawCallback",function(){(p.bSorted||y(p)==="ssp"||T.bDeferRender)&&wa(p)},"sc");var a=q.children("caption").each(function(){this._captionSide=h(this).css("caption-side")}),b=q.children("thead");b.length===0&&(b=h("<thead/>").appendTo(q));p.nTHead=b[0];b=q.children("tbody");b.length===0&&(b=h("<tbody/>").appendTo(q));p.nTBody=b[0];b=q.children("tfoot");if(b.length===0&&a.length>0&&(p.oScroll.sX!==""||p.oScroll.sY!==""))b=h("<tfoot/>").appendTo(q);if(b.length===0||b.children().length===0)q.addClass(u.sNoFooter);
else if(b.length>0){p.nTFoot=b[0];da(p.aoFooter,p.nTFoot)}if(g.aaData)for(j=0;j<g.aaData.length;j++)M(p,g.aaData[j]);else(p.bDeferLoading||y(p)=="dom")&&ma(p,h(p.nTBody).children("tr"));p.aiDisplay=p.aiDisplayMaster.slice();p.bInitialised=true;n===false&&ga(p)};g.bStateSave?(T.bStateSave=!0,z(p,"aoDrawCallback",xa,"state_save"),Ib(p,g,e)):e()}});b=null;return this},x,s,o,u,Xa={},Mb=/[\r\n]/g,Aa=/<.*?>/g,Zb=/^\d{2,4}[\.\/\-]\d{1,2}[\.\/\-]\d{1,2}([T ]{1}\d{1,2}[:\.]\d{2}([\.:]\d{2})?)?$/,$b=RegExp("(\\/|\\.|\\*|\\+|\\?|\\||\\(|\\)|\\[|\\]|\\{|\\}|\\\\|\\$|\\^|\\-)",
"g"),Wa=/[',$£€¥%\u2009\u202F\u20BD\u20a9\u20BArfk]/gi,L=function(a){return!a||!0===a||"-"===a?!0:!1},Nb=function(a){var b=parseInt(a,10);return!isNaN(b)&&isFinite(a)?b:null},Ob=function(a,b){Xa[b]||(Xa[b]=RegExp(Pa(b),"g"));return"string"===typeof a&&"."!==b?a.replace(/\./g,"").replace(Xa[b],"."):a},Ya=function(a,b,c){var d="string"===typeof a;if(L(a))return!0;b&&d&&(a=Ob(a,b));c&&d&&(a=a.replace(Wa,""));return!isNaN(parseFloat(a))&&isFinite(a)},Pb=function(a,b,c){return L(a)?!0:!(L(a)||"string"===
typeof a)?null:Ya(a.replace(Aa,""),b,c)?!0:null},D=function(a,b,c){var d=[],e=0,f=a.length;if(c!==k)for(;e<f;e++)a[e]&&a[e][b]&&d.push(a[e][b][c]);else for(;e<f;e++)a[e]&&d.push(a[e][b]);return d},ia=function(a,b,c,d){var e=[],f=0,g=b.length;if(d!==k)for(;f<g;f++)a[b[f]][c]&&e.push(a[b[f]][c][d]);else for(;f<g;f++)e.push(a[b[f]][c]);return e},W=function(a,b){var c=[],d;b===k?(b=0,d=a):(d=b,b=a);for(var e=b;e<d;e++)c.push(e);return c},Qb=function(a){for(var b=[],c=0,d=a.length;c<d;c++)a[c]&&b.push(a[c]);
return b},qa=function(a){var b;a:{if(!(2>a.length)){b=a.slice().sort();for(var c=b[0],d=1,e=b.length;d<e;d++){if(b[d]===c){b=!1;break a}c=b[d]}}b=!0}if(b)return a.slice();b=[];var e=a.length,f,g=0,d=0;a:for(;d<e;d++){c=a[d];for(f=0;f<g;f++)if(b[f]===c)continue a;b.push(c);g++}return b};m.util={throttle:function(a,b){var c=b!==k?b:200,d,e;return function(){var b=this,g=+new Date,j=arguments;d&&g<d+c?(clearTimeout(e),e=setTimeout(function(){d=k;a.apply(b,j)},c)):(d=g,a.apply(b,j))}},escapeRegex:function(a){return a.replace($b,
"\\$1")}};var A=function(a,b,c){a[b]!==k&&(a[c]=a[b])},ba=/\[.*?\]$/,U=/\(\)$/,Pa=m.util.escapeRegex,va=h("<div>")[0],Wb=va.textContent!==k,Yb=/<.*?>/g,Na=m.util.throttle,Rb=[],w=Array.prototype,ac=function(a){var b,c,d=m.settings,e=h.map(d,function(a){return a.nTable});if(a){if(a.nTable&&a.oApi)return[a];if(a.nodeName&&"table"===a.nodeName.toLowerCase())return b=h.inArray(a,e),-1!==b?[d[b]]:null;if(a&&"function"===typeof a.settings)return a.settings().toArray();"string"===typeof a?c=h(a):a instanceof
h&&(c=a)}else return[];if(c)return c.map(function(){b=h.inArray(this,e);return-1!==b?d[b]:null}).toArray()};s=function(a,b){if(!(this instanceof s))return new s(a,b);var c=[],d=function(a){(a=ac(a))&&(c=c.concat(a))};if(h.isArray(a))for(var e=0,f=a.length;e<f;e++)d(a[e]);else d(a);this.context=qa(c);b&&h.merge(this,b);this.selector={rows:null,cols:null,opts:null};s.extend(this,this,Rb)};m.Api=s;h.extend(s.prototype,{any:function(){return 0!==this.count()},concat:w.concat,context:[],count:function(){return this.flatten().length},
each:function(a){for(var b=0,c=this.length;b<c;b++)a.call(this,this[b],b,this);return this},eq:function(a){var b=this.context;return b.length>a?new s(b[a],this[a]):null},filter:function(a){var b=[];if(w.filter)b=w.filter.call(this,a,this);else for(var c=0,d=this.length;c<d;c++)a.call(this,this[c],c,this)&&b.push(this[c]);return new s(this.context,b)},flatten:function(){var a=[];return new s(this.context,a.concat.apply(a,this.toArray()))},join:w.join,indexOf:w.indexOf||function(a,b){for(var c=b||0,
d=this.length;c<d;c++)if(this[c]===a)return c;return-1},iterator:function(a,b,c,d){var e=[],f,g,j,h,n,l=this.context,m,o,u=this.selector;"string"===typeof a&&(d=c,c=b,b=a,a=!1);g=0;for(j=l.length;g<j;g++){var r=new s(l[g]);if("table"===b)f=c.call(r,l[g],g),f!==k&&e.push(f);else if("columns"===b||"rows"===b)f=c.call(r,l[g],this[g],g),f!==k&&e.push(f);else if("column"===b||"column-rows"===b||"row"===b||"cell"===b){o=this[g];"column-rows"===b&&(m=Ba(l[g],u.opts));h=0;for(n=o.length;h<n;h++)f=o[h],f=
"cell"===b?c.call(r,l[g],f.row,f.column,g,h):c.call(r,l[g],f,g,h,m),f!==k&&e.push(f)}}return e.length||d?(a=new s(l,a?e.concat.apply([],e):e),b=a.selector,b.rows=u.rows,b.cols=u.cols,b.opts=u.opts,a):this},lastIndexOf:w.lastIndexOf||function(a,b){return this.indexOf.apply(this.toArray.reverse(),arguments)},length:0,map:function(a){var b=[];if(w.map)b=w.map.call(this,a,this);else for(var c=0,d=this.length;c<d;c++)b.push(a.call(this,this[c],c));return new s(this.context,b)},pluck:function(a){return this.map(function(b){return b[a]})},
pop:w.pop,push:w.push,reduce:w.reduce||function(a,b){return gb(this,a,b,0,this.length,1)},reduceRight:w.reduceRight||function(a,b){return gb(this,a,b,this.length-1,-1,-1)},reverse:w.reverse,selector:null,shift:w.shift,slice:function(){return new s(this.context,this)},sort:w.sort,splice:w.splice,toArray:function(){return w.slice.call(this)},to$:function(){return h(this)},toJQuery:function(){return h(this)},unique:function(){return new s(this.context,qa(this))},unshift:w.unshift});s.extend=function(a,
b,c){if(c.length&&b&&(b instanceof s||b.__dt_wrapper)){var d,e,f,g=function(a,b,c){return function(){var d=b.apply(a,arguments);s.extend(d,d,c.methodExt);return d}};d=0;for(e=c.length;d<e;d++)f=c[d],b[f.name]="function"===typeof f.val?g(a,f.val,f):h.isPlainObject(f.val)?{}:f.val,b[f.name].__dt_wrapper=!0,s.extend(a,b[f.name],f.propExt)}};s.register=o=function(a,b){if(h.isArray(a))for(var c=0,d=a.length;c<d;c++)s.register(a[c],b);else for(var e=a.split("."),f=Rb,g,j,c=0,d=e.length;c<d;c++){g=(j=-1!==
e[c].indexOf("()"))?e[c].replace("()",""):e[c];var i;a:{i=0;for(var n=f.length;i<n;i++)if(f[i].name===g){i=f[i];break a}i=null}i||(i={name:g,val:{},methodExt:[],propExt:[]},f.push(i));c===d-1?i.val=b:f=j?i.methodExt:i.propExt}};s.registerPlural=u=function(a,b,c){s.register(a,c);s.register(b,function(){var a=c.apply(this,arguments);return a===this?this:a instanceof s?a.length?h.isArray(a[0])?new s(a.context,a[0]):a[0]:k:a})};o("tables()",function(a){var b;if(a){b=s;var c=this.context;if("number"===
typeof a)a=[c[a]];else var d=h.map(c,function(a){return a.nTable}),a=h(d).filter(a).map(function(){var a=h.inArray(this,d);return c[a]}).toArray();b=new b(a)}else b=this;return b});o("table()",function(a){var a=this.tables(a),b=a.context;return b.length?new s(b[0]):a});u("tables().nodes()","table().node()",function(){return this.iterator("table",function(a){return a.nTable},1)});u("tables().body()","table().body()",function(){return this.iterator("table",function(a){return a.nTBody},1)});u("tables().header()",
"table().header()",function(){return this.iterator("table",function(a){return a.nTHead},1)});u("tables().footer()","table().footer()",function(){return this.iterator("table",function(a){return a.nTFoot},1)});u("tables().containers()","table().container()",function(){return this.iterator("table",function(a){return a.nTableWrapper},1)});o("draw()",function(a){return this.iterator("table",function(b){"page"===a?N(b):("string"===typeof a&&(a="full-hold"===a?!1:!0),S(b,!1===a))})});o("page()",function(a){return a===
k?this.page.info().page:this.iterator("table",function(b){Sa(b,a)})});o("page.info()",function(){if(0===this.context.length)return k;var a=this.context[0],b=a._iDisplayStart,c=a.oFeatures.bPaginate?a._iDisplayLength:-1,d=a.fnRecordsDisplay(),e=-1===c;return{page:e?0:Math.floor(b/c),pages:e?1:Math.ceil(d/c),start:b,end:a.fnDisplayEnd(),length:c,recordsTotal:a.fnRecordsTotal(),recordsDisplay:d,serverSide:"ssp"===y(a)}});o("page.len()",function(a){return a===k?0!==this.context.length?this.context[0]._iDisplayLength:
k:this.iterator("table",function(b){Qa(b,a)})});var Sb=function(a,b,c){if(c){var d=new s(a);d.one("draw",function(){c(d.ajax.json())})}if("ssp"==y(a))S(a,b);else{C(a,!0);var e=a.jqXHR;e&&4!==e.readyState&&e.abort();sa(a,[],function(c){na(a);for(var c=ta(a,c),d=0,e=c.length;d<e;d++)M(a,c[d]);S(a,b);C(a,!1)})}};o("ajax.json()",function(){var a=this.context;if(0<a.length)return a[0].json});o("ajax.params()",function(){var a=this.context;if(0<a.length)return a[0].oAjaxData});o("ajax.reload()",function(a,
b){return this.iterator("table",function(c){Sb(c,!1===b,a)})});o("ajax.url()",function(a){var b=this.context;if(a===k){if(0===b.length)return k;b=b[0];return b.ajax?h.isPlainObject(b.ajax)?b.ajax.url:b.ajax:b.sAjaxSource}return this.iterator("table",function(b){h.isPlainObject(b.ajax)?b.ajax.url=a:b.ajax=a})});o("ajax.url().load()",function(a,b){return this.iterator("table",function(c){Sb(c,!1===b,a)})});var Za=function(a,b,c,d,e){var f=[],g,j,i,n,l,m;i=typeof b;if(!b||"string"===i||"function"===
i||b.length===k)b=[b];i=0;for(n=b.length;i<n;i++){j=b[i]&&b[i].split&&!b[i].match(/[\[\(:]/)?b[i].split(","):[b[i]];l=0;for(m=j.length;l<m;l++)(g=c("string"===typeof j[l]?h.trim(j[l]):j[l]))&&g.length&&(f=f.concat(g))}a=x.selector[a];if(a.length){i=0;for(n=a.length;i<n;i++)f=a[i](d,e,f)}return qa(f)},$a=function(a){a||(a={});a.filter&&a.search===k&&(a.search=a.filter);return h.extend({search:"none",order:"current",page:"all"},a)},ab=function(a){for(var b=0,c=a.length;b<c;b++)if(0<a[b].length)return a[0]=
a[b],a[0].length=1,a.length=1,a.context=[a.context[b]],a;a.length=0;return a},Ba=function(a,b){var c,d,e,f=[],g=a.aiDisplay;c=a.aiDisplayMaster;var j=b.search;d=b.order;e=b.page;if("ssp"==y(a))return"removed"===j?[]:W(0,c.length);if("current"==e){c=a._iDisplayStart;for(d=a.fnDisplayEnd();c<d;c++)f.push(g[c])}else if("current"==d||"applied"==d)f="none"==j?c.slice():"applied"==j?g.slice():h.map(c,function(a){return-1===h.inArray(a,g)?a:null});else if("index"==d||"original"==d){c=0;for(d=a.aoData.length;c<
d;c++)"none"==j?f.push(c):(e=h.inArray(c,g),(-1===e&&"removed"==j||0<=e&&"applied"==j)&&f.push(c))}return f};o("rows()",function(a,b){a===k?a="":h.isPlainObject(a)&&(b=a,a="");var b=$a(b),c=this.iterator("table",function(c){var e=b,f;return Za("row",a,function(a){var b=Nb(a);if(b!==null&&!e)return[b];f||(f=Ba(c,e));if(b!==null&&h.inArray(b,f)!==-1)return[b];if(a===null||a===k||a==="")return f;if(typeof a==="function")return h.map(f,function(b){var e=c.aoData[b];return a(b,e._aData,e.nTr)?b:null});
b=Qb(ia(c.aoData,f,"nTr"));if(a.nodeName){if(a._DT_RowIndex!==k)return[a._DT_RowIndex];if(a._DT_CellIndex)return[a._DT_CellIndex.row];b=h(a).closest("*[data-dt-row]");return b.length?[b.data("dt-row")]:[]}if(typeof a==="string"&&a.charAt(0)==="#"){var i=c.aIds[a.replace(/^#/,"")];if(i!==k)return[i.idx]}return h(b).filter(a).map(function(){return this._DT_RowIndex}).toArray()},c,e)},1);c.selector.rows=a;c.selector.opts=b;return c});o("rows().nodes()",function(){return this.iterator("row",function(a,
b){return a.aoData[b].nTr||k},1)});o("rows().data()",function(){return this.iterator(!0,"rows",function(a,b){return ia(a.aoData,b,"_aData")},1)});u("rows().cache()","row().cache()",function(a){return this.iterator("row",function(b,c){var d=b.aoData[c];return"search"===a?d._aFilterData:d._aSortData},1)});u("rows().invalidate()","row().invalidate()",function(a){return this.iterator("row",function(b,c){ca(b,c,a)})});u("rows().indexes()","row().index()",function(){return this.iterator("row",function(a,
b){return b},1)});u("rows().ids()","row().id()",function(a){for(var b=[],c=this.context,d=0,e=c.length;d<e;d++)for(var f=0,g=this[d].length;f<g;f++){var h=c[d].rowIdFn(c[d].aoData[this[d][f]]._aData);b.push((!0===a?"#":"")+h)}return new s(c,b)});u("rows().remove()","row().remove()",function(){var a=this;this.iterator("row",function(b,c,d){var e=b.aoData,f=e[c],g,h,i,n,l;e.splice(c,1);g=0;for(h=e.length;g<h;g++)if(i=e[g],l=i.anCells,null!==i.nTr&&(i.nTr._DT_RowIndex=g),null!==l){i=0;for(n=l.length;i<
n;i++)l[i]._DT_CellIndex.row=g}oa(b.aiDisplayMaster,c);oa(b.aiDisplay,c);oa(a[d],c,!1);0<b._iRecordsDisplay&&b._iRecordsDisplay--;Ra(b);c=b.rowIdFn(f._aData);c!==k&&delete b.aIds[c]});this.iterator("table",function(a){for(var c=0,d=a.aoData.length;c<d;c++)a.aoData[c].idx=c});return this});o("rows.add()",function(a){var b=this.iterator("table",function(b){var c,f,g,h=[];f=0;for(g=a.length;f<g;f++)c=a[f],c.nodeName&&"TR"===c.nodeName.toUpperCase()?h.push(ma(b,c)[0]):h.push(M(b,c));return h},1),c=this.rows(-1);
c.pop();h.merge(c,b);return c});o("row()",function(a,b){return ab(this.rows(a,b))});o("row().data()",function(a){var b=this.context;if(a===k)return b.length&&this.length?b[0].aoData[this[0]]._aData:k;b[0].aoData[this[0]]._aData=a;ca(b[0],this[0],"data");return this});o("row().node()",function(){var a=this.context;return a.length&&this.length?a[0].aoData[this[0]].nTr||null:null});o("row.add()",function(a){a instanceof h&&a.length&&(a=a[0]);var b=this.iterator("table",function(b){return a.nodeName&&
"TR"===a.nodeName.toUpperCase()?ma(b,a)[0]:M(b,a)});return this.row(b[0])});var bb=function(a,b){var c=a.context;if(c.length&&(c=c[0].aoData[b!==k?b:a[0]])&&c._details)c._details.remove(),c._detailsShow=k,c._details=k},Tb=function(a,b){var c=a.context;if(c.length&&a.length){var d=c[0].aoData[a[0]];if(d._details){(d._detailsShow=b)?d._details.insertAfter(d.nTr):d._details.detach();var e=c[0],f=new s(e),g=e.aoData;f.off("draw.dt.DT_details column-visibility.dt.DT_details destroy.dt.DT_details");0<D(g,
"_details").length&&(f.on("draw.dt.DT_details",function(a,b){e===b&&f.rows({page:"current"}).eq(0).each(function(a){a=g[a];a._detailsShow&&a._details.insertAfter(a.nTr)})}),f.on("column-visibility.dt.DT_details",function(a,b){if(e===b)for(var c,d=aa(b),f=0,h=g.length;f<h;f++)c=g[f],c._details&&c._details.children("td[colspan]").attr("colspan",d)}),f.on("destroy.dt.DT_details",function(a,b){if(e===b)for(var c=0,d=g.length;c<d;c++)g[c]._details&&bb(f,c)}))}}};o("row().child()",function(a,b){var c=this.context;
if(a===k)return c.length&&this.length?c[0].aoData[this[0]]._details:k;if(!0===a)this.child.show();else if(!1===a)bb(this);else if(c.length&&this.length){var d=c[0],c=c[0].aoData[this[0]],e=[],f=function(a,b){if(h.isArray(a)||a instanceof h)for(var c=0,k=a.length;c<k;c++)f(a[c],b);else a.nodeName&&"tr"===a.nodeName.toLowerCase()?e.push(a):(c=h("<tr><td/></tr>").addClass(b),h("td",c).addClass(b).html(a)[0].colSpan=aa(d),e.push(c[0]))};f(a,b);c._details&&c._details.detach();c._details=h(e);c._detailsShow&&
c._details.insertAfter(c.nTr)}return this});o(["row().child.show()","row().child().show()"],function(){Tb(this,!0);return this});o(["row().child.hide()","row().child().hide()"],function(){Tb(this,!1);return this});o(["row().child.remove()","row().child().remove()"],function(){bb(this);return this});o("row().child.isShown()",function(){var a=this.context;return a.length&&this.length?a[0].aoData[this[0]]._detailsShow||!1:!1});var bc=/^([^:]+):(name|visIdx|visible)$/,Ub=function(a,b,c,d,e){for(var c=
[],d=0,f=e.length;d<f;d++)c.push(B(a,e[d],b));return c};o("columns()",function(a,b){a===k?a="":h.isPlainObject(a)&&(b=a,a="");var b=$a(b),c=this.iterator("table",function(c){var e=a,f=b,g=c.aoColumns,j=D(g,"sName"),i=D(g,"nTh");return Za("column",e,function(a){var b=Nb(a);if(a==="")return W(g.length);if(b!==null)return[b>=0?b:g.length+b];if(typeof a==="function"){var e=Ba(c,f);return h.map(g,function(b,f){return a(f,Ub(c,f,0,0,e),i[f])?f:null})}var k=typeof a==="string"?a.match(bc):"";if(k)switch(k[2]){case "visIdx":case "visible":b=
parseInt(k[1],10);if(b<0){var m=h.map(g,function(a,b){return a.bVisible?b:null});return[m[m.length+b]]}return[Z(c,b)];case "name":return h.map(j,function(a,b){return a===k[1]?b:null});default:return[]}if(a.nodeName&&a._DT_CellIndex)return[a._DT_CellIndex.column];b=h(i).filter(a).map(function(){return h.inArray(this,i)}).toArray();if(b.length||!a.nodeName)return b;b=h(a).closest("*[data-dt-column]");return b.length?[b.data("dt-column")]:[]},c,f)},1);c.selector.cols=a;c.selector.opts=b;return c});u("columns().header()",
"column().header()",function(){return this.iterator("column",function(a,b){return a.aoColumns[b].nTh},1)});u("columns().footer()","column().footer()",function(){return this.iterator("column",function(a,b){return a.aoColumns[b].nTf},1)});u("columns().data()","column().data()",function(){return this.iterator("column-rows",Ub,1)});u("columns().dataSrc()","column().dataSrc()",function(){return this.iterator("column",function(a,b){return a.aoColumns[b].mData},1)});u("columns().cache()","column().cache()",
function(a){return this.iterator("column-rows",function(b,c,d,e,f){return ia(b.aoData,f,"search"===a?"_aFilterData":"_aSortData",c)},1)});u("columns().nodes()","column().nodes()",function(){return this.iterator("column-rows",function(a,b,c,d,e){return ia(a.aoData,e,"anCells",b)},1)});u("columns().visible()","column().visible()",function(a,b){var c=this.iterator("column",function(b,c){if(a===k)return b.aoColumns[c].bVisible;var f=b.aoColumns,g=f[c],j=b.aoData,i,n,l;if(a!==k&&g.bVisible!==a){if(a){var m=
h.inArray(!0,D(f,"bVisible"),c+1);i=0;for(n=j.length;i<n;i++)l=j[i].nTr,f=j[i].anCells,l&&l.insertBefore(f[c],f[m]||null)}else h(D(b.aoData,"anCells",c)).detach();g.bVisible=a;ea(b,b.aoHeader);ea(b,b.aoFooter);xa(b)}});a!==k&&(this.iterator("column",function(c,e){r(c,null,"column-visibility",[c,e,a,b])}),(b===k||b)&&this.columns.adjust());return c});u("columns().indexes()","column().index()",function(a){return this.iterator("column",function(b,c){return"visible"===a?$(b,c):c},1)});o("columns.adjust()",
function(){return this.iterator("table",function(a){Y(a)},1)});o("column.index()",function(a,b){if(0!==this.context.length){var c=this.context[0];if("fromVisible"===a||"toData"===a)return Z(c,b);if("fromData"===a||"toVisible"===a)return $(c,b)}});o("column()",function(a,b){return ab(this.columns(a,b))});o("cells()",function(a,b,c){h.isPlainObject(a)&&(a.row===k?(c=a,a=null):(c=b,b=null));h.isPlainObject(b)&&(c=b,b=null);if(null===b||b===k)return this.iterator("table",function(b){var d=a,e=$a(c),f=
b.aoData,g=Ba(b,e),j=Qb(ia(f,g,"anCells")),i=h([].concat.apply([],j)),l,n=b.aoColumns.length,m,o,u,s,r,v;return Za("cell",d,function(a){var c=typeof a==="function";if(a===null||a===k||c){m=[];o=0;for(u=g.length;o<u;o++){l=g[o];for(s=0;s<n;s++){r={row:l,column:s};if(c){v=f[l];a(r,B(b,l,s),v.anCells?v.anCells[s]:null)&&m.push(r)}else m.push(r)}}return m}if(h.isPlainObject(a))return[a];c=i.filter(a).map(function(a,b){return{row:b._DT_CellIndex.row,column:b._DT_CellIndex.column}}).toArray();if(c.length||
!a.nodeName)return c;v=h(a).closest("*[data-dt-row]");return v.length?[{row:v.data("dt-row"),column:v.data("dt-column")}]:[]},b,e)});var d=this.columns(b,c),e=this.rows(a,c),f,g,j,i,n,l=this.iterator("table",function(a,b){f=[];g=0;for(j=e[b].length;g<j;g++){i=0;for(n=d[b].length;i<n;i++)f.push({row:e[b][g],column:d[b][i]})}return f},1);h.extend(l.selector,{cols:b,rows:a,opts:c});return l});u("cells().nodes()","cell().node()",function(){return this.iterator("cell",function(a,b,c){return(a=a.aoData[b])&&
a.anCells?a.anCells[c]:k},1)});o("cells().data()",function(){return this.iterator("cell",function(a,b,c){return B(a,b,c)},1)});u("cells().cache()","cell().cache()",function(a){a="search"===a?"_aFilterData":"_aSortData";return this.iterator("cell",function(b,c,d){return b.aoData[c][a][d]},1)});u("cells().render()","cell().render()",function(a){return this.iterator("cell",function(b,c,d){return B(b,c,d,a)},1)});u("cells().indexes()","cell().index()",function(){return this.iterator("cell",function(a,
b,c){return{row:b,column:c,columnVisible:$(a,c)}},1)});u("cells().invalidate()","cell().invalidate()",function(a){return this.iterator("cell",function(b,c,d){ca(b,c,a,d)})});o("cell()",function(a,b,c){return ab(this.cells(a,b,c))});o("cell().data()",function(a){var b=this.context,c=this[0];if(a===k)return b.length&&c.length?B(b[0],c[0].row,c[0].column):k;ib(b[0],c[0].row,c[0].column,a);ca(b[0],c[0].row,"data",c[0].column);return this});o("order()",function(a,b){var c=this.context;if(a===k)return 0!==
c.length?c[0].aaSorting:k;"number"===typeof a?a=[[a,b]]:a.length&&!h.isArray(a[0])&&(a=Array.prototype.slice.call(arguments));return this.iterator("table",function(b){b.aaSorting=a.slice()})});o("order.listener()",function(a,b,c){return this.iterator("table",function(d){La(d,a,b,c)})});o("order.fixed()",function(a){if(!a){var b=this.context,b=b.length?b[0].aaSortingFixed:k;return h.isArray(b)?{pre:b}:b}return this.iterator("table",function(b){b.aaSortingFixed=h.extend(!0,{},a)})});o(["columns().order()",
"column().order()"],function(a){var b=this;return this.iterator("table",function(c,d){var e=[];h.each(b[d],function(b,c){e.push([c,a])});c.aaSorting=e})});o("search()",function(a,b,c,d){var e=this.context;return a===k?0!==e.length?e[0].oPreviousSearch.sSearch:k:this.iterator("table",function(e){e.oFeatures.bFilter&&fa(e,h.extend({},e.oPreviousSearch,{sSearch:a+"",bRegex:null===b?!1:b,bSmart:null===c?!0:c,bCaseInsensitive:null===d?!0:d}),1)})});u("columns().search()","column().search()",function(a,
b,c,d){return this.iterator("column",function(e,f){var g=e.aoPreSearchCols;if(a===k)return g[f].sSearch;e.oFeatures.bFilter&&(h.extend(g[f],{sSearch:a+"",bRegex:null===b?!1:b,bSmart:null===c?!0:c,bCaseInsensitive:null===d?!0:d}),fa(e,e.oPreviousSearch,1))})});o("state()",function(){return this.context.length?this.context[0].oSavedState:null});o("state.clear()",function(){return this.iterator("table",function(a){a.fnStateSaveCallback.call(a.oInstance,a,{})})});o("state.loaded()",function(){return this.context.length?
this.context[0].oLoadedState:null});o("state.save()",function(){return this.iterator("table",function(a){xa(a)})});m.versionCheck=m.fnVersionCheck=function(a){for(var b=m.version.split("."),a=a.split("."),c,d,e=0,f=a.length;e<f;e++)if(c=parseInt(b[e],10)||0,d=parseInt(a[e],10)||0,c!==d)return c>d;return!0};m.isDataTable=m.fnIsDataTable=function(a){var b=h(a).get(0),c=!1;if(a instanceof m.Api)return!0;h.each(m.settings,function(a,e){var f=e.nScrollHead?h("table",e.nScrollHead)[0]:null,g=e.nScrollFoot?
h("table",e.nScrollFoot)[0]:null;if(e.nTable===b||f===b||g===b)c=!0});return c};m.tables=m.fnTables=function(a){var b=!1;h.isPlainObject(a)&&(b=a.api,a=a.visible);var c=h.map(m.settings,function(b){if(!a||a&&h(b.nTable).is(":visible"))return b.nTable});return b?new s(c):c};m.camelToHungarian=I;o("$()",function(a,b){var c=this.rows(b).nodes(),c=h(c);return h([].concat(c.filter(a).toArray(),c.find(a).toArray()))});h.each(["on","one","off"],function(a,b){o(b+"()",function(){var a=Array.prototype.slice.call(arguments);
a[0]=h.map(a[0].split(/\s/),function(a){return!a.match(/\.dt\b/)?a+".dt":a}).join(" ");var d=h(this.tables().nodes());d[b].apply(d,a);return this})});o("clear()",function(){return this.iterator("table",function(a){na(a)})});o("settings()",function(){return new s(this.context,this.context)});o("init()",function(){var a=this.context;return a.length?a[0].oInit:null});o("data()",function(){return this.iterator("table",function(a){return D(a.aoData,"_aData")}).flatten()});o("destroy()",function(a){a=a||
!1;return this.iterator("table",function(b){var c=b.nTableWrapper.parentNode,d=b.oClasses,e=b.nTable,f=b.nTBody,g=b.nTHead,j=b.nTFoot,i=h(e),f=h(f),k=h(b.nTableWrapper),l=h.map(b.aoData,function(a){return a.nTr}),o;b.bDestroying=!0;r(b,"aoDestroyCallback","destroy",[b]);a||(new s(b)).columns().visible(!0);k.off(".DT").find(":not(tbody *)").off(".DT");h(E).off(".DT-"+b.sInstance);e!=g.parentNode&&(i.children("thead").detach(),i.append(g));j&&e!=j.parentNode&&(i.children("tfoot").detach(),i.append(j));
b.aaSorting=[];b.aaSortingFixed=[];wa(b);h(l).removeClass(b.asStripeClasses.join(" "));h("th, td",g).removeClass(d.sSortable+" "+d.sSortableAsc+" "+d.sSortableDesc+" "+d.sSortableNone);f.children().detach();f.append(l);g=a?"remove":"detach";i[g]();k[g]();!a&&c&&(c.insertBefore(e,b.nTableReinsertBefore),i.css("width",b.sDestroyWidth).removeClass(d.sTable),(o=b.asDestroyStripes.length)&&f.children().each(function(a){h(this).addClass(b.asDestroyStripes[a%o])}));c=h.inArray(b,m.settings);-1!==c&&m.settings.splice(c,
1)})});h.each(["column","row","cell"],function(a,b){o(b+"s().every()",function(a){var d=this.selector.opts,e=this;return this.iterator(b,function(f,g,h,i,n){a.call(e[b](g,"cell"===b?h:d,"cell"===b?d:k),g,h,i,n)})})});o("i18n()",function(a,b,c){var d=this.context[0],a=Q(a)(d.oLanguage);a===k&&(a=b);c!==k&&h.isPlainObject(a)&&(a=a[c]!==k?a[c]:a._);return a.replace("%d",c)});m.version="1.10.16";m.settings=[];m.models={};m.models.oSearch={bCaseInsensitive:!0,sSearch:"",bRegex:!1,bSmart:!0};m.models.oRow=
{nTr:null,anCells:null,_aData:[],_aSortData:null,_aFilterData:null,_sFilterRow:null,_sRowStripe:"",src:null,idx:-1};m.models.oColumn={idx:null,aDataSort:null,asSorting:null,bSearchable:null,bSortable:null,bVisible:null,_sManualType:null,_bAttrSrc:!1,fnCreatedCell:null,fnGetData:null,fnSetData:null,mData:null,mRender:null,nTh:null,nTf:null,sClass:null,sContentPadding:null,sDefaultContent:null,sName:null,sSortDataType:"std",sSortingClass:null,sSortingClassJUI:null,sTitle:null,sType:null,sWidth:null,
sWidthOrig:null};m.defaults={aaData:null,aaSorting:[[0,"asc"]],aaSortingFixed:[],ajax:null,aLengthMenu:[10,25,50,100],aoColumns:null,aoColumnDefs:null,aoSearchCols:[],asStripeClasses:null,bAutoWidth:!0,bDeferRender:!1,bDestroy:!1,bFilter:!0,bInfo:!0,bLengthChange:!0,bPaginate:!0,bProcessing:!1,bRetrieve:!1,bScrollCollapse:!1,bServerSide:!1,bSort:!0,bSortMulti:!0,bSortCellsTop:!1,bSortClasses:!0,bStateSave:!1,fnCreatedRow:null,fnDrawCallback:null,fnFooterCallback:null,fnFormatNumber:function(a){return a.toString().replace(/\B(?=(\d{3})+(?!\d))/g,
this.oLanguage.sThousands)},fnHeaderCallback:null,fnInfoCallback:null,fnInitComplete:null,fnPreDrawCallback:null,fnRowCallback:null,fnServerData:null,fnServerParams:null,fnStateLoadCallback:function(a){try{return JSON.parse((-1===a.iStateDuration?sessionStorage:localStorage).getItem("DataTables_"+a.sInstance+"_"+location.pathname))}catch(b){}},fnStateLoadParams:null,fnStateLoaded:null,fnStateSaveCallback:function(a,b){try{(-1===a.iStateDuration?sessionStorage:localStorage).setItem("DataTables_"+a.sInstance+
"_"+location.pathname,JSON.stringify(b))}catch(c){}},fnStateSaveParams:null,iStateDuration:7200,iDeferLoading:null,iDisplayLength:10,iDisplayStart:0,iTabIndex:0,oClasses:{},oLanguage:{oAria:{sSortAscending:": activate to sort column ascending",sSortDescending:": activate to sort column descending"},oPaginate:{sFirst:"First",sLast:"Last",sNext:"Next",sPrevious:"Previous"},sEmptyTable:"No data available in table",sInfo:"Showing _START_ to _END_ of _TOTAL_ entries",sInfoEmpty:"Showing 0 to 0 of 0 entries",
sInfoFiltered:"(filtered from _MAX_ total entries)",sInfoPostFix:"",sDecimal:"",sThousands:",",sLengthMenu:"Show _MENU_ entries",sLoadingRecords:"Loading...",sProcessing:"Processing...",sSearch:"Search:",sSearchPlaceholder:"",sUrl:"",sZeroRecords:"No matching records found"},oSearch:h.extend({},m.models.oSearch),sAjaxDataProp:"data",sAjaxSource:null,sDom:"lfrtip",searchDelay:null,sPaginationType:"simple_numbers",sScrollX:"",sScrollXInner:"",sScrollY:"",sServerMethod:"GET",renderer:null,rowId:"DT_RowId"};
X(m.defaults);m.defaults.column={aDataSort:null,iDataSort:-1,asSorting:["asc","desc"],bSearchable:!0,bSortable:!0,bVisible:!0,fnCreatedCell:null,mData:null,mRender:null,sCellType:"td",sClass:"",sContentPadding:"",sDefaultContent:null,sName:"",sSortDataType:"std",sTitle:null,sType:null,sWidth:null};X(m.defaults.column);m.models.oSettings={oFeatures:{bAutoWidth:null,bDeferRender:null,bFilter:null,bInfo:null,bLengthChange:null,bPaginate:null,bProcessing:null,bServerSide:null,bSort:null,bSortMulti:null,
bSortClasses:null,bStateSave:null},oScroll:{bCollapse:null,iBarWidth:0,sX:null,sXInner:null,sY:null},oLanguage:{fnInfoCallback:null},oBrowser:{bScrollOversize:!1,bScrollbarLeft:!1,bBounding:!1,barWidth:0},ajax:null,aanFeatures:[],aoData:[],aiDisplay:[],aiDisplayMaster:[],aIds:{},aoColumns:[],aoHeader:[],aoFooter:[],oPreviousSearch:{},aoPreSearchCols:[],aaSorting:null,aaSortingFixed:[],asStripeClasses:null,asDestroyStripes:[],sDestroyWidth:0,aoRowCallback:[],aoHeaderCallback:[],aoFooterCallback:[],
aoDrawCallback:[],aoRowCreatedCallback:[],aoPreDrawCallback:[],aoInitComplete:[],aoStateSaveParams:[],aoStateLoadParams:[],aoStateLoaded:[],sTableId:"",nTable:null,nTHead:null,nTFoot:null,nTBody:null,nTableWrapper:null,bDeferLoading:!1,bInitialised:!1,aoOpenRows:[],sDom:null,searchDelay:null,sPaginationType:"two_button",iStateDuration:0,aoStateSave:[],aoStateLoad:[],oSavedState:null,oLoadedState:null,sAjaxSource:null,sAjaxDataProp:null,bAjaxDataGet:!0,jqXHR:null,json:k,oAjaxData:k,fnServerData:null,
aoServerParams:[],sServerMethod:null,fnFormatNumber:null,aLengthMenu:null,iDraw:0,bDrawing:!1,iDrawError:-1,_iDisplayLength:10,_iDisplayStart:0,_iRecordsTotal:0,_iRecordsDisplay:0,oClasses:{},bFiltered:!1,bSorted:!1,bSortCellsTop:null,oInit:null,aoDestroyCallback:[],fnRecordsTotal:function(){return"ssp"==y(this)?1*this._iRecordsTotal:this.aiDisplayMaster.length},fnRecordsDisplay:function(){return"ssp"==y(this)?1*this._iRecordsDisplay:this.aiDisplay.length},fnDisplayEnd:function(){var a=this._iDisplayLength,
b=this._iDisplayStart,c=b+a,d=this.aiDisplay.length,e=this.oFeatures,f=e.bPaginate;return e.bServerSide?!1===f||-1===a?b+d:Math.min(b+a,this._iRecordsDisplay):!f||c>d||-1===a?d:c},oInstance:null,sInstance:null,iTabIndex:0,nScrollHead:null,nScrollFoot:null,aLastSort:[],oPlugins:{},rowIdFn:null,rowId:null};m.ext=x={buttons:{},classes:{},builder:"-source-",errMode:"alert",feature:[],search:[],selector:{cell:[],column:[],row:[]},internal:{},legacy:{ajax:null},pager:{},renderer:{pageButton:{},header:{}},
order:{},type:{detect:[],search:{},order:{}},_unique:0,fnVersionCheck:m.fnVersionCheck,iApiIndex:0,oJUIClasses:{},sVersion:m.version};h.extend(x,{afnFiltering:x.search,aTypes:x.type.detect,ofnSearch:x.type.search,oSort:x.type.order,afnSortData:x.order,aoFeatures:x.feature,oApi:x.internal,oStdClasses:x.classes,oPagination:x.pager});h.extend(m.ext.classes,{sTable:"dataTable",sNoFooter:"no-footer",sPageButton:"paginate_button",sPageButtonActive:"current",sPageButtonDisabled:"disabled",sStripeOdd:"odd",
sStripeEven:"even",sRowEmpty:"dataTables_empty",sWrapper:"dataTables_wrapper",sFilter:"dataTables_filter",sInfo:"dataTables_info",sPaging:"dataTables_paginate paging_",sLength:"dataTables_length",sProcessing:"dataTables_processing",sSortAsc:"sorting_asc",sSortDesc:"sorting_desc",sSortable:"sorting",sSortableAsc:"sorting_asc_disabled",sSortableDesc:"sorting_desc_disabled",sSortableNone:"sorting_disabled",sSortColumn:"sorting_",sFilterInput:"",sLengthSelect:"",sScrollWrapper:"dataTables_scroll",sScrollHead:"dataTables_scrollHead",
sScrollHeadInner:"dataTables_scrollHeadInner",sScrollBody:"dataTables_scrollBody",sScrollFoot:"dataTables_scrollFoot",sScrollFootInner:"dataTables_scrollFootInner",sHeaderTH:"",sFooterTH:"",sSortJUIAsc:"",sSortJUIDesc:"",sSortJUI:"",sSortJUIAscAllowed:"",sSortJUIDescAllowed:"",sSortJUIWrapper:"",sSortIcon:"",sJUIHeader:"",sJUIFooter:""});var Kb=m.ext.pager;h.extend(Kb,{simple:function(){return["previous","next"]},full:function(){return["first","previous","next","last"]},numbers:function(a,b){return[ha(a,
b)]},simple_numbers:function(a,b){return["previous",ha(a,b),"next"]},full_numbers:function(a,b){return["first","previous",ha(a,b),"next","last"]},first_last_numbers:function(a,b){return["first",ha(a,b),"last"]},_numbers:ha,numbers_length:7});h.extend(!0,m.ext.renderer,{pageButton:{_:function(a,b,c,d,e,f){var g=a.oClasses,j=a.oLanguage.oPaginate,i=a.oLanguage.oAria.paginate||{},n,l,m=0,o=function(b,d){var k,s,u,r,v=function(b){Sa(a,b.data.action,true)};k=0;for(s=d.length;k<s;k++){r=d[k];if(h.isArray(r)){u=
h("<"+(r.DT_el||"div")+"/>").appendTo(b);o(u,r)}else{n=null;l="";switch(r){case "ellipsis":b.append('<span class="ellipsis">&#x2026;</span>');break;case "first":n=j.sFirst;l=r+(e>0?"":" "+g.sPageButtonDisabled);break;case "previous":n=j.sPrevious;l=r+(e>0?"":" "+g.sPageButtonDisabled);break;case "next":n=j.sNext;l=r+(e<f-1?"":" "+g.sPageButtonDisabled);break;case "last":n=j.sLast;l=r+(e<f-1?"":" "+g.sPageButtonDisabled);break;default:n=r+1;l=e===r?g.sPageButtonActive:""}if(n!==null){u=h("<a>",{"class":g.sPageButton+
" "+l,"aria-controls":a.sTableId,"aria-label":i[r],"data-dt-idx":m,tabindex:a.iTabIndex,id:c===0&&typeof r==="string"?a.sTableId+"_"+r:null}).html(n).appendTo(b);Va(u,{action:r},v);m++}}}},s;try{s=h(b).find(G.activeElement).data("dt-idx")}catch(u){}o(h(b).empty(),d);s!==k&&h(b).find("[data-dt-idx="+s+"]").focus()}}});h.extend(m.ext.type.detect,[function(a,b){var c=b.oLanguage.sDecimal;return Ya(a,c)?"num"+c:null},function(a){if(a&&!(a instanceof Date)&&!Zb.test(a))return null;var b=Date.parse(a);
return null!==b&&!isNaN(b)||L(a)?"date":null},function(a,b){var c=b.oLanguage.sDecimal;return Ya(a,c,!0)?"num-fmt"+c:null},function(a,b){var c=b.oLanguage.sDecimal;return Pb(a,c)?"html-num"+c:null},function(a,b){var c=b.oLanguage.sDecimal;return Pb(a,c,!0)?"html-num-fmt"+c:null},function(a){return L(a)||"string"===typeof a&&-1!==a.indexOf("<")?"html":null}]);h.extend(m.ext.type.search,{html:function(a){return L(a)?a:"string"===typeof a?a.replace(Mb," ").replace(Aa,""):""},string:function(a){return L(a)?
a:"string"===typeof a?a.replace(Mb," "):a}});var za=function(a,b,c,d){if(0!==a&&(!a||"-"===a))return-Infinity;b&&(a=Ob(a,b));a.replace&&(c&&(a=a.replace(c,"")),d&&(a=a.replace(d,"")));return 1*a};h.extend(x.type.order,{"date-pre":function(a){return Date.parse(a)||-Infinity},"html-pre":function(a){return L(a)?"":a.replace?a.replace(/<.*?>/g,"").toLowerCase():a+""},"string-pre":function(a){return L(a)?"":"string"===typeof a?a.toLowerCase():!a.toString?"":a.toString()},"string-asc":function(a,b){return a<
b?-1:a>b?1:0},"string-desc":function(a,b){return a<b?1:a>b?-1:0}});cb("");h.extend(!0,m.ext.renderer,{header:{_:function(a,b,c,d){h(a.nTable).on("order.dt.DT",function(e,f,g,h){if(a===f){e=c.idx;b.removeClass(c.sSortingClass+" "+d.sSortAsc+" "+d.sSortDesc).addClass(h[e]=="asc"?d.sSortAsc:h[e]=="desc"?d.sSortDesc:c.sSortingClass)}})},jqueryui:function(a,b,c,d){h("<div/>").addClass(d.sSortJUIWrapper).append(b.contents()).append(h("<span/>").addClass(d.sSortIcon+" "+c.sSortingClassJUI)).appendTo(b);
h(a.nTable).on("order.dt.DT",function(e,f,g,h){if(a===f){e=c.idx;b.removeClass(d.sSortAsc+" "+d.sSortDesc).addClass(h[e]=="asc"?d.sSortAsc:h[e]=="desc"?d.sSortDesc:c.sSortingClass);b.find("span."+d.sSortIcon).removeClass(d.sSortJUIAsc+" "+d.sSortJUIDesc+" "+d.sSortJUI+" "+d.sSortJUIAscAllowed+" "+d.sSortJUIDescAllowed).addClass(h[e]=="asc"?d.sSortJUIAsc:h[e]=="desc"?d.sSortJUIDesc:c.sSortingClassJUI)}})}}});var Vb=function(a){return"string"===typeof a?a.replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,
"&quot;"):a};m.render={number:function(a,b,c,d,e){return{display:function(f){if("number"!==typeof f&&"string"!==typeof f)return f;var g=0>f?"-":"",h=parseFloat(f);if(isNaN(h))return Vb(f);h=h.toFixed(c);f=Math.abs(h);h=parseInt(f,10);f=c?b+(f-h).toFixed(c).substring(2):"";return g+(d||"")+h.toString().replace(/\B(?=(\d{3})+(?!\d))/g,a)+f+(e||"")}}},text:function(){return{display:Vb}}};h.extend(m.ext.internal,{_fnExternApiFunc:Lb,_fnBuildAjax:sa,_fnAjaxUpdate:kb,_fnAjaxParameters:tb,_fnAjaxUpdateDraw:ub,
_fnAjaxDataSrc:ta,_fnAddColumn:Da,_fnColumnOptions:ja,_fnAdjustColumnSizing:Y,_fnVisibleToColumnIndex:Z,_fnColumnIndexToVisible:$,_fnVisbleColumns:aa,_fnGetColumns:la,_fnColumnTypes:Fa,_fnApplyColumnDefs:hb,_fnHungarianMap:X,_fnCamelToHungarian:I,_fnLanguageCompat:Ca,_fnBrowserDetect:fb,_fnAddData:M,_fnAddTr:ma,_fnNodeToDataIndex:function(a,b){return b._DT_RowIndex!==k?b._DT_RowIndex:null},_fnNodeToColumnIndex:function(a,b,c){return h.inArray(c,a.aoData[b].anCells)},_fnGetCellData:B,_fnSetCellData:ib,
_fnSplitObjNotation:Ia,_fnGetObjectDataFn:Q,_fnSetObjectDataFn:R,_fnGetDataMaster:Ja,_fnClearTable:na,_fnDeleteIndex:oa,_fnInvalidate:ca,_fnGetRowElements:Ha,_fnCreateTr:Ga,_fnBuildHead:jb,_fnDrawHead:ea,_fnDraw:N,_fnReDraw:S,_fnAddOptionsHtml:mb,_fnDetectHeader:da,_fnGetUniqueThs:ra,_fnFeatureHtmlFilter:ob,_fnFilterComplete:fa,_fnFilterCustom:xb,_fnFilterColumn:wb,_fnFilter:vb,_fnFilterCreateSearch:Oa,_fnEscapeRegex:Pa,_fnFilterData:yb,_fnFeatureHtmlInfo:rb,_fnUpdateInfo:Bb,_fnInfoMacros:Cb,_fnInitialise:ga,
_fnInitComplete:ua,_fnLengthChange:Qa,_fnFeatureHtmlLength:nb,_fnFeatureHtmlPaginate:sb,_fnPageChange:Sa,_fnFeatureHtmlProcessing:pb,_fnProcessingDisplay:C,_fnFeatureHtmlTable:qb,_fnScrollDraw:ka,_fnApplyToChildren:H,_fnCalculateColumnWidths:Ea,_fnThrottle:Na,_fnConvertToWidth:Db,_fnGetWidestNode:Eb,_fnGetMaxLenString:Fb,_fnStringToCss:v,_fnSortFlatten:V,_fnSort:lb,_fnSortAria:Hb,_fnSortListener:Ua,_fnSortAttachListener:La,_fnSortingClasses:wa,_fnSortData:Gb,_fnSaveState:xa,_fnLoadState:Ib,_fnSettingsFromNode:ya,
_fnLog:J,_fnMap:F,_fnBindAction:Va,_fnCallbackReg:z,_fnCallbackFire:r,_fnLengthOverflow:Ra,_fnRenderer:Ma,_fnDataSource:y,_fnRowAttributes:Ka,_fnCalculateEnd:function(){}});h.fn.dataTable=m;m.$=h;h.fn.dataTableSettings=m.settings;h.fn.dataTableExt=m.ext;h.fn.DataTable=function(a){return h(this).dataTable(a).api()};h.each(m,function(a,b){h.fn.DataTable[a]=b});return h.fn.dataTable});

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,45 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<!--
2013-9-30: Created.
-->
<svg>
<metadata>
Created by iconfont
</metadata>
<defs>
<font id="laydate-icon" horiz-adv-x="1024" >
<font-face
font-family="laydate-icon"
font-weight="500"
font-stretch="normal"
units-per-em="1024"
ascent="896"
descent="-128"
/>
<missing-glyph />
<glyph glyph-name="x" unicode="x" horiz-adv-x="1001"
d="M281 543q-27 -1 -53 -1h-83q-18 0 -36.5 -6t-32.5 -18.5t-23 -32t-9 -45.5v-76h912v41q0 16 -0.5 30t-0.5 18q0 13 -5 29t-17 29.5t-31.5 22.5t-49.5 9h-133v-97h-438v97zM955 310v-52q0 -23 0.5 -52t0.5 -58t-10.5 -47.5t-26 -30t-33 -16t-31.5 -4.5q-14 -1 -29.5 -0.5
t-29.5 0.5h-32l-45 128h-439l-44 -128h-29h-34q-20 0 -45 1q-25 0 -41 9.5t-25.5 23t-13.5 29.5t-4 30v167h911zM163 247q-12 0 -21 -8.5t-9 -21.5t9 -21.5t21 -8.5q13 0 22 8.5t9 21.5t-9 21.5t-22 8.5zM316 123q-8 -26 -14 -48q-5 -19 -10.5 -37t-7.5 -25t-3 -15t1 -14.5
t9.5 -10.5t21.5 -4h37h67h81h80h64h36q23 0 34 12t2 38q-5 13 -9.5 30.5t-9.5 34.5q-5 19 -11 39h-368zM336 498v228q0 11 2.5 23t10 21.5t20.5 15.5t34 6h188q31 0 51.5 -14.5t20.5 -52.5v-227h-327z" />
<glyph glyph-name="youyou" unicode="&#58882;" d="M283.648 721.918976 340.873216 780.926976 740.352 383.997952 340.876288-12.925952 283.648 46.077952 619.52 383.997952Z" horiz-adv-x="1024" />
<glyph glyph-name="zuozuo" unicode="&#58883;" d="M740.352 721.918976 683.126784 780.926976 283.648 383.997952 683.123712-12.925952 740.352 46.077952 404.48 383.997952Z" horiz-adv-x="1024" />
<glyph glyph-name="xiayiye" unicode="&#58970;" d="M62.573 384.103l423.401 423.662c18.985 18.985 49.757 18.985 68.727 0 18.982-18.972 18.985-49.746 0-68.729l-355.058-355.067 356.796-356.796c18.977-18.971 18.976-49.746 0-68.727-18.982-18.976-49.751-18.976-68.727 0l-39.753 39.753 0.269 0.246-385.655 385.661zM451.365 384.103l423.407 423.662c18.985 18.985 49.757 18.985 68.727 0 18.982-18.972 18.985-49.746 0-68.729l-355.058-355.067 356.796-356.796c18.977-18.971 18.976-49.746 0-68.727-18.982-18.976-49.757-18.977-68.727 0l-39.762 39.754 0.273 0.249-385.662 385.661zM451.365 384.103z" horiz-adv-x="1024" />
<glyph glyph-name="xiayiye1" unicode="&#58971;" d="M948.066926 382.958838l-411.990051-412.24426c-18.47333-18.47333-48.417689-18.47333-66.875207 0-18.47333 18.461167-18.47333 48.405526 0 66.875207L814.691135 383.088983 467.512212 730.269123c-18.466032 18.458735-18.466032 48.405526 0 66.873991 18.468465 18.464816 48.410391 18.464816 66.872774 0l38.682336-38.682336-0.261507-0.239614 375.259894-375.265975v0.003649m-378.312834 0L157.756743-29.285422c-18.47333-18.47333-48.415256-18.47333-66.872775 0-18.47333 18.461167-18.47333 48.405526 0 66.875207L436.369787 383.088983 89.19208 730.269123c-18.4636 18.458735-18.4636 48.405526 0 66.873991 18.470898 18.464816 48.415256 18.464816 66.872774 0l38.692067-38.682336-0.266372-0.239614 375.267191-375.265975-0.004865 0.003649m0 0z" horiz-adv-x="1024" />
</font>
</defs></svg>

After

Width:  |  Height:  |  Size: 3.0 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,128 @@
$(function () {
$('#sampleTable').DataTable();
$(".new-scan").click(function () {
const task_name = $('[name="task_name"]').val();
const target_addr = $('[name="target_addr"]').val();
const scan_type = $('[name="scan_type"]').val();
const description_val = $('[name="description_val"]').val();
if (!task_name || !target_addr || !scan_type) {
swal("Warning", "Please check the input!", "error");
} else {
$.post('/acunetix-scanner', {
"task_name": task_name,
"target_addr": target_addr,
"scan_type": scan_type,
"description_val": description_val,
"source": "new_scan"
}, function (e) {
if (e === 'success') {
swal({
title: "Task added successfully!",
text: "",
type: "success",
confirmButtonColor: "#41b883",
confirmButtonText: "ok",
closeOnConfirm: false
},
function () {
location.href = "/acunetix-scanner";
});
} else {
swal("Error", "Something wrong", "error");
}
})
}
});
});
function delete_scan(nid){
swal({
title: "Are you sure want to delete?",
text: "",
type: "warning",
showCancelButton: true,
confirmButtonColor: "#DD6B55",
confirmButtonText: "Delete",
closeOnConfirm: false
},
function() {
$.post('/acunetix-tasks', {
"delete": nid,
"source": 'delete_scan',
}, function (e) {
if (e === 'success') {
swal({
title: "Delete Success",
text: "",
type: "success",
confirmButtonColor: "#41b883",
confirmButtonText: "ok",
closeOnConfirm: false
},
function () {
location.href = "/acunetix-tasks";
});
} else {
swal("Error", "Something wrong", "error");
}
})
})
}
function report_url(nid){
$.post('/acunetix-tasks', {
"scan_id": nid,
"source": 'report',
}, function (e) {
if (e !== 'warning') {
document.getElementById("report_download_html").innerHTML="<a href=\"static/download/" + e['html_url'] + "\" target=\"view_window\"><button class=\"btn btn-primary btn-block\" type=\"button\">HTML</button></a>";
document.getElementById("report_download_pdf").innerHTML="<a href=\"static/download/" + e['pdf_url'] + "\" target=\"view_window\"><button class=\"btn btn-primary btn-block\" type=\"button\">PDF</button></a>";
}
})
}
function delete_task(nid){
swal({
title: "Are you sure want to delete?",
text: "",
type: "warning",
showCancelButton: true,
confirmButtonColor: "#DD6B55",
confirmButtonText: "Delete",
closeOnConfirm: false
},
function() {
$.post('/acunetix-scanner', {
"delete": nid,
"source": 'delete_task',
}, function (e) {
if (e === 'success') {
swal({
title: "Delete Success",
text: "",
type: "success",
confirmButtonColor: "#41b883",
confirmButtonText: "ok",
closeOnConfirm: false
},
function () {
location.href = "/acunetix-scanner";
});
} else {
swal("Error", "Something wrong", "error");
}
})
})
}
function down_report(nid){
$.post('/acunetix-scanner', {
"task_id": nid,
"source": 'download_report',
}, function (e) {
if (e !== 'warning') {
document.getElementById("report_download_html").innerHTML="<a href=\"static/download/" + e['html_url'] + "\" target=\"view_window\"><button class=\"btn btn-primary btn-block\" type=\"button\">HTML</button></a>";
document.getElementById("report_download_pdf").innerHTML="<a href=\"static/download/" + e['pdf_url'] + "\" target=\"view_window\"><button class=\"btn btn-primary btn-block\" type=\"button\">PDF</button></a>";
}
})
}

View File

@ -0,0 +1,191 @@
$(function () {
$('#sampleTable').DataTable();
var demo1 = $('select[name="plugin_list"]').bootstrapDualListbox();
var demo2 = $('select[name="auth_service_list"]').bootstrapDualListbox();
$(".asset-update").click(function () {
const asset_name = $('[name="asset_name_edit"]').val();
const asset_id = $('[name="asset_id_edit"]').val();
const host_val = $('[name="asset_host_edit"]').val();
const dept_name = $('[name="dept_name_edit"]').val();
const admin_name = $('[name="admin_name_edit"]').val();
const discover_option = $("input[type='checkbox']").is(':checked');
if (!asset_name || !host_val || !dept_name) {
swal("Warning","Please check the input!", "error");
} else {
$.post('/asset-management', {
"asset_name": asset_name,
"asset_id": asset_id,
"host_val": host_val,
"dept_name": dept_name,
"admin_name": admin_name,
"discover_option": discover_option,
"source": "asset_update"
}, function (e) {
if (e === 'success') {
swal({
title: "Updated successfully!",
text: "",
type: "success",
confirmButtonColor: "#41b883",
confirmButtonText: "ok",
closeOnConfirm: false
},
function(){
location.href = "/asset-management";
});
} else {
swal("Error","Something wrong", "error");
}
})
}
});
$("#asset-scan").click(function () {
const taskname_val = $('[name="taskname_val"]').val();
const plugin_val = $('[name="plugin_list"]').val().join(",");
const recursion_val = $('[name="recursion_val"]').val();
const target_val = $('[name="target_val"]').val();
if (!taskname_val || !plugin_val || !target_val) {
swal("Warning","Please check the input!", "error");
} else {
$.post('/add-task', {
"taskname_val": taskname_val,
"plugin_val": plugin_val,
"recursion_val": recursion_val,
"target_val": target_val,
"source": "asset",
}, function (e) {
if (e === 'success') {
swal({
title: "Task added successfully!",
text: "",
type: "success",
confirmButtonColor: "#41b883",
confirmButtonText: "ok",
closeOnConfirm: false
},
function(){
location.href = "/task-management";
});
} else {
swal("Warning","Failed to create task!", "error");
}
})
}
});
$("#asset-auth-tasks").click(function () {
const task_name = $('[name="auth_task_name"]').val();
const target_list = $('[name="auth_target_list"]').val();
const service_list = $('[name="auth_service_list"]').val().join(",");
const username_list = $('[name="auth_username_list"]').val();
const password_list = $('[name="auth_password_list"]').val();
const args = $('[name="auth_args"]').val();
const recursion = $('[name="auth_recursion"]').val();
if (!task_name || !target_list || !service_list|| !username_list|| !password_list || !recursion) {
swal("Warning","Please check the input!", "error");
} else {
$.post('/auth-tester', {
"task_name": task_name,
"target_list": target_list,
"service_list": service_list,
"username_list": username_list,
"password_list": password_list,
"args": args,
"recursion": recursion,
}, function (e) {
if (e === 'success') {
swal({
title: "Task added successfully!",
text: "",
type: "success",
confirmButtonColor: "#41b883",
confirmButtonText: "ok",
closeOnConfirm: false
},
function(){
location.href = "/auth-tester-tasks";
});
} else {
swal("Warning","Failed to create task!", "error");
}
})
}
});
});
function delete_asset(nid){
const data = {
"delete": nid,
};
swal({
title: "Are you sure want to delete?",
text: "",
type: "warning",
showCancelButton: true,
confirmButtonColor: "#DD6B55",
confirmButtonText: "Delete",
closeOnConfirm: false
},
function(){
$.ajax({
type: 'GET',
url: '/asset-management',
data: data,
success: function() {
location.href = "/asset-management";
},
error: function(xhr, type) {
}
});
});
}
function asset_info(nid){
const data = {
"edit": nid,
};
$.ajax({
type: 'GET',
url: '/asset-management',
data: data,
dataType: 'json',
success: function(respond) {
const data = eval(respond);
const asset_name = data.asset_name;
const dept_name = data.dept_name;
const admin_name = data.admin_name;
const asset_host = data.asset_host;
$('#asset_name_edit').val(asset_name);
$('#dept_name_edit').val(dept_name);
$('#admin_name_edit').val(admin_name);
$('#asset_host_edit').val(asset_host);
$('#asset_id_edit').val(nid);
},
error: function(xhr, type) {
}
});
}
function get_asset_host(nid){
const data = {
"scan": nid,
};
$.ajax({
type: 'GET',
url: '/asset-management',
data: data,
dataType: 'json',
success: function(respond) {
const data = eval(respond);
const asset_host = data.asset_host;
$('#scan_target_list').val(asset_host);
$('#auth_target_list').val(asset_host);
},
error: function(xhr, type) {
}
});
}

View File

@ -0,0 +1,96 @@
$(function () {
$('#sampleTable').DataTable();
var demo1 = $('select[name="plugin_list"]').bootstrapDualListbox();
$("#server-scan").click(function () {
const taskname_val = $('[name="taskname_val"]').val();
const plugin_val = $('[name="plugin_list"]').val().join(",");
const recursion_val = $('[name="recursion_val"]').val();
const target_val = $('[name="target_val"]').val();
if (!taskname_val || !plugin_val || !target_val) {
swal("Warning","Please check the input!", "error");
} else {
$.post('/add-task', {
"taskname_val": taskname_val,
"plugin_val": plugin_val,
"recursion_val": recursion_val,
"target_val": target_val,
"source": "asset",
}, function (e) {
if (e === 'success') {
swal({
title: "Task added successfully!",
text: "",
type: "success",
confirmButtonColor: "#41b883",
confirmButtonText: "ok",
closeOnConfirm: false
},
function(){
location.href = "/task-management";
});
} else {
swal("Warning","Failed to create task!", "error");
}
})
}
});
});
function server_info(nid){
const data = {
"info": nid,
};
$.ajax({
type: 'GET',
url: '/asset-services',
data: data,
dataType: 'json',
success: function(result) {
$('#server_info').html(JSON.stringify(result, null, 4));
},
error: function(xhr, type) {
}
});
}
function selectAll()
{
var allMails = document.getElementsByName("allSelect")[0];
var mails = document.getElementsByName("select_id");
if(allMails.checked)
{
for(var i = 0; i < mails.length; ++i)
{
mails[i].checked = true;
}
}
else
{
for(var i = 0; i < mails.length; ++i)
{
mails[i].checked = false;
}
}
}
function newScan() {
var select_list = [];
$("input[name='select_id']:checked").each(function () {
select_list.push(this.value);
});
if(select_list.length === 0) {
swal("Warning","Please select the target", "error");
} else {
get_server_host(select_list)
}
}
function get_server_host(server_list){
$.post('/asset-services', {
"server_list": server_list.join(","),
"source": "server_scan"
}, function (e) {
$('#scan_target_list').val(e);
});
}

View File

@ -0,0 +1,66 @@
$(function () {
$('#sampleTable').DataTable();
});
function get_target_host(nid){
$.post('/auth-tester-tasks', {
"task_id": nid,
"source": "target_info"
}, function (e) {
document.getElementById("target_info_data").innerHTML=e;
})
}
function delete_task(nid){
const data = {
"delete": nid,
};
swal({
title: "Are you sure want to delete?",
text: "",
type: "warning",
showCancelButton: true,
confirmButtonColor: "#DD6B55",
confirmButtonText: "Delete",
closeOnConfirm: false
},
function(){
$.ajax({
type: 'GET',
url: '/auth-tester-tasks',
data: data,
success: function() {
location.href = "/auth-tester-tasks";
},
error: function(xhr, type) {
}
});
});
}
function rescan_task(nid){
const data = {
"rescan": nid,
};
swal({
title: "Are you sure want to rescan?",
text: "This will clear the scan result",
type: "warning",
showCancelButton: true,
confirmButtonColor: "#DD6B55",
confirmButtonText: "Rescan",
closeOnConfirm: false
},
function(){
$.ajax({
type: 'GET',
url: '/auth-tester-tasks',
data: data,
success: function() {
location.href = "/auth-tester-tasks";
},
error: function(xhr, type) {
}
});
});
}

View File

@ -0,0 +1,31 @@
function selectAll()
{
var allMails = document.getElementsByName("allSelect")[0];
var mails = document.getElementsByName("select_id");
if(allMails.checked)
{
for(var i = 0; i < mails.length; ++i)
{
mails[i].checked = true;
}
}
else
{
for(var i = 0; i < mails.length; ++i)
{
mails[i].checked = false;
}
}
}
function getAll() {
var select_list = [];
$("input[name='select_id']:checked").each(function () {
select_list.push(this.value);
});
if(select_list.length === 0) {
swal("Warning","Please select the target", "error");
} else {
alert(select_list)
}
}

View File

@ -0,0 +1,37 @@
$(function () {
$("#newAsset").click(function () {
const asset_name = $('[name="asset_name"]').val();
const asset_host = $('[name="asset_host"]').val();
const dept_name = $('[name="dept_name"]').val();
const admin_name = $('[name="admin_name"]').val();
const discover_option = $("input[type='checkbox']").is(':checked');
if (!asset_name || !asset_host) {
swal("Warning","Please check the input!", "error");
} else {
$.post('/new-asset', {
"asset_name": asset_name,
"asset_host": asset_host,
"dept_name": dept_name,
"admin_name": admin_name,
"discover_option": discover_option,
"source": "new_asset",
}, function (e) {
if (e === 'success') {
swal({
title: "Task added successfully!",
text: "",
type: "success",
confirmButtonColor: "#41b883",
confirmButtonText: "ok",
closeOnConfirm: false
},
function(){
location.href = "/asset-management";
});
} else {
swal("Warning","Failed to create asset!", "error");
}
})
}
});
});

View File

@ -0,0 +1,42 @@
$(function () {
var demo1 = $('select[name="service_list"]').bootstrapDualListbox();
$("#newAuth").click(function () {
const task_name = $('[name="task_name"]').val();
const target_list = $('[name="target_list"]').val();
const service_list = $('[name="service_list"]').val().join(",");
const username_list = $('[name="username_list"]').val();
const password_list = $('[name="password_list"]').val();
const args = $('[name="args"]').val();
const recursion = $('[name="recursion"]').val();
if (!task_name || !target_list || !service_list|| !username_list|| !password_list || !recursion) {
swal("Warning","Please check the input!", "error");
} else {
$.post('/auth-tester', {
"task_name": task_name,
"target_list": target_list,
"service_list": service_list,
"username_list": username_list,
"password_list": password_list,
"args": args,
"recursion": recursion,
}, function (e) {
if (e === 'success') {
swal({
title: "Task added successfully!",
text: "",
type: "success",
confirmButtonColor: "#41b883",
confirmButtonText: "ok",
closeOnConfirm: false
},
function(){
location.href = "/auth-tester-tasks";
});
} else {
swal("Warning","Failed to create task!", "error");
}
})
}
});
});

View File

@ -0,0 +1,37 @@
$(function () {
var demo1 = $('select[name="plugin_list"]').bootstrapDualListbox();
$("#showConfig").click(function () {
const taskname_val = $('[name="taskname_val"]').val();
const plugin_val = $('[name="plugin_list"]').val().join(",");
const recursion_val = $('[name="recursion_val"]').val();
const target_val = $('[name="target_val"]').val();
if (!taskname_val || !plugin_val || !target_val) {
swal("Warning","Please check the input!", "error");
} else {
$.post('/add-task', {
"taskname_val": taskname_val,
"plugin_val": plugin_val,
"recursion_val": recursion_val,
"target_val": target_val,
"source": "scan_view",
}, function (e) {
if (e === 'success') {
swal({
title: "Task added successfully!",
text: "",
type: "success",
confirmButtonColor: "#41b883",
confirmButtonText: "ok",
closeOnConfirm: false
},
function(){
location.href = "/task-management";
});
} else {
swal("Warning","Failed to create task!", "error");
}
})
}
});
});

View File

@ -0,0 +1,81 @@
function delete_plugin(nid){
const data = {
"delete": nid,
};
swal({
title: "Are you sure you want to delete?",
text: "If you delete an item, it will be permanently lost",
type: "warning",
showCancelButton: true,
confirmButtonColor: "#DD6B55",
confirmButtonText: "Delete",
closeOnConfirm: false
},
function(){
$.ajax({
type: 'GET',
url: '/plugin-management',
data: data,
success: function() {
location.href = "/plugin-management";
},
error: function(xhr, type) {}
});
});
}
function plugin_info(nid){
const data = {
"info": nid,
};
$.ajax({
type: 'GET',
url: '/plugin-management',
data: data,
dataType: 'json',
success: function(result) {
$('#plugin_info').html(JSON.stringify(result, null, 4));
},
error: function(xhr, type) {
}
});
}
$('#sampleTable').DataTable();
Dropzone.autoDiscover = false;
$(".dropzone").dropzone({
url: "plugin-upload",
init: function() {
this.on("complete", function (data) {
const res = eval('(' + data.xhr.responseText + ')');
if (res.result === "success") {
swal({
title: "Upload Completed",
text: "",
type: "success",
confirmButtonColor: "#DD6B55",
confirmButtonText: "OK",
closeOnConfirm: false
},
function(){
location.href = "/plugin-management";
});
} else {
swal({
title: "Upload Error",
text: "<p>Plugin Developer Guide: <a href=\"https://github.com/knownsec/Pocsuite/blob/master/docs/CODING.md\" target=\"view_window\">Pocsuite PoC </a></p>",
html: true,
type: "error",
confirmButtonColor: "#DD6B55",
confirmButtonText: "OK",
closeOnConfirm: false
},
function(){
location.href = "/plugin-management";
});
}
});
}
});

View File

@ -0,0 +1,121 @@
$(function () {
$('#sampleTable').DataTable();
setTimeout('reflush()',5000);
$(".port-update").click(function () {
const port_list = $('[name="edit_port_val"]').val();
if (!port_list) {
swal("Warning","Please check the input!", "error");
} else {
$.post('/advanced-option', {
"port_list": port_list,
"source": "port_scan"
}, function (e) {
if (e === 'success') {
swal({
title: "Updated successfully!",
text: "",
type: "success",
confirmButtonColor: "#41b883",
confirmButtonText: "ok",
closeOnConfirm: false
},
function(){
location.href = "/port-scanner";
});
} else {
swal("Error","Something wrong", "error");
}
})
}
});
$(".new-scan").click(function () {
const target_val = $('[name="target_val"]').val();
const arguments_val = $('[name="arguments_val"]').val();
const port_val = $('[name="port_val"]').val();
if (!target_val) {
swal("Warning","Please check the input!", "error");
} else {
$.post('/port-scanner', {
"target_val": target_val,
"arguments_val": arguments_val,
"port_val": port_val,
"source": "new_scan"
}, function (e) {
if (e.result === 'success') {
swal({
title: "Added Successfully!",
text: "",
type: "success",
confirmButtonColor: "#41b883",
confirmButtonText: "ok",
closeOnConfirm: false
},
function(){
location.href = "/port-scanner?scan_id=" + e.scan_id;
});
} else {
swal("Error","Something wrong", "error");
}
})
}
});
});
function reflush() {
var url = location.search;
var pre_result = document.getElementById('pre_result').innerHTML;
var url_re = url.indexOf("scan_id");
var pre_re = pre_result.indexOf("nmap");
if (url_re !== -1) {
if (pre_re === -1) {
window.location.reload();
}
}
}
function port_result(nid){
const data = {
"result": nid,
};
$.ajax({
type: 'GET',
url: '/port-scanner',
data: data,
success: function(result) {
$('#port_result').html(result);
},
error: function(xhr, type) {
}
});
}
function result_delete(nid){
const data = {
"delete": nid,
};
swal({
title: "Are you sure you want to delete?",
text: "",
type: "warning",
showCancelButton: true,
confirmButtonColor: "#DD6B55",
confirmButtonText: "Delete",
closeOnConfirm: false
},
function(){
$.ajax({
type: 'GET',
url: '/port-scanner',
data: data,
success: function() {
location.href = "/port-scanner";
},
error: function(xhr, type) {
}
});
});
}

View File

@ -0,0 +1,118 @@
var demo1 = $('select[name="plugin_list"]').bootstrapDualListbox();
var demo2 = $('select[name="auth_service_list"]').bootstrapDualListbox();
$(".btn_select").on("click",function(){
var selects = document.getElementsByName("select_id");
if($(this).attr("rel")==="select_all"){
document.getElementById( "btn_select" ).rel = "unselect_all";
document.getElementById( "btn_select" ).innerHTML = "Unselect All";
for(var i = 0; i < selects.length; ++i)
{
selects[i].checked = true;
}
}else if($(this).attr("rel")==="unselect_all"){
document.getElementById( "btn_select" ).rel = "select_all";
document.getElementById( "btn_select" ).innerHTML = "Select All";
for(var i = 0; i < selects.length; ++i)
{
selects[i].checked = false;
}
}
});
$("#asset-auth-tasks").click(function () {
const task_name = $('[name="auth_task_name"]').val();
const target_list = $('[name="auth_target_list"]').val();
const service_list = $('[name="auth_service_list"]').val().join(",");
const username_list = $('[name="auth_username_list"]').val();
const password_list = $('[name="auth_password_list"]').val();
const args = $('[name="auth_args"]').val();
const recursion = $('[name="auth_recursion"]').val();
if (!task_name || !target_list || !service_list|| !username_list|| !password_list || !recursion) {
swal("Warning","Please check the input!", "error");
} else {
$.post('/auth-tester', {
"task_name": task_name,
"target_list": target_list,
"service_list": service_list,
"username_list": username_list,
"password_list": password_list,
"args": args,
"recursion": recursion,
}, function (e) {
if (e === 'success') {
swal({
title: "Task added successfully!",
text: "",
type: "success",
confirmButtonColor: "#41b883",
confirmButtonText: "ok",
closeOnConfirm: false
},
function(){
location.href = "/auth-tester-tasks";
});
} else {
swal("Warning","Failed to create task!", "error");
}
})
}
});
$("#server-scan").click(function () {
const taskname_val = $('[name="taskname_val"]').val();
const plugin_val = $('[name="plugin_list"]').val().join(",");
const recursion_val = $('[name="recursion_val"]').val();
const target_val = $('[name="target_val"]').val();
if (!taskname_val || !plugin_val || !target_val) {
swal("Warning","Please check the input!", "error");
} else {
$.post('/add-task', {
"taskname_val": taskname_val,
"plugin_val": plugin_val,
"recursion_val": recursion_val,
"target_val": target_val,
"source": "asset",
}, function (e) {
if (e === 'success') {
swal({
title: "Task added successfully!",
text: "",
type: "success",
confirmButtonColor: "#41b883",
confirmButtonText: "ok",
closeOnConfirm: false
},
function(){
location.href = "/task-management";
});
} else {
swal("Warning","Failed to create task!", "error");
}
})
}
});
function newServiceScan() {
var select_list = [];
$("input[name='select_id']:checked").each(function () {
select_list.push(this.value);
});
if(select_list.length === 0) {
swal("Warning","Please select the target", "error");
} else {
$('#scan_target_list').val(select_list.join("\n"))
}
}
function newAuthTester() {
var select_list = [];
$("input[name='select_id']:checked").each(function () {
select_list.push(this.value);
});
if(select_list.length === 0) {
swal("Warning","Please select the target", "error");
} else {
$('#auth_target_list').val(select_list.join("\n"))
}
}

View File

@ -0,0 +1,128 @@
$(function () {
$(".update-thread-config").click(function () {
const poc_thread = $('[id="poc_thread"]').val();
const discovery_thread = $('[id="discovery_thread"]').val();
const subdomain_thread = $('[id="subdomain_thread"]').val();
const port_thread = $('[id="port_thread"]').val();
const auth_tester_thread = $('[id="auth_tester_thread"]').val();
const discovery_time = $('[name="discovery_time_val"]').val();
if (!poc_thread || !discovery_thread || !subdomain_thread || !port_thread || !discovery_time) {
swal("Warning","Please check the input!", "error");
} else {
$.post('/advanced-option', {
"poc_thread": poc_thread,
"discovery_thread": discovery_thread,
"subdomain_thread": subdomain_thread,
"port_thread": port_thread,
"auth_tester_thread": auth_tester_thread,
"discovery_time": discovery_time,
"source": "thread_settings",
}, function (e) {
if (e === 'success') {
swal({
title: "Updated Successfully!",
text: "",
type: "success",
confirmButtonColor: "#41b883",
confirmButtonText: "ok",
closeOnConfirm: false
},
function(){
location.href = "/advanced-option";
});
} else {
swal("Error","Something wrong", "error");
}
})
}
});
$(".update-subdomain-dict-config").click(function () {
const subdomain_dict_2 = $('[id="subdomain_dict_2"]').val();
const subdomain_dict_3 = $('[id="subdomain_dict_3"]').val();
if (!subdomain_dict_2 || !subdomain_dict_3) {
swal("Warning","Please check the input!", "error");
} else {
$.post('/advanced-option', {
"subdomain_dict_2": subdomain_dict_2,
"subdomain_dict_3": subdomain_dict_3,
"source": "subdomain_dict"
}, function (e) {
if (e === 'success') {
swal({
title: "Successfully Update!",
text: "",
type: "success",
confirmButtonColor: "#41b883",
confirmButtonText: "ok",
closeOnConfirm: false
},
function(){
location.href = "/advanced-option";
});
} else {
swal("Error","Something wrong", "error");
}
})
}
});
$(".update-user-passwd").click(function () {
const username_list = $('[id="username_list"]').val();
const password_list = $('[id="password_list"]').val();
if (!username_list || !password_list) {
swal("Warning","Please check the input!", "error");
} else {
$.post('/advanced-option', {
"username_list": username_list,
"password_list": password_list,
"source": "auth"
}, function (e) {
if (e === 'success') {
swal({
title: "Successfully Update!",
text: "",
type: "success",
confirmButtonColor: "#41b883",
confirmButtonText: "ok",
closeOnConfirm: false
},
function(){
location.href = "/advanced-option";
});
} else {
swal("Error","Something wrong", "error");
}
})
}
});
$(".update-port-config").click(function () {
const port_list = $('[id="port_list"]').val();
if (!port_list) {
swal("Warning","Please check the input!", "error");
} else {
$.post('/advanced-option', {
"port_list": port_list,
"source": "port_list"
}, function (e) {
if (e === 'success') {
swal({
title: "Updated Successfully!",
text: "",
type: "success",
confirmButtonColor: "#41b883",
confirmButtonText: "ok",
closeOnConfirm: false
},
function(){
location.href = "/advanced-option";
});
} else {
swal("Error","Something wrong", "error");
}
})
}
});
});

View File

@ -0,0 +1,162 @@
$(function () {
$('#sampleTable').DataTable();
var demo1 = $('select[name="plugin_list"]').bootstrapDualListbox();
$("#new_domain").click(function () {
const domain_name_val = $('[name="domain_name_val"]').val();
const domain_val = $('[name="domain_val"]').val();
const third_domain = $("input[type='checkbox']").is(':checked');
if (!domain_name_val || !domain_val) {
swal("Warning","Please check the input!", "error");
} else {
$.post('/subdomain-brute', {
"domain_name_val": domain_name_val,
"domain_val": domain_val,
"third_domain": third_domain,
"source": "new_domain",
}, function (e) {
if (e === 'success') {
swal({
title: "Successfully Created!",
text: "",
type: "success",
confirmButtonColor: "#41b883",
confirmButtonText: "ok",
closeOnConfirm: false
},
function(){
location.href = "/subdomain-brute";
});
} else {
swal("Warning","Failed to create task!", "error");
}
})
}
});
$("#domain-scan").click(function () {
const taskname_val = $('[name="taskname_val"]').val();
const plugin_val = $('[name="plugin_list"]').val().join(",");
const recursion_val = $('[name="recursion_val"]').val();
const target_val = $('[name="target_val"]').val();
if (!taskname_val || !plugin_val || !target_val) {
swal("Warning","Please check the input!", "error");
} else {
$.post('/add-task', {
"taskname_val": taskname_val,
"plugin_val": plugin_val,
"recursion_val": recursion_val,
"target_val": target_val,
"source": "subdomain",
}, function (e) {
if (e === 'success') {
swal({
title: "Successfully Created!",
text: "",
type: "success",
confirmButtonColor: "#41b883",
confirmButtonText: "ok",
closeOnConfirm: false
},
function(){
location.href = "/task-management";
});
} else {
swal("Warning","Failed to create task!", "error");
}
})
}
});
$("#awvs-scan").click(function () {
const task_name = $('[name="awvs_task_name"]').val();
const target_addr = $('[name="awvs_target"]').val();
const scan_type = $('[name="awvs_scan_type"]').val();
const description_val = $('[name="awvs_desc_val"]').val();
if (!task_name || !target_addr || !scan_type) {
swal("Warning", "Please check the input!", "error");
} else {
$.post('/acunetix-scanner', {
"task_name": task_name,
"target_addr": target_addr,
"scan_type": scan_type,
"description_val": description_val,
"source": "new_scan"
}, function (e) {
if (e === 'success') {
swal({
title: "Task added successfully!",
text: "",
type: "success",
confirmButtonColor: "#41b883",
confirmButtonText: "ok",
closeOnConfirm: false
},
function () {
location.href = "/acunetix-scanner";
});
} else {
swal("Error", "Something wrong", "error");
}
})
}
});
});
function delete_domain(nid){
const data = {
"delete": nid,
};
swal({
title: "Are you sure you want to delete?",
text: "If you delete an item, it will be permanently lost",
type: "warning",
showCancelButton: true,
confirmButtonColor: "#DD6B55",
confirmButtonText: "Delete",
closeOnConfirm: false
},
function(){
$.ajax({
type: 'GET',
url: '/subdomain-brute',
data: data,
success: function() {
location.href = "/subdomain-brute";
},
error: function(xhr, type) {}
});
});
}
function get_domain_host(nid){
const data = {
"subdomain": nid,
};
$.ajax({
type: 'GET',
url: '/subdomain-list',
data: data,
success: function(respond) {
$('#scan_target_list').val(respond);
},
error: function(xhr, type) {
}
});
}
function get_domain_awvs(nid){
const data = {
"subdomain": nid,
};
$.ajax({
type: 'GET',
url: '/subdomain-list',
data: data,
success: function(respond) {
$('#awvs_target').val(respond);
},
error: function(xhr, type) {
}
});
}

View File

@ -0,0 +1,3 @@
$(function () {
$('#sampleTable').DataTable();
});

View File

@ -0,0 +1,113 @@
$(function () {
$('#sampleTable').DataTable();
$(".task-update").click(function () {
const taskname_val = $('[name="taskname_val"]').val();
const task_id = $('[name="task_id"]').val();
const recursion_val = $('[name="recursion_val"]').val();
const target_val = $('[name="target_val"]').val();
if (!taskname_val || !task_id || !target_val) {
swal("Warning","Please check the input!", "error");
} else {
$.post('/task-edit', {
"taskname_val": taskname_val,
"task_id": task_id,
"recursion_val": recursion_val,
"target_val": target_val,
}, function (e) {
if (e === 'success') {
swal({
title: "Updated Successfully!",
text: "",
type: "success",
confirmButtonColor: "#41b883",
confirmButtonText: "ok",
closeOnConfirm: false
},
function(){
location.href = "/task-management";
});
} else {
swal("Error","Something wrong", "error");
}
})
}
});
});
function rescan_task(nid){
const data = {
"rescan": nid,
};
swal({
title: "Are you sure want to rescan?",
text: "This will clear the scan result",
type: "warning",
showCancelButton: true,
confirmButtonColor: "#DD6B55",
confirmButtonText: "Rescan",
closeOnConfirm: false
},
function(){
$.ajax({
type: 'GET',
url: '/task-management',
data: data,
success: function() {
location.href = "/task-management";
},
error: function(xhr, type) {
}
});
});
}
function task_edit_id(nid){
const data = {
"edit": nid,
};
$.ajax({
type: 'GET',
url: '/task-management',
data: data,
dataType: 'json',
success: function(e) {
const data = eval(e);
const task_name = data.task_name;
const scan_target_list = data.scan_target;
$('#scan_target_list').val(scan_target_list);
$('#task_name').val(task_name);
$('#task_id').val(nid);
},
error: function(xhr, type) {
}
});
}
function task_delete(nid){
const data = {
"delete": nid,
};
swal({
title: "Are you sure you want to delete?",
text: "",
type: "warning",
showCancelButton: true,
confirmButtonColor: "#DD6B55",
confirmButtonText: "Delete",
closeOnConfirm: false
},
function(){
$.ajax({
type: 'GET',
url: '/task-management',
data: data,
success: function() {
location.href = "/task-management";
},
error: function(xhr, type) {
}
});
});
}

View File

@ -0,0 +1,31 @@
$(function () {
$.ajax({
type: 'GET',
url: '/update',
success: function (response) {
var html = "<ul class='app-notification dropdown-menu dropdown-menu-right'><li class='app-notification__title'>You have " +response.title.length + " new notifications.</li>";
for(var i = 0; i < response.title.length; i++)
{
html += "<li><a class=\"app-notification__item\" href=" + response.url[i] + " target='_blank'><span class=\"app-notification__icon\"><span class=\"fa-stack fa-lg\">" +
"<i class=\"fa fa-circle fa-stack-2x text-primary\"></i><i class=\"fa fa-envelope fa-stack-1x fa-inverse\"></i></span></span><div>" +
"<p class=\"app-notification__message\">" + response.title[i] + "</p><p class='app-notification__meta'>" + response.text[i] + "</p></div></a></li>";
}
html += "<li class='app-notification__footer'><a href='#'>See all notifications.</a></li></ul>";
$('#notification_update').html(html);
},
error: function() {
var html = "<ul class='app-notification dropdown-menu dropdown-menu-right'><li class='app-notification__title'>You have 0 new notifications.</li>" +
"<div class=\"app-notification__content\"><li><a class=\"app-notification__item\" href=\"javascript:;\"><span class=\"app-notification__icon\">" +
"<span class=\"fa-stack fa-lg\"></span></span><div></div>";
$('#notification_update').html(html);
}
});
});
function readVersion() {
var reader = new FileReader();
reader.onload = function(e) {
var text = reader.result;
};
reader.readAsText(file, encoding);
}

View File

@ -0,0 +1,23 @@
$(function () {
$('#sampleTable').DataTable();
});
function vul_result(nid){
const data = {
"result": nid,
};
$.ajax({
type: 'GET',
url: '/vulnerability',
data: data,
dataType: 'json',
success: function(result) {
var json_result = JSON.stringify(result, null, 4);
$('#scan_target_list').html("<pre>" + json_result + "</pre>");
},
error: function(xhr, type) {
}
});
}

View File

@ -0,0 +1,30 @@
$(function () {
$('#sampleTable').DataTable();
});
function delete_result(nid){
const data = {
"delete": nid,
};
swal({
title: "Are you sure want to delete?",
text: "",
type: "warning",
showCancelButton: true,
confirmButtonColor: "#DD6B55",
confirmButtonText: "Delete",
closeOnConfirm: false
},
function(){
$.ajax({
type: 'GET',
url: '/week-passwd-list',
data: data,
success: function() {
location.href = "/week-passwd-list";
},
error: function(xhr, type) {
}
});
});
}

View File

@ -0,0 +1,19 @@
{% extends "base.html" %}
{% block css %}
{% endblock %}
{% block content %}
<main class="app-content">
<div class="page-error tile">
<h1><i class="fa fa-exclamation-circle"></i> Error 404: Page not found</h1>
<p>The page you have requested is not found.</p>
<p>
<a class="btn btn-primary" href="javascript:window.history.back();">Go Back</a>
</p>
</div>
</main>
{% endblock %}
{% block js %}
{% endblock %}

View File

@ -0,0 +1,19 @@
{% extends "base.html" %}
{% block css %}
{% endblock %}
{% block content %}
<main class="app-content">
<div class="page-error tile">
<h1><i class="fa fa-exclamation-circle"></i> Error 500: Internal server error</h1>
<p>Internal server error.</p>
<p>
<a class="btn btn-primary" href="javascript:window.history.back();">Go Back</a>
</p>
</div>
</main>
{% endblock %}
{% block js %}
{% endblock %}

View File

@ -0,0 +1,183 @@
{% extends "base.html" %}
{% block css %}
{% endblock %}
{% block content %}
<main class="app-content">
<div class="app-title">
<div>
<h1><i class="fa fa-th-list"></i>&nbsp;Acunetix Scanner</h1>
<p>Acunetix Vulnerability Scanner: Web Application Security</p>
</div>
<ul class="app-breadcrumb breadcrumb side">
<li class="breadcrumb-item"><i class="fa fa-home fa-lg"></i></li>
<li class="breadcrumb-item">Home</li>
<li class="breadcrumb-item active"><a href="#">Acunetix Scanner</a></li>
</ul>
</div>
<div class="row">
<div class="col-md-12">
<div class="tile">
<div class="tile-body">
<div id="sampleTable_wrapper" class="dataTables_wrapper container-fluid dt-bootstrap4 no-footer">
<div class="row"><div class="col-sm-12 col-md-6">
<div class="dataTables_length" id="sampleTable_length">
<a class="btn btn-primary" href="#" data-target="#newScan" data-toggle="modal" title="New Scan">
<i class="fa fa-gitlab fa-lg"></i> New Scan</a>
<br>
<br>
</div>
</div>
</div>
<table class="table table-hover table-bordered" id="sampleTable">
<thead>
<tr class="text-center">
<th>Name</th>
<th>Type</th>
<th>Target</th>
<th>Description</th>
<th>Date</th>
<th>Manage</th>
</tr>
</thead>
<tbody>
{% for i in acunetix_task %}
<tr class="text-center">
<td>
<a href="#" target="view_window">{{ i['task_name'] }}</a>
</td>
{% if i['scan_type'] == '0' %}
<td>Full Scan</td>
{% elif i['scan_type'] == '1' %}
<td>High Risk Vulnerabilities</td>
{% elif i['scan_type'] == '2' %}
<td>Cross-site Scripting Vulnerabilities</td>
{% elif i['scan_type'] == '3' %}
<td>SQL Injection Vulnerabilities</td>
{% elif i['scan_type'] == '4' %}
<td>Weak Passwords</td>
{% elif i['scan_type'] == '5' %}
<td>Crawl Only</td>
{% endif %}
<td>{{ i['target_list'][0] }}...</td>
<td>{{ i['description'] }}</td>
<td>{{ i['date'] }}</td>
<td class="text-center">
<div class="hidden-sm hidden-xs action-buttons">
<a onclick="down_report('{{ i['_id'] }}')" role="button" data-target="#downloadReport" data-toggle="modal" href="#" title="Download Report">
<i class="fa fa-download"></i>
</a>
&nbsp;
&nbsp;
<a role="button" href="#" onclick="delete_task('{{ i['_id'] }}')" title="Delete">
<i class="fa fa-trash-o"></i>
</a>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="modal" id="downloadReport" >
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Download Report</h5>
<button class="close" type="button" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
</div>
<div class="modal-body">
<form class="form-group row">
<div class="col-md-2"></div>
<div class="col-md-4" id="report_download_html">
<p>Generating...</p>
</div>
<div class="col-md-4" id="report_download_pdf">
{# <p>Please wait...</p>#}
</div>
<div class="col-md-2"></div>
</form>
<div class="modal-footer">
<p class="text-muted">If the download page returns 'Not Found(404)', please wait a few seconds to refresh the download page</p>
<button class="btn default " type="button" data-dismiss="modal">Close</button>
</div>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
<div class="modal" id="newScan" >
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">New Scan</h5>
<button class="close" type="button" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
</div>
<div class="modal-body">
<form class="form-horizontal" role="form">
<div class="form-group">
<label class="control-label no-padding-right">Task Name <span class="text-danger">*</span></label>
<div>
<input type="text" class="form-control" id="task_name" name="task_name" placeholder="">
</div>
</div>
<div class="form-group">
<label class="control-label no-padding-right">Target <span class="text-danger">*</span></label>
<div>
<textarea class="form-control" id="target_addr" name="target_addr" rows="4" placeholder="One url per line:&#13;&#10;http://example.com&#13;&#10;http://example.com"></textarea>
</div>
</div>
<div class="form-group">
<label class="control-label no-padding-right">Scan Type <span class="text-danger">*</span></label>
<div >
<select class="form-control col-md-7" id="scan_type" title="Scan Type" name="scan_type">
<option value="0">Full Scan</option>
<option value="1">High Risk Vulnerabilities</option>
<option value="2">Cross-site Scripting Vulnerabilities</option>
<option value="3">SQL Injection Vulnerabilities</option>
<option value="4">Weak Passwords</option>
<option value="5">Crawl Only</option>
</select>
</div>
</div>
<div class="hr hr-16 hr-dotted"></div>
<div class="form-group">
<label class="control-label no-padding-right">Description </label>
<div>
<input type="text" class="form-control" id="description_val" name="description_val" placeholder="">
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal" aria-hidden="true">Cancel
</button>
<button class="btn btn-primary new-scan" type="button">
<span>OK</span>
</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
</div>
</div>
</div>
</div>
</div>
</main>
{% endblock %}
{% block js %}
<!-- Data table plugin-->
<script type="text/javascript" src="static/js/plugins/jquery.dataTables.min.js"></script>
<script type="text/javascript" src="static/js/plugins/dataTables.bootstrap.min.js"></script>
<script src="static/js/plugins/sweetalert/sweetalert.min.js"></script>
<script src="static/js/server/acunetix-scanner.js"></script>
{% endblock %}

View File

@ -0,0 +1,113 @@
{% extends "base.html" %}
{% block css %}
{% endblock %}
{% block content %}
<main class="app-content">
<div class="app-title">
<div>
<h1><i class="fa fa-th-list"></i>&nbsp;Acunetix Scanner</h1>
<p>Acunetix Vulnerability Scanner: Web Application Security</p>
</div>
<ul class="app-breadcrumb breadcrumb side">
<li class="breadcrumb-item"><i class="fa fa-home fa-lg"></i></li>
<li class="breadcrumb-item">Home</li>
<li class="breadcrumb-item active"><a href="#">Acunetix Scanner</a></li>
</ul>
</div>
<div class="row">
<div class="col-md-12">
<div class="tile">
<div class="tile-body">
<div id="sampleTable_wrapper" class="dataTables_wrapper container-fluid dt-bootstrap4 no-footer">
<table class="table table-hover table-bordered" id="sampleTable">
<thead>
<tr class="text-center">
<th>Address</th>
<th>Type</th>
<th>Status</th>
<th>Vulnerability</th>
<th>Description</th>
<th>Date</th>
<th>Manage</th>
</tr>
</thead>
<tbody>
{% for i in tasks_info %}
<tr class="text-center">
<td>
<a href="{{ i['address'] }}" target="view_window">{{ i['address'] }}</a>
</td>
<td>{{ i['profile_name'] }}</td>
<td>{{ i['status'] }}</td>
<td class="text-center">
<span class="badge badge-danger">{{ i['vul_high'] }}</span>
&nbsp;
<span class="badge badge-warning">{{ i['vul_medium'] }}</span>
&nbsp;
<span class="badge badge-info">{{ i['vul_low'] }}</span>
&nbsp;
<span class="badge badge-success">{{ i['vul_info'] }}</span>
</td>
<td>{{ i['desc'] }}</td>
<td>{{ i['start_date'] }}</td>
<td class="text-center">
<div class="hidden-sm hidden-xs action-buttons">
<a onclick="report_url('{{ i['scan_id'] }}')" role="button" data-target="#downloadReport" data-toggle="modal" href="#" title="Download Report">
<i class="fa fa-download"></i>
</a>
&nbsp;
&nbsp;
<a role="button" href="#" onclick="delete_scan('{{ i['scan_id'] }}')" title="Delete">
<i class="fa fa-trash-o"></i>
</a>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="modal" id="downloadReport" >
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Download Report</h5>
<button class="close" type="button" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
</div>
<div class="modal-body">
<form class="form-group row">
<div class="col-md-2"></div>
<div class="col-md-4" id="report_download_html">
<p>Generating...</p>
</div>
<div class="col-md-4" id="report_download_pdf">
{# <p>Please wait...</p>#}
</div>
<div class="col-md-2"></div>
</form>
<div class="modal-footer">
<p class="text-muted">If the download page returns 'Not Found(404)', please wait a few seconds to refresh the download page</p>
<button class="btn default " type="button" data-dismiss="modal">Close</button>
</div>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
</div>
</div>
</div>
</div>
</div>
</main>
{% endblock %}
{% block js %}
<!-- Data table plugin-->
<script type="text/javascript" src="static/js/plugins/jquery.dataTables.min.js"></script>
<script type="text/javascript" src="static/js/plugins/dataTables.bootstrap.min.js"></script>
<script src="static/js/plugins/sweetalert/sweetalert.min.js"></script>
<script src="static/js/server/acunetix-scanner.js"></script>
{% endblock %}

View File

@ -0,0 +1,152 @@
{% extends "base.html" %}
{% block css %}
<link href="static/css/duallistbox/bootstrap-duallistbox.css" rel="stylesheet">
{% endblock %}
{% block content %}
<main class="app-content">
<div class="app-title">
<div>
<h1><i class="fa fa-edit"></i>Advanced Options</h1>
</div>
<ul class="app-breadcrumb breadcrumb">
<li class="breadcrumb-item"><i class="fa fa-home fa-lg"></i></li>
<li class="breadcrumb-item">Config</li>
<li class="breadcrumb-item"><a href="#">Advanced Options</a></li>
</ul>
</div>
<div class="row">
<div class="col-md-6">
<div class="tile">
<h3 class="tile-title">Thread Settings</h3>
<div class="tile-body">
<form class="form-horizontal">
<div class="form-group row">
<label class="control-label col-md-3">PoC Scanner<span class="text-danger">*</span></label>
<div class="col-md-8">
<input class="form-control" value="{{ config_info['poc_thread'] }}" type="text" id="poc_thread" placeholder="Max simultaneous hosts per scan"/>
</div>
</div>
<div class="form-group row">
<label class="control-label col-md-3">Discovery<span class="text-danger">*</span></label>
<div class="col-md-8">
<input class="form-control" type="text" value="{{ config_info['discovery_thread'] }}" id='discovery_thread' placeholder="Max simultaneous hosts per scan">
</div>
</div>
<div class="form-group row">
<label class="control-label col-md-3">SubDomain<span class="text-danger">*</span></label>
<div class="col-md-8">
<input class="form-control" type="text" value="{{ config_info['subdomain_thread'] }}" id='subdomain_thread' placeholder="Max simultaneous hosts per scan">
</div>
</div>
<div class="form-group row">
<label class="control-label col-md-3">Port Scanner<span class="text-danger">*</span></label>
<div class="col-md-8">
<input class="form-control" type="text" value="{{ config_info['port_thread'] }}" id='port_thread' placeholder="Max simultaneous hosts per scan">
</div>
</div>
<div class="form-group row">
<label class="control-label col-md-3">Auth Tester<span class="text-danger">*</span></label>
<div class="col-md-8">
<input class="form-control" type="text" value="{{ config_info['auth_tester_thread'] }}" id='auth_tester_thread' placeholder="Max simultaneous hosts per scan">
</div>
</div>
<div class="form-group row">
<label class="control-label col-md-3">Discovery Time<span class="text-danger">*</span></label>
<div class="col-md-8">
<input class="form-control" type="text" value="{{ config_info['discovery_time'] }}" name="discovery_time_val" id='discovery_time_setting' placeholder="-">
</div>
</div>
</form>
</div>
<div class="tile-footer"><a class="btn btn-primary update-thread-config" href="#"><i class="fa fa-check-circle"></i> Submit</a></div>
</div>
</div>
<div class="col-md-6">
<div class="tile">
<h3 class="tile-title">Subdomain Dictionary</h3>
<div class="tile-body">
<form class="form-horizontal">
<div class="form-group row">
<div class="col-md-6">
<label class="control-label no-padding-right">Second-level domain<span class="text-danger">*</span></label>
<textarea class="form-control" id='subdomain_dict_2' type="text" placeholder="One value per line" rows="10">{{ config_info['subdomain_dict_2'] }}</textarea>
</div>
<div class="col-md-6">
<label class="control-label no-padding-right">Three-level domain<span class="text-danger">*</span></label>
<textarea class="form-control" id='subdomain_dict_3' type="text" placeholder="One value per line" rows="10">{{ config_info['subdomain_dict_3'] }}</textarea>
</div>
</div>
</form>
</div>
<div class="tile-footer"><a class="btn btn-primary update-subdomain-dict-config" href="#"><i class="fa fa-check-circle"></i> Submit</a></div>
</div>
</div>
<div class="col-md-6">
<div class="tile">
<h3 class="tile-title">Thread Settings</h3>
<div class="tile-body">
<form class="form-horizontal">
<div class="form-group row">
<label class="control-label col-md-3">Port List<span class="text-danger">*</span></label>
<div class="col-md-8">
<textarea class="form-control" type="text" id="port_list" rows="6" placeholder="Server Discovery Port">{{ config_info['port_list'] }}</textarea>
</div>
</div>
</form>
</div>
<div class="tile-footer"><a class="btn btn-primary update-port-config" href="#"><i class="fa fa-check-circle"></i> Submit</a></div>
</div>
</div>
<div class="col-md-6">
<div class="tile">
<h3 class="tile-title">Username & Password</h3>
<div class="tile-body">
<form class="form-horizontal">
<div class="form-group row">
<div class="col-md-6">
<label class="control-label no-padding-right">Username<span class="text-danger">*</span></label>
<textarea class="form-control" id='username_list' type="text" placeholder="One username per line" rows="10">{{ config_info['username_dict'] }}</textarea>
</div>
<div class="col-md-6">
<label class="control-label no-padding-right">Password<span class="text-danger">*</span></label>
<textarea class="form-control" id='password_list' type="text" placeholder="One password per line" rows="10">{{ config_info['password_dict'] }}</textarea>
</div>
</div>
</form>
</div>
<div class="tile-footer"><a class="btn btn-primary update-user-passwd" href="#"><i class="fa fa-check-circle"></i> Submit</a></div>
</div>
</div>
</div>
</main>
{% block js %}
<script src="static/js/plugins/sweetalert/sweetalert.min.js"></script>
<script type="text/javascript" src="static/js/plugins/laydate/laydate.js"></script>
<script src="static/js/server/settings.js"></script>
<script>
laydate.render({
elem: '#discovery_time_setting',
type: 'time',
lang: 'en'
});
</script>
{% endblock %}
{% endblock %}

View File

@ -0,0 +1,277 @@
{% extends "base.html" %}
{% block css %}
<link href="static/css/duallistbox/bootstrap-duallistbox.css" rel="stylesheet">
{% endblock %}
{% block content %}
<main class="app-content">
<div class="app-title">
<div>
<h1><i class="fa fa-th-list"></i>&nbsp;Asset Management</h1>
<p></p>
</div>
<ul class="app-breadcrumb breadcrumb side">
<li class="breadcrumb-item"><i class="fa fa-home fa-lg"></i></li>
<li class="breadcrumb-item">Home</li>
<li class="breadcrumb-item active"><a href="#">Asset List</a></li>
</ul>
</div>
<div class="row">
<div class="col-md-12">
<div class="tile">
<div class="tile-body">
<table class="table table-hover table-bordered" id="sampleTable">
<thead>
<tr class="text-center">
<th>Name</th>
<th>Dept</th>
<th>Admin</th>
<th>Discover</th>
<th>asset_date</th>
<th>Manage</th>
</tr>
</thead>
<tbody>
{% for i in asset_info %}
<tr>
<td>
<a href="asset-services?asset={{ i['_id'] }}">{{ i['asset_name'] }}</a>
</td>
<td>{{ i['dept_name'] }}</td>
<td>{{ i['admin_name'] }}</td>
<td>{{ i['discover_option'] }}</td>
<td>{{ i['asset_date'] }}</td>
<td class="text-center">
<a onclick="get_asset_host('{{ i['_id'] }}')" role="button" href="#" title="New Vul Scan" data-toggle="modal" data-target="#newScan">
<i class="fa fa-bug"></i>
</a>
&nbsp;
&nbsp;
<a onclick="get_asset_host('{{ i['_id'] }}')" role="button" href="#" title="New Auth Tester" data-toggle="modal" data-target="#newAuthtest">
<i class="fa fa-gavel"></i>
</a>
&nbsp;
&nbsp;
<a onclick="asset_info('{{ i['_id'] }}')" role="button" data-toggle="modal" href="#" title="Edit" data-target="#editAsset">
<i class="fa fa-pencil"></i>
</a>
&nbsp;
&nbsp;
<a onclick="delete_asset('{{ i['_id'] }}')" role="button" href="#" title="Delete">
<i class="fa fa-trash-o"></i>
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="modal fade" id="editAsset" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"><!-- /edit-modal -->
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title" id="myModalLabel">
Edit Asset
</h4>
</div>
<div class="modal-body" >
<form class="form-horizontal" role="form">
<div class="form-group">
<label for="name"> Name <span class="text-danger">*</span></label>
<input type="text" class="form-control" name="asset_name_edit" id="asset_name_edit" placeholder="Loading...">
</div>
<div class="form-group">
<label for="name"> Asset ID</label>
<input type="text" title="Asset ID" class="form-control" name="asset_id_edit" id="asset_id_edit" disabled="disabled">
</div>
<div class="form-group">
<label for="name"> Host <span class="text-danger">*</span></label>
<textarea class="form-control" rows="3" id="asset_host_edit" name="asset_host_edit" placeholder="Loading..."></textarea>
</div>
<div class="form-group">
<label for="name"> Dept <span class="text-danger">*</span></label>
<input type="text" class="form-control" id="dept_name_edit" name="dept_name_edit">
</div>
<div class="form-group">
<label for="name"> Admin <span class="text-danger">*</span></label>
<input type="text" class="form-control" id="admin_name_edit" name="admin_name_edit">
</div>
<div class="toggle lg">
<label>Discover Option
<input type="checkbox" checked><span class="button-indecator"></span>
</label>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal" aria-hidden="true">Cancel
</button>
<button class="btn btn-primary asset-update" type="button">
<span>Submit</span> <i class="fa fa-send m-l-10"></i>
</button>
</div>
</form>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal-end -->
<div class="modal fade" id="newScan" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"><!-- /scan-modal -->
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title" id="myModalLabel">
New Scan
</h4>
</div>
<div class="modal-body" >
<form class="form-horizontal" role="form">
<div class="form-group">
<label class="control-label no-padding-right">Task Name <span class="text-danger">*</span></label>
<div>
<input type="text" class="form-control" id="task_name" name="taskname_val" placeholder="Task Name">
</div>
</div>
<div class="space-6"></div>
<div class="form-group">
<label class="control-label no-padding-right">Recursion</label>
<div>
<select class="form-control" id="form-field-plan" title="Recursion" name="recursion_val">
<option value="0">Once</option>
<option value="1">Every day</option>
<option value="7">Every week</option>
<option value="30">Every month</option>
</select>
</div>
</div>
<div class="form-group">
<label class="control-label no-padding-right">Plugins Select <span class="text-danger">*</span></label>
<div>
<select multiple="multiple" size="6" name="plugin_list" title="Plugin Select">
{% for a in plugin_info %}
<option value="{{ a['_id'] }}">{{ a['plugin_name'] }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="hr hr-16 hr-dotted"></div>
<div class="form-group">
<label class="control-label no-padding-right">Target <span class="text-danger">*</span></label>
<div>
<textarea class="form-control" rows="5" id="scan_target_list" title="Target" name="target_val" placeholder="Loading..."></textarea>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal" aria-hidden="true">Cancel</button>
<button class="btn btn-primary " id="asset-scan" type="button">
<span>Submit</span> <i class="fa fa-send m-l-10"></i>
</button>
</div>
</form>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal-end -->
<div class="modal fade" id="newAuthtest" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"><!-- /scan-modal -->
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title" id="myModalLabel">
New Auth Tester
</h4>
</div>
<div class="modal-body" >
<form class="form-horizontal" role="form">
<div class="form-group">
<label class="control-label no-padding-right">Task Name <span class="text-danger">*</span></label>
<div>
<input type="text" class="form-control" name="auth_task_name" placeholder="Task Name">
</div>
</div>
<div class="form-group">
<label class="control-label no-padding-right">Recursion</label>
<div>
<select class="form-control" id="form-field-plan" title="Recursion" name="auth_recursion">
<option value="0">Once</option>
<option value="1">Every day</option>
<option value="7">Every week</option>
<option value="30">Every month</option>
</select>
</div>
</div>
<div class="form-group">
<label class="control-label no-padding-right">Args</label>
<div>
<input class="form-control" name="auth_args" title="Args" placeholder=""/>
</div>
</div>
<div class="space-6"></div>
<div class="form-group">
<label class="control-label no-padding-right">Protocols Select <span class="text-danger">*</span></label>
<div>
<select multiple="multiple" size="6" name="auth_service_list" title="Plugin Select">
{% for a in protocols %}
<option value="{{ a }}">{{ a | upper }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="hr hr-16 hr-dotted"></div>
<div class="form-group">
<label class="control-label no-padding-right">Target <span class="text-danger">*</span></label>
<div>
<textarea class="form-control" rows="5" id="auth_target_list" title="Target" name="auth_target_list" placeholder="Loading..."></textarea>
</div>
</div>
<div class="form-group row">
<div class="col-md-6">
<label class="control-label no-padding-right">Username<span class="text-danger">*</span></label>
<div>
<textarea class="form-control" placeholder="One username per line" rows="6" name="auth_username_list">{{ username_list }}</textarea>
</div>
</div>
<div class="col-md-6">
<label class="control-label no-padding-right">Password<span class="text-danger">*</span></label>
<div>
<textarea class="form-control" placeholder="One password per line" rows="6" name="auth_password_list">{{ password_list }}</textarea>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal" aria-hidden="true">Cancel</button>
<button class="btn btn-primary " id="asset-auth-tasks" type="button">
<span>Submit</span> <i class="fa fa-send m-l-10"></i>
</button>
</div>
</form>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal-end -->
</div>
</div>
</div>
</div>
</main>
{% endblock %}
{% block js %}
<!-- Data table plugin-->
<script type="text/javascript" src="static/js/plugins/jquery.dataTables.min.js"></script>
<script type="text/javascript" src="static/js/plugins/dataTables.bootstrap.min.js"></script>
<script src="static/js/plugins/sweetalert/sweetalert.min.js"></script>
<script src="static/js/jquery/jquery.bootstrap-duallistbox.js"></script>
<script src="static/js/server/asset-management.js"></script>
{% endblock %}

View File

@ -0,0 +1,167 @@
{% extends "base.html" %}
{% block css %}
<link href="static/css/duallistbox/bootstrap-duallistbox.css" rel="stylesheet">
{% endblock %}
{% block content %}
<main class="app-content">
<div class="app-title">
<div>
<h1><i class="fa fa-th-list"></i>&nbsp;Services List</h1>
<p></p>
</div>
<ul class="app-breadcrumb breadcrumb side">
<li class="breadcrumb-item"><i class="fa fa-home fa-lg"></i></li>
<li class="breadcrumb-item">Home</li>
<li class="breadcrumb-item active"><a href="#">Services List</a></li>
</ul>
</div>
<div class="row">
<div class="col-md-12">
<div class="tile">
<div class="tile-body">
<div id="sampleTable_wrapper" class="dataTables_wrapper container-fluid dt-bootstrap4 no-footer">
<div class="row"><div class="col-sm-12 col-md-6">
<div class="dataTables_length" id="sampleTable_length">
<a class="btn btn-primary" href="#" onclick="newScan()" role="button" title="New Scan" data-toggle="modal" data-target="#newScan">
<i class="fa fa-gitlab fa-lg"></i> New Scan</a>
<br>
<br>
</div>
<div class="modal fade" id="newScan" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"><!-- /scan-modal -->
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title" id="myModalLabel">
New Scan
</h4>
</div>
<div class="modal-body" >
<form class="form-horizontal" role="form">
<div class="form-group">
<label class="control-label no-padding-right">Task Name <span class="text-danger">*</span></label>
<div>
<input type="text" class="form-control" id="task_name" name="taskname_val" placeholder="Task Name">
</div>
</div>
<div class="space-6"></div>
<div class="form-group">
<label class="control-label no-padding-right">Recursion</label>
<div>
<select class="form-control" id="form-field-plan" title="Recursion" name="recursion_val">
<option value="0">Once</option>
<option value="1">Every day</option>
<option value="7">Every week</option>
<option value="30">Every month</option>
</select>
</div>
</div>
<div class="form-group">
<label class="control-label no-padding-right">Plugin Select <span class="text-danger">*</span></label>
<div>
<select multiple="multiple" size="6" name="plugin_list" title="Plugin Select">
{% for a in plugin_info %}
<option value="{{ a['_id'] }}">{{ a['plugin_name'] }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="hr hr-16 hr-dotted"></div>
<div class="form-group">
<label class="control-label no-padding-right">Target <span class="text-danger">*</span></label>
<div>
<textarea class="form-control" rows="5" id="scan_target_list" title="Target" name="target_val" placeholder="Loading..."></textarea>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal" aria-hidden="true">Cancel</button>
<button class="btn btn-primary " id="server-scan" type="button">
<span>Submit</span> <i class="fa fa-send m-l-10"></i>
</button>
</div>
</form>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal-end -->
</div>
</div>
<table class="table table-hover table-bordered" id="sampleTable">
<thead>
<tr class="text-center">
<th>
<input title="checkbox_all" onclick="selectAll()" type="checkbox" name="allSelect" value="1" />
</th>
<th>Host</th>
<th>Port</th>
<th>Server</th>
<th>Version</th>
<th>Asset</th>
<th>Date</th>
<th>Manage</th>
</tr>
</thead>
<tbody>
{% for i in server_data %}
<tr >
<td class="text-center">
<input title="checkbox" type="checkbox" name='select_id' value="{{ i['_id'] }}" />
</td>
<td><a onclick="server_info('{{ i['_id'] }}')" role="button" data-target="#serverInfo" data-toggle="modal" href="#" title="Plugin Info">{{ i['host'] }}</a></td>
<td>{{ i['port'] }}</td>
<td>{{ i['product'] }}</td>
<td>{{ i['version'] }}</td>
<td>{{ i['asset_name'] }}</td>
<td>{{ i['date'] }}</td>
<td class="text-center">
<div class="hidden-sm hidden-xs action-buttons">
<a onclick="server_info('{{ i['_id'] }}')" role="button" data-target="#serverInfo" data-toggle="modal" href="#" title="Plugin Info">
<i class="fa fa-search-plus"></i>
</a>
&nbsp;
&nbsp;
&nbsp;
<a href="asset-services?delete={{ i['_id'] }}" title="Delete">
<i class="fa fa-trash-o"></i>
</a>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="modal" id="serverInfo" >
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Server Info</h5>
<button class="close" type="button" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
</div>
<div class="modal-body">
<pre id="server_info" title="Plugin Info">Loading...</pre>
</div>
<div class="modal-footer">
<button class="btn btn-primary" type="button" data-dismiss="modal">Close</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
</div>
</div>
</div>
</div>
</main>
{% endblock %}
{% block js %}
<!-- Data table plugin-->
<script type="text/javascript" src="static/js/plugins/jquery.dataTables.min.js"></script>
<script type="text/javascript" src="static/js/plugins/dataTables.bootstrap.min.js"></script>
<script src="static/js/plugins/sweetalert/sweetalert.min.js"></script>
<script src="static/js/jquery/jquery.bootstrap-duallistbox.js"></script>
<script src="static/js/server/asset-services-list.js"></script>
{% endblock %}

View File

@ -0,0 +1,112 @@
{% extends "base.html" %}
{% block css %}
{% endblock %}
{% block content %}
<main class="app-content">
<div class="app-title">
<div>
<h1><i class="fa fa-th-list"></i>&nbsp;Tasks Management</h1>
<p></p>
</div>
<ul class="app-breadcrumb breadcrumb side">
<li class="breadcrumb-item"><i class="fa fa-home fa-lg"></i></li>
<li class="breadcrumb-item">Home</li>
<li class="breadcrumb-item active"><a href="#">Tasks Management</a></li>
</ul>
</div>
<div class="row">
<div class="col-md-12">
<div class="tile">
<div class="tile-body">
<table class="table table-hover table-bordered" id="sampleTable">
<thead>
<tr class="text-center">
<th>Name</th>
<th>Service</th>
<th>Recursion</th>
<th>Status</th>
<th>Count</th>
<th>Date</th>
<th>Manage</th>
</tr>
</thead>
<tbody>
{% for i in auth_tasks %}
<tr class="text-center">
<td>
<a href="week-passwd-list?task={{ i['_id'] }}">{{ i['task_name'] }}</a>
</td>
<td>{{ i['service'] | join(',') | truncate(15 , True) | upper}}</td>
{% if i['recursion'] == 0 %}
<td>Once</td>
{% elif i['recursion'] == 1 %}
<td>Every day</td>
{% elif i['recursion'] == 7 %}
<td>Every week</td>
{% elif i['recursion'] == 30 %}
<td>Every month</td>
{% endif %}
<td>{{ i['status'] }}</td>
<td><span class="badge badge-primary">{{ i['week_count'] }}</span></td>
<td>{{ i['date'] }}</td>
<td class="text-center">
<a onclick="get_target_host('{{ i['_id'] }}')" role="button" href="#" title="Target Info" data-toggle="modal" data-target="#targetInfo">
<i class="fa fa-align-justify"></i>
</a>
&nbsp;
&nbsp;
&nbsp;
<a onclick="rescan_task('{{ i['_id'] }}')" role="button" href="#" title="Rescan">
<i class="fa fa-refresh"></i>
</a>
&nbsp;
&nbsp;
<a onclick="delete_task('{{ i['_id'] }}')" role="button" href="#" title="Delete">
<i class="fa fa-trash-o"></i>
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="modal fade" id="targetInfo" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"><!-- /edit-modal -->
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title" id="myModalLabel">
Target Info
</h4>
</div>
<div class="modal-body" >
<form class="form-horizontal" role="form">
<div class="form-group">
<pre class="form-control" id="target_info_data">Loading...</pre>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal" aria-hidden="true">
Cancel
</button>
</div>
</form>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal-end -->
</div>
</div>
</div>
</div>
</main>
{% endblock %}
{% block js %}
<!-- Data table plugin-->
<script type="text/javascript" src="static/js/plugins/jquery.dataTables.min.js"></script>
<script type="text/javascript" src="static/js/plugins/dataTables.bootstrap.min.js"></script>
<script src="static/js/plugins/sweetalert/sweetalert.min.js"></script>
<script src="static/js/server/auth-tester-tasks.js"></script>
{% endblock %}

View File

@ -0,0 +1,172 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Fuxi Scanner</title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Main CSS-->
{% block css %}
{% endblock %}
<link rel="stylesheet" type="text/css" href="static/css/main.css">
<link rel="stylesheet" type="text/css" href="static/css/font-awesome-4.7.0/css/font-awesome.css">
</head>
<body class="app sidebar-mini rtl">
<!-- Navbar-->
<header class="app-header"><a class="app-header__logo" href="index">Fuxi Scanner</a>
<!-- Sidebar toggle button--><a class="app-sidebar__toggle" href="#" data-toggle="sidebar" aria-label="Hide Sidebar"></a>
<!-- Navbar Right Menu-->
<ul class="app-nav">
<li class="app-search">
<form method="post" action="search">
<input class="app-search__input" type="search" name="search" placeholder="Search">
<button class="app-search__button search_btn" type="submit"><i class="fa fa-search"></i></button>
</form>
</li>
<!--Notification Menu-->
<li class="dropdown"><a class="app-nav__item" href="#" data-toggle="dropdown" aria-label="Show notifications"><i class="fa fa-bell-o fa-lg"></i></a>
<div id="notification_update">
</div>
</li>
<!-- User Menu-->
<li class="dropdown"><a class="app-nav__item" href="#" data-toggle="dropdown" aria-label="Open Profile Menu"><i class="fa fa-user fa-lg"></i></a>
<ul class="dropdown-menu settings-menu dropdown-menu-right">
<li><a class="dropdown-item" href="advanced-option"><i class="fa fa-cog fa-lg"></i> Settings</a></li>
<li><a class="dropdown-item" href="https://fuxi-scanner.com" target="_blank"><i class="fa fa-user fa-lg"></i> About</a></li>
<li><div class="dropdown-divider"></div><a class="dropdown-item" href="login-out"><i class="fa fa-sign-out fa-lg"></i> Logout</a></li>
</ul>
</li>
</ul>
</header>
<!-- Sidebar menu-->
<div class="app-sidebar__overlay" data-toggle="sidebar"></div>
<aside class="app-sidebar">
<ul class="app-menu">
<li>
<a class="app-menu__item" href="dashboard">
<i class="app-menu__icon fa fa-line-chart"></i>
<span class="app-menu__label">Dashboard</span>
</a>
</li>
<li class="treeview">
<a class="app-menu__item" href="#" data-toggle="treeview">
<i class="app-menu__icon fa fa-bug"></i>
<span class="app-menu__label">Vulnerability Scanner</span>
<i class="treeview-indicator fa fa-angle-right"></i>
</a>
<ul class="treeview-menu">
<li><a class="treeview-item" href="new-scan"><i class="icon fa fa-edit"></i>New Scan</a></li>
<li><a class="treeview-item" href="task-management"><i class="icon fa fa-indent"></i>Tasks</a></li>
<li><a class="treeview-item" href="vulnerability"><i class="icon fa fa-circle-o"></i> Vulnerabilities</a></li>
<li><a class="treeview-item" href="plugin-management"><i class="icon fa fa-gitlab"></i> Plugins</a></li>
</ul>
</li>
<li class="treeview">
<a class="app-menu__item" href="#" data-toggle="treeview">
<i class="app-menu__icon fa fa-calendar-minus-o"></i>
<span class="app-menu__label">Asset Management</span>
<i class="treeview-indicator fa fa-angle-right"></i>
</a>
<ul class="treeview-menu">
<li><a class="treeview-item" href="new-asset"><i class="icon fa fa-edit"></i>New Asset</a></li>
<li><a class="treeview-item" href="asset-management"><i class="icon fa fa-indent"></i>Asset</a></li>
<li><a class="treeview-item" href="asset-services"><i class="icon fa fa-circle-o"></i> Services</a></li>
</ul>
</li>
<li class="treeview">
<a class="app-menu__item" href="#" data-toggle="treeview">
<i class="app-menu__icon fa fa-gavel"></i>
<span class="app-menu__label">Authentication Tester</span>
<i class="treeview-indicator fa fa-angle-right"></i>
</a>
<ul class="treeview-menu">
<li><a class="treeview-item" href="new-auth-tester"><i class="icon fa fa-pencil"></i>Add Scan</a></li>
<li><a class="treeview-item" href="auth-tester-tasks"><i class="icon fa fa-indent"></i>Tasks Management</a></li>
<li><a class="treeview-item" href="week-passwd-list"><i class="icon fa fa-file-text"></i>Week Passwd List</a></li>
</ul>
</li>
<li class="treeview">
<a class="app-menu__item" href="#" data-toggle="treeview">
<i class="app-menu__icon fa fa-deviantart"></i>
<span class="app-menu__label">Subdomain Brute</span>
<i class="treeview-indicator fa fa-angle-right"></i>
</a>
<ul class="treeview-menu">
<li><a class="treeview-item" href="subdomain-brute"><i class="icon fa fa-pencil"></i>New Domain</a></li>
<li><a class="treeview-item" href="subdomain-list"><i class="icon fa fa-indent"></i>Result</a></li>
</ul>
</li>
{# <li class="treeview">#}
{# <a class="app-menu__item" href="#" data-toggle="treeview">#}
{# <i class="app-menu__icon fa fa-crop"></i>#}
{# <span class="app-menu__label">DirBuster</span>#}
{# <i class="treeview-indicator fa fa-angle-right"></i>#}
{# </a>#}
{# <ul class="treeview-menu">#}
{# <li><a class="treeview-item" href="subdomain-brute"><i class="icon fa fa-pencil"></i>New Scan</a></li>#}
{# <li><a class="treeview-item" href="subdomain-list"><i class="icon fa fa-indent"></i>Result</a></li>#}
{# </ul>#}
{# </li>#}
<li class="treeview">
<a class="app-menu__item" href="#" data-toggle="treeview">
<i class="app-menu__icon fa fa-heartbeat"></i>
<span class="app-menu__label">Acunetix Scanner</span>
<i class="treeview-indicator fa fa-angle-right"></i>
</a>
<ul class="treeview-menu">
<li><a class="treeview-item" href="acunetix-scanner"><i class="icon fa fa-pencil"></i>New Scanner</a></li>
<li><a class="treeview-item" href="acunetix-tasks"><i class="icon fa fa-gear"></i>Tasks Management</a></li>
</ul>
</li>
<li>
<a class="app-menu__item" href="port-scanner">
<i class="app-menu__icon fa fa-eercast"></i>
<span class="app-menu__label">Port Scanner</span>
{# <i class="treeview-indicator fa fa-angle-right"></i>#}
</a>
</li>
<li class="treeview">
<a class="app-menu__item" href="#" data-toggle="treeview">
<i class="app-menu__icon fa fa-cogs"></i>
<span class="app-menu__label">Settings</span>
<i class="treeview-indicator fa fa-angle-right"></i>
</a>
<ul class="treeview-menu">
<li><a class="treeview-item" href="advanced-option"><i class="icon fa fa-pencil"></i>Advanced Options</a></li>
{# <li><a class="treeview-item" href="system-config"><i class="icon fa fa-gear"></i>System Config</a></li>#}
</ul>
</li>
</ul>
</aside>
{% block content %}
{% endblock %}
<script src="static/js/jquery/jquery-3.2.1.min.js"></script>
<script src="static/js/popper.min.js"></script>
<script src="static/js/bootstrap/bootstrap.min.js"></script>
<script src="static/js/main.js"></script>
<script src="static/js/plugins/pace.min.js"></script>
{# <script src="static/js/server/update.js"></script>#}
{% block js %}
{% endblock %}
</body>
</html>

View File

@ -0,0 +1,330 @@
{% extends "base.html" %}
{% block css %}
<link href="static/css/duallistbox/bootstrap-duallistbox.css" rel="stylesheet">
{% endblock %}
{% block content %}
<main class="app-content">
<div class="app-title">
<div>
<h1><i class="fa fa-dashboard"></i> Dashboard</h1>
</div>
<ul class="app-breadcrumb breadcrumb">
<li class="breadcrumb-item"><i class="fa fa-home fa-lg"></i></li>
<li class="breadcrumb-item"><a href="#">Dashboard</a></li>
</ul>
</div>
<div class="row">
<div class="col-md-6 col-lg-3">
<div class="widget-small danger coloured-icon">
<a href="vulnerability" style="text-decoration:none;">
<i class="icon fa fa-bug fa-3x"></i>
</a>
<div class="info">
<h4>Vulnerability</h4>
<p><b>{{ dashboard_data['vul_count'] }}</b></p>
</div>
</div>
</div>
<div class="col-md-6 col-lg-3">
<div class="widget-small info coloured-icon">
<a href="plugin-management" style="text-decoration:none;">
<i class="icon fa fa-gitlab fa-3x"></i>
</a>
<div class="info">
<h4>Plugin</h4>
<p><b>{{ dashboard_data['plugin_count'] }}</b></p>
</div>
</div>
</div>
<div class="col-md-6 col-lg-3">
<div class="widget-small primary coloured-icon">
<a href="week-passwd-list" style="text-decoration:none;">
<i class="icon fa fa-gg fa-3x"></i>
</a>
<div class="info">
<h4 >Week Password</h4>
<p><b>{{ dashboard_data['week_passwd_count'] }}</b></p>
</div>
</div>
</div>
<div class="col-md-6 col-lg-3">
<div class="widget-small warning coloured-icon">
<a href="asset-services" style="text-decoration:none;">
<i class="icon fa fa-snowflake-o fa-3x"></i>
</a>
<div class="info">
<h4>Host</h4>
<p><b>{{ dashboard_data['server_count'] }}</b></p>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="tile">
<h3 class="tile-title">Vulnerability Trend</h3>
<div>
<canvas class="embed-responsive-item" id="vulTrend"></canvas>
</div>
</div>
</div>
<div class="col-md-6">
<div class="tile">
<h3 class="tile-title">Top 10 Vulnerability</h3>
<div>
<canvas class="embed-responsive-item" id="vulStats"></canvas>
</div>
</div>
</div>
<div class="col-md-6">
<div class="tile">
<h3 class="tile-title">Host Trend</h3>
<div>
<canvas class="embed-responsive-item" id="hostTrend"></canvas>
</div>
</div>
</div>
<div class="col-md-6">
<div class="tile">
<h3 class="tile-title">Week Password</h3>
<div>
<canvas class="embed-responsive-item" id="weekpasswordStats"></canvas>
</div>
</div>
</div>
</div>
{# <div class="row">#}
{# <div class="col-md-4">#}
{# <div class="tile">#}
{# <h3 class="tile-title">Security Advisories</h3>#}
{# <div>#}
{# <div id="360Rss"></div>#}
{# </div>#}
{# </div>#}
{# </div>#}
{##}
{# <div class="col-md-4">#}
{# <div class="tile">#}
{# <h3 class="tile-title">Security News</h3>#}
{# <div>#}
{# <div id="freebufRss"></div>#}
{# </div>#}
{# </div>#}
{# </div>#}
{##}
{# <div class="col-md-4">#}
{# <div class="tile">#}
{# <h3 class="tile-title">Newest PoC</h3>#}
{# <div>#}
{# <div id="seebugRss"></div>#}
{# </div>#}
{# </div>#}
{# </div>#}
{# </div>#}
</main>
{% endblock %}
{% block js %}
<!-- Data table plugin-->
<script type="text/javascript" src="static/js/plugins/Chart.js"></script>
<script src="static/js/plugins/FeedEk.js"></script>
<script>
var vulStats = document.getElementById("vulStats");
var vulTrend = document.getElementById("vulTrend");
var hostTrend = document.getElementById("hostTrend");
var weekpasswordStats = document.getElementById("weekpasswordStats");
var vulChart = new Chart(vulTrend, {
type: 'line',
data: {
labels: [
{% for vul_date in dashboard_data['vul_trend_date'] %}
'{{ vul_date }}',
{% endfor %}
],
datasets: [{
label: 'Vulnerability',
data: [
{% for count in dashboard_data['vul_trend_count'] %}
{{ count }},
{% endfor %}
],
fillColor: "rgba(220,220,220,0.2)",
strokeColor: "rgba(220,220,220,1)",
borderColor: '#35c9a3',
pointColor: "rgba(220,220,220,1)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(220,220,220,1)",
},
{
label: 'Week Password',
data: [
{% for count in dashboard_data['week_passwd_trend'] %}
{{ count }},
{% endfor %}
],
fillColor: "rgba(220,220,220,0.2)",
strokeColor: "rgba(220,220,220,1)",
borderColor: '#55acc9',
pointColor: "rgba(220,220,220,1)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(220,220,220,1)",
}
],
},
options: {}
});
var hostLine = new Chart(hostTrend, {
type: 'line',
data: {
labels: [
{% for a in dashboard_data['host_trend_date'] %}
'{{ a }}',
{% endfor %}
],
datasets: [{
label: 'Host',
data: [
{% for b in dashboard_data['host_trend_count'] %}
{{ b }},
{% endfor %}
],
fillColor: "rgba(220,220,220,0.2)",
strokeColor: "rgba(220,220,220,1)",
borderColor: '#35c9a3',
pointColor: "rgba(220,220,220,1)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(220,220,220,1)",
},
{
label: 'Server',
data: [
{% for s in dashboard_data['server_trend_count'] %}
{{ s }},
{% endfor %}
],
fillColor: "rgba(220,220,220,0.2)",
strokeColor: "rgba(220,220,220,1)",
borderColor: '#55acc9',
pointColor: "rgba(220,220,220,1)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(220,220,220,1)",
}
],
},
options: {}
});
var vulStats = new Chart(vulStats,{
type: 'pie',
data: {
datasets: [{
data: [
{% for count in dashboard_data['vul_stats_count'] %}
'{{ count }}',
{% endfor %}
],
backgroundColor: [
'#1abc9c',
'#3498db',
'#9b59b6',
'#f1c40f',
'#e67e22',
'#e74c3c',
'#2c3e50',
'#f39c12',
'#badc58',
'#7ed6df'
],
}],
labels: [
{% for name in dashboard_data['vul_stats_name'] %}
'{{ name }}',
{% endfor %}
],
color: "#46BFBD",
highlight: "#5AD3D1",
},
options: {
{#responsive: false,#}
}
});
var passwdStats = new Chart(weekpasswordStats,{
type: 'pie',
data: {
datasets: [{
data: [
{% for p_c in dashboard_data['password_stats_count'] %}
'{{ p_c }}',
{% endfor %}
],
backgroundColor: [
'#1abc9c',
'#3498db',
'#9b59b6',
'#f1c40f',
'#e67e22',
'#e74c3c',
'#2c3e50',
'#f39c12',
'#badc58',
'#7ed6df'
],
}],
labels: [
{% for passwd in dashboard_data['password_stats_val'] %}
'{{ passwd }}',
{% endfor %}
],
color: "#46BFBD",
highlight: "#5AD3D1",
},
options: {
{#responsive: false,#}
}
});
</script>
<script>
$(document).ready(function () {
$('#seebugRss').FeedEk({
FeedUrl:'https://www.seebug.org/rss/new/',
MaxCount: 6,
ShowDesc: false,
ShowPubDate: false,
});
$('#freebufRss').FeedEk({
FeedUrl:'http://www.freebuf.com/feed',
MaxCount: 6,
ShowDesc: false,
ShowPubDate: false,
});
$('#360Rss').FeedEk({
FeedUrl:'https://cert.360.cn/feed',
MaxCount: 6,
ShowDesc: false,
ShowPubDate: false,
});
});
</script>
{% endblock %}

View File

@ -0,0 +1,86 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Main CSS-->
<link rel="stylesheet" type="text/css" href="static/css/main.css">
<!-- Font-icon css-->
<link rel="stylesheet" type="text/css" href="static/font/css/font-awesome.min.css">
<title>Fuxi - Login</title>
</head>
<body>
<section class="material-half-bg">
<div class="cover"></div>
</section>
<section class="lockscreen-content">
<div class="lock-box">
<p class="text-center text-muted">Account Locked</p>
<form class="unlock-form" action="" method="post">
<div class="form-group">
<label class="control-label">PASSWORD</label>
<input class="form-control" type="password" name="password">
</div>
<div class="form-group btn-container">
<button class="btn btn-primary btn-block" type="submit"><i class="fa fa-lock fa-lg"></i>Login </button>
</div>
</form>
</div>
</section>
<script src="static/js/jquery/jquery-3.2.1.min.js"></script>
<script src="static/js/popper.min.js"></script>
<script src="static/js/bootstrap/bootstrap.min.js"></script>
<script src="static/js/main.js"></script>
<script src="static/js/plugins/pace.min.js"></script>
<script src="static/js/plugins/sweetalert/sweetalert.min.js"></script>
<script>
$(function () {
$(".login").click(function() {
const data = {
"password": $('[name="password"]').val()
};
$.ajax({
type: "POST",
url: "/login",
data: data,
success: function(e){
if (e === "success") {
swal({
title: "Successfully",
text: "",
type: "success",
timer: 700,
confirmButtonText: "OK",
closeOnConfirm: false
},
function(){
location.href = "/index";
});
} else {
swal({
title: e,
text: "",
type: "error",
confirmButtonColor: "#DD6B55",
confirmButtonText: "Cancel",
closeOnConfirm: false
},
function(){
location.href = "/login";
});
}
}
});
});
});
</script>
</body>
</html>

View File

@ -0,0 +1,83 @@
{% extends "base.html" %}
{% block css %}
{% endblock %}
{% block content %}
<main class="app-content">
<div class="app-title">
<div>
<h1><i class="fa fa-edit"></i> New Asset</h1>
</div>
<ul class="app-breadcrumb breadcrumb">
<li class="breadcrumb-item"><i class="fa fa-home fa-lg"></i></li>
<li class="breadcrumb-item">Home</li>
<li class="breadcrumb-item"><a href="#">New Asset</a></li>
</ul>
</div>
<div class="row">
<div class="col-md-12">
<div class="tile">
<div class="row">
<div class="col-lg-2">
</div>
<div class="col-lg-8">
<form class="form-horizontal">
<div class="form-group row">
<label class="control-label col-md-3">Asset Name <span class="text-danger">*</span></label>
<div class="col-md-8">
<input class="form-control" name="asset_name" type="text" placeholder="Asset Name">
</div>
</div>
<div class="form-group row">
<label class="control-label col-md-3">Host <span class="text-danger">*</span></label>
<div class="col-md-8">
<textarea class="form-control" name="asset_host" rows="8" placeholder="Example:&#13;&#10;192.168.1.1&#13;&#10;192.168.1.0/24&#13;&#10;www.example.com"></textarea>
</div>
</div>
<div class="form-group row">
<label class="control-label col-md-3">Dept Name <span class="text-danger">*</span></label>
<div class="col-md-8">
<input class="form-control" name="dept_name" type="text" placeholder="Dept Name">
</div>
</div>
<div class="form-group row">
<label class="control-label col-md-3">Admin Name <span class="text-danger">*</span></label>
<div class="col-md-8">
<input class="form-control" name="admin_name" type="text" placeholder="Admin Name">
</div>
</div>
<div class="form-group row">
<label class="control-label col-md-3">Discover Option</label>
<div class="toggle lg col-md-8">
<label>
<input type="checkbox" checked><span class="button-indecator"></span>
</label>
</div>
</div>
</form>
<div class="tile-footer">
<button class="btn btn-primary " id="newAsset" type="button">Submit</button>
</div>
</div>
<div class="col-lg-2">
</div>
</div>
</div>
</div>
</div>
</main>
{% block js %}
<script src="static/js/plugins/sweetalert/sweetalert.min.js"></script>
<script src="static/js/plugins/select2.min.js"></script>
<script src="static/js/server/new-asset.js"></script>
{% endblock %}
{% endblock %}

View File

@ -0,0 +1,105 @@
{% extends "base.html" %}
{% block css %}
<link href="static/css/duallistbox/bootstrap-duallistbox.css" rel="stylesheet">
{% endblock %}
{% block content %}
<main class="app-content">
<div class="app-title">
<div>
<h1><i class="fa fa-edit"></i> Auth Tester</h1>
<p>Create a new week password scan task</p>
</div>
<ul class="app-breadcrumb breadcrumb">
<li class="breadcrumb-item"><i class="fa fa-home fa-lg"></i></li>
<li class="breadcrumb-item">Home</li>
<li class="breadcrumb-item"><a href="#">Auth Tester</a></li>
</ul>
</div>
<div class="row">
<div class="col-md-12">
<div class="tile">
<div class="row">
<div class="col-lg-2">
</div>
<div class="col-lg-8">
<form class="form-horizontal">
<div class="form-group row">
<label class="control-label col-md-3">Task Name <span class="text-danger">*</span></label>
<div class="col-md-9">
<input class="form-control" name="task_name" type="text" placeholder="Task Name">
</div>
</div>
<div class="form-group row">
<label class="control-label col-md-3">Recursion </label>
<div class="col-md-9">
<select class="form-control col-md-6" name="recursion" title="Recursion">
<option value="0">Once</option>
<option value="1">Every day</option>
<option value="7">Every week</option>
<option value="30">Every month</option>
</select>
</div>
</div>
<div class="form-group row">
<label class="control-label col-md-3">Args </label>
<div class="col-md-9">
<input class="form-control" name="args" title="Args" placeholder=""/>
</div>
</div>
<div class="form-group row">
<label class="control-label col-md-3">Protocols Select <span class="text-danger">*</span></label>
<div class="col-md-9">
<select multiple="multiple" size="7" name="service_list" title="Protocols">
{% for a in protocols %}
<option value="{{ a }}">{{ a | upper }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="form-group row">
<label class="control-label col-md-3">Target <span class="text-danger">*</span></label>
<div class="col-md-9">
<textarea class="form-control" name="target_list" rows="8" placeholder="Example:&#13;&#10;192.168.1.1&#13;&#10;192.168.1.0/24&#13;&#10;www.example.com"></textarea>
</div>
</div>
<div class="form-group row">
<label class="control-label col-md-3">User & Passwd <span class="text-danger">*</span></label>
<div class="col-md-9">
<div class="form-group row">
<div class="col-md-6">
<textarea class="form-control" placeholder="One username per line" rows="6" name="username_list">{{ username_list }}</textarea>
</div>
<div class="col-md-6">
<textarea class="form-control" placeholder="One password per line" rows="6" name="password_list">{{ password_list }}</textarea>
</div>
</div>
</div>
</div>
<button class="btn btn-primary" id="newAuth" type="button"><i class="fa fa-fw fa-lg fa-check-circle"></i>Submit</button>
</form>
</div>
<div class="col-md-2">
</div>
</div>
</div>
</div>
</div>
</main>
{% block js %}
<script src="static/js/jquery/jquery.bootstrap-duallistbox.js"></script>
<script src="static/js/plugins/sweetalert/sweetalert.min.js"></script>
<script src="static/js/server/new-auth-tester.js"></script>
{% endblock %}
{% endblock %}

View File

@ -0,0 +1,84 @@
{% extends "base.html" %}
{% block css %}
<link href="static/css/duallistbox/bootstrap-duallistbox.css" rel="stylesheet">
{% endblock %}
{% block content %}
<main class="app-content">
<div class="app-title">
<div>
<h1><i class="fa fa-edit"></i> New Scan</h1>
<p>Create a new scan task</p>
</div>
<ul class="app-breadcrumb breadcrumb">
<li class="breadcrumb-item"><i class="fa fa-home fa-lg"></i></li>
<li class="breadcrumb-item">Forms</li>
<li class="breadcrumb-item"><a href="#">New Scan</a></li>
</ul>
</div>
<div class="row">
<div class="col-md-12">
<div class="tile">
<div class="row">
<div class="col-lg-2">
</div>
<div class="col-lg-8">
<form class="form-horizontal">
<div class="form-group row">
<label class="control-label col-md-3">Task Name <span class="text-danger">*</span></label>
<div class="col-md-9">
<input class="form-control" name="taskname_val" type="text" placeholder="Task Name">
</div>
</div>
<div class="form-group row">
<label class="control-label col-md-3">Recursion </label>
<div class="col-md-9">
<select class="form-control col-md-6" name="recursion_val" title="Recursion">
<option value="0">Once</option>
<option value="1">Every day</option>
<option value="7">Every week</option>
<option value="30">Every month</option>
</select>
</div>
</div>
<div class="form-group row">
<label class="control-label col-md-3">Plugin Select <span class="text-danger">*</span></label>
<div class="col-md-9">
<select multiple="multiple" size="7" name="plugin_list">
{% for a in plugin_info %}
<option value="{{ a['_id'] }}">{{ a['plugin_name'] }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="form-group row">
<label class="control-label col-md-3">Target <span class="text-danger">*</span></label>
<div class="col-md-9">
<textarea class="form-control" name="target_val" rows="8" placeholder="Example:&#13;&#10;192.168.1.1&#13;&#10;192.168.1.0/24&#13;&#10;www.example.com"></textarea>
</div>
</div>
<button class="btn btn-primary" id="showConfig" type="button"><i class="fa fa-fw fa-lg fa-check-circle"></i>Submit</button>
</form>
</div>
<div class="col-md-2">
</div>
</div>
</div>
</div>
</div>
</main>
{% block js %}
<script src="static/js/jquery/jquery.bootstrap-duallistbox.js"></script>
<script src="static/js/plugins/sweetalert/sweetalert.min.js"></script>
<script src="static/js/server/new-scan.js"></script>
{% endblock %}
{% endblock %}

View File

@ -0,0 +1,132 @@
{% extends "base.html" %}
{% block css %}
<link href="static/css/dropzone.css" rel="stylesheet">
{% endblock %}
{% block content %}
<main class="app-content">
<div class="app-title">
<div>
<h1><i class="fa fa-th-list"></i>&nbsp;Plugin Management</h1>
<p></p>
</div>
<ul class="app-breadcrumb breadcrumb side">
<li class="breadcrumb-item"><i class="fa fa-home fa-lg"></i></li>
<li class="breadcrumb-item">Home</li>
<li class="breadcrumb-item active"><a href="#">Plugin List</a></li>
</ul>
</div>
<div class="row">
<div class="col-md-12">
<div class="tile">
<div class="tile-body">
<div id="sampleTable_wrapper" class="dataTables_wrapper container-fluid dt-bootstrap4 no-footer">
<div class="row"><div class="col-sm-12 col-md-6">
<div class="dataTables_length" id="sampleTable_length">
<a class="btn btn-primary" href="#" data-target="#newPlugin" data-toggle="modal" title="Add Plugins">
<i class="fa fa-gitlab fa-lg"></i> Add Plugins</a>
<br>
<br>
</div>
</div>
</div>
<table class="table table-hover table-bordered" id="sampleTable">
<thead>
<tr class="text-center">
<th>Name</th>
<th>App</th>
<th>Version</th>
<th>Type</th>
<th>Date</th>
<th>Manage</th>
</tr>
</thead>
<tbody>
{% for i in plugin_info %}
<tr class="center">
<td>
<a href="vulnerability?plugin={{ i['_id'] }}">{{ i['plugin_name'] }}</a>
</td>
<td>{{ i['plugin_app'] }}</td>
<td>{{ i['plugin_version'] }}</td>
<td>{{ i['plugin_type'] }}</td>
<td>{{ i['plugin_date'] }}</td>
<td class="text-center">
<div class="hidden-sm hidden-xs action-buttons">
<a onclick="plugin_info('{{ i['_id'] }}')" role="button" data-target="#pluginInfo" data-toggle="modal" href="#" title="Plugin Info" >
<i class="fa fa-search-plus"></i>
</a>
&nbsp;
&nbsp;
&nbsp;
<a id="test1" role="button" href="#" rel="{{ i['_id'] }}" onclick="delete_plugin('{{ i['_id'] }}')" title="delete">
<i class="fa fa-trash-o"></i>
</a>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="modal" id="pluginInfo" >
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Plugin Info</h5>
<button class="close" type="button" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
</div>
<div class="modal-body">
<pre id="plugin_info" title="Plugin Info">Loading...</pre>
</div>
<div class="modal-footer">
<button class="btn btn-primary" type="button" data-dismiss="modal">Close</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
<div class="modal" id="newPlugin" >
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Add Plugins</h5>
<button class="close" type="button" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
</div>
<div class="modal-body">
<form action="#" class="dropzone">
<div class="fallback">
<input name="file" type="file" multiple />
</div>
</form>
<br>
<p class="help-block">Plugin Developer Guide:
<a href="https://github.com/knownsec/Pocsuite/blob/master/docs/CODING.md" target="view_window">Pocsuite PoC </a>
</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal" aria-hidden="true">Cancel
</button>
{# <button class="btn btn-primary " id="upload-plugin" type="button">#}
{# <span>OK</span>#}
{# </button>#}
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
</div>
</div>
</div>
</div>
</div>
</main>
{% endblock %}
{% block js %}
<!-- Data table plugin-->
<script type="text/javascript" src="static/js/plugins/jquery.dataTables.min.js"></script>
<script type="text/javascript" src="static/js/plugins/dataTables.bootstrap.min.js"></script>
<script src="static/js/plugins/sweetalert/sweetalert.min.js"></script>
<script src="static/js/plugins/dropzone.js"></script>
<script src="static/js/server/plugin-management.js"></script>
{% endblock %}

View File

@ -0,0 +1,176 @@
{% extends "base.html" %}
{% block css %}
{% endblock %}
{% block content %}
<main class="app-content">
<div class="app-title">
<div>
<h1><i class="fa fa-th-list"></i>&nbsp;Port Scanner</h1>
<p></p>
</div>
<ul class="app-breadcrumb breadcrumb side">
<li class="breadcrumb-item"><i class="fa fa-home fa-lg"></i></li>
<li class="breadcrumb-item">Home</li>
<li class="breadcrumb-item active"><a href="#">Port Scanner</a></li>
</ul>
</div>
<div class="row">
<div class="col-md-12">
<div class="tile">
<div class="tile-body">
<div class="bs-component">
<ul class="nav nav-tabs">
<li class="nav-item"><a class="nav-link active" data-toggle="tab" href="#home">Add Scan</a></li>
{# <li class="nav-item"><a class="nav-link" data-toggle="tab" href="#profile">Result</a></li>#}
<li class="nav-item dropdown"><a class="nav-link dropdown-toggle" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false">Advanced</a>
<div class="dropdown-menu">
<a class="dropdown-item" role="button" data-toggle="modal" href="#" data-target="#editPort">Default Port</a>
<div class="dropdown-divider"></div><a class="dropdown-item" href="advanced-option">Thread Settings</a>
</div>
<div class="modal fade" id="editPort" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title" id="myModalLabel">
Default Port
</h4>
</div>
<div class="modal-body" >
<form class="form-horizontal" role="form">
<div class="form-group">
<label class="control-label no-padding-right">One port per line</label>
<div>
<textarea class="form-control" placeholder="One password per line" rows="8" name="edit_port_val">{{ port_list }}</textarea>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal" aria-hidden="true">Cancel
</button>
<button class="btn btn-primary port-update" type="button">
<span>Submit</span> <i class="fa fa-send m-l-10"></i>
</button>
</div>
</form>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div>
</li>
</ul>
<div class="tab-content" id="myTabContent">
<div class="tab-pane fade active show" id="home">
<div class="col-lg-8">
<br>
<form class="form-horizontal">
<div class="form-group row">
<label class="control-label col-md-2">Target <span class="text-danger">*</span></label>
<div class="col-md-6">
<input class="form-control" name="target_val" type="text" value="{{ host }}" placeholder="Example: 192.168.1.1 or 192.168.1.1/24">
</div>
<div class="col-md-1"></div>
<div class="col-md-3">
<button class="btn btn-primary btn-block new-scan" type="button">Submit&nbsp;&nbsp;<i class="fa fa-arrow-circle-right"></i></button>
</div>
</div>
<div class="form-group row">
<label class="control-label col-md-2">Arguments </label>
<div class="col-md-10">
<select class="form-control col-md-5" name="arguments_val" title="Recursion">
<option value="0">Default</option>
<option value="1">-sT -T4 --open -p</option>
<option value="2">-sS -T4 -Pn -p</option>
<option value="3">-sT -sV -O -A -p</option>
</select>
</div>
</div>
<div class="form-group row">
<label class="control-label col-md-2">Port</label>
<div class="col-md-10">
<textarea class="form-control" title="" rows="2" name="port_val" >{{ port }}</textarea>
</div>
</div>
<div class="form-group row">
<label class="control-label col-md-2">Result</label>
<div class="col-md-10" id="pre_result">
<pre class='form-control'>{{ result }}</pre>
</div>
</div>
</form>
</div>
</div>
{# <div class="tab-pane fade" id="profile">#}
{# <br>#}
{# <div class="col-md-12">#}
{# <div class="tile">#}
{# <div class="tile-body">#}
{# <table class="table table-hover table-bordered" id="sampleTable">#}
{# <thead>#}
{# <tr class="text-center">#}
{# <th>Host</th>#}
{# <th>status</th>#}
{# <th>Date</th>#}
{# <th>Manage</th>#}
{# </tr>#}
{# </thead>#}
{# <tbody>#}
{# {% for i in port_data %}#}
{# <tr>#}
{# <td>#}
{# <a href="">{{ i['host'] }}</a>#}
{# </td>#}
{# <td>{{ i['status'] }}</td>#}
{# <td>{{ i['date'] }}</td>#}
{# <td class="text-center">#}
{# <a role="button" href="#" onclick="port_result('{{ i['_id'] }}')" title="Result" data-toggle="modal" data-target="#portResult">#}
{# <i class="fa fa-file-archive-o"></i>#}
{# </a>#}
{# &nbsp;#}
{# <a onclick="result_delete('{{ i['_id'] }}')" role="button" href="#" title="Delete">#}
{# <i class="fa fa-trash-o"></i>#}
{# </a>#}
{# </td>#}
{# </tr>#}
{# {% endfor %}#}
{# </tbody>#}
{# </table>#}
{# <div class="modal fade" id="portResult" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">#}
{# <div class="modal-dialog">#}
{# <div class="modal-content">#}
{# <div class="modal-header">#}
{# <h4 class="modal-title" id="myModalLabel">#}
{# Result#}
{# </h4>#}
{# </div>#}
{# <div class="modal-body" >#}
{# <p id="port_result" title="Port Scan Result">Loading...</p>#}
{# </div>#}
{# </div><!-- /.modal-content -->#}
{# </div><!-- /.modal-dialog -->#}
{# </div><!-- /.modal-end -->#}
{# </div>#}
{# </div>#}
{# </div>#}
{# </div>#}
</div>
</div>
</div>
</div>
</div>
</div>
</main>
{% endblock %}
{% block js %}
<!-- Data table plugin-->
<script type="text/javascript" src="static/js/plugins/jquery.dataTables.min.js"></script>
<script type="text/javascript" src="static/js/plugins/dataTables.bootstrap.min.js"></script>
<script src="static/js/plugins/sweetalert/sweetalert.min.js"></script>
<script src="static/js/server/port-scanner.js"></script>
{% endblock %}

View File

@ -0,0 +1,207 @@
{% extends "base.html" %}
{% block css %}
<link href="static/css/duallistbox/bootstrap-duallistbox.css" rel="stylesheet">
{% endblock %}
{% block content %}
<main class="app-content">
<div class="app-title">
<div>
<h1><i class="fa fa-th-list"></i>&nbsp;Service Search</h1>
<p></p>
</div>
<ul class="app-breadcrumb breadcrumb side">
<li class="breadcrumb-item"><i class="fa fa-home fa-lg"></i></li>
<li class="breadcrumb-item">Home</li>
<li class="breadcrumb-item active"><a href="#">Search</a></li>
</ul>
</div>
<div class="row">
<div class="col-md-12">
<div class="tile">
<div>
<a class="btn btn-primary btn_select" href="#" id="btn_select" rel="select_all">Select All</a>&nbsp;&nbsp;
<a class="btn btn-primary" href="#" id="new_scan" role="button" onclick="newServiceScan()" title="New Scan" data-toggle="modal" data-target="#newScan"><i class="fa fa-gitlab fa-lg"></i>New Scan</a>
<a class="btn btn-primary" href="#" role="button" onclick="newAuthTester()" title="New Auth Tester" data-toggle="modal" data-target="#newAuthtest"><i class="fa fa-gitlab fa-lg"></i>New Auth Tester</a>
</div>
<div class="modal fade" id="newScan" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"><!-- /scan-modal -->
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title" id="myModalLabel">
New Scan
</h4>
</div>
<div class="modal-body" >
<form class="form-horizontal" role="form">
<div class="form-group">
<label class="control-label no-padding-right">Task Name <span class="text-danger">*</span></label>
<div>
<input type="text" class="form-control" id="task_name" name="taskname_val" placeholder="Task Name">
</div>
</div>
<div class="space-6"></div>
<div class="form-group">
<label class="control-label no-padding-right">Recursion</label>
<div>
<select class="form-control" id="form-field-plan" title="Recursion" name="recursion_val">
<option value="0">Once</option>
<option value="1">Every day</option>
<option value="7">Every week</option>
<option value="30">Every month</option>
</select>
</div>
</div>
<div class="form-group">
<label class="control-label no-padding-right">Plugin Select <span class="text-danger">*</span></label>
<div>
<select multiple="multiple" size="6" name="plugin_list" title="Plugin Select">
{% for a in plugin_info %}
<option value="{{ a['_id'] }}">{{ a['plugin_name'] }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="hr hr-16 hr-dotted"></div>
<div class="form-group">
<label class="control-label no-padding-right">Target <span class="text-danger">*</span></label>
<div>
<textarea class="form-control" rows="5" id="scan_target_list" title="Target" name="target_val" placeholder="Loading..."></textarea>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal" aria-hidden="true">Cancel</button>
<button class="btn btn-primary " id="server-scan" type="button">
<span>Submit</span> <i class="fa fa-send m-l-10"></i>
</button>
</div>
</form>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal-end -->
<div class="modal fade" id="newAuthtest" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"><!-- /scan-modal -->
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title" id="myModalLabel">
New Auth Tester
</h4>
</div>
<div class="modal-body" >
<form class="form-horizontal" role="form">
<div class="form-group">
<label class="control-label no-padding-right">Task Name <span class="text-danger">*</span></label>
<div>
<input type="text" class="form-control" name="auth_task_name" placeholder="Task Name">
</div>
</div>
<div class="form-group">
<label class="control-label no-padding-right">Recursion</label>
<div>
<select class="form-control" id="form-field-plan" title="Recursion" name="auth_recursion">
<option value="0">Once</option>
<option value="1">Every day</option>
<option value="7">Every week</option>
<option value="30">Every month</option>
</select>
</div>
</div>
<div class="form-group">
<label class="control-label no-padding-right">Args</label>
<div>
<input class="form-control" name="auth_args" title="Args" placeholder=""/>
</div>
</div>
<div class="space-6"></div>
<div class="form-group">
<label class="control-label no-padding-right">Protocols Select <span class="text-danger">*</span></label>
<div>
<select multiple="multiple" size="6" name="auth_service_list" title="Plugin Select">
{% for a in protocols %}
<option value="{{ a }}">{{ a | upper }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="hr hr-16 hr-dotted"></div>
<div class="form-group">
<label class="control-label no-padding-right">Target <span class="text-danger">*</span></label>
<div>
<textarea class="form-control" rows="5" id="auth_target_list" title="Target" name="auth_target_list" placeholder="Loading..."></textarea>
</div>
</div>
<div class="form-group row">
<div class="col-md-6">
<label class="control-label no-padding-right">Username<span class="text-danger">*</span></label>
<div>
<textarea class="form-control" placeholder="One username per line" rows="6" name="auth_username_list">{{ username_list }}</textarea>
</div>
</div>
<div class="col-md-6">
<label class="control-label no-padding-right">Password<span class="text-danger">*</span></label>
<div>
<textarea class="form-control" placeholder="One password per line" rows="6" name="auth_password_list">{{ password_list }}</textarea>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal" aria-hidden="true">Cancel</button>
<button class="btn btn-primary " id="asset-auth-tasks" type="button">
<span>Submit</span> <i class="fa fa-send m-l-10"></i>
</button>
</div>
</form>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal-end -->
</div>
<div class="row">
<div class="col-lg-12">
<div class="list-group">
<a class="list-group-item list-group-item-action">
<h4 class="list-group-item-heading">
{{ data }}
</h4>
</a>
</div>
{% for i in search_result %}
<div class="list-group">
<a class="list-group-item list-group-item-action">
<h4 class="list-group-item-heading">
<input title="checkbox" type="checkbox" name='select_id' value="{{ i['host'] }}:{{ i['port'] }}" />
&nbsp;&nbsp;&nbsp;&nbsp;Host:&nbsp;&nbsp;{{ i['host'] }}&nbsp;&nbsp;&nbsp;&nbsp;Port:&nbsp;&nbsp;{{ i['port'] }}&nbsp;&nbsp;&nbsp;&nbsp;Product:&nbsp;&nbsp;{{ i['product'] }}&nbsp;&nbsp;&nbsp;&nbsp;Version:&nbsp;&nbsp;{{ i['version'] }}
</h4>
<br>
<pre style="font-size:15px;white-space: pre-wrap;word-wrap: break-word;">{{ i['cpe'] }}&#13;&#10;{{ i['extrainfo'] }}&#13;&#10;{{ i['script'] }}&#13;&#10;{{ i['asset_name'] }}&#13;&#10;{{ i['date'] }}</pre>
</a>
</div>
<br>
{% endfor %}
</div>
</div>
</div>
</div>
</main>
{% endblock %}
{% block js %}
<!-- Data table plugin-->
<script src="static/js/plugins/sweetalert/sweetalert.min.js"></script>
<script src="static/js/jquery/jquery.bootstrap-duallistbox.js"></script>
<script src="static/js/server/search.js"></script>
{% endblock %}

View File

@ -0,0 +1,255 @@
{% extends "base.html" %}
{% block css %}
<link href="static/css/duallistbox/bootstrap-duallistbox.css" rel="stylesheet">
{% endblock %}
{% block content %}
<main class="app-content">
<div class="app-title">
<div>
<h1><i class="fa fa-th-list"></i>&nbsp;Subdomain Brute</h1>
<p></p>
</div>
<ul class="app-breadcrumb breadcrumb side">
<li class="breadcrumb-item"><i class="fa fa-home fa-lg"></i></li>
<li class="breadcrumb-item">Home</li>
<li class="breadcrumb-item active"><a href="#">New Brute</a></li>
</ul>
</div>
<div class="row">
<div class="col-md-12">
<div class="tile">
<div class="tile-body">
<div id="sampleTable_wrapper" class="dataTables_wrapper container-fluid dt-bootstrap4 no-footer">
<div class="row"><div class="col-sm-12 col-md-6">
<div class="dataTables_length" id="sampleTable_length">
<a class="btn btn-primary" href="#" data-target="#newDomain" data-toggle="modal" title="Add Plugins">
<i class="fa fa-plus-square fa-lg"></i> New Domain</a>
<br>
<br>
</div>
</div>
</div>
<table class="table table-hover table-bordered" id="sampleTable">
<thead>
<tr class="text-center">
<th>Name</th>
<th>Domain</th>
<th>Status</th>
<th>Date</th>
<th>Manage</th>
</tr>
</thead>
<tbody>
{% for i in domain_data %}
<tr class="center">
<td>
<a href="subdomain-list?domain={{ i['_id'] }}">{{ i['domain_name'] }}</a>
</td>
<td>{{ i['domain'] | join(',') | truncate(15 , True)}}</td>
<td>{{ i['status'] }}</td>
<td>{{ i['date'] }}</td>
<td class="text-center">
<div class="hidden-sm hidden-xs action-buttons">
<a onclick="get_domain_host('{{ i['_id'] }}')" role="button" href="#" title="New Vul Scan" data-toggle="modal" data-target="#newScan">
<i class="fa fa-bug"></i>
</a>
&nbsp;
&nbsp;
<a onclick="get_domain_awvs('{{ i['_id'] }}')" role="button" href="#" title="Acunetix Scanner" data-toggle="modal" data-target="#newAWVS">
<i class="fa fa-heartbeat"></i>
</a>
&nbsp;
&nbsp;
<a role="button" href="?download={{ i['_id'] }}" title="Download" >
<i class="fa fa-download"></i>
</a>
&nbsp;
&nbsp;
<a id="test1" role="button" href="#" onclick="delete_domain('{{ i['_id'] }}')" title="Delete">
<i class="fa fa-trash-o"></i>
</a>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="modal" id="newDomain" >
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Add Domain</h5>
<button class="close" type="button" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
</div>
<div class="modal-body">
<form action="#" class="dropzone">
<div class="form-group">
<label class="control-label no-padding-right">Domain Name<span class="text-danger">*</span></label>
<div>
<input type="text" class="form-control" id="domain_name" name="domain_name_val" placeholder="Task Name">
</div>
</div>
<div class="form-group">
<label class="control-label no-padding-right">Domain<span class="text-danger">*</span></label>
<div>
<textarea type="text" class="form-control" id="domain" name="domain_val" placeholder="Domain Name"></textarea>
</div>
</div>
<div class="toggle lg">
<label>Third-level Domain
<input type="checkbox" checked><span class="button-indecator"></span>
</label>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal" aria-hidden="true">Cancel</button>
<button class="btn btn-primary " id="new_domain" type="button">
<i class="fa fa-fw fa-lg fa-check-circle"></i>Submit
</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
</div>
<div class="modal" id="newAWVS" >
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Acunetix Scanner</h5>
<button class="close" type="button" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
</div>
<div class="modal-body">
<form class="form-horizontal" role="form">
<div class="form-group">
<label class="control-label no-padding-right">Task Name <span class="text-danger">*</span></label>
<div>
<input type="text" class="form-control" id="awvs_task_name" name="awvs_task_name" placeholder="">
</div>
</div>
<div class="form-group">
<label class="control-label no-padding-right">Target <span class="text-danger">*</span></label>
<div>
<textarea class="form-control" id="awvs_target" name="awvs_target" rows="4" placeholder="One url per line:&#13;&#10;http://example.com&#13;&#10;http://example.com"></textarea>
</div>
</div>
<div class="form-group">
<label class="control-label no-padding-right">Scan Type <span class="text-danger">*</span></label>
<div >
<select class="form-control col-md-7" id="awvs_scan_type" title="Scan Type" name="awvs_scan_type">
<option value="0">Full Scan</option>
<option value="1">High Risk Vulnerabilities</option>
<option value="2">Cross-site Scripting Vulnerabilities</option>
<option value="3">SQL Injection Vulnerabilities</option>
<option value="4">Weak Passwords</option>
<option value="5">Crawl Only</option>
</select>
</div>
</div>
<div class="hr hr-16 hr-dotted"></div>
<div class="form-group">
<label class="control-label no-padding-right">Description </label>
<div>
<input type="text" class="form-control" id="awvs_desc_val" name="awvs_desc_val" placeholder="">
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal" aria-hidden="true">Cancel
</button>
<button class="btn btn-primary" id="awvs-scan" type="button">
<span>OK</span>
</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
<div class="modal fade" id="newScan" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"><!-- /scan-modal -->
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title" id="myModalLabel">
New Scan
</h4>
</div>
<div class="modal-body" >
<form class="form-horizontal" role="form">
<div class="form-group">
<label class="control-label no-padding-right">Task Name <span class="text-danger">*</span></label>
<div>
<input type="text" class="form-control" id="task_name" name="taskname_val" placeholder="Task Name">
</div>
</div>
<div class="space-6"></div>
<div class="form-group">
<label class="control-label no-padding-right">Recursion</label>
<div>
<select class="form-control" id="form-field-plan" title="Recursion" name="recursion_val">
<option value="0">Once</option>
<option value="1">Every day</option>
<option value="7">Every week</option>
<option value="30">Every month</option>
</select>
</div>
</div>
<div class="form-group">
<label class="control-label no-padding-right">Plugin Select <span class="text-danger">*</span></label>
<div>
<select multiple="multiple" size="6" name="plugin_list" title="Plugin Select">
{% for a in plugin_data %}
<option value="{{ a['_id'] }}">{{ a['plugin_name'] }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="hr hr-16 hr-dotted"></div>
<div class="form-group">
<label class="control-label no-padding-right">Target <span class="text-danger">*</span></label>
<div>
<textarea class="form-control" rows="5" id="scan_target_list" title="Target" name="target_val" placeholder="Loading..."></textarea>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal" aria-hidden="true">Cancel
</button>
<button class="btn btn-primary " id="domain-scan" type="button">
<span>Submit</span> <i class="fa fa-send m-l-10"></i>
</button>
</div>
</form>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal-end -->
</div>
</div>
</div>
</div>
</main>
{% endblock %}
{% block js %}
<!-- Data table plugin-->
<script type="text/javascript" src="static/js/plugins/jquery.dataTables.min.js"></script>
<script type="text/javascript" src="static/js/plugins/dataTables.bootstrap.min.js"></script>
<script src="static/js/plugins/sweetalert/sweetalert.min.js"></script>
<script src="static/js/jquery/jquery.bootstrap-duallistbox.js"></script>
<script src="static/js/server/subdomain-brute.js"></script>
{% endblock %}

View File

@ -0,0 +1,67 @@
{% extends "base.html" %}
{% block css %}
{% endblock %}
{% block content %}
<main class="app-content">
<div class="app-title">
<div>
<h1><i class="fa fa-th-list"></i>&nbsp;Subdomain List</h1>
<p></p>
</div>
<ul class="app-breadcrumb breadcrumb side">
<li class="breadcrumb-item"><i class="fa fa-home fa-lg"></i></li>
<li class="breadcrumb-item">Home</li>
<li class="breadcrumb-item active"><a href="#">Subdomain List</a></li>
</ul>
</div>
<div class="row">
<div class="col-md-12">
<div class="tile">
<div class="tile-body">
<table class="table table-hover table-bordered" id="sampleTable">
<thead>
<tr class="text-center">
<th>Subdomain</th>
<th>Domain</th>
<th>Title</th>
<th>IP</th>
<th>Date</th>
<th>Manage</th>
</tr>
</thead>
<tbody>
{% for i in sub_result %}
<tr class="center">
<td>
<a role="button" href="http://{{ i['subdomain'] }}" target="view_window" title="Open">
{{ i['subdomain'] }}
</a>
</td>
<td>{{ i['domain'] }}</td>
<td>{{ i['title'] }}</td>
<td>{{ i['result'] | join(' | ') | truncate(25 , True) }}</td>
<td>{{ i['date'] }}</td>
<td class="text-center">
<a href="sudomain-list?delete={{ i['_id'] }}" title="delete" >
<i class="fa fa-trash-o"></i>
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</main>
{% endblock %}
{% block js %}
<!-- Data table plugin-->
<script type="text/javascript" src="static/js/plugins/jquery.dataTables.min.js"></script>
<script type="text/javascript" src="static/js/plugins/dataTables.bootstrap.min.js"></script>
<script src="static/js/plugins/sweetalert/sweetalert.min.js"></script>
<script src="static/js/server/subdomain-list.js"></script>
{% endblock %}

View File

@ -0,0 +1,139 @@
{% extends "base.html" %}
{% block css %}
{% endblock %}
{% block content %}
<main class="app-content">
<div class="app-title">
<div>
<h1><i class="fa fa-th-list"></i>&nbsp;Task Management</h1>
<p></p>
</div>
<ul class="app-breadcrumb breadcrumb side">
<li class="breadcrumb-item"><i class="fa fa-home fa-lg"></i></li>
<li class="breadcrumb-item">Home</li>
<li class="breadcrumb-item active"><a href="#">Task List</a></li>
</ul>
</div>
<div class="row">
<div class="col-md-12">
<div class="tile">
<div class="tile-body">
<table class="table table-hover table-bordered" id="sampleTable">
<thead>
<tr class="text-center">
<th>Name</th>
<th>Recursion</th>
<th>Status</th>
<th>Scan date</th>
<th>Last Modified</th>
<th>Manage</th>
</tr>
</thead>
<tbody>
{% for i in task_data %}
<tr>
<td>
<a href="vulnerability?task={{ i['_id'] }}">{{ i['task_name'] }}</a>
</td>
{% if i['task_recursion'] == '0' %}
<td>Once</td>
{% elif i['task_recursion'] == '1' %}
<td>Every day</td>
{% elif i['task_recursion'] == '7' %}
<td>Every week</td>
{% elif i['task_recursion'] == '30' %}
<td>Every month</td>
{% endif %}
<td>{{ i['task_status'] }}</td>
<td>{{ i['start_date'] }}</td>
<td>{{ i['end_date'] }}</td>
<td class="text-center">
<a onclick="rescan_task('{{ i['_id'] }}')" role="button" href="#" title="Rescan">
<i class="fa fa-refresh"></i>&nbsp;&nbsp;
</a>
&nbsp;
<a onclick="task_edit_id('{{ i['_id'] }}')" role="button" data-toggle="modal" href="#" title="Edit" data-target="#editTask">
<i class="fa fa-pencil"></i>
</a>
&nbsp;
<a onclick="task_delete('{{ i['_id'] }}')" role="button" href="#" title="Delete">
<i class="fa fa-trash-o"></i>
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="modal fade" id="editTask" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title" id="myModalLabel">
Edit Task
</h4>
</div>
<div class="modal-body" >
<form class="form-horizontal" role="form">
<div class="form-group">
<label class="control-label no-padding-right">Task Name</label>
<div>
<input type="text" class="form-control" id="task_name" name="taskname_val" placeholder="Task Name">
</div>
</div>
<div class="form-group">
<label class="control-label no-padding-right">Task ID</label>
<div>
<input type="text" class="form-control" id="task_id" name="task_id" disabled="disabled" title="Task ID">
</div>
</div>
<div class="space-6"></div>
<div class="form-group">
<label class="control-label no-padding-right">Recursion</label>
<div>
<select class="form-control" id="form-field-plan" title="Recursion" name="recursion_val">
<option value="0">Once</option>
<option value="1">Every day</option>
<option value="7">Every week</option>
<option value="30">Every month</option>
</select>
</div>
</div>
<div class="hr hr-16 hr-dotted"></div>
<div class="form-group">
<label class="control-label no-padding-right">Target</label>
<div>
<textarea class="form-control" rows="5" id="scan_target_list" title="Target" name="target_val"></textarea>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal" aria-hidden="true">Cancel
</button>
<button class="btn btn-primary task-update" type="button">
<span>Submit</span> <i class="fa fa-send m-l-10"></i>
</button>
</div>
</form>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div>
</div>
</div>
</div>
</div>
</main>
{% endblock %}
{% block js %}
<!-- Data table plugin-->
<script type="text/javascript" src="static/js/plugins/jquery.dataTables.min.js"></script>
<script type="text/javascript" src="static/js/plugins/dataTables.bootstrap.min.js"></script>
<script src="static/js/plugins/sweetalert/sweetalert.min.js"></script>
<script src="static/js/server/task-management.js"></script>
{% endblock %}

View File

@ -0,0 +1,90 @@
{% extends "base.html" %}
{% block css %}
{% endblock %}
{% block content %}
<main class="app-content">
<div class="app-title">
<div>
<h1><i class="fa fa-th-list"></i>&nbsp;Vulnerability Management</h1>
<p></p>
</div>
<ul class="app-breadcrumb breadcrumb side">
<li class="breadcrumb-item"><i class="fa fa-home fa-lg"></i></li>
<li class="breadcrumb-item">Home</li>
<li class="breadcrumb-item active"><a href="#">Vulnerability List</a></li>
</ul>
</div>
<div class="row">
<div class="col-md-12">
<div class="tile">
<div class="tile-body">
<table class="table table-hover table-bordered" id="sampleTable">
<thead>
<tr class="text-center">
<th>Host</th>
<th>Name</th>
<th>Type</th>
<th>Task</th>
<th>Date</th>
<th>Manage</th>
</tr>
</thead>
<tbody>
{% for i in vul_data %}
<tr class="text-center">
<td>
<a role="button" href="http://{{ i['target'] }}" target="_blank" title="Result">
{{ i['target'] }}
</a>
</td>
<td>{{ i['plugin_name'] }}</td>
<td>{{ i['plugin_type'] }}</td>
<td>{{ i['task_name'] }}</td>
<td>{{ i['date'] }}</td>
<td class="text-center">
<a onclick="vul_result('{{ i['_id'] }}')" role="button" data-target="#vulResult" data-toggle="modal" href="#" title="Result" >
<i class="ace-icon fa fa-file-archive-o bigger-130"></i>
</a>
&nbsp;
<a href="vulnerability?delete={{ i['_id'] }}" title="Delete" >
<i class="fa fa-trash-o"></i>
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="modal" id="vulResult" >
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Vulnerability Info</h5>
<button class="close" type="button" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
</div>
<div class="modal-body">
<div id='scan_target_list'>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-primary" type="button" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
{% endblock %}
{% block js %}
<!-- Data table plugin-->
<script type="text/javascript" src="static/js/plugins/jquery.dataTables.min.js"></script>
<script type="text/javascript" src="static/js/plugins/dataTables.bootstrap.min.js"></script>
<script src="static/js/plugins/sweetalert/sweetalert.min.js"></script>
<script src="static/js/server/vulnerability.js"></script>
{% endblock %}

View File

@ -0,0 +1,68 @@
{% extends "base.html" %}
{% block css %}
<link href="static/css/duallistbox/bootstrap-duallistbox.css" rel="stylesheet">
{% endblock %}
{% block content %}
<main class="app-content">
<div class="app-title">
<div>
<h1><i class="fa fa-th-list"></i>&nbsp;Week Passwd List</h1>
<p></p>
</div>
<ul class="app-breadcrumb breadcrumb side">
<li class="breadcrumb-item"><i class="fa fa-home fa-lg"></i></li>
<li class="breadcrumb-item">Home</li>
<li class="breadcrumb-item active"><a href="week-passwd-list">Week Passwd List</a></li>
</ul>
</div>
<div class="row">
<div class="col-md-12">
<div class="tile">
<div class="tile-body">
<table class="table table-hover table-bordered" id="sampleTable">
<thead>
<tr class="text-center">
<th>Task Name</th>
<th>Target</th>
<th>Service</th>
<th>Username</th>
<th>Password</th>
<th>Date</th>
<th>Manage</th>
</tr>
</thead>
<tbody>
{% for i in weekpasswd_data %}
<tr class="text-center">
<td>{{ i['task_name'] }}</td>
<td>{{ i['target'] }}</td>
<td>{{ i['service'] | upper}}</td>
<td>{{ i['username'] }}</td>
<td>{{ i['password'] }}</td>
<td>{{ i['date'] }}</td>
<td class="text-center">
<a onclick="delete_result('{{ i['_id'] }}')" role="button" href="#" title="Delete">
<i class="ace-icon fa fa-trash-o bigger-130"></i>
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</main>
{% endblock %}
{% block js %}
<!-- Data table plugin-->
<script type="text/javascript" src="static/js/plugins/jquery.dataTables.min.js"></script>
<script type="text/javascript" src="static/js/plugins/dataTables.bootstrap.min.js"></script>
<script src="static/js/plugins/sweetalert/sweetalert.min.js"></script>
<script src="static/js/jquery/jquery.bootstrap-duallistbox.js"></script>
<script src="static/js/server/week-passwd-list.js"></script>
{% endblock %}

View File

@ -0,0 +1,7 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author : jeffzhang
# @Time : 18-5-10
# @File : __init__.py.py
# @Desc : ""

View File

@ -0,0 +1,94 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author : jeffzhang
# @Time : 18-5-22
# @File : acunetix_scanner.py
# @Desc : ""
import time
from bson import ObjectId
from flask import Blueprint, render_template, request, jsonify
from fuxi.views.lib.parse_target import parse_target
from fuxi.views.lib.mongo_db import connectiondb, db_name_conf
from fuxi.views.authenticate import login_check
from fuxi.views.modules.acunetix_scanner.awvs_api import AcunetixScanner
acunetix_scanner = Blueprint('acunetix_scanner', __name__)
acunetix_db = db_name_conf()['acunetix_db']
@acunetix_scanner.route('/acunetix-scanner', methods=['GET', 'POST'])
@login_check
def acunetix_view():
# scanner view
if request.method == "GET":
acunetix_task = connectiondb(acunetix_db).find()
return render_template('acunetix-scanner.html', acunetix_task=acunetix_task)
else:
if request.form.get('source') == "new_scan":
target_id = []
task_name = request.form.get('task_name')
target_list = request.form.get('target_addr').split("\n")
scan_type = request.form.get('scan_type')
description_val = request.form.get('description_val')
for target in parse_target(target_list):
target_id.append(AcunetixScanner().start_task(target, description_val, scan_type)['target_id'])
task_data = {
"task_name": task_name,
"target_list": target_list,
"scan_type": scan_type,
"description": description_val,
"status": "",
"target_id": target_id,
"date": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),
}
connectiondb(acunetix_db).insert(task_data)
# print(new_scan)
return "success"
elif request.form.get('source') == "delete_task":
task_id = request.form.get('delete')
target_id = connectiondb(acunetix_db).find_one({"_id": ObjectId(task_id)})['target_id']
if connectiondb(acunetix_db).remove({"_id": ObjectId(task_id)}):
for t_id in target_id:
AcunetixScanner().delete_target(t_id)
return "success"
else:
return "warning"
elif request.form.get('source') == "download_report":
task_id = request.form.get('task_id')
target_id = connectiondb(acunetix_db).find_one({"_id": ObjectId(task_id)})['target_id']
task_name = connectiondb(acunetix_db).find_one({"_id": ObjectId(task_id)})['task_name']
report_url = AcunetixScanner().reports(target_id, 'targets', task_name)
if report_url:
return jsonify({"html_url": report_url[0], "pdf_url": report_url[1]})
else:
return "warning"
@acunetix_scanner.route('/acunetix-tasks', methods=['GET', 'POST'])
@login_check
def acunetix_tasks():
# scanner view
if request.method == "GET":
try:
tasks_info = AcunetixScanner().get_all()
except Exception as e:
print(e)
tasks_info = ''
return render_template('acunetix-tasks.html', tasks_info=tasks_info)
else:
if request.form.get('source') == "delete_scan":
scan_id = request.form.get('delete')
result = AcunetixScanner().delete_scan(scan_id)
if result:
return "success"
else:
return "warning"
elif request.form.get('source') == "report":
# scan_id type is list
scan_id = [request.form.get('scan_id')]
report_url = AcunetixScanner().reports(scan_id, 'scans', scan_id)
if report_url:
return jsonify({"html_url": report_url[0], "pdf_url": report_url[1]})
else:
return "warning"

View File

@ -0,0 +1,208 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author : jeffzhang
# @Time : 18-5-10
# @File : asset_management.py
# @Desc : ""
import time
import json
from threading import Thread
from flask import Blueprint, render_template, request, jsonify, redirect, url_for
from bson import ObjectId
from lib.mongo_db import connectiondb, db_name_conf
from fuxi.views.authenticate import login_check
from instance import config_name
from fuxi.views.modules.discovery.asset_discovery import AssetDiscovery
asset_management = Blueprint('asset_management', __name__)
tasks_db = db_name_conf()['tasks_db']
asset_db = db_name_conf()['asset_db']
server_db = db_name_conf()['server_db']
subdomain_db = db_name_conf()['subdomain_db']
vul_db = db_name_conf()['vul_db']
plugin_db = db_name_conf()['plugin_db']
config_db = db_name_conf()['config_db']
# new asset view
@asset_management.route('/new-asset', methods=['GET', 'POST'])
@login_check
def new_asset():
# default asset view
if request.method == "GET":
return render_template('new-asset.html')
else:
# create asset (post)
if request.form.get("source") == "new_asset":
asset_name = request.form.get('asset_name')
asset_host = request.form.get('asset_host').replace('\r', '').split('\n', -1),
dept_name = request.form.get('dept_name')
admin_name = request.form.get('admin_name')
discover_option = request.form.get('discover_option')
if discover_option == "true":
discover_option = 'Enable'
else:
discover_option = 'Disallow'
asset_data = {
'asset_name': asset_name,
'asset_host': asset_host[0],
'dept_name': dept_name,
'admin_name': admin_name,
"asset_date": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),
'discover_option': discover_option,
}
asset_id = connectiondb(asset_db).insert_one(asset_data).inserted_id
if discover_option == "Enable":
scanner = AssetDiscovery(asset_id)
t1 = Thread(target=scanner.set_discovery, args=())
t1.start()
return "success"
else:
return "success"
else:
return "Warning"
# asset view
@asset_management.route('/asset-management', methods=['GET', 'POST'])
@login_check
def asset_view():
if request.method == "GET":
# asset delete
if request.args.get("delete"):
asset_id = request.args.get("delete")
if connectiondb(asset_db).delete_one({'_id': ObjectId(asset_id)}):
return "success"
# get asset info
elif request.args.get("edit"):
asset_id = request.args.get("edit")
try:
asset_info = connectiondb(asset_db).find_one({'_id': ObjectId(asset_id)})
asset_info_json = {
'asset_name': asset_info['asset_name'],
'admin_name': asset_info['admin_name'],
'dept_name': asset_info['dept_name'],
'asset_id': asset_id,
'asset_host': '\n'.join(asset_info['asset_host']),
}
return jsonify(asset_info_json)
except Exception as e:
print(e)
# get asset host info for new scan
elif request.args.get("scan"):
asset_id = request.args.get("scan")
try:
asset_host = connectiondb(asset_db).find_one({'_id': ObjectId(asset_id)})['asset_host']
asset_host_json = {
'asset_host': '\n'.join(asset_host),
}
return jsonify(asset_host_json)
except Exception as e:
print(e)
else:
# asset list(view)
config_info = connectiondb(config_db).find_one({"config_name": config_name})
asset_info = connectiondb(asset_db).find()
plugin_info = connectiondb(plugin_db).find()
username_list = '\n'.join(config_info['username_dict'])
password_list = '\n'.join(config_info['password_dict'])
protocols = config_info['auth_service']
return render_template("asset-management.html", asset_info=asset_info, plugin_info=plugin_info,
protocols=protocols, username_list=username_list, password_list=password_list)
else:
# asset db update
if request.form.get("source") == "asset_update":
asset_id = request.form.get('asset_id')
asset_name = request.form.get('asset_name')
asset_host = request.form.get('host_val').replace('\r', '').split('\n', -1),
dept_name = request.form.get('dept_name')
admin_name = request.form.get('admin_name')
discover_option = request.form.get('discover_option')
if discover_option == "true":
discover_option = 'Enable'
else:
discover_option = 'Disallow'
update_asset = connectiondb(asset_db).update_one(
{'_id': ObjectId(asset_id)},
{'$set': {
'asset_name': asset_name,
'dept_name': dept_name,
'asset_host': asset_host[0],
'admin_name': admin_name,
"asset_date": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),
'discover_option': discover_option,
}
}
)
if update_asset:
if discover_option == "Enable":
scanner = AssetDiscovery(ObjectId(asset_id))
t1 = Thread(target=scanner.set_discovery, args=())
t1.start()
return "success"
else:
return "Warning"
# asset server view
@asset_management.route('/asset-services', methods=['GET', 'POST'])
@login_check
def asset_server():
if request.method == "GET":
plugin_info = connectiondb(plugin_db).find()
if request.args.get('asset'):
asset_id = request.args.get('asset')
server_data = connectiondb(server_db).find({"tag": {"$ne": "delete"}, 'asset_id': ObjectId(asset_id)})
return render_template("asset-services.html", server_data=server_data, plugin_info=plugin_info)
elif request.args.get('delete'):
server_id = request.args.get('delete')
if connectiondb(server_db).update_one({'_id': ObjectId(server_id)}, {"$set": {"tag": "delete"}}):
return redirect(url_for('asset_management.asset_server'))
elif request.args.get('info'):
server_id = request.args.get('info')
server_info = connectiondb(server_db).find_one({"tag": {"$ne": "delete"}, '_id': ObjectId(server_id)})
if server_info:
del server_info['_id']
del server_info['asset_id']
return jsonify(server_info)
else:
return jsonify({"result": "Warning"})
server_data = connectiondb(server_db).find({"tag": {"$ne": "delete"}})
return render_template("asset-services.html", server_data=server_data, plugin_info=plugin_info)
else:
if request.form.get('source') == 'server_scan':
server_host = []
server_list = request.form.get('server_list').split(",")
for server_id in server_list:
server_info = connectiondb(server_db).find_one({"_id": ObjectId(server_id)})
server_host.append(server_info['host'] + ":" + str(server_info['port']))
return "\n".join(server_host)
@asset_management.route('/search', methods=['GET', 'POST'])
@login_check
def search_view():
config_info = connectiondb(config_db).find_one({"config_name": config_name})
username_list = '\n'.join(config_info['username_dict'])
password_list = '\n'.join(config_info['password_dict'])
plugin_info = connectiondb(plugin_db).find()
protocols = config_info['auth_service']
if request.method == "GET":
data = "Your search - \"\" - did not match any documents."
return render_template('search.html', data=data, plugin_info=plugin_info, protocols=protocols)
else:
search_result = []
key = request.form.get('search').strip()
for i in connectiondb(server_db).find({"tag": {"$ne": "delete"}}, {'_id': 0, 'asset_id': 0}):
if key in str(i):
search_result.append(i)
if len(search_result) == 0:
data = "Your search - " + key + " - did not match any documents."
return render_template('search.html', data=data)
else:
return render_template('search.html', search_result=search_result, plugin_info=plugin_info,
username_list=username_list, password_list=password_list, protocols=protocols)

View File

@ -0,0 +1,124 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author : jeffzhang
# @Time : 18-5-23
# @File : auth_tester.py
# @Desc : ""
import time
from threading import Thread
from flask import Blueprint, render_template, request
from bson import ObjectId
from lib.mongo_db import connectiondb, db_name_conf
from fuxi.views.authenticate import login_check
from instance import config_name
from fuxi.views.modules.auth_tester.auth_scanner import AuthCrack
auth_tester = Blueprint('auth_tester', __name__)
auth_db = db_name_conf()['auth_db']
weekpasswd_db = db_name_conf()['weekpasswd_db']
config_db = db_name_conf()['config_db']
@auth_tester.route('/new-auth-tester')
@login_check
def view_new_auth_tester():
# default view
config_info = connectiondb(config_db).find_one({"config_name": config_name})
username_list = "\n".join(config_info['username_dict'])
password_list = "\n".join(config_info['password_dict'])
protocols = config_info['auth_service']
return render_template('new-auth-tester.html', username_list=username_list, password_list=password_list,
protocols=protocols)
@auth_tester.route('/auth-tester', methods=['POST'])
@login_check
def new_auth_tester():
# create new task
username_list = request.form.get('username_list').split('\n')
password_list = request.form.get('password_list').split('\n')
task_name = time.strftime("%y%m%d", time.localtime()) + "_" + request.form.get('task_name')
target_list = request.form.get('target_list').split('\n')
recursion = int(request.form.get('recursion'))
service = request.form.get('service_list').split(',')
args = request.form.get('args')
data = {
"task_name": task_name,
"target": target_list,
"username": username_list,
"password": password_list,
"service": service,
"recursion": recursion,
"status": "Queued",
"args": args,
"date": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),
"week_count": 0,
}
task_id = connectiondb(auth_db).insert_one(data).inserted_id
if task_id:
scanner = AuthCrack(task_id)
t1 = Thread(target=scanner.start_scan, args=())
t1.start()
return 'success'
else:
return False
@auth_tester.route('/auth-tester-tasks', methods=['GET', 'POST'])
@login_check
def task_management():
if request.method == "GET":
# delete task
if request.args.get('delete'):
task_id = request.args.get('delete')
connectiondb(weekpasswd_db).update({"task_id": ObjectId(task_id)}, {"$set": {"tag": "delete"}}, multi=True)
if connectiondb(auth_db).remove({"_id": ObjectId(task_id)}):
return "success"
# rescan task
elif request.args.get('rescan'):
task_id = request.args.get('rescan')
# connectiondb(weekpasswd_db).remove({"task_id": ObjectId(task_id)})
connectiondb(weekpasswd_db).update({"task_id": ObjectId(task_id)}, {"$set": {"tag": "delete"}}, multi=True)
connectiondb(auth_db).update_one({"_id": ObjectId(task_id)}, {"$set": {
"status": "Queued",
"date": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),
"week_count": 0,
}})
scanner = AuthCrack(ObjectId(task_id))
if scanner:
t1 = Thread(target=scanner.start_scan, args=())
t1.start()
return "success"
# default view
else:
auth_tasks = connectiondb(auth_db).find()
return render_template('auth-tester-tasks.html', auth_tasks=auth_tasks)
# return target info
elif request.form.get('source') == "target_info":
task_id = request.form.get('task_id')
# list to string
target_info = '\n'.join(connectiondb(auth_db).find_one({"_id": ObjectId(task_id)})['target']),
return target_info
@auth_tester.route('/week-passwd-list', methods=['GET', 'POST'])
@login_check
def week_passwd_list():
if request.method == "GET":
if request.args.get('delete'):
_id = request.args.get('delete')
# delete week password
# if connectiondb(weekpasswd_db).remove({"_id": ObjectId(_id)}):
if connectiondb(weekpasswd_db).update_one({"_id": ObjectId(_id)}, {"$set": {"tag": "delete"}}):
return "success"
# screening result by task_id
elif request.args.get('task'):
_id = request.args.get('task')
weekpasswd_data = connectiondb(weekpasswd_db).find({"task_id": ObjectId(_id), "tag": {"$ne": "delete"}})
return render_template('week-passwd-list.html', weekpasswd_data=weekpasswd_data)
# default view
else:
weekpasswd_data = connectiondb(weekpasswd_db).find({"tag": {"$ne": "delete"}})
return render_template('week-passwd-list.html', weekpasswd_data=weekpasswd_data)

View File

@ -0,0 +1,58 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author : jeffzhang
# @Time : 18-5-10
# @File : authenticate.py
# @Desc : ""
from flask import Blueprint, render_template, request, redirect, url_for, Flask, session
from instance import config
from functools import wraps
authenticate = Blueprint('authenticate', __name__)
ProductionConfig = config.ProductionConfig
app = Flask(__name__)
app.config.from_object(ProductionConfig)
@authenticate.route('/login', methods=['GET', 'POST'])
def login_view():
# login view
if request.method == 'POST':
# username = request.form.get('username')
password = request.form.get('password')
if password == app.config.get('WEB_PASSWORD'):
try:
session['login'] = 'A1akPTQJiz9wi9yo4rDz8ubM1b1'
return redirect(url_for('index.view_base'))
except Exception as e:
print(e)
return render_template('login.html', msg="Internal Server Error")
else:
return render_template('login.html', msg="Invalid Password")
return render_template('login.html')
# login-out
@authenticate.route('/login-out')
def login_out():
session['login'] = ''
return redirect(url_for('authenticate.login_view'))
# login-check
def login_check(f):
@wraps(f)
def wrapper(*args, **kwargs):
try:
if "login" in session:
if session['login'] == 'A1akPTQJiz9wi9yo4rDz8ubM1b1':
return f(*args, **kwargs)
else:
return redirect(url_for('authenticate.login_view'))
else:
return redirect(url_for('authenticate.login_view'))
except Exception, e:
print e
return redirect(url_for('authenticate.login_view'))
return wrapper

Some files were not shown because too many files have changed in this diff Show More