diff --git a/bin/crawlers/Crawler.py b/bin/crawlers/Crawler.py
index fd8a758f..4b499eb9 100755
--- a/bin/crawlers/Crawler.py
+++ b/bin/crawlers/Crawler.py
@@ -19,6 +19,7 @@ from lib.ConfigLoader import ConfigLoader
from lib.objects.Domains import Domain
from lib.objects.Items import Item
from lib.objects import Screenshots
+from lib.objects import Titles
logging.config.dictConfig(ail_logger.get_config(name='crawlers'))
@@ -252,6 +253,13 @@ class Crawler(AbstractModule):
self.root_item = item_id
parent_id = item_id
+ item = Item(item_id)
+
+ title_content = crawlers.extract_title_from_html(entries['html'])
+ if title_content:
+ title = Titles.create_title(title_content)
+ title.add(item.get_date(), item_id)
+
# SCREENSHOT
if self.screenshot:
if 'png' in entries and entries['png']:
@@ -260,7 +268,6 @@ class Crawler(AbstractModule):
if not screenshot.is_tags_safe():
unsafe_tag = 'dark-web:topic="pornography-child-exploitation"'
self.domain.add_tag(unsafe_tag)
- item = Item(item_id)
item.add_tag(unsafe_tag)
# Remove Placeholder pages # TODO Replace with warning list ???
if screenshot.id not in self.placeholder_screenshots:
diff --git a/bin/lib/ail_core.py b/bin/lib/ail_core.py
index 6f4ed42e..a9128489 100755
--- a/bin/lib/ail_core.py
+++ b/bin/lib/ail_core.py
@@ -15,7 +15,7 @@ config_loader = ConfigLoader()
r_serv_db = config_loader.get_db_conn("Kvrocks_DB")
config_loader = None
-AIL_OBJECTS = sorted({'cve', 'cryptocurrency', 'decoded', 'domain', 'item', 'pgp', 'screenshot', 'username'})
+AIL_OBJECTS = sorted({'cve', 'cryptocurrency', 'decoded', 'domain', 'item', 'pgp', 'screenshot', 'title', 'username'})
def get_ail_uuid():
ail_uuid = r_serv_db.get('ail:uuid')
diff --git a/bin/lib/correlations_engine.py b/bin/lib/correlations_engine.py
index c0e8d370..f09d5c5f 100755
--- a/bin/lib/correlations_engine.py
+++ b/bin/lib/correlations_engine.py
@@ -44,11 +44,12 @@ CORRELATION_TYPES_BY_OBJ = {
"cryptocurrency": ["domain", "item"],
"cve": ["domain", "item"],
"decoded": ["domain", "item"],
- "domain": ["cve", "cryptocurrency", "decoded", "item", "pgp", "username", "screenshot"],
- "item": ["cve", "cryptocurrency", "decoded", "domain", "pgp", "username", "screenshot"],
+ "domain": ["cve", "cryptocurrency", "decoded", "item", "pgp", "title", "screenshot", "username"],
+ "item": ["cve", "cryptocurrency", "decoded", "domain", "pgp", "screenshot", "title", "username"],
"pgp": ["domain", "item"],
- "username": ["domain", "item"],
"screenshot": ["domain", "item"],
+ "title": ["domain", "item"],
+ "username": ["domain", "item"],
}
def get_obj_correl_types(obj_type):
diff --git a/bin/lib/crawlers.py b/bin/lib/crawlers.py
index 2a9c2a01..d8f4c890 100755
--- a/bin/lib/crawlers.py
+++ b/bin/lib/crawlers.py
@@ -183,6 +183,47 @@ def extract_favicon_from_html(html, url):
# # # - - # # #
+# # # # # # # #
+# #
+# TITLE #
+# #
+# # # # # # # #
+
+def extract_title_from_html(html):
+ soup = BeautifulSoup(html, 'html.parser')
+ title = soup.title
+ if title:
+ return str(title.string)
+ return ''
+
+def extract_description_from_html(html):
+ soup = BeautifulSoup(html, 'html.parser')
+ description = soup.find('meta', attrs={'name': 'description'})
+ if description:
+ return description['content']
+ return ''
+
+def extract_description_from_html(html):
+ soup = BeautifulSoup(html, 'html.parser')
+ description = soup.find('meta', attrs={'name': 'description'})
+ if description:
+ return description['content']
+ return ''
+
+def extract_keywords_from_html(html):
+ soup = BeautifulSoup(html, 'html.parser')
+ keywords = soup.find('meta', attrs={'name': 'keywords'})
+ if keywords:
+ return keywords['content']
+ return ''
+
+def extract_author_from_html(html):
+ soup = BeautifulSoup(html, 'html.parser')
+ keywords = soup.find('meta', attrs={'name': 'author'})
+ if keywords:
+ return keywords['content']
+ return ''
+# # # - - # # #
################################################################################
@@ -1711,7 +1752,7 @@ def test_ail_crawlers():
load_blacklist()
# if __name__ == '__main__':
- # task = CrawlerTask('2dffcae9-8f66-4cfa-8e2c-de1df738a6cd')
- # print(task.get_meta())
- # _clear_captures()
-
+# item = Item('crawled/2023/03/06/foo.bec50a87b5-0c21-4ed4-9cb2-2d717a7a6507')
+# content = item.get_content()
+# r = extract_author_from_html(content)
+# print(r)
diff --git a/bin/lib/module_extractor.py b/bin/lib/module_extractor.py
index 99d51a6b..02f499fd 100755
--- a/bin/lib/module_extractor.py
+++ b/bin/lib/module_extractor.py
@@ -3,7 +3,6 @@
import json
import os
import sys
-import time
import yara
@@ -15,6 +14,7 @@ sys.path.append(os.environ['AIL_BIN'])
##################################
from lib.objects import ail_objects
from lib.objects.Items import Item
+from lib.objects.Titles import Title
from lib import correlations_engine
from lib import regex_helper
from lib.ConfigLoader import ConfigLoader
@@ -58,18 +58,25 @@ def get_correl_match(extract_type, obj_id, content):
correl = correlations_engine.get_correlation_by_correl_type('item', '', obj_id, extract_type)
to_extract = []
map_subtype = {}
+ map_value_id = {}
for c in correl:
subtype, value = c.split(':', 1)
- map_subtype[value] = subtype
- to_extract.append(value)
+ if extract_type == 'title':
+ title = Title(value).get_content()
+ to_extract.append(title)
+ map_value_id[title] = value
+ else:
+ map_subtype[value] = subtype
+ to_extract.append(value)
+ map_value_id[value] = value
if to_extract:
objs = regex_helper.regex_finditer(r_key, '|'.join(to_extract), obj_id, content)
for obj in objs:
- if map_subtype[obj[2]]:
+ if map_subtype.get(obj[2]):
subtype = map_subtype[obj[2]]
else:
subtype = ''
- extracted.append([obj[0], obj[1], obj[2], f'{extract_type}:{subtype}:{obj[2]}'])
+ extracted.append([obj[0], obj[1], obj[2], f'{extract_type}:{subtype}:{map_value_id[obj[2]]}'])
return extracted
def _get_yara_match(data):
@@ -173,7 +180,7 @@ def extract(obj_id, content=None):
if matches:
extracted = extracted + matches
- for obj_t in ['cve', 'cryptocurrency', 'username']: # Decoded, PGP->extract bloc
+ for obj_t in ['cve', 'cryptocurrency', 'title', 'username']: # Decoded, PGP->extract bloc
matches = get_correl_match(obj_t, obj_id, content)
if matches:
extracted = extracted + matches
diff --git a/bin/lib/objects/Titles.py b/bin/lib/objects/Titles.py
new file mode 100755
index 00000000..3c682224
--- /dev/null
+++ b/bin/lib/objects/Titles.py
@@ -0,0 +1,114 @@
+#!/usr/bin/env python3
+# -*-coding:UTF-8 -*
+
+import os
+import sys
+
+from hashlib import sha256
+from flask import url_for
+
+from pymisp import MISPObject
+
+sys.path.append(os.environ['AIL_BIN'])
+##################################
+# Import Project packages
+##################################
+from lib.ConfigLoader import ConfigLoader
+from lib.objects.abstract_daterange_object import AbstractDaterangeObject, AbstractDaterangeObjects
+
+config_loader = ConfigLoader()
+r_objects = config_loader.get_db_conn("Kvrocks_Objects")
+baseurl = config_loader.get_config_str("Notifications", "ail_domain")
+config_loader = None
+
+
+class Title(AbstractDaterangeObject):
+ """
+ AIL Title Object.
+ """
+
+ def __init__(self, id):
+ super(Title, self).__init__('title', id)
+
+ # def get_ail_2_ail_payload(self):
+ # payload = {'raw': self.get_gzip_content(b64=True),
+ # 'compress': 'gzip'}
+ # return payload
+
+ # # WARNING: UNCLEAN DELETE /!\ TEST ONLY /!\
+ def delete(self):
+ # # TODO:
+ pass
+
+ def get_content(self, r_type='str'):
+ if r_type == 'str':
+ return self._get_field('content')
+
+ def get_link(self, flask_context=False):
+ if flask_context:
+ url = url_for('correlation.show_correlation', type=self.type, id=self.id)
+ else:
+ url = f'{baseurl}/correlation/show?type={self.type}&id={self.id}'
+ return url
+
+ # TODO # CHANGE COLOR
+ def get_svg_icon(self):
+ return {'style': 'fas', 'icon': '\uf1dc', 'color': '#1E88E5', 'radius': 5}
+
+ def get_misp_object(self):
+ obj_attrs = []
+ obj = MISPObject('tsk-web-history')
+ obj.first_seen = self.get_first_seen()
+ obj.last_seen = self.get_last_seen()
+
+ obj_attrs.append(obj.add_attribute('title', value=self.get_content()))
+ for obj_attr in obj_attrs:
+ for tag in self.get_tags():
+ obj_attr.add_tag(tag)
+ return obj
+
+ def get_meta(self, options=set()):
+ meta = self._get_meta(options=options)
+ meta['id'] = self.id
+ meta['tags'] = self.get_tags(r_list=True)
+ meta['content'] = self.get_content()
+ return meta
+
+ def add(self, date, item_id):
+ self._add(date, item_id)
+
+ def create(self, content, _first_seen=None, _last_seen=None):
+ self._set_field('content', content)
+ self._create()
+
+
+def create_title(content):
+ title_id = sha256(content.encode()).hexdigest()
+ title = Title(title_id)
+ if not title.exists():
+ title.create(content)
+ return title
+
+class Titles(AbstractDaterangeObjects):
+ """
+ Titles Objects
+ """
+ def __init__(self):
+ super().__init__('title')
+
+ def get_metas(self, obj_ids, options=set()):
+ return self._get_metas(Title, obj_ids, options=options)
+
+ def sanitize_name_to_search(self, name_to_search):
+ return name_to_search
+
+
+# if __name__ == '__main__':
+# from lib import crawlers
+# from lib.objects import Items
+# for item in Items.get_all_items_objects(filters={'sources': ['crawled']}):
+# title_content = crawlers.extract_title_from_html(item.get_content())
+# if title_content:
+# print(item.id, title_content)
+# title = create_title(title_content)
+# title.add(item.get_date(), item.id)
diff --git a/bin/lib/objects/abstract_daterange_object.py b/bin/lib/objects/abstract_daterange_object.py
index 882c11c7..59a579f4 100755
--- a/bin/lib/objects/abstract_daterange_object.py
+++ b/bin/lib/objects/abstract_daterange_object.py
@@ -7,6 +7,7 @@ Base Class for AIL Objects
# Import External packages
##################################
import os
+import re
import sys
from abc import abstractmethod, ABC
@@ -44,8 +45,14 @@ class AbstractDaterangeObject(AbstractObject, ABC):
def exists(self):
return r_object.exists(f'meta:{self.type}:{self.id}')
+ def _get_field(self, field):
+ return r_object.hget(f'meta:{self.type}:{self.id}', field)
+
+ def _set_field(self, field, value):
+ return r_object.hset(f'meta:{self.type}:{self.id}', field, value)
+
def get_first_seen(self, r_int=False):
- first_seen = r_object.hget(f'meta:{self.type}:{self.id}', 'first_seen')
+ first_seen = self._get_field('first_seen')
if r_int:
if first_seen:
return int(first_seen)
@@ -55,7 +62,7 @@ class AbstractDaterangeObject(AbstractObject, ABC):
return first_seen
def get_last_seen(self, r_int=False):
- last_seen = r_object.hget(f'meta:{self.type}:{self.id}', 'last_seen')
+ last_seen = self._get_field('last_seen')
if r_int:
if last_seen:
return int(last_seen)
@@ -83,10 +90,10 @@ class AbstractDaterangeObject(AbstractObject, ABC):
return meta_dict
def set_first_seen(self, first_seen):
- r_object.hset(f'meta:{self.type}:{self.id}', 'first_seen', first_seen)
+ self._set_field('first_seen', first_seen)
def set_last_seen(self, last_seen):
- r_object.hset(f'meta:{self.type}:{self.id}', 'last_seen', last_seen)
+ self._set_field('last_seen', last_seen)
def update_daterange(self, date):
date = int(date)
@@ -139,11 +146,85 @@ class AbstractDaterangeObject(AbstractObject, ABC):
self.add_correlation('domain', '', domain)
# TODO:ADD objects + Stats
- def _create(self, first_seen, last_seen):
- self.set_first_seen(first_seen)
- self.set_last_seen(last_seen)
+ def _create(self, first_seen=None, last_seen=None):
+ if first_seen:
+ self.set_first_seen(first_seen)
+ if last_seen:
+ self.set_last_seen(last_seen)
r_object.sadd(f'{self.type}:all', self.id)
# TODO
def _delete(self):
pass
+
+
+class AbstractDaterangeObjects(ABC):
+ """
+ Abstract Daterange Objects
+ """
+
+ def __init__(self, obj_type):
+ """ Abstract for Daterange Objects
+
+ :param obj_type: object type (item, ...)
+ """
+ self.type = obj_type
+
+ def get_all(self):
+ return r_object.smembers(f'{self.type}:all')
+
+ def get_by_date(self, date):
+ return r_object.zrange(f'{self.type}:date:{date}', 0, -1)
+
+ def get_nb_by_date(self, date):
+ return r_object.zcard(f'{self.type}:date:{date}')
+
+ def get_by_daterange(self, date_from, date_to):
+ obj_ids = set()
+ for date in Date.substract_date(date_from, date_to):
+ obj_ids = obj_ids | set(self.get_by_date(date))
+ return obj_ids
+
+ @abstractmethod
+ def get_metas(self, obj_ids, options=set()):
+ pass
+
+ def _get_metas(self, obj_class_ref, obj_ids, options=set()):
+ dict_obj = {}
+ for obj_id in obj_ids:
+ obj = obj_class_ref(obj_id)
+ dict_obj[obj_id] = obj.get_meta(options=options)
+ return dict_obj
+
+ @abstractmethod
+ def sanitize_name_to_search(self, name_to_search):
+ return name_to_search
+
+ def search_by_name(self, name_to_search, r_pos=False):
+ objs = {}
+ # for subtype in subtypes:
+ r_name = self.sanitize_name_to_search(name_to_search)
+ if not name_to_search or isinstance(r_name, dict):
+ return objs
+ r_name = re.compile(r_name)
+ for title_name in self.get_all():
+ res = re.search(r_name, title_name)
+ if res:
+ objs[title_name] = {}
+ if r_pos:
+ objs[title_name]['hl-start'] = res.start()
+ objs[title_name]['hl-end'] = res.end()
+ return objs
+
+ def api_get_chart_nb_by_daterange(self, date_from, date_to):
+ date_type = []
+ for date in Date.substract_date(date_from, date_to):
+ d = {'date': f'{date[0:4]}-{date[4:6]}-{date[6:8]}',
+ self.type: self.get_nb_by_date(date)}
+ date_type.append(d)
+ return date_type
+
+ def api_get_meta_by_daterange(self, date_from, date_to):
+ date = Date.sanitise_date_range(date_from, date_to)
+ return self.get_metas(self.get_by_daterange(date['date_from'], date['date_to']), options={'sparkline'})
+
diff --git a/bin/lib/objects/abstract_object.py b/bin/lib/objects/abstract_object.py
index b65c9ace..631597c4 100755
--- a/bin/lib/objects/abstract_object.py
+++ b/bin/lib/objects/abstract_object.py
@@ -187,7 +187,7 @@ class AbstractObject(ABC):
pass
@staticmethod
- def get_misp_object_first_last_seen(misp_obj):
+ def get_misp_object_first_last_seen(misp_obj): # TODO REMOVE ME ????
"""
:type misp_obj: MISPObject
"""
diff --git a/bin/lib/objects/ail_objects.py b/bin/lib/objects/ail_objects.py
index 01445c9e..d52a0bbd 100755
--- a/bin/lib/objects/ail_objects.py
+++ b/bin/lib/objects/ail_objects.py
@@ -21,6 +21,7 @@ from lib.objects.Domains import Domain
from lib.objects.Items import Item, get_all_items_objects, get_nb_items_objects
from lib.objects import Pgps
from lib.objects.Screenshots import Screenshot
+from lib.objects import Titles
from lib.objects import Usernames
config_loader = ConfigLoader()
@@ -59,6 +60,8 @@ def get_object(obj_type, subtype, id):
return CryptoCurrencies.CryptoCurrency(id, subtype)
elif obj_type == 'pgp':
return Pgps.Pgp(id, subtype)
+ elif obj_type == 'title':
+ return Titles.Title(id)
elif obj_type == 'username':
return Usernames.Username(id, subtype)
@@ -160,10 +163,12 @@ def get_object_card_meta(obj_type, subtype, id, related_btc=False):
obj = get_object(obj_type, subtype, id)
meta = obj.get_meta()
meta['icon'] = obj.get_svg_icon()
- if subtype or obj_type == 'cve':
+ if subtype or obj_type == 'cve' or obj_type == 'title':
meta['sparkline'] = obj.get_sparkline()
if obj_type == 'cve':
meta['cve_search'] = obj.get_cve_search()
+ # if obj_type == 'title':
+ # meta['cve_search'] = obj.get_cve_search()
if subtype == 'bitcoin' and related_btc:
meta["related_btc"] = btc_ail.get_bitcoin_info(obj.id)
if obj.get_type() == 'decoded':
diff --git a/bin/modules/Phone.py b/bin/modules/Phone.py
index a7537eda..16af8303 100755
--- a/bin/modules/Phone.py
+++ b/bin/modules/Phone.py
@@ -43,7 +43,7 @@ class Phone(AbstractModule):
def extract(self, obj_id, content, tag):
extracted = []
- phones = self.regex_phone_iter('US', obj_id, content)
+ phones = self.regex_phone_iter('ZZ', obj_id, content)
for phone in phones:
extracted.append([phone[0], phone[1], phone[2], f'tag:{tag}'])
return extracted
diff --git a/var/www/Flask_server.py b/var/www/Flask_server.py
index c6669ef6..63addc22 100755
--- a/var/www/Flask_server.py
+++ b/var/www/Flask_server.py
@@ -49,6 +49,7 @@ from blueprints.settings_b import settings_b
from blueprints.objects_cve import objects_cve
from blueprints.objects_decoded import objects_decoded
from blueprints.objects_subtypes import objects_subtypes
+from blueprints.objects_title import objects_title
Flask_dir = os.environ['AIL_FLASK']
@@ -102,6 +103,7 @@ app.register_blueprint(settings_b, url_prefix=baseUrl)
app.register_blueprint(objects_cve, url_prefix=baseUrl)
app.register_blueprint(objects_decoded, url_prefix=baseUrl)
app.register_blueprint(objects_subtypes, url_prefix=baseUrl)
+app.register_blueprint(objects_title, url_prefix=baseUrl)
# ========= =========#
# ========= Cookie name ========
diff --git a/var/www/blueprints/objects_title.py b/var/www/blueprints/objects_title.py
new file mode 100644
index 00000000..eef7f69c
--- /dev/null
+++ b/var/www/blueprints/objects_title.py
@@ -0,0 +1,86 @@
+#!/usr/bin/env python3
+# -*-coding:UTF-8 -*
+
+'''
+ Blueprint Flask: crawler splash endpoints: dashboard, onion crawler ...
+'''
+
+import os
+import sys
+
+from flask import Flask, render_template, jsonify, request, Blueprint, redirect, url_for, Response, abort, send_file
+from flask_login import login_required, current_user
+
+# Import Role_Manager
+from Role_Manager import login_admin, login_analyst, login_read_only
+
+sys.path.append(os.environ['AIL_BIN'])
+##################################
+# Import Project packages
+##################################
+from lib.objects import Titles
+from packages import Date
+
+# ============ BLUEPRINT ============
+objects_title = Blueprint('objects_title', __name__, template_folder=os.path.join(os.environ['AIL_FLASK'], 'templates/objects/title'))
+
+# ============ VARIABLES ============
+bootstrap_label = ['primary', 'success', 'danger', 'warning', 'info']
+
+
+# ============ FUNCTIONS ============
+@objects_title.route("/objects/title", methods=['GET'])
+@login_required
+@login_read_only
+def objects_titles():
+ date_from = request.args.get('date_from')
+ date_to = request.args.get('date_to')
+ show_objects = request.args.get('show_objects')
+ date = Date.sanitise_date_range(date_from, date_to)
+ date_from = date['date_from']
+ date_to = date['date_to']
+
+ if show_objects:
+ dict_objects = Titles.Titles().api_get_meta_by_daterange(date_from, date_to)
+ else:
+ dict_objects = {}
+
+ return render_template("TitleDaterange.html", date_from=date_from, date_to=date_to,
+ dict_objects=dict_objects, show_objects=show_objects)
+
+@objects_title.route("/objects/title/post", methods=['POST'])
+@login_required
+@login_read_only
+def objects_titles_post():
+ date_from = request.form.get('date_from')
+ date_to = request.form.get('date_to')
+ show_objects = request.form.get('show_objects')
+ return redirect(url_for('objects_title.objects_titles', date_from=date_from, date_to=date_to, show_objects=show_objects))
+
+@objects_title.route("/objects/title/range/json", methods=['GET'])
+@login_required
+@login_read_only
+def objects_title_range_json():
+ date_from = request.args.get('date_from')
+ date_to = request.args.get('date_to')
+ date = Date.sanitise_date_range(date_from, date_to)
+ date_from = date['date_from']
+ date_to = date['date_to']
+ return jsonify(Titles.Titles().api_get_chart_nb_by_daterange(date_from, date_to))
+
+@objects_title.route("/objects/title/search", methods=['POST'])
+@login_required
+@login_read_only
+def objects_title_search():
+ to_search = request.form.get('object_id')
+
+ # TODO SANITIZE ID
+ # TODO Search all
+ title = Titles.Title(to_search)
+ if not title.exists():
+ abort(404)
+ else:
+ return redirect(title.get_link(flask_context=True))
+
+# ============= ROUTES ==============
+
diff --git a/var/www/templates/correlation/metadata_card_cve.html b/var/www/templates/correlation/metadata_card_cve.html
index d1cfab9f..1e166ddc 100644
--- a/var/www/templates/correlation/metadata_card_cve.html
+++ b/var/www/templates/correlation/metadata_card_cve.html
@@ -108,7 +108,7 @@
Tags:
{% for tag in dict_object["metadata"]['tags'] %}
{% endfor %}
diff --git a/var/www/templates/correlation/metadata_card_title.html b/var/www/templates/correlation/metadata_card_title.html
new file mode 100644
index 00000000..cd943349
--- /dev/null
+++ b/var/www/templates/correlation/metadata_card_title.html
@@ -0,0 +1,173 @@
+
+
+
+{% with modal_add_tags=dict_object['metadata_card']['add_tags_modal']%}
+ {% include 'modals/add_tags.html' %}
+{% endwith %}
+
+{% include 'modals/edit_tag.html' %}
+
+
+
+
+
+
+
+
+
+
diff --git a/var/www/templates/correlation/show_correlation.html b/var/www/templates/correlation/show_correlation.html
index b8a9dd79..8342e8b6 100644
--- a/var/www/templates/correlation/show_correlation.html
+++ b/var/www/templates/correlation/show_correlation.html
@@ -113,6 +113,8 @@
{% include 'correlation/metadata_card_domain.html' %}
{% elif dict_object["object_type"] == "screenshot" %}
{% include 'correlation/metadata_card_screenshot.html' %}
+ {% elif dict_object["object_type"] == "title" %}
+ {% include 'correlation/metadata_card_title.html' %}
{% elif dict_object["object_type"] == "item" %}
{% include 'correlation/metadata_card_item.html' %}
{% endif %}
diff --git a/var/www/templates/crawler/crawler_splash/showDomain.html b/var/www/templates/crawler/crawler_splash/showDomain.html
index 43f00d4b..b2e2f0b3 100644
--- a/var/www/templates/crawler/crawler_splash/showDomain.html
+++ b/var/www/templates/crawler/crawler_splash/showDomain.html
@@ -347,6 +347,46 @@
{% endif %}
+ {% if 'title' in dict_domain%}
+
+
+
+
+
+
+
+
+ Tilte |
+
+
+
+ {% for title in dict_domain['title']%}
+
+ {{ title[1] }} |
+
+ {% endfor %}
+
+
+
+
+
+
+ {% endif %}
+
{% if dict_domain["history"] %}
@@ -489,6 +529,9 @@
{% endif %}
{% if 'cryptocurrency' in dict_domain%}
$('#tablecurrency').DataTable({});
+ {% endif %}
+ {% if 'title' in dict_domain%}
+ $('#tabletitle').DataTable({});
{% endif %}
table = $('#myTable_1').DataTable(
{
diff --git a/var/www/templates/objects/title/TitleDaterange.html b/var/www/templates/objects/title/TitleDaterange.html
new file mode 100644
index 00000000..17efda7c
--- /dev/null
+++ b/var/www/templates/objects/title/TitleDaterange.html
@@ -0,0 +1,611 @@
+
+
+
+
+
Titles - AIL
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {% include 'nav_bar.html' %}
+
+
+
+
+ {% include 'sidebars/sidebar_objects.html' %}
+
+
+
+
+
+
+
+
+
+
Search Title by name:
+
+
+
+
+
+
+
+
+
+
+
Select a date range :
+
+
+
+
+
+
+
+
+
+
+
+ {% if dict_objects %}
+ {% if date_from|string == date_to|string %}
+
{{ date_from }} Title:
+ {% else %}
+
{{ date_from }} to {{ date_to }} Title:
+ {% endif %}
+
+
+
+ |
+ First Seen |
+ Last Seen |
+ Total |
+ Last days |
+
+
+
+ {% for obj_id in dict_objects %}
+
+ {{ dict_objects[obj_id]['content'] }} |
+ {{ dict_objects[obj_id]['first_seen'] }} |
+ {{ dict_objects[obj_id]['last_seen'] }} |
+ {{ dict_objects[obj_id]['nb_seen'] }} |
+ |
+
+ {% endfor %}
+
+
+
+
+ {% else %}
+ {% if show_objects %}
+ {% if date_from|string == date_to|string %}
+
{{ date_from }}, No Title
+ {% else %}
+
{{ date_from }} to {{ date_to }}, No Title
+ {% endif %}
+ {% endif %}
+ {% endif %}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/var/www/templates/sidebars/sidebar_objects.html b/var/www/templates/sidebars/sidebar_objects.html
index 46fe58eb..4f09e138 100644
--- a/var/www/templates/sidebars/sidebar_objects.html
+++ b/var/www/templates/sidebars/sidebar_objects.html
@@ -34,6 +34,12 @@
CVE
+
+
+
+ Title
+
+
@@ -61,7 +67,6 @@
-