diff --git a/lookyloo/lookyloo.py b/lookyloo/lookyloo.py index a302954..a525e19 100644 --- a/lookyloo/lookyloo.py +++ b/lookyloo/lookyloo.py @@ -303,7 +303,8 @@ class Lookyloo(): if categ_file.exists(): with categ_file.open() as f: current_categories = [line.strip() for line in f.readlines()] - return {e: self.taxonomies.revert_machinetag(e) for e in current_categories} + # return {e: self.taxonomies.revert_machinetag(e) for e in current_categories} + return {e: e for e in current_categories} return {} def categorize_capture(self, capture_uuid: str, /, category: str) -> None: @@ -311,7 +312,7 @@ class Lookyloo(): if not get_config('generic', 'enable_categorization'): return # Make sure the category is mappable to a taxonomy. - self.taxonomies.revert_machinetag(category) + # self.taxonomies.revert_machinetag(category) categ_file = self._captures_index[capture_uuid].capture_dir / 'categories' # get existing categories if possible @@ -335,9 +336,10 @@ class Lookyloo(): current_categories = {line.strip() for line in f.readlines()} else: current_categories = set() - current_categories.remove(category) - with categ_file.open('w') as f: - f.writelines(f'{t}\n' for t in current_categories) + if category in current_categories: + current_categories.remove(category) + with categ_file.open('w') as f: + f.writelines(f'{t}\n' for t in current_categories) def trigger_modules(self, capture_uuid: str, /, force: bool=False, auto_trigger: bool=False) -> dict[str, Any]: '''Launch the 3rd party modules on a capture. diff --git a/website/web/__init__.py b/website/web/__init__.py index f16f7ae..ba29f23 100644 --- a/website/web/__init__.py +++ b/website/web/__init__.py @@ -660,19 +660,31 @@ def historical_lookups(tree_uuid: str) -> str | WerkzeugResponse | Response: circl_pdns=data.get('circl_pdns')) -@app.route('/tree//categories_capture/', defaults={'query': ''}) +@app.route('/tree//categories_capture/', defaults={'query': ''}, methods=['GET', 'POST']) @app.route('/tree//categories_capture/', methods=['GET']) def categories_capture(tree_uuid: str, query: str) -> str | WerkzeugResponse | Response: if not enable_categorization: return redirect(url_for('tree', tree_uuid=tree_uuid)) - current_categories = lookyloo.categories_capture(tree_uuid) matching_categories = None - if query: + if 'verification-status' in request.form: + # fast categories + categories = [] + possible_ctgs = {'legitime': ["parking-page", "default-page", 'institution', 'captcha', 'authentication-form', 'adult-content', 'shop'], + 'malicious': ['clone', 'phishing', 'captcha', 'authentication-form', 'adult-content', 'shop'], + 'unclear': ['captcha', 'authentication-form', 'adult-content', 'shop']} + if request.form.get('verification-status') in possible_ctgs.keys(): + for category in possible_ctgs[request.form.get('verification-status')]: + if category in request.form: + categories.append(category) + for category in categories: + lookyloo.categorize_capture(tree_uuid, category) + if 'query' in request.form and request.form.get('query').strip(): matching_categories = {} t = get_taxonomies() entries = t.search(query) if entries: matching_categories = {e: t.revert_machinetag(e) for e in entries} + current_categories = lookyloo.categories_capture(tree_uuid) return render_template('categories_capture.html', tree_uuid=tree_uuid, current_categories=current_categories, matching_categories=matching_categories) diff --git a/website/web/static/tree.css b/website/web/static/tree.css index 0031889..be64843 100644 --- a/website/web/static/tree.css +++ b/website/web/static/tree.css @@ -185,4 +185,16 @@ hr { background: white; border: 2px solid; padding: 5px; -} \ No newline at end of file +} + +/* Fast categories*/ +.fast-categories { + border: 2px solid; + margin: 5px; + padding: 5px; +} + +.fast-categories fieldset { + border: 1px solid; + padding: 5px; +} diff --git a/website/web/templates/tree.html b/website/web/templates/tree.html index da0cf95..cbe2ce4 100644 --- a/website/web/templates/tree.html +++ b/website/web/templates/tree.html @@ -65,15 +65,79 @@ $('#categoriesModal').on('show.bs.modal', function(e) { var button = $(e.relatedTarget); var modal = $(this); - modal.find('#categoriesModal .modal-body').load(button.data("remote")); + modal.find('.modal-body').load(button.data("remote")); }); - $('#searchCategories').submit(function(event){ + /*$('#searchCategories').submit(function(event){ var query = $("#query").val(); - $('#categoriesModal .modal-body').load("{{ url_for('categories_capture', tree_uuid=tree_uuid) }}" + query, function() { + $('#categoriesModal .modal-body').load("{ url_for('categories_capture', tree_uuid=tree_uuid) }}" + query, function() { $('#categoriesModal').modal({show:true}); }); event.preventDefault(); }); + */ + + $('#fast-categories').submit(function(event){ + event.preventDefault(); + var query = $('#fast-categories').serialize(); // Serialize form data + + $.ajax({ + type: 'POST', + url: '{{ url_for('categories_capture', tree_uuid=tree_uuid) }}', + data: query, + success: function(response) { + $('#categoriesModal .modal-body').html(response); + $('#categoriesModal').modal({show:true}); + }, + error: function(error) { + console.log("An error occurred: ", error); + } + }); + }); + + // Fast categories + document.getElementById("legitime").addEventListener('change', function(){ + if (this.checked){ + disableInput(document.getElementById('malicious-categories')); + enableInput(document.getElementById('legitime-categories')); + } + }); + document.getElementById("malicious").addEventListener('change', function(){ + if (this.checked){ + enableInput(document.getElementById('malicious-categories')); + disableInput(document.getElementById('legitime-categories')); + } + }); + document.getElementById("unclear").addEventListener('change', function(){ + if (this.checked){ + disableInput(document.getElementById('malicious-categories')); + disableInput(document.getElementById('legitime-categories')); + } + }); + document.getElementById("legitime-categories").addEventListener('click', function(){ + if (this.querySelectorAll('input[type="checkbox"]:checked').length > 0) { + document.getElementById("legitime").checked = true; + } + }); + document.getElementById("malicious-categories").addEventListener('click', function(){ + if (this.querySelectorAll('input[type="checkbox"]:checked').length > 0) { + document.getElementById("malicious").checked = true; + } + }); + + function disableInput(container) { + const Input = container.querySelectorAll('input'); + Input.forEach(function(checkbox){ + checkbox.disabled = true; + checkbox.checked = false; + }); + container.hidden = true; + } + + function enableInput(container) { + const Input = container.querySelectorAll('input'); + Input.forEach(checkbox => checkbox.disabled = false); + container.hidden = false; + }