mirror of https://github.com/CIRCL/AIL-framework
chg: [UI + item submit] remove browse paste from UI + fix pasteSubmit tagging
parent
51eb951a47
commit
f4cdddbc7f
|
@ -96,25 +96,48 @@ def remove_submit_uuid(uuid):
|
||||||
r_serv_db.srem('submitted:uuid', uuid)
|
r_serv_db.srem('submitted:uuid', uuid)
|
||||||
print('{} all file submitted'.format(uuid))
|
print('{} all file submitted'.format(uuid))
|
||||||
|
|
||||||
|
def add_item_tag(tag, item_path):
|
||||||
|
item_date = int(get_item_date(item_path))
|
||||||
|
|
||||||
|
#add tag
|
||||||
|
r_serv_metadata.sadd('tag:{}'.format(item_path), tag)
|
||||||
|
r_serv_tags.sadd('{}:{}'.format(tag, item_date), item_path)
|
||||||
|
|
||||||
|
r_serv_tags.hincrby('daily_tags:{}'.format(item_date), tag, 1)
|
||||||
|
|
||||||
|
tag_first_seen = r_serv_tags.hget('tag_metadata:{}'.format(tag), 'last_seen')
|
||||||
|
if tag_first_seen is None:
|
||||||
|
tag_first_seen = 99999999
|
||||||
|
else:
|
||||||
|
tag_first_seen = int(tag_first_seen)
|
||||||
|
tag_last_seen = r_serv_tags.hget('tag_metadata:{}'.format(tag), 'last_seen')
|
||||||
|
if tag_last_seen is None:
|
||||||
|
tag_last_seen = 0
|
||||||
|
else:
|
||||||
|
tag_last_seen = int(tag_last_seen)
|
||||||
|
|
||||||
|
#add new tag in list of all used tags
|
||||||
|
r_serv_tags.sadd('list_tags', tag)
|
||||||
|
|
||||||
|
# update fisrt_seen/last_seen
|
||||||
|
if item_date < tag_first_seen:
|
||||||
|
r_serv_tags.hset('tag_metadata:{}'.format(tag), 'first_seen', item_date)
|
||||||
|
|
||||||
|
# update metadata last_seen
|
||||||
|
if item_date > tag_last_seen:
|
||||||
|
r_serv_tags.hset('tag_metadata:{}'.format(tag), 'last_seen', item_date)
|
||||||
|
|
||||||
def add_tags(tags, tagsgalaxies, path):
|
def add_tags(tags, tagsgalaxies, path):
|
||||||
list_tag = tags.split(',')
|
list_tag = tags.split(',')
|
||||||
list_tag_galaxies = tagsgalaxies.split(',')
|
list_tag_galaxies = tagsgalaxies.split(',')
|
||||||
|
|
||||||
if list_tag != ['']:
|
if list_tag != ['']:
|
||||||
for tag in list_tag:
|
for tag in list_tag:
|
||||||
#add tag
|
add_item_tag(tag, path)
|
||||||
r_serv_metadata.sadd('tag:'+path, tag)
|
|
||||||
r_serv_tags.sadd(tag, path)
|
|
||||||
#add new tag in list of all used tags
|
|
||||||
r_serv_tags.sadd('list_tags', tag)
|
|
||||||
|
|
||||||
if list_tag_galaxies != ['']:
|
if list_tag_galaxies != ['']:
|
||||||
for tag in list_tag_galaxies:
|
for tag in list_tag_galaxies:
|
||||||
#add tag
|
add_item_tag(tag, path)
|
||||||
r_serv_metadata.sadd('tag:'+path, tag)
|
|
||||||
r_serv_tags.sadd(tag, path)
|
|
||||||
#add new tag in list of all used tags
|
|
||||||
r_serv_tags.sadd('list_tags', tag)
|
|
||||||
|
|
||||||
def verify_extention_filename(filename):
|
def verify_extention_filename(filename):
|
||||||
if not '.' in filename:
|
if not '.' in filename:
|
||||||
|
|
|
@ -1,181 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# -*-coding:UTF-8 -*
|
|
||||||
|
|
||||||
'''
|
|
||||||
Flask functions and routes for the trending modules page
|
|
||||||
'''
|
|
||||||
import redis
|
|
||||||
import json
|
|
||||||
import flask
|
|
||||||
import os
|
|
||||||
from datetime import datetime
|
|
||||||
from flask import Flask, render_template, jsonify, request, Blueprint
|
|
||||||
|
|
||||||
import Paste
|
|
||||||
|
|
||||||
# ============ VARIABLES ============
|
|
||||||
import Flask_config
|
|
||||||
|
|
||||||
app = Flask_config.app
|
|
||||||
cfg = Flask_config.cfg
|
|
||||||
baseUrl = Flask_config.baseUrl
|
|
||||||
max_preview_char = Flask_config.max_preview_char
|
|
||||||
max_preview_modal = Flask_config.max_preview_modal
|
|
||||||
r_serv_metadata = Flask_config.r_serv_metadata
|
|
||||||
bootstrap_label = Flask_config.bootstrap_label
|
|
||||||
|
|
||||||
#init all lvlDB servers
|
|
||||||
curYear = datetime.now().year
|
|
||||||
int_year = int(curYear)
|
|
||||||
r_serv_db = {}
|
|
||||||
# port generated automatically depending on available levelDB date
|
|
||||||
yearList = []
|
|
||||||
|
|
||||||
for x in range(0, (int_year - 2018) + 1):
|
|
||||||
|
|
||||||
intYear = int_year - x
|
|
||||||
|
|
||||||
yearList.append([str(intYear), intYear, int(curYear) == intYear])
|
|
||||||
r_serv_db[intYear] = redis.StrictRedis(
|
|
||||||
host=cfg.get("ARDB_DB", "host"),
|
|
||||||
port=cfg.getint("ARDB_DB", "port"),
|
|
||||||
db=intYear,
|
|
||||||
decode_responses=True)
|
|
||||||
|
|
||||||
yearList.sort(reverse=True)
|
|
||||||
|
|
||||||
browsepastes = Blueprint('browsepastes', __name__, template_folder='templates')
|
|
||||||
|
|
||||||
# ============ FUNCTIONS ============
|
|
||||||
|
|
||||||
def getPastebyType(server, module_name):
|
|
||||||
all_path = []
|
|
||||||
for path in server.smembers('WARNING_'+module_name):
|
|
||||||
all_path.append(path)
|
|
||||||
|
|
||||||
return all_path
|
|
||||||
|
|
||||||
|
|
||||||
def event_stream_getImportantPasteByModule(module_name, year):
|
|
||||||
index = 0
|
|
||||||
all_pastes_list = getPastebyType(r_serv_db[year], module_name)
|
|
||||||
paste_tags = []
|
|
||||||
|
|
||||||
for path in all_pastes_list:
|
|
||||||
index += 1
|
|
||||||
paste = Paste.Paste(path)
|
|
||||||
content = paste.get_p_content()
|
|
||||||
content_range = max_preview_char if len(content)>max_preview_char else len(content)-1
|
|
||||||
curr_date = str(paste._get_p_date())
|
|
||||||
curr_date = curr_date[0:4]+'/'+curr_date[4:6]+'/'+curr_date[6:]
|
|
||||||
p_tags = r_serv_metadata.smembers('tag:'+path)
|
|
||||||
l_tags = []
|
|
||||||
for tag in p_tags:
|
|
||||||
complete_tag = tag.replace('"', '"')
|
|
||||||
tag = tag.split('=')
|
|
||||||
if len(tag) > 1:
|
|
||||||
if tag[1] != '':
|
|
||||||
tag = tag[1][1:-1]
|
|
||||||
# no value
|
|
||||||
else:
|
|
||||||
tag = tag[0][1:-1]
|
|
||||||
# use for custom tags
|
|
||||||
else:
|
|
||||||
tag = tag[0]
|
|
||||||
|
|
||||||
l_tags.append( (tag, complete_tag) )
|
|
||||||
|
|
||||||
data = {}
|
|
||||||
data["module"] = module_name
|
|
||||||
data["index"] = index
|
|
||||||
data["path"] = path
|
|
||||||
data["content"] = content[0:content_range]
|
|
||||||
data["linenum"] = paste.get_lines_info()[0]
|
|
||||||
data["date"] = curr_date
|
|
||||||
data["l_tags"] = l_tags
|
|
||||||
data["bootstrap_label"] = bootstrap_label
|
|
||||||
data["char_to_display"] = max_preview_modal
|
|
||||||
data["finished"] = True if index == len(all_pastes_list) else False
|
|
||||||
yield 'retry: 100000\ndata: %s\n\n' % json.dumps(data) #retry to avoid reconnection of the browser
|
|
||||||
|
|
||||||
# ============ ROUTES ============
|
|
||||||
|
|
||||||
@browsepastes.route("/browseImportantPaste/", methods=['GET'])
|
|
||||||
def browseImportantPaste():
|
|
||||||
module_name = request.args.get('moduleName')
|
|
||||||
return render_template("browse_important_paste.html", year_list=yearList, selected_year=curYear)
|
|
||||||
|
|
||||||
|
|
||||||
@browsepastes.route("/importantPasteByModule/", methods=['GET'])
|
|
||||||
def importantPasteByModule():
|
|
||||||
module_name = request.args.get('moduleName')
|
|
||||||
|
|
||||||
# # TODO: VERIFY YEAR VALIDITY
|
|
||||||
try:
|
|
||||||
currentSelectYear = int(request.args.get('year'))
|
|
||||||
except:
|
|
||||||
print('Invalid year input')
|
|
||||||
currentSelectYear = int(datetime.now().year)
|
|
||||||
|
|
||||||
all_content = []
|
|
||||||
paste_date = []
|
|
||||||
paste_linenum = []
|
|
||||||
all_path = []
|
|
||||||
paste_tags = []
|
|
||||||
allPastes = getPastebyType(r_serv_db[currentSelectYear], module_name)
|
|
||||||
|
|
||||||
for path in allPastes[0:10]:
|
|
||||||
all_path.append(path)
|
|
||||||
paste = Paste.Paste(path)
|
|
||||||
content = paste.get_p_content()
|
|
||||||
content_range = max_preview_char if len(content)>max_preview_char else len(content)-1
|
|
||||||
all_content.append(content[0:content_range].replace("\"", "\'").replace("\r", " ").replace("\n", " "))
|
|
||||||
curr_date = str(paste._get_p_date())
|
|
||||||
curr_date = curr_date[0:4]+'/'+curr_date[4:6]+'/'+curr_date[6:]
|
|
||||||
paste_date.append(curr_date)
|
|
||||||
paste_linenum.append(paste.get_lines_info()[0])
|
|
||||||
p_tags = r_serv_metadata.smembers('tag:'+path)
|
|
||||||
l_tags = []
|
|
||||||
for tag in p_tags:
|
|
||||||
complete_tag = tag
|
|
||||||
tag = tag.split('=')
|
|
||||||
if len(tag) > 1:
|
|
||||||
if tag[1] != '':
|
|
||||||
tag = tag[1][1:-1]
|
|
||||||
# no value
|
|
||||||
else:
|
|
||||||
tag = tag[0][1:-1]
|
|
||||||
# use for custom tags
|
|
||||||
else:
|
|
||||||
tag = tag[0]
|
|
||||||
|
|
||||||
l_tags.append( (tag, complete_tag) )
|
|
||||||
|
|
||||||
paste_tags.append(l_tags)
|
|
||||||
|
|
||||||
if len(allPastes) > 10:
|
|
||||||
finished = False
|
|
||||||
else:
|
|
||||||
finished = True
|
|
||||||
|
|
||||||
return render_template("important_paste_by_module.html",
|
|
||||||
moduleName=module_name,
|
|
||||||
year=currentSelectYear,
|
|
||||||
all_path=all_path,
|
|
||||||
content=all_content,
|
|
||||||
paste_date=paste_date,
|
|
||||||
paste_linenum=paste_linenum,
|
|
||||||
char_to_display=max_preview_modal,
|
|
||||||
paste_tags=paste_tags,
|
|
||||||
bootstrap_label=bootstrap_label,
|
|
||||||
finished=finished)
|
|
||||||
|
|
||||||
@browsepastes.route("/_getImportantPasteByModule", methods=['GET'])
|
|
||||||
def getImportantPasteByModule():
|
|
||||||
module_name = request.args.get('moduleName')
|
|
||||||
currentSelectYear = int(request.args.get('year'))
|
|
||||||
return flask.Response(event_stream_getImportantPasteByModule(module_name, currentSelectYear), mimetype="text/event-stream")
|
|
||||||
|
|
||||||
|
|
||||||
# ========= REGISTRATION =========
|
|
||||||
app.register_blueprint(browsepastes, url_prefix=baseUrl)
|
|
|
@ -1,190 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
|
|
||||||
<title>Browse Important Paste - AIL</title>
|
|
||||||
<link rel="icon" href="{{ url_for('static', filename='image/ail-icon.png') }}">
|
|
||||||
|
|
||||||
<!-- Core CSS -->
|
|
||||||
<link href="{{ url_for('static', filename='css/bootstrap.min.css') }}" rel="stylesheet">
|
|
||||||
<link href="{{ url_for('static', filename='font-awesome/css/font-awesome.css') }}" rel="stylesheet">
|
|
||||||
<link href="{{ url_for('static', filename='css/sb-admin-2.css') }}" rel="stylesheet">
|
|
||||||
<link href="{{ url_for('static', filename='css/dataTables.bootstrap.css') }}" rel="stylesheet" type="text/css" />
|
|
||||||
<script language="javascript" src="{{ url_for('static', filename='js/jquery.js')}}"></script>
|
|
||||||
<script src="{{ url_for('static', filename='js/bootstrap.min.js') }}"></script>
|
|
||||||
<script src="{{ url_for('static', filename='js/jquery.dataTables.min.js') }}"></script>
|
|
||||||
<script src="{{ url_for('static', filename='js/dataTables.bootstrap.js') }}"></script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.tooltip-inner {
|
|
||||||
text-align: left;
|
|
||||||
height: 200%;
|
|
||||||
width: 200%;
|
|
||||||
max-width: 500px;
|
|
||||||
max-height: 500px;
|
|
||||||
font-size: 13px;
|
|
||||||
}
|
|
||||||
xmp {
|
|
||||||
white-space:pre-wrap;
|
|
||||||
word-wrap:break-word;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
{% include 'navbar.html' %}
|
|
||||||
|
|
||||||
<!-- Modal -->
|
|
||||||
<div id="mymodal" class="modal fade" role="dialog">
|
|
||||||
<div class="modal-dialog modal-lg">
|
|
||||||
|
|
||||||
<!-- Modal content-->
|
|
||||||
<div id="mymodalcontent" class="modal-content">
|
|
||||||
<div id="mymodalbody" class="modal-body" max-width="850px">
|
|
||||||
<p>Loading paste information...</p>
|
|
||||||
<img id="loading-gif-modal" src="{{url_for('static', filename='image/loading.gif') }}" height="26" width="26" style="margin: 4px;">
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<a id="button_show_path" target="_blank" href=""><button type="button" class="btn btn-info">Show saved paste</button></a>
|
|
||||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div id="page-wrapper">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-lg-12">
|
|
||||||
<h1 class="page-header" data-page="page-browse" >Browse important pastes</h1>
|
|
||||||
</div>
|
|
||||||
<!-- /.col-lg-12 -->
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-12" style="margin-bottom: 0.2cm;">
|
|
||||||
<strong style="">Year: </strong>
|
|
||||||
<select class="form-control" id="index_year" style="display: inline-block; margin-bottom: 5px; width: 5%">
|
|
||||||
{% for yearElem in year_list %}
|
|
||||||
<option {% if yearElem[2] %} selected="selected" {% endif %} value="{{ yearElem[0] }}" >{{ yearElem[1] }}</option>
|
|
||||||
{% endfor %}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</br>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- /.row -->
|
|
||||||
<div class="row">
|
|
||||||
|
|
||||||
<!-- /.nav-tabs -->
|
|
||||||
<ul class="nav nav-tabs">
|
|
||||||
<li name='nav-pan' class="active"><a data-toggle="tab" href="#credential-tab" data-attribute-name="credential" data-panel="credential-panel">Credentials</a></li>
|
|
||||||
<li name='nav-pan'><a data-toggle="tab" href="#creditcard-tab" data-attribute-name="creditcard" data-panel="creditcard-panel">Credit cards</a></li>
|
|
||||||
<li name='nav-pan'><a data-toggle="tab" href="#sqlinjection-tab" data-attribute-name="sqlinjection" data-panel="sqlinjection-panel">SQL injections</a></li>
|
|
||||||
<li name='nav-pan'><a data-toggle="tab" href="#cve-tab" data-attribute-name="cve" data-panel="cve-panel">CVEs</a></li>
|
|
||||||
<li name='nav-pan'><a data-toggle="tab" href="#keys-tab" data-attribute-name="keys" data-panel="keys-panel">Keys</a></li>
|
|
||||||
<li name='nav-pan'><a data-toggle="tab" href="#apikey-tab" data-attribute-name="apikey" data-panel="apikey-panel">API Keys</a></li>
|
|
||||||
<li name='nav-pan'><a data-toggle="tab" href="#mail-tab" data-attribute-name="mail" data-panel="mail-panel">Mails</a></li>
|
|
||||||
<li name='nav-pan'><a data-toggle="tab" href="#phone-tab" data-attribute-name="phone" data-panel="phone-panel">Phones</a></li>
|
|
||||||
<li name='nav-pan'><a data-toggle="tab" href="#onion-tab" data-attribute-name="onion" data-panel="onion-panel">Onions</a></li>
|
|
||||||
<li name='nav-pan'><a data-toggle="tab" href="#bitcoin-tab" data-attribute-name="bitcoin" data-panel="bitcoin-panel">Bitcoin</a></li>
|
|
||||||
<li name='nav-pan'><a data-toggle="tab" href="#base64-tab" data-attribute-name="base64" data-panel="base64-panel">Base64</a></li>
|
|
||||||
</ul>
|
|
||||||
</br>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="tab-content">
|
|
||||||
<div class="col-lg-12 tab-pane fade in active" id="credential-tab" >
|
|
||||||
<img id="loading-gif-modal" src="{{url_for('static', filename='image/loading.gif') }}" style="margin: 4px;">
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-12 tab-pane fade" id="creditcard-tab">
|
|
||||||
<img id="loading-gif-modal" src="{{url_for('static', filename='image/loading.gif') }}" style="margin: 4px;">
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-12 tab-pane fade" id="sqlinjection-tab">
|
|
||||||
<img id="loading-gif-modal" src="{{url_for('static', filename='image/loading.gif') }}" style="margin: 4px;">
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-12 tab-pane fade" id="cve-tab">
|
|
||||||
<img id="loading-gif-modal" src="{{url_for('static', filename='image/loading.gif') }}" style="margin: 4px;">
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-12 tab-pane fade" id="keys-tab">
|
|
||||||
<img id="loading-gif-modal" src="{{url_for('static', filename='image/loading.gif') }}" style="margin: 4px;">
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-12 tab-pane fade" id="apikey-tab">
|
|
||||||
<img id="loading-gif-modal" src="{{url_for('static', filename='image/loading.gif') }}" style="margin: 4px;">
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-12 tab-pane fade" id="mail-tab">
|
|
||||||
<img id="loading-gif-modal" src="{{url_for('static', filename='image/loading.gif') }}" style="margin: 4px;">
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-12 tab-pane fade" id="phone-tab">
|
|
||||||
<img id="loading-gif-modal" src="{{url_for('static', filename='image/loading.gif') }}" style="margin: 4px;">
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-12 tab-pane fade" id="onion-tab">
|
|
||||||
<img id="loading-gif-modal" src="{{url_for('static', filename='image/loading.gif') }}" style="margin: 4px;">
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-12 tab-pane fade" id="bitcoin-tab">
|
|
||||||
<img id="loading-gif-modal" src="{{url_for('static', filename='image/loading.gif') }}" style="margin: 4px;">
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-12 tab-pane fade" id="base64-tab">
|
|
||||||
<img id="loading-gif-modal" src="{{url_for('static', filename='image/loading.gif') }}" style="margin: 4px;">
|
|
||||||
</div>
|
|
||||||
</div> <!-- tab-content -->
|
|
||||||
<!-- /.row -->
|
|
||||||
</div>
|
|
||||||
<!-- /#page-wrapper -->
|
|
||||||
|
|
||||||
<!-- import graph function -->
|
|
||||||
<script>
|
|
||||||
$(document).ready(function(){
|
|
||||||
activePage = $('h1.page-header').attr('data-page');
|
|
||||||
$("#"+activePage).addClass("active");
|
|
||||||
|
|
||||||
var dataPath = 'credential';
|
|
||||||
$.get("{{ url_for('browsepastes.importantPasteByModule') }}"+"?moduleName="+dataPath+"&year="+currentSelectYear, function(data, status){
|
|
||||||
$('#'+dataPath+'-tab').html(data);
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
|
|
||||||
<script>
|
|
||||||
// When a pannel is shown, create the data-table.
|
|
||||||
var previous_tab = $('[data-attribute-name="credential');
|
|
||||||
var currentTabName = previous_tab.attr('data-attribute-name');
|
|
||||||
var loading_gif = "<img id='loading-gif-modal' class='img-center' src=\"{{url_for('static', filename='image/loading.gif') }}\" height='26' width='26' style='margin: 4px;'>";
|
|
||||||
var currentSelectYear = {{ selected_year }};
|
|
||||||
|
|
||||||
$('#index_year').on('change', function() {
|
|
||||||
currentSelectYear = this.value;
|
|
||||||
|
|
||||||
$.get("{{ url_for('browsepastes.importantPasteByModule') }}"+"?moduleName="+currentTabName+"&year="+currentSelectYear, function(data, status){
|
|
||||||
$('#'+currentTabName+'-tab').html(data);
|
|
||||||
});
|
|
||||||
})
|
|
||||||
|
|
||||||
$('.nav-tabs a').on('shown.bs.tab', function(event){
|
|
||||||
var dataPath = $(event.target).attr('data-attribute-name');
|
|
||||||
currentTabName = dataPath;
|
|
||||||
$.get("{{ url_for('browsepastes.importantPasteByModule') }}"+"?moduleName="+currentTabName+"&year="+currentSelectYear, function(data, status){
|
|
||||||
currentTab = $('[name].active').children();
|
|
||||||
$('#'+previous_tab.attr('data-attribute-name')+'-tab').html(loading_gif);
|
|
||||||
currentTab.removeClass( "active" );
|
|
||||||
|
|
||||||
$('#'+dataPath+'-tab').html(data);
|
|
||||||
|
|
||||||
$(event.target).parent().addClass( "active" );
|
|
||||||
previous_tab = currentTab;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
|
@ -1 +0,0 @@
|
||||||
<li id='page-browse'><a href="{{ url_for('browsepastes.browseImportantPaste') }}"><i class="fa fa-search-plus "></i> Browse important pastes</a></li>
|
|
|
@ -1,261 +0,0 @@
|
||||||
<table class="table table-striped table-bordered table-hover" id="myTable_{{ moduleName }}">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>#</th>
|
|
||||||
<th style="max-width: 800px;">Path</th>
|
|
||||||
<th>Date</th>
|
|
||||||
<th># of lines</th>
|
|
||||||
<th>Action</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{% for path in all_path %}
|
|
||||||
<tr>
|
|
||||||
<td> {{ loop.index0 }}</td>
|
|
||||||
<td><a target="_blank" href="{{ url_for('showsavedpastes.showsavedpaste') }}?paste={{path}}">{{ path }}</a>
|
|
||||||
<div>
|
|
||||||
{% for tag in paste_tags[loop.index0] %}
|
|
||||||
<a href="{{ url_for('Tags.get_tagged_paste') }}?ltags={{ tag[1] }}">
|
|
||||||
<span class="label label-{{ bootstrap_label[loop.index0 % 5] }} pull-left">{{ tag[0] }}</span>
|
|
||||||
</a>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>{{ paste_date[loop.index0] }}</td>
|
|
||||||
<td>{{ paste_linenum[loop.index0] }}</td>
|
|
||||||
<td><p><span class="glyphicon glyphicon-info-sign" data-toggle="tooltip" data-placement="left" title="{{ content[loop.index0] }} "></span> <button type="button" class="btn-link" data-num="{{ loop.index0 + 1 }}" data-toggle="modal" data-target="#mymodal" data-url="{{ url_for('showsavedpastes.showsavedpaste') }}?paste={{ path }}&num={{ loop.index0+1 }}" data-path="{{ path }}"><span class="fa fa-search-plus"></span></button></p></td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</br>
|
|
||||||
<div id="nbr_entry" class="alert alert-info">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div id="div_stil_data">
|
|
||||||
<button id="load_more_json_button1" type="button" class="btn btn-default" onclick="add_entries(100)" style="display: none">Load 100 entries</button>
|
|
||||||
<button id="load_more_json_button2" type="button" class="btn btn-warning" onclick="add_entries(300)" style="display: none">Load 300 entries</button>
|
|
||||||
<img id="loading_gif_browse" src="{{url_for('static', filename='image/loading.gif') }}" heigt="20" width="20" style="margin: 2px;"></div>
|
|
||||||
</br>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<script>
|
|
||||||
var json_array = [];
|
|
||||||
var all_data_received = false;
|
|
||||||
var curr_numElem;
|
|
||||||
var elem_added = 10; //10 elements are added by default in the page loading
|
|
||||||
var tot_num_entry = 10; //10 elements are added by default in the page loading
|
|
||||||
|
|
||||||
function deploy_source() {
|
|
||||||
var button_load_more_displayed = false;
|
|
||||||
|
|
||||||
if(typeof(EventSource) !== "undefined" && typeof(source) !== "") {
|
|
||||||
$("#load_more_json_button1").show();
|
|
||||||
$("#load_more_json_button2").show();
|
|
||||||
var source = new EventSource("{{ url_for('browsepastes.getImportantPasteByModule') }}"+"?moduleName="+moduleName+"&year="+currentSelectYear);
|
|
||||||
source.onmessage = function(event) {
|
|
||||||
var feed = jQuery.parseJSON( event.data );
|
|
||||||
curr_numElem = parseInt($("#myTable_"+moduleName).attr('data-numElem'));
|
|
||||||
if (feed.index > curr_numElem & feed.module == moduleName) { // Avoid doubling the pastes
|
|
||||||
json_array.push(feed);
|
|
||||||
tot_num_entry++;
|
|
||||||
$("#nbr_entry").text(tot_num_entry + " entries available, " + (tot_num_entry - elem_added) + " not displayed");
|
|
||||||
|
|
||||||
$("#myTable_"+moduleName).attr('data-numElem', curr_numElem+1);
|
|
||||||
|
|
||||||
if(feed.index > 100 && !button_load_more_displayed) {
|
|
||||||
button_load_more_displayed = true;
|
|
||||||
add_entries_X(20);
|
|
||||||
}
|
|
||||||
if(feed.finished) {
|
|
||||||
$("#loading_gif_browse").hide();
|
|
||||||
source.close();
|
|
||||||
all_data_received = true;
|
|
||||||
add_entries_X(10);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
console.log("Sorry, your browser does not support server-sent events...");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function add_entries(iter) { //Used to disable the button before going to the big loop
|
|
||||||
$("#load_more_json_button1").attr('disabled','disabled');
|
|
||||||
$("#load_more_json_button2").attr('disabled','disabled');
|
|
||||||
setTimeout(function() { add_entries_X(iter);}, 50);
|
|
||||||
}
|
|
||||||
|
|
||||||
function add_entries_X(to_add) {
|
|
||||||
for(i=0; i<to_add; i++) {
|
|
||||||
if(json_array.length == 0 && all_data_received) {
|
|
||||||
$("#load_more_json_button1").hide();
|
|
||||||
$("#load_more_json_button2").hide();
|
|
||||||
$("#nbr_entry").hide();
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
var feed = json_array.shift();
|
|
||||||
elem_added++;
|
|
||||||
var tag = ""
|
|
||||||
for(j=0; j<feed.l_tags.length; j++) {
|
|
||||||
console.log(feed.l_tags[j][1])
|
|
||||||
tag = tag + "<a href=\"{{ url_for('Tags.get_tagged_paste') }}?ltags=" + feed.l_tags[j][1] + "\">"
|
|
||||||
+ "<span class=\"label label-" + feed.bootstrap_label[j % 5] + " pull-left\">" + feed.l_tags[j][0] + "</span>" + "</a>";
|
|
||||||
}
|
|
||||||
search_table.row.add( [
|
|
||||||
feed.index,
|
|
||||||
"<a target=\"_blank\" href=\"{{ url_for('showsavedpastes.showsavedpaste') }}?paste="+feed.path+"&num="+feed.index+"\"> "+ feed.path +"</a>"
|
|
||||||
+ "<div>" + tag + "</div>" ,
|
|
||||||
feed.date,
|
|
||||||
feed.linenum,
|
|
||||||
"<p><span class=\"glyphicon glyphicon-info-sign\" data-toggle=\"tooltip\" data-placement=\"left\" title=\""+feed.content.replace(/\"/g, "\'").replace(/\r/g, "\'").replace(/\n/g, "\'")+"\"></span> <button type=\"button\" class=\"btn-link\" data-num=\""+feed.index+"\" data-toggle=\"modal\" data-target=\"#mymodal\" data-url=\"{{ url_for('showsavedpastes.showsavedpaste') }}?paste="+feed.path+"&num="+feed.index+"\" data-path=\""+feed.path+"\"><span class=\"fa fa-search-plus\"></span></button></p>"
|
|
||||||
] ).draw( false );
|
|
||||||
$("#myTable_"+moduleName).attr('data-numElem', curr_numElem+1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$("#load_more_json_button1").removeAttr('disabled');
|
|
||||||
$("#load_more_json_button2").removeAttr('disabled');
|
|
||||||
$("#nbr_entry").text(tot_num_entry + " entries available, " + (tot_num_entry - elem_added) + " not displayed");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
|
|
||||||
<script>
|
|
||||||
var moduleName = "{{ moduleName }}";
|
|
||||||
var currentSelectYear = "{{ year }}";
|
|
||||||
var search_table;
|
|
||||||
var last_clicked_paste;
|
|
||||||
var can_change_modal_content = true;
|
|
||||||
$("#myTable_"+moduleName).attr('data-numElem', "{{ all_path|length }}");
|
|
||||||
|
|
||||||
$(document).ready(function(){
|
|
||||||
$('[data-toggle="tooltip"]').tooltip();
|
|
||||||
$("[data-toggle='modal']").off('click.openmodal').on("click.openmodal", function (event) {
|
|
||||||
get_html_and_update_modal(event, $(this));
|
|
||||||
});
|
|
||||||
|
|
||||||
search_table = $('#myTable_'+moduleName).DataTable({ "order": [[ 2, "desc" ]] });
|
|
||||||
|
|
||||||
if( "{{ finished }}" == "True"){
|
|
||||||
$("#load_more_json_button1").hide();
|
|
||||||
$("#load_more_json_button2").hide();
|
|
||||||
$("#nbr_entry").hide();
|
|
||||||
$("#loading_gif_browse").hide();
|
|
||||||
} else {
|
|
||||||
deploy_source();
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<!-- Dynamically update the modal -->
|
|
||||||
<script type="text/javascript">
|
|
||||||
// static data
|
|
||||||
var alert_message = '<div class="alert alert-info alert-dismissable"><button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button><strong>No more data.</strong> Full paste displayed.</div>';
|
|
||||||
var complete_paste = null;
|
|
||||||
var char_to_display = {{ char_to_display }};
|
|
||||||
var start_index = 0;
|
|
||||||
|
|
||||||
// When the modal goes out, refresh it to normal content
|
|
||||||
$("#mymodal").on('hidden.bs.modal', function () {
|
|
||||||
can_change_modal_content = true;
|
|
||||||
$("#mymodalbody").html("<p>Loading paste information...</p>");
|
|
||||||
var loading_gif = "<img id='loading-gif-modal' class='img-center' src=\"{{url_for('static', filename='image/loading.gif') }}\" height='26' width='26' style='margin: 4px;'>";
|
|
||||||
$("#mymodalbody").append(loading_gif); // Show the loading GIF
|
|
||||||
$("#button_show_path").attr('href', '');
|
|
||||||
$("#button_show_path").hide();
|
|
||||||
complete_paste = null;
|
|
||||||
start_index = 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Update the paste preview in the modal
|
|
||||||
function update_preview() {
|
|
||||||
if (start_index + char_to_display > complete_paste.length-1){ // end of paste reached
|
|
||||||
var final_index = complete_paste.length-1;
|
|
||||||
var flag_stop = true;
|
|
||||||
} else {
|
|
||||||
var final_index = start_index + char_to_display;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (final_index != start_index){ // still have data to display
|
|
||||||
// Append the new content using text() and not append (XSS)
|
|
||||||
$("#mymodalbody").find("#paste-holder").text($("#mymodalbody").find("#paste-holder").text()+complete_paste.substring(start_index+1, final_index+1));
|
|
||||||
start_index = final_index;
|
|
||||||
if (flag_stop)
|
|
||||||
nothing_to_display();
|
|
||||||
} else {
|
|
||||||
nothing_to_display();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Update the modal when there is no more data
|
|
||||||
function nothing_to_display() {
|
|
||||||
var new_content = $(alert_message).hide();
|
|
||||||
$("#mymodalbody").find("#panel-body").append(new_content);
|
|
||||||
new_content.show('fast');
|
|
||||||
$("#load-more-button").hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
function get_html_and_update_modal(event, truemodal) {
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
var modal=truemodal;
|
|
||||||
var url = " {{ url_for('showsavedpastes.showpreviewpaste') }}?paste=" + modal.attr('data-path') + "&num=" + modal.attr('data-num');
|
|
||||||
last_clicked_paste = modal.attr('data-num');
|
|
||||||
$.get(url, function (data) {
|
|
||||||
|
|
||||||
// verify that the reveived data is really the current clicked paste. Otherwise, ignore it.
|
|
||||||
var received_num = parseInt(data.split("|num|")[1]);
|
|
||||||
if (received_num == last_clicked_paste && can_change_modal_content) {
|
|
||||||
can_change_modal_content = false;
|
|
||||||
|
|
||||||
// clear data by removing html, body, head tags. prevent dark modal background stack bug.
|
|
||||||
var cleared_data = data.split("<body>")[1].split("</body>")[0];
|
|
||||||
$("#mymodalbody").html(cleared_data);
|
|
||||||
|
|
||||||
var button = $('<button type="button" id="load-more-button" class="btn btn-info btn-xs center-block" data-url="' + $(modal).attr('data-path') +'" data-toggle="tooltip" data-placement="bottom" title="Load more content"><span class="glyphicon glyphicon-download"></span></button>');
|
|
||||||
button.tooltip();
|
|
||||||
$("#mymodalbody").children(".panel-default").append(button);
|
|
||||||
|
|
||||||
$("#button_show_path").attr('href', $(modal).attr('data-url'));
|
|
||||||
$("#button_show_path").show('fast');
|
|
||||||
$("#loading-gif-modal").css("visibility", "hidden"); // Hide the loading GIF
|
|
||||||
if ($("[data-initsize]").attr('data-initsize') < char_to_display) { // All the content is displayed
|
|
||||||
nothing_to_display();
|
|
||||||
}
|
|
||||||
// On click, donwload all paste's content
|
|
||||||
$("#load-more-button").on("click", function (event) {
|
|
||||||
if (complete_paste == null) { //Donwload only once
|
|
||||||
$.get("{{ url_for('showsavedpastes.getmoredata') }}"+"?paste="+$(modal).attr('data-path'), function(data, status){
|
|
||||||
complete_paste = data;
|
|
||||||
update_preview();
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
update_preview();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else if (can_change_modal_content) {
|
|
||||||
$("#mymodalbody").html("Ignoring previous not finished query of paste #" + received_num);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Use to bind the button with the new displayed data
|
|
||||||
// (The bind do not happens if the dataTable is in tabs and the clicked data is in another page)
|
|
||||||
|
|
||||||
search_table.on( 'draw.dt', function () {
|
|
||||||
// Bind tooltip each time we draw a new page
|
|
||||||
$('[data-toggle="tooltip"]').tooltip();
|
|
||||||
// On click, get html content from url and update the corresponding modal
|
|
||||||
$("[data-toggle='modal']").off('click.openmodal').on("click.openmodal", function (event) {
|
|
||||||
get_html_and_update_modal(event, $(this));
|
|
||||||
});
|
|
||||||
} );
|
|
||||||
|
|
||||||
</script>
|
|
Loading…
Reference in New Issue