NMAPDEV plugin work v0.5 #645 🆕🔎

This commit is contained in:
jokob-sk
2024-04-24 23:19:23 +10:00
parent c7cb69c914
commit 141ba5d6c1
7 changed files with 151 additions and 51 deletions

View File

@@ -875,24 +875,24 @@ input[readonly] {
cursor: not-allowed;
}
.removable-option:hover::before {
.interactable-option:hover::before {
opacity: 1;
}
.removable-option::before {
content: 'Double-click to ❌';
.interactable-option::before {
content: 'Click 📝 | 2x❌';
position: absolute;
right: 0;
top: 0;
color: white;
background-color: rgb(255, 87, 87);
background-color: rgb(255, 188, 87);
padding: 3px;
transition: opacity 0.5s;
opacity: 0;
border-radius: 3px;
}
.removable-option:hover {
.interactable-option:hover {
transition: background-color 2s;
cursor: pointer;
}

View File

@@ -366,6 +366,28 @@ function showModalInput (title, message, btnCancel=getString('Gen_Cancel'), btnO
$('#modal-input').modal('show');
}
// -----------------------------------------------------------------------------
function showModalFieldInput (title, message, btnCancel=getString('Gen_Cancel'), btnOK=getString('Gen_Okay'), curValue="", callbackFunction=null) {
// set captions
prefix = 'modal-field-input'
$(`#${prefix}-title`).html (title);
$(`#${prefix}-message`).html (message);
$(`#${prefix}-cancel`).html (btnCancel);
$(`#${prefix}-OK`).html (btnOK);
if ( callbackFunction != null)
{
modalCallbackFunction = callbackFunction;
}
$(`#modal-field-input-field`).val(curValue)
// Show modal
$(`#${prefix}`).modal('show');
}
// -----------------------------------------------------------------------------
function modalDefaultOK () {
// Hide modal

View File

@@ -185,12 +185,43 @@
// -------------------------------------------------------------------
// Function to initialize remove functionality on select options
function initRemoveBtnOptn(selectorId) {
let isDoubleClick = false;
function initListInteractionOptions(selectorId) {
$(`#${selectorId} option`).addClass('interactable-option')
// Attach double-click event listeners to "Remove"
$(`#${selectorId} option`).addClass('removable-option').on('dblclick', function() {
$(`#${selectorId} option`).on('dblclick', function() {
isDoubleClick = true;
const $option = $(this);
removeOptionItem($option);
});
$(`#${selectorId} option`).on('click', function() {
const $option = $(this);
// Reset the flag after a short delay
setTimeout(() => {
console.log(isDoubleClick);
if (!isDoubleClick) {
// Single-click action
showModalFieldInput (
`<i class="fa fa-square-plus pointer"></i> ${getString('DevDetail_button_AddIcon')}`,
getString('DevDetail_button_AddIcon_Help'),
getString('Gen_Cancel'),
getString('Gen_Okay'),
$option.html(),
function() {
alert('aaa');
});
isDoubleClick = false;
}
}, 300); // Adjust this delay as needed
});
}
@@ -198,3 +229,9 @@ function initRemoveBtnOptn(selectorId) {

View File

@@ -94,7 +94,7 @@
</div>
</div>
<!-- Modal input -->
<!-- Modal textarea input -->
<div class="modal modal-warning fade" id="modal-input" style="display: none;">
<div class="modal-dialog">
<div class="modal-content">
@@ -118,6 +118,30 @@
</div>
<!-- Modal field input -->
<div class="modal modal-warning fade" id="modal-field-input" style="display: none;">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 id="modal-field-input-title" class="modal-title"> Modal Title </h4>
</div>
<div id="modal-field-input-message" class="modal-body"> Modal message </div>
<input id="modal-field-input-field" class="modal-field-input" type="text" ></input>
<div class="modal-footer">
<button id="modal-field-input-cancel" type="button" class="btn btn-outline pull-left" style="min-width: 80px;" data-dismiss="modal"> Cancel </button>
<button id="modal-field-input-OK" type="button" class="btn btn-outline" style="min-width: 80px;" onclick="modalDefaultInput()"> OK </button>
</div>
</div>
</div>
</div>
<!-- Alert float -->
<div id="notification" class="alert alert-dimissible pa_alert_notification">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>

View File

@@ -20,7 +20,7 @@ sys.path.extend([f"{INSTALL_PATH}/front/plugins", f"{INSTALL_PATH}/server"])
from plugin_helper import Plugin_Object, Plugin_Objects, decodeBase64
from logger import mylog, append_line_to_file
from helper import timeNowTZ, get_setting_value
from helper import timeNowTZ, get_setting_value, extract_between_strings, extract_ip_addresses, extract_mac_addresses
from const import logPath, applicationPath, fullDbPath
from database import DB
from device import Device_obj
@@ -52,20 +52,20 @@ def main():
unique_devices = execute_scan(subnets, timeout)
mylog('verbose', [f'[{pluginName}] Unknown devices count: {len(unique_devices)}'])
mylog('verbose', [f'[{pluginName}] Devices found: {len(unique_devices)}'])
for device in unique_devices:
plugin_objects.add_object(
# "MAC", "IP", "Name", "Vendor", "Interface"
primaryId = device[0],
secondaryId = device[1],
watched1 = device[2],
watched2 = device[3],
watched3 = device[4],
primaryId = device['mac'],
secondaryId = device['ip'],
watched1 = device['name'],
watched2 = device['vendor'],
watched3 = device['interface'],
watched4 = '',
extra = '',
foreignKey = device[0])
foreignKey = device['mac'])
plugin_objects.write_result_file()
@@ -85,33 +85,29 @@ def execute_scan (subnets_list, timeout):
# scan each interface
for interface in subnets_list:
nmap_output = execute_scan_on_interface(interface, timeout)
mylog('verbose', [f'[{pluginName}] nmap_output: ', nmap_output])
scan_output = execute_scan_on_interface (interface, timeout)
if nmap_output is not None:
nmap_output_ent = nmap_output.split('Nmap scan report for')
# loop thru entries for individual devices
for ent in nmap_output_ent:
mylog('verbose', [f'[{pluginName}] scan_output: ', scan_output])
lines = ent.split('\n')
if len(lines) >= 3:
# lines[0] can be DESKTOP-DIHOG0E.localdomain (192.168.1.121) or 192.168.1.255
# lines[1] can be Host is up (0.21s latency).
# lines[2] can be MAC Address: 6C:4A:4A:7B:4A:43 (Motorola Mobility, a Lenovo Company)
# Regular expression patterns
entry_pattern = r'Nmap scan report for (.*?) \((\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\)'
mac_pattern = r'MAC Address: ([0-9A-Fa-f:]+)'
vendor_pattern = r'\((.*?)\)'
ip_address = extract_ip_addresses(lines[0])[0]
host_name = extract_between_strings(lines[0], ' ', ' ')
vendor = extract_between_strings(lines[2], '(', ')')
mac_addresses = extract_mac_addresses(lines[2])
# Compile regular expression patterns
entry_regex = re.compile(entry_pattern)
mac_regex = re.compile(mac_pattern)
vendor_regex = re.compile(vendor_pattern)
# Find all matches
entries = entry_regex.findall(scan_output)
mac_addresses = mac_regex.findall(scan_output)
vendors = vendor_regex.findall(scan_output)
for i in range(len(entries)):
name, ip_address = entries[i]
devices_list.append([mac_addresses[i], ip_address, name, vendors[i], interface])
if len(mac_addresses) == 1:
devices_list.append({'name': host_name, 'ip': ip_address, 'mac': mac_addresses[0], 'vendor': vendor, 'interface': interface})
return devices_list

View File

@@ -441,11 +441,11 @@ while ($row = $result -> fetchArray (SQLITE3_ASSOC)) {
<input class="form-control" id="ipInterface" type="text" placeholder="eth0" />
</div>
<div class="col-xs-3">
<button class="btn btn-primary" onclick="addInterface();initRemoveBtnOptn('${codeName}')">Add</button>
<button class="btn btn-primary" onclick="addInterface();initListInteractionOptions('${codeName}')">Add</button>
</div>
</div>
<div class="form-group">
<select class="form-control" my-data-type="${setType}" name="${codeName}" id="${codeName}" onchange="initRemoveBtnOptn(${codeName})" multiple readonly>`;
<select class="form-control" my-data-type="${setType}" name="${codeName}" id="${codeName}" onchange="initListInteractionOptions(${codeName})" multiple readonly>`;
options = createArray(val);
@@ -471,7 +471,7 @@ while ($row = $result -> fetchArray (SQLITE3_ASSOC)) {
<input class="form-control" type="text" id="${codeName}_input" placeholder="Enter value"/>
</div>
<div class="col-xs-3">
<button class="btn btn-primary" my-input-from="${codeName}_input" my-input-to="${codeName}" onclick="addList(this);initRemoveBtnOptn('${codeName}')">Add</button>
<button class="btn btn-primary" my-input-from="${codeName}_input" my-input-to="${codeName}" onclick="addList(this);initListInteractionOptions('${codeName}')">Add</button>
</div>
</div>
<div class="form-group">
@@ -523,7 +523,7 @@ while ($row = $result -> fetchArray (SQLITE3_ASSOC)) {
// init remove list item buttons
if(['subnets', 'list' ].includes(setType))
{
initRemoveBtnOptn(codeName)
initListInteractionOptions(codeName)
}
}

View File

@@ -659,6 +659,27 @@ def generate_mac_links (html, deviceUrl):
return html
#-------------------------------------------------------------------------------
def extract_between_strings(text, start, end):
start_index = text.find(start)
end_index = text.find(end, start_index + len(start))
if start_index != -1 and end_index != -1:
return text[start_index + len(start):end_index]
else:
return ""
#-------------------------------------------------------------------------------
def extract_mac_addresses(text):
mac_pattern = r"([0-9A-Fa-f]{2}(?:[:-][0-9A-Fa-f]{2}){5})"
mac_addresses = re.findall(mac_pattern, text)
return mac_addresses
#-------------------------------------------------------------------------------
def extract_ip_addresses(text):
ip_pattern = r"\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b"
ip_addresses = re.findall(ip_pattern, text)
return ip_addresses
#-------------------------------------------------------------------------------
# JSON methods
#-------------------------------------------------------------------------------