├── static ├── images │ ├── favicon.ico │ ├── flags32.png │ ├── sort_asc.png │ ├── sort_both.png │ ├── sort_desc.png │ ├── Sorting icons.psd │ ├── back_disabled.png │ ├── back_enabled.png │ ├── forward_disabled.png │ ├── forward_enabled.png │ ├── back_enabled_hover.png │ ├── sort_asc_disabled.png │ ├── sort_desc_disabled.png │ └── forward_enabled_hover.png ├── admin │ ├── img │ │ ├── icon-no.gif │ │ ├── icon-yes.gif │ │ ├── nav-bg.gif │ │ ├── default-bg.gif │ │ ├── icon_alert.gif │ │ ├── icon_clock.gif │ │ ├── icon_error.gif │ │ ├── changelist-bg.gif │ │ ├── icon-unknown.gif │ │ ├── icon_addlink.gif │ │ ├── icon_calendar.gif │ │ ├── icon_success.gif │ │ ├── inline-delete.png │ │ ├── sorting-icons.gif │ │ ├── tooltag-add.png │ │ ├── deleted-overlay.gif │ │ ├── icon_changelink.gif │ │ ├── icon_deletelink.gif │ │ ├── icon_searchbox.png │ │ ├── inline-restore.png │ │ ├── nav-bg-grabber.gif │ │ ├── nav-bg-reverse.gif │ │ ├── nav-bg-selected.gif │ │ ├── selector-icons.gif │ │ ├── selector-search.gif │ │ ├── changelist-bg_rtl.gif │ │ ├── default-bg-reverse.gif │ │ ├── gis │ │ │ ├── move_vertex_on.png │ │ │ └── move_vertex_off.png │ │ ├── inline-delete-8bit.png │ │ ├── inline-splitter-bg.gif │ │ ├── tooltag-arrowright.png │ │ └── inline-restore-8bit.png │ ├── js │ │ ├── jquery.init.js │ │ ├── prepopulate.min.js │ │ ├── collapse.min.js │ │ ├── related-widget-wrapper.js │ │ ├── collapse.js │ │ ├── LICENSE-JQUERY.txt │ │ ├── prepopulate.js │ │ ├── timeparse.js │ │ ├── actions.min.js │ │ ├── inlines.min.js │ │ ├── SelectBox.js │ │ ├── admin │ │ │ └── RelatedObjectLookups.js │ │ ├── actions.js │ │ ├── urlify.js │ │ ├── calendar.js │ │ ├── core.js │ │ └── SelectFilter2.js │ └── css │ │ ├── dashboard.css │ │ ├── login.css │ │ ├── ie.css │ │ ├── rtl.css │ │ ├── changelists.css │ │ └── forms.css ├── glyphicons-halflings.png ├── glyphicons-halflings-white.png ├── fonts │ ├── glyphicons-halflings-regular.eot │ ├── glyphicons-halflings-regular.ttf │ └── glyphicons-halflings-regular.woff ├── js │ ├── npm.js │ ├── bootstrap-number-input.min.js │ ├── dataTables.bootstrap.min.js │ ├── sorttable.min.js │ └── bootstrap-select.min.js └── css │ ├── bootstrap-datetimepicker.min.css │ ├── bootstrap-datepicker.min.css │ ├── dataTables.tableTools.min.css │ └── dataTables.bootstrap.min.css ├── requirements.txt ├── .gitignore ├── templates ├── navbar.html ├── main │ ├── new_task.html │ ├── task.html │ └── tasks.html ├── registration │ └── login.html └── base.html ├── main ├── __init__.py ├── management │ ├── __init__.py │ └── commands │ │ └── __init__.py ├── migrations │ ├── __init__.py │ ├── 0002_auto_20150818_1536.py │ └── 0001_initial.py ├── templatetags │ ├── __init__.py │ └── certego_tags.py ├── tests.py ├── urls.py ├── forms.py ├── admin.py ├── views.py ├── models.py └── api.py ├── pcapoptikon ├── __init__.py ├── wsgi.py ├── urls.py ├── authorization.py ├── fields.py └── settings.py ├── manage.py ├── reload.sh ├── Dockerfile ├── nagios └── check_queue.py ├── start.sh └── README.md /static/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/images/favicon.ico -------------------------------------------------------------------------------- /static/images/flags32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/images/flags32.png -------------------------------------------------------------------------------- /static/images/sort_asc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/images/sort_asc.png -------------------------------------------------------------------------------- /static/admin/img/icon-no.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/admin/img/icon-no.gif -------------------------------------------------------------------------------- /static/admin/img/icon-yes.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/admin/img/icon-yes.gif -------------------------------------------------------------------------------- /static/admin/img/nav-bg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/admin/img/nav-bg.gif -------------------------------------------------------------------------------- /static/images/sort_both.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/images/sort_both.png -------------------------------------------------------------------------------- /static/images/sort_desc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/images/sort_desc.png -------------------------------------------------------------------------------- /static/admin/img/default-bg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/admin/img/default-bg.gif -------------------------------------------------------------------------------- /static/admin/img/icon_alert.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/admin/img/icon_alert.gif -------------------------------------------------------------------------------- /static/admin/img/icon_clock.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/admin/img/icon_clock.gif -------------------------------------------------------------------------------- /static/admin/img/icon_error.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/admin/img/icon_error.gif -------------------------------------------------------------------------------- /static/glyphicons-halflings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/glyphicons-halflings.png -------------------------------------------------------------------------------- /static/images/Sorting icons.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/images/Sorting icons.psd -------------------------------------------------------------------------------- /static/images/back_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/images/back_disabled.png -------------------------------------------------------------------------------- /static/images/back_enabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/images/back_enabled.png -------------------------------------------------------------------------------- /static/admin/img/changelist-bg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/admin/img/changelist-bg.gif -------------------------------------------------------------------------------- /static/admin/img/icon-unknown.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/admin/img/icon-unknown.gif -------------------------------------------------------------------------------- /static/admin/img/icon_addlink.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/admin/img/icon_addlink.gif -------------------------------------------------------------------------------- /static/admin/img/icon_calendar.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/admin/img/icon_calendar.gif -------------------------------------------------------------------------------- /static/admin/img/icon_success.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/admin/img/icon_success.gif -------------------------------------------------------------------------------- /static/admin/img/inline-delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/admin/img/inline-delete.png -------------------------------------------------------------------------------- /static/admin/img/sorting-icons.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/admin/img/sorting-icons.gif -------------------------------------------------------------------------------- /static/admin/img/tooltag-add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/admin/img/tooltag-add.png -------------------------------------------------------------------------------- /static/images/forward_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/images/forward_disabled.png -------------------------------------------------------------------------------- /static/images/forward_enabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/images/forward_enabled.png -------------------------------------------------------------------------------- /static/admin/img/deleted-overlay.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/admin/img/deleted-overlay.gif -------------------------------------------------------------------------------- /static/admin/img/icon_changelink.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/admin/img/icon_changelink.gif -------------------------------------------------------------------------------- /static/admin/img/icon_deletelink.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/admin/img/icon_deletelink.gif -------------------------------------------------------------------------------- /static/admin/img/icon_searchbox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/admin/img/icon_searchbox.png -------------------------------------------------------------------------------- /static/admin/img/inline-restore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/admin/img/inline-restore.png -------------------------------------------------------------------------------- /static/admin/img/nav-bg-grabber.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/admin/img/nav-bg-grabber.gif -------------------------------------------------------------------------------- /static/admin/img/nav-bg-reverse.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/admin/img/nav-bg-reverse.gif -------------------------------------------------------------------------------- /static/admin/img/nav-bg-selected.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/admin/img/nav-bg-selected.gif -------------------------------------------------------------------------------- /static/admin/img/selector-icons.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/admin/img/selector-icons.gif -------------------------------------------------------------------------------- /static/admin/img/selector-search.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/admin/img/selector-search.gif -------------------------------------------------------------------------------- /static/images/back_enabled_hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/images/back_enabled_hover.png -------------------------------------------------------------------------------- /static/images/sort_asc_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/images/sort_asc_disabled.png -------------------------------------------------------------------------------- /static/images/sort_desc_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/images/sort_desc_disabled.png -------------------------------------------------------------------------------- /static/admin/img/changelist-bg_rtl.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/admin/img/changelist-bg_rtl.gif -------------------------------------------------------------------------------- /static/admin/img/default-bg-reverse.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/admin/img/default-bg-reverse.gif -------------------------------------------------------------------------------- /static/admin/img/gis/move_vertex_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/admin/img/gis/move_vertex_on.png -------------------------------------------------------------------------------- /static/admin/img/inline-delete-8bit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/admin/img/inline-delete-8bit.png -------------------------------------------------------------------------------- /static/admin/img/inline-splitter-bg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/admin/img/inline-splitter-bg.gif -------------------------------------------------------------------------------- /static/admin/img/tooltag-arrowright.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/admin/img/tooltag-arrowright.png -------------------------------------------------------------------------------- /static/glyphicons-halflings-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/glyphicons-halflings-white.png -------------------------------------------------------------------------------- /static/images/forward_enabled_hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/images/forward_enabled_hover.png -------------------------------------------------------------------------------- /static/admin/img/gis/move_vertex_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/admin/img/gis/move_vertex_off.png -------------------------------------------------------------------------------- /static/admin/img/inline-restore-8bit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/admin/img/inline-restore-8bit.png -------------------------------------------------------------------------------- /static/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /static/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /static/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certego/pcapoptikon/HEAD/static/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | Django==1.11.29 2 | django-tastypie==0.14.2 3 | django-widget-tweaks==1.4.1 4 | hexdump==3.2 5 | idstools==0.5.0 6 | ipython==3.2.1 7 | jsonfield==1.0.3 8 | MySQL-python==1.2.5 9 | python-dateutil==2.4.2 10 | python-mimeparse==0.1.4 11 | pytz==2015.4 12 | simplejson==3.8.0 13 | six==1.9.0 14 | wheel==0.24.0 15 | -------------------------------------------------------------------------------- /static/admin/js/jquery.init.js: -------------------------------------------------------------------------------- 1 | /* Puts the included jQuery into our own namespace using noConflict and passing 2 | * it 'true'. This ensures that the included jQuery doesn't pollute the global 3 | * namespace (i.e. this preserves pre-existing values for both window.$ and 4 | * window.jQuery). 5 | */ 6 | var django = django || {}; 7 | django.jQuery = jQuery.noConflict(true); 8 | -------------------------------------------------------------------------------- /static/admin/js/prepopulate.min.js: -------------------------------------------------------------------------------- 1 | (function(b){b.fn.prepopulate=function(e,g){return this.each(function(){var a=b(this),d=function(){if(!a.data("_changed")){var f=[];b.each(e,function(h,c){c=b(c);c.val().length>0&&f.push(c.val())});a.val(URLify(f.join(" "),g))}};a.data("_changed",false);a.change(function(){a.data("_changed",true)});a.val()||b(e.join(",")).keyup(d).change(d).focus(d)})}})(django.jQuery); 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore Python byte code 2 | *.pyc 3 | 4 | # Ignore certificates 5 | *.pem 6 | *.cert 7 | 8 | # Ignore OS generated files 9 | .DS_Store* 10 | .AppleDouble 11 | ehthumbs.db 12 | Icon? 13 | Thumbs.db 14 | .directory 15 | 16 | # Ignore development files 17 | docs/book/src/_build/ 18 | .idea/ 19 | 20 | # Ignore Django secret_key 21 | pcapoptikon/secret_key.py 22 | 23 | # Ignore others files 24 | .settings/ 25 | .project 26 | .pydevproject 27 | *.gz 28 | *.swp 29 | .ropeproject/ 30 | -------------------------------------------------------------------------------- /static/js/npm.js: -------------------------------------------------------------------------------- 1 | // This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment. 2 | require('../../js/transition.js') 3 | require('../../js/alert.js') 4 | require('../../js/button.js') 5 | require('../../js/carousel.js') 6 | require('../../js/collapse.js') 7 | require('../../js/dropdown.js') 8 | require('../../js/modal.js') 9 | require('../../js/tooltip.js') 10 | require('../../js/popover.js') 11 | require('../../js/scrollspy.js') 12 | require('../../js/tab.js') 13 | require('../../js/affix.js') -------------------------------------------------------------------------------- /static/admin/css/dashboard.css: -------------------------------------------------------------------------------- 1 | /* DASHBOARD */ 2 | 3 | .dashboard .module table th { 4 | width: 100%; 5 | } 6 | 7 | .dashboard .module table td { 8 | white-space: nowrap; 9 | } 10 | 11 | .dashboard .module table td a { 12 | display: block; 13 | padding-right: .6em; 14 | } 15 | 16 | /* RECENT ACTIONS MODULE */ 17 | 18 | .module ul.actionlist { 19 | margin-left: 0; 20 | } 21 | 22 | ul.actionlist li { 23 | list-style-type: none; 24 | } 25 | 26 | ul.actionlist li { 27 | overflow: hidden; 28 | text-overflow: ellipsis; 29 | -o-text-overflow: ellipsis; 30 | } 31 | -------------------------------------------------------------------------------- /static/admin/js/collapse.min.js: -------------------------------------------------------------------------------- 1 | (function(a){a(document).ready(function(){a("fieldset.collapse").each(function(c,b){a(b).find("div.errors").length==0&&a(b).addClass("collapsed").find("h2").first().append(' ('+gettext("Show")+")")});a("fieldset.collapse a.collapse-toggle").click(function(){a(this).closest("fieldset").hasClass("collapsed")?a(this).text(gettext("Hide")).closest("fieldset").removeClass("collapsed").trigger("show.fieldset",[a(this).attr("id")]):a(this).text(gettext("Show")).closest("fieldset").addClass("collapsed").trigger("hide.fieldset", 2 | [a(this).attr("id")]);return false})})})(django.jQuery); 3 | -------------------------------------------------------------------------------- /templates/navbar.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /main/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # __init__.py 4 | # 5 | # This program is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License version 2 as 7 | # published by the Free Software Foundation. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program; if not, write to the Free Software 16 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, 17 | # MA 02111-1307 USA 18 | # 19 | # Author: Pietro Delsante53 | {% block breadcrumb %}{% endblock %} 54 | {% block content %}{% endblock %} 55 | 56 | 61 |
| Protocol: | 31 |{{event.protocol}} | 32 |
| Source: | 35 |{{event.source_ip}}:{{event.sport_itype}} | 36 |
| Destination: | 39 |{{event.destination_ip}}:{{event.dport_icode}} | 40 |
| Packet #{{forloop.counter}} | 44 |{{packet.data|b64decode_hexdump}} |
45 |
No signatures
53 | {% endif %} 54 | 55 | {% endblock %} 56 | {% block bottomscripts %} 57 | {% endblock %} 58 | {% block customcss %} 59 | {% endblock %} -------------------------------------------------------------------------------- /main/models.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # models.py 4 | # 5 | # This program is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License version 2 as 7 | # published by the Free Software Foundation. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program; if not, write to the Free Software 16 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, 17 | # MA 02111-1307 USA 18 | # 19 | # Author: Pietro Delsante| ID | 9 |File | 10 |Submitted on | 11 |Owner | 12 |Status | 13 |Hits | 14 |
/suricata/etpro.rules.tar.gz
56 | if [ $(echo $1 | egrep '^[0-9]{16}$' | wc -l) -eq 1 ]; then
57 | log "Using supplied OinkCode to set up ETPro ruleset in oinkmaster"
58 | sed -ir "s|^url = http://rules.emergingthreats.net/open/suricata/emerging.rules.tar.gz|url = https://rules.emergingthreats.net/$1/suricata/etpro.rules.tar.gz|" /etc/oinkmaster.conf
59 | sed -i 's/emerging-\(.*\)\.rules/\1.rules/g' /etc/suricata/suricata.yaml # ETPro rule files have a different name
60 | else
61 | log "Using default ET Open ruleset (to change this, please pass your ETPro oinkcode as the first param to $0"
62 | fi
63 |
64 | # Update suricata rules
65 | log "Running OinkMaster to update signatures..."
66 | oinkmaster -C /etc/oinkmaster.conf -o /etc/suricata/rules
67 |
68 | # Update sid-msg.map
69 | log "Updating sid-msg.map"
70 | /usr/share/oinkmaster/create-sidmap.pl /etc/suricata/rules > /etc/suricata/rules/sid-msg.map
71 |
72 | # Start Suricata
73 | log "Starting Suricata..."
74 | rm -f /var/run/suricata.pid
75 | /usr/bin/suricata -c /etc/suricata/suricata.yaml --unix-socket --pidfile /var/run/suricata.pid >/var/log/suricata/suricata.log 2>&1 &
76 |
77 | # Start the pcapoptikon HTTP server
78 | log "Starting the PCAPOptikon HTTP Server..."
79 | /usr/bin/python /opt/pcapoptikon/manage.py runserver 0.0.0.0:8000 >/var/log/pcapoptikon_web.log 2>&1 &
80 | log $! > /var/run/pcapoptikon-http.pid
81 |
82 | # Start the pcapoptikon daemon
83 | log "Starting the PCAPOptikon worker daemon..."
84 | /usr/bin/python /opt/pcapoptikon/manage.py run_daemon >/var/log/pcapoptikon_daemon.log 2>&1 &
85 | log $! > /var/run/pcapoptikon-daemon.pid
86 |
87 | # Give a hint about how to use
88 | log "Running on: http://"$(hostname -i)":8000/"
89 | log "Username: admin"
90 | log "Api-Key: "$(mysql -e 'SELECT `key` FROM tastypie_apikey WHERE user_id = (SELECT id FROM auth_user WHERE username = '"'"'admin'"'"');' pcapoptikon)
91 |
92 | # Run oinkmaster every 24 hours and restart suricata and pcapoptikon daemon to reload the rules
93 | while true; do
94 | sleep $(expr 60 \* 60 \* 24)
95 |
96 | log "Running oinkmaster to update rules"
97 | oinkmaster -C /etc/oinkmaster.conf -o /etc/suricata/rules
98 |
99 | log "Updating sid-msg.map"
100 | /usr/share/oinkmaster/create-sidmap.pl /etc/suricata/rules > /etc/suricata/rules/sid-msg.map
101 |
102 | log "Stopping pcapoptikon's run_daemon and deleting pid file"
103 | kill $(cat /var/run/pcapoptikon-daemon.pid)
104 | sleep 5
105 | rm -f /var/run/pcapoptikon-daemon.pid
106 |
107 | log "Stopping suricata and deleting pid file"
108 | kill $(cat /var/run/suricata.pid)
109 | sleep 5
110 | rm -f /var/run/suricata.pid
111 |
112 | log "Starting up suricata and run_daemon again"
113 | /usr/bin/suricata -c /etc/suricata/suricata.yaml --unix-socket --pidfile /var/run/suricata.pid >/dev/null 2>&1 &
114 | /usr/bin/python /opt/pcapoptikon/manage.py run_daemon >/var/log/pcapoptikon_daemon.log 2>&1 &
115 | log $! > /var/run/pcapoptikon-daemon.pid
116 |
117 | log "Signatures reloaded"
118 | done
119 |
--------------------------------------------------------------------------------
/static/admin/css/rtl.css:
--------------------------------------------------------------------------------
1 | body {
2 | direction: rtl;
3 | }
4 |
5 | /* LOGIN */
6 |
7 | .login .form-row {
8 | float: right;
9 | }
10 |
11 | .login .form-row label {
12 | float: right;
13 | padding-left: 0.5em;
14 | padding-right: 0;
15 | text-align: left;
16 | }
17 |
18 | .login .submit-row {
19 | clear: both;
20 | padding: 1em 9.4em 0 0;
21 | }
22 |
23 | /* GLOBAL */
24 |
25 | th {
26 | text-align: right;
27 | }
28 |
29 | .module h2, .module caption {
30 | text-align: right;
31 | }
32 |
33 | .addlink, .changelink {
34 | padding-left: 0px;
35 | padding-right: 12px;
36 | background-position: 100% 0.2em;
37 | }
38 |
39 | .deletelink {
40 | padding-left: 0px;
41 | padding-right: 12px;
42 | background-position: 100% 0.25em;
43 | }
44 |
45 | .object-tools {
46 | float: left;
47 | }
48 |
49 | thead th:first-child,
50 | tfoot td:first-child {
51 | border-left: 1px solid #ddd !important;
52 | }
53 |
54 | /* LAYOUT */
55 |
56 | #user-tools {
57 | right: auto;
58 | left: 0;
59 | text-align: left;
60 | }
61 |
62 | div.breadcrumbs {
63 | text-align: right;
64 | }
65 |
66 | #content-main {
67 | float: right;
68 | }
69 |
70 | #content-related {
71 | float: left;
72 | margin-left: -19em;
73 | margin-right: auto;
74 | }
75 |
76 | .colMS {
77 | margin-left: 20em !important;
78 | margin-right: 10px !important;
79 | }
80 |
81 | /* SORTABLE TABLES */
82 |
83 | table thead th.sorted .sortoptions {
84 | float: left;
85 | }
86 |
87 | thead th.sorted .text {
88 | padding-right: 0;
89 | padding-left: 42px;
90 | }
91 |
92 | /* dashboard styles */
93 |
94 | .dashboard .module table td a {
95 | padding-left: .6em;
96 | padding-right: 12px;
97 | }
98 |
99 | /* changelists styles */
100 |
101 | .change-list .filtered {
102 | background: white url(../img/changelist-bg_rtl.gif) top left repeat-y !important;
103 | }
104 |
105 | .change-list .filtered table {
106 | border-left: 1px solid #ddd;
107 | border-right: 0px none;
108 | }
109 |
110 | #changelist-filter {
111 | right: auto;
112 | left: 0;
113 | border-left: 0px none;
114 | border-right: 1px solid #ddd;
115 | }
116 |
117 | .change-list .filtered .results, .change-list .filtered .paginator, .filtered #toolbar, .filtered div.xfull {
118 | margin-right: 0px !important;
119 | margin-left: 160px !important;
120 | }
121 |
122 | #changelist-filter li.selected {
123 | border-left: 0px none;
124 | padding-left: 0px;
125 | margin-left: 0;
126 | border-right: 5px solid #ccc;
127 | padding-right: 5px;
128 | margin-right: -10px;
129 | }
130 |
131 | .filtered .actions {
132 | border-left:1px solid #DDDDDD;
133 | margin-left:160px !important;
134 | border-right: 0 none;
135 | margin-right:0 !important;
136 | }
137 |
138 | #changelist table tbody td:first-child, #changelist table tbody th:first-child {
139 | border-right: 0;
140 | border-left: 1px solid #ddd;
141 | }
142 |
143 | /* FORMS */
144 |
145 | .aligned label {
146 | padding: 0 0 3px 1em;
147 | float: right;
148 | }
149 |
150 | .submit-row {
151 | text-align: left
152 | }
153 |
154 | .submit-row p.deletelink-box {
155 | float: right;
156 | }
157 |
158 | .submit-row .deletelink {
159 | background: url(../img/icon_deletelink.gif) 0 50% no-repeat;
160 | padding-right: 14px;
161 | }
162 |
163 | .vDateField, .vTimeField {
164 | margin-left: 2px;
165 | }
166 |
167 | form ul.inline li {
168 | float: right;
169 | padding-right: 0;
170 | padding-left: 7px;
171 | }
172 |
173 | input[type=submit].default, .submit-row input.default {
174 | float: left;
175 | }
176 |
177 | fieldset .field-box {
178 | float: right;
179 | margin-left: 20px;
180 | margin-right: 0;
181 | }
182 |
183 | .errorlist li {
184 | background-position: 100% .3em;
185 | padding: 4px 25px 4px 5px;
186 | }
187 |
188 | .errornote {
189 | background-position: 100% .3em;
190 | padding: 4px 25px 4px 5px;
191 | }
192 |
193 | /* WIDGETS */
194 |
195 | .calendarnav-previous {
196 | top: 0;
197 | left: auto;
198 | right: 0;
199 | }
200 |
201 | .calendarnav-next {
202 | top: 0;
203 | right: auto;
204 | left: 0;
205 | }
206 |
207 | .calendar caption, .calendarbox h2 {
208 | text-align: center;
209 | }
210 |
211 | .selector {
212 | float: right;
213 | }
214 |
215 | .selector .selector-filter {
216 | text-align: right;
217 | }
218 |
219 | .inline-deletelink {
220 | float: left;
221 | }
222 |
223 | /* MISC */
224 |
225 | .inline-related h2, .inline-group h2 {
226 | text-align: right
227 | }
228 |
229 | .inline-related h3 span.delete {
230 | padding-right: 20px;
231 | padding-left: inherit;
232 | left: 10px;
233 | right: inherit;
234 | float:left;
235 | }
236 |
237 | .inline-related h3 span.delete label {
238 | margin-left: inherit;
239 | margin-right: 2px;
240 | }
241 |
242 | /* IE7 specific bug fixes */
243 |
244 | div.colM {
245 | position: relative;
246 | }
247 |
248 | .submit-row input {
249 | float: left;
250 | }
251 |
--------------------------------------------------------------------------------
/static/admin/js/actions.js:
--------------------------------------------------------------------------------
1 | (function($) {
2 | var lastChecked;
3 |
4 | $.fn.actions = function(opts) {
5 | var options = $.extend({}, $.fn.actions.defaults, opts);
6 | var actionCheckboxes = $(this);
7 | var list_editable_changed = false;
8 | var checker = function(checked) {
9 | if (checked) {
10 | showQuestion();
11 | } else {
12 | reset();
13 | }
14 | $(actionCheckboxes).prop("checked", checked)
15 | .parent().parent().toggleClass(options.selectedClass, checked);
16 | },
17 | updateCounter = function() {
18 | var sel = $(actionCheckboxes).filter(":checked").length;
19 | // _actions_icnt is defined in the generated HTML
20 | // and contains the total amount of objects in the queryset
21 | $(options.counterContainer).html(interpolate(
22 | ngettext('%(sel)s of %(cnt)s selected', '%(sel)s of %(cnt)s selected', sel), {
23 | sel: sel,
24 | cnt: _actions_icnt
25 | }, true));
26 | $(options.allToggle).prop("checked", function() {
27 | var value;
28 | if (sel == actionCheckboxes.length) {
29 | value = true;
30 | showQuestion();
31 | } else {
32 | value = false;
33 | clearAcross();
34 | }
35 | return value;
36 | });
37 | },
38 | showQuestion = function() {
39 | $(options.acrossClears).hide();
40 | $(options.acrossQuestions).show();
41 | $(options.allContainer).hide();
42 | },
43 | showClear = function() {
44 | $(options.acrossClears).show();
45 | $(options.acrossQuestions).hide();
46 | $(options.actionContainer).toggleClass(options.selectedClass);
47 | $(options.allContainer).show();
48 | $(options.counterContainer).hide();
49 | },
50 | reset = function() {
51 | $(options.acrossClears).hide();
52 | $(options.acrossQuestions).hide();
53 | $(options.allContainer).hide();
54 | $(options.counterContainer).show();
55 | },
56 | clearAcross = function() {
57 | reset();
58 | $(options.acrossInput).val(0);
59 | $(options.actionContainer).removeClass(options.selectedClass);
60 | };
61 | // Show counter by default
62 | $(options.counterContainer).show();
63 | // Check state of checkboxes and reinit state if needed
64 | $(this).filter(":checked").each(function(i) {
65 | $(this).parent().parent().toggleClass(options.selectedClass);
66 | updateCounter();
67 | if ($(options.acrossInput).val() == 1) {
68 | showClear();
69 | }
70 | });
71 | $(options.allToggle).show().click(function() {
72 | checker($(this).prop("checked"));
73 | updateCounter();
74 | });
75 | $("a", options.acrossQuestions).click(function(event) {
76 | event.preventDefault();
77 | $(options.acrossInput).val(1);
78 | showClear();
79 | });
80 | $("a", options.acrossClears).click(function(event) {
81 | event.preventDefault();
82 | $(options.allToggle).prop("checked", false);
83 | clearAcross();
84 | checker(0);
85 | updateCounter();
86 | });
87 | lastChecked = null;
88 | $(actionCheckboxes).click(function(event) {
89 | if (!event) { event = window.event; }
90 | var target = event.target ? event.target : event.srcElement;
91 | if (lastChecked && $.data(lastChecked) != $.data(target) && event.shiftKey === true) {
92 | var inrange = false;
93 | $(lastChecked).prop("checked", target.checked)
94 | .parent().parent().toggleClass(options.selectedClass, target.checked);
95 | $(actionCheckboxes).each(function() {
96 | if ($.data(this) == $.data(lastChecked) || $.data(this) == $.data(target)) {
97 | inrange = (inrange) ? false : true;
98 | }
99 | if (inrange) {
100 | $(this).prop("checked", target.checked)
101 | .parent().parent().toggleClass(options.selectedClass, target.checked);
102 | }
103 | });
104 | }
105 | $(target).parent().parent().toggleClass(options.selectedClass, target.checked);
106 | lastChecked = target;
107 | updateCounter();
108 | });
109 | $('form#changelist-form table#result_list tr').find('td:gt(0) :input').change(function() {
110 | list_editable_changed = true;
111 | });
112 | $('form#changelist-form button[name="index"]').click(function(event) {
113 | if (list_editable_changed) {
114 | return confirm(gettext("You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost."));
115 | }
116 | });
117 | $('form#changelist-form input[name="_save"]').click(function(event) {
118 | var action_changed = false;
119 | $('select option:selected', options.actionContainer).each(function() {
120 | if ($(this).val()) {
121 | action_changed = true;
122 | }
123 | });
124 | if (action_changed) {
125 | if (list_editable_changed) {
126 | return confirm(gettext("You have selected an action, but you haven't saved your changes to individual fields yet. Please click OK to save. You'll need to re-run the action."));
127 | } else {
128 | return confirm(gettext("You have selected an action, and you haven't made any changes on individual fields. You're probably looking for the Go button rather than the Save button."));
129 | }
130 | }
131 | });
132 | };
133 | /* Setup plugin defaults */
134 | $.fn.actions.defaults = {
135 | actionContainer: "div.actions",
136 | counterContainer: "span.action-counter",
137 | allContainer: "div.actions span.all",
138 | acrossInput: "div.actions input.select-across",
139 | acrossQuestions: "div.actions span.question",
140 | acrossClears: "div.actions span.clear",
141 | allToggle: "#action-toggle",
142 | selectedClass: "selected"
143 | };
144 | })(django.jQuery);
145 |
--------------------------------------------------------------------------------
/static/css/bootstrap-datepicker.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Datepicker for Bootstrap
3 | *
4 | * Copyright 2012 Stefan Petre
5 | * Licensed under the Apache License v2.0
6 | * http://www.apache.org/licenses/LICENSE-2.0
7 | *
8 | */
9 | .datepicker {
10 | top: 0;
11 | left: 0;
12 | padding: 4px;
13 | margin-top: 1px;
14 | -webkit-border-radius: 4px;
15 | -moz-border-radius: 4px;
16 | border-radius: 4px;
17 | /*.dow {
18 | border-top: 1px solid #ddd !important;
19 | }*/
20 |
21 | }
22 | .datepicker:before {
23 | content: '';
24 | display: inline-block;
25 | border-left: 7px solid transparent;
26 | border-right: 7px solid transparent;
27 | border-bottom: 7px solid #ccc;
28 | border-bottom-color: rgba(0, 0, 0, 0.2);
29 | position: absolute;
30 | top: -7px;
31 | left: 6px;
32 | }
33 | .datepicker:after {
34 | content: '';
35 | display: inline-block;
36 | border-left: 6px solid transparent;
37 | border-right: 6px solid transparent;
38 | border-bottom: 6px solid #ffffff;
39 | position: absolute;
40 | top: -6px;
41 | left: 7px;
42 | }
43 | .datepicker > div {
44 | display: none;
45 | }
46 | .datepicker table {
47 | width: 100%;
48 | margin: 0;
49 | }
50 | .datepicker td,
51 | .datepicker th {
52 | text-align: center;
53 | width: 20px;
54 | height: 20px;
55 | -webkit-border-radius: 4px;
56 | -moz-border-radius: 4px;
57 | border-radius: 4px;
58 | }
59 | .datepicker td.day:hover {
60 | background: #eeeeee;
61 | cursor: pointer;
62 | }
63 | .datepicker td.day.disabled {
64 | color: #eeeeee;
65 | }
66 | .datepicker td.old,
67 | .datepicker td.new {
68 | color: #999999;
69 | }
70 | .datepicker td.active,
71 | .datepicker td.active:hover {
72 | color: #ffffff;
73 | background-color: #006dcc;
74 | background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
75 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
76 | background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
77 | background-image: -o-linear-gradient(top, #0088cc, #0044cc);
78 | background-image: linear-gradient(to bottom, #0088cc, #0044cc);
79 | background-repeat: repeat-x;
80 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);
81 | border-color: #0044cc #0044cc #002a80;
82 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
83 | *background-color: #0044cc;
84 | /* Darken IE7 buttons by default so they stand out more given they won't have borders */
85 |
86 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
87 | color: #fff;
88 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
89 | }
90 | .datepicker td.active:hover,
91 | .datepicker td.active:hover:hover,
92 | .datepicker td.active:focus,
93 | .datepicker td.active:hover:focus,
94 | .datepicker td.active:active,
95 | .datepicker td.active:hover:active,
96 | .datepicker td.active.active,
97 | .datepicker td.active:hover.active,
98 | .datepicker td.active.disabled,
99 | .datepicker td.active:hover.disabled,
100 | .datepicker td.active[disabled],
101 | .datepicker td.active:hover[disabled] {
102 | color: #ffffff;
103 | background-color: #0044cc;
104 | *background-color: #003bb3;
105 | }
106 | .datepicker td.active:active,
107 | .datepicker td.active:hover:active,
108 | .datepicker td.active.active,
109 | .datepicker td.active:hover.active {
110 | background-color: #003399 \9;
111 | }
112 | .datepicker td span {
113 | display: block;
114 | width: 47px;
115 | height: 54px;
116 | line-height: 54px;
117 | float: left;
118 | margin: 2px;
119 | cursor: pointer;
120 | -webkit-border-radius: 4px;
121 | -moz-border-radius: 4px;
122 | border-radius: 4px;
123 | }
124 | .datepicker td span:hover {
125 | background: #eeeeee;
126 | }
127 | .datepicker td span.active {
128 | color: #ffffff;
129 | background-color: #006dcc;
130 | background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
131 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
132 | background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
133 | background-image: -o-linear-gradient(top, #0088cc, #0044cc);
134 | background-image: linear-gradient(to bottom, #0088cc, #0044cc);
135 | background-repeat: repeat-x;
136 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);
137 | border-color: #0044cc #0044cc #002a80;
138 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
139 | *background-color: #0044cc;
140 | /* Darken IE7 buttons by default so they stand out more given they won't have borders */
141 |
142 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
143 | color: #fff;
144 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
145 | }
146 | .datepicker td span.active:hover,
147 | .datepicker td span.active:focus,
148 | .datepicker td span.active:active,
149 | .datepicker td span.active.active,
150 | .datepicker td span.active.disabled,
151 | .datepicker td span.active[disabled] {
152 | color: #ffffff;
153 | background-color: #0044cc;
154 | *background-color: #003bb3;
155 | }
156 | .datepicker td span.active:active,
157 | .datepicker td span.active.active {
158 | background-color: #003399 \9;
159 | }
160 | .datepicker td span.old {
161 | color: #999999;
162 | }
163 | .datepicker th.switch {
164 | width: 145px;
165 | }
166 | .datepicker th.next,
167 | .datepicker th.prev {
168 | font-size: 21px;
169 | }
170 | .datepicker thead tr:first-child th {
171 | cursor: pointer;
172 | }
173 | .datepicker thead tr:first-child th:hover {
174 | background: #eeeeee;
175 | }
176 | .input-append.date .add-on i,
177 | .input-prepend.date .add-on i {
178 | display: block;
179 | cursor: pointer;
180 | width: 16px;
181 | height: 16px;
182 | }
--------------------------------------------------------------------------------
/static/css/dataTables.tableTools.min.css:
--------------------------------------------------------------------------------
1 | div.DTTT_container{position:relative;float:right;margin-bottom:1em}@media screen and (max-width:640px){div.DTTT_container{float:none!important;text-align:center}div.DTTT_container:after{visibility:hidden;display:block;content:"";clear:both;height:0}}a.DTTT_button,button.DTTT_button,div.DTTT_button{position:relative;display:inline-block;margin-right:3px;padding:5px 8px;border:1px solid #999;cursor:pointer;font-size:.88em;color:#000!important;-webkit-border-radius:2px;-moz-border-radius:2px;-ms-border-radius:2px;-o-border-radius:2px;border-radius:2px;-webkit-box-shadow:1px 1px 3px #ccc;-moz-box-shadow:1px 1px 3px #ccc;-ms-box-shadow:1px 1px 3px #ccc;-o-box-shadow:1px 1px 3px #ccc;box-shadow:1px 1px 3px #ccc;background:#fff;background:-webkit-linear-gradient(top,#fff 0,#f3f3f3 89%,#f9f9f9 100%);background:-moz-linear-gradient(top,#fff 0,#f3f3f3 89%,#f9f9f9 100%);background:-ms-linear-gradient(top,#fff 0,#f3f3f3 89%,#f9f9f9 100%);background:-o-linear-gradient(top,#fff 0,#f3f3f3 89%,#f9f9f9 100%);background:linear-gradient(top,#fff 0,#f3f3f3 89%,#f9f9f9 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#f9f9f9', GradientType=0)}button.DTTT_button{height:30px;padding:3px 8px}.DTTT_button embed{outline:0}a.DTTT_button:hover,button.DTTT_button:hover,div.DTTT_button:hover{border:1px solid #666;text-decoration:none!important;-webkit-box-shadow:1px 1px 3px #999;-moz-box-shadow:1px 1px 3px #999;-ms-box-shadow:1px 1px 3px #999;-o-box-shadow:1px 1px 3px #999;box-shadow:1px 1px 3px #999;background:#f3f3f3;background:-webkit-linear-gradient(top,#f3f3f3 0,#e2e2e2 89%,#f4f4f4 100%);background:-moz-linear-gradient(top,#f3f3f3 0,#e2e2e2 89%,#f4f4f4 100%);background:-ms-linear-gradient(top,#f3f3f3 0,#e2e2e2 89%,#f4f4f4 100%);background:-o-linear-gradient(top,#f3f3f3 0,#e2e2e2 89%,#f4f4f4 100%);background:linear-gradient(top,#f3f3f3 0,#e2e2e2 89%,#f4f4f4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f3f3f3', endColorstr='#f4f4f4', GradientType=0)}a.DTTT_button:focus,button.DTTT_button:focus,div.DTTT_button:focus{border:1px solid #426c9e;text-shadow:0 1px 0 #c4def1;outline:0;background-color:#a3d0ef 100%;background-image:-webkit-linear-gradient(top,#a3d0ef 0,#79ace9 65%,#a3d0ef 100%);background-image:-moz-linear-gradient(top,#a3d0ef 0,#79ace9 65%,#a3d0ef 100%);background-image:-ms-linear-gradient(top,#a3d0ef 0,#79ace9 65%,#a3d0ef 100%);background-image:-o-linear-gradient(top,#a3d0ef 0,#79ace9 65%,#a3d0ef 100%);background-image:linear-gradient(top,#a3d0ef 0,#79ace9 65%,#a3d0ef 100%);filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0, StartColorStr='#a3d0ef', EndColorStr='#a3d0ef')}a.DTTT_button:active,button.DTTT_button:active,div.DTTT_button:active{-webkit-box-shadow:inset 1px 1px 3px #999;-moz-box-shadow:inset 1px 1px 3px #999;box-shadow:inset 1px 1px 3px #999}a.DTTT_disabled,button.DTTT_disabled,div.DTTT_disabled{color:#999;border:1px solid #d0d0d0;background:#fff;background:-webkit-linear-gradient(top,#fff 0,#f9f9f9 89%,#fafafa 100%);background:-moz-linear-gradient(top,#fff 0,#f9f9f9 89%,#fafafa 100%);background:-ms-linear-gradient(top,#fff 0,#f9f9f9 89%,#fafafa 100%);background:-o-linear-gradient(top,#fff 0,#f9f9f9 89%,#fafafa 100%);background:linear-gradient(top,#fff 0,#f9f9f9 89%,#fafafa 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#fafafa', GradientType=0)}button.DTTT_button_collection span{padding-right:17px;background:url(../images/collection.png) center right no-repeat}button.DTTT_button_collection:hover span{padding-right:17px;background:url(../images/collection_hover.png) center right no-repeat #f0f0f0}table.DTTT_selectable tbody tr{cursor:pointer}table.dataTable tr.DTTT_selected.odd,table.dataTable tr.DTTT_selected.odd td.sorting_1,table.dataTable tr.DTTT_selected.odd td.sorting_2,table.dataTable tr.DTTT_selected.odd td.sorting_3{background-color:#9FAFD1}table.dataTable tr.DTTT_selected.even,table.dataTable tr.DTTT_selected.even td.sorting_1,table.dataTable tr.DTTT_selected.even td.sorting_2,table.dataTable tr.DTTT_selected.even td.sorting_3{background-color:#B0BED9}div.DTTT_collection{width:150px;padding:8px 8px 4px;border:1px solid #ccc;border:1px solid rgba(0,0,0,.4);background-color:#f3f3f3;background-color:rgba(255,255,255,.3);overflow:hidden;z-index:2002;-webkit-border-radius:5px;-moz-border-radius:5px;-ms-border-radius:5px;-o-border-radius:5px;border-radius:5px;-webkit-box-shadow:3px 3px 5px rgba(0,0,0,.3);-moz-box-shadow:3px 3px 5px rgba(0,0,0,.3);-ms-box-shadow:3px 3px 5px rgba(0,0,0,.3);-o-box-shadow:3px 3px 5px rgba(0,0,0,.3);box-shadow:3px 3px 5px rgba(0,0,0,.3)}div.DTTT_collection_background{background:url(../images/background.png) top left;z-index:2001}div.DTTT_collection a.DTTT_button,div.DTTT_collection button.DTTT_button,div.DTTT_collection div.DTTT_button{position:relative;left:0;right:0;display:block;float:none;margin-bottom:4px;-webkit-box-shadow:1px 1px 3px #999;-moz-box-shadow:1px 1px 3px #999;-ms-box-shadow:1px 1px 3px #999;-o-box-shadow:1px 1px 3px #999;box-shadow:1px 1px 3px #999}.DTTT_print_info{position:fixed;top:50%;left:50%;width:400px;height:150px;margin-left:-200px;margin-top:-75px;text-align:center;color:#333;padding:10px 30px;background:#fff;background:-webkit-linear-gradient(top,#fff 0,#f3f3f3 89%,#f9f9f9 100%);background:-moz-linear-gradient(top,#fff 0,#f3f3f3 89%,#f9f9f9 100%);background:-ms-linear-gradient(top,#fff 0,#f3f3f3 89%,#f9f9f9 100%);background:-o-linear-gradient(top,#fff 0,#f3f3f3 89%,#f9f9f9 100%);background:linear-gradient(top,#fff 0,#f3f3f3 89%,#f9f9f9 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#f9f9f9', GradientType=0);opacity:.95;border:1px solid #000;border:1px solid rgba(0,0,0,.5);-webkit-border-radius:6px;-moz-border-radius:6px;-ms-border-radius:6px;-o-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 3px 7px rgba(0,0,0,.5);-moz-box-shadow:0 3px 7px rgba(0,0,0,.5);-ms-box-shadow:0 3px 7px rgba(0,0,0,.5);-o-box-shadow:0 3px 7px rgba(0,0,0,.5);box-shadow:0 3px 7px rgba(0,0,0,.5)}.DTTT_print_info h6{font-weight:400;font-size:28px;line-height:28px;margin:1em}.DTTT_print_info p{font-size:14px;line-height:20px}
--------------------------------------------------------------------------------
/static/css/dataTables.bootstrap.min.css:
--------------------------------------------------------------------------------
1 | div.dataTables_length label{font-weight:400;text-align:left;white-space:nowrap}div.dataTables_length select{width:75px;display:inline-block}div.dataTables_filter{text-align:right}div.dataTables_filter label{font-weight:400;white-space:nowrap;text-align:left}div.dataTables_filter input{margin-left:.5em;display:inline-block}div.dataTables_info{padding-top:8px;white-space:nowrap}div.dataTables_paginate{margin:0;white-space:nowrap;text-align:right}div.dataTables_paginate ul.pagination{margin:2px 0;white-space:nowrap}@media screen and (max-width:767px){div.dataTables_filter,div.dataTables_info,div.dataTables_length,div.dataTables_paginate{text-align:center}}table.dataTable td,table.dataTable th{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}table.dataTable{clear:both;margin-top:6px!important;margin-bottom:6px!important;max-width:none!important}table.dataTable thead .sorting,table.dataTable thead .sorting_asc,table.dataTable thead .sorting_asc_disabled,table.dataTable thead .sorting_desc,table.dataTable thead .sorting_desc_disabled{cursor:pointer}table.dataTable thead .sorting{background:url(../images/sort_both.png) center right no-repeat}table.dataTable thead .sorting_asc{background:url(../images/sort_asc.png) center right no-repeat}table.dataTable thead .sorting_desc{background:url(../images/sort_desc.png) center right no-repeat}table.dataTable thead .sorting_asc_disabled{background:url(../images/sort_asc_disabled.png) center right no-repeat}table.dataTable thead .sorting_desc_disabled{background:url(../images/sort_desc_disabled.png) center right no-repeat}table.dataTable thead>tr>th{padding-left:18px;padding-right:18px}table.dataTable th:active{outline:0}div.dataTables_scrollHead table{margin-bottom:0!important;border-bottom-left-radius:0;border-bottom-right-radius:0}div.dataTables_scrollHead table thead tr:last-child td:first-child,div.dataTables_scrollHead table thead tr:last-child th:first-child{border-bottom-left-radius:0!important;border-bottom-right-radius:0!important}div.dataTables_scrollBody table{border-top:none;margin-top:0!important;margin-bottom:0!important}div.dataTables_scrollBody tbody tr:first-child td,div.dataTables_scrollBody tbody tr:first-child th{border-top:none}div.dataTables_scrollFoot table{margin-top:0!important;border-top:none}table.table-bordered.dataTable{border-collapse:separate!important}table.table-bordered thead td,table.table-bordered thead th{border-left-width:0;border-top-width:0}table.table-bordered tbody td,table.table-bordered tbody th{border-left-width:0;border-bottom-width:0}table.table-bordered td:last-child,table.table-bordered th:last-child{border-right-width:0}div.dataTables_scrollHead table.table-bordered{border-bottom-width:0}.table.dataTable tbody tr.active td,.table.dataTable tbody tr.active th{background-color:#08C;color:#fff}.table.dataTable tbody tr.active:hover td,.table.dataTable tbody tr.active:hover th{background-color:#0075b0!important}.table.dataTable tbody tr.active td>a,.table.dataTable tbody tr.active th>a{color:#fff}.table-striped.dataTable tbody tr.active:nth-child(odd) td,.table-striped.dataTable tbody tr.active:nth-child(odd) th{background-color:#017ebc}table.DTTT_selectable tbody tr{cursor:pointer}div.DTTT .btn{color:#333!important;font-size:12px}div.DTTT .btn:hover{text-decoration:none!important}ul.DTTT_dropdown.dropdown-menu{z-index:2003}ul.DTTT_dropdown.dropdown-menu a{color:#333!important}ul.DTTT_dropdown.dropdown-menu li{position:relative}ul.DTTT_dropdown.dropdown-menu li:hover a{background-color:#08c;color:#fff!important}div.DTTT_collection_background{z-index:2002}div.DTTT_print_info{position:fixed;top:50%;left:50%;width:400px;height:150px;margin-left:-200px;margin-top:-75px;text-align:center;color:#333;padding:10px 30px;opacity:.95;background-color:#fff;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 3px 7px rgba(0,0,0,.5);box-shadow:0 3px 7px rgba(0,0,0,.5)}div.DTTT_print_info h6{font-weight:400;font-size:28px;line-height:28px;margin:1em}div.DTTT_print_info p{font-size:14px;line-height:20px}div.dataTables_processing{position:absolute;top:50%;left:50%;width:100%;height:60px;margin-left:-50%;margin-top:-25px;padding-top:20px;padding-bottom:20px;text-align:center;font-size:1.2em;background:-webkit-gradient(linear,left top,right top,color-stop(0%,rgba(255,255,255,0)),color-stop(25%,rgba(255,255,255,.9)),color-stop(75%,rgba(255,255,255,.9)),color-stop(100%,rgba(255,255,255,0)));background:-webkit-linear-gradient(left,rgba(255,255,255,0) 0,rgba(255,255,255,.9) 25%,rgba(255,255,255,.9) 75%,rgba(255,255,255,0) 100%);background:-moz-linear-gradient(left,rgba(255,255,255,0) 0,rgba(255,255,255,.9) 25%,rgba(255,255,255,.9) 75%,rgba(255,255,255,0) 100%);background:-ms-linear-gradient(left,rgba(255,255,255,0) 0,rgba(255,255,255,.9) 25%,rgba(255,255,255,.9) 75%,rgba(255,255,255,0) 100%);background:-o-linear-gradient(left,rgba(255,255,255,0) 0,rgba(255,255,255,.9) 25%,rgba(255,255,255,.9) 75%,rgba(255,255,255,0) 100%);background:linear-gradient(to right,rgba(255,255,255,0) 0,rgba(255,255,255,.9) 25%,rgba(255,255,255,.9) 75%,rgba(255,255,255,0) 100%)}div.DTFC_LeftFootWrapper table,div.DTFC_LeftHeadWrapper table,div.DTFC_RightFootWrapper table,div.DTFC_RightHeadWrapper table,table.DTFC_Cloned tr.even{background-color:#fff;margin-bottom:0}div.DTFC_LeftHeadWrapper table,div.DTFC_RightHeadWrapper table{border-bottom:none!important;margin-bottom:0!important;border-top-right-radius:0!important;border-bottom-left-radius:0!important;border-bottom-right-radius:0!important}div.DTFC_LeftHeadWrapper table thead tr:last-child td:first-child,div.DTFC_LeftHeadWrapper table thead tr:last-child th:first-child,div.DTFC_RightHeadWrapper table thead tr:last-child td:first-child,div.DTFC_RightHeadWrapper table thead tr:last-child th:first-child{border-bottom-left-radius:0!important;border-bottom-right-radius:0!important}div.DTFC_LeftBodyWrapper table,div.DTFC_RightBodyWrapper table{border-top:none;margin:0!important}div.DTFC_LeftBodyWrapper tbody tr:first-child td,div.DTFC_LeftBodyWrapper tbody tr:first-child th,div.DTFC_RightBodyWrapper tbody tr:first-child td,div.DTFC_RightBodyWrapper tbody tr:first-child th{border-top:none}div.DTFC_LeftFootWrapper table,div.DTFC_RightFootWrapper table{border-top:none;margin-top:0!important}div.FixedHeader_Cloned table{margin:0!important}
--------------------------------------------------------------------------------
/static/admin/js/urlify.js:
--------------------------------------------------------------------------------
1 | var LATIN_MAP = {
2 | 'À': 'A', 'Á': 'A', 'Â': 'A', 'Ã': 'A', 'Ä': 'A', 'Å': 'A', 'Æ': 'AE', 'Ç':
3 | 'C', 'È': 'E', 'É': 'E', 'Ê': 'E', 'Ë': 'E', 'Ì': 'I', 'Í': 'I', 'Î': 'I',
4 | 'Ï': 'I', 'Ð': 'D', 'Ñ': 'N', 'Ò': 'O', 'Ó': 'O', 'Ô': 'O', 'Õ': 'O', 'Ö':
5 | 'O', 'Ő': 'O', 'Ø': 'O', 'Ù': 'U', 'Ú': 'U', 'Û': 'U', 'Ü': 'U', 'Ű': 'U',
6 | 'Ý': 'Y', 'Þ': 'TH', 'Ÿ': 'Y', 'ß': 'ss', 'à':'a', 'á':'a', 'â': 'a', 'ã':
7 | 'a', 'ä': 'a', 'å': 'a', 'æ': 'ae', 'ç': 'c', 'è': 'e', 'é': 'e', 'ê': 'e',
8 | 'ë': 'e', 'ì': 'i', 'í': 'i', 'î': 'i', 'ï': 'i', 'ð': 'd', 'ñ': 'n', 'ò':
9 | 'o', 'ó': 'o', 'ô': 'o', 'õ': 'o', 'ö': 'o', 'ő': 'o', 'ø': 'o', 'ù': 'u',
10 | 'ú': 'u', 'û': 'u', 'ü': 'u', 'ű': 'u', 'ý': 'y', 'þ': 'th', 'ÿ': 'y'
11 | };
12 | var LATIN_SYMBOLS_MAP = {
13 | '©':'(c)'
14 | };
15 | var GREEK_MAP = {
16 | 'α':'a', 'β':'b', 'γ':'g', 'δ':'d', 'ε':'e', 'ζ':'z', 'η':'h', 'θ':'8',
17 | 'ι':'i', 'κ':'k', 'λ':'l', 'μ':'m', 'ν':'n', 'ξ':'3', 'ο':'o', 'π':'p',
18 | 'ρ':'r', 'σ':'s', 'τ':'t', 'υ':'y', 'φ':'f', 'χ':'x', 'ψ':'ps', 'ω':'w',
19 | 'ά':'a', 'έ':'e', 'ί':'i', 'ό':'o', 'ύ':'y', 'ή':'h', 'ώ':'w', 'ς':'s',
20 | 'ϊ':'i', 'ΰ':'y', 'ϋ':'y', 'ΐ':'i',
21 | 'Α':'A', 'Β':'B', 'Γ':'G', 'Δ':'D', 'Ε':'E', 'Ζ':'Z', 'Η':'H', 'Θ':'8',
22 | 'Ι':'I', 'Κ':'K', 'Λ':'L', 'Μ':'M', 'Ν':'N', 'Ξ':'3', 'Ο':'O', 'Π':'P',
23 | 'Ρ':'R', 'Σ':'S', 'Τ':'T', 'Υ':'Y', 'Φ':'F', 'Χ':'X', 'Ψ':'PS', 'Ω':'W',
24 | 'Ά':'A', 'Έ':'E', 'Ί':'I', 'Ό':'O', 'Ύ':'Y', 'Ή':'H', 'Ώ':'W', 'Ϊ':'I',
25 | 'Ϋ':'Y'
26 | };
27 | var TURKISH_MAP = {
28 | 'ş':'s', 'Ş':'S', 'ı':'i', 'İ':'I', 'ç':'c', 'Ç':'C', 'ü':'u', 'Ü':'U',
29 | 'ö':'o', 'Ö':'O', 'ğ':'g', 'Ğ':'G'
30 | };
31 | var RUSSIAN_MAP = {
32 | 'а':'a', 'б':'b', 'в':'v', 'г':'g', 'д':'d', 'е':'e', 'ё':'yo', 'ж':'zh',
33 | 'з':'z', 'и':'i', 'й':'j', 'к':'k', 'л':'l', 'м':'m', 'н':'n', 'о':'o',
34 | 'п':'p', 'р':'r', 'с':'s', 'т':'t', 'у':'u', 'ф':'f', 'х':'h', 'ц':'c',
35 | 'ч':'ch', 'ш':'sh', 'щ':'sh', 'ъ':'', 'ы':'y', 'ь':'', 'э':'e', 'ю':'yu',
36 | 'я':'ya',
37 | 'А':'A', 'Б':'B', 'В':'V', 'Г':'G', 'Д':'D', 'Е':'E', 'Ё':'Yo', 'Ж':'Zh',
38 | 'З':'Z', 'И':'I', 'Й':'J', 'К':'K', 'Л':'L', 'М':'M', 'Н':'N', 'О':'O',
39 | 'П':'P', 'Р':'R', 'С':'S', 'Т':'T', 'У':'U', 'Ф':'F', 'Х':'H', 'Ц':'C',
40 | 'Ч':'Ch', 'Ш':'Sh', 'Щ':'Sh', 'Ъ':'', 'Ы':'Y', 'Ь':'', 'Э':'E', 'Ю':'Yu',
41 | 'Я':'Ya'
42 | };
43 | var UKRAINIAN_MAP = {
44 | 'Є':'Ye', 'І':'I', 'Ї':'Yi', 'Ґ':'G', 'є':'ye', 'і':'i', 'ї':'yi', 'ґ':'g'
45 | };
46 | var CZECH_MAP = {
47 | 'č':'c', 'ď':'d', 'ě':'e', 'ň': 'n', 'ř':'r', 'š':'s', 'ť':'t', 'ů':'u',
48 | 'ž':'z', 'Č':'C', 'Ď':'D', 'Ě':'E', 'Ň': 'N', 'Ř':'R', 'Š':'S', 'Ť':'T',
49 | 'Ů':'U', 'Ž':'Z'
50 | };
51 | var POLISH_MAP = {
52 | 'ą':'a', 'ć':'c', 'ę':'e', 'ł':'l', 'ń':'n', 'ó':'o', 'ś':'s', 'ź':'z',
53 | 'ż':'z', 'Ą':'A', 'Ć':'C', 'Ę':'E', 'Ł':'L', 'Ń':'N', 'Ó':'O', 'Ś':'S',
54 | 'Ź':'Z', 'Ż':'Z'
55 | };
56 | var LATVIAN_MAP = {
57 | 'ā':'a', 'č':'c', 'ē':'e', 'ģ':'g', 'ī':'i', 'ķ':'k', 'ļ':'l', 'ņ':'n',
58 | 'š':'s', 'ū':'u', 'ž':'z', 'Ā':'A', 'Č':'C', 'Ē':'E', 'Ģ':'G', 'Ī':'I',
59 | 'Ķ':'K', 'Ļ':'L', 'Ņ':'N', 'Š':'S', 'Ū':'U', 'Ž':'Z'
60 | };
61 | var ARABIC_MAP = {
62 | 'أ':'a', 'ب':'b', 'ت':'t', 'ث': 'th', 'ج':'g', 'ح':'h', 'خ':'kh', 'د':'d',
63 | 'ذ':'th', 'ر':'r', 'ز':'z', 'س':'s', 'ش':'sh', 'ص':'s', 'ض':'d', 'ط':'t',
64 | 'ظ':'th', 'ع':'aa', 'غ':'gh', 'ف':'f', 'ق':'k', 'ك':'k', 'ل':'l', 'م':'m',
65 | 'ن':'n', 'ه':'h', 'و':'o', 'ي':'y'
66 | };
67 | var LITHUANIAN_MAP = {
68 | 'ą':'a', 'č':'c', 'ę':'e', 'ė':'e', 'į':'i', 'š':'s', 'ų':'u', 'ū':'u',
69 | 'ž':'z',
70 | 'Ą':'A', 'Č':'C', 'Ę':'E', 'Ė':'E', 'Į':'I', 'Š':'S', 'Ų':'U', 'Ū':'U',
71 | 'Ž':'Z'
72 | };
73 | var SERBIAN_MAP = {
74 | 'ђ':'dj', 'ј':'j', 'љ':'lj', 'њ':'nj', 'ћ':'c', 'џ':'dz', 'đ':'dj',
75 | 'Ђ':'Dj', 'Ј':'j', 'Љ':'Lj', 'Њ':'Nj', 'Ћ':'C', 'Џ':'Dz', 'Đ':'Dj'
76 | };
77 | var AZERBAIJANI_MAP = {
78 | 'ç':'c', 'ə':'e', 'ğ':'g', 'ı':'i', 'ö':'o', 'ş':'s', 'ü':'u',
79 | 'Ç':'C', 'Ə':'E', 'Ğ':'G', 'İ':'I', 'Ö':'O', 'Ş':'S', 'Ü':'U'
80 | };
81 |
82 | var ALL_DOWNCODE_MAPS = [
83 | LATIN_MAP,
84 | LATIN_SYMBOLS_MAP,
85 | GREEK_MAP,
86 | TURKISH_MAP,
87 | RUSSIAN_MAP,
88 | UKRAINIAN_MAP,
89 | CZECH_MAP,
90 | POLISH_MAP,
91 | LATVIAN_MAP,
92 | ARABIC_MAP,
93 | LITHUANIAN_MAP,
94 | SERBIAN_MAP,
95 | AZERBAIJANI_MAP
96 | ];
97 |
98 | var Downcoder = {
99 | 'Initialize': function() {
100 | if (Downcoder.map) { // already made
101 | return;
102 | }
103 | Downcoder.map = {};
104 | Downcoder.chars = [];
105 | for (var i=0; i5':" ▴";this.appendChild(sortrevind);return}if(this.className.search(/\bsorttable_sorted_reverse\b/)!=-1){sorttable.reverse(this.sorttable_tbody);this.className=this.className.replace("sorttable_sorted_reverse","sorttable_sorted");this.removeChild(document.getElementById("sorttable_sortrevind"));sortfwdind=document.createElement("span");sortfwdind.id="sorttable_sortfwdind";sortfwdind.innerHTML=stIsIE?' 6':" ▾";this.appendChild(sortfwdind);return}theadrow=this.parentNode;forEach(theadrow.childNodes,function(e){if(e.nodeType==1){e.className=e.className.replace("sorttable_sorted_reverse","");e.className=e.className.replace("sorttable_sorted","")}});sortfwdind=document.getElementById("sorttable_sortfwdind");if(sortfwdind){sortfwdind.parentNode.removeChild(sortfwdind)}sortrevind=document.getElementById("sorttable_sortrevind");if(sortrevind){sortrevind.parentNode.removeChild(sortrevind)}this.className+=" sorttable_sorted";sortfwdind=document.createElement("span");sortfwdind.id="sorttable_sortfwdind";sortfwdind.innerHTML=stIsIE?' 6':" ▾";this.appendChild(sortfwdind);row_array=[];col=this.sorttable_columnindex;rows=this.sorttable_tbody.rows;for(var t=0;t12){return sorttable.sort_ddmm}else if(second>12){return sorttable.sort_mmdd}else{sortfn=sorttable.sort_ddmm}}}}return sortfn},getInnerText:function(e){if(!e)return"";hasInputs=typeof e.getElementsByTagName=="function"&&e.getElementsByTagName("input").length;if(e.getAttribute("sorttable_customkey")!=null){return e.getAttribute("sorttable_customkey")}else if(typeof e.textContent!="undefined"&&!hasInputs){return e.textContent.replace(/^\s+|\s+$/g,"")}else if(typeof e.innerText!="undefined"&&!hasInputs){return e.innerText.replace(/^\s+|\s+$/g,"")}else if(typeof e.text!="undefined"&&!hasInputs){return e.text.replace(/^\s+|\s+$/g,"")}else{switch(e.nodeType){case 3:if(e.nodeName.toLowerCase()=="input"){return e.value.replace(/^\s+|\s+$/g,"")};case 4:return e.nodeValue.replace(/^\s+|\s+$/g,"");break;case 1:case 11:var t="";for(var n=0;n=0;t--){e.appendChild(newrows[t])}delete newrows},sort_numeric:function(e,t){aa=parseFloat(e[0].replace(/[^0-9.-]/g,""));if(isNaN(aa))aa=0;bb=parseFloat(t[0].replace(/[^0-9.-]/g,""));if(isNaN(bb))bb=0;return aa-bb},sort_alpha:function(e,t){if(e[0]==t[0])return 0;if(e[0]0){var o=e[s];e[s]=e[s+1];e[s+1]=o;i=true}}r--;if(!i)break;for(var s=r;s>n;--s){if(t(e[s],e[s-1])<0){var o=e[s];e[s]=e[s-1];e[s-1]=o;i=true}}n++}}};if(document.addEventListener){document.addEventListener("DOMContentLoaded",sorttable.init,false)}if(/WebKit/i.test(navigator.userAgent)){var _timer=setInterval(function(){if(/loaded|complete/.test(document.readyState)){sorttable.init()}},10)}window.onload=sorttable.init;dean_addEvent.guid=1;fixEvent.preventDefault=function(){this.returnValue=false};fixEvent.stopPropagation=function(){this.cancelBubble=true};if(!Array.forEach){Array.forEach=function(e,t,n){for(var r=0;r=0) && parseFloat(navigator.appVersion);
5 | var isIE = ((document.all) && (!isOpera)) && parseFloat(navigator.appVersion.split("MSIE ")[1].split(";")[0]);
6 |
7 | // Cross-browser event handlers.
8 | function addEvent(obj, evType, fn) {
9 | if (obj.addEventListener) {
10 | obj.addEventListener(evType, fn, false);
11 | return true;
12 | } else if (obj.attachEvent) {
13 | var r = obj.attachEvent("on" + evType, fn);
14 | return r;
15 | } else {
16 | return false;
17 | }
18 | }
19 |
20 | function removeEvent(obj, evType, fn) {
21 | if (obj.removeEventListener) {
22 | obj.removeEventListener(evType, fn, false);
23 | return true;
24 | } else if (obj.detachEvent) {
25 | obj.detachEvent("on" + evType, fn);
26 | return true;
27 | } else {
28 | return false;
29 | }
30 | }
31 |
32 | function cancelEventPropagation(e) {
33 | if (!e) e = window.event;
34 | e.cancelBubble = true;
35 | if (e.stopPropagation) e.stopPropagation();
36 | }
37 |
38 | // quickElement(tagType, parentReference [, textInChildNode, attribute, attributeValue ...]);
39 | function quickElement() {
40 | var obj = document.createElement(arguments[0]);
41 | if (arguments[2]) {
42 | var textNode = document.createTextNode(arguments[2]);
43 | obj.appendChild(textNode);
44 | }
45 | var len = arguments.length;
46 | for (var i = 3; i < len; i += 2) {
47 | obj.setAttribute(arguments[i], arguments[i+1]);
48 | }
49 | arguments[1].appendChild(obj);
50 | return obj;
51 | }
52 |
53 | // "a" is reference to an object
54 | function removeChildren(a) {
55 | while (a.hasChildNodes()) a.removeChild(a.lastChild);
56 | }
57 |
58 | // ----------------------------------------------------------------------------
59 | // Cross-browser xmlhttp object
60 | // from http://jibbering.com/2002/4/httprequest.html
61 | // ----------------------------------------------------------------------------
62 | var xmlhttp;
63 | /*@cc_on @*/
64 | /*@if (@_jscript_version >= 5)
65 | try {
66 | xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
67 | } catch (e) {
68 | try {
69 | xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
70 | } catch (E) {
71 | xmlhttp = false;
72 | }
73 | }
74 | @else
75 | xmlhttp = false;
76 | @end @*/
77 | if (!xmlhttp && typeof XMLHttpRequest != 'undefined') {
78 | xmlhttp = new XMLHttpRequest();
79 | }
80 |
81 | // ----------------------------------------------------------------------------
82 | // Find-position functions by PPK
83 | // See http://www.quirksmode.org/js/findpos.html
84 | // ----------------------------------------------------------------------------
85 | function findPosX(obj) {
86 | var curleft = 0;
87 | if (obj.offsetParent) {
88 | while (obj.offsetParent) {
89 | curleft += obj.offsetLeft - ((isOpera) ? 0 : obj.scrollLeft);
90 | obj = obj.offsetParent;
91 | }
92 | // IE offsetParent does not include the top-level
93 | if (isIE && obj.parentElement){
94 | curleft += obj.offsetLeft - obj.scrollLeft;
95 | }
96 | } else if (obj.x) {
97 | curleft += obj.x;
98 | }
99 | return curleft;
100 | }
101 |
102 | function findPosY(obj) {
103 | var curtop = 0;
104 | if (obj.offsetParent) {
105 | while (obj.offsetParent) {
106 | curtop += obj.offsetTop - ((isOpera) ? 0 : obj.scrollTop);
107 | obj = obj.offsetParent;
108 | }
109 | // IE offsetParent does not include the top-level
110 | if (isIE && obj.parentElement){
111 | curtop += obj.offsetTop - obj.scrollTop;
112 | }
113 | } else if (obj.y) {
114 | curtop += obj.y;
115 | }
116 | return curtop;
117 | }
118 |
119 | //-----------------------------------------------------------------------------
120 | // Date object extensions
121 | // ----------------------------------------------------------------------------
122 |
123 | Date.prototype.getTwelveHours = function() {
124 | hours = this.getHours();
125 | if (hours == 0) {
126 | return 12;
127 | }
128 | else {
129 | return hours <= 12 ? hours : hours-12
130 | }
131 | }
132 |
133 | Date.prototype.getTwoDigitMonth = function() {
134 | return (this.getMonth() < 9) ? '0' + (this.getMonth()+1) : (this.getMonth()+1);
135 | }
136 |
137 | Date.prototype.getTwoDigitDate = function() {
138 | return (this.getDate() < 10) ? '0' + this.getDate() : this.getDate();
139 | }
140 |
141 | Date.prototype.getTwoDigitTwelveHour = function() {
142 | return (this.getTwelveHours() < 10) ? '0' + this.getTwelveHours() : this.getTwelveHours();
143 | }
144 |
145 | Date.prototype.getTwoDigitHour = function() {
146 | return (this.getHours() < 10) ? '0' + this.getHours() : this.getHours();
147 | }
148 |
149 | Date.prototype.getTwoDigitMinute = function() {
150 | return (this.getMinutes() < 10) ? '0' + this.getMinutes() : this.getMinutes();
151 | }
152 |
153 | Date.prototype.getTwoDigitSecond = function() {
154 | return (this.getSeconds() < 10) ? '0' + this.getSeconds() : this.getSeconds();
155 | }
156 |
157 | Date.prototype.getHourMinute = function() {
158 | return this.getTwoDigitHour() + ':' + this.getTwoDigitMinute();
159 | }
160 |
161 | Date.prototype.getHourMinuteSecond = function() {
162 | return this.getTwoDigitHour() + ':' + this.getTwoDigitMinute() + ':' + this.getTwoDigitSecond();
163 | }
164 |
165 | Date.prototype.strftime = function(format) {
166 | var fields = {
167 | c: this.toString(),
168 | d: this.getTwoDigitDate(),
169 | H: this.getTwoDigitHour(),
170 | I: this.getTwoDigitTwelveHour(),
171 | m: this.getTwoDigitMonth(),
172 | M: this.getTwoDigitMinute(),
173 | p: (this.getHours() >= 12) ? 'PM' : 'AM',
174 | S: this.getTwoDigitSecond(),
175 | w: '0' + this.getDay(),
176 | x: this.toLocaleDateString(),
177 | X: this.toLocaleTimeString(),
178 | y: ('' + this.getFullYear()).substr(2, 4),
179 | Y: '' + this.getFullYear(),
180 | '%' : '%'
181 | };
182 | var result = '', i = 0;
183 | while (i < format.length) {
184 | if (format.charAt(i) === '%') {
185 | result = result + fields[format.charAt(i + 1)];
186 | ++i;
187 | }
188 | else {
189 | result = result + format.charAt(i);
190 | }
191 | ++i;
192 | }
193 | return result;
194 | }
195 |
196 | // ----------------------------------------------------------------------------
197 | // String object extensions
198 | // ----------------------------------------------------------------------------
199 | String.prototype.pad_left = function(pad_length, pad_string) {
200 | var new_string = this;
201 | for (var i = 0; new_string.length < pad_length; i++) {
202 | new_string = pad_string + new_string;
203 | }
204 | return new_string;
205 | }
206 |
207 | String.prototype.strptime = function(format) {
208 | var split_format = format.split(/[.\-/]/);
209 | var date = this.split(/[.\-/]/);
210 | var i = 0;
211 | while (i < split_format.length) {
212 | switch (split_format[i]) {
213 | case "%d":
214 | var day = date[i];
215 | break;
216 | case "%m":
217 | var month = date[i] - 1;
218 | break;
219 | case "%Y":
220 | var year = date[i];
221 | break;
222 | case "%y":
223 | var year = date[i];
224 | break;
225 | }
226 | ++i;
227 | };
228 | return new Date(year, month, day);
229 | }
230 |
231 | // ----------------------------------------------------------------------------
232 | // Get the computed style for and element
233 | // ----------------------------------------------------------------------------
234 | function getStyle(oElm, strCssRule){
235 | var strValue = "";
236 | if(document.defaultView && document.defaultView.getComputedStyle){
237 | strValue = document.defaultView.getComputedStyle(oElm, "").getPropertyValue(strCssRule);
238 | }
239 | else if(oElm.currentStyle){
240 | strCssRule = strCssRule.replace(/\-(\w)/g, function (strMatch, p1){
241 | return p1.toUpperCase();
242 | });
243 | strValue = oElm.currentStyle[strCssRule];
244 | }
245 | return strValue;
246 | }
247 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # PCAPOptikon
2 | PCAPOptikon is a project that will provide a web GUI and some REST APIs to analyze arbitrary PCAP files with Suricata IDS.
3 |
4 | PCAPOptikon uses Django 1.8 and TastyPie.
5 |
6 | ## Docker image
7 | Docker is surely the quickest way to get started with PCAPOptikon. You can download it by running:
8 |
9 | $ sudo docker pull certego/pcapoptikon
10 |
11 | Now, I would suggest you to create a _data-only_ docker container to grant the persistence of MySQL data (`certego/pcapoptikon` exposes the volume `/var/lib/mysql`):
12 |
13 | $ sudo docker create --name pcapoptikon_data certego/pcapoptikon
14 |
15 | Now, a couple other directories that you may want to create locally on your host are:
16 |
17 | $ mkdir -p /var/log/pcapoptikon
18 | $ mkdir -p /var/tmp/pcapoptikon
19 |
20 | You can then run your docker container this way:
21 |
22 | $ sudo docker run -d --name=pcapoptikon --volumes-from=pcapoptikon_data -v=/var/log/pcapoptikon:/var/log -v=/var/tmp/pcapoptikon:/var/tmp -p=8000:8000 certego/pcapoptikon
23 |
24 | This command will create a new daemonized docker container, called `pcapoptikon`, mounting `/var/lib/mysql` from `pcapoptikon_data` and mounting `/var/log` and `/var/tmp` from the folders you just created on the host. It will also expose the container's port 8000 on localhost, so that you can simply point your browser to: http://localhost:8000/
25 |
26 | Default username and password are `admin:admin`. You will find some useful info on your host's `/var/log/pcapoptikon/pcapoptikon_startup.log` and in the other log files in the same folder.
27 |
28 | Should you own a valid ETPro oinkcode, you can supply it to the startup script that way:
29 |
30 | $ sudo docker run -d --name=pcapoptikon --volumes-from=pcapoptikon_data -v=/var/log/pcapoptikon:/var/log -v=/var/tmp/pcapoptikon:/var/tmp -p=8000:8000 certego/pcapoptikon /opt/pcapoptikon/start.sh
31 |
32 | Please note that, in this last case, you have to specify the docker instance's entry point `/opt/pcapoptikon/start.sh` yourself.
33 |
34 | ### Working with local.rules
35 | PCAPOptikon can be very useful when testing your own rules. You can do so by modifying the local.rules file. In this case, I suggest that you mount the whole rules folder as a volume on your local disk, so that you can easily modify them with your favourite editor. As an example:
36 |
37 | $ docker run -d --name=pcapoptikon --volumes-from=pcapoptikon_data -v=/var/log/pcapoptikon:/var/log -v=/var/tmp/pcapoptikon:/var/tmp -v=/var/tmp/suricata/rules:/etc/suricata/rules -p=8000:8000 certego/pcapoptikon
38 |
39 | This would mount PCAPOptikon's rules dir on your local `/var/tmp/suricata/rules` dir (please make sure it exists).
40 |
41 | To reload the newly modified rules, you can simply restart the whole docker container, but this will also run oinkmaster and download the whole ruleset from scratch. A quicker way is to use the included `reload.sh` script, that will manage all the necessary daemons for you:
42 |
43 | $ docker exec -ti pcapoptikon /opt/pcapoptikon/reload.sh
44 |
45 | This script has its own log file inside the container: `/var/log/pcapoptikon_reload.log`.
46 |
47 | ## Manual Install
48 |
49 | ### System-wide requirements
50 | Please make sure the following packages are installed:
51 |
52 | $ apt-get install mysql-server mysql-common mysql-client libmysqlclient-dev python-dev
53 |
54 | PCAPOptikon needs a Suricata instance running on the same host as the rest of the program. Installing it is pretty simple:
55 |
56 | $ sudo apt-get install software-properties-common python-software-properties
57 | $ sudo add-apt-repository -y ppa:oisf/suricata-stable
58 | $ sudo apt-get update
59 | $ sudo apt-get install suricata
60 |
61 | PCAPOptikon expects to find `classification.config` and `reference` under the folder `/etc/suricata/rules/` instead than just `/etc/suricata/` (which is the default), so please make sure that your `/etc/suricata/suricata.yaml` contains the following:
62 |
63 | classification-file: /etc/suricata/rules/classification.config
64 | reference-file: /etc/suricata/rules/reference.config
65 |
66 | It is also recommended that you install `oinkmaster` (or `pulledpork`) and configure it as appropriate (rule url, oinkcode, etc).
67 |
68 | You may also want to enable the following option in `/etc/suricata/suricata.yaml`:
69 |
70 | - rule-reload: true
71 |
72 | Doing so will let Suricata reload the rules whenever you send the process a `SIGUSR2` signal, without having to restart it. So, for example, you can run the following:
73 |
74 | $ oinkmaster -C /etc/oinkmaster.conf -o /etc/suricata/rules && killall -SIGUSR2 suricata
75 |
76 | If you're using the `./start.sh` script which comes with PCAPOptikon, it will do that for you.
77 |
78 | ### Python requirements
79 | First of all, this will clone PCAPOptikon in your current working directory:
80 |
81 | $ git clone https://github.com/certego/pcapoptikon.git
82 |
83 | **Please consider using VirtualEnv, especially if you already have other projects running on Django versions other than 1.8**. Installing VirtualEnv is extremely easy:
84 |
85 | $ sudo pip install virtualenv
86 |
87 | Actually, you only need sudo if you're installing `virtualenv` globally (which I suggest you to do). Now, `cd` to PCAPOptikon's root directory to create and activate your virtual environment:
88 |
89 | $ cd pcapoptikon
90 | $ virtualenv venv
91 | $ source venv/bin/activate
92 |
93 | That's all. The first command will create a folder named `venv`, with a copy of the Python executable, pip and some other tools; the second command will activate the virtual environment for you. From now on, every time you run `pip install`, the requested modules will be installed locally, without touching your global Python environment.
94 |
95 | Now make sure that the virtual environment is still active and then install the requirements by running:
96 |
97 | $ pip install -r requirements.txt
98 |
99 | Now, use pip to copy the `suricatasc` module from your system-wide python install:
100 |
101 | $ pip install --no-index --find-links=/usr/lib/pymodules/python2.7/ suricatasc
102 |
103 | Now you're ready to install PCAPOptikon itself. First, please create a new empty MySQL database and populate it:
104 |
105 | $ mysqladmin create pcapoptikon
106 | $ python manage.py migrate
107 |
108 | You are now ready to create a new user by running:
109 |
110 | $ python manage.py createsuperuser
111 |
112 | ## Running PCAPOptikon
113 | Launch the daemon with the following command (from PCAPOptikon's root directory):
114 |
115 | $ python manage.py run_daemon
116 |
117 | Now, you can run the web GUI with the following:
118 |
119 | $ python manage.py runserver
120 |
121 | By default, this will run the server on 127.0.0.1:8000 (you will only be able to reach it from localhost). If you wish to reach it from the local network, simply run:
122 |
123 | $ python manage.py runserver 0.0.0.0:8000
124 |
125 | or whatever other port you want.
126 |
127 | ## Using PCAPOptikon
128 |
129 | ### The GUI
130 | Simply point your browser to http://127.0.0.1:8000/ (or whatever ip/port you chose) and enjoy a simple web GUI that lets you submit new tasks and show their results.
131 |
132 | ### The Admin GUI
133 | PCAPOptikon includes a standard Django admin GUI that will help you manage your tasks (you can delete or modify them from there): http://127.0.0.1:8000/admin/
134 |
135 | ### The APIs
136 | PCAPOptikon also includes a full REST API made with `django-tastypie`. To access it programatically, it's recommended that you use an API key. You can create one via the Admin GUI (see above).
137 |
138 | The API endpoint can be found at http://127.0.0.1:8000/api/v1/?format=json
139 |
140 | To list all the pending tasks, just visit: http://127.0.0.1:8000/api/v1/task/?format=json
141 |
142 | To view the status of task #1: http://127.0.0.1:8000/api/v1/task/1/?format=json
143 |
144 | Making a POST request to http://127.0.0.1:8000/api/v1/task/ will create a new task for you. Please note that the PCAP file you're sending will need to be encoded with base64. An example Python script making a POST request to create a new task is the following:
145 |
146 | import base64
147 | import json
148 | import os
149 | import requests
150 |
151 |
152 | api_url = "http://127.0.0.1:8000/api/v1/"
153 | api_user = ""
154 | api_key = ""
155 | pcap_file = "/path/to/dump.pcap"
156 |
157 | headers = {
158 | 'Authorization': 'ApiKey {}:{}'.format(api_user, api_key),
159 | 'Content-Type': 'application/json'
160 | }
161 |
162 | with open(pcap_file, 'rb') as i:
163 | payload = {
164 | 'pcap_file': {
165 | "name": os.path.basename(self.pcap_path),
166 | "file": base64.b64encode(i.read()),
167 | "content_type": "application/vnd.tcpdump.pcap",
168 | }
169 | }
170 |
171 | response = requests.post(
172 | os.path.join(api_url, 'task/'),
173 | data=json.dumps(payload),
174 | headers=headers
175 | )
176 |
177 | if response.status_code == 201:
178 | retrieve_url = response.headers['Location']
179 | log.debug("Will need to poll URL: {}".format(retrieve_url))
180 |
181 | # Now you can start polling the address specified by retrieve_url
182 | # to retrieve the results, which will be available in a few seconds.
183 | else:
184 | # Something went wrong
185 | raise Exception("Got status code: {}".format(response.status_code))
186 |
--------------------------------------------------------------------------------
/static/admin/js/SelectFilter2.js:
--------------------------------------------------------------------------------
1 | /*
2 | SelectFilter2 - Turns a multiple-select box into a filter interface.
3 |
4 | Requires core.js, SelectBox.js and addevent.js.
5 | */
6 | (function($) {
7 | function findForm(node) {
8 | // returns the node of the form containing the given node
9 | if (node.tagName.toLowerCase() != 'form') {
10 | return findForm(node.parentNode);
11 | }
12 | return node;
13 | }
14 |
15 | window.SelectFilter = {
16 | init: function(field_id, field_name, is_stacked, admin_static_prefix) {
17 | if (field_id.match(/__prefix__/)){
18 | // Don't initialize on empty forms.
19 | return;
20 | }
21 | var from_box = document.getElementById(field_id);
22 | from_box.id += '_from'; // change its ID
23 | from_box.className = 'filtered';
24 |
25 | var ps = from_box.parentNode.getElementsByTagName('p');
26 | for (var i=0; i, because it just gets in the way.
29 | from_box.parentNode.removeChild(ps[i]);
30 | } else if (ps[i].className.indexOf("help") != -1) {
31 | // Move help text up to the top so it isn't below the select
32 | // boxes or wrapped off on the side to the right of the add
33 | // button:
34 | from_box.parentNode.insertBefore(ps[i], from_box.parentNode.firstChild);
35 | }
36 | }
37 |
38 | // or
39 | var selector_div = quickElement('div', from_box.parentNode);
40 | selector_div.className = is_stacked ? 'selector stacked' : 'selector';
41 |
42 | //
43 | var selector_available = quickElement('div', selector_div);
44 | selector_available.className = 'selector-available';
45 | var title_available = quickElement('h2', selector_available, interpolate(gettext('Available %s') + ' ', [field_name]));
46 | quickElement('img', title_available, '', 'src', admin_static_prefix + 'img/icon-unknown.gif', 'width', '10', 'height', '10', 'class', 'help help-tooltip', 'title', interpolate(gettext('This is the list of available %s. You may choose some by selecting them in the box below and then clicking the "Choose" arrow between the two boxes.'), [field_name]));
47 |
48 | var filter_p = quickElement('p', selector_available, '', 'id', field_id + '_filter');
49 | filter_p.className = 'selector-filter';
50 |
51 | var search_filter_label = quickElement('label', filter_p, '', 'for', field_id + "_input");
52 |
53 | var search_selector_img = quickElement('img', search_filter_label, '', 'src', admin_static_prefix + 'img/selector-search.gif', 'class', 'help-tooltip', 'alt', '', 'title', interpolate(gettext("Type into this box to filter down the list of available %s."), [field_name]));
54 |
55 | filter_p.appendChild(document.createTextNode(' '));
56 |
57 | var filter_input = quickElement('input', filter_p, '', 'type', 'text', 'placeholder', gettext("Filter"));
58 | filter_input.id = field_id + '_input';
59 |
60 | selector_available.appendChild(from_box);
61 | var choose_all = quickElement('a', selector_available, gettext('Choose all'), 'title', interpolate(gettext('Click to choose all %s at once.'), [field_name]), 'href', 'javascript: (function(){ SelectBox.move_all("' + field_id + '_from", "' + field_id + '_to"); SelectFilter.refresh_icons("' + field_id + '");})()', 'id', field_id + '_add_all_link');
62 | choose_all.className = 'selector-chooseall';
63 |
64 | //
65 | var selector_chooser = quickElement('ul', selector_div);
66 | selector_chooser.className = 'selector-chooser';
67 | var add_link = quickElement('a', quickElement('li', selector_chooser), gettext('Choose'), 'title', gettext('Choose'), 'href', 'javascript: (function(){ SelectBox.move("' + field_id + '_from","' + field_id + '_to"); SelectFilter.refresh_icons("' + field_id + '");})()', 'id', field_id + '_add_link');
68 | add_link.className = 'selector-add';
69 | var remove_link = quickElement('a', quickElement('li', selector_chooser), gettext('Remove'), 'title', gettext('Remove'), 'href', 'javascript: (function(){ SelectBox.move("' + field_id + '_to","' + field_id + '_from"); SelectFilter.refresh_icons("' + field_id + '");})()', 'id', field_id + '_remove_link');
70 | remove_link.className = 'selector-remove';
71 |
72 | //
73 | var selector_chosen = quickElement('div', selector_div);
74 | selector_chosen.className = 'selector-chosen';
75 | var title_chosen = quickElement('h2', selector_chosen, interpolate(gettext('Chosen %s') + ' ', [field_name]));
76 | quickElement('img', title_chosen, '', 'src', admin_static_prefix + 'img/icon-unknown.gif', 'width', '10', 'height', '10', 'class', 'help help-tooltip', 'title', interpolate(gettext('This is the list of chosen %s. You may remove some by selecting them in the box below and then clicking the "Remove" arrow between the two boxes.'), [field_name]));
77 |
78 | var to_box = quickElement('select', selector_chosen, '', 'id', field_id + '_to', 'multiple', 'multiple', 'size', from_box.size, 'name', from_box.getAttribute('name'));
79 | to_box.className = 'filtered';
80 | var clear_all = quickElement('a', selector_chosen, gettext('Remove all'), 'title', interpolate(gettext('Click to remove all chosen %s at once.'), [field_name]), 'href', 'javascript: (function() { SelectBox.move_all("' + field_id + '_to", "' + field_id + '_from"); SelectFilter.refresh_icons("' + field_id + '");})()', 'id', field_id + '_remove_all_link');
81 | clear_all.className = 'selector-clearall';
82 |
83 | from_box.setAttribute('name', from_box.getAttribute('name') + '_old');
84 |
85 | // Set up the JavaScript event handlers for the select box filter interface
86 | addEvent(filter_input, 'keypress', function(e) { SelectFilter.filter_key_press(e, field_id); });
87 | addEvent(filter_input, 'keyup', function(e) { SelectFilter.filter_key_up(e, field_id); });
88 | addEvent(filter_input, 'keydown', function(e) { SelectFilter.filter_key_down(e, field_id); });
89 | addEvent(from_box, 'change', function(e) { SelectFilter.refresh_icons(field_id) });
90 | addEvent(to_box, 'change', function(e) { SelectFilter.refresh_icons(field_id) });
91 | addEvent(from_box, 'dblclick', function() { SelectBox.move(field_id + '_from', field_id + '_to'); SelectFilter.refresh_icons(field_id); });
92 | addEvent(to_box, 'dblclick', function() { SelectBox.move(field_id + '_to', field_id + '_from'); SelectFilter.refresh_icons(field_id); });
93 | addEvent(findForm(from_box), 'submit', function() { SelectBox.select_all(field_id + '_to'); });
94 | SelectBox.init(field_id + '_from');
95 | SelectBox.init(field_id + '_to');
96 | // Move selected from_box options to to_box
97 | SelectBox.move(field_id + '_from', field_id + '_to');
98 |
99 | if (!is_stacked) {
100 | // In horizontal mode, give the same height to the two boxes.
101 | var j_from_box = $(from_box);
102 | var j_to_box = $(to_box);
103 | var resize_filters = function() { j_to_box.height($(filter_p).outerHeight() + j_from_box.outerHeight()); }
104 | if (j_from_box.outerHeight() > 0) {
105 | resize_filters(); // This fieldset is already open. Resize now.
106 | } else {
107 | // This fieldset is probably collapsed. Wait for its 'show' event.
108 | j_to_box.closest('fieldset').one('show.fieldset', resize_filters);
109 | }
110 | }
111 |
112 | // Initial icon refresh
113 | SelectFilter.refresh_icons(field_id);
114 | },
115 | refresh_icons: function(field_id) {
116 | var from = $('#' + field_id + '_from');
117 | var to = $('#' + field_id + '_to');
118 | var is_from_selected = from.find('option:selected').length > 0;
119 | var is_to_selected = to.find('option:selected').length > 0;
120 | // Active if at least one item is selected
121 | $('#' + field_id + '_add_link').toggleClass('active', is_from_selected);
122 | $('#' + field_id + '_remove_link').toggleClass('active', is_to_selected);
123 | // Active if the corresponding box isn't empty
124 | $('#' + field_id + '_add_all_link').toggleClass('active', from.find('option').length > 0);
125 | $('#' + field_id + '_remove_all_link').toggleClass('active', to.find('option').length > 0);
126 | },
127 | filter_key_press: function(event, field_id) {
128 | var from = document.getElementById(field_id + '_from');
129 | // don't submit form if user pressed Enter
130 | if ((event.which && event.which == 13) || (event.keyCode && event.keyCode == 13)) {
131 | from.selectedIndex = 0;
132 | SelectBox.move(field_id + '_from', field_id + '_to');
133 | from.selectedIndex = 0;
134 | event.preventDefault()
135 | return false;
136 | }
137 | },
138 | filter_key_up: function(event, field_id) {
139 | var from = document.getElementById(field_id + '_from');
140 | var temp = from.selectedIndex;
141 | SelectBox.filter(field_id + '_from', document.getElementById(field_id + '_input').value);
142 | from.selectedIndex = temp;
143 | return true;
144 | },
145 | filter_key_down: function(event, field_id) {
146 | var from = document.getElementById(field_id + '_from');
147 | // right arrow -- move across
148 | if ((event.which && event.which == 39) || (event.keyCode && event.keyCode == 39)) {
149 | var old_index = from.selectedIndex;
150 | SelectBox.move(field_id + '_from', field_id + '_to');
151 | from.selectedIndex = (old_index == from.length) ? from.length - 1 : old_index;
152 | return false;
153 | }
154 | // down arrow -- wrap around
155 | if ((event.which && event.which == 40) || (event.keyCode && event.keyCode == 40)) {
156 | from.selectedIndex = (from.length == from.selectedIndex + 1) ? 0 : from.selectedIndex + 1;
157 | }
158 | // up arrow -- wrap around
159 | if ((event.which && event.which == 38) || (event.keyCode && event.keyCode == 38)) {
160 | from.selectedIndex = (from.selectedIndex == 0) ? from.length - 1 : from.selectedIndex - 1;
161 | }
162 | return true;
163 | }
164 | }
165 |
166 | })(django.jQuery);
167 |
--------------------------------------------------------------------------------
/static/js/bootstrap-select.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * bootstrap-select v1.0
3 | * http://silviomoreto.github.io/bootstrap-select/
4 | *
5 | * Copyright 2013 bootstrap-select
6 | * Licensed under the MIT license
7 | */
8 | !function(b){var a=function(d,c,f){if(f){f.stopPropagation();f.preventDefault()}this.$element=b(d);this.$newElement=null;this.button=null;this.$menu=null;this.options=b.extend({},b.fn.selectpicker.defaults,this.$element.data(),typeof c=="object"&&c);if(this.options.title==null){this.options.title=this.$element.attr("title")}this.val=a.prototype.val;this.render=a.prototype.render;this.refresh=a.prototype.refresh;this.setStyle=a.prototype.setStyle;this.selectAll=a.prototype.selectAll;this.deselectAll=a.prototype.deselectAll;this.init()};a.prototype={constructor:a,init:function(c){this.$element.hide();this.multiple=this.$element.prop("multiple");var f=this.$element.attr("id");this.$newElement=this.createView();this.$element.after(this.$newElement);this.$menu=this.$newElement.find("> .dropdown-menu");this.button=this.$newElement.find("> button");if(f!==undefined){var d=this;this.button.attr("data-id",f);b('label[for="'+f+'"]').click(function(){d.button.focus()})}if(this.multiple){this.$newElement.addClass("show-tick")}this.checkDisabled();this.checkTabIndex();this.clickListener();this.render();this.liHeight();this.setWidth();this.setStyle();if(this.options.container){this.selectPosition()}},createDropdown:function(){var c="";return b(c)},createView:function(){var c=this.createDropdown();var d=this.createLi();c.find("ul").append(d);return c},reloadLi:function(){this.destroyLi();var c=this.createLi();this.$newElement.find("ul").append(c)},destroyLi:function(){this.$newElement.find("li").remove()},createLi:function(){var e=this,d=[],c="";this.$element.find("option").each(function(h){var j=b(this);var g=j.attr("class")||"";var i=j.attr("style")||"";var n=j.data("content")?j.data("content"):j.html();var l=j.data("subtext")!==undefined?''+j.data("subtext")+"":"";var k=j.data("icon")!==undefined?' ':"";if(k!==""&&(j.is(":disabled")||j.parent().is(":disabled"))){k=""+k+""}if(!j.data("content")){n=k+''+n+l+""}if(e.options.hideDisabled&&(j.is(":disabled")||j.parent().is(":disabled"))){d.push('')}else{if(j.parent().is("optgroup")&&j.data("divider")!=true){if(j.index()==0){var m=j.parent().attr("label");var o=j.parent().data("subtext")!==undefined?''+j.parent().data("subtext")+"":"";var f=j.parent().data("icon")?' ':"";m=f+''+m+o+"";if(j[0].index!=0){d.push('- '+m+"
"+e.createA(n,"opt "+g,i))}else{d.push("- "+m+"
"+e.createA(n,"opt "+g,i))}}else{d.push(e.createA(n,"opt "+g,i))}}else{if(j.data("divider")==true){d.push('')}else{if(b(this).data("hidden")==true){d.push("")}else{d.push(e.createA(n,g,i))}}}}});b.each(d,function(f,g){c+="- "+g+"
"});if(!this.multiple&&this.$element.find("option:selected").length==0&&!e.options.title){this.$element.find("option").eq(0).prop("selected",true).attr("selected","selected")}return b(c)},createA:function(e,c,d){return''+e+''},render:function(){var g=this;this.$element.find("option").each(function(h){g.setDisabled(h,b(this).is(":disabled")||b(this).parent().is(":disabled"));g.setSelected(h,b(this).is(":selected"))});var f=this.$element.find("option:selected").map(function(h,k){var l=b(this);var j=l.data("icon")&&g.options.showIcon?' ':"";var i;if(g.options.showSubtext&&l.attr("data-subtext")&&!g.multiple){i=' '+l.data("subtext")+""}else{i=""}if(l.data("content")&&g.options.showContent){return l.data("content")}else{if(l.attr("title")!=undefined){return l.attr("title")}else{return j+l.html()+i}}}).toArray();var e=!this.multiple?f[0]:f.join(", ");if(g.multiple&&g.options.selectedTextFormat.indexOf("count")>-1){var c=g.options.selectedTextFormat.split(">");var d=this.options.hideDisabled?":not([disabled])":"";if((c.length>1&&f.length>c[1])||(c.length==1&&f.length>=2)){e=g.options.countSelectedText.replace("{0}",f.length).replace("{1}",this.$element.find('option:not([data-divider="true"]):not([data-hidden="true"])'+d).length)}}if(!e){e=g.options.title!=undefined?g.options.title:g.options.noneSelectedText}g.$newElement.find(".filter-option").html(e)},setStyle:function(e,d){if(this.$element.attr("class")){this.$newElement.addClass(this.$element.attr("class").replace(/selectpicker|mobile-device/gi,""))}var c=e?e:this.options.style;if(d=="add"){this.button.addClass(c)}else{this.button.removeClass(this.options.style);this.button.addClass(c)}},liHeight:function(){var d=this.$newElement.clone();d.appendTo("body");var c=d.addClass("open").find(".dropdown-menu li > a").outerHeight();d.remove();this.$newElement.data("liHeight",c)},setSize:function(){var i=this,e=this.$newElement.find("> .dropdown-menu"),h=e.find(".inner"),k=h.find("li > a"),j=this.$newElement.outerHeight(),n=this.$newElement.data("liHeight"),g=e.find("li .divider").outerHeight(true),c=parseInt(e.css("padding-top"))+parseInt(e.css("padding-bottom"))+parseInt(e.css("border-top-width"))+parseInt(e.css("border-bottom-width")),d=this.options.hideDisabled?":not(.disabled)":"",f;if(this.options.size=="auto"){var o=function(){var r=i.$newElement.offset().top;var p=r-b(window).scrollTop();var u=b(window).height();var q=c+parseInt(e.css("margin-top"))+parseInt(e.css("margin-bottom"))+2;var t=u-p-j-q;var s;f=t;if(i.$newElement.hasClass("dropup")){f=p-q}if((e.find("li").length+e.find("dt").length)>3){s=n*3+q-2}else{s=0}e.css({"max-height":f+"px",overflow:"hidden","min-height":s+"px"});h.css({"max-height":(f-c)+"px","overflow-y":"auto"})};o();b(window).resize(o);b(window).scroll(o)}else{if(this.options.size&&this.options.size!="auto"&&e.find("li"+d).length>this.options.size){var m=e.find("li"+d+" > *").filter(":not(.div-contain)").slice(0,this.options.size).last().parent().index();var l=e.find("li").slice(0,m+1).find(".div-contain").length;f=n*this.options.size+l*g+c;e.css({"max-height":f+"px",overflow:"hidden"});h.css({"max-height":(f-c)+"px","overflow-y":"auto"})}}},setWidth:function(){var d=this.$newElement.find("> .dropdown-menu");if(this.options.width=="auto"){d.css("min-width","0");var c=d.css("width");this.$newElement.css("width",c)}else{if(this.options.width){this.$newElement.css("width",this.options.width)}}},selectPosition:function(){var h=this,d="",e=b(d),g,f,c=function(i){e.addClass(i.attr("class").replace(/open/gi,""));g=i.offset();f=i[0].offsetHeight;e.css({top:g.top+f,left:g.left,width:i[0].offsetWidth,position:"absolute"})};this.$newElement.on("click",function(){c(b(this));e.toggleClass("open");e.append(h.$menu);e.appendTo(h.options.container);return false});b(window).resize(function(){c(h.$newElement)});b(window).scroll(function(){c(h.$newElement)});b("html").on("click",function(){e.removeClass("open")})},mobile:function(){this.$element.addClass("mobile-device").appendTo(this.$newElement);if(this.options.container){this.$menu.hide()}},refresh:function(){this.reloadLi();this.render();this.setWidth();this.setStyle();this.checkDisabled()},setSelected:function(c,d){this.$menu.find("li").eq(c).toggleClass("selected",d)},setDisabled:function(c,d){if(d){this.$menu.find("li").eq(c).addClass("disabled").find("a").attr("href","#").attr("tabindex",-1)}else{this.$menu.find("li").eq(c).removeClass("disabled").find("a").removeAttr("href").attr("tabindex",0)}},isDisabled:function(){return this.$element.is(":disabled")||this.$element.attr("readonly")},checkDisabled:function(){var c=this;if(this.isDisabled()){this.button.addClass("disabled");this.button.attr("tabindex","-1")}else{if(!this.isDisabled()&&this.button.hasClass("disabled")){this.button.removeClass("disabled");this.button.removeAttr("tabindex")}}this.button.click(function(){if(c.isDisabled()){return false}})},checkTabIndex:function(){if(this.$element.is("[tabindex]")){var c=this.$element.attr("tabindex");this.button.attr("tabindex",c)}},clickListener:function(){var c=this;b("body").on("touchstart.dropdown",".dropdown-menu",function(d){d.stopPropagation()});this.$newElement.on("click",function(){c.setSize()});this.$menu.on("click","li a",function(j){var d=b(this).parent().index(),i=b(this).parent(),h=c.$element.val();if(c.multiple){j.stopPropagation()}j.preventDefault();if(c.$element.not(":disabled")&&!b(this).parent().hasClass("disabled")){if(!c.multiple){c.$element.find("option").prop("selected",false);c.$element.find("option").eq(d).prop("selected",true)}else{var g=c.$element.find("option").eq(d);var f=g.prop("selected");g.prop("selected",!f)}c.button.focus();if(h!=c.$element.val()){c.$element.change()}}});this.$menu.on("click","li.disabled a, li dt, li .div-contain",function(d){d.preventDefault();d.stopPropagation();c.button.focus()});this.$element.on("change",function(d){c.render()})},val:function(c){if(c!=undefined){this.$element.val(c);this.$element.change();return this.$element}else{return this.$element.val()}},selectAll:function(){this.$element.find("option").prop("selected",true).attr("selected","selected");this.render()},deselectAll:function(){this.$element.find("option").prop("selected",false).removeAttr("selected");this.render()},keydown:function(n){var o,m,h,l,j,i,p,d,g;o=b(this);h=o.parent();m=b("[role=menu] li:not(.divider):visible a",h);if(!m.length){return}if(/(38|40)/.test(n.keyCode)){l=m.index(m.filter(":focus"));i=m.parent(":not(.disabled)").first().index();p=m.parent(":not(.disabled)").last().index();j=m.eq(l).parent().nextAll(":not(.disabled)").eq(0).index();d=m.eq(l).parent().prevAll(":not(.disabled)").eq(0).index();g=m.eq(j).parent().prevAll(":not(.disabled)").eq(0).index();if(n.keyCode==38){if(l!=g&&l>d){l=d}if(lp){l=p}}m.eq(l).focus()}else{var f={48:"0",49:"1",50:"2",51:"3",52:"4",53:"5",54:"6",55:"7",56:"8",57:"9",59:";",65:"a",66:"b",67:"c",68:"d",69:"e",70:"f",71:"g",72:"h",73:"i",74:"j",75:"k",76:"l",77:"m",78:"n",79:"o",80:"p",81:"q",82:"r",83:"s",84:"t",85:"u",86:"v",87:"w",88:"x",89:"y",90:"z",96:"0",97:"1",98:"2",99:"3",100:"4",101:"5",102:"6",103:"7",104:"8",105:"9"};var c=[];m.each(function(){if(b(this).parent().is(":not(.disabled)")){if(b.trim(b(this).text().toLowerCase()).substring(0,1)==f[n.keyCode]){c.push(b(this).parent().index())}}});var k=b(document).data("keycount");k++;b(document).data("keycount",k);var q=b.trim(b(":focus").text().toLowerCase()).substring(0,1);if(q!=f[n.keyCode]){k=1;b(document).data("keycount",k)}else{if(k>=c.length){b(document).data("keycount",0)}}m.eq(c[k-1]).focus()}if(/(13)/.test(n.keyCode)){b(":focus").click();h.addClass("open");b(document).data("keycount",0)}},hide:function(){this.$newElement.hide()},show:function(){this.$newElement.show()},destroy:function(){this.$newElement.remove();this.$element.remove()}};b.fn.selectpicker=function(e,f){var c=arguments;var g;var d=this.each(function(){if(b(this).is("select")){var m=b(this),l=m.data("selectpicker"),h=typeof e=="object"&&e;if(!l){m.data("selectpicker",(l=new a(this,h,f)))}else{if(h){for(var j in h){l.options[j]=h[j]}}}if(typeof e=="string"){var k=e;if(l[k] instanceof Function){[].shift.apply(c);g=l[k].apply(l,c)}else{g=l.options[k]}}}});if(g!=undefined){return g}else{return d}};b.fn.selectpicker.defaults={style:null,size:"auto",title:null,selectedTextFormat:"values",noneSelectedText:"Nothing selected",countSelectedText:"{0} of {1} selected",width:null,container:false,hideDisabled:false,showSubtext:false,showIcon:true,showContent:true};b(document).data("keycount",0).on("keydown","[data-toggle=dropdown], [role=menu]",a.prototype.keydown)}(window.jQuery);
9 |
--------------------------------------------------------------------------------