Compare commits

...

124 Commits
v2.52 ... v3.02

Author SHA1 Message Date
pucherot
9232f31778 Pi.Alert v3.02
#114 - Fixed: UNIQUE constraint failed with Local MAC
2021-04-24 11:48:11 +02:00
pucherot
9c324b1817 Installation Script 2021-04-23 22:05:47 +02:00
pucherot
25b5db0e23 Update pialert_install.sh 2021-04-23 19:35:51 +02:00
pucherot
2af9d1dd38 Pi.Alert 3.01
#106
2021-04-23 13:54:25 +02:00
pucherot
040216ce3c Pi.Alert 3.01 2021-04-22 23:10:49 +02:00
pucherot
99c29fe86b Pi.Alert 3.01 2021-04-22 23:03:59 +02:00
pucherot
27afadfcdc Pi.Alert 3.01
#106
2021-04-22 22:12:38 +02:00
pucherot
4342f0f212 Pi.Alert 3.01
#106
2021-04-22 22:03:48 +02:00
pucherot
405331d177 Pi.Alert 3.00 2021-04-22 19:55:00 +02:00
pucherot
ffe2851e4f Pi.Alert 3.00 2021-04-22 08:53:43 +02:00
pucherot
6ade5a4f63 Pi.Alert 3.00 2021-04-21 22:49:52 +02:00
pucherot
e39845afc0 Pi.Alert 3.00 2021-04-21 22:36:41 +02:00
pucherot
ffa1059b26 tar 3.0 2021-04-21 22:29:53 +02:00
pucherot
53eafb8c7b Update pialert_update.sh 2021-04-21 21:44:45 +02:00
pucherot
63b5346308 Pi.Alert 3.0 2021-04-21 21:37:34 +02:00
pucherot
9b87b4dfe4 DeviceDetails update 2021-04-21 20:46:16 +02:00
pucherot
5e250c3950 Update VERSIONS_HISTORY.md 2021-04-21 20:36:44 +02:00
pucherot
ee8979aa09 Update VERSIONS_HISTORY.md 2021-04-21 20:31:47 +02:00
pucherot
9dc9cd3f2b Update VERSIONS_HISTORY.md 2021-04-21 20:29:30 +02:00
pucherot
2f2063c515 Update VERSIONS_HISTORY.md 2021-04-21 19:56:35 +02:00
pucherot
2568703376 tar Pi.Alert 3.0 2021-04-21 19:29:49 +02:00
pucherot
4072bbf406 Pi.Alert 3.00 2021-04-21 19:23:35 +02:00
pucherot
10757f0717 Update RAMDOM_MAC.md 2021-04-17 15:23:20 +02:00
pucherot
b77f727ed5 Update pialert_install.sh 2021-04-11 20:54:21 +02:00
pucherot
fa21d28c90 Update README.md 2021-04-11 15:50:57 +02:00
pucherot
7cc9abf477 Update README.md 2021-04-11 15:50:05 +02:00
pucherot
62f76f8bae Update README.md 2021-04-11 15:49:17 +02:00
pucherot
e4a1fe741b Update INSTALL.md 2021-04-11 15:47:45 +02:00
pucherot
0394461e2e Update UNINSTALL.md 2021-04-11 15:42:09 +02:00
pucherot
b72405806e Create UNINSTALL.md 2021-04-11 14:49:00 +02:00
pucherot
044949dc88 Update pialert_uninstall.sh 2021-04-11 12:30:27 +02:00
pucherot
14665230ff Update pialert_uninstall.sh 2021-04-11 12:16:30 +02:00
pucherot
0fb4150c96 Update pialert_uninstall.sh 2021-04-11 11:52:21 +02:00
pucherot
018c43cdc4 Update pialert_uninstall.sh 2021-04-11 11:47:39 +02:00
pucherot
3b34a42f10 Update pialert_uninstall.sh 2021-04-11 11:43:01 +02:00
pucherot
faf12f4d18 Update pialert_uninstall.sh 2021-04-11 11:32:42 +02:00
pucherot
85e07c639d Uninstall script 2021-04-11 11:22:14 +02:00
pucherot
097e5e738e Update pialert_install.sh 2021-02-08 11:37:28 +01:00
pucherot
af93a12b8f tar update 2021-02-02 10:30:37 +01:00
pucherot
228078c07b Update pialert_update.sh 2021-02-02 10:14:38 +01:00
pucherot
f8014f1bf4 Update pialert_update.sh 2021-02-02 10:08:59 +01:00
pucherot
b6abdcb357 tar update 2021-02-02 09:57:36 +01:00
pucherot
8d1696bc19 Update pialert_install.sh 2021-02-02 07:40:55 +01:00
pucherot
88f656ade5 tar update 2021-02-01 22:52:55 +01:00
pucherot
a23b619951 Update deviceDetails.php 2021-02-01 22:46:37 +01:00
pucherot
471b63dd83 Update pialert_update.sh 2021-02-01 22:35:49 +01:00
pucherot
1e8cf244be Update pialert_update.sh 2021-02-01 22:28:27 +01:00
pucherot
6ad34c0ace Update pialert_update.sh 2021-02-01 22:24:32 +01:00
pucherot
62b1c314d6 Update pialert_update.sh 2021-02-01 22:15:14 +01:00
pucherot
0e5c2af981 v2.70 2021-02-01 21:30:51 +01:00
pucherot
2955ac6535 Headers 2021-02-01 09:26:32 +01:00
pucherot
e694ed0a43 get Local IP 2021-01-28 13:59:34 +01:00
pucherot
933ca8d0d8 Update pialert_install.sh 2021-01-28 13:53:03 +01:00
pucherot
a86d5a6a69 tar update 2021-01-28 11:38:10 +01:00
pucherot
0d5e665c3a Update pialert_install.sh 2021-01-28 11:23:54 +01:00
pucherot
4ec1599b0e tar update 2021-01-27 17:59:51 +01:00
pucherot
31ab202744 Update pialert_update.sh 2021-01-27 17:09:25 +01:00
pucherot
42de9abfe3 tar update 2021-01-27 17:03:37 +01:00
pucherot
462c6613fc Update pialert_update.sh
bugfix #55
2021-01-27 17:02:07 +01:00
pucherot
119d648a93 tar update 2021-01-27 16:56:15 +01:00
pucherot
8eb09bd556 Update INSTALL.md 2021-01-27 13:41:39 +01:00
pucherot
2bd61aface Update INSTALL.md 2021-01-27 11:35:25 +01:00
pucherot
cf0df99bf1 Update process doc 2021-01-27 11:31:12 +01:00
pucherot
534b98feaa Create pialert_update.sh 2021-01-27 11:21:15 +01:00
pucherot
b5b51d428f Update pialert_install.sh 2021-01-26 17:25:36 +01:00
pucherot
a4eb028801 Update pialert_install.sh 2021-01-26 16:16:02 +01:00
pucherot
42b6e99ada Update pialert_install.sh 2021-01-26 15:09:52 +01:00
pucherot
4495d3f56c Update pialert_install.sh 2021-01-26 14:59:56 +01:00
pucherot
6963e98c28 Update pialert_install.sh 2021-01-26 14:54:03 +01:00
pucherot
56c97bc7af Update INSTALL.md 2021-01-26 10:13:41 +01:00
pucherot
c053aa2d01 Update pialert_install.sh 2021-01-26 10:10:12 +01:00
pucherot
b973d13c83 Tar update 2021-01-25 22:57:28 +01:00
pucherot
ae28886b2f Tar v2.61 2021-01-25 22:45:29 +01:00
pucherot
ed0102b212 Update INSTALL.md 2021-01-25 22:38:52 +01:00
pucherot
dff7171d3c Update README.md 2021-01-25 22:36:56 +01:00
pucherot
4dd75fbd47 v2.61
Installation script
#46 - Changed My IP query hosts
2021-01-25 22:27:54 +01:00
pucherot
7583ad802b tar 2021-01-19 23:40:06 +01:00
pucherot
b1be970ff2 Update INSTALL.md 2021-01-19 23:28:36 +01:00
pucherot
581d9c1e9f Update README.md 2021-01-19 23:17:20 +01:00
pucherot
b38c2f5c16 Update VERSIONS_HISTORY.md 2021-01-19 23:16:18 +01:00
pucherot
d4b8f52138 v2.60 - Improved installation process 2021-01-19 23:11:01 +01:00
pucherot
b0138ef89f Doc 2021-01-18 22:42:27 +01:00
pucherot
d6a742c6da Update INSTALL.md 2021-01-18 22:23:10 +01:00
pucherot
43ed1376dc tar 2021-01-18 22:18:53 +01:00
pucherot
0a1ee8ba94 Merge branch 'main' of https://github.com/pucherot/Pi.Alert into main 2021-01-18 22:14:39 +01:00
pucherot
3501ebdf25 Update INSTALL.md 2021-01-18 22:12:40 +01:00
pucherot
9e45441bf5 index.html 2021-01-18 22:08:46 +01:00
pucherot
57105cb6a4 Separate install & tar folders 2021-01-18 21:38:18 +01:00
pucherot
df33d07915 separate tar and install folders 2021-01-18 19:41:02 +01:00
pucherot
9ab7e01255 Update INSTALL.md 2021-01-18 16:44:12 +01:00
pucherot
ecbd1a821a Update INSTALL.md 2021-01-18 16:36:37 +01:00
pucherot
5781bb5c71 Update INSTALL.md 2021-01-18 16:11:28 +01:00
pucherot
1c21a59a74 Update INSTALL.md 2021-01-18 16:09:34 +01:00
pucherot
9b73c3a424 Update INSTALL.md 2021-01-18 15:52:57 +01:00
pucherot
e5b3408377 Update INSTALL.md 2021-01-18 15:43:03 +01:00
pucherot
d3c2c8699f Update INSTALL.md 2021-01-18 12:54:07 +01:00
pucherot
b4acfff1b9 Code headers 2021-01-16 08:36:41 +01:00
pucherot
3d04cdbc57 Code headers 2021-01-16 08:32:39 +01:00
pucherot
e49dfc9c3d Update RAMDOM_MAC.md 2021-01-15 14:32:55 +01:00
pucherot
f3c8a5d407 Doc 2021-01-15 14:00:35 +01:00
pucherot
a2f23d37ec Update README.md 2021-01-15 13:19:54 +01:00
pucherot
cdb263e791 Update RAMDOM_MAC.md 2021-01-15 12:56:25 +01:00
pucherot
a983b374c9 Update INSTALL.md 2021-01-15 12:56:07 +01:00
pucherot
40844c721c Update DEVICE_MANAGEMENT.md 2021-01-15 12:55:36 +01:00
pucherot
90242c8f3b Update README.md 2021-01-15 12:54:19 +01:00
pucherot
5f73a286bb License 2021-01-15 12:44:37 +01:00
pucherot
f8564f4dd7 v2.56
BUGFIX #23
2021-01-15 09:12:52 +01:00
pucherot
78352ed5a4 Merge branch 'main' of https://github.com/pucherot/Pi.Alert into main 2021-01-14 22:35:13 +01:00
pucherot
bb4be279c8 Update front to use .conf 2021-01-14 22:33:34 +01:00
pucherot
9f73af8ce6 Update front to use .conf 2021-01-14 22:30:07 +01:00
pucherot
f6eedd84d8 Update INSTALL.md 2021-01-14 22:11:10 +01:00
pucherot
cd9a1ac22a Update INSTALL.md 2021-01-14 13:25:24 +01:00
pucherot
0e3f14dd9d v2.55 2021-01-14 12:45:11 +01:00
pucherot
dbe0a0548b v2.54 2021-01-13 12:38:51 +01:00
pucherot
e8f723d985 Bugfix #6 v2.54 2021-01-13 12:18:13 +01:00
pucherot
cc50d0f75e Update pialert.py 2021-01-13 08:30:06 +01:00
pucherot
a473845242 Merge pull request #9 from nebbywan/main
Add Python3 support at line 31 and fix case mismatch
2021-01-12 21:17:09 +01:00
Zach McDonough
bda526b202 Update pialert.py
Add support for Python3 @ line 31
Fix case mismatch @ line 1216
2021-01-12 09:26:46 -08:00
pucherot
9057e41ff8 Update INSTALL.md 2021-01-12 17:12:36 +01:00
pucherot
75bb53fdd1 Merge pull request #7 from derekpurdy/patch-1
Update INSTALL.md
2021-01-12 17:10:52 +01:00
Derek Purdy
e7ebd9bab5 Update INSTALL.md 2021-01-12 10:53:49 -05:00
pucherot
30aeab305d Tar 2021-01-11 18:17:40 +01:00
pucherot
3e6d9847be Update INSTALL.md 2021-01-11 17:17:44 +01:00
pucherot
3c34c822e7 Update INSTALL.md 2021-01-11 17:09:43 +01:00
47 changed files with 4499 additions and 1911 deletions

View File

View File

@@ -36,16 +36,18 @@ Up to three scanning methods are used:
## Components ## Components
The system consists of two parts: The system consists of two parts:
- **Back**, in charge of: ### Back
In charge of:
- Scan the network searching connected devices using the scanning methods - Scan the network searching connected devices using the scanning methods
described described
- Store the information in the DB - Store the information in the DB
- Report the changes detected by e-mail - Report the changes detected by e-mail
| ![Report 1][report1] | ![Report 2][report2] | | ![Report 1][report1] | ![Report 2][report2] |
| -------------------- | -------------------- | | -------------------- | -------------------- |
- **Front**, a web frontal that allows: ### Front
A web frontal that allows:
- Manage the devices inventory and the characteristics - Manage the devices inventory and the characteristics
- Display in a visual way all the information collected by the back - Display in a visual way all the information collected by the back
- Sessions - Sessions
@@ -65,21 +67,35 @@ The system consists of two parts:
# Installation # Installation
<!--- --------------------------------------------------------------------- ---> <!--- --------------------------------------------------------------------- --->
Initially designed to run on a Raspberry PI, probably it can run on many other Initially designed to run on a Raspberry Pi, probably it can run on many other
Linux distributions. Linux distributions.
- [Installation instructions](docs/INSTALL.md) - One-step Automated Install:
#### `curl -sSL https://github.com/pucherot/Pi.Alert/raw/main/install/pialert_install.sh | bash`
- [Installation Guide (step by step)](docs/INSTALL.md)
## Device Management # Update
<!--- --------------------------------------------------------------------- ---> <!--- --------------------------------------------------------------------- --->
- One-step Automated Update:
#### `curl -sSL https://github.com/pucherot/Pi.Alert/raw/main/install/pialert_update.sh | bash`
# Uninstall process
<!--- --------------------------------------------------------------------- --->
- [Unistall process](docs/UNINSTALL.md)
# Device Management
<!--- --------------------------------------------------------------------- --->
- [Device Management instructions](docs/DEVICE_MANAGEMENT.md) - [Device Management instructions](docs/DEVICE_MANAGEMENT.md)
## Other useful info ## Other useful info
<!--- --------------------------------------------------------------------- ---> <!--- --------------------------------------------------------------------- --->
### [Versions History](docs/VERSIONS_HISTORY.md)
### Powered by: ### Powered by:
| Product | Objetive | | Product | Objetive |
| ------------ | -------------------------------------- | | ------------ | -------------------------------------- |
@@ -97,7 +113,7 @@ Linux distributions.
### License ### License
GPL 3.0 GPL 3.0
[Read more here](docs/LICENSE.txt) [Read more here](LICENSE.txt)
### Contact ### Contact
pi.alert.application@gmail.com pi.alert.application@gmail.com

View File

@@ -1,29 +0,0 @@
VERSION = '2.52'
VERSION_YEAR = '2021'
VERSION_DATE = '2021-01-11'
DB_PATH = '/home/pi/pialert/db/pialert.db'
LOG_PATH = '/home/pi/pialert/log'
VENDORS_DB = '/usr/share/arp-scan/ieee-oui.txt'
PA_FRONT_URL = 'http://pi.alert/deviceDetails.php?mac='
PRINT_LOG = False
SMTP_SERVER = 'smtp.gmail.com'
SMTP_PORT = 587
SMTP_USER = 'user@gmail.com'
SMTP_PASS = 'password'
REPORT_MAIL = False
REPORT_FROM = 'Pi.Alert <' + SMTP_USER +'>'
REPORT_TO = 'user@gmail.com'
DDNS_ACTIVE = False
DDNS_DOMAIN = 'your_domain.freeddns.org'
DDNS_USER = 'dynu_user'
DDNS_PASSWORD = 'A0000000B0000000C0000000D0000000'
DDNS_UPDATE_URL = 'https://api.dynu.com/nic/update?'
PIHOLE_ACTIVE = False
PIHOLE_DB = '/etc/pihole/pihole-FTL.db'
DHCP_ACTIVE = False
DHCP_LEASES = '/etc/pihole/dhcp.leases'

View File

@@ -1,7 +0,0 @@
#
# Pi.Alert cron
#
0 3 * * 1 python ~/pialert/back/pialert.py update_vendors >~/pialert/log/pialert.vendors.log 2>&1
*/1 * * * * python ~/pialert/back/pialert.py internet_IP >~/pialert/log/pialert.IP.log 2>&1
*/5 * * * * python ~/pialert/back/pialert.py 1 >~/pialert/log/pialert.1.log 2>&1
*/15 * * * * python ~/pialert/back/pialert.py 15 >~/pialert/log/pialert.15.log 2>&1

View File

@@ -1,8 +1,13 @@
#!/usr/bin/env python #!/usr/bin/env python
# #
# Pi.Alert v2.52 / 2021-01-11 #-------------------------------------------------------------------------------
# Puche 2020 # Pi.Alert v2.70 / 2021-02-01
# GNU GPLv3 # Open Source Network Guard / WIFI & LAN intrusion detector
#
# pialert.py - Back module. Network scanner
#-------------------------------------------------------------------------------
# Puche 2021 pi.alert.application@gmail.com GNU GPLv3
#-------------------------------------------------------------------------------
#=============================================================================== #===============================================================================
@@ -27,8 +32,15 @@ import csv
#=============================================================================== #===============================================================================
# CONFIG CONSTANTS # CONFIG CONSTANTS
#=============================================================================== #===============================================================================
PIALERT_PATH = os.path.dirname(os.path.abspath(__file__)) PIALERT_BACK_PATH = os.path.dirname(os.path.abspath(__file__))
execfile (PIALERT_PATH + "/pialert.conf") PIALERT_PATH = PIALERT_BACK_PATH + "/.."
if (sys.version_info > (3,0)):
exec(open(PIALERT_PATH + "/config/version.conf").read())
exec(open(PIALERT_PATH + "/config/pialert.conf").read())
else:
execfile (PIALERT_PATH + "/config/version.conf")
execfile (PIALERT_PATH + "/config/pialert.conf")
#=============================================================================== #===============================================================================
@@ -46,7 +58,6 @@ def main ():
print ('---------------------------------------------------------') print ('---------------------------------------------------------')
# Initialize global variables # Initialize global variables
# PIALERT_PATH = os.path.dirname(os.path.abspath(__file__))
log_timestamp = datetime.datetime.now() log_timestamp = datetime.datetime.now()
# DB # DB
@@ -68,6 +79,8 @@ def main ():
res = check_internet_IP() res = check_internet_IP()
elif cycle == 'update_vendors': elif cycle == 'update_vendors':
res = update_devices_MAC_vendors() res = update_devices_MAC_vendors()
elif cycle == 'update_vendors_silent':
res = update_devices_MAC_vendors('-s')
else : else :
res = scan_network() res = scan_network()
@@ -152,16 +165,19 @@ def check_internet_IP ():
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
def get_internet_IP (): def get_internet_IP ():
# BUGFIX #46 - curl http://ipv4.icanhazip.com repeatedly is very slow
# Using 'dig' # Using 'dig'
# dig_args = ['dig', '+short', 'myip.opendns.com', dig_args = ['dig', '+short', '-4', 'myip.opendns.com', '@resolver1.opendns.com']
# '@resolver1.opendns.com'] cmd_output = subprocess.check_output (dig_args, universal_newlines=True)
# Using 'curl' instead of 'dig' ## BUGFIX #12 - Query IPv4 address (not IPv6)
curl_args = ['curl', '-s', 'https://diagnostic.opendns.com/myip'] ## Using 'curl' instead of 'dig'
curl_output = subprocess.check_output (curl_args, universal_newlines=True) ## curl_args = ['curl', '-s', 'https://diagnostic.opendns.com/myip']
#curl_args = ['curl', '-s', QUERY_MYIP_SERVER]
#cmd_output = subprocess.check_output (curl_args, universal_newlines=True)
# Check result is an IP # Check result is an IP
IP = check_IP_format (curl_output) IP = check_IP_format (cmd_output)
return IP return IP
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
@@ -237,14 +253,14 @@ def check_IP_format (pIP):
#=============================================================================== #===============================================================================
# UPDATE DEVICE MAC VENDORS # UPDATE DEVICE MAC VENDORS
#=============================================================================== #===============================================================================
def update_devices_MAC_vendors (): def update_devices_MAC_vendors (pArg = ''):
# Header # Header
print ('Update HW Vendors') print ('Update HW Vendors')
print (' Timestamp:', startTime ) print (' Timestamp:', startTime )
# Update vendors DB (iab oui) # Update vendors DB (iab oui)
print ('\nUpdating vendors DB (iab & oui)...') print ('\nUpdating vendors DB (iab & oui)...')
update_args = ['sh', PIALERT_PATH + '/vendors_db_update.sh'] update_args = ['sh', PIALERT_BACK_PATH + '/update_vendors.sh', pArg]
update_output = subprocess.check_output (update_args) update_output = subprocess.check_output (update_args)
# DEBUG # DEBUG
# update_args = ['./vendors_db_update.sh'] # update_args = ['./vendors_db_update.sh']
@@ -292,9 +308,12 @@ def update_devices_MAC_vendors ():
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
def query_MAC_vendor (pMAC): def query_MAC_vendor (pMAC):
try : try :
# BUGFIX #6 - Fix pMAC parameter as numbers
pMACstr = str(pMAC)
# Check MAC parameter # Check MAC parameter
mac = pMAC.replace (':','') mac = pMACstr.replace (':','')
if len(pMAC) != 17 or len(mac) != 12 : if len(pMACstr) != 17 or len(mac) != 12 :
return -2 return -2
# Search vendor in HW Vendors DB # Search vendor in HW Vendors DB
@@ -355,7 +374,7 @@ def scan_network ():
read_DHCP_leases () read_DHCP_leases ()
# Load current scan data # Load current scan data
print ('\nProcesising scan results...') print ('\nProcessing scan results...')
print_log ('Save scanned devices') print_log ('Save scanned devices')
save_scanned_devices (arpscan_devices, cycle_interval) save_scanned_devices (arpscan_devices, cycle_interval)
@@ -378,6 +397,10 @@ def scan_network ():
print (' Updating Devices Info...') print (' Updating Devices Info...')
update_devices_data_from_scan () update_devices_data_from_scan ()
# Resolve devices names
print_log (' Resolve devices names...')
update_devices_names()
# Void false connection - disconnections # Void false connection - disconnections
print (' Voiding false (ghost) disconnections...') print (' Voiding false (ghost) disconnections...')
void_ghost_disconnections () void_ghost_disconnections ()
@@ -422,20 +445,22 @@ def query_ScanCycle_Data (pOpenCloseDB = False):
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
def execute_arpscan (pRetries): def execute_arpscan (pRetries):
# Prepara command arguments
arpscan_args = ['sudo', 'arp-scan', '--localnet', '--ignoredups', # #101 - arp-scan subnet configuration
'--retry=' + str(pRetries)] # Prepare command arguments
subnets = SCAN_SUBNETS.strip().split()
arpscan_args = ['sudo', 'arp-scan', '--ignoredups', '--retry=' + str(pRetries)] + subnets
# arpscan_args = ['sudo', 'arp-scan', SCAN_SUBNETS, '--ignoredups', '--retry=' + str(pRetries)]
# print (arpscan_args)
# TESTING - Fast Scan # TESTING - Fast Scan
# arpscan_args = ['sudo', 'arp-scan', '--localnet', '--ignoredups', # arpscan_args = ['sudo', 'arp-scan', '--localnet', '--ignoredups', '--retry=1']
# '--retry=1']
# DEBUG - arp-scan command # DEBUG - arp-scan command
# print (" ".join (arpscan_args)) # print (" ".join (arpscan_args))
# Execute command # Execute command
arpscan_output = subprocess.check_output (arpscan_args, arpscan_output = subprocess.check_output (arpscan_args, universal_newlines=True)
universal_newlines=True)
# Search IP + MAC + Vendor as regular expresion # Search IP + MAC + Vendor as regular expresion
re_ip = r'(?P<ip>((2[0-5]|1[0-9]|[0-9])?[0-9]\.){3}((2[0-5]|1[0-9]|[0-9])?[0-9]))' re_ip = r'(?P<ip>((2[0-5]|1[0-9]|[0-9])?[0-9]\.){3}((2[0-5]|1[0-9]|[0-9])?[0-9]))'
@@ -447,8 +472,28 @@ def execute_arpscan (pRetries):
devices_list = [device.groupdict() devices_list = [device.groupdict()
for device in re.finditer (re_pattern, arpscan_output)] for device in re.finditer (re_pattern, arpscan_output)]
# Bugfix #5 - Delete duplicated MAC's with different IP's
# TEST - Force duplicated device
# devices_list.append(devices_list[0])
# Delete duplicate MAC
unique_mac = []
unique_devices = []
for device in devices_list :
if device['mac'] not in unique_mac:
unique_mac.append(device['mac'])
unique_devices.append(device)
# DEBUG
# print (devices_list)
# print (unique_mac)
# print (unique_devices)
# print (len(devices_list))
# print (len(unique_mac))
# print (len(unique_devices))
# return list # return list
return devices_list return unique_devices
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
def copy_pihole_network (): def copy_pihole_network ():
@@ -532,6 +577,34 @@ def save_scanned_devices (p_arpscan_devices, p_cycle_interval):
(int(startTime.strftime('%s')) - 60 * p_cycle_interval), (int(startTime.strftime('%s')) - 60 * p_cycle_interval),
cycle) ) cycle) )
# Check Internet connectivity
internet_IP = get_internet_IP()
# TESTING - Force IP
# internet_IP = ""
if internet_IP != "" :
sql.execute ("""INSERT INTO CurrentScan (cur_ScanCycle, cur_MAC, cur_IP, cur_Vendor, cur_ScanMethod)
VALUES (?, 'Internet', ?, Null, 'queryDNS') """, (cycle, internet_IP) )
# #76 Add Local MAC of default local interface
# BUGFIX #106 - Device that pialert is running
# local_mac_cmd = ["bash -lc ifconfig `ip route list default | awk {'print $5'}` | grep ether | awk '{print $2}'"]
# local_mac_cmd = ["/sbin/ifconfig `ip route list default | sort -nk11 | head -1 | awk {'print $5'}` | grep ether | awk '{print $2}'"]
local_mac_cmd = ["/sbin/ifconfig `ip -o route get 1 | sed 's/^.*dev \\([^ ]*\\).*$/\\1/;q'` | grep ether | awk '{print $2}'"]
local_mac = subprocess.Popen (local_mac_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate()[0].decode().strip()
# local_dev_cmd = ["ip -o route get 1 | sed 's/^.*dev \\([^ ]*\\).*$/\\1/;q'"]
# local_dev = subprocess.Popen (local_dev_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate()[0].decode().strip()
# local_ip_cmd = ["ip route list default | awk {'print $7'}"]
local_ip_cmd = ["ip -o route get 1 | sed 's/^.*src \\([^ ]*\\).*$/\\1/;q'"]
local_ip = subprocess.Popen (local_ip_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate()[0].decode().strip()
# Check if local mac has been detected with other methods
sql.execute ("SELECT COUNT(*) FROM CurrentScan WHERE cur_ScanCycle = ? AND cur_MAC = ? ", (cycle, local_mac) )
if sql.fetchone()[0] == 0 :
sql.execute ("INSERT INTO CurrentScan (cur_ScanCycle, cur_MAC, cur_IP, cur_Vendor, cur_ScanMethod) "+
"VALUES ( ?, ?, ?, Null, 'local_MAC') ", (cycle, local_mac, local_ip) )
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
def print_scan_stats (): def print_scan_stats ():
# Devices Detected # Devices Detected
@@ -684,16 +757,39 @@ def create_new_devices ():
# DHCP Leases - Create New Devices # DHCP Leases - Create New Devices
print_log ('New devices - 6 DHCP Leases Create devices') print_log ('New devices - 6 DHCP Leases Create devices')
sql.execute ("""INSERT INTO Devices (dev_MAC, dev_name, dev_Vendor, # BUGFIX #23 - Duplicated MAC in DHCP.Leases
dev_LastIP, dev_FirstConnection, dev_LastConnection, # TEST - Force Duplicated MAC
# sql.execute ("""INSERT INTO DHCP_Leases VALUES
# (1610700000, 'TEST1', '10.10.10.1', 'Test 1', '*')""")
# sql.execute ("""INSERT INTO DHCP_Leases VALUES
# (1610700000, 'TEST2', '10.10.10.2', 'Test 2', '*')""")
sql.execute ("""INSERT INTO Devices (dev_MAC, dev_name, dev_LastIP,
dev_Vendor, dev_FirstConnection, dev_LastConnection,
dev_ScanCycle, dev_AlertEvents, dev_AlertDeviceDown, dev_ScanCycle, dev_AlertEvents, dev_AlertDeviceDown,
dev_PresentLastScan) dev_PresentLastScan)
SELECT DHCP_MAC, DHCP_Name, '(unknown)', DHCP_IP, ?, ?, SELECT DISTINCT DHCP_MAC,
1, 1, 0, 1 (SELECT DHCP_Name FROM DHCP_Leases AS D2
FROM DHCP_Leases WHERE D2.DHCP_MAC = D1.DHCP_MAC
ORDER BY DHCP_DateTime DESC LIMIT 1),
(SELECT DHCP_IP FROM DHCP_Leases AS D2
WHERE D2.DHCP_MAC = D1.DHCP_MAC
ORDER BY DHCP_DateTime DESC LIMIT 1),
'(unknown)', ?, ?, 1, 1, 0, 1
FROM DHCP_Leases AS D1
WHERE NOT EXISTS (SELECT 1 FROM Devices WHERE NOT EXISTS (SELECT 1 FROM Devices
WHERE dev_MAC = DHCP_MAC) """, WHERE dev_MAC = DHCP_MAC) """,
(startTime, startTime) ) (startTime, startTime) )
# sql.execute ("""INSERT INTO Devices (dev_MAC, dev_name, dev_Vendor,
# dev_LastIP, dev_FirstConnection, dev_LastConnection,
# dev_ScanCycle, dev_AlertEvents, dev_AlertDeviceDown,
# dev_PresentLastScan)
# SELECT DHCP_MAC, DHCP_Name, '(unknown)', DHCP_IP, ?, ?,
# 1, 1, 0, 1
# FROM DHCP_Leases
# WHERE NOT EXISTS (SELECT 1 FROM Devices
# WHERE dev_MAC = DHCP_MAC) """,
# (startTime, startTime) )
print_log ('New Devices end') print_log ('New Devices end')
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
@@ -842,13 +938,90 @@ def update_devices_data_from_scan ():
print_log ('Update devices end') print_log ('Update devices end')
#-------------------------------------------------------------------------------
# Feature #43 - Resoltion name for unknown devices
def update_devices_names ():
# Initialize variables
recordsToUpdate = []
ignored = 0
notFound = 0
# Devices without name
print (' Trying to resolve devices without name...', end='')
# BUGFIX #97 - Updating name of Devices w/o IP
for device in sql.execute ("SELECT * FROM Devices WHERE dev_Name IN ('(unknown)','') AND dev_LastIP <> '-'") :
# Resolve device name
newName = resolve_device_name (device['dev_MAC'], device['dev_LastIP'])
if newName == -1 :
notFound += 1
elif newName == -2 :
ignored += 1
else :
recordsToUpdate.append ([newName, device['dev_MAC']])
# progress bar
print ('.', end='')
sys.stdout.flush()
# Print log
print ('')
print (" Names updated: ", len(recordsToUpdate) )
# DEBUG - print list of record to update
# print (recordsToUpdate)
# update devices
sql.executemany ("UPDATE Devices SET dev_Name = ? WHERE dev_MAC = ? ", recordsToUpdate )
# DEBUG - print number of rows updated
# print (sql.rowcount)
#-------------------------------------------------------------------------------
def resolve_device_name (pMAC, pIP):
try :
pMACstr = str(pMAC)
# Check MAC parameter
mac = pMACstr.replace (':','')
if len(pMACstr) != 17 or len(mac) != 12 :
return -2
# DEBUG
# print (pMAC, pIP)
# Resolve name with DIG
dig_args = ['dig', '+short', '-x', pIP]
newName = subprocess.check_output (dig_args, universal_newlines=True)
# Check returns
newName = newName.strip()
if len(newName) == 0 :
return -2
# Eliminate local domain
if newName.endswith('.') :
newName = newName[:-1]
if newName.endswith('.lan') :
newName = newName[:-4]
if newName.endswith('.local') :
newName = newName[:-6]
if newName.endswith('.home') :
newName = newName[:-5]
# Return newName
return newName
# not Found
except subprocess.CalledProcessError :
return -1
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
def void_ghost_disconnections (): def void_ghost_disconnections ():
# Void connect ghost events (disconnect event exists in last X min.) # Void connect ghost events (disconnect event exists in last X min.)
print_log ('Void - 1 Connect ghost events') print_log ('Void - 1 Connect ghost events')
sql.execute ("""UPDATE Events SET eve_PairEventRowid = Null, sql.execute ("""UPDATE Events SET eve_PairEventRowid = Null,
eve_EventType ='VOIDED - ' || eve_EventType eve_EventType ='VOIDED - ' || eve_EventType
WHERE eve_EventType = 'Connected' WHERE eve_MAC != 'Internet'
AND eve_EventType = 'Connected'
AND eve_DateTime = ? AND eve_DateTime = ?
AND eve_MAC IN ( AND eve_MAC IN (
SELECT Events.eve_MAC SELECT Events.eve_MAC
@@ -867,7 +1040,8 @@ def void_ghost_disconnections ():
# Void connect paired events # Void connect paired events
print_log ('Void - 2 Paired events') print_log ('Void - 2 Paired events')
sql.execute ("""UPDATE Events SET eve_PairEventRowid = Null sql.execute ("""UPDATE Events SET eve_PairEventRowid = Null
WHERE eve_PairEventRowid IN ( WHERE eve_MAC != 'Internet'
AND eve_PairEventRowid IN (
SELECT Events.RowID SELECT Events.RowID
FROM CurrentScan, Devices, ScanCycles, Events FROM CurrentScan, Devices, ScanCycles, Events
WHERE cur_ScanCycle = ? WHERE cur_ScanCycle = ?
@@ -885,7 +1059,8 @@ def void_ghost_disconnections ():
print_log ('Void - 3 Disconnect ghost events') print_log ('Void - 3 Disconnect ghost events')
sql.execute ("""UPDATE Events SET eve_PairEventRowid = Null, sql.execute ("""UPDATE Events SET eve_PairEventRowid = Null,
eve_EventType = 'VOIDED - '|| eve_EventType eve_EventType = 'VOIDED - '|| eve_EventType
WHERE ROWID IN ( WHERE eve_MAC != 'Internet'
AND ROWID IN (
SELECT Events.RowID SELECT Events.RowID
FROM CurrentScan, Devices, ScanCycles, Events FROM CurrentScan, Devices, ScanCycles, Events
WHERE cur_ScanCycle = ? WHERE cur_ScanCycle = ?
@@ -993,12 +1168,12 @@ def email_reporting ():
openDB() openDB()
# Open text Template # Open text Template
template_file = open(PIALERT_PATH + '/report_template.txt', 'r') template_file = open(PIALERT_BACK_PATH + '/report_template.txt', 'r')
mail_text = template_file.read() mail_text = template_file.read()
template_file.close() template_file.close()
# Open html Template # Open html Template
template_file = open(PIALERT_PATH + '/report_template.html', 'r') template_file = open(PIALERT_BACK_PATH + '/report_template.html', 'r')
mail_html = template_file.read() mail_html = template_file.read()
template_file.close() template_file.close()
@@ -1043,7 +1218,7 @@ def email_reporting ():
eventAlert['eve_EventType'], eventAlert['eve_DateTime'], eventAlert['eve_EventType'], eventAlert['eve_DateTime'],
eventAlert['eve_IP'], eventAlert['eve_AdditionalInfo']) eventAlert['eve_IP'], eventAlert['eve_AdditionalInfo'])
mail_html_Internet += html_line_template.format ( mail_html_Internet += html_line_template.format (
PA_FRONT_URL, eventAlert['eve_MAC'], REPORT_DEVICE_URL, eventAlert['eve_MAC'],
eventAlert['eve_EventType'], eventAlert['eve_DateTime'], eventAlert['eve_EventType'], eventAlert['eve_DateTime'],
eventAlert['eve_IP'], eventAlert['eve_AdditionalInfo']) eventAlert['eve_IP'], eventAlert['eve_AdditionalInfo'])
@@ -1071,7 +1246,7 @@ def email_reporting ():
eventAlert['eve_IP'], eventAlert['dev_Name'], eventAlert['eve_IP'], eventAlert['dev_Name'],
eventAlert['eve_AdditionalInfo']) eventAlert['eve_AdditionalInfo'])
mail_html_new_devices += html_line_template.format ( mail_html_new_devices += html_line_template.format (
PA_FRONT_URL, eventAlert['eve_MAC'], eventAlert['eve_MAC'], REPORT_DEVICE_URL, eventAlert['eve_MAC'], eventAlert['eve_MAC'],
eventAlert['eve_DateTime'], eventAlert['eve_IP'], eventAlert['eve_DateTime'], eventAlert['eve_IP'],
eventAlert['dev_Name'], eventAlert['eve_AdditionalInfo']) eventAlert['dev_Name'], eventAlert['eve_AdditionalInfo'])
@@ -1098,7 +1273,7 @@ def email_reporting ():
eventAlert['eve_MAC'], eventAlert['eve_DateTime'], eventAlert['eve_MAC'], eventAlert['eve_DateTime'],
eventAlert['eve_IP'], eventAlert['dev_Name']) eventAlert['eve_IP'], eventAlert['dev_Name'])
mail_html_devices_down += html_line_template.format ( mail_html_devices_down += html_line_template.format (
PA_FRONT_URL, eventAlert['eve_MAC'], eventAlert['eve_MAC'], REPORT_DEVICE_URL, eventAlert['eve_MAC'], eventAlert['eve_MAC'],
eventAlert['eve_DateTime'], eventAlert['eve_IP'], eventAlert['eve_DateTime'], eventAlert['eve_IP'],
eventAlert['dev_Name']) eventAlert['dev_Name'])
@@ -1128,7 +1303,7 @@ def email_reporting ():
eventAlert['eve_IP'], eventAlert['eve_EventType'], eventAlert['eve_IP'], eventAlert['eve_EventType'],
eventAlert['dev_Name'], eventAlert['eve_AdditionalInfo']) eventAlert['dev_Name'], eventAlert['eve_AdditionalInfo'])
mail_html_events += html_line_template.format ( mail_html_events += html_line_template.format (
PA_FRONT_URL, eventAlert['eve_MAC'], eventAlert['eve_MAC'], REPORT_DEVICE_URL, eventAlert['eve_MAC'], eventAlert['eve_MAC'],
eventAlert['eve_DateTime'], eventAlert['eve_IP'], eventAlert['eve_DateTime'], eventAlert['eve_IP'],
eventAlert['eve_EventType'], eventAlert['dev_Name'], eventAlert['eve_EventType'], eventAlert['dev_Name'],
eventAlert['eve_AdditionalInfo']) eventAlert['eve_AdditionalInfo'])
@@ -1210,7 +1385,7 @@ def write_file (pPath, pText):
file.close() file.close()
else: else:
file = open (pPath, 'w', encoding='utf-8') file = open (pPath, 'w', encoding='utf-8')
file.write (ptext) file.write (pText)
file.close() file.close()
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------

View File

@@ -1,3 +1,12 @@
<!-- ---------------------------------------------------------------------------
# Pi.Alert
# Open Source Network Guard / WIFI & LAN intrusion detector
#
# repot_template.html - Back module. Template to email reporting in HTML format
#-------------------------------------------------------------------------------
# Puche 2021 pi.alert.application@gmail.com GNU GPLv3
#--------------------------------------------------------------------------- -->
<html> <html>
<head> <head>
@@ -101,9 +110,9 @@
<td> <td>
<table width=100% border=0 bgcolor=#70AD47 cellpadding=5px cellspacing=0 style="border-collapse: collapse; font-size: 12px; font-weight: bold; color:#385723"> <table width=100% border=0 bgcolor=#70AD47 cellpadding=5px cellspacing=0 style="border-collapse: collapse; font-size: 12px; font-weight: bold; color:#385723">
<tr> <tr>
<td width=25% style="text-align:Left"> Puche <PIALERT_YEAR></td> <td width=25% style="text-align:Left"> <span style="display:inline-block; transform: rotate(180deg)">&copy;</span> <PIALERT_YEAR> Puche</td>
<td width=50% style="text-align:center"> Pi.Alert <PIALERT_VERSION> &nbsp; / &nbsp; <PIALERT_VERSION_DATE> </td> <td width=50% style="text-align:center"> Pi.Alert <PIALERT_VERSION> &nbsp; &nbsp; (<PIALERT_VERSION_DATE>) </td>
<td width=25% style="text-align:right"> GNU GPLv3</td> <td width=25% style="text-align:right"> GNU GPLv3</td>
</tr> </tr>
</table> </table>
</td> </td>

View File

@@ -24,4 +24,4 @@ Events
<TABLE_EVENTS> <TABLE_EVENTS>
</SECTION_EVENTS> </SECTION_EVENTS>
---------------------------------------------------------------------- ----------------------------------------------------------------------
Puche <PIALERT_YEAR> Pi.Alert <PIALERT_VERSION> / <PIALERT_VERSION_DATE> GNU GPLv3 (?) <PIALERT_YEAR> Puche Pi.Alert <PIALERT_VERSION> (<PIALERT_VERSION_DATE>) GNU GPLv3

62
back/update_vendors.sh Normal file
View File

@@ -0,0 +1,62 @@
#!/bin/sh
# ------------------------------------------------------------------------------
# Pi.Alert
# Open Source Network Guard / WIFI & LAN intrusion detector
#
# update_vendors.sh - Back module. IEEE Vendors db update
# ------------------------------------------------------------------------------
# Puche 2021 pi.alert.application@gmail.com GNU GPLv3
# ------------------------------------------------------------------------------
# ----------------------------------------------------------------------
# Main directories to update:
# /usr/share/arp-scan
# /usr/share/ieee-data
# /var/lib/ieee-data
# ----------------------------------------------------------------------
# ----------------------------------------------------------------------
echo Updating... /usr/share/ieee-data/
cd /usr/share/ieee-data/
sudo mkdir -p 2_backup
sudo cp *.txt 2_backup
sudo cp *.csv 2_backup
sudo curl $1 -# -O http://standards-oui.ieee.org/iab/iab.csv
sudo curl $1 -# -O http://standards-oui.ieee.org/iab/iab.txt
sudo curl $1 -# -O http://standards-oui.ieee.org/oui28/mam.csv
sudo curl $1 -# -O http://standards-oui.ieee.org/oui28/mam.txt
sudo curl $1 -# -O http://standards-oui.ieee.org/oui36/oui36.csv
sudo curl $1 -# -O http://standards-oui.ieee.org/oui36/oui36.txt
sudo curl $1 -# -O http://standards-oui.ieee.org/oui/oui.csv
sudo curl $1 -# -O http://standards-oui.ieee.org/oui/oui.txt
# ----------------------------------------------------------------------
echo ""
echo Updating... /usr/share/arp-scan/
cd /usr/share/arp-scan
sudo mkdir -p 2_backup
sudo cp *.txt 2_backup
# Update from /usb/lib/ieee-data
sudo get-iab -v
sudo get-oui -v
# Update from ieee website
# sudo get-iab -v -u http://standards-oui.ieee.org/iab/iab.txt
# sudo get-oui -v -u http://standards-oui.ieee.org/oui/oui.txt
# Update from ieee website develop
# sudo get-iab -v -u http://standards.ieee.org/develop/regauth/iab/iab.txt
# sudo get-oui -v -u http://standards.ieee.org/develop/regauth/oui/oui.txt
# Update from Sanitized oui (linuxnet.ca)
# sudo get-oui -v -u https://linuxnet.ca/ieee/oui.txt

View File

@@ -1,54 +0,0 @@
#!/bin/sh
#
# Update MAC Vendor DB
#
# /usr/share/arp-scan
# /usr/share/ieee-data
# /var/lib/ieee-data
# ----------------------------------------------------------------------
# ----------------------------------------------------------------------
echo Updating... /usr/share/ieee-data/
cd /usr/share/ieee-data/
sudo mkdir -p 2_backup
sudo cp *.txt 2_backup
sudo cp *.csv 2_backup
sudo curl -# -O http://standards-oui.ieee.org/iab/iab.csv
sudo curl -# -O http://standards-oui.ieee.org/iab/iab.txt
sudo curl -# -O http://standards-oui.ieee.org/oui28/mam.csv
sudo curl -# -O http://standards-oui.ieee.org/oui28/mam.txt
sudo curl -# -O http://standards-oui.ieee.org/oui36/oui36.csv
sudo curl -# -O http://standards-oui.ieee.org/oui36/oui36.txt
sudo curl -# -O http://standards-oui.ieee.org/oui/oui.csv
sudo curl -# -O http://standards-oui.ieee.org/oui/oui.txt
# ----------------------------------------------------------------------
echo ""
echo Updating... /usr/share/arp-scan/
cd /usr/share/arp-scan
sudo mkdir -p 2_backup
sudo cp *.txt 2_backup
# Update from /usb/lib/ieee-data
sudo get-iab -v
sudo get-oui -v
# Update from ieee website
# sudo get-iab -v -u http://standards-oui.ieee.org/iab/iab.txt
# sudo get-oui -v -u http://standards-oui.ieee.org/oui/oui.txt
# Update from ieee website develop
# sudo get-iab -v -u http://standards.ieee.org/develop/regauth/iab/iab.txt
# sudo get-oui -v -u http://standards.ieee.org/develop/regauth/oui/oui.txt
# Update from Sanitized oui (linuxnet.ca)
# sudo get-oui -v -u https://linuxnet.ca/ieee/oui.txt

50
config/pialert.conf Normal file
View File

@@ -0,0 +1,50 @@
#-------------------------------------------------------------------------------
# Pi.Alert
# Open Source Network Guard / WIFI & LAN intrusion detector
#
# pialert.conf - Back module. Configuration file
#-------------------------------------------------------------------------------
# Puche 2021 pi.alert.application@gmail.com GNU GPLv3
#-------------------------------------------------------------------------------
PIALERT_PATH = '/home/pi/pialert'
DB_PATH = PIALERT_PATH + '/db/pialert.db'
LOG_PATH = PIALERT_PATH + '/log'
VENDORS_DB = '/usr/share/arp-scan/ieee-oui.txt'
PRINT_LOG = False
SMTP_SERVER = 'smtp.gmail.com'
SMTP_PORT = 587
SMTP_USER = 'user@gmail.com'
SMTP_PASS = 'password'
REPORT_MAIL = False
REPORT_FROM = 'Pi.Alert <' + SMTP_USER +'>'
REPORT_TO = 'user@gmail.com'
REPORT_DEVICE_URL = 'http://pi.alert/deviceDetails.php?mac='
# QUERY_MYIP_SERVER = 'https://diagnostic.opendns.com/myip'
QUERY_MYIP_SERVER = 'http://ipv4.icanhazip.com'
DDNS_ACTIVE = False
DDNS_DOMAIN = 'your_domain.freeddns.org'
DDNS_USER = 'dynu_user'
DDNS_PASSWORD = 'A0000000B0000000C0000000D0000000'
DDNS_UPDATE_URL = 'https://api.dynu.com/nic/update?'
PIHOLE_ACTIVE = False
PIHOLE_DB = '/etc/pihole/pihole-FTL.db'
DHCP_ACTIVE = False
DHCP_LEASES = '/etc/pihole/dhcp.leases'
# arp-scan options & samples
#
# Scan local network (default)
# SCAN_SUBNETS = '--localnet'
#
# Scan two subnets
# SCAN_SUBNETS = '192.168.11.0/24 192.168.144.0/24'
#
# Scan using interface eth0
# SCAN_SUBNETS = '--localnet --interface=eth0'
SCAN_SUBNETS = '--localnet'

3
config/version.conf Normal file
View File

@@ -0,0 +1,3 @@
VERSION = '3.02'
VERSION_YEAR = '2021'
VERSION_DATE = '2021-04-24'

View File

Binary file not shown.

View File

@@ -79,7 +79,7 @@ decides to change the MAC).
### License ### License
GPL 3.0 GPL 3.0
[Read more here](LICENSE.txt) [Read more here](../LICENSE.txt)
### Contact ### Contact
pi.alert.application@gmail.com pi.alert.application@gmail.com

View File

@@ -1,9 +1,9 @@
# Pi.Alert Installation # Pi.Alert Installation Guide
<!--- --------------------------------------------------------------------- ---> <!--- --------------------------------------------------------------------- --->
Initially designed to run on a Raspberry PI, probably it can run on many other Initially designed to run on a Raspberry PI, probably it can run on many other
Linux distributions. Linux distributions.
Stimated time: 20' Estimated time: 20'
### Dependencies ### Dependencies
| Dependency | Comments | | Dependency | Comments |
@@ -14,188 +14,327 @@ Stimated time: 20'
| dnsmasq | Optional. Scan Method 3. Check devices using DHCP server | | dnsmasq | Optional. Scan Method 3. Check devices using DHCP server |
| IEEE HW DB | Necessary to identified Device vendor | | IEEE HW DB | Necessary to identified Device vendor |
# Installation process ## One-step Automated Install:
<!--- --------------------------------------------------------------------- --->
#### `curl -sSL https://github.com/pucherot/Pi.Alert/raw/main/install/pialert_install.sh | bash`
## One-step Automated Update:
<!--- --------------------------------------------------------------------- --->
#### `curl -sSL https://github.com/pucherot/Pi.Alert/raw/main/install/pialert_update.sh | bash`
## Uninstall process
<!--- --------------------------------------------------------------------- --->
- [Unistall process](./UNINSTALL.md)
## Installation process (step by step)
<!--- --------------------------------------------------------------------- ---> <!--- --------------------------------------------------------------------- --->
## Raspberry Setup ### Raspberry Setup
<!--- --------------------------------------------------------------------- ---> <!--- --------------------------------------------------------------------- --->
1 - Install 'Raspberry Pi OS' 1.1 - Install 'Raspberry Pi OS'
- Instructions https://www.raspberrypi.org/documentation/installation/installing-images/ - Instructions https://www.raspberrypi.org/documentation/installation/installing-images/
- *Lite version (without Descktop) is enough for Pi.Alert* - *Lite version (without Desktop) is enough for Pi.Alert*
2 - Activate ssh 1.2 - Activate ssh
- Create a empty file with name 'ssh' in the boot partition of the SD - Create a empty file with name 'ssh' in the boot partition of the SD
3 - Start the raspberry 1.3 - Start the raspberry
4 - Login to the system with pi user 1.4 - Login to the system with pi user
``` ```
user: pi user: pi
password: raspberry password: raspberry
``` ```
5 - Change de default password of pi user 1.5 - Change the default password of pi user
``` ```
passwd passwd
``` ```
6 - Setup the basic configuration 1.6 - Setup the basic configuration
``` ```
sudo raspi-config sudo raspi-config
``` ```
7 - Optionally, configure a static IP in raspi-config 1.7 - Optionally, configure a static IP in raspi-config
8 - Update the OS 1.8 - Update the OS
``` ```
sudo apt-get update sudo apt-get update
sudo apt-get upgrade sudo apt-get upgrade
sudo reboot sudo shutdown -r now
``` ```
## Pi-hole Setup
### Pi-hole Setup (optional)
<!--- --------------------------------------------------------------------- ---> <!--- --------------------------------------------------------------------- --->
1- Links & Doc 2.1 - Links & Doc
- https://pi-hole.net/ - https://pi-hole.net/
- https://github.com/pi-hole/pi-hole - https://github.com/pi-hole/pi-hole
- https://github.com/pi-hole/pi-hole/#one-step-automated-install - https://github.com/pi-hole/pi-hole/#one-step-automated-install
2 - Login to the system with pi user 2.2 - Login to the system with pi user
3 - Install Pi-hole 2.3 - Install Pi-hole
``` ```
curl -sSL https://install.pi-hole.net | bash curl -sSL https://install.pi-hole.net | bash
``` ```
- Mark "Install web admin interface" - Select "Install web admin interface"
- Mark "Install web server lighttpd" - Select "Install web server lighttpd"
4 - Configure Pi-hole admin password 2.4 - Configure Pi-hole admin password
``` ```
pihole -a -p PASSWORD pihole -a -p PASSWORD
``` ```
2.5 - Connect to web admin panel
```
hostname -I
```
or this one if have severals interfaces
```
ip -o route get 1 | sed 's/^.*src \([^ ]*\).*$/\1/;q'
```
5 - Connect to web admin panel
- http://192.168.1.x/admin/ - http://192.168.1.x/admin/
- (*replace the 192.168.1.x with your Raspberry IP*) - (*replace 192.168.1.x with your Raspberry IP*)
6 - Activate DHCP server 2.6 - Activate DHCP server
- Pi-hole -> Settings -> DHCP -> Mark "DHCP server enabled" - Pi-hole admin portal -> Settings -> DHCP -> Mark "DHCP server enabled"
7 - Add pi.alert DNS Record 2.7 - Add pi.alert DNS Record
- Pi-hole -> Local DNS -> DNS Records -> Add new domain /IP ```
hostname -I
```
or this one if have severals interfaces
```
ip -o route get 1 | sed 's/^.*src \([^ ]*\).*$/\1/;q'
```
- Pi-hole admin portal -> Local DNS -> DNS Records -> Add new domain /IP
- pi.alert 192.168.1.x - pi.alert 192.168.1.x
- (*replace the 192.168.1.x with your Raspberry IP*) - (*replace 192.168.1.x with your Raspberry IP*)
8 - Deactivate your current DHCP Server (*Normaly at your router or AP*) 2.8 - Deactivate your current DHCP Server (*usually at your router or AP*)
9 - Renew your computer IP to unsure you are using the new DHCP and DNS server 2.9 - Renew your computer IP to unsure you are using the new DHCP and DNS server
- Windows: cmd -> ipconfig /renew - Windows: cmd -> ipconfig /renew
- Linux: shell -> sudo dhclient -r; sudo dhclient - Linux: shell -> sudo dhclient -r; sudo dhclient
- Mac: Apple menu -> System Preferences -> Network -> Select the network -> - Mac: Apple menu -> System Preferences -> Network -> Select the network
Advanced -> TCP/IP -> Renew DHCP Lease -> Advanced -> TCP/IP -> Renew DHCP Lease
## arp-scan & Python
### Lighttpd & PHP
<!--- --------------------------------------------------------------------- ---> <!--- --------------------------------------------------------------------- --->
1 - Install arp-scan utility and test If you have installed Pi.hole, lighttpd and PHP are already installed and this
``` block is not necessary
sudo apt-get install arp-scan
3.1 - Install apt-utils
```
sudo apt-get install apt-utils -y
```
3.2 - Install lighttpd
```
sudo apt-get install lighttpd -y
```
3.3 - If Pi.Alert will be the only site available in this webserver, you can
redirect the default server page to pialert subfolder
```
sudo mv /var/www/html/index.lighttpd.html /var/www/html/index.lighttpd.html.old
sudo ln -s ~/pialert/install/index.html /var/www/html/index.html
```
3.4 - Install PHP
```
sudo apt-get install php php-cgi php-fpm php-sqlite3 -y
```
3.5 - Activate PHP
```
sudo lighttpd-enable-mod fastcgi-php
sudo service lighttpd restart
```
3.6 - Install sqlite3
```
sudo apt-get install sqlite3 -y
```
### arp-scan & Python
<!--- --------------------------------------------------------------------- --->
4.1 - Install arp-scan utility and test
```
sudo apt-get install arp-scan -y
sudo arp-scan -l sudo arp-scan -l
``` ```
2 - Install Python & packages 4.2 - Install dnsutils & net-tools utilities
``` ```
sudo apt-get install python-setuptools sudo apt-get install dnsutils net-tools -y
sudo apt install python-pip ```
pip install netaddr 4.3 - Test Python
pip install dpkt
pip install MacLookup New versions of 'Raspberry Pi OS' includes Python. You can check that
``` Python is installed with the command:
```
python -V
```
New versions of Ubuntu includes Python 3. You can choose between use `python3`
command or to install Python 2 (that includes `python` command).
## Pi.Alert If you prefer to use Python 3, in the next installation block, you must update
`pialert.cron` file with the correct command: `python3` instead of `python`.
```
python3 -V
```
4.4 - If Python is not installed in your system, you can install it with this
command:
```
sudo apt-get install python
```
Or this one if you prefer Python 3:
```
sudo apt-get install python3
```
### Pi.Alert
<!--- --------------------------------------------------------------------- ---> <!--- --------------------------------------------------------------------- --->
1- Download Pi.Alert and uncmompress 5.1 - Download Pi.Alert and uncompress
``` ```
curl -LO https://github.com/pucherot/Pi.Alert/raw/main/install/pialert_latest.tar cd
curl -LO https://github.com/pucherot/Pi.Alert/raw/main/tar/pialert_latest.tar
tar xvf pialert_latest.tar tar xvf pialert_latest.tar
rm pialert_latest.tar rm pialert_latest.tar
``` ```
2 - Public the front portal 5.2 - Public the front portal
``` ```
sudo ln -s /home/pi/pialert/front /var/www/html/pialert sudo ln -s ~/pialert/front /var/www/html/pialert
``` ```
3 - Update lighttp config 5.3 - Configure web server redirection
```
sudo sh -c "printf '\n\n\$HTTP[\"host\"] == \"pi.alert\" {\n server.document-root = \"/var/www/html/pialert/\"\n}\n' >> /etc/lighttpd/external.conf" If you have configured your DNS server (Pi.hole or other) to resolve pi.alert
with the IP of your raspberry, youy must configure lighttpd to redirect these
requests to the correct pialert web folder
```
sudo cp ~/pialert/install/pialert_front.conf /etc/lighttpd/conf-available
sudo ln -s ../conf-available/pialert_front.conf /etc/lighttpd/conf-enabled/pialert_front.conf
sudo /etc/init.d/lighttpd restart sudo /etc/init.d/lighttpd restart
``` ```
4 - If you want to use email reporting with gmail 5.4 - If you want to use email reporting with gmail
- Go to your Google Account https://myaccount.google.com/ - Go to your Google Account https://myaccount.google.com/
- On the left navigation panel, click Security - On the left navigation panel, click Security
- On the bottom of the page, in the Less secure app access panel, - On the bottom of the page, in the Less secure app access panel,
click Turn on access click Turn on access
- Click Save button - Click Save button
5 - Config Pialert parameters 5.5 - Config Pialert parameters
``` ```
nano ~/pialert/back/pialert.conf sed -i "s,'/home/pi/pialert','$HOME/pialert'," ~/pialert/config/pialert.conf
``` nano ~/pialert/config/pialert.conf
- if you want to use email reporting, configure this parameters ```
``` - If you want to use email reporting, configure this parameters
REPORT_MAIL = True ```ini
SMTP_USER = 'user@gmail.com' REPORT_MAIL = True
SMTP_PASS = 'password' REPORT_TO = 'user@gmail.com'
REPORT_TO = 'user@gmail.com' SMTP_SERVER = 'smtp.gmail.com'
``` SMTP_PORT = 587
SMTP_USER = 'user@gmail.com'
SMTP_PASS = 'password'
```
- if you want to update yout Dynamic DNS, configure this parameters - If you want to update your Dynamic DNS, configure this parameters
``` ```ini
DDNS_ACTIVE = True DDNS_ACTIVE = True
DDNS_DOMAIN = 'your_domain.freeddns.org' DDNS_DOMAIN = 'your_domain.freeddns.org'
DDNS_USER = 'dynu_user' DDNS_USER = 'dynu_user'
DDNS_PASSWORD = 'A0000000B0000000C0000000D0000000' DDNS_PASSWORD = 'A0000000B0000000C0000000D0000000'
DDNS_UPDATE_URL = 'https://api.dynu.com/nic/update?' DDNS_UPDATE_URL = 'https://api.dynu.com/nic/update?'
``` ```
- if you have installed Pi.hole and DHCP, activate this parameters - If you have installed Pi.hole and DHCP, activate this parameters
``` ```ini
PIHOLE_ACTIVE = True PIHOLE_ACTIVE = True
DHCP_ACTIVE = True DHCP_ACTIVE = True
``` ```
6 - Update vendors DB 5.6 - Update vendors DB
``` ```
python ~/pialert/back/pialert.py update_vendors python ~/pialert/back/pialert.py update_vendors
``` ```
or
```
python3 ~/pialert/back/pialert.py update_vendors
```
7 - Test Pi.Alert Scan 5.7 - Test Pi.Alert Scan
``` ```
python ~/pialert/back/pialert.py internet_IP python ~/pialert/back/pialert.py internet_IP
python ~/pialert/back/pialert.py 1 python ~/pialert/back/pialert.py 1
``` ```
or
```
python3 ~/pialert/back/pialert.py internet_IP
python3 ~/pialert/back/pialert.py 1
```
8 - Add crontab jobs 5.8 - Update crontab template with python3
```
(crontab -l 2>/dev/null; cat ~/pialert/back/pialert.cron) | crontab -
```
9 - Use admin panel to configure the devices If you prefer to use Python 3 (installed in the previous block), you must
update `pialert.cron` file with the correct command: `python3` instead of
`python`
```
sed -i 's/python/python3/g' ~/pialert/install/pialert.cron
```
5.9 - Add crontab jobs
```
(crontab -l 2>/dev/null; cat ~/pialert/install/pialert.cron) | crontab -
```
5.10 - Add permissions to the web-server user
```
sudo chgrp -R www-data ~/pialert/db
chmod -R 770 ~/pialert/db
```
5.11 - Check DNS record for pi.alert (explained in point 2.7 of Pi.hole
installation)
- Add pi.alert DNS Record
```
hostname -I
```
or this one if have severals interfaces
```
ip -o route get 1 | sed 's/^.*src \([^ ]*\).*$/\1/;q'
```
- Pi-hole admin portal -> Local DNS -> DNS Records -> Add new domain /IP
- pi.alert 192.168.1.x
- (*replace 192.168.1.x with your Raspberry IP*)
5.12 - Use admin panel to configure the devices
- http://pi.alert/ - http://pi.alert/
- http://192.168.1.x/pialert/
- (*replace 192.168.1.x with your Raspberry IP*)
## Device Management ### Device Management
<!--- --------------------------------------------------------------------- ---> <!--- --------------------------------------------------------------------- --->
- [Device Management instructions](./DEVICE_MANAGEMENT.md) - [Device Management instructions](./DEVICE_MANAGEMENT.md)
### License ### License
GPL 3.0 GPL 3.0
[Read more here](LICENSE.txt) [Read more here](../LICENSE.txt)
### Contact ### Contact
pi.alert.application@gmail.com pi.alert.application@gmail.com

View File

@@ -4,7 +4,7 @@
The latest versions of some operating systems (IOS and Android) incorporate a The latest versions of some operating systems (IOS and Android) incorporate a
new & interesting functionality to improve privacy: **Random MACs**. new & interesting functionality to improve privacy: **Random MACs**.
This functionality allows you to **hide the true MAC** of the device and This functionality allows you to **hide the real MAC** of the device and
**assign a random MAC** when we connect to WIFI networks. **assign a random MAC** when we connect to WIFI networks.
This behavior is especially useful when connecting to WIFI's that we do not This behavior is especially useful when connecting to WIFI's that we do not
@@ -16,12 +16,12 @@ WIFI's**, in this way, Pi.Alert will be able to identify the device, and it
will not identify it as a new device every so often (every time IOS or Android will not identify it as a new device every so often (every time IOS or Android
decides to change the MAC). decides to change the MAC).
### IOS ## IOS
![ios][ios] ![ios][ios]
- [Use private Wi-Fi addresses in iOS 14](https://support.apple.com/en-us/HT211227) - [Use private Wi-Fi addresses in iOS 14](https://support.apple.com/en-us/HT211227)
### Android ## Android
![Android][Android] ![Android][Android]
- [How to Disable MAC Randomization in Android 10](https://support.boingo.com/s/article/How-to-Disable-MAC-Randomization-in-Android-10-Android-Q) - [How to Disable MAC Randomization in Android 10](https://support.boingo.com/s/article/How-to-Disable-MAC-Randomization-in-Android-10-Android-Q)
@@ -30,7 +30,7 @@ decides to change the MAC).
### License ### License
GPL 3.0 GPL 3.0
[Read more here](LICENSE.txt) [Read more here](../LICENSE.txt)
### Contact ### Contact
pi.alert.application@gmail.com pi.alert.application@gmail.com

64
docs/UNINSTALL.md Normal file
View File

@@ -0,0 +1,64 @@
# Pi.Alert Uninstallation Guide
<!--- --------------------------------------------------------------------- --->
Estimated time: 5'
## One-step Automated Uninstall:
<!--- --------------------------------------------------------------------- --->
#### `curl -sSL https://github.com/pucherot/Pi.Alert/raw/main/install/pialert_uninstall.sh | bash`
## Uninstallation process (step by step)
<!--- --------------------------------------------------------------------- --->
1.1 - Remove Pi.Alert files
```
rm -r "~/pialert"
```
1.2 - Remove Pi.Alert web front
```
sudo rm "/var/www/html/pialert"
```
1.3 - Remove lighttpd Pi.Alert config
```
sudo rm "/etc/lighttpd/conf-available/pialert_front.conf"
sudo rm "/etc/lighttpd/conf-enabled/pialert_front.conf"
```
1.4 - Remove lighttpd Pi.Alert cache
```
sudo rm -r /var/cache/lighttpd/compress/pialert
```
1.5 - Remove Pi.Alert DNS entry
```
sudo sed -i '/pi.alert/d' /etc/pihole/custom.list
sudo pihole restartdns
```
1.6 - Remove Pi.Alert crontab jobs
```
crontab -l 2>/dev/null | sed ':a;N;$!ba;s/#-------------------------------------------------------------------------------\n# Pi.Alert\n# Open Source Network Guard \/ WIFI & LAN intrusion detector \n#\n# pialert.cron - Back module. Crontab jobs\n#-------------------------------------------------------------------------------\n# Puche 2021 pi.alert.application@gmail.com GNU GPLv3\n#-------------------------------------------------------------------------------//g' | crontab -
crontab -l 2>/dev/null | sed '/pialert.py/d' | crontab -
```
### Uninstallation Notes
<!--- --------------------------------------------------------------------- --->
- If you installed Pi-hole during the Pi.Alert installation process,
Pi-hole will still be available after uninstalling Pi.Alert
- lighttpd, PHP, arp-scan & Python have not been uninstalled
They may be required by other software
You can uninstall them manually with command 'apt-get remove XX'
### License
GPL 3.0
[Read more here](../LICENSE.txt)
### Contact
pi.alert.application@gmail.com

77
docs/VERSIONS_HISTORY.md Normal file
View File

@@ -0,0 +1,77 @@
# Pi.Alert Version History
<!--- --------------------------------------------------------------------- --->
| Version | Description |
| ------- | --------------------------------------------------------------- |
| v3.00 | Major set of New features & Enhancements |
| v2.70 | New features & Usability improvements in the web prontal |
| v2.61 | Bug fixing |
| v2.60 | Improved the compability of installation process (Ubuntu) |
| v2.56 | Bug fixing |
| v2.55 | Bug fixing |
| v2.52 | Bug fixing |
| v2.51 | Bug fixing |
| v2.50 | First public release |
## Pi.Alert v3.02
<!--- --------------------------------------------------------------------- --->
**PENDING UPDATE DOC**
- Fixed: UNIQUE constraint failed with Local MAC #114
## Pi.Alert v3.01
<!--- --------------------------------------------------------------------- --->
**PENDING UPDATE DOC**
- Fixed: Problem with local MAC & IP (raspberry) #106
## Pi.Alert v3.00
<!--- --------------------------------------------------------------------- --->
**PENDING UPDATE DOC**
- `arp-scan` config options: interface, several subnets. #101 #15
- Next/previos button while editing devices #66 #37
- Internet presence/sessions monitoring #63
- Logical delete / archive / hide Device #93
- Flag to mark device with random MAC's #87
- New Device Types predefined in combobox #92
- Ask before leave the page with unsaved changes #104
- Option to don't mark devices as new during installation #94
- Uninstall script #62
- Fixed: Error updating name of devices w/o IP #97
- Fixed: Deleted devices reappear #84
- Fixed: Device running Pi.Alert must be marked as "on-line" #76
- Fixed: Incorrect calculation of presence hours #102
- Fixed: Problem redirect to homepage clicking in logo #103
## Pi.Alert v2.70
<!--- --------------------------------------------------------------------- --->
- Added Client names resolution #43
- Added Check to mark devices as "known" #16
- Remember "Show XXX entries" dropdown value #16 #26
- Remember "sorting" in devices #16
- Remember "Device panel " in device detail #16
- Added "All" option to "Show x Entries" option #16
- Added optional Location field (Door, Basement, etc.) to devices #16
- "Device updated successfully" message now is not modal #16
- Now is possible to delete Devices #16
- Added Device Type Singleboard Computer (SBC) #16
- Allowed to use " in device name #42
## Pi.Alert v2.60
<!--- --------------------------------------------------------------------- --->
- `pialert.conf` moved from `back` to `config` folder
- `pialert.conf` splitted in two files: `pialert.conf` and `version.conf`
- Added compatibility with Python 3 (default version installed with Ubuntu)
- Added compatibility in the Installation guide with Ubuntu server
- Eliminated some unnecessary packages from the installation
### License
GPL 3.0
[Read more here](../LICENSE.txt)
### Contact
pi.alert.application@gmail.com

View File

@@ -1,3 +1,12 @@
<!-- ---------------------------------------------------------------------------
# Pi.Alert
# Open Source Network Guard / WIFI & LAN intrusion detector
#
# repot_sample.html - Back module. Sample email reporting in HTML format
#-------------------------------------------------------------------------------
# Puche 2021 pi.alert.application@gmail.com GNU GPLv3
#--------------------------------------------------------------------------- -->
<html> <html>
<head> <head>

View File

@@ -1,3 +1,12 @@
<!-- ---------------------------------------------------------------------------
# Pi.Alert
# Open Source Network Guard / WIFI & LAN intrusion detector
#
# repot_sample.html - Back module. Sample email reporting in HTML format
#-------------------------------------------------------------------------------
# Puche 2021 pi.alert.application@gmail.com GNU GPLv3
#--------------------------------------------------------------------------- -->
<html> <html>
<head> <head>

View File

@@ -1,6 +1,11 @@
/******************************************************************************* /* -----------------------------------------------------------------------------
* Pi.alert CSS # Pi.Alert
*******************************************************************************/ # Open Source Network Guard / WIFI & LAN intrusion detector
#
# pialert.css - Front module. CSS styles
#-------------------------------------------------------------------------------
# Puche 2021 pi.alert.application@gmail.com GNU GPLv3
----------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
Global Variables Global Variables
@@ -32,6 +37,10 @@
color: #808080; color: #808080;
} }
.text-gray-20 {
color: rgba(192,192,192,20%);
}
.text-aqua-20 { .text-aqua-20 {
color: rgba(0,192,239,20%); color: rgba(0,192,239,20%);
} }
@@ -146,6 +155,13 @@
margin-bottom: 1.3em; margin-bottom: 1.3em;
} }
.pa-small-box-footer {
color: white !important;
font-size: 18px;
}
/* -------------------------------------------------------------------------- */
.pa-small-box-aqua { .pa-small-box-aqua {
border-top: 3px solid #00c0ef; border-top: 3px solid #00c0ef;
box-shadow: 0 5px 5px rgba(0, 0, 0, 0.1); box-shadow: 0 5px 5px rgba(0, 0, 0, 0.1);
@@ -164,8 +180,6 @@
color: #00c0ef; color: #00c0ef;
} }
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
.pa-small-box-green { .pa-small-box-green {
border-top: 3px solid #00a65a; border-top: 3px solid #00a65a;
@@ -223,6 +237,25 @@
color: #dd4b39; color: #dd4b39;
} }
/* -------------------------------------------------------------------------- */
.pa-small-box-gray {
border-top: 3px solid #a0a0a0;
box-shadow: 0 5px 5px rgba(0, 0, 0, 0.1);
}
.pa-small-box-gray .inner {
color: #a0a0a0;
background-color:#FFFFFF;
}
.pa-small-box-gray .inner h3 {
margin-left: 0.5em;
}
.pa-small-box-gray .icon {
color: #a0a0a0;
}
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
Customized Box Borders Customized Box Borders
@@ -299,6 +332,29 @@
color: #B0B0B0; color: #B0B0B0;
} }
/* -----------------------------------------------------------------------------
Customized buttons
----------------------------------------------------------------------------- */
.pa-btn {
padding: 10px;
min-width: 90px;
}
.pa-btn-delete {
border-color:#ffb060;
background-color:#ffd080;
}
.pa-btn-delete:hover {
border-color:#ffb060;
background-color:#ffb060;
}
.pa-btn-records, .pa-btn-records:hover, .pa-btn-records:focus, .pa-btn-records:active {
border-color:#ddd;
background-color:#f4f4f4;
cursor: default;
}
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
@@ -371,3 +427,28 @@
z-index: 100; z-index: 100;
} }
/* -----------------------------------------------------------------------------
Notification float banner
----------------------------------------------------------------------------- */
.pa_alert_notification {
text-align: center;
font-size: large;
font-weight: bold;
color: #258744;
background-color: #d4edda;
border-color: #c3e6cb;
border-radius: 5px;
max-width: 1000px; /* 80% wrapper 1250px */
width: 80%;
z-index: 9999;
position: fixed;
top: 30px;
margin: auto;
transform: translate(0,0);
display: none;
}

View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,12 @@
<!-- ----------------------------------------------------------------------- --> <!-- ---------------------------------------------------------------------------
# Pi.Alert
# Open Source Network Guard / WIFI & LAN intrusion detector
#
# devices.php - Front module. Devices list page
#-------------------------------------------------------------------------------
# Puche 2021 pi.alert.application@gmail.com GNU GPLv3
#--------------------------------------------------------------------------- -->
<?php <?php
require 'php/templates/header.php'; require 'php/templates/header.php';
?> ?>
@@ -11,102 +19,75 @@
<h1 id="pageTitle"> <h1 id="pageTitle">
Devices Devices
</h1> </h1>
<!-- period selector -->
<span class="breadcrumb text-gray50">
New Devices period:
<select id="period" onchange="javascript: periodChanged();">
<option value="1 day">Today</option>
<option value="7 days">Last Week</option>
<option value="1 month" selected>Last Month</option>
<option value="1 year">Last Year</option>
<option value="100 years">All info</option>
</select>
</span>
</section> </section>
<!-- Main content ---------------------------------------------------------- --> <!-- Main content ---------------------------------------------------------- -->
<section class="content"> <section class="content">
<!-- top small box 1 ------------------------------------------------------- -->
<div class="row"> <div class="row">
<!-- top small box --------------------------------------------------------- --> <div class="col-lg-2 col-sm-4 col-xs-6">
<div class="col-lg-3 col-sm-6 col-xs-6"> <a href="#" onclick="javascript: getDevicesList('all');">
<a href="#" onclick="javascript: queryList('all');"> <div class="small-box bg-aqua pa-small-box-aqua pa-small-box-2">
<div class="small-box bg-aqua pa-small-box-aqua"> <div class="inner"> <h3 id="devicesAll"> -- </h3> </div>
<div class="inner"> <div class="icon"> <i class="fa fa-laptop text-aqua-20"></i> </div>
<div class="small-box-footer pa-small-box-footer"> All Devices <i class="fa fa-arrow-circle-right"></i> </div>
<h4>Total Devices</h4>
<h3 id="devicesAll"> -- </h3>
</div>
<div class="icon">
<i class="fa fa-laptop"></i>
</div>
<div class="small-box-footer">
Details <i class="fa fa-arrow-circle-right"></i>
</div>
</div> </div>
</a> </a>
</div> </div>
<!-- top small box --------------------------------------------------------- --> <!-- top small box 2 ------------------------------------------------------- -->
<div class="col-lg-3 col-sm-6 col-xs-6"> <div class="col-lg-2 col-sm-4 col-xs-6">
<a href="#" onclick="javascript: queryList('connected');"> <a href="#" onclick="javascript: getDevicesList('connected');">
<div class="small-box bg-green pa-small-box-green"> <div class="small-box bg-green pa-small-box-green pa-small-box-2">
<div class="inner"> <div class="inner"> <h3 id="devicesConnected"> -- </h3> </div>
<div class="icon"> <i class="fa fa-plug text-green-20"></i> </div>
<h4>Connected</h4> <div class="small-box-footer pa-small-box-footer"> Connected <i class="fa fa-arrow-circle-right"></i> </div>
<h3 id="devicesConnected"> -- </h3>
</div>
<div class="icon">
<i class="fa fa-plug"></i>
</div>
<div class="small-box-footer">
Details <i class="fa fa-arrow-circle-right"></i>
</div>
</div> </div>
</a> </a>
</div> </div>
<!-- top small box --------------------------------------------------------- --> <!-- top small box 3 ------------------------------------------------------- -->
<div class="col-lg-3 col-sm-6 col-xs-6"> <div class="col-lg-2 col-sm-4 col-xs-6">
<a href="#" onclick="javascript: queryList('new');"> <a href="#" onclick="javascript: getDevicesList('favorites');">
<div class="small-box bg-yellow pa-small-box-yellow"> <div class="small-box bg-yellow pa-small-box-yellow pa-small-box-2">
<div class="inner"> <div class="inner"> <h3 id="devicesFavorites"> -- </h3> </div>
<div class="icon"> <i class="fa fa-star text-yellow-20"></i> </div>
<h4>New Devices</h4> <div class="small-box-footer pa-small-box-footer"> Favorites <i class="fa fa-arrow-circle-right"></i> </div>
<h3 id="devicesNew"> -- </h3>
</div>
<div class="icon">
<i class="ion ion-plus-round"></i>
</div>
<div class="small-box-footer">
Details <i class="fa fa-arrow-circle-right"></i>
</div>
</div> </div>
</a> </a>
</div> </div>
<!-- top small box --------------------------------------------------------- --> <!-- top small box 4 ------------------------------------------------------- -->
<div class="col-lg-3 col-sm-6 col-xs-6"> <div class="col-lg-2 col-sm-4 col-xs-6">
<a href="#" onclick="javascript: queryList('down');"> <a href="#" onclick="javascript: getDevicesList('new');">
<div class="small-box bg-red pa-small-box-red"> <div class="small-box bg-yellow pa-small-box-yellow pa-small-box-2">
<div class="inner"> <div class="inner"> <h3 id="devicesNew"> -- </h3> </div>
<div class="icon"> <i class="ion ion-plus-round text-yellow-20"></i> </div>
<div class="small-box-footer pa-small-box-footer"> New Devices <i class="fa fa-arrow-circle-right"></i> </div>
</div>
</a>
</div>
<h4>Down Alerts</h4> <!-- top small box 5 ------------------------------------------------------- -->
<h3 id="devicesDown"> -- </h3> <div class="col-lg-2 col-sm-4 col-xs-6">
<a href="#" onclick="javascript: getDevicesList('down');">
<div class="small-box bg-red pa-small-box-red pa-small-box-2">
<div class="inner"> <h3 id="devicesDown"> -- </h3> </div>
<div class="icon"> <i class="fa fa-warning text-red-20"></i> </div>
<div class="small-box-footer pa-small-box-footer"> Down Alerts <i class="fa fa-arrow-circle-right"></i> </div>
</div>
</a>
</div>
</div> <!-- top small box 6 ------------------------------------------------------- -->
<div class="icon"> <div class="col-lg-2 col-sm-4 col-xs-6">
<i class="fa fa-warning"></i> <a href="#" onclick="javascript: getDevicesList('archived');">
</div> <div class="small-box bg-gray pa-small-box-gray pa-small-box-2">
<div class="small-box-footer"> <div class="inner"> <h3 id="devicesArchived"> -- </h3> </div>
Details <i class="fa fa-arrow-circle-right"></i> <div class="icon"> <i class="fa fa-eye-slash text-gray-20"></i> </div>
</div> <div class="small-box-footer pa-small-box-footer"> Archived <i class="fa fa-arrow-circle-right"></i> </div>
</div> </div>
</a> </a>
</div> </div>
@@ -118,30 +99,36 @@
<div class="row"> <div class="row">
<div class="col-xs-12"> <div class="col-xs-12">
<div id="tableDevicesBox" class="box"> <div id="tableDevicesBox" class="box">
<!-- box-header -->
<div class="box-header"> <div class="box-header">
<h3 id="tableDevicesTitle" class="box-title text-gray">Devices</h3> <h3 id="tableDevicesTitle" class="box-title text-gray">Devices</h3>
</div> </div>
<!-- /.box-header -->
<!-- table -->
<div class="box-body table-responsive"> <div class="box-body table-responsive">
<table id="tableDevices" class="table table-bordered table-hover table-striped "> <table id="tableDevices" class="table table-bordered table-hover table-striped">
<thead> <thead>
<tr> <tr>
<th>Name</th> <th>Name</th>
<th>Owner</th> <th>Owner</th>
<th>Device type</th> <th>Type</th>
<th>Favorite</th> <th>Favorite</th>
<th>Group</th> <th>Group</th>
<th>First Session</th> <th>First Session</th>
<th>Last Session</th> <th>Last Session</th>
<th>Last IP</th> <th>Last IP</th>
<th>MAC</th>
<th>Status</th> <th>Status</th>
<th>MAC</th> <th>MAC</th>
<th>Last IP Order</th> <th>Last IP Order</th>
<th>Rowid</th>
</tr> </tr>
</thead> </thead>
</table> </table>
</div> </div>
<!-- /.box-body --> <!-- /.box-body -->
</div> </div>
<!-- /.box --> <!-- /.box -->
</div> </div>
@@ -171,169 +158,185 @@
<!-- page script ----------------------------------------------------------- --> <!-- page script ----------------------------------------------------------- -->
<script> <script>
var deviceStatus = 'all';
var parTableRows = 'Front_Devices_Rows';
var parTableOrder = 'Front_Devices_Order';
var tableRows = 10;
var tableOrder = [[3,'desc'], [0,'asc']];
// ----------------------------------------------------------------------------- // Read parameters & Initialize components
var deviceStatus = ''; main();
var period = '';
// Initialize MAC
var urlParams = new URLSearchParams(window.location.search);
if (urlParams.has ('status') == true) {
deviceStatus = urlParams.get ('status');
} else {
deviceStatus = 'all';
}
// Initialize components
$(function () {
initializeDatatable();
periodChanged();
});
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
function periodChanged () { function main () {
// Requery totals and list // get parameter value
queryTotals(); $.get('php/server/parameters.php?action=get&parameter='+ parTableRows, function(data) {
queryList (deviceStatus); var result = JSON.parse(data);
if (Number.isInteger (result) ) {
tableRows = result;
}
// get parameter value
$.get('php/server/parameters.php?action=get&parameter='+ parTableOrder, function(data) {
var result = JSON.parse(data);
result = JSON.parse(result);
if (Array.isArray (result) ) {
tableOrder = result;
}
// Initialize components with parameters
initializeDatatable();
// query data
getDevicesTotals();
getDevicesList (deviceStatus);
});
});
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
function initializeDatatable () { function initializeDatatable () {
var table=
$('#tableDevices').DataTable({ $('#tableDevices').DataTable({
'paging' : true, 'paging' : true,
'lengthChange': true, 'lengthChange' : true,
'searching' : true, 'lengthMenu' : [[10, 25, 50, 100, 500, -1], [10, 25, 50, 100, 500, 'All']],
'ordering' : true, 'searching' : true,
'info' : true, 'ordering' : true,
'autoWidth' : false, 'info' : true,
'autoWidth' : false,
'order' : [[3,"desc"], [0,"asc"]], // Parameters
'pageLength' : tableRows,
'order' : tableOrder,
// 'order' : [[3,'desc'], [0,'asc']],
'columnDefs' : [ 'columnDefs' : [
{visible: false, targets: [9, 10] }, {visible: false, targets: [10, 11, 12] },
{className: 'text-center', targets: [3, 8] }, {className: 'text-center', targets: [3, 8, 9] },
{width: '0px', targets: 8 }, {width: '80px', targets: [5, 6] },
{orderData: [10], targets: 7 }, {width: '0px', targets: 9 },
{orderData: [11], targets: 7 },
// Device Name // Device Name
{targets: [0], {targets: [0],
"createdCell": function (td, cellData, rowData, row, col) { 'createdCell': function (td, cellData, rowData, row, col) {
$(td).html ('<b><a href="deviceDetails.php?mac='+ rowData[9]+ '&period='+ period +'" class="">'+ cellData +'</a></b>'); $(td).html ('<b><a href="deviceDetails.php?mac='+ rowData[10] +'" class="">'+ cellData +'</a></b>');
} }, } },
// Favorite // Favorite
{targets: [3], {targets: [3],
"createdCell": function (td, cellData, rowData, row, col) { 'createdCell': function (td, cellData, rowData, row, col) {
if (cellData == 1){ if (cellData == 1){
$(td).html ('<i class="fa fa-star text-yellow" style="font-size:16px"></i>'); $(td).html ('<i class="fa fa-star text-yellow" style="font-size:16px"></i>');
} else { } else {
$(td).html (''); $(td).html ('');
} }
} }, } },
// Dates // Dates
{targets: [5, 6], {targets: [5, 6],
"createdCell": function (td, cellData, rowData, row, col) { 'createdCell': function (td, cellData, rowData, row, col) {
$(td).html (translateHTMLcodes (cellData)); $(td).html (translateHTMLcodes (cellData));
} }, } },
// Status color // Random MAC
{targets: [8], {targets: [8],
"createdCell": function (td, cellData, rowData, row, col) { 'createdCell': function (td, cellData, rowData, row, col) {
switch (cellData) { if (cellData == 1){
case 'Down': $(td).html ('<i data-toggle="tooltip" data-placement="right" title="Random MAC" style="font-size: 16px;" class="text-yellow glyphicon glyphicon-random"></i>');
color='red'; break; } else {
case 'New': $(td).html ('');
color='yellow'; break; }
case 'On-line': } },
color='green'; break;
case 'Off-line':
color='gray text-white'; break;
default:
color='aqua'; break;
};
$(td).html ('<a href="deviceDetails.php?mac='+ rowData[9]+ '&period='+ period +'" class="badge bg-'+ color +'">'+ cellData +'</a>'); // Status color
} }, {targets: [9],
'createdCell': function (td, cellData, rowData, row, col) {
switch (cellData) {
case 'Down': color='red'; break;
case 'New': color='yellow'; break;
case 'On-line': color='green'; break;
case 'Off-line': color='gray text-white'; break;
case 'Archived': color='gray text-white'; break;
default: color='aqua'; break;
};
$(td).html ('<a href="deviceDetails.php?mac='+ rowData[10] +'" class="badge bg-'+ color +'">'+ cellData +'</a>');
} },
], ],
// Processing
'processing' : true, 'processing' : true,
'language' : { 'language' : {
processing: '<table><td width="130px" align="middle">Loading...</td><td><i class="ion ion-ios-loop-strong fa-spin fa-2x fa-fw"></td></table>', processing: '<table> <td width="130px" align="middle">Loading...</td><td><i class="ion ion-ios-loop-strong fa-spin fa-2x fa-fw"></td> </table>',
emptyTable: 'No data' emptyTable: 'No data'
} }
}); });
// Save cookie Rows displayed, and Parameters rows & order
$('#tableDevices').on( 'length.dt', function ( e, settings, len ) {
setParameter (parTableRows, len);
} );
$('#tableDevices').on( 'order.dt', function () {
setParameter (parTableOrder, JSON.stringify (table.order()) );
setCookie ('devicesList',JSON.stringify (table.column(12, { 'search': 'applied' }).data().toArray()) );
} );
$('#tableDevices').on( 'search.dt', function () {
setCookie ('devicesList', JSON.stringify (table.column(12, { 'search': 'applied' }).data().toArray()) );
} );
}; };
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
function queryTotals () { function getDevicesTotals () {
// debugTimer();
// stop timer // stop timer
stopTimerRefreshData(); stopTimerRefreshData();
// period
period = document.getElementById('period').value;
// get totals and put in boxes // get totals and put in boxes
$.get('php/server/devices.php?action=totals&period='+ period, function(data) { $.get('php/server/devices.php?action=getDevicesTotals', function(data) {
var totalsDevices = JSON.parse(data); var totalsDevices = JSON.parse(data);
$('#devicesAll').html (totalsDevices[0].toLocaleString()); $('#devicesAll').html (totalsDevices[0].toLocaleString());
$('#devicesConnected').html (totalsDevices[1].toLocaleString()); $('#devicesConnected').html (totalsDevices[1].toLocaleString());
$('#devicesNew').html (totalsDevices[2].toLocaleString()); $('#devicesFavorites').html (totalsDevices[2].toLocaleString());
$('#devicesDown').html (totalsDevices[3].toLocaleString()); $('#devicesNew').html (totalsDevices[3].toLocaleString());
}); $('#devicesDown').html (totalsDevices[4].toLocaleString());
$('#devicesArchived').html (totalsDevices[5].toLocaleString());
// Timer for refresh data // Timer for refresh data
newTimerRefreshData (queryTotals); newTimerRefreshData (getDevicesTotals);
} );
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
function queryList (status) { function getDevicesList (status) {
// Save status and period selected // Save status selected
deviceStatus = status; deviceStatus = status;
period = document.getElementById('period').value;
// Defini color & title for the status selected // Define color & title for the status selected
switch (deviceStatus) { switch (deviceStatus) {
case 'all': case 'all': tableTitle = 'All Devices'; color = 'aqua'; break;
tableTitle = 'Total Devices'; case 'connected': tableTitle = 'Connected Devices'; color = 'green'; break;
color = 'aqua'; case 'favorites': tableTitle = 'Favorites'; color = 'yellow'; break;
break; case 'new': tableTitle = 'New Devices'; color = 'yellow'; break;
case 'connected': case 'down': tableTitle = 'Down Alerts'; color = 'red'; break;
tableTitle = 'Connected Devices'; case 'archived': tableTitle = 'Archived Devices'; color = 'gray'; break;
color = 'green'; default: tableTitle = 'Devices'; color = 'gray'; break;
break;
case 'new':
tableTitle = 'New Devices';
color = 'yellow';
break;
case 'down':
tableTitle = 'Down Alerts';
color = 'red';
break;
case 'favorites':
tableTitle = 'Favorites';
color = 'yellow';
break;
default:
tableTitle = 'Devices';
boxClass = '';
break;
} }
// Set title and color // Set title and color
document.getElementById('tableDevicesTitle').className = 'box-title text-' + color; $('#tableDevicesTitle')[0].className = 'box-title text-'+ color;
document.getElementById('tableDevicesBox').className = 'box box-' + color; $('#tableDevicesBox')[0].className = 'box box-'+ color;
$('#tableDevicesTitle').html (tableTitle); $('#tableDevicesTitle').html (tableTitle);
// Define new datasource URL and reload // Define new datasource URL and reload
$('#tableDevices').DataTable().ajax.url('php/server/devices.php?action=list&status=' + deviceStatus +'&period='+ period ).load(); $('#tableDevices').DataTable().ajax.url(
'php/server/devices.php?action=getDevicesList&status=' + deviceStatus).load();
}; };
</script> </script>

View File

@@ -1,4 +1,12 @@
<!-- ----------------------------------------------------------------------- --> <!-- ---------------------------------------------------------------------------
# Pi.Alert
# Open Source Network Guard / WIFI & LAN intrusion detector
#
# events.php - Front module. Events page
#-------------------------------------------------------------------------------
# Puche 2021 pi.alert.application@gmail.com GNU GPLv3
#--------------------------------------------------------------------------- -->
<?php <?php
require 'php/templates/header.php'; require 'php/templates/header.php';
?> ?>
@@ -13,9 +21,8 @@
</h1> </h1>
<!-- period selector --> <!-- period selector -->
<span class="breadcrumb text-gray50"> <span class="breadcrumb" style="top: 0px;">
Events period: <select class="form-control" id="period" onchange="javascript: periodChanged();">
<select id="period" onchange="javascript: periodChanged();">
<option value="1 day">Today</option> <option value="1 day">Today</option>
<option value="7 days">Last Week</option> <option value="7 days">Last Week</option>
<option value="1 month" selected>Last Month</option> <option value="1 month" selected>Last Month</option>
@@ -23,126 +30,75 @@
<option value="100 years">All info</option> <option value="100 years">All info</option>
</select> </select>
</span> </span>
</section> </section>
<!-- Main content ---------------------------------------------------------- --> <!-- Main content ---------------------------------------------------------- -->
<section class="content"> <section class="content">
<!-- top small box --------------------------------------------------------- -->
<div class="row"> <div class="row">
<!-- top small box --------------------------------------------------------- -->
<div class="col-lg-2 col-sm-4 col-xs-6"> <div class="col-lg-2 col-sm-4 col-xs-6">
<a href="#" onclick="javascript: queryList('all');"> <a href="#" onclick="javascript: getEvents('all');">
<div class="small-box bg-aqua pa-small-box-aqua pa-small-box-2"> <div class="small-box bg-aqua pa-small-box-aqua pa-small-box-2">
<div class="inner"> <div class="inner"> <h3 id="eventsAll"> -- </h3> </div>
<div class="icon"> <i class="fa fa-bolt text-aqua-20"></i> </div>
<h3 id="eventsAll"> -- </h3> <div class="small-box-footer pa-small-box-footer"> All events <i class="fa fa-arrow-circle-right"></i> </div>
</div>
<div class="icon">
<i class="fa fa-bolt text-aqua-20"></i>
</div>
<div class="small-box-footer">
All events <i class="fa fa-arrow-circle-right"></i>
</div>
</div> </div>
</a> </a>
</div> </div>
<!-- top small box --------------------------------------------------------- --> <!-- top small box --------------------------------------------------------- -->
<div class="col-lg-2 col-sm-4 col-xs-6"> <div class="col-lg-2 col-sm-4 col-xs-6">
<a href="#" onclick="javascript: queryList('sessions');"> <a href="#" onclick="javascript: getEvents('sessions');">
<div class="small-box bg-green pa-small-box-green pa-small-box-2"> <div class="small-box bg-green pa-small-box-green pa-small-box-2">
<div class="inner"> <div class="inner"> <h3 id="eventsSessions"> -- </h3> </div>
<div class="icon"> <i class="fa fa-plug text-green-20"></i> </div>
<h3 id="eventsSessions"> -- </h3> <div class="small-box-footer pa-small-box-footer"> Sessions <i class="fa fa-arrow-circle-right"></i> </div>
</div>
<div class="icon">
<i class="fa fa-plug text-green-20"></i>
</div>
<div class="small-box-footer">
Sessions <i class="fa fa-arrow-circle-right"></i>
</div>
</div> </div>
</a> </a>
</div> </div>
<!-- top small box --------------------------------------------------------- --> <!-- top small box --------------------------------------------------------- -->
<div class="col-lg-2 col-sm-4 col-xs-6"> <div class="col-lg-2 col-sm-4 col-xs-6">
<a href="#" onclick="javascript: queryList('missing');"> <a href="#" onclick="javascript: getEvents('missing');">
<div class="small-box bg-yellow pa-small-box-yellow pa-small-box-2"> <div class="small-box bg-yellow pa-small-box-yellow pa-small-box-2">
<div class="inner"> <div class="inner"> <h3 id="eventsMissing"> -- </h3> </div>
<div class="icon"> <i class="fa fa-exchange text-yellow-20"></i> </div>
<h3 id="eventsMissing"> -- </h3> <div class="small-box-footer pa-small-box-footer"> Missing Sessions <i class="fa fa-arrow-circle-right"></i> </div>
</div>
<div class="icon">
<i class="fa fa-exchange text-yellow-20"></i>
</div>
<div class="small-box-footer">
Missing Sessions <i class="fa fa-arrow-circle-right"></i>
</div>
</div> </div>
</a> </a>
</div> </div>
<!-- top small box --------------------------------------------------------- --> <!-- top small box --------------------------------------------------------- -->
<div class="col-lg-2 col-sm-4 col-xs-6"> <div class="col-lg-2 col-sm-4 col-xs-6">
<a href="#" onclick="javascript: queryList('voided');"> <a href="#" onclick="javascript: getEvents('voided');">
<div class="small-box bg-yellow pa-small-box-yellow pa-small-box-2"> <div class="small-box bg-yellow pa-small-box-yellow pa-small-box-2">
<div class="inner"> <div class="inner"> <h3 id="eventsVoided"> -- </h3> </div>
<div class="icon text-aqua-20"> <i class="fa fa-exclamation-circle text-yellow-20"></i> </div>
<h3 id="eventsVoided"> -- </h3> <div class="small-box-footer pa-small-box-footer"> Voided Sessions <i class="fa fa-arrow-circle-right"></i> </div>
</div>
<div class="icon text-aqua-20">
<i class="fa fa-exclamation-circle text-yellow-20"></i>
</div>
<div class="small-box-footer">
Voided Sessions <i class="fa fa-arrow-circle-right"></i>
</div>
</div> </div>
</a> </a>
</div> </div>
<!-- top small box --------------------------------------------------------- --> <!-- top small box --------------------------------------------------------- -->
<div class="col-lg-2 col-sm-4 col-xs-6"> <div class="col-lg-2 col-sm-4 col-xs-6">
<a href="#" onclick="javascript: queryList('new');"> <a href="#" onclick="javascript: getEvents('new');">
<div class="small-box bg-yellow pa-small-box-yellow pa-small-box-2"> <div class="small-box bg-yellow pa-small-box-yellow pa-small-box-2">
<div class="inner"> <div class="inner"> <h3 id="eventsNewDevices"> -- </h3> </div>
<div class="icon"> <i class="ion ion-plus-round text-yellow-20"></i> </div>
<h3 id="eventsNewDevices"> -- </h3> <div class="small-box-footer pa-small-box-footer"> New Devices <i class="fa fa-arrow-circle-right"></i> </div>
</div>
<div class="icon">
<i class="ion ion-plus-round text-yellow-20"></i>
</div>
<div class="small-box-footer">
New Devices <i class="fa fa-arrow-circle-right"></i>
</div>
</div> </div>
</a> </a>
</div> </div>
<!-- top small box --------------------------------------------------------- --> <!-- top small box --------------------------------------------------------- -->
<div class="col-lg-2 col-sm-4 col-xs-6"> <div class="col-lg-2 col-sm-4 col-xs-6">
<a href="#" onclick="javascript: queryList('down');"> <a href="#" onclick="javascript: getEvents('down');">
<div class="small-box bg-red pa-small-box-red pa-small-box-2"> <div class="small-box bg-red pa-small-box-red pa-small-box-2">
<div class="inner"> <div class="inner"> <h3 id="eventsDown"> -- </h3> </div>
<div class="icon"> <i class="fa fa-warning text-red-20"></i> </div>
<h3 id="eventsDown"> -- </h3> <div class="small-box-footer pa-small-box-footer"> Down Alerts <i class="fa fa-arrow-circle-right"></i> </div>
</div>
<div class="icon">
<i class="fa fa-warning text-red-20"></i>
</div>
<div class="small-box-footer">
Down Alerts <i class="fa fa-arrow-circle-right"></i>
</div>
</div> </div>
</a> </a>
</div> </div>
@@ -154,10 +110,13 @@
<div class="row"> <div class="row">
<div class="col-xs-12"> <div class="col-xs-12">
<div id="tableEventsBox" class="box"> <div id="tableEventsBox" class="box">
<!-- box-header -->
<div class="box-header"> <div class="box-header">
<h3 id="tableEventsTitle" class="box-title text-gray">Events</h3> <h3 id="tableEventsTitle" class="box-title text-gray">Events</h3>
</div> </div>
<!-- /.box-header -->
<!-- table -->
<div class="box-body table-responsive"> <div class="box-body table-responsive">
<table id="tableEvents" class="table table-bordered table-hover table-striped "> <table id="tableEvents" class="table table-bordered table-hover table-striped ">
<thead> <thead>
@@ -179,6 +138,7 @@
</table> </table>
</div> </div>
<!-- /.box-body --> <!-- /.box-body -->
</div> </div>
<!-- /.box --> <!-- /.box -->
</div> </div>
@@ -208,86 +168,113 @@
<!-- page script ----------------------------------------------------------- --> <!-- page script ----------------------------------------------------------- -->
<script> <script>
var parPeriod = 'Front_Events_Period';
var parTableRows = 'Front_Events_Rows';
var eventsType = 'all';
var period = '';
var tableRows = 10;
// Read parameters & Initialize components
main();
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
var eventsType = ''; function main () {
var period = ''; // get parameter value
$.get('php/server/parameters.php?action=get&parameter='+ parPeriod, function(data) {
var result = JSON.parse(data);
if (result) {
period = result;
$('#period').val(period);
}
// Initialize MAC // get parameter value
var urlParams = new URLSearchParams(window.location.search); $.get('php/server/parameters.php?action=get&parameter='+ parTableRows, function(data) {
if (urlParams.has ('status') == true) { var result = JSON.parse(data);
eventsType = urlParams.get ('type'); if (Number.isInteger (result) ) {
} else { tableRows = result;
eventsType = 'all'; }
}
// Initialize components // Initialize components
$(function () { initializeDatatable();
initializeDatatable();
periodChanged(); // query data
getEventsTotals();
getEvents (eventsType);
});
}); });
// -----------------------------------------------------------------------------
function periodChanged () {
// Requery totals and list
queryTotals();
queryList (eventsType);
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
function initializeDatatable () { function initializeDatatable () {
$('#tableEvents').DataTable({ $('#tableEvents').DataTable({
'paging' : true, 'paging' : true,
'lengthChange': true, 'lengthChange' : true,
'searching' : true, 'lengthMenu' : [[10, 25, 50, 100, 500, -1], [10, 25, 50, 100, 500, 'All']],
'ordering' : true, 'searching' : true,
'info' : true, 'ordering' : true,
'autoWidth' : false, 'info' : true,
'autoWidth' : false,
'order' : [[0,"desc"], [3,"desc"], [5,"desc"]], 'order' : [[0,"desc"], [3,"desc"], [5,"desc"]],
// Parameters
'pageLength' : tableRows,
'columnDefs' : [ 'columnDefs' : [
{visible: false, targets: [0,5,6,7,8,10] }, {visible: false, targets: [0,5,6,7,8,10] },
{className: 'text-center', targets: [] }, {className: 'text-center', targets: [] },
{orderData: [8], targets: 7 }, {orderData: [8], targets: 7 },
{orderData: [10], targets: 9 }, {orderData: [10], targets: 9 },
// Device Name // Device Name
{targets: [1], {targets: [1],
"createdCell": function (td, cellData, rowData, row, col) { "createdCell": function (td, cellData, rowData, row, col) {
$(td).html ('<b><a href="deviceDetails.php?mac='+ rowData[13]+ '&period='+ period +'" class="">'+ cellData +'</a></b>'); $(td).html ('<b><a href="deviceDetails.php?mac='+ rowData[13] +'" class="">'+ cellData +'</a></b>');
} }, } },
// Replace HTML codes // Replace HTML codes
{targets: [3,4,5,6,7], {targets: [3,4,5,6,7],
"createdCell": function (td, cellData, rowData, row, col) { "createdCell": function (td, cellData, rowData, row, col) {
$(td).html (translateHTMLcodes (cellData)); $(td).html (translateHTMLcodes (cellData));
} } } }
], ],
// Processing
'processing' : true, 'processing' : true,
'language' : { 'language' : {
processing: '<table><td width="130px" align="middle">Loading...</td><td><i class="ion ion-ios-loop-strong fa-spin fa-2x fa-fw"></td></table>', processing: '<table><td width="130px" align="middle">Loading...</td><td><i class="ion ion-ios-loop-strong fa-spin fa-2x fa-fw"></td></table>',
emptyTable: 'No data' emptyTable: 'No data'
} }
}); });
// Save Parameter rows when changed
$('#tableEvents').on( 'length.dt', function ( e, settings, len ) {
setParameter (parTableRows, len);
} );
}; };
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
function queryTotals () { function periodChanged () {
// debugTimer(); // Save Parameter Period
period = $('#period').val();
setParameter (parPeriod, period);
// Requery totals and events
getEventsTotals();
getEvents (eventsType);
}
// -----------------------------------------------------------------------------
function getEventsTotals () {
// stop timer // stop timer
stopTimerRefreshData(); stopTimerRefreshData();
// period
period = document.getElementById('period').value;
// get totals and put in boxes // get totals and put in boxes
$.get('php/server/events.php?action=totals&period='+ period, function(data) { $.get('php/server/events.php?action=getEventsTotals&period='+ period, function(data) {
var totalsEvents = JSON.parse(data); var totalsEvents = JSON.parse(data);
$('#eventsAll').html (totalsEvents[0].toLocaleString()); $('#eventsAll').html (totalsEvents[0].toLocaleString());
@@ -296,57 +283,32 @@ function queryTotals () {
$('#eventsVoided').html (totalsEvents[3].toLocaleString()); $('#eventsVoided').html (totalsEvents[3].toLocaleString());
$('#eventsNewDevices').html (totalsEvents[4].toLocaleString()); $('#eventsNewDevices').html (totalsEvents[4].toLocaleString());
$('#eventsDown').html (totalsEvents[5].toLocaleString()); $('#eventsDown').html (totalsEvents[5].toLocaleString());
});
// Timer for refresh data // Timer for refresh data
newTimerRefreshData (queryTotals); newTimerRefreshData (getEventsTotals);
});
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
function queryList (p_eventsType) { function getEvents (p_eventsType) {
// Save status and period selected // Save status selected
eventsType = p_eventsType; eventsType = p_eventsType;
period = document.getElementById('period').value;
// Define color & title for the status selected // Define color & title for the status selected
sesionCols = false;
switch (eventsType) { switch (eventsType) {
case 'all': case 'all': tableTitle = 'All Events'; color = 'aqua'; sesionCols = false; break;
tableTitle = 'All Events'; case 'sessions': tableTitle = 'Sessions'; color = 'green'; sesionCols = true; break;
color = 'aqua'; case 'missing': tableTitle = 'Missing Events'; color = 'yellow'; sesionCols = true; break;
break; case 'voided': tableTitle = 'Voided Events'; color = 'yellow'; sesionCols = false; break;
case 'sessions': case 'new': tableTitle = 'New Devices Events'; color = 'yellow'; sesionCols = false; break;
tableTitle = 'Sessions'; case 'down': tableTitle = 'Down Alerts'; color = 'red'; sesionCols = false; break;
color = 'green'; default: tableTitle = 'Events'; boxClass = ''; sesionCols = false; break;
sesionCols = true;
break;
case 'missing':
tableTitle = 'Missing Events';
color = 'yellow';
sesionCols = true;
break;
case 'voided':
tableTitle = 'Voided Events';
color = 'yellow';
break;
case 'new':
tableTitle = 'New Devices Events';
color = 'yellow';
break;
case 'down':
tableTitle = 'Down Alerts';
color = 'red';
break;
default:
tableTitle = 'Events';
boxClass = '';
break;
} }
// Set title and color // Set title and color
document.getElementById('tableEventsTitle').className = 'box-title text-' + color; $('#tableEventsTitle')[0].className = 'box-title text-' + color;
document.getElementById('tableEventsBox').className = 'box box-' + color; $('#tableEventsBox')[0].className = 'box box-' + color;
$('#tableEventsTitle').html (tableTitle); $('#tableEventsTitle').html (tableTitle);
// Coluumns Visibility // Coluumns Visibility
@@ -360,7 +322,7 @@ function queryList (p_eventsType) {
$('#tableEvents').DataTable().clear(); $('#tableEvents').DataTable().clear();
$('#tableEvents').DataTable().draw(); $('#tableEvents').DataTable().draw();
$('#tableEvents').DataTable().order ([0,"desc"], [3,"desc"], [5,"desc"]); $('#tableEvents').DataTable().order ([0,"desc"], [3,"desc"], [5,"desc"]);
$('#tableEvents').DataTable().ajax.url('php/server/events.php?action=list&type=' + eventsType +'&period='+ period ).load(); $('#tableEvents').DataTable().ajax.url('php/server/events.php?action=getEvents&type=' + eventsType +'&period='+ period ).load();
}; };
</script> </script>

View File

Before

Width:  |  Height:  |  Size: 139 KiB

After

Width:  |  Height:  |  Size: 139 KiB

View File

@@ -1,4 +1,12 @@
<!-- ----------------------------------------------------------------------- --> <!-- ---------------------------------------------------------------------------
# Pi.Alert
# Open Source Network Guard / WIFI & LAN intrusion detector
#
# devices.php - Front module. Devices list page
#-------------------------------------------------------------------------------
# Puche 2021 pi.alert.application@gmail.com GNU GPLv3
#--------------------------------------------------------------------------- -->
<?php <?php
require 'php/templates/header.php'; require 'php/templates/header.php';
?> ?>
@@ -11,102 +19,75 @@
<h1 id="pageTitle"> <h1 id="pageTitle">
Devices Devices
</h1> </h1>
<!-- period selector -->
<span class="breadcrumb text-gray50">
New Devices period:
<select id="period" onchange="javascript: periodChanged();">
<option value="1 day">Today</option>
<option value="7 days">Last Week</option>
<option value="1 month" selected>Last Month</option>
<option value="1 year">Last Year</option>
<option value="100 years">All info</option>
</select>
</span>
</section> </section>
<!-- Main content ---------------------------------------------------------- --> <!-- Main content ---------------------------------------------------------- -->
<section class="content"> <section class="content">
<!-- top small box 1 ------------------------------------------------------- -->
<div class="row"> <div class="row">
<!-- top small box --------------------------------------------------------- --> <div class="col-lg-2 col-sm-4 col-xs-6">
<div class="col-lg-3 col-sm-6 col-xs-6"> <a href="#" onclick="javascript: getDevicesList('all');">
<a href="#" onclick="javascript: queryList('all');"> <div class="small-box bg-aqua pa-small-box-aqua pa-small-box-2">
<div class="small-box bg-aqua pa-small-box-aqua"> <div class="inner"> <h3 id="devicesAll"> -- </h3> </div>
<div class="inner"> <div class="icon"> <i class="fa fa-laptop text-aqua-20"></i> </div>
<div class="small-box-footer pa-small-box-footer"> All Devices <i class="fa fa-arrow-circle-right"></i> </div>
<h4>Total Devices</h4>
<h3 id="devicesAll"> -- </h3>
</div>
<div class="icon">
<i class="fa fa-laptop"></i>
</div>
<div class="small-box-footer">
Details <i class="fa fa-arrow-circle-right"></i>
</div>
</div> </div>
</a> </a>
</div> </div>
<!-- top small box --------------------------------------------------------- --> <!-- top small box 2 ------------------------------------------------------- -->
<div class="col-lg-3 col-sm-6 col-xs-6"> <div class="col-lg-2 col-sm-4 col-xs-6">
<a href="#" onclick="javascript: queryList('connected');"> <a href="#" onclick="javascript: getDevicesList('connected');">
<div class="small-box bg-green pa-small-box-green"> <div class="small-box bg-green pa-small-box-green pa-small-box-2">
<div class="inner"> <div class="inner"> <h3 id="devicesConnected"> -- </h3> </div>
<div class="icon"> <i class="fa fa-plug text-green-20"></i> </div>
<h4>Connected</h4> <div class="small-box-footer pa-small-box-footer"> Connected <i class="fa fa-arrow-circle-right"></i> </div>
<h3 id="devicesConnected"> -- </h3>
</div>
<div class="icon">
<i class="fa fa-plug"></i>
</div>
<div class="small-box-footer">
Details <i class="fa fa-arrow-circle-right"></i>
</div>
</div> </div>
</a> </a>
</div> </div>
<!-- top small box --------------------------------------------------------- --> <!-- top small box 3 ------------------------------------------------------- -->
<div class="col-lg-3 col-sm-6 col-xs-6"> <div class="col-lg-2 col-sm-4 col-xs-6">
<a href="#" onclick="javascript: queryList('new');"> <a href="#" onclick="javascript: getDevicesList('favorites');">
<div class="small-box bg-yellow pa-small-box-yellow"> <div class="small-box bg-yellow pa-small-box-yellow pa-small-box-2">
<div class="inner"> <div class="inner"> <h3 id="devicesFavorites"> -- </h3> </div>
<div class="icon"> <i class="fa fa-star text-yellow-20"></i> </div>
<h4>New Devices</h4> <div class="small-box-footer pa-small-box-footer"> Favorites <i class="fa fa-arrow-circle-right"></i> </div>
<h3 id="devicesNew"> -- </h3>
</div>
<div class="icon">
<i class="ion ion-plus-round"></i>
</div>
<div class="small-box-footer">
Details <i class="fa fa-arrow-circle-right"></i>
</div>
</div> </div>
</a> </a>
</div> </div>
<!-- top small box --------------------------------------------------------- --> <!-- top small box 4 ------------------------------------------------------- -->
<div class="col-lg-3 col-sm-6 col-xs-6"> <div class="col-lg-2 col-sm-4 col-xs-6">
<a href="#" onclick="javascript: queryList('down');"> <a href="#" onclick="javascript: getDevicesList('new');">
<div class="small-box bg-red pa-small-box-red"> <div class="small-box bg-yellow pa-small-box-yellow pa-small-box-2">
<div class="inner"> <div class="inner"> <h3 id="devicesNew"> -- </h3> </div>
<div class="icon"> <i class="ion ion-plus-round text-yellow-20"></i> </div>
<div class="small-box-footer pa-small-box-footer"> New Devices <i class="fa fa-arrow-circle-right"></i> </div>
</div>
</a>
</div>
<h4>Down Alerts</h4> <!-- top small box 5 ------------------------------------------------------- -->
<h3 id="devicesDown"> -- </h3> <div class="col-lg-2 col-sm-4 col-xs-6">
<a href="#" onclick="javascript: getDevicesList('down');">
<div class="small-box bg-red pa-small-box-red pa-small-box-2">
<div class="inner"> <h3 id="devicesDown"> -- </h3> </div>
<div class="icon"> <i class="fa fa-warning text-red-20"></i> </div>
<div class="small-box-footer pa-small-box-footer"> Down Alerts <i class="fa fa-arrow-circle-right"></i> </div>
</div>
</a>
</div>
</div> <!-- top small box 6 ------------------------------------------------------- -->
<div class="icon"> <div class="col-lg-2 col-sm-4 col-xs-6">
<i class="fa fa-warning"></i> <a href="#" onclick="javascript: getDevicesList('archived');">
</div> <div class="small-box bg-gray pa-small-box-gray pa-small-box-2">
<div class="small-box-footer"> <div class="inner"> <h3 id="devicesArchived"> -- </h3> </div>
Details <i class="fa fa-arrow-circle-right"></i> <div class="icon"> <i class="fa fa-eye-slash text-gray-20"></i> </div>
</div> <div class="small-box-footer pa-small-box-footer"> Archived <i class="fa fa-arrow-circle-right"></i> </div>
</div> </div>
</a> </a>
</div> </div>
@@ -118,30 +99,36 @@
<div class="row"> <div class="row">
<div class="col-xs-12"> <div class="col-xs-12">
<div id="tableDevicesBox" class="box"> <div id="tableDevicesBox" class="box">
<!-- box-header -->
<div class="box-header"> <div class="box-header">
<h3 id="tableDevicesTitle" class="box-title text-gray">Devices</h3> <h3 id="tableDevicesTitle" class="box-title text-gray">Devices</h3>
</div> </div>
<!-- /.box-header -->
<!-- table -->
<div class="box-body table-responsive"> <div class="box-body table-responsive">
<table id="tableDevices" class="table table-bordered table-hover table-striped "> <table id="tableDevices" class="table table-bordered table-hover table-striped">
<thead> <thead>
<tr> <tr>
<th>Name</th> <th>Name</th>
<th>Owner</th> <th>Owner</th>
<th>Device type</th> <th>Type</th>
<th>Favorite</th> <th>Favorite</th>
<th>Group</th> <th>Group</th>
<th>First Session</th> <th>First Session</th>
<th>Last Session</th> <th>Last Session</th>
<th>Last IP</th> <th>Last IP</th>
<th>MAC</th>
<th>Status</th> <th>Status</th>
<th>MAC</th> <th>MAC</th>
<th>Last IP Order</th> <th>Last IP Order</th>
<th>Rowid</th>
</tr> </tr>
</thead> </thead>
</table> </table>
</div> </div>
<!-- /.box-body --> <!-- /.box-body -->
</div> </div>
<!-- /.box --> <!-- /.box -->
</div> </div>
@@ -171,169 +158,185 @@
<!-- page script ----------------------------------------------------------- --> <!-- page script ----------------------------------------------------------- -->
<script> <script>
var deviceStatus = 'all';
var parTableRows = 'Front_Devices_Rows';
var parTableOrder = 'Front_Devices_Order';
var tableRows = 10;
var tableOrder = [[3,'desc'], [0,'asc']];
// ----------------------------------------------------------------------------- // Read parameters & Initialize components
var deviceStatus = ''; main();
var period = '';
// Initialize MAC
var urlParams = new URLSearchParams(window.location.search);
if (urlParams.has ('status') == true) {
deviceStatus = urlParams.get ('status');
} else {
deviceStatus = 'all';
}
// Initialize components
$(function () {
initializeDatatable();
periodChanged();
});
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
function periodChanged () { function main () {
// Requery totals and list // get parameter value
queryTotals(); $.get('php/server/parameters.php?action=get&parameter='+ parTableRows, function(data) {
queryList (deviceStatus); var result = JSON.parse(data);
if (Number.isInteger (result) ) {
tableRows = result;
}
// get parameter value
$.get('php/server/parameters.php?action=get&parameter='+ parTableOrder, function(data) {
var result = JSON.parse(data);
result = JSON.parse(result);
if (Array.isArray (result) ) {
tableOrder = result;
}
// Initialize components with parameters
initializeDatatable();
// query data
getDevicesTotals();
getDevicesList (deviceStatus);
});
});
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
function initializeDatatable () { function initializeDatatable () {
var table=
$('#tableDevices').DataTable({ $('#tableDevices').DataTable({
'paging' : true, 'paging' : true,
'lengthChange': true, 'lengthChange' : true,
'searching' : true, 'lengthMenu' : [[10, 25, 50, 100, 500, -1], [10, 25, 50, 100, 500, 'All']],
'ordering' : true, 'searching' : true,
'info' : true, 'ordering' : true,
'autoWidth' : false, 'info' : true,
'autoWidth' : false,
'order' : [[3,"desc"], [0,"asc"]], // Parameters
'pageLength' : tableRows,
'order' : tableOrder,
// 'order' : [[3,'desc'], [0,'asc']],
'columnDefs' : [ 'columnDefs' : [
{visible: false, targets: [9, 10] }, {visible: false, targets: [10, 11, 12] },
{className: 'text-center', targets: [3, 8] }, {className: 'text-center', targets: [3, 8, 9] },
{width: '0px', targets: 8 }, {width: '80px', targets: [5, 6] },
{orderData: [10], targets: 7 }, {width: '0px', targets: 9 },
{orderData: [11], targets: 7 },
// Device Name // Device Name
{targets: [0], {targets: [0],
"createdCell": function (td, cellData, rowData, row, col) { 'createdCell': function (td, cellData, rowData, row, col) {
$(td).html ('<b><a href="deviceDetails.php?mac='+ rowData[9]+ '&period='+ period +'" class="">'+ cellData +'</a></b>'); $(td).html ('<b><a href="deviceDetails.php?mac='+ rowData[10] +'" class="">'+ cellData +'</a></b>');
} }, } },
// Favorite // Favorite
{targets: [3], {targets: [3],
"createdCell": function (td, cellData, rowData, row, col) { 'createdCell': function (td, cellData, rowData, row, col) {
if (cellData == 1){ if (cellData == 1){
$(td).html ('<i class="fa fa-star text-yellow" style="font-size:16px"></i>'); $(td).html ('<i class="fa fa-star text-yellow" style="font-size:16px"></i>');
} else { } else {
$(td).html (''); $(td).html ('');
} }
} }, } },
// Dates // Dates
{targets: [5, 6], {targets: [5, 6],
"createdCell": function (td, cellData, rowData, row, col) { 'createdCell': function (td, cellData, rowData, row, col) {
$(td).html (translateHTMLcodes (cellData)); $(td).html (translateHTMLcodes (cellData));
} }, } },
// Status color // Random MAC
{targets: [8], {targets: [8],
"createdCell": function (td, cellData, rowData, row, col) { 'createdCell': function (td, cellData, rowData, row, col) {
switch (cellData) { if (cellData == 1){
case 'Down': $(td).html ('<i data-toggle="tooltip" data-placement="right" title="Random MAC" style="font-size: 16px;" class="text-yellow glyphicon glyphicon-random"></i>');
color='red'; break; } else {
case 'New': $(td).html ('');
color='yellow'; break; }
case 'On-line': } },
color='green'; break;
case 'Off-line':
color='gray text-white'; break;
default:
color='aqua'; break;
};
$(td).html ('<a href="deviceDetails.php?mac='+ rowData[9]+ '&period='+ period +'" class="badge bg-'+ color +'">'+ cellData +'</a>'); // Status color
} }, {targets: [9],
'createdCell': function (td, cellData, rowData, row, col) {
switch (cellData) {
case 'Down': color='red'; break;
case 'New': color='yellow'; break;
case 'On-line': color='green'; break;
case 'Off-line': color='gray text-white'; break;
case 'Archived': color='gray text-white'; break;
default: color='aqua'; break;
};
$(td).html ('<a href="deviceDetails.php?mac='+ rowData[10] +'" class="badge bg-'+ color +'">'+ cellData +'</a>');
} },
], ],
// Processing
'processing' : true, 'processing' : true,
'language' : { 'language' : {
processing: '<table><td width="130px" align="middle">Loading...</td><td><i class="ion ion-ios-loop-strong fa-spin fa-2x fa-fw"></td></table>', processing: '<table> <td width="130px" align="middle">Loading...</td><td><i class="ion ion-ios-loop-strong fa-spin fa-2x fa-fw"></td> </table>',
emptyTable: 'No data' emptyTable: 'No data'
} }
}); });
// Save cookie Rows displayed, and Parameters rows & order
$('#tableDevices').on( 'length.dt', function ( e, settings, len ) {
setParameter (parTableRows, len);
} );
$('#tableDevices').on( 'order.dt', function () {
setParameter (parTableOrder, JSON.stringify (table.order()) );
setCookie ('devicesList',JSON.stringify (table.column(12, { 'search': 'applied' }).data().toArray()) );
} );
$('#tableDevices').on( 'search.dt', function () {
setCookie ('devicesList', JSON.stringify (table.column(12, { 'search': 'applied' }).data().toArray()) );
} );
}; };
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
function queryTotals () { function getDevicesTotals () {
// debugTimer();
// stop timer // stop timer
stopTimerRefreshData(); stopTimerRefreshData();
// period
period = document.getElementById('period').value;
// get totals and put in boxes // get totals and put in boxes
$.get('php/server/devices.php?action=totals&period='+ period, function(data) { $.get('php/server/devices.php?action=getDevicesTotals', function(data) {
var totalsDevices = JSON.parse(data); var totalsDevices = JSON.parse(data);
$('#devicesAll').html (totalsDevices[0].toLocaleString()); $('#devicesAll').html (totalsDevices[0].toLocaleString());
$('#devicesConnected').html (totalsDevices[1].toLocaleString()); $('#devicesConnected').html (totalsDevices[1].toLocaleString());
$('#devicesNew').html (totalsDevices[2].toLocaleString()); $('#devicesFavorites').html (totalsDevices[2].toLocaleString());
$('#devicesDown').html (totalsDevices[3].toLocaleString()); $('#devicesNew').html (totalsDevices[3].toLocaleString());
}); $('#devicesDown').html (totalsDevices[4].toLocaleString());
$('#devicesArchived').html (totalsDevices[5].toLocaleString());
// Timer for refresh data // Timer for refresh data
newTimerRefreshData (queryTotals); newTimerRefreshData (getDevicesTotals);
} );
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
function queryList (status) { function getDevicesList (status) {
// Save status and period selected // Save status selected
deviceStatus = status; deviceStatus = status;
period = document.getElementById('period').value;
// Defini color & title for the status selected // Define color & title for the status selected
switch (deviceStatus) { switch (deviceStatus) {
case 'all': case 'all': tableTitle = 'All Devices'; color = 'aqua'; break;
tableTitle = 'Total Devices'; case 'connected': tableTitle = 'Connected Devices'; color = 'green'; break;
color = 'aqua'; case 'favorites': tableTitle = 'Favorites'; color = 'yellow'; break;
break; case 'new': tableTitle = 'New Devices'; color = 'yellow'; break;
case 'connected': case 'down': tableTitle = 'Down Alerts'; color = 'red'; break;
tableTitle = 'Connected Devices'; case 'archived': tableTitle = 'Archived Devices'; color = 'gray'; break;
color = 'green'; default: tableTitle = 'Devices'; color = 'gray'; break;
break;
case 'new':
tableTitle = 'New Devices';
color = 'yellow';
break;
case 'down':
tableTitle = 'Down Alerts';
color = 'red';
break;
case 'favorites':
tableTitle = 'Favorites';
color = 'yellow';
break;
default:
tableTitle = 'Devices';
boxClass = '';
break;
} }
// Set title and color // Set title and color
document.getElementById('tableDevicesTitle').className = 'box-title text-' + color; $('#tableDevicesTitle')[0].className = 'box-title text-'+ color;
document.getElementById('tableDevicesBox').className = 'box box-' + color; $('#tableDevicesBox')[0].className = 'box box-'+ color;
$('#tableDevicesTitle').html (tableTitle); $('#tableDevicesTitle').html (tableTitle);
// Define new datasource URL and reload // Define new datasource URL and reload
$('#tableDevices').DataTable().ajax.url('php/server/devices.php?action=list&status=' + deviceStatus +'&period='+ period ).load(); $('#tableDevices').DataTable().ajax.url(
'php/server/devices.php?action=getDevicesList&status=' + deviceStatus).load();
}; };
</script> </script>

View File

@@ -1,9 +1,167 @@
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
Pi.Alert Common Javascript functions * Pi.Alert
* Open Source Network Guard / WIFI & LAN intrusion detector
*
* pialert_common.js - Front module. Common Javascript functions
*-------------------------------------------------------------------------------
* Puche 2021 pi.alert.application@gmail.com GNU GPLv3
----------------------------------------------------------------------------- */ ----------------------------------------------------------------------------- */
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
var timerRefreshData = '' var timerRefreshData = ''
var modalCallbackFunction = '';
// -----------------------------------------------------------------------------
function setCookie (cookie, value, expirationHours='') {
// Calc expiration date
var expires = '';
if (typeof expirationHours === 'number') {
expires = ';expires=' + new Date(Date.now() + expirationHours *60*60*1000).toUTCString();
}
// Save Cookie
document.cookie = cookie + "=" + value + expires;
}
// -----------------------------------------------------------------------------
function getCookie (cookie) {
// Array of cookies
var allCookies = document.cookie.split(';');
// For each cookie
for (var i = 0; i < allCookies.length; i++) {
var currentCookie = allCookies[i].trim();
// If the current cookie is the correct cookie
if (currentCookie.indexOf (cookie +'=') == 0) {
// Return value
return currentCookie.substring (cookie.length+1);
}
}
// Return empty (not found)
return "";
}
// -----------------------------------------------------------------------------
function deleteCookie (cookie) {
document.cookie = cookie + '=;expires=Thu, 01 Jan 1970 00:00:00 UTC';
}
// -----------------------------------------------------------------------------
function deleteAllCookies() {
// Array of cookies
var allCookies = document.cookie.split(";");
// For each cookie
for (var i = 0; i < allCookies.length; i++) {
var cookie = allCookies[i].trim();
var eqPos = cookie.indexOf("=");
var name = eqPos > -1 ? cookie.substr(0, eqPos) : cookie;
document.cookie = name + "=;expires=Thu, 01 Jan 1970 00:00:00 UTC";
}
}
// -----------------------------------------------------------------------------
function showModalDefault (title, message, btnCancel, btnOK, callbackFunction) {
// set captions
$('#modal-default-title').html (title);
$('#modal-default-message').html (message);
$('#modal-default-cancel').html (btnCancel);
$('#modal-default-OK').html (btnOK);
modalCallbackFunction = callbackFunction;
// Show modal
$('#modal-default').modal('show');
}
// -----------------------------------------------------------------------------
function showModalWarning (title, message, btnCancel, btnOK, callbackFunction) {
// set captions
$('#modal-warning-title').html (title);
$('#modal-warning-message').html (message);
$('#modal-warning-cancel').html (btnCancel);
$('#modal-warning-OK').html (btnOK);
modalCallbackFunction = callbackFunction;
// Show modal
$('#modal-warning').modal('show');
}
// -----------------------------------------------------------------------------
function modalDefaultOK () {
// Hide modal
$('#modal-default').modal('hide');
// timer to execute function
window.setTimeout( function() {
window[modalCallbackFunction]();
}, 100);
}
// -----------------------------------------------------------------------------
function modalWarningOK () {
// Hide modal
$('#modal-warning').modal('hide');
// timer to execute function
window.setTimeout( function() {
window[modalCallbackFunction]();
}, 100);
}
// -----------------------------------------------------------------------------
function showMessage (textMessage="") {
if (textMessage.toLowerCase().includes("error") ) {
// show error
alert (textMessage);
} else {
// show temporal notification
$("#alert-message").html (textMessage);
$("#notification").fadeIn(1, function () {
window.setTimeout( function() {
$("#notification").fadeOut(500)
}, 3000);
} );
}
}
// -----------------------------------------------------------------------------
function setParameter (parameter, value) {
// Retry
$.get('php/server/parameters.php?action=set&parameter=' + parameter +
'&value='+ value,
function(data) {
if (data != "OK") {
// Retry
sleep (200);
$.get('php/server/parameters.php?action=set&parameter=' + parameter +
'&value='+ value,
function(data) {
if (data != "OK") {
// alert (data);
} else {
// alert ("OK. Second attempt");
};
} );
};
} );
}
// -----------------------------------------------------------------------------
function sleep(milliseconds) {
const date = Date.now();
let currentDate = null;
do {
currentDate = Date.now();
} while (currentDate - date < milliseconds);
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@@ -35,5 +193,7 @@ function newTimerRefreshData (refeshFunction) {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
function debugTimer () { function debugTimer () {
document.getElementById ('pageTitle').innerHTML = (new Date().getSeconds()); $('#pageTitle').html (new Date().getSeconds());
} }

View File

@@ -1,32 +1,40 @@
<?php <?php
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// PHP Open DB // Pi.Alert
// Open Source Network Guard / WIFI & LAN intrusion detector
//
// db.php - Front module. Server side. DB common file
//------------------------------------------------------------------------------
// Puche 2021 pi.alert.application@gmail.com GNU GPLv3
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// DB File Path // DB File Path
$DBFILE = '../../../db/pialert.db'; $DBFILE = '../../../db/pialert.db';
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Connect DB // Connect DB
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
function SQLite3_connect ($trytoreconnect) { function SQLite3_connect ($trytoreconnect) {
global $DBFILE; global $DBFILE;
try try
{
// connect to database
// return new SQLite3($DBFILE, SQLITE3_OPEN_READONLY);
return new SQLite3($DBFILE, SQLITE3_OPEN_READWRITE);
}
catch (Exception $exception)
{
// sqlite3 throws an exception when it is unable to connect
// try to reconnect one time after 3 seconds
if($trytoreconnect)
{ {
// connect to database sleep(3);
// return new SQLite3($DBFILE, SQLITE3_OPEN_READONLY); return SQLite3_connect(false);
return new SQLite3($DBFILE, SQLITE3_OPEN_READWRITE);
}
catch (Exception $exception)
{
// sqlite3 throws an exception when it is unable to connect
// try to reconnect one time after 3 seconds
if($trytoreconnect)
{
sleep(3);
return SQLite3_connect(false);
}
} }
}
} }
@@ -34,19 +42,19 @@ function SQLite3_connect ($trytoreconnect) {
// Open DB // Open DB
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
function OpenDB () { function OpenDB () {
global $DBFILE; global $DBFILE;
global $db; global $db;
if(strlen($DBFILE) == 0) if(strlen($DBFILE) == 0)
{ {
die ('No database available'); die ('Database no available');
} }
$db = SQLite3_connect(true); $db = SQLite3_connect(true);
if(!$db) if(!$db)
{ {
die ('Error connecting to database'); die ('Error connecting to database');
} }
} }
?> ?>

View File

@@ -1,14 +1,25 @@
<?php <?php
//------------------------------------------------------------------------------
// Pi.Alert
// Open Source Network Guard / WIFI & LAN intrusion detector
//
// devices.php - Front module. Server side. Manage Devices
//------------------------------------------------------------------------------
// Puche 2021 pi.alert.application@gmail.com GNU GPLv3
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// External files // External files
require 'db.php'; require 'db.php';
require 'util.php'; require 'util.php';
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Action selector // Action selector
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Set maximum execution time to 1 minute // Set maximum execution time to 15 seconds
ini_set ('max_execution_time','60'); ini_set ('max_execution_time','15');
// Open DB // Open DB
OpenDB(); OpenDB();
@@ -17,68 +28,209 @@
if (isset ($_REQUEST['action']) && !empty ($_REQUEST['action'])) { if (isset ($_REQUEST['action']) && !empty ($_REQUEST['action'])) {
$action = $_REQUEST['action']; $action = $_REQUEST['action'];
switch ($action) { switch ($action) {
case 'totals': queryTotals(); break; case 'getDeviceData': getDeviceData(); break;
case 'list': queryList(); break; case 'setDeviceData': setDeviceData(); break;
case 'queryDeviceData': queryDeviceData(); break; case 'deleteDevice': deleteDevice(); break;
case 'updateData': updateDeviceData(); break;
case 'calendar': queryCalendarList(); break; case 'getDevicesTotals': getDevicesTotals(); break;
case 'queryOwners': queryOwners(); break; case 'getDevicesList': getDevicesList(); break;
case 'queryDeviceTypes': queryDeviceTypes(); break; case 'getDevicesListCalendar': getDevicesListCalendar(); break;
case 'queryGroups': queryGroups(); break;
default: logServerConsole ('Action: '. $action); break; case 'getOwners': getOwners(); break;
case 'getDeviceTypes': getDeviceTypes(); break;
case 'getGroups': getGroups(); break;
case 'getLocations': getLocations(); break;
default: logServerConsole ('Action: '. $action); break;
} }
} }
//------------------------------------------------------------------------------
// Query Device Data
//------------------------------------------------------------------------------
function getDeviceData() {
global $db;
// Request Parameters
$periodDate = getDateFromPeriod();
$mac = $_REQUEST['mac'];
// Device Data
$sql = 'SELECT rowid, *,
CASE WHEN dev_AlertDeviceDown=1 AND dev_PresentLastScan=0 THEN "Down"
WHEN dev_PresentLastScan=1 THEN "On-line"
ELSE "Off-line" END as dev_Status
FROM Devices
WHERE dev_MAC="'. $mac .'" or cast(rowid as text)="'. $mac. '"';
$result = $db->query($sql);
$row = $result -> fetchArray (SQLITE3_ASSOC);
$deviceData = $row;
$mac = $deviceData['dev_MAC'];
$deviceData['dev_FirstConnection'] = formatDate ($row['dev_FirstConnection']); // Date formated
$deviceData['dev_LastConnection'] = formatDate ($row['dev_LastConnection']); // Date formated
$deviceData['dev_RandomMAC'] = ( in_array($mac[1], array("2","6","A","E","a","e")) ? 1 : 0);
// Count Totals
$condition = ' WHERE eve_MAC="'. $mac .'" AND eve_DateTime >= '. $periodDate;
// Connections
$sql = 'SELECT COUNT(*) FROM Sessions
WHERE ses_MAC="'. $mac .'"
AND ( ses_DateTimeConnection >= '. $periodDate .'
OR ses_DateTimeDisconnection >= '. $periodDate .'
OR ses_StillConnected = 1 )';
$result = $db->query($sql);
$row = $result -> fetchArray (SQLITE3_NUM);
$deviceData['dev_Sessions'] = $row[0];
// Events
$sql = 'SELECT COUNT(*) FROM Events '. $condition .' AND eve_EventType <> "Connected" AND eve_EventType <> "Disconnected" ';
$result = $db->query($sql);
$row = $result -> fetchArray (SQLITE3_NUM);
$deviceData['dev_Events'] = $row[0];
// Down Alerts
$sql = 'SELECT COUNT(*) FROM Events '. $condition .' AND eve_EventType = "Device Down"';
$result = $db->query($sql);
$row = $result -> fetchArray (SQLITE3_NUM);
$deviceData['dev_DownAlerts'] = $row[0];
// Presence hours
$sql = 'SELECT CAST(( MAX (0, SUM (julianday (IFNULL (ses_DateTimeDisconnection, DATETIME("now","localtime")))
- julianday (CASE WHEN ses_DateTimeConnection < '. $periodDate .' THEN '. $periodDate .'
ELSE ses_DateTimeConnection END)) *24 )) AS INT)
FROM Sessions
WHERE ses_MAC="'. $mac .'"
AND ses_DateTimeConnection IS NOT NULL
AND (ses_DateTimeDisconnection IS NOT NULL OR ses_StillConnected = 1 )
AND ( ses_DateTimeConnection >= '. $periodDate .'
OR ses_DateTimeDisconnection >= '. $periodDate .'
OR ses_StillConnected = 1 )';
$result = $db->query($sql);
$row = $result -> fetchArray (SQLITE3_NUM);
$deviceData['dev_PresenceHours'] = round ($row[0]);
// Return json
echo (json_encode ($deviceData));
}
//------------------------------------------------------------------------------
// Update Device Data
//------------------------------------------------------------------------------
function setDeviceData() {
global $db;
// sql
$sql = 'UPDATE Devices SET
dev_Name = "'. quotes($_REQUEST['name']) .'",
dev_Owner = "'. quotes($_REQUEST['owner']) .'",
dev_DeviceType = "'. quotes($_REQUEST['type']) .'",
dev_Vendor = "'. quotes($_REQUEST['vendor']) .'",
dev_Favorite = "'. quotes($_REQUEST['favorite']) .'",
dev_Group = "'. quotes($_REQUEST['group']) .'",
dev_Location = "'. quotes($_REQUEST['location']) .'",
dev_Comments = "'. quotes($_REQUEST['comments']) .'",
dev_StaticIP = "'. quotes($_REQUEST['staticIP']) .'",
dev_ScanCycle = "'. quotes($_REQUEST['scancycle']) .'",
dev_AlertEvents = "'. quotes($_REQUEST['alertevents']) .'",
dev_AlertDeviceDown = "'. quotes($_REQUEST['alertdown']) .'",
dev_SkipRepeated = "'. quotes($_REQUEST['skiprepeated']) .'",
dev_NewDevice = "'. quotes($_REQUEST['newdevice']) .'",
dev_Archived = "'. quotes($_REQUEST['archived']) .'"
WHERE dev_MAC="' . $_REQUEST['mac'] .'"';
// update Data
$result = $db->query($sql);
// check result
if ($result == TRUE) {
echo "Device updated successfully";
} else {
echo "Error updating device\n\n$sql \n\n". $db->lastErrorMsg();
}
}
//------------------------------------------------------------------------------
// Delete Device
//------------------------------------------------------------------------------
function deleteDevice() {
global $db;
// sql
$sql = 'DELETE FROM Devices WHERE dev_MAC="' . $_REQUEST['mac'] .'"';
// execute sql
$result = $db->query($sql);
// check result
if ($result == TRUE) {
echo "Device deleted successfully";
} else {
echo "Error deleting device\n\n$sql \n\n". $db->lastErrorMsg();
}
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Query total numbers of Devices by status // Query total numbers of Devices by status
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
function queryTotals() { function getDevicesTotals() {
global $db; global $db;
// All // All
$result = $db->query('SELECT COUNT(*) FROM Devices '); $result = $db->query('SELECT COUNT(*) FROM Devices '. getDeviceCondition ('all'));
$row = $result -> fetchArray (SQLITE3_NUM); $row = $result -> fetchArray (SQLITE3_NUM);
$devices = $row[0]; $devices = $row[0];
// Connected // On-Line
$result = $db->query('SELECT COUNT(*) FROM Devices ' . getDeviceCondition ('connected') ); $result = $db->query('SELECT COUNT(*) FROM Devices '. getDeviceCondition ('connected') );
$row = $result -> fetchArray (SQLITE3_NUM); $row = $result -> fetchArray (SQLITE3_NUM);
$connected = $row[0]; $connected = $row[0];
// Favorites
$result = $db->query('SELECT COUNT(*) FROM Devices '. getDeviceCondition ('favorites') );
$row = $result -> fetchArray (SQLITE3_NUM);
$favorites = $row[0];
// New // New
$result = $db->query('SELECT COUNT(*) FROM Devices ' . getDeviceCondition ('new') ); $result = $db->query('SELECT COUNT(*) FROM Devices '. getDeviceCondition ('new') );
$row = $result -> fetchArray (SQLITE3_NUM); $row = $result -> fetchArray (SQLITE3_NUM);
$newDevices = $row[0]; $newDevices = $row[0];
// Down Alerts // Down Alerts
$result = $db->query('SELECT COUNT(*) FROM Devices ' . getDeviceCondition ('down')); $result = $db->query('SELECT COUNT(*) FROM Devices '. getDeviceCondition ('down'));
$row = $result -> fetchArray (SQLITE3_NUM); $row = $result -> fetchArray (SQLITE3_NUM);
$devicesDownAlert = $row[0]; $downAlert = $row[0];
echo (json_encode (array ($devices, $connected, $newDevices, $devicesDownAlert))); // Archived
$result = $db->query('SELECT COUNT(*) FROM Devices '. getDeviceCondition ('archived'));
$row = $result -> fetchArray (SQLITE3_NUM);
$archived = $row[0];
echo (json_encode (array ($devices, $connected, $favorites, $newDevices, $downAlert, $archived)));
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Query the List of devices in a determined Status // Query the List of devices in a determined Status
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
function queryList() { function getDevicesList() {
global $db; global $db;
// Request Parameters
$periodDate = getDateFromPeriod();
// SQL // SQL
$condition = getDeviceCondition ($_REQUEST['status']); $condition = getDeviceCondition ($_REQUEST['status']);
$result = $db->query('SELECT *, $sql = 'SELECT rowid, *, CASE
CASE WHEN dev_AlertDeviceDown=1 AND dev_PresentLastScan=0 THEN "Down" WHEN dev_AlertDeviceDown=1 AND dev_PresentLastScan=0 THEN "Down"
WHEN dev_FirstConnection >= ' . $periodDate . ' THEN "New" WHEN dev_NewDevice=1 THEN "New"
WHEN dev_PresentLastScan=1 THEN "On-line" WHEN dev_PresentLastScan=1 THEN "On-line"
ELSE "Off-line" ELSE "Off-line"
END AS dev_Status END AS dev_Status
FROM Devices ' . $condition); FROM Devices '. $condition;
$result = $db->query($sql);
// arrays of rows // arrays of rows
$tableData = array(); $tableData = array();
@@ -91,10 +243,12 @@ function queryList() {
formatDate ($row['dev_FirstConnection']), formatDate ($row['dev_FirstConnection']),
formatDate ($row['dev_LastConnection']), formatDate ($row['dev_LastConnection']),
$row['dev_LastIP'], $row['dev_LastIP'],
( in_array($row['dev_MAC'][1], array("2","6","A","E","a","e")) ? 1 : 0),
$row['dev_Status'], $row['dev_Status'],
$row['dev_MAC'], // MAC (hidden) $row['dev_MAC'], // MAC (hidden)
formatIPlong ($row['dev_LastIP']) // IP orderable formatIPlong ($row['dev_LastIP']), // IP orderable
); $row['rowid'] // Rowid (hidden)
);
} }
// Control no rows // Control no rows
@@ -106,130 +260,13 @@ function queryList() {
echo (json_encode ($tableData)); echo (json_encode ($tableData));
} }
//------------------------------------------------------------------------------
// Query the List of Owners
//------------------------------------------------------------------------------
function queryOwners() {
global $db;
// SQL
$result = $db->query('SELECT DISTINCT 1 as dev_Order, dev_Owner
FROM Devices
WHERE dev_Owner <> "(unknown)" AND dev_Owner <> ""
AND dev_Favorite = 1
UNION
SELECT DISTINCT 2 as dev_Order, dev_Owner
FROM Devices
WHERE dev_Owner <> "(unknown)" AND dev_Owner <> ""
AND dev_Favorite = 0
AND dev_Owner NOT IN (SELECT dev_Owner FROM Devices WHERE dev_Favorite = 1)
ORDER BY 1,2 ');
// arrays of rows
$tableData = array();
while ($row = $result -> fetchArray (SQLITE3_ASSOC)) {
$tableData[] = array ('order' => $row['dev_Order'],
'name' => $row['dev_Owner']);
}
// Return json
echo (json_encode ($tableData));
}
//------------------------------------------------------------------------------
// Query the List of types
//------------------------------------------------------------------------------
function queryDeviceTypes() {
global $db;
// SQL
$result = $db->query('SELECT DISTINCT 9 as dev_Order, dev_DeviceType
FROM Devices
WHERE dev_DeviceType NOT IN ("",
"Smartphone", "Tablet",
"Laptop", "Mini PC", "PC", "Printer", "Server",
"Game Console", "SmartTV", "TV Decoder", "Virtual Assistance",
"Clock", "House Appliance", "Phone", "Radio",
"AP", "NAS", "PLC", "Router")
UNION SELECT 1 as dev_Order, "Smartphone"
UNION SELECT 1 as dev_Order, "Tablet"
UNION SELECT 2 as dev_Order, "Laptop"
UNION SELECT 2 as dev_Order, "Mini PC"
UNION SELECT 2 as dev_Order, "PC"
UNION SELECT 2 as dev_Order, "Printer"
UNION SELECT 2 as dev_Order, "Server"
UNION SELECT 3 as dev_Order, "Game Console"
UNION SELECT 3 as dev_Order, "SmartTV"
UNION SELECT 3 as dev_Order, "TV Decoder"
UNION SELECT 3 as dev_Order, "Virtual Assistance"
UNION SELECT 4 as dev_Order, "Clock"
UNION SELECT 4 as dev_Order, "House Appliance"
UNION SELECT 4 as dev_Order, "Phone"
UNION SELECT 4 as dev_Order, "Radio"
UNION SELECT 5 as dev_Order, "AP"
UNION SELECT 5 as dev_Order, "NAS"
UNION SELECT 5 as dev_Order, "PLC"
UNION SELECT 5 as dev_Order, "Router"
UNION SELECT 10 as dev_Order, "Other"
ORDER BY 1,2 ');
// arrays of rows
$tableData = array();
while ($row = $result -> fetchArray (SQLITE3_ASSOC)) {
$tableData[] = array ('order' => $row['dev_Order'],
'name' => $row['dev_DeviceType']);
}
// Return json
echo (json_encode ($tableData));
}
//------------------------------------------------------------------------------
// Query the List of groups
//------------------------------------------------------------------------------
function queryGroups() {
global $db;
// SQL
$result = $db->query('SELECT DISTINCT 1 as dev_Order, dev_Group
FROM Devices
WHERE dev_Group <> "(unknown)" AND dev_Group <> "Others" AND dev_Group <> ""
UNION SELECT 1 as dev_Order, "Always on"
UNION SELECT 1 as dev_Order, "Friends"
UNION SELECT 1 as dev_Order, "Personal"
UNION SELECT 2 as dev_Order, "Others"
ORDER BY 1,2 ');
// arrays of rows
$tableData = array();
while ($row = $result -> fetchArray (SQLITE3_ASSOC)) {
$tableData[] = array ('order' => $row['dev_Order'],
'name' => $row['dev_Group']);
}
// Return json
echo (json_encode ($tableData));
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Query the List of devices for calendar // Query the List of devices for calendar
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
function queryCalendarList() { function getDevicesListCalendar() {
global $db; global $db;
// Request Parameters
$periodDate = getDateFromPeriod();
// SQL // SQL
$condition = getDeviceCondition ($_REQUEST['status']); $condition = getDeviceCondition ($_REQUEST['status']);
$result = $db->query('SELECT * FROM Devices ' . $condition); $result = $db->query('SELECT * FROM Devices ' . $condition);
@@ -252,67 +289,178 @@ function queryCalendarList() {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Query Device Data // Query the List of Owners
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
function queryDeviceData() { function getOwners() {
global $db; global $db;
// Request Parameters // SQL
$periodDate = getDateFromPeriod(); $sql = 'SELECT DISTINCT 1 as dev_Order, dev_Owner
$mac = $_REQUEST['mac']; FROM Devices
WHERE dev_Owner <> "(unknown)" AND dev_Owner <> ""
// Device Data AND dev_Favorite = 1
$result = $db->query('SELECT *, UNION
CASE WHEN dev_AlertDeviceDown=1 AND dev_PresentLastScan=0 THEN "Down" SELECT DISTINCT 2 as dev_Order, dev_Owner
WHEN dev_PresentLastScan=1 THEN "On-line" FROM Devices
ELSE "Off-line" END as dev_Status WHERE dev_Owner <> "(unknown)" AND dev_Owner <> ""
FROM Devices AND dev_Favorite = 0
WHERE dev_MAC="' . $mac .'"'); AND dev_Owner NOT IN
(SELECT dev_Owner FROM Devices WHERE dev_Favorite = 1)
$row = $result -> fetchArray (SQLITE3_ASSOC); ORDER BY 1,2 ';
$deviceData = $row; $result = $db->query($sql);
$deviceData['dev_FirstConnection'] = formatDate ($row['dev_FirstConnection']); // Date formated
$deviceData['dev_LastConnection'] = formatDate ($row['dev_LastConnection']); // Date formated
// Count Totals
$condicion = ' WHERE eve_MAC="' . $mac .'" AND eve_DateTime >= ' . $periodDate;
// Connections
$result = $db->query('SELECT COUNT(*) FROM Sessions
WHERE ses_MAC="' . $mac .'"
AND ( ses_DateTimeConnection >= ' . $periodDate . '
OR ses_DateTimeDisconnection >= ' . $periodDate . '
OR ses_StillConnected = 1 ) ');
$row = $result -> fetchArray (SQLITE3_NUM);
$deviceData['dev_Sessions'] = $row[0];
// Events
$result = $db->query('SELECT COUNT(*) FROM Events ' . $condicion . ' AND eve_EventType <> "Connected" AND eve_EventType <> "Disconnected" ');
$row = $result -> fetchArray (SQLITE3_NUM);
$deviceData['dev_Events'] = $row[0];
// Donw Alerts
$result = $db->query('SELECT COUNT(*) FROM Events ' . $condicion . ' AND eve_EventType = "Device Down"');
$row = $result -> fetchArray (SQLITE3_NUM);
$deviceData['dev_DownAlerts'] = $row[0];
// Presence hours
$result = $db->query('SELECT SUM (julianday (IFNULL (ses_DateTimeDisconnection, DATETIME("now")))
- julianday (CASE WHEN ses_DateTimeConnection < ' . $periodDate . ' THEN ' . $periodDate . '
ELSE ses_DateTimeConnection END)) *24
FROM Sessions
WHERE ses_MAC="' . $mac .'"
AND ses_DateTimeConnection IS NOT NULL
AND (ses_DateTimeDisconnection IS NOT NULL OR ses_StillConnected = 1 )
AND ( ses_DateTimeConnection >= ' . $periodDate . '
OR ses_DateTimeDisconnection >= ' . $periodDate . '
OR ses_StillConnected = 1 ) ');
$row = $result -> fetchArray (SQLITE3_NUM);
$deviceData['dev_PresenceHours'] = round ($row[0]);
// arrays of rows
$tableData = array();
while ($row = $result -> fetchArray (SQLITE3_ASSOC)) {
$tableData[] = array ('order' => $row['dev_Order'],
'name' => $row['dev_Owner']);
}
// Return json // Return json
echo (json_encode ($deviceData)); echo (json_encode ($tableData));
}
//------------------------------------------------------------------------------
// Query the List of types
//------------------------------------------------------------------------------
function getDeviceTypes() {
global $db;
// SQL
$sql = 'SELECT DISTINCT 9 as dev_Order, dev_DeviceType
FROM Devices
WHERE dev_DeviceType NOT IN ("",
"Smartphone", "Tablet",
"Laptop", "Mini PC", "PC", "Printer", "Server", "Singleboard Computer (SBC)",
"Game Console", "SmartTV", "TV Decoder", "Virtual Assistance",
"Clock", "House Appliance", "Phone", "Radio",
"AP", "NAS", "PLC", "Router")
UNION SELECT 1 as dev_Order, "Smartphone"
UNION SELECT 1 as dev_Order, "Tablet"
UNION SELECT 2 as dev_Order, "Laptop"
UNION SELECT 2 as dev_Order, "Mini PC"
UNION SELECT 2 as dev_Order, "PC"
UNION SELECT 2 as dev_Order, "Printer"
UNION SELECT 2 as dev_Order, "Server"
UNION SELECT 2 as dev_Order, "Singleboard Computer (SBC)"
UNION SELECT 3 as dev_Order, "Domotic"
UNION SELECT 3 as dev_Order, "Game Console"
UNION SELECT 3 as dev_Order, "SmartTV"
UNION SELECT 3 as dev_Order, "TV Decoder"
UNION SELECT 3 as dev_Order, "Virtual Assistance"
UNION SELECT 4 as dev_Order, "Clock"
UNION SELECT 4 as dev_Order, "House Appliance"
UNION SELECT 4 as dev_Order, "Phone"
UNION SELECT 4 as dev_Order, "Radio"
UNION SELECT 5 as dev_Order, "AP"
UNION SELECT 5 as dev_Order, "NAS"
UNION SELECT 5 as dev_Order, "PLC"
UNION SELECT 5 as dev_Order, "Router"
UNION SELECT 5 as dev_Order, "USB LAN Adapter"
UNION SELECT 5 as dev_Order, "USB WIFI Adapter"
UNION SELECT 10 as dev_Order, "Other"
ORDER BY 1,2';
$result = $db->query($sql);
// arrays of rows
$tableData = array();
while ($row = $result -> fetchArray (SQLITE3_ASSOC)) {
$tableData[] = array ('order' => $row['dev_Order'],
'name' => $row['dev_DeviceType']);
}
// Return json
echo (json_encode ($tableData));
}
//------------------------------------------------------------------------------
// Query the List of groups
//------------------------------------------------------------------------------
function getGroups() {
global $db;
// SQL
$sql = 'SELECT DISTINCT 1 as dev_Order, dev_Group
FROM Devices
WHERE dev_Group NOT IN ("(unknown)", "Others") AND dev_Group <> ""
UNION SELECT 1 as dev_Order, "Always on"
UNION SELECT 1 as dev_Order, "Friends"
UNION SELECT 1 as dev_Order, "Personal"
UNION SELECT 2 as dev_Order, "Others"
ORDER BY 1,2 ';
$result = $db->query($sql);
// arrays of rows
$tableData = array();
while ($row = $result -> fetchArray (SQLITE3_ASSOC)) {
$tableData[] = array ('order' => $row['dev_Order'],
'name' => $row['dev_Group']);
}
// Return json
echo (json_encode ($tableData));
}
//------------------------------------------------------------------------------
// Query the List of locations
//------------------------------------------------------------------------------
function getLocations() {
global $db;
// SQL
$sql = 'SELECT DISTINCT 9 as dev_Order, dev_Location
FROM Devices
WHERE dev_Location <> ""
AND dev_Location NOT IN (
"Bathroom", "Bedroom", "Dining room", "Hallway",
"Kitchen", "Laundry", "Living room", "Study",
"Attic", "Basement", "Garage",
"Back yard", "Garden", "Terrace",
"Other")
UNION SELECT 1 as dev_Order, "Bathroom"
UNION SELECT 1 as dev_Order, "Bedroom"
UNION SELECT 1 as dev_Order, "Dining room"
UNION SELECT 1 as dev_Order, "Hall"
UNION SELECT 1 as dev_Order, "Kitchen"
UNION SELECT 1 as dev_Order, "Laundry"
UNION SELECT 1 as dev_Order, "Living room"
UNION SELECT 1 as dev_Order, "Study"
UNION SELECT 2 as dev_Order, "Attic"
UNION SELECT 2 as dev_Order, "Basement"
UNION SELECT 2 as dev_Order, "Garage"
UNION SELECT 3 as dev_Order, "Back yard"
UNION SELECT 3 as dev_Order, "Garden"
UNION SELECT 3 as dev_Order, "Terrace"
UNION SELECT 10 as dev_Order, "Other"
ORDER BY 1,2 ';
$result = $db->query($sql);
// arrays of rows
$tableData = array();
while ($row = $result -> fetchArray (SQLITE3_ASSOC)) {
$tableData[] = array ('order' => $row['dev_Order'],
'name' => $row['dev_Location']);
}
// Return json
echo (json_encode ($tableData));
} }
@@ -320,58 +468,15 @@ function queryDeviceData() {
// Status Where conditions // Status Where conditions
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
function getDeviceCondition ($deviceStatus) { function getDeviceCondition ($deviceStatus) {
// Request Parameters
$periodDate = getDateFromPeriod();
switch ($deviceStatus) { switch ($deviceStatus) {
case 'all': case 'all': return 'WHERE dev_Archived=0'; break;
return ''; case 'connected': return 'WHERE dev_Archived=0 AND dev_PresentLastScan=1'; break;
case 'connected': case 'favorites': return 'WHERE dev_Archived=0 AND dev_Favorite=1'; break;
return 'WHERE dev_PresentLastScan=1'; case 'new': return 'WHERE dev_Archived=0 AND dev_NewDevice=1'; break;
case 'new': case 'down': return 'WHERE dev_Archived=0 AND dev_AlertDeviceDown=1 AND dev_PresentLastScan=0'; break;
return 'WHERE dev_FirstConnection >= ' . $periodDate; case 'archived': return 'WHERE dev_Archived=1'; break;
case 'down': default: return 'WHERE 1=0'; break;
return 'WHERE dev_AlertDeviceDown=1 AND dev_PresentLastScan=0';
case 'favorites':
return 'WHERE dev_Favorite=1';
default:
return 'WHERE 1=0';
} }
} }
//------------------------------------------------------------------------------
// Update Device Data
//------------------------------------------------------------------------------
function updateDeviceData() {
global $db;
// sql
$sql = 'UPDATE Devices SET
dev_Name = "'. $_REQUEST['name'] .'",
dev_Owner = "'. $_REQUEST['owner'] .'",
dev_DeviceType = "'. $_REQUEST['type'] .'",
dev_Vendor = "'. $_REQUEST['vendor'] .'",
dev_Favorite = "'. $_REQUEST['favorite'] .'",
dev_Group = "'. $_REQUEST['group'] .'",
dev_Comments = "'. $_REQUEST['comments'] .'",
dev_StaticIP = "'. $_REQUEST['staticIP'] .'",
dev_ScanCycle = "'. $_REQUEST['scancycle'] .'",
dev_AlertEvents = "'. $_REQUEST['alertevents'] .'",
dev_AlertDeviceDown = "'. $_REQUEST['alertdown'] .'",
dev_SkipRepeated = "'. $_REQUEST['skiprepeated'] .'"
WHERE dev_MAC="' . $_REQUEST['mac'] .'"';
// update Data
$result = $db->query($sql);
// check result
if ($result == TRUE) {
echo "Device updated successfully";
} else {
echo "Error updating device\n\n". $sql .'\n\n' . $db->lastErrorMsg();
}
}
?> ?>

View File

@@ -1,9 +1,20 @@
<?php <?php
//------------------------------------------------------------------------------
// Pi.Alert
// Open Source Network Guard / WIFI & LAN intrusion detector
//
// events.php - Front module. Server side. Manage Events
//------------------------------------------------------------------------------
// Puche 2021 pi.alert.application@gmail.com GNU GPLv3
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// External files // External files
require 'db.php'; require 'db.php';
require 'util.php'; require 'util.php';
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Action selector // Action selector
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@@ -17,13 +28,13 @@
if (isset ($_REQUEST['action']) && !empty ($_REQUEST['action'])) { if (isset ($_REQUEST['action']) && !empty ($_REQUEST['action'])) {
$action = $_REQUEST['action']; $action = $_REQUEST['action'];
switch ($action) { switch ($action) {
case 'totals': queryTotals(); break; case 'getEventsTotals': getEventsTotals(); break;
case 'list': queryList(); break; case 'getEvents': getEvents(); break;
case 'deviceSessions': queryDeviceSessions(); break; case 'getDeviceSessions': getDeviceSessions(); break;
case 'devicePresence': queryDevicePresence(); break; case 'getDevicePresence': getDevicePresence(); break;
case 'deviceEvents': queryDeviceEvents(); break; case 'getDeviceEvents': getDeviceEvents(); break;
case 'calendarPresence': queryCalendarPresence(); break; case 'getEventsCalendar': getEventsCalendar(); break;
default: logServerConsole ('Action: '. $action); break; default: logServerConsole ('Action: '. $action); break;
} }
} }
@@ -31,7 +42,7 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Query total numbers of Events // Query total numbers of Events
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
function queryTotals() { function getEventsTotals() {
global $db; global $db;
// Request Parameters // Request Parameters
@@ -86,7 +97,7 @@ function queryTotals() {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Query the List of events // Query the List of events
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
function queryList() { function getEvents() {
global $db; global $db;
// Request Parameters // Request Parameters
@@ -104,30 +115,18 @@ function queryList() {
// SQL Variations for status // SQL Variations for status
switch ($type) { switch ($type) {
case 'all': case 'all': $SQL = $SQL1; break;
$SQL = $SQL1;
break;
case 'sessions': case 'sessions':
$SQL = $SQL2 . ' WHERE ( ses_DateTimeConnection >= '. $periodDate .' $SQL = $SQL2 . ' WHERE ( ses_DateTimeConnection >= '. $periodDate .' OR ses_DateTimeDisconnection >= '. $periodDate .' OR ses_StillConnected = 1 ) ';
OR ses_DateTimeDisconnection >= '. $periodDate .'
OR ses_StillConnected = 1 ) ';
break; break;
case 'missing': case 'missing':
$SQL = $SQL2 . ' WHERE (ses_DateTimeConnection IS NULL AND ses_DateTimeDisconnection >= '. $periodDate .' ) $SQL = $SQL2 . ' WHERE (ses_DateTimeConnection IS NULL AND ses_DateTimeDisconnection >= '. $periodDate .' )
OR (ses_DateTimeDisconnection IS NULL AND ses_StillConnected = 0 AND ses_DateTimeConnection >= '. $periodDate .' )'; OR (ses_DateTimeDisconnection IS NULL AND ses_StillConnected = 0 AND ses_DateTimeConnection >= '. $periodDate .' )';
break; break;
case 'voided': case 'voided': $SQL = $SQL1 .' AND eve_EventType LIKE "VOIDED%" '; break;
$SQL = $SQL1 .' AND eve_EventType LIKE "VOIDED%" '; case 'new': $SQL = $SQL1 .' AND eve_EventType = "New Device" '; break;
break; case 'down': $SQL = $SQL1 .' AND eve_EventType = "Device Down" '; break;
case 'new': default: $SQL = $SQL1 .' AND 1==0 '; break;
$SQL = $SQL1 .' AND eve_EventType = "New Device" ';
break;
case 'down':
$SQL = $SQL1 .' AND eve_EventType = "Device Down" ';
break;
default:
$SQL = $SQL1 .' AND 1==0 ';
break;
} }
// Query // Query
@@ -187,7 +186,7 @@ function queryList() {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Query Device Sessions // Query Device Sessions
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
function queryDeviceSessions() { function getDeviceSessions() {
global $db; global $db;
// Request Parameters // Request Parameters
@@ -195,15 +194,16 @@ function queryDeviceSessions() {
$periodDate = getDateFromPeriod(); $periodDate = getDateFromPeriod();
// SQL // SQL
$result = $db->query('SELECT IFNULL (ses_DateTimeConnection, ses_DateTimeDisconnection) ses_DateTimeOrder, $SQL = 'SELECT IFNULL (ses_DateTimeConnection, ses_DateTimeDisconnection) ses_DateTimeOrder,
ses_EventTypeConnection, ses_DateTimeConnection, ses_EventTypeConnection, ses_DateTimeConnection,
ses_EventTypeDisconnection, ses_DateTimeDisconnection, ses_StillConnected, ses_EventTypeDisconnection, ses_DateTimeDisconnection, ses_StillConnected,
ses_IP, ses_AdditionalInfo ses_IP, ses_AdditionalInfo
FROM Sessions FROM Sessions
WHERE ses_MAC="' . $mac .'" WHERE ses_MAC="' . $mac .'"
AND ( ses_DateTimeConnection >= '. $periodDate .' AND ( ses_DateTimeConnection >= '. $periodDate .'
OR ses_DateTimeDisconnection >= '. $periodDate .' OR ses_DateTimeDisconnection >= '. $periodDate .'
OR ses_StillConnected = 1 ) '); OR ses_StillConnected = 1 ) ';
$result = $db->query($SQL);
// arrays of rows // arrays of rows
$tableData = array(); $tableData = array();
@@ -228,7 +228,7 @@ function queryDeviceSessions() {
if ($row['ses_EventTypeConnection'] == '<missing event>' || $row['ses_EventTypeDisconnection'] == '<missing event>') { if ($row['ses_EventTypeConnection'] == '<missing event>' || $row['ses_EventTypeDisconnection'] == '<missing event>') {
$dur = '...'; $dur = '...';
} elseif ($row['ses_StillConnected'] == true) { } elseif ($row['ses_StillConnected'] == true) {
$dur = formatDateDiff ($row['ses_DateTimeConnection'], ''); //******************************************************************************************* $dur = formatDateDiff ($row['ses_DateTimeConnection'], ''); //***********
} else { } else {
$dur = formatDateDiff ($row['ses_DateTimeConnection'], $row['ses_DateTimeDisconnection']); $dur = formatDateDiff ($row['ses_DateTimeConnection'], $row['ses_DateTimeDisconnection']);
} }
@@ -256,7 +256,7 @@ function queryDeviceSessions() {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Query Device Presence Calendar // Query Device Presence Calendar
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
function queryDevicePresence() { function getDevicePresence() {
global $db; global $db;
// Request Parameters // Request Parameters
@@ -266,24 +266,26 @@ function queryDevicePresence() {
$endDate = '"'. formatDateISO ($_REQUEST ['end']) .'"'; $endDate = '"'. formatDateISO ($_REQUEST ['end']) .'"';
// SQL // SQL
$result = $db->query('SELECT ses_EventTypeConnection, ses_DateTimeConnection, $SQL = 'SELECT ses_EventTypeConnection, ses_DateTimeConnection,
ses_EventTypeDisconnection, ses_DateTimeDisconnection, ses_IP, ses_AdditionalInfo, ses_EventTypeDisconnection, ses_DateTimeDisconnection, ses_IP, ses_AdditionalInfo,
CASE WHEN ses_EventTypeConnection = "<missing event>" THEN CASE
IFNULL ((SELECT MAX(ses_DateTimeDisconnection) FROM Sessions AS SES2 WHERE SES2.ses_MAC = SES1.ses_MAC AND SES2.ses_DateTimeDisconnection < SES1.ses_DateTimeDisconnection), DATETIME(ses_DateTimeDisconnection, "-1 hour")) WHEN ses_EventTypeConnection = "<missing event>" THEN
ELSE ses_DateTimeConnection IFNULL ((SELECT MAX(ses_DateTimeDisconnection) FROM Sessions AS SES2 WHERE SES2.ses_MAC = SES1.ses_MAC AND SES2.ses_DateTimeDisconnection < SES1.ses_DateTimeDisconnection), DATETIME(ses_DateTimeDisconnection, "-1 hour"))
END AS ses_DateTimeConnectionCorrected, ELSE ses_DateTimeConnection
END AS ses_DateTimeConnectionCorrected,
CASE WHEN ses_EventTypeDisconnection = "<missing event>" THEN CASE
(SELECT MIN(ses_DateTimeConnection) FROM Sessions AS SES2 WHERE SES2.ses_MAC = SES1.ses_MAC AND SES2.ses_DateTimeConnection > SES1.ses_DateTimeConnection) WHEN ses_EventTypeDisconnection = "<missing event>" THEN
ELSE ses_DateTimeDisconnection (SELECT MIN(ses_DateTimeConnection) FROM Sessions AS SES2 WHERE SES2.ses_MAC = SES1.ses_MAC AND SES2.ses_DateTimeConnection > SES1.ses_DateTimeConnection)
END AS ses_DateTimeDisconnectionCorrected ELSE ses_DateTimeDisconnection
END AS ses_DateTimeDisconnectionCorrected
FROM Sessions AS SES1 FROM Sessions AS SES1
WHERE ses_MAC="' . $mac .'" WHERE ses_MAC="' . $mac .'"
AND (ses_DateTimeConnectionCorrected <= date('. $endDate .') AND (ses_DateTimeConnectionCorrected <= date('. $endDate .')
AND (ses_DateTimeDisconnectionCorrected >= date('. $startDate .') OR ses_StillConnected = 1 )) AND (ses_DateTimeDisconnectionCorrected >= date('. $startDate .') OR ses_StillConnected = 1 )) ';
'); $result = $db->query($SQL);
// arrays of rows // arrays of rows
while ($row = $result -> fetchArray (SQLITE3_ASSOC)) { while ($row = $result -> fetchArray (SQLITE3_ASSOC)) {
@@ -300,10 +302,6 @@ function queryDevicePresence() {
'IP: ' . $row['ses_IP']; 'IP: ' . $row['ses_IP'];
// Save row data // Save row data
// 'start' => formatDateISO ($row['ses_DateTimeConnectionCorrected']),
// 'end' => formatDateISO ($row['ses_DateTimeDisconnectionCorrected']),
// 'start' => $row['ses_DateTimeConnectionCorrected'],
// 'end' => $row['ses_DateTimeDisconnectionCorrected'],
$tableData[] = array( $tableData[] = array(
'title' => '', 'title' => '',
'start' => formatDateISO ($row['ses_DateTimeConnectionCorrected']), 'start' => formatDateISO ($row['ses_DateTimeConnectionCorrected']),
@@ -326,32 +324,33 @@ function queryDevicePresence() {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Query Presence Calendar for all Devices // Query Presence Calendar for all Devices
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
function queryCalendarPresence() { function getEventsCalendar() {
global $db; global $db;
// Request Parameters // Request Parameters
$periodDate = getDateFromPeriod();
$startDate = '"'. $_REQUEST ['start'] .'"'; $startDate = '"'. $_REQUEST ['start'] .'"';
$endDate = '"'. $_REQUEST ['end'] .'"'; $endDate = '"'. $_REQUEST ['end'] .'"';
// SQL // SQL
$result = $db->query('SELECT ses_MAC, ses_EventTypeConnection, ses_DateTimeConnection, $SQL = 'SELECT ses_MAC, ses_EventTypeConnection, ses_DateTimeConnection,
ses_EventTypeDisconnection, ses_DateTimeDisconnection, ses_IP, ses_AdditionalInfo, ses_EventTypeDisconnection, ses_DateTimeDisconnection, ses_IP, ses_AdditionalInfo,
CASE WHEN ses_EventTypeConnection = "<missing event>" THEN CASE
IFNULL ((SELECT MAX(ses_DateTimeDisconnection) FROM Sessions AS SES2 WHERE SES2.ses_MAC = SES1.ses_MAC AND SES2.ses_DateTimeDisconnection < SES1.ses_DateTimeDisconnection), DATETIME(ses_DateTimeDisconnection, "-1 hour")) WHEN ses_EventTypeConnection = "<missing event>" THEN
ELSE ses_DateTimeConnection IFNULL ((SELECT MAX(ses_DateTimeDisconnection) FROM Sessions AS SES2 WHERE SES2.ses_MAC = SES1.ses_MAC AND SES2.ses_DateTimeDisconnection < SES1.ses_DateTimeDisconnection), DATETIME(ses_DateTimeDisconnection, "-1 hour"))
END AS ses_DateTimeConnectionCorrected, ELSE ses_DateTimeConnection
END AS ses_DateTimeConnectionCorrected,
CASE WHEN ses_EventTypeDisconnection = "<missing event>" THEN CASE
(SELECT MIN(ses_DateTimeConnection) FROM Sessions AS SES2 WHERE SES2.ses_MAC = SES1.ses_MAC AND SES2.ses_DateTimeConnection > SES1.ses_DateTimeConnection) WHEN ses_EventTypeDisconnection = "<missing event>" THEN
ELSE ses_DateTimeDisconnection (SELECT MIN(ses_DateTimeConnection) FROM Sessions AS SES2 WHERE SES2.ses_MAC = SES1.ses_MAC AND SES2.ses_DateTimeConnection > SES1.ses_DateTimeConnection)
END AS ses_DateTimeDisconnectionCorrected ELSE ses_DateTimeDisconnection
END AS ses_DateTimeDisconnectionCorrected
FROM Sessions AS SES1 FROM Sessions AS SES1
WHERE ( ses_DateTimeConnectionCorrected <= Date('. $endDate .') WHERE ( ses_DateTimeConnectionCorrected <= Date('. $endDate .')
AND (ses_DateTimeDisconnectionCorrected >= Date('. $startDate .') OR ses_StillConnected = 1 )) AND (ses_DateTimeDisconnectionCorrected >= Date('. $startDate .') OR ses_StillConnected = 1 )) ';
'); $result = $db->query($SQL);
// arrays of rows // arrays of rows
while ($row = $result -> fetchArray (SQLITE3_ASSOC)) { while ($row = $result -> fetchArray (SQLITE3_ASSOC)) {
@@ -392,7 +391,7 @@ function queryCalendarPresence() {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Query Device events // Query Device events
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
function queryDeviceEvents() { function getDeviceEvents() {
global $db; global $db;
// Request Parameters // Request Parameters
@@ -401,13 +400,13 @@ function queryDeviceEvents() {
$hideConnections = $_REQUEST ['hideConnections']; $hideConnections = $_REQUEST ['hideConnections'];
// SQL // SQL
$result = $db->query('SELECT eve_DateTime, eve_EventType, eve_IP, eve_AdditionalInfo $SQL = 'SELECT eve_DateTime, eve_EventType, eve_IP, eve_AdditionalInfo
FROM Events FROM Events
WHERE eve_MAC="'. $mac .'" AND eve_DateTime >= '. $periodDate .' WHERE eve_MAC="'. $mac .'" AND eve_DateTime >= '. $periodDate .'
AND ( (eve_EventType <> "Connected" AND eve_EventType <> "Disconnected" AND AND ( (eve_EventType <> "Connected" AND eve_EventType <> "Disconnected" AND
eve_EventType <> "VOIDED - Connected" AND eve_EventType <> "VOIDED - Disconnected") eve_EventType <> "VOIDED - Connected" AND eve_EventType <> "VOIDED - Disconnected")
OR "'. $hideConnections .'" = "false" ) OR "'. $hideConnections .'" = "false" ) ';
'); $result = $db->query($SQL);
// arrays of rows // arrays of rows
$tableData = array(); $tableData = array();
@@ -425,5 +424,4 @@ function queryDeviceEvents() {
echo (json_encode ($tableData)); echo (json_encode ($tableData));
} }
?> ?>

View File

@@ -0,0 +1,88 @@
<?php
//------------------------------------------------------------------------------
// Pi.Alert
// Open Source Network Guard / WIFI & LAN intrusion detector
//
// parameters.php - Front module. Server side. Manage Parameters
//------------------------------------------------------------------------------
// Puche 2021 pi.alert.application@gmail.com GNU GPLv3
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// External files
require 'db.php';
require 'util.php';
//------------------------------------------------------------------------------
// Action selector
//------------------------------------------------------------------------------
// Set maximum execution time to 15 seconds
ini_set ('max_execution_time','15');
// Open DB
OpenDB();
// Action functions
if (isset ($_REQUEST['action']) && !empty ($_REQUEST['action'])) {
$action = $_REQUEST['action'];
switch ($action) {
case 'get': getParameter(); break;
case 'set': setParameter(); break;
default: logServerConsole ('Action: '. $action); break;
}
}
//------------------------------------------------------------------------------
// Get Parameter Value
//------------------------------------------------------------------------------
function getParameter() {
global $db;
$parameter = $_REQUEST['parameter'];
$sql = 'SELECT par_Value FROM Parameters
WHERE par_ID="'. quotes($_REQUEST['parameter']) .'"';
$result = $db->query($sql);
$row = $result -> fetchArray (SQLITE3_NUM);
$value = $row[0];
echo (json_encode ($value));
}
//------------------------------------------------------------------------------
// Set Parameter Value
//------------------------------------------------------------------------------
function setParameter() {
global $db;
// Update value
$sql = 'UPDATE Parameters SET par_Value="'. quotes ($_REQUEST['value']) .'"
WHERE par_ID="'. quotes($_REQUEST['parameter']) .'"';
$result = $db->query($sql);
if (! $result == TRUE) {
echo "Error updating parameter\n\n$sql \n\n". $db->lastErrorMsg();
return;
}
$changes = $db->changes();
if ($changes == 0) {
// Insert new value
$sql = 'INSERT INTO Parameters (par_ID, par_Value)
VALUES ("'. quotes($_REQUEST['parameter']) .'",
"'. quotes($_REQUEST['value']) .'")';
$result = $db->query($sql);
if (! $result == TRUE) {
echo "Error creating parameter\n\n$sql \n\n". $db->lastErrorMsg();
return;
}
}
echo 'OK';
}
?>

View File

@@ -1,4 +1,13 @@
<?php <?php
//------------------------------------------------------------------------------
// Pi.Alert
// Open Source Network Guard / WIFI & LAN intrusion detector
//
// util.php - Front module. Server side. Common generic functions
//------------------------------------------------------------------------------
// Puche 2021 pi.alert.application@gmail.com GNU GPLv3
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Formatting data functions // Formatting data functions
@@ -37,7 +46,11 @@ function formatIPlong ($IP) {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
function getDateFromPeriod () { function getDateFromPeriod () {
$period = $_REQUEST['period']; $period = $_REQUEST['period'];
return '"'. date ('Y-m-d', strtotime ('+1 day -'.$period) ) .'"'; return '"'. date ('Y-m-d', strtotime ('+1 day -'. $period) ) .'"';
}
function quotes ($text) {
return str_replace ('"','""',$text);
} }
function logServerConsole ($text) { function logServerConsole ($text) {

View File

@@ -1,41 +1,65 @@
<!-- ---------------------------------------------------------------------------
# Pi.Alert
# Open Source Network Guard / WIFI & LAN intrusion detector
#
# footer.php - Front module. Common footer to all the web pages
#-------------------------------------------------------------------------------
# Puche 2021 pi.alert.application@gmail.com GNU GPLv3
#--------------------------------------------------------------------------- -->
<!-- Main Footer --> <!-- Main Footer -->
<footer class="main-footer"> <footer class="main-footer">
<!-- Default to the left --> <!-- Default to the left -->
&copy; 2021 Puche
<!-- &copy; 2020 Puche -->
<?php
$conf_file = '../config/version.conf';
$conf_data = parse_ini_file($conf_file);
echo '<span style="display:inline-block; transform: rotate(180deg)">&copy;</span> '. $conf_data['VERSION_YEAR'] .' Puche';
?>
<!-- To the right --> <!-- To the right -->
<div class="pull-right no-hidden-xs"> <div class="pull-right no-hidden-xs">
Pi.alert&nbsp&nbsp2.52&nbsp&nbsp<small>(2021-01-11)</small>
<!-- Pi.Alert 2.50 <small>(2019-12-30)</small> -->
<?php
$conf_file = '../config/version.conf';
$conf_data = parse_ini_file($conf_file);
echo 'Pi.Alert&nbsp&nbsp'. $conf_data['VERSION'] .'&nbsp&nbsp<small>('. $conf_data['VERSION_DATE'] .')</small>';
?>
</div> </div>
</footer> </footer>
<!-- ----------------------------------------------------------------------- -->
<!-- Control Sidebar --> <!-- Control Sidebar -->
<!-- DELETED --> <!-- DELETED -->
</div> </div>
<!-- ./wrapper --> <!-- ./wrapper -->
<!-- ----------------------------------------------------------------------- -->
<!-- REQUIRED JS SCRIPTS --> <!-- REQUIRED JS SCRIPTS -->
<!-- jQuery 3 --> <!-- jQuery 3 -->
<script src="lib/AdminLTE/bower_components/jquery/dist/jquery.min.js"></script> <script src="lib/AdminLTE/bower_components/jquery/dist/jquery.min.js"></script>
<!-- Bootstrap 3.3.7 --> <!-- Bootstrap 3.3.7 -->
<script src="lib/AdminLTE/bower_components/bootstrap/dist/js/bootstrap.min.js"></script> <script src="lib/AdminLTE/bower_components/bootstrap/dist/js/bootstrap.min.js"></script>
<!-- AdminLTE App --> <!-- AdminLTE App -->
<script src="lib/AdminLTE/dist/js/adminlte.min.js"></script> <script src="lib/AdminLTE/dist/js/adminlte.min.js"></script>
<!-- Optionally, you can add Slimscroll and FastClick plugins. <!-- Optionally, you can add Slimscroll and FastClick plugins.
Both of these plugins are recommended to enhance the Both of these plugins are recommended to enhance the
user experience. --> user experience. -->
<!-- SlimScroll --> <!-- SlimScroll -->
<script src="lib/AdminLTE/bower_components/jquery-slimscroll/jquery.slimscroll.min.js"></script> <!-- <script src="lib/AdminLTE/bower_components/jquery-slimscroll/jquery.slimscroll.min.js"></script> -->
<!-- FastClick --> <!-- FastClick -->
<script src="lib/AdminLTE/bower_components/fastclick/lib/fastclick.js"></script> <!-- <script src="lib/AdminLTE/bower_components/fastclick/lib/fastclick.js"></script> -->
<!-- Pi.Alert -------------------------------------------------------------- --> <!-- Pi.Alert -------------------------------------------------------------- -->
<script src="js/pialert_common.js"></script> <script src="js/pialert_common.js"></script>
</body> </body>
</html> </html>

View File

@@ -1,60 +1,77 @@
<!-- ---------------------------------------------------------------------------
# Pi.Alert
# Open Source Network Guard / WIFI & LAN intrusion detector
#
# header.php - Front module. Common header to all the web pages
#-------------------------------------------------------------------------------
# Puche 2021 pi.alert.application@gmail.com GNU GPLv3
#--------------------------------------------------------------------------- -->
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<!-- ----------------------------------------------------------------------- -->
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Pi.alert</title> <title>Pi.Alert</title>
<!-- Tell the browser to be responsive to screen width --> <!-- Tell the browser to be responsive to screen width -->
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport"> <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
<!-- Bootstrap 3.3.7 --> <!-- Bootstrap 3.3.7 -->
<link rel="stylesheet" href="lib/AdminLTE/bower_components/bootstrap/dist/css/bootstrap.min.css"> <link rel="stylesheet" href="lib/AdminLTE/bower_components/bootstrap/dist/css/bootstrap.min.css">
<!-- Font Awesome --> <!-- Font Awesome -->
<link rel="stylesheet" href="lib/AdminLTE/bower_components/font-awesome/css/font-awesome.min.css"> <link rel="stylesheet" href="lib/AdminLTE/bower_components/font-awesome/css/font-awesome.min.css">
<!-- Ionicons --> <!-- Ionicons -->
<link rel="stylesheet" href="lib/AdminLTE/bower_components/Ionicons/css/ionicons.min.css"> <link rel="stylesheet" href="lib/AdminLTE/bower_components/Ionicons/css/ionicons.min.css">
<!-- Theme style --> <!-- Theme style -->
<link rel="stylesheet" href="lib/AdminLTE/dist/css/AdminLTE.min.css"> <link rel="stylesheet" href="lib/AdminLTE/dist/css/AdminLTE.min.css">
<!-- AdminLTE Skins. We have chosen the skin-blue for this starter <!-- AdminLTE Skins. We have chosen the skin-blue for this starter
page. However, you can choose any other skin. Make sure you page. However, you can choose any other skin. Make sure you
apply the skin class to the body tag so the changes take effect. --> apply the skin class to the body tag so the changes take effect. -->
<link rel="stylesheet" href="lib/AdminLTE/dist/css/skins/skin-yellow-light.min.css"> <link rel="stylesheet" href="lib/AdminLTE/dist/css/skins/skin-yellow-light.min.css">
<!-- Pi.Alert CSS -->
<!-- Pi.alert CSS -->
<link rel="stylesheet" href="css/pialert.css"> <link rel="stylesheet" href="css/pialert.css">
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries --> <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// --> <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]> <!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script> <script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script> <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]--> <![endif]-->
<!-- Google Font --> <!-- Google Font -->
<link rel="stylesheet" <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,300italic,400italic,600italic">
href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,300italic,400italic,600italic">
<!-- Page Icon --> <!-- Page Icon -->
<link rel="icon" type="image/png" sizes="160x160" href="img/pialertLogoGray80.png" /> <link rel="icon" type="image/png" sizes="160x160" href="img/pialertLogoGray80.png" />
</head> </head>
<!-- ----------------------------------------------------------------------- -->
<!-- Layout Boxed Yellow --> <!-- Layout Boxed Yellow -->
<body class="hold-transition skin-yellow-light layout-boxed sidebar-mini" style="background-image: url('img/backgroud.png');"> <body class="hold-transition skin-yellow-light layout-boxed sidebar-mini" style="background-image: url('img/background.png');">
<!-- Site wrapper --> <!-- Site wrapper -->
<div class="wrapper"> <div class="wrapper">
<!-- Main Header --> <!-- Main Header -->
<header class="main-header"> <header class="main-header">
<!-- ----------------------------------------------------------------------- -->
<!-- Logo --> <!-- Logo -->
<a href="/" class="logo"> <a href="." class="logo">
<!-- mini logo for sidebar mini 50x50 pixels --> <!-- mini logo for sidebar mini 50x50 pixels -->
<span class="logo-mini">P<b>a</b></span> <span class="logo-mini">P<b>a</b></span>
<!-- logo for regular state and mobile devices --> <!-- logo for regular state and mobile devices -->
<span class="logo-lg">Pi<b>.alert</b></span> <span class="logo-lg">Pi<b>.Alert</b></span>
</a> </a>
<!-- ----------------------------------------------------------------------- -->
<!-- Header Navbar --> <!-- Header Navbar -->
<nav class="navbar navbar-static-top" role="navigation"> <nav class="navbar navbar-static-top" role="navigation">
<!-- Sidebar toggle button--> <!-- Sidebar toggle button-->
@@ -73,33 +90,37 @@
<!-- Menu Toggle Button --> <!-- Menu Toggle Button -->
<a href="#" class="dropdown-toggle" data-toggle="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown">
<!-- The user image in the navbar--> <!-- The user image in the navbar-->
<img src="img/pialertLogoWhite.png" class="user-image" style="border-radius: initial" alt="Pi.alert Logo"> <img src="img/pialertLogoWhite.png" class="user-image" style="border-radius: initial" alt="Pi.Alert Logo">
<!-- hidden-xs hides the username on small devices so only the image appears. --> <!-- hidden-xs hides the username on small devices so only the image appears. -->
<span class="hidden-xs">Pi.alert</span> <span class="hidden-xs">Pi.Alert</span>
</a> </a>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<!-- The user image in the menu --> <!-- The user image in the menu -->
<li class="user-header"> <li class="user-header">
<img src="img/pialertLogoWhite.png" class="img-circle" alt="Pi.alert Logo" style="border-color:transparent"> <img src="img/pialertLogoWhite.png" class="img-circle" alt="Pi.Alert Logo" style="border-color:transparent">
<p> <p>
Open Source Network Guard Open Source Network Guard
<small>Designed for Raspberry Pi</small> <small>Designed for Raspberry Pi</small>
</p> </p>
</li> </li>
<!-- Menu Body --> <!-- Menu Body -->
<li class="user-body"> <li class="user-body">
<div class="row"> <div class="row">
<div class="col-xs-4 text-center"> <div class="col-xs-4 text-center">
<a href="https://github.com/pucherot/Pi.Alert">GitHub</a> <a target="_blank" href="https://github.com/pucherot/Pi.Alert">GitHub Pi.Alert</a>
</div> </div>
<div class="col-xs-4 text-center"> <div class="col-xs-4 text-center">
<a href="https://github.com/pucherot/Pi.Alert">Pi.Alert</a> <a href="mailto:pi.alert.application@gmail.com">email Support</a>
<!-- <a href="#">Website</a> -->
</div> </div>
<div class="col-xs-4 text-center">
<a target="_blank" href="https://github.com/pucherot/Pi.Alert/blob/main/LICENSE.txt">GNU GPLv3</a>
</div>
<!--
<div class="col-xs-4 text-center"> <div class="col-xs-4 text-center">
<a href="#">Updates</a> <a href="#">Updates</a>
</div> </div>
-->
</div> </div>
<!-- /.row --> <!-- /.row -->
</li> </li>
@@ -109,6 +130,8 @@
</div> </div>
</nav> </nav>
</header> </header>
<!-- ----------------------------------------------------------------------- -->
<!-- Left side column. contains the logo and sidebar --> <!-- Left side column. contains the logo and sidebar -->
<aside class="main-sidebar"> <aside class="main-sidebar">
@@ -117,120 +140,13 @@
<!-- Sidebar user panel (optional) --> <!-- Sidebar user panel (optional) -->
<div class="user-panel"> <div class="user-panel">
<a href="/" class="logo"> <a href="." class="logo">
<img src="img/pialertLogoGray80.png" class="img-responsive" alt="Pi.alert Logo"/> <img src="img/pialertLogoGray80.png" class="img-responsive" alt="Pi.Alert Logo"/>
</a> </a>
<div class="pull-left image">
<!--
<br><img src="img/pialertLogoBlack.png" class="img-responsive" alt="Pi.alert Logo" style="display: table; table-layout: fixed;" />
-->
</div>
<div class="pull-left info" style="display: none">
<p>Status</p>
<?php
$pistatus = exec('sudo pihole status web');
$pistatus=1;
$FTL=true;
$celsius=56.7;
$temperatureunit='C';
$nproc=2;
$loaddata=array();
$loaddata[]=1.1;
$loaddata[]=1.2;
$loaddata[]=1.3;
$memory_usage=0.452;
if ($pistatus == "1") {
echo '<a id="status"><i class="fa fa-circle" style="color:#7FFF00"></i> Active</a>';
} elseif ($pistatus == "0") {
echo '<a id="status"><i class="fa fa-circle" style="color:#FF0000"></i> Offline</a>';
} elseif ($pistatus == "-1") {
echo '<a id="status"><i class="fa fa-circle" style="color:#FF0000"></i> DNS service not running</a>';
} else {
echo '<a id="status"><i class="fa fa-circle" style="color:#ff9900"></i> Unknown</a>';
}
// CPU Temp
if($FTL)
{
if ($celsius >= -273.15) {
echo "<a id=\"temperature\"><i class=\"fa fa-fire\" style=\"color:";
if ($celsius > 60) {
echo "#FF0000";
}
else
{
echo "#3366FF";
}
echo "\"></i> Temp:&nbsp;";
if($temperatureunit === "F")
{
echo round($fahrenheit,1) . "&nbsp;&deg;F";
}
elseif($temperatureunit === "K")
{
echo round($kelvin,1) . "&nbsp;K";
}
else
{
echo round($celsius,1) . "&nbsp;&deg;C";
}
echo "</a>";
}
}
else
{
echo '<a id=\"temperature\"><i class="fa fa-circle" style="color:#FF0000"></i> FTL offline</a>';
}
?>
<br/>
<?php
echo "<a title=\"Detected $nproc cores\"><i class=\"fa fa-circle\" style=\"color:";
if ($loaddata[0] > $nproc) {
echo "#FF0000";
}
else
{
echo "#7FFF00";
}
echo "\"></i> Load:&nbsp;&nbsp;" . $loaddata[0] . "&nbsp;&nbsp;" . $loaddata[1] . "&nbsp;&nbsp;". $loaddata[2] . "</a>";
?>
<br/>
<?php
echo "<a><i class=\"fa fa-circle\" style=\"color:";
if ($memory_usage > 0.75 || $memory_usage < 0.0) {
echo "#FF0000";
}
else
{
echo "#7FFF00";
}
if($memory_usage > 0.0)
{
echo "\"></i> Memory usage:&nbsp;&nbsp;" . sprintf("%.1f",100.0*$memory_usage) . "&thinsp;%</a>";
}
else
{
echo "\"></i> Memory usage:&nbsp;&nbsp; N/A</a>";
}
?>
</div>
</div> </div>
<!-- search form (Optional) --> <!-- search form (Optional) -->
<!-- <!-- DELETED -->
<form action="#" method="get" class="sidebar-form">
<div class="input-group">
<input type="text" name="q" class="form-control" placeholder="Search...">
<span class="input-group-btn">
<button type="submit" name="search" id="search-btn" class="btn btn-flat"><i class="fa fa-search"></i>
</button>
</span>
</div>
</form>
-->
<!-- /.search form -->
<!-- Sidebar Menu --> <!-- Sidebar Menu -->
<ul class="sidebar-menu" data-widget="tree"> <ul class="sidebar-menu" data-widget="tree">
@@ -238,7 +154,6 @@ $memory_usage=0.452;
<li class="header">MAIN MENU</li> <li class="header">MAIN MENU</li>
--> -->
<!-- Optionally, you can add icons to the links -->
<li class=" <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('devices.php', 'deviceDetails.php') ) ){ echo 'active'; } ?>"> <li class=" <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('devices.php', 'deviceDetails.php') ) ){ echo 'active'; } ?>">
<a href="devices.php"><i class="fa fa-laptop"></i> <span>Devices</span></a> <a href="devices.php"><i class="fa fa-laptop"></i> <span>Devices</span></a>
</li> </li>
@@ -261,14 +176,18 @@ $memory_usage=0.452;
<i class="fa fa-angle-left pull-right"></i> <i class="fa fa-angle-left pull-right"></i>
</span> </span>
</a> </a>
<ul class="treeview-menu"> <ul class="treeview-menu">
<li><a href="#">Scan Cycles</a></li> <li class=" <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('scancycles.php', 'scancyclesDetails.php') ) ){ echo 'active'; } ?>">
<a href="scancycles.php"><i class="fa fa-link"></i> <span>Scan Cycles</span></a>
</li>
<li><a href="#">Cron Status</a></li> <li><a href="#">Cron Status</a></li>
<li><a href="#">Current IP</a></li> <li><a href="#">Current IP</a></li>
</ul> </ul>
</li> </li>
--> -->
</ul> </ul>
<!-- /.sidebar-menu --> <!-- /.sidebar-menu -->
</section> </section>
<!-- /.sidebar --> <!-- /.sidebar -->

View File

@@ -0,0 +1,61 @@
<!-- ---------------------------------------------------------------------------
# Pi.Alert
# Open Source Network Guard / WIFI & LAN intrusion detector
#
# notificacion.php - Front module. Common notification & modal window
#-------------------------------------------------------------------------------
# Puche 2021 pi.alert.application@gmail.com GNU GPLv3
#--------------------------------------------------------------------------- -->
<!-- Modal Default -->
<div class="modal fade" id="modal-default" style="display: none;">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header" style="background-color: #d0d0d0;">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 id="modal-default-title" class="modal-title"> Modal Default Title </h4>
</div>
<div id="modal-default-message" class="modal-body"> Modal Default message </div>
<div class="modal-footer">
<button id="modal-default-cancel" type="button" class="btn btn-default pull-left" style="min-width: 80px;" data-dismiss="modal"> Cancel </button>
<button id="modal-default-OK" type="button" class="btn btn-primary" style="min-width: 80px;" onclick="modalDefaultOK()"> OK </button>
</div>
</div>
<!-- /.modal-content -->
</div>
<!-- /.modal-dialog -->
</div>
<!-- Modal warning -->
<div class="modal modal-warning fade" id="modal-warning" 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-warning-title" class="modal-title"> Modal Title </h4>
</div>
<div id="modal-warning-message" class="modal-body"> Modal message </div>
<div class="modal-footer">
<button id="modal-warning-cancel" type="button" class="btn btn-outline pull-left" style="min-width: 80px;" data-dismiss="modal"> Cancel </button>
<button id="modal-warning-OK" type="button" class="btn btn-outline" style="min-width: 80px;" onclick="modalWarningOK()"> 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>
<div id="alert-message"> Alert message </div>
</div>

View File

@@ -1,4 +1,12 @@
<!-- ----------------------------------------------------------------------- --> <!-- ---------------------------------------------------------------------------
# Pi.Alert
# Open Source Network Guard / WIFI & LAN intrusion detector
#
# presence.php - Front module. Device Presence calendar page
#-------------------------------------------------------------------------------
# Puche 2021 pi.alert.application@gmail.com GNU GPLv3
#--------------------------------------------------------------------------- -->
<?php <?php
require 'php/templates/header.php'; require 'php/templates/header.php';
?> ?>
@@ -9,104 +17,77 @@
<!-- Content header--------------------------------------------------------- --> <!-- Content header--------------------------------------------------------- -->
<section class="content-header"> <section class="content-header">
<h1 id="pageTitle"> <h1 id="pageTitle">
Presence by Devices Presence by Device
</h1> </h1>
<!-- period selector -->
<span class="breadcrumb text-gray50">
New Devices period:
<select id="period" onchange="javascript: periodChanged();">
<option value="1 day">Today</option>
<option value="7 days">Last Week</option>
<option value="1 month" selected>Last Month</option>
<option value="1 year">Last Year</option>
<option value="100 years">All info</option>
</select>
</span>
</section> </section>
<!-- Main content ---------------------------------------------------------- --> <!-- Main content ---------------------------------------------------------- -->
<section class="content"> <section class="content">
<!-- top small box 1 ------------------------------------------------------- -->
<div class="row"> <div class="row">
<!-- top small box --------------------------------------------------------- --> <div class="col-lg-2 col-sm-4 col-xs-6">
<div class="col-lg-3 col-sm-6 col-xs-6"> <a href="#" onclick="javascript: getDevicesPresence('all');">
<a href="#" onclick="javascript: queryPresence('all');"> <div class="small-box bg-aqua pa-small-box-aqua pa-small-box-2">
<div class="small-box bg-aqua pa-small-box-aqua"> <div class="inner"> <h3 id="devicesAll"> -- </h3> </div>
<div class="inner"> <div class="icon"> <i class="fa fa-laptop text-aqua-20"></i> </div>
<div class="small-box-footer pa-small-box-footer"> All Devices <i class="fa fa-arrow-circle-right"></i> </div>
<h4>All Devices</h4>
<h3 id="devicesAll"> -- </h3>
</div>
<div class="icon">
<i class="fa fa-laptop"></i>
</div>
<div class="small-box-footer">
Details <i class="fa fa-arrow-circle-right"></i>
</div>
</div> </div>
</a> </a>
</div> </div>
<!-- top small box --------------------------------------------------------- --> <!-- top small box 2 ------------------------------------------------------- -->
<div class="col-lg-3 col-sm-6 col-xs-6"> <div class="col-lg-2 col-sm-4 col-xs-6">
<a href="#" onclick="javascript: queryPresence('connected');"> <a href="#" onclick="javascript: getDevicesPresence('connected');">
<div class="small-box bg-green pa-small-box-green"> <div class="small-box bg-green pa-small-box-green pa-small-box-2">
<div class="inner"> <div class="inner"> <h3 id="devicesConnected"> -- </h3> </div>
<div class="icon"> <i class="fa fa-plug text-green-20"></i> </div>
<h4>Connected</h4> <div class="small-box-footer pa-small-box-footer"> Connected <i class="fa fa-arrow-circle-right"></i> </div>
<h3 id="devicesConnected"> -- </h3>
</div>
<div class="icon">
<i class="fa fa-plug"></i>
</div>
<div class="small-box-footer">
Details <i class="fa fa-arrow-circle-right"></i>
</div>
</div> </div>
</a> </a>
</div> </div>
<!-- top small box --------------------------------------------------------- --> <!-- top small box 3 ------------------------------------------------------- -->
<div class="col-lg-3 col-sm-6 col-xs-6"> <div class="col-lg-2 col-sm-4 col-xs-6">
<a href="#" onclick="javascript: queryPresence('new');"> <a href="#" onclick="javascript: getDevicesPresence('favorites');">
<div class="small-box bg-yellow pa-small-box-yellow"> <div class="small-box bg-yellow pa-small-box-yellow pa-small-box-2">
<div class="inner"> <div class="inner"> <h3 id="devicesFavorites"> -- </h3> </div>
<div class="icon"> <i class="fa fa-star text-yellow-20"></i> </div>
<h4>New Devices</h4> <div class="small-box-footer pa-small-box-footer"> Favorites <i class="fa fa-arrow-circle-right"></i> </div>
<h3 id="devicesNew"> -- </h3>
</div>
<div class="icon">
<i class="ion ion-plus-round"></i>
</div>
<div class="small-box-footer">
Details <i class="fa fa-arrow-circle-right"></i>
</div>
</div> </div>
</a> </a>
</div> </div>
<!-- top small box --------------------------------------------------------- --> <!-- top small box 4 ------------------------------------------------------- -->
<div class="col-lg-3 col-sm-6 col-xs-6"> <div class="col-lg-2 col-sm-4 col-xs-6">
<a href="#" onclick="javascript: queryPresence('down');"> <a href="#" onclick="javascript: getDevicesPresence('new');">
<div class="small-box bg-red pa-small-box-red"> <div class="small-box bg-yellow pa-small-box-yellow pa-small-box-2">
<div class="inner"> <div class="inner"> <h3 id="devicesNew"> -- </h3> </div>
<div class="icon"> <i class="ion ion-plus-round text-yellow-20"></i> </div>
<div class="small-box-footer pa-small-box-footer"> New Devices <i class="fa fa-arrow-circle-right"></i> </div>
</div>
</a>
</div>
<h4>Down Alerts</h4> <!-- top small box 5 ------------------------------------------------------- -->
<h3 id="devicesDown"> -- </h3> <div class="col-lg-2 col-sm-4 col-xs-6">
<a href="#" onclick="javascript: getDevicesPresence('down');">
<div class="small-box bg-red pa-small-box-red pa-small-box-2">
<div class="inner"> <h3 id="devicesDown"> -- </h3> </div>
<div class="icon"> <i class="fa fa-warning text-red-20"></i> </div>
<div class="small-box-footer pa-small-box-footer"> Down Alerts <i class="fa fa-arrow-circle-right"></i> </div>
</div>
</a>
</div>
</div> <!-- top small box 6 ------------------------------------------------------- -->
<div class="icon"> <div class="col-lg-2 col-sm-4 col-xs-6">
<i class="fa fa-warning"></i> <a href="#" onclick="javascript: getDevicesPresence('archived');">
</div> <div class="small-box bg-gray pa-small-box-gray pa-small-box-2">
<div class="small-box-footer"> <div class="inner"> <h3 id="devicesHidden"> -- </h3> </div>
Details <i class="fa fa-arrow-circle-right"></i> <div class="icon"> <i class="fa fa-eye-slash text-gray-20"></i> </div>
</div> <div class="small-box-footer pa-small-box-footer"> Hidden <i class="fa fa-arrow-circle-right"></i> </div>
</div> </div>
</a> </a>
</div> </div>
@@ -118,20 +99,27 @@
<div class="row"> <div class="row">
<div class="col-lg-12 col-sm-12 col-xs-12"> <div class="col-lg-12 col-sm-12 col-xs-12">
<div id="tableDevicesBox" class="box" style="min-height: 500px"> <div id="tableDevicesBox" class="box" style="min-height: 500px">
<!-- box-header -->
<div class="box-header"> <div class="box-header">
<h3 id="tableDevicesTitle" class="box-title text-gray">Devices</h3> <h3 id="tableDevicesTitle" class="box-title text-gray">Devices</h3>
</div> </div>
<!-- box-body -->
<div class="box-body table-responsive"> <div class="box-body table-responsive">
<!-- spinner --> <!-- spinner -->
<div id="loading" style="display: none"> <div id="loading" style="display: none">
<div class="pa_semitransparent-panel"></div> <div class="pa_semitransparent-panel"></div>
<div class="panel panel-default pa_spinner"> <div class="panel panel-default pa_spinner">
<table><td width="130px" align="middle">Loading...</td><td><i class="ion ion-ios-loop-strong fa-spin fa-2x fa-fw"></td></table> <table>
<td width="130px" align="middle">Loading...</td>
<td><i class="ion ion-ios-loop-strong fa-spin fa-2x fa-fw"></td>
</table>
</div> </div>
</div> </div>
<!-- Calendar -->
<div id="calendar"></div> <div id="calendar"></div>
</div> </div>
@@ -156,15 +144,6 @@
<!-- ----------------------------------------------------------------------- --> <!-- ----------------------------------------------------------------------- -->
<!-- iCkeck -->
<link rel="stylesheet" href="lib/AdminLTE/plugins/iCheck/all.css">
<script src="lib/AdminLTE/plugins/iCheck/icheck.min.js"></script>
<!-- Datatable -->
<link rel="stylesheet" href="lib/AdminLTE/bower_components/datatables.net-bs/css/dataTables.bootstrap.min.css">
<script src="lib/AdminLTE/bower_components/datatables.net/js/jquery.dataTables.min.js"></script>
<script src="lib/AdminLTE/bower_components/datatables.net-bs/js/dataTables.bootstrap.min.js"></script>
<!-- fullCalendar --> <!-- fullCalendar -->
<link rel="stylesheet" href="lib/AdminLTE/bower_components/fullcalendar/dist/fullcalendar.min.css"> <link rel="stylesheet" href="lib/AdminLTE/bower_components/fullcalendar/dist/fullcalendar.min.css">
<link rel="stylesheet" href="lib/AdminLTE/bower_components/fullcalendar/dist/fullcalendar.print.min.css" media="print"> <link rel="stylesheet" href="lib/AdminLTE/bower_components/fullcalendar/dist/fullcalendar.print.min.css" media="print">
@@ -178,23 +157,19 @@
<!-- page script ----------------------------------------------------------- --> <!-- page script ----------------------------------------------------------- -->
<script> <script>
var deviceStatus = 'all';
// Read parameters & Initialize components
main();
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
var deviceStatus = ''; function main () {
var period = '';
// Initialize MAC
var urlParams = new URLSearchParams(window.location.search);
if (urlParams.has ('status') == true) {
deviceStatus = urlParams.get ('status');
} else {
deviceStatus = 'all';
}
// Initialize components // Initialize components
$(function () { $(function () {
initializeiCheck();
initializeCalendar(); initializeCalendar();
periodChanged(); getDevicesTotals();
getDevicesPresence(deviceStatus);
}); });
// Force re-render calendar on tab change (bugfix for render error at left panel) // Force re-render calendar on tab change (bugfix for render error at left panel)
@@ -203,38 +178,12 @@
$('#calendar').fullCalendar('rerenderEvents'); $('#calendar').fullCalendar('rerenderEvents');
} }
}); });
// -----------------------------------------------------------------------------
function periodChanged () {
// Requery totals and list
queryTotals();
queryPresence(deviceStatus);
}
// -----------------------------------------------------------------------------
function initializeiCheck () {
// Default
$('input').iCheck({
checkboxClass: 'icheckbox_flat-blue',
radioClass: 'iradio_flat-blue',
increaseArea: '20%'
});
// readonly
$('#readonlyblock input').iCheck({
checkboxClass: 'icheckbox_flat-blue',
radioClass: 'iradio_flat-blue',
increaseArea: '-100%'
});
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
function initializeCalendar () { function initializeCalendar () {
$('#calendar').fullCalendar({ $('#calendar').fullCalendar({
header: { header: {
left : 'prev,next today', left : 'prev,next today',
center : 'title', center : 'title',
@@ -253,8 +202,8 @@ function initializeCalendar () {
resourceOrder : '-favorite,title', resourceOrder : '-favorite,title',
schedulerLicenseKey: 'CC-Attribution-NonCommercial-NoDerivatives', //schedulerLicenseKey: 'CC-Attribution-NonCommercial-NoDerivatives',
// schedulerLicenseKey: 'GPL-My-Project-Is-Open-Source', schedulerLicenseKey: 'GPL-My-Project-Is-Open-Source',
views: { views: {
timelineYear: { timelineYear: {
@@ -299,7 +248,7 @@ function initializeCalendar () {
cell.removeClass('fc-sat'); cell.removeClass('fc-sat');
cell.removeClass('fc-sun'); cell.removeClass('fc-sun');
return; return;
} };
if (date.day() == 0) { if (date.day() == 0) {
cell.addClass('fc-sun'); }; cell.addClass('fc-sun'); };
@@ -312,7 +261,8 @@ function initializeCalendar () {
}, },
resourceRender: function (resourceObj, labelTds, bodyTds) { resourceRender: function (resourceObj, labelTds, bodyTds) {
labelTds.find('span.fc-cell-text').html ('<b><a href="deviceDetails.php?mac='+ resourceObj.id+ '&period='+ period +'" class="">'+ resourceObj.title +'</a></b>'); labelTds.find('span.fc-cell-text').html (
'<b><a href="deviceDetails.php?mac='+ resourceObj.id+ '" class="">'+ resourceObj.title +'</a></b>');
// Resize heihgt // Resize heihgt
// $(".fc-content table tbody tr .fc-widget-content div").addClass('fc-resized-row'); // $(".fc-content table tbody tr .fc-widget-content div").addClass('fc-resized-row');
@@ -336,78 +286,54 @@ function initializeCalendar () {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
function queryTotals () { function getDevicesTotals () {
// debugTimer();
// stop timer // stop timer
stopTimerRefreshData(); stopTimerRefreshData();
// period
period = document.getElementById('period').value;
// get totals and put in boxes // get totals and put in boxes
$.get('php/server/devices.php?action=totals&period='+ period, function(data) { $.get('php/server/devices.php?action=getDevicesTotals', function(data) {
var totalsDevices = JSON.parse(data); var totalsDevices = JSON.parse(data);
$('#devicesAll').html (totalsDevices[0].toLocaleString()); $('#devicesAll').html (totalsDevices[0].toLocaleString());
$('#devicesConnected').html (totalsDevices[1].toLocaleString()); $('#devicesConnected').html (totalsDevices[1].toLocaleString());
$('#devicesNew').html (totalsDevices[2].toLocaleString()); $('#devicesFavorites').html (totalsDevices[2].toLocaleString());
$('#devicesDown').html (totalsDevices[3].toLocaleString()); $('#devicesNew').html (totalsDevices[3].toLocaleString());
}); $('#devicesDown').html (totalsDevices[4].toLocaleString());
$('#devicesHidden').html (totalsDevices[5].toLocaleString());
// Timer for refresh data // Timer for refresh data
newTimerRefreshData (queryTotals); newTimerRefreshData (getDevicesTotals);
} );
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
function queryPresence (status) { function getDevicesPresence (status) {
// Save status and period selected // Save status selected
deviceStatus = status; deviceStatus = status;
period = document.getElementById('period').value;
// Defini color & title for the status selected // Defini color & title for the status selected
switch (deviceStatus) { switch (deviceStatus) {
case 'all': case 'all': tableTitle = 'All Devices'; color = 'aqua'; break;
tableTitle = 'Total Devices'; case 'connected': tableTitle = 'Connected Devices'; color = 'green'; break;
color = 'aqua'; case 'favorites': tableTitle = 'Favorites'; color = 'yellow'; break;
break; case 'new': tableTitle = 'New Devices'; color = 'yellow'; break;
case 'connected': case 'down': tableTitle = 'Down Alerts'; color = 'red'; break;
tableTitle = 'Connected Devices'; case 'archived': tableTitle = 'Archived Devices'; color = 'gray'; break;
color = 'green'; default: tableTitle = 'Devices'; color = 'gray'; break;
break;
case 'new':
tableTitle = 'New Devices';
color = 'yellow';
break;
case 'down':
tableTitle = 'Down Alerts';
color = 'red';
break;
case 'favorites':
tableTitle = 'Favorites';
color = 'yellow';
break;
default:
tableTitle = 'Devices';
boxClass = '';
break;
} }
// Set title and color // Set title and color
document.getElementById('tableDevicesTitle').className = 'box-title text-' + color; $('#tableDevicesTitle')[0].className = 'box-title text-'+ color;
document.getElementById('tableDevicesBox').className = 'box box-' + color; $('#tableDevicesBox')[0].className = 'box box-'+ color;
$('#tableDevicesTitle').html (tableTitle); $('#tableDevicesTitle').html (tableTitle);
$('#calendar').fullCalendar ('option', 'resources', 'php/server/devices.php?action=calendar&status='+ deviceStatus +'&period='+ period); // Define new datasource URL and reload
$('#calendar').fullCalendar ('option', 'resources', 'php/server/devices.php?action=getDevicesListCalendar&status='+ deviceStatus);
$('#calendar').fullCalendar ('refetchResources'); $('#calendar').fullCalendar ('refetchResources');
// Query calendar
// resources : 'https://fullcalendar.io/demo-resources.json',
// events : 'https://fullcalendar.io/demo-events.json?with-resources',
$('#calendar').fullCalendar('removeEventSources'); $('#calendar').fullCalendar('removeEventSources');
$('#calendar').fullCalendar('addEventSource', { url: 'php/server/events.php?action=calendarPresence&period='+ period }); $('#calendar').fullCalendar('addEventSource', { url: 'php/server/events.php?action=getEventsCalendar' });
}; };
</script> </script>

View File

@@ -1,16 +0,0 @@
#
PIALERT_VERSION=2.52
PIALERT_DEV_PATH=/media/WD_4TB/dev
cd $PIALERT_DEV_PATH
tar tvf pialert/install/pialert_$PIALERT_VERSION.tar | wc -l
rm pialert/install/pialert_$PIALERT_VERSION.tar
tar cvf pialert/install/pialert_$PIALERT_VERSION.tar --exclude="pialert/install" --exclude="pialert/.git" pialert | wc -l
rm pialert/install/pialert_latest.tar
ln -s pialert_$PIALERT_VERSION.tar pialert/install/pialert_latest.tar

11
install/index.html Normal file
View File

@@ -0,0 +1,11 @@
<!-- ---------------------------------------------------------------------------
# Pi.Alert
# Open Source Network Guard / WIFI & LAN intrusion detector
#
# index.html - Redirect default page to pialert web admin portal
#-------------------------------------------------------------------------------
# Puche 2021 pi.alert.application@gmail.com GNU GPLv3
#--------------------------------------------------------------------------- -->
<meta http-equiv="refresh" content="0; url=pialert"/>
<meta http-equiv="Cache-Control" content="no-store" />

13
install/pialert.cron Normal file
View File

@@ -0,0 +1,13 @@
#-------------------------------------------------------------------------------
# Pi.Alert
# Open Source Network Guard / WIFI & LAN intrusion detector
#
# pialert.cron - Back module. Crontab jobs
#-------------------------------------------------------------------------------
# Puche 2021 pi.alert.application@gmail.com GNU GPLv3
#-------------------------------------------------------------------------------
0 3 * * 1 python ~/pialert/back/pialert.py update_vendors >~/pialert/log/pialert.vendors.log 2>&1
*/1 * * * * python ~/pialert/back/pialert.py internet_IP >~/pialert/log/pialert.IP.log 2>&1
*/5 * * * * python ~/pialert/back/pialert.py 1 >~/pialert/log/pialert.1.log 2>&1
*/15 * * * * python ~/pialert/back/pialert.py 15 >~/pialert/log/pialert.15.log 2>&1

View File

@@ -0,0 +1,12 @@
# ------------------------------------------------------------------------------
# Pi.Alert
# Open Source Network Guard / WIFI & LAN intrusion detector
#
# pialert_front.conf - lighttpd domain redirection
# ------------------------------------------------------------------------------
# Puche 2021 pi.alert.application@gmail.com GNU GPLv3
# ------------------------------------------------------------------------------
$HTTP["host"] == "pi.alert" {
server.document-root = "/var/www/html/pialert/"
}

785
install/pialert_install.sh Normal file
View File

@@ -0,0 +1,785 @@
#!/bin/bash
# ------------------------------------------------------------------------------
# Pi.Alert
# Open Source Network Guard / WIFI & LAN intrusion detector
#
# pialert_install.sh - Installation script
# ------------------------------------------------------------------------------
# Puche 2021 pi.alert.application@gmail.com GNU GPLv3
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Variables
# ------------------------------------------------------------------------------
COLS=70
ROWS=12
INSTALL_DIR=~
PIALERT_HOME="$INSTALL_DIR/pialert"
LIGHTTPD_CONF_DIR="/etc/lighttpd"
WEBROOT="/var/www/html"
PIALERT_DEFAULT_PAGE=false
LOG="pialert_install_`date +"%Y-%m-%d_%H-%M"`.log"
# MAIN_IP=`ip -o route get 1 | sed -n 's/.*src \([0-9.]\+\).*/\1/p'`
MAIN_IP=`ip -o route get 1 | sed 's/^.*src \([^ ]*\).*$/\1/;q'`
PIHOLE_INSTALL=false
PIHOLE_ACTIVE=false
DHCP_ACTIVATE=false
DHCP_ACTIVE=false
DHCP_RANGE_START="192.168.1.200"
DHCP_RANGE_END="192.168.1.251"
DHCP_ROUTER="192.168.1.1"
DHCP_LEASE="1"
DHCP_DOMAIN="local"
USE_PYTHON_VERSION=0
PYTHON_BIN=python
FIRST_SCAN_KNOWN=true
REPORT_MAIL=False
REPORT_TO=user@gmail.com
SMTP_SERVER=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=user@gmail.com
SMTP_PASS=password
DDNS_ACTIVE=False
DDNS_DOMAIN='your_domain.freeddns.org'
DDNS_USER='dynu_user'
DDNS_PASSWORD='A0000000B0000000C0000000D0000000'
DDNS_UPDATE_URL='https://api.dynu.com/nic/update?'
# ------------------------------------------------------------------------------
# Main
# ------------------------------------------------------------------------------
main() {
print_superheader "Pi.Alert Installation"
log "`date`"
log "Logfile: $LOG"
check_pialert_home
ask_config
set -e
install_pihole
activate_DHCP
add_pialert_DNS
install_lighttpd
install_arpscan
install_python
install_pialert
print_header "Installation process finished"
print_msg "Use: - http://pi.alert/"
print_msg " - http://$MAIN_IP/pialert/"
print_msg "To access Pi.Alert web"
print_msg ""
move_logfile
}
# ------------------------------------------------------------------------------
# Ask config questions
# ------------------------------------------------------------------------------
ask_config() {
# Ask installation
ask_yesno "This script will install Pi.Alert in this system using this path:\n$PIALERT_HOME" \
"Do you want to continue ?"
if ! $ANSWER ; then
exit 1
fi
# Ask Pi-hole Installation
PIHOLE_ACTIVE=false
if [ -e /usr/local/bin/pihole ] || [ -e /etc/pihole ]; then
PIHOLE_ACTIVE=true
fi
PIHOLE_INSTALL=false
if $PIHOLE_ACTIVE ; then
msgbox "Pi-hole is already installed in this system." \
"Perfect: Pi-hole Installation is not necessary"
else
ask_yesno "Pi-hole is not installed." \
"Do you want to install Pi-hole before installing Pi.Alert ?" "YES"
if $ANSWER ; then
PIHOLE_INSTALL=true
msgbox "In the installation wizard of Pi-hole, select this options" \
"'Install web admin interface' & 'Install web server lighttpd'"
fi
fi
# Ask DHCP Activation
DHCP_ACTIVE=false
DHCP_ACTIVATE=false
if $PIHOLE_ACTIVE ; then
DHCP_ACTIVE=`sudo grep DHCP_ACTIVE /etc/pihole/setupVars.conf | awk -F= '/./{print $2}'`
if [ "$DHCP_ACTIVE" = "" ] ; then DHCP_ACTIVE=false; fi
if ! $DHCP_ACTIVE ; then
ask_yesno "Pi-hole DHCP server is not active." \
"Do you want to activate Pi-hole DHCP server ?"
if $ANSWER ; then
DHCP_ACTIVATE=true
fi
fi
elif $PIHOLE_INSTALL ; then
ask_yesno "Pi-hole installation." \
"Do you want to activate Pi-hole DHCP server ?"
if $ANSWER ; then
DHCP_ACTIVATE=true
fi
fi
if $DHCP_ACTIVATE ; then
msgbox "Default DHCP options will be used. Range=$DHCP_RANGE_START - $DHCP_RANGE_END / Router=$DHCP_ROUTER / Domain=$DHCP_DOMAIN / Leases=$DHCP_LEASE h." \
"Yo can change this values in your Pi-hole Admin Portal"
msgbox "Make sure your router's DHCP server is disabled" \
"when using the Pi-hole DHCP server!"
fi
# Ask Pi.Alert deafault page
PIALERT_DEFAULT_PAGE=false
if ! $PIHOLE_ACTIVE && ! $PIHOLE_INSTALL; then
ask_yesno "As Pi-hole is not going to be available in this system," \
"Do you want to use Pi.Alert as default web server page ?" "YES"
if $ANSWER ; then
PIALERT_DEFAULT_PAGE=true
fi
fi
# Ask Python version
ask_option "What Python version do you want to use ?" \
3 \
0 " - Use Python already installed in the system (DEFAULT)" \
2 " - Use Python 2" \
3 " - Use Python 3"
if [ "$ANSWER" = "" ] ; then
USE_PYTHON_VERSION=0
else
USE_PYTHON_VERSION=$ANSWER
fi
# Ask first scan options
ask_yesno "First Scan options" \
"Do you want to mark the new devices as known devices during the first scan?" "YES"
FIRST_SCAN_KNOWN=$ANSWER
# Ask e-mail notification config
MAIL_REPORT=false
ask_yesno "Pi.Alert can notify you by e-mail when a network event occurs" \
"Do you want to activate this feature ?"
if $ANSWER ; then
ask_yesno "e-mail notification needs a SMTP server (i.e. smtp.gmail.com)" \
"Do you want to continue activating this feature ?"
MAIL_REPORT=$ANSWER
fi
if $MAIL_REPORT ; then
ask_input "" "Notify alert to this e-mail address:" "user@gmail.com"
REPORT_TO=$ANSWER
ask_input "" "SMTP server:" "smtp.gmail.com"
SMTP_SERVER=$ANSWER
ask_input "" "SMTP user:" "user@gmail.com"
SMTP_USER=$ANSWER
ask_input "" "SMTP password:" "password"
SMTP_PASS=$ANSWER
fi
# Ask Dynamic DNS config
DDNS_ACTIVE=false
ask_yesno "Pi.Alert can update your Dynamic DNS IP (i.e with www.dynu.net)" \
"Do you want to activate this feature ?"
if $ANSWER ; then
ask_yesno "Dynamics DNS updater needs a DNS with IP Update Protocol" \
"(i.e with www.dynu.net). Do you want to continue ?"
DDNS_ACTIVE=$ANSWER
fi
if $DDNS_ACTIVE ; then
ask_input "" "Domain to update:" "your_domain.freeddns.org"
DDNS_DOMAIN=$ANSWER
ask_input "" "DDNS user:" "dynu_user"
DDNS_USER=$ANSWER
ask_input "" "DDNS password:" "A0000000B0000000C0000000D0000000"
DDNS_PASSWORD=$ANSWER
ask_input "" "URL to update DDNS IP:" "https://api.dynu.com/nic/update?"
DDNS_UPDATE_URL=$ANSWER
fi
# Final config message
msgbox "Configuration finished. To update the configuration, edit file:" \
"$PIALERT_HOME/config/pialert.conf"
msgbox "" "The installation will start now"
}
# ------------------------------------------------------------------------------
# Install Pi-hole
# ------------------------------------------------------------------------------
install_pihole() {
print_header "Pi-hole"
if ! $PIHOLE_INSTALL ; then
return
fi
print_msg "- Checking if Pi-hole is installed..."
if [ -e /usr/local/bin/pihole ] || [ -e /etc/pihole ]; then
print_msg " - Pi-hole already installed"
print_msg "`pihole -v 2>&1`"
print_msg ""
PIHOLE_ACTIVE=true
return
fi
print_msg "- Installing Pi-hole..."
print_msg " - Pi-hole has its own logfile"
curl -sSL https://install.pi-hole.net | bash
print_msg ""
PIHOLE_ACTIVE=true
}
# ------------------------------------------------------------------------------
# Activate DHCP
# ------------------------------------------------------------------------------
activate_DHCP() {
if ! $DHCP_ACTIVATE ; then
return
fi
if ! $PIHOLE_ACTIVE ; then
return
fi
print_msg "- Checking if DHCP is active..."
if [ -e /etc/pihole ]; then
DHCP_ACTIVE= `grep DHCP_ACTIVE /etc/pihole/setupVars.conf | awk -F= '/./{print $2}'`
fi
if $DHCP_ACTIVE ; then
print_msg " - DHCP already active"
fi
print_msg "- Activating DHCP..."
sudo pihole -a enabledhcp "$DHCP_RANGE_START" "$DHCP_RANGE_END" "$DHCP_ROUTER" "$DHCP_LEASE" "$DHCP_DOMAIN" 2>&1 >> "$LOG"
DHCP_ACTIVE=true
}
# ------------------------------------------------------------------------------
# Add Pi.Alert DNS
# ------------------------------------------------------------------------------
add_pialert_DNS() {
if ! $PIHOLE_ACTIVE ; then
return
fi
print_msg "- Checking if 'pi.alert' is configured in Local DNS..."
if grep -Fq pi.alert /etc/pihole/custom.list; then
print_msg " - 'pi.alert' already in Local DNS..."
return
fi
print_msg "- Adding 'pi.alert' to Local DNS..."
sudo sh -c "echo $MAIN_IP pi.alert >> /etc/pihole/custom.list" 2>&1 >> "$LOG"
sudo pihole restartdns 2>&1 >> "$LOG"
}
# ------------------------------------------------------------------------------
# Install Lighttpd & PHP
# ------------------------------------------------------------------------------
install_lighttpd() {
print_header "Lighttpd & PHP"
print_msg "- Installing apt-utils..."
sudo apt-get install apt-utils -y 2>&1 >> "$LOG"
print_msg "- Installing lighttpd..."
sudo apt-get install lighttpd -y 2>&1 >> "$LOG"
print_msg "- Installing PHP..."
sudo apt-get install php php-cgi php-fpm php-sqlite3 -y 2>&1 >> "$LOG"
print_msg "- Activating PHP..."
ERRNO=0
sudo lighttpd-enable-mod fastcgi-php 2>&1 >>"$LOG" || ERRNO=$?
log_no_screen "-- Command error code: $ERRNO"
if [ "$ERRNO" = "1" ] ; then
process_error "Error activating PHP"
fi
print_msg "- Restarting lighttpd..."
sudo service lighttpd restart 2>&1 >> "$LOG"
# sudo /etc/init.d/lighttpd restart 2>&1 >> "$LOG"
print_msg "- Installing sqlite3..."
sudo apt-get install sqlite3 -y 2>&1 >> "$LOG"
}
# ------------------------------------------------------------------------------
# Install arp-scan & dnsutils
# ------------------------------------------------------------------------------
install_arpscan() {
print_header "arp-scan & dnsutils"
print_msg "- Installing arp-scan..."
sudo apt-get install arp-scan -y 2>&1 >> "$LOG"
print_msg "- Testing arp-scan..."
sudo arp-scan -l | head -n -3 | tail +3 | tee -a "$LOG"
print_msg "- Installing dnsutils & net-tools..."
sudo apt-get install dnsutils net-tools -y 2>&1 >> "$LOG"
}
# ------------------------------------------------------------------------------
# Install Python
# ------------------------------------------------------------------------------
install_python() {
print_header "Python"
check_python_versions
if [ $USE_PYTHON_VERSION -eq 0 ] ; then
print_msg "- Using the available Python version installed"
if $PYTHON3 ; then
print_msg " - Python 3 is available"
USE_PYTHON_VERSION=3
elif $PYTHON2 ; then
print_msg " - Python 2 is available"
USE_PYTHON_VERSION=2
else
print_msg " - Python is not available in this system"
print_msg " - Python 3 will be installed"
USE_PYTHON_VERSION=3
fi
echo ""
fi
if [ $USE_PYTHON_VERSION -eq 2 ] ; then
if $PYTHON2 ; then
print_msg "- Using Python 2"
else
print_msg "- Installing Python 2..."
sudo apt-get install python -y 2>&1 >> "$LOG"
fi
PYTHON_BIN="python"
elif [ $USE_PYTHON_VERSION -eq 3 ] ; then
if $PYTHON3 ; then
print_msg "- Using Python 3"
else
print_msg "- Installing Python 3..."
sudo apt-get install python3 -y 2>&1 >> "$LOG"
fi
PYTHON_BIN="python3"
else
process_error "Unknown Python version to use: $USE_PYTHON_VERSION"
fi
}
# ------------------------------------------------------------------------------
# Check Python versions available
# ------------------------------------------------------------------------------
check_python_versions() {
print_msg "- Checking Python 2..."
if [ -f /usr/bin/python ] ; then
print_msg " - Python 2 is installed"
print_msg " - `python -V 2>&1`"
PYTHON2=true
else
print_msg " - Python 2 is NOT installed"
PYTHON2=false
fi
echo ""
print_msg "- Checking Python 3..."
if [ -f /usr/bin/python3 ] ; then
print_msg " - Python 3 is installed"
print_msg " - `python3 -V 2>&1`"
PYTHON3=true
else
print_msg " - Python 3 is NOT installed"
PYTHON3=false
fi
echo ""
}
# ------------------------------------------------------------------------------
# Install Pi.Alert
# ------------------------------------------------------------------------------
install_pialert() {
print_header "Pi.Alert"
download_pialert
configure_pialert
test_pialert
add_jobs_to_crontab
publish_pialert
set_pialert_default_page
}
# ------------------------------------------------------------------------------
# Download and uncompress Pi.Alert
# ------------------------------------------------------------------------------
download_pialert() {
if [ -f "$INSTALL_DIR/pialert_latest.tar" ] ; then
print_msg "- Deleting previous downloaded tar file"
rm -r "$INSTALL_DIR/pialert_latest.tar"
fi
print_msg "- Downloading installation tar file..."
curl -Lo "$INSTALL_DIR/pialert_latest.tar" https://github.com/pucherot/Pi.Alert/raw/main/tar/pialert_latest.tar
echo ""
print_msg "- Uncompressing tar file"
tar xf "$INSTALL_DIR/pialert_latest.tar" -C "$INSTALL_DIR" --checkpoint=100 --checkpoint-action="ttyout=." 2>&1 >> "$LOG"
echo ""
print_msg "- Deleting downloaded tar file..."
rm -r "$INSTALL_DIR/pialert_latest.tar"
}
# ------------------------------------------------------------------------------
# Configure Pi.Alert parameters
# ------------------------------------------------------------------------------
configure_pialert() {
print_msg "- Settting Pi.Alert config file"
set_pialert_parameter PIALERT_PATH "'$PIALERT_HOME'"
set_pialert_parameter REPORT_MAIL "$REPORT_MAIL"
set_pialert_parameter REPORT_TO "'$REPORT_TO'"
set_pialert_parameter SMTP_SERVER "'$SMTP_SERVER'"
set_pialert_parameter SMTP_PORT "$SMTP_PORT"
set_pialert_parameter SMTP_USER "'$SMTP_USER'"
set_pialert_parameter SMTP_PASS "'$SMTP_PASS'"
set_pialert_parameter DDNS_ACTIVE "$DDNS_ACTIVE"
set_pialert_parameter DDNS_DOMAIN "'$DDNS_DOMAIN'"
set_pialert_parameter DDNS_USER "'$DDNS_USER'"
set_pialert_parameter DDNS_PASSWORD "'$DDNS_PASSWORD'"
set_pialert_parameter DDNS_UPDATE_URL "'$DDNS_UPDATE_URL'"
set_pialert_parameter PIHOLE_ACTIVE "$PIHOLE_ACTIVE"
set_pialert_parameter DHCP_ACTIVE "$DHCP_ACTIVE"
}
# ------------------------------------------------------------------------------
# Set Pi.Alert parameter
# ------------------------------------------------------------------------------
set_pialert_parameter() {
if [ "$2" = "false" ] ; then
VALUE="False"
elif [ "$2" = "true" ] ; then
VALUE="True"
else
VALUE="$2"
fi
sed -i "/^$1.*=/s|=.*|= $VALUE|" $PIALERT_HOME/config/pialert.conf 2>&1 >> "$LOG"
}
# ------------------------------------------------------------------------------
# Test Pi.Alert
# ------------------------------------------------------------------------------
test_pialert() {
print_msg "- Testing Pi.Alert HW vendors database update process..."
print_msg "*** PLEASE WAIT A COUPLE OF MINUTES..."
stdbuf -i0 -o0 -e0 $PYTHON_BIN $PIALERT_HOME/back/pialert.py update_vendors_silent 2>&1 | tee -ai "$LOG"
echo ""
print_msg "- Testing Pi.Alert Internet IP Lookup..."
stdbuf -i0 -o0 -e0 $PYTHON_BIN $PIALERT_HOME/back/pialert.py internet_IP 2>&1 | tee -ai "$LOG"
echo ""
print_msg "- Testing Pi.Alert Network scan..."
print_msg "*** PLEASE WAIT A COUPLE OF MINUTES..."
stdbuf -i0 -o0 -e0 $PYTHON_BIN $PIALERT_HOME/back/pialert.py 1 2>&1 | tee -ai "$LOG"
if $FIRST_SCAN_KNOWN ; then
echo ""
print_msg "- Set devices as Known devices..."
sqlite3 $PIALERT_HOME/db/pialert.db "UPDATE Devices SET dev_NewDevice=0, dev_AlertEvents=0 WHERE dev_NewDevice=1" 2>&1 >> "$LOG"
fi
}
# ------------------------------------------------------------------------------
# Add Pi.Alert jobs to crontab
# ------------------------------------------------------------------------------
add_jobs_to_crontab() {
if crontab -l 2>/dev/null | grep -Fq pialert ; then
print_msg "- Pi.Alert crontab jobs already exists. This is your crontab:"
crontab -l | grep -F pialert 2>&1 | tee -ai "$LOG"
return
fi
print_msg "- Adding jobs to the crontab..."
if [ $USE_PYTHON_VERSION -eq 3 ] ; then
sed -i "s/\<python\>/$PYTHON_BIN/g" $PIALERT_HOME/install/pialert.cron
fi
(crontab -l 2>/dev/null || : ; cat $PIALERT_HOME/install/pialert.cron) | crontab -
}
# ------------------------------------------------------------------------------
# Publish Pi.Alert web
# ------------------------------------------------------------------------------
publish_pialert() {
if [ -e "$WEBROOT/pialert" ] || [ -L "$WEBROOT/pialert" ] ; then
print_msg "- Deleting previous Pi.Alert site"
sudo rm -r "$WEBROOT/pialert" 2>&1 >> "$LOG"
fi
print_msg "- Setting permissions..."
sudo chgrp -R www-data $PIALERT_HOME/db 2>&1 >> "$LOG"
chmod -R g+rwx $PIALERT_HOME/db 2>&1 >> "$LOG"
chmod go+x $INSTALL_DIR 2>&1 >> "$LOG"
print_msg "- Publishing Pi.Alert web..."
sudo ln -s "$PIALERT_HOME/front" "$WEBROOT/pialert" 2>&1 >> "$LOG"
print_msg "- Configuring http://pi.alert/ redirection..."
if [ -e "$LIGHTTPD_CONF_DIR/conf-available/pialert_front.conf" ] ; then
sudo rm -r "$LIGHTTPD_CONF_DIR/conf-available/pialert_front.conf" 2>&1 >> "$LOG"
fi
sudo cp "$PIALERT_HOME/install/pialert_front.conf" "$LIGHTTPD_CONF_DIR/conf-available" 2>&1 >> "$LOG"
if [ -e "$LIGHTTPD_CONF_DIR/conf-enabled/pialert_front.conf" ] || \
[ -L "$LIGHTTPD_CONF_DIR/conf-enabled/pialert_front.conf" ] ; then
sudo rm -r "$LIGHTTPD_CONF_DIR/conf-enabled/pialert_front.conf" 2>&1 >> "$LOG"
fi
sudo ln -s ../conf-available/pialert_front.conf "$LIGHTTPD_CONF_DIR/conf-enabled/pialert_front.conf" 2>&1 >> "$LOG"
print_msg "- Restarting lighttpd..."
sudo sudo service lighttpd restart 2>&1 >> "$LOG"
# sudo /etc/init.d/lighttpd restart 2>&1 >> "$LOG"
}
# ------------------------------------------------------------------------------
# Set Pi.Alert the default web server page
# ------------------------------------------------------------------------------
set_pialert_default_page() {
if ! $PIALERT_DEFAULT_PAGE ; then
return
fi
print_msg "- Setting Pi.Alert as default web server page..."
if [ -e "$WEBROOT/index.lighttpd.html" ] ; then
if [ -e "$WEBROOT/index.lighttpd.html.orig" ] ; then
sudo rm "$WEBROOT/index.lighttpd.html" 2>&1 >> "$LOG"
else
sudo mv "$WEBROOT/index.lighttpd.html" "$WEBROOT/index.lighttpd.html.orig" 2>&1 >> "$LOG"
fi
fi
if [ -e "$WEBROOT/index.html" ] || [ -L "$WEBROOT/index.html" ] ; then
if [ -e "$WEBROOT/index.html.orig" ] ; then
sudo rm "$WEBROOT/index.html" 2>&1 >> "$LOG"
else
sudo mv "$WEBROOT/index.html" "$WEBROOT/index.html.orig" 2>&1 >> "$LOG"
fi
fi
sudo cp "$PIALERT_HOME/install/index.html" "$WEBROOT/index.html" 2>&1 >>"$LOG"
}
# ------------------------------------------------------------------------------
# Check Pi.Alert Installation Path
# ------------------------------------------------------------------------------
check_pialert_home() {
mkdir -p "$INSTALL_DIR"
if [ ! -d "$INSTALL_DIR" ] ; then
process_error "Installation path does not exists: $INSTALL_DIR"
fi
if [ -e "$PIALERT_HOME" ] || [ -L "$PIALERT_HOME" ] ; then
process_error "Pi.Alert path already exists: $PIALERT_HOME"
fi
}
# ------------------------------------------------------------------------------
# Move Logfile
# ------------------------------------------------------------------------------
move_logfile() {
NEWLOG="$PIALERT_HOME/log/$LOG"
mkdir -p "$PIALERT_HOME/log"
mv $LOG $NEWLOG
LOG="$NEWLOG"
NEWLOG=""
}
# ------------------------------------------------------------------------------
# ASK
# ------------------------------------------------------------------------------
msgbox() {
LINE1=$(printf "%*s" $(((${#1}+$COLS-5)/2)) "$1")
LINE2=$(printf "%*s" $(((${#2}+$COLS-5)/2)) "$2")
END_DIALOG=false
while ! $END_DIALOG ; do
whiptail --title "Pi.Alert Installation" --msgbox "$LINE1\\n\\n$LINE2" $ROWS $COLS
BUTTON=$?
ask_cancel
ANSWER=true
done
}
ask_yesno() {
LINE1=$(printf "%*s" $(((${#1}+$COLS-5)/2)) "$1")
LINE2=$(printf "%*s" $(((${#2}+$COLS-5)/2)) "$2")
if [ "$3" = "YES" ]; then
DEF_BUTTON=""
else
DEF_BUTTON="--defaultno"
fi
END_DIALOG=false
while ! $END_DIALOG ; do
whiptail --title "Pi.Alert Installation" --yesno $DEF_BUTTON "$LINE1\\n\\n$LINE2" $ROWS $COLS
BUTTON=$?
ask_cancel
done
if [ "$BUTTON" = "0" ] ; then
ANSWER=true
else
ANSWER=false
fi
}
ask_option() {
MENU_ARGS=("$@")
MENU_ARGS=("${MENU_ARGS[@]:1}")
END_DIALOG=false
while ! $END_DIALOG ; do
ANSWER=$(whiptail --title "Pi.Alert Installation" --menu "$1" $ROWS $COLS "${MENU_ARGS[@]}" 3>&2 2>&1 1>&3 )
BUTTON=$?
ask_cancel CANCEL
done
}
ask_input() {
LINE1=$(printf "%*s" $(((${#1}+$COLS-5)/2)) "$1")
LINE2=$(printf "%*s" $(((${#2}+$COLS-5)/2)) "$2")
END_DIALOG=false
while ! $END_DIALOG ; do
ANSWER=$(whiptail --title "Pi.Alert Installation" --inputbox "$LINE1\\n\\n$LINE2" $ROWS $COLS "$3" 3>&2 2>&1 1>&3 )
BUTTON=$?
ask_cancel CANCEL
if $END_DIALOG && [ "$ANSWER" = "" ] ; then
msgbox "" "You must enter a value"
END_DIALOG=false
fi
done
}
ask_cancel() {
LINE0="Do you want to cancel the installation process"
LINE0=$(printf "\n\n%*s" $(((${#LINE0}+$COLS-5)/2)) "$LINE0")
if [ "$BUTTON" = "1" ] && [ "$1" = "CANCEL" ] ; then BUTTON="255"; fi
if [ "$BUTTON" = "255" ] ; then
whiptail --title "Pi.Alert Installation" --yesno --defaultno "$LINE0" $ROWS $COLS
if [ "$?" = "0" ] ; then
process_error "Installation Aborted by User"
fi
else
END_DIALOG=true
fi
}
# ------------------------------------------------------------------------------
# Log
# ------------------------------------------------------------------------------
log() {
echo "$1" | tee -a "$LOG"
}
log_no_screen () {
echo "$1" >> "$LOG"
}
log_only_screen () {
echo "$1"
}
print_msg() {
log_no_screen ""
log "$1"
}
print_superheader() {
log ""
log "############################################################"
log " $1"
log "############################################################"
}
print_header() {
log ""
log "------------------------------------------------------------"
log " $1"
log "------------------------------------------------------------"
}
process_error() {
log ""
log "************************************************************"
log "************************************************************"
log "** ERROR INSTALLING PI.ALERT **"
log "************************************************************"
log "************************************************************"
log ""
log "$1"
log ""
log "Use 'cat $LOG' to view installation log"
log ""
# msgbox "****** ERROR INSTALLING Pi.ALERT ******" "$1"
exit 1
}
# ------------------------------------------------------------------------------
main
exit 0

View File

@@ -0,0 +1,207 @@
#!/bin/bash
# ------------------------------------------------------------------------------
# Pi.Alert
# Open Source Network Guard / WIFI & LAN intrusion detector
#
# pialert_uninstall.sh - Uninstallation script
# ------------------------------------------------------------------------------
# Puche 2021 pi.alert.application@gmail.com GNU GPLv3
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Variables
# ------------------------------------------------------------------------------
COLS=70
ROWS=12
INSTALL_DIR=~
PIALERT_HOME="$INSTALL_DIR/pialert"
LIGHTTPD_CONF_DIR="/etc/lighttpd"
WEBROOT="/var/www/html"
LOG="pialert_uninstall_`date +"%Y-%m-%d_%H-%M"`.log"
# ------------------------------------------------------------------------------
# Main
# ------------------------------------------------------------------------------
main() {
print_superheader "Pi.Alert Uninstallation"
log "`date`"
log "Logfile: $LOG"
# Ask uninstallation
ask_yesno "This script will uninstall Pi.Alert from this system.\nUninstall path: $PIALERT_HOME" \
"Do you want to continue ?"
if ! $ANSWER ; then
exit 1
fi
msgbox "" "The uninstallation process will start now"
# Uninstall prrocess
print_header "Removing files"
sudo rm -r "$PIALERT_HOME" 2>&1 >> "$LOG"
sudo rm "$WEBROOT/pialert" 2>&1 >> "$LOG"
sudo rm "$LIGHTTPD_CONF_DIR/conf-available/pialert_front.conf" 2>&1 >> "$LOG"
sudo rm "$LIGHTTPD_CONF_DIR/conf-enabled/pialert_front.conf" 2>&1 >> "$LOG"
sudo rm -r /var/cache/lighttpd/compress/pialert 2>&1 >> "$LOG"
# Removing
print_header "Removing Pi.Alert DNS name"
if [ -f /etc/pihole/custom.list ] ; then
sudo sed -i '/pi.alert/d' /etc/pihole/custom.list 2>&1 >> "$LOG"
sudo pihole restartdns 2>&1 >> "$LOG"
fi
# Uninstall crontab jobs
print_header "Removing crontab jobs"
crontab -l 2>/dev/null | sed '/pialert.py/d' | sed ':a;N;$!ba;s/#-------------------------------------------------------------------------------\n# Pi.Alert\n# Open Source Network Guard \/ WIFI & LAN intrusion detector \n#\n# pialert.cron - Back module. Crontab jobs\n#-------------------------------------------------------------------------------\n# Puche 2021 pi.alert.application@gmail.com GNU GPLv3\n#-------------------------------------------------------------------------------//g' | crontab -
# final message
print_header "Uninstallation process finished"
print_msg "Note1: If you installed Pi-hole during the Pi.Alert installation process"
print_msg " Pi-hole will still be available after uninstalling Pi.Alert"
print_msg ""
print_msg "Note2: lighttpd, PHP, arp-scan & Python have not been uninstalled."
print_msg " They may be required by other software"
print_msg " You can uninstall them manually with command 'apt-get remove XX'"
}
# ------------------------------------------------------------------------------
# ASK
# ------------------------------------------------------------------------------
msgbox() {
LINE1=$(printf "%*s" $(((${#1}+$COLS-5)/2)) "$1")
LINE2=$(printf "%*s" $(((${#2}+$COLS-5)/2)) "$2")
END_DIALOG=false
while ! $END_DIALOG ; do
whiptail --title "Pi.Alert Uninstallation" --msgbox "$LINE1\\n\\n$LINE2" $ROWS $COLS
BUTTON=$?
ask_cancel
ANSWER=true
done
}
ask_yesno() {
LINE1=$(printf "%*s" $(((${#1}+$COLS-5)/2)) "$1")
LINE2=$(printf "%*s" $(((${#2}+$COLS-5)/2)) "$2")
if [ "$3" = "YES" ]; then
DEF_BUTTON=""
else
DEF_BUTTON="--defaultno"
fi
END_DIALOG=false
while ! $END_DIALOG ; do
whiptail --title "Pi.Alert Uninstallation" --yesno $DEF_BUTTON "$LINE1\\n\\n$LINE2" $ROWS $COLS
BUTTON=$?
ask_cancel
done
if [ "$BUTTON" = "0" ] ; then
ANSWER=true
else
ANSWER=false
fi
}
ask_option() {
MENU_ARGS=("$@")
MENU_ARGS=("${MENU_ARGS[@]:1}")
END_DIALOG=false
while ! $END_DIALOG ; do
ANSWER=$(whiptail --title "Pi.Alert Uninstallation" --menu "$1" $ROWS $COLS "${MENU_ARGS[@]}" 3>&2 2>&1 1>&3 )
BUTTON=$?
ask_cancel CANCEL
done
}
ask_input() {
LINE1=$(printf "%*s" $(((${#1}+$COLS-5)/2)) "$1")
LINE2=$(printf "%*s" $(((${#2}+$COLS-5)/2)) "$2")
END_DIALOG=false
while ! $END_DIALOG ; do
ANSWER=$(whiptail --title "Pi.Alert Uninstallation" --inputbox "$LINE1\\n\\n$LINE2" $ROWS $COLS "$3" 3>&2 2>&1 1>&3 )
BUTTON=$?
ask_cancel CANCEL
if $END_DIALOG && [ "$ANSWER" = "" ] ; then
msgbox "" "You must enter a value"
END_DIALOG=false
fi
done
}
ask_cancel() {
LINE0="Do you want to cancel the uninstallation process"
LINE0=$(printf "\n\n%*s" $(((${#LINE0}+$COLS-5)/2)) "$LINE0")
if [ "$BUTTON" = "1" ] && [ "$1" = "CANCEL" ] ; then BUTTON="255"; fi
if [ "$BUTTON" = "255" ] ; then
whiptail --title "Pi.Alert Uninstallation" --yesno --defaultno "$LINE0" $ROWS $COLS
if [ "$?" = "0" ] ; then
process_error "Uninstallation Aborted by User"
fi
else
END_DIALOG=true
fi
}
# ------------------------------------------------------------------------------
# Log
# ------------------------------------------------------------------------------
log() {
echo "$1" | tee -a "$LOG"
}
log_no_screen () {
echo "$1" >> "$LOG"
}
log_only_screen () {
echo "$1"
}
print_msg() {
log_no_screen ""
log "$1"
}
print_superheader() {
log ""
log "############################################################"
log " $1"
log "############################################################"
}
print_header() {
log ""
log "------------------------------------------------------------"
log " $1"
log "------------------------------------------------------------"
}
process_error() {
log ""
log "************************************************************"
log "************************************************************"
log "** ERROR UNINSTALLING PI.ALERT **"
log "************************************************************"
log "************************************************************"
log ""
# msgbox "****** ERROR UNINSTALLING Pi.ALERT ******" "$1"
exit 1
}
# ------------------------------------------------------------------------------
main
exit 0

305
install/pialert_update.sh Normal file
View File

@@ -0,0 +1,305 @@
#!/bin/bash
# ------------------------------------------------------------------------------
# Pi.Alert
# Open Source Network Guard / WIFI & LAN intrusion detector
#
# pialert_update.sh - Update script
# ------------------------------------------------------------------------------
# Puche 2021 pi.alert.application@gmail.com GNU GPLv3
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Variables
# ------------------------------------------------------------------------------
INSTALL_DIR=~
PIALERT_HOME="$INSTALL_DIR/pialert"
LOG="pialert_update_`date +"%Y-%m-%d_%H-%M"`.log"
PYTHON_BIN=python
# ------------------------------------------------------------------------------
# Main
# ------------------------------------------------------------------------------
main() {
print_superheader "Pi.Alert Update"
log "`date`"
log "Logfile: $LOG"
log ""
set -e
check_pialert_home
check_python_version
create_backup
move_files
clean_files
check_packages
download_pialert
update_config
update_db
test_pialert
print_header "Update process finished"
print_msg ""
move_logfile
}
# ------------------------------------------------------------------------------
# Create backup
# ------------------------------------------------------------------------------
create_backup() {
# Previous backups are not deleted
# print_msg "- Deleting previous Pi.Alert backups..."
# rm "$INSTALL_DIR/"pialert_update_backup_*.tar 2>/dev/null || :
print_msg "- Creating new Pi.Alert backup..."
cd "$INSTALL_DIR"
tar cvf "$INSTALL_DIR"/pialert_update_backup_`date +"%Y-%m-%d_%H-%M"`.tar pialert --checkpoint=100 --checkpoint-action="ttyout=." 2>&1 >> "$LOG"
echo ""
}
# ------------------------------------------------------------------------------
# Move files to the new directory
# ------------------------------------------------------------------------------
move_files() {
if [ -e "$PIALERT_HOME/back/pialert.conf" ] ; then
print_msg "- Moving pialert.conf to the new directory..."
mkdir -p "$PIALERT_HOME/config"
mv "$PIALERT_HOME/back/pialert.conf" "$PIALERT_HOME/config"
fi
}
# ------------------------------------------------------------------------------
# Move files to the new directory
# ------------------------------------------------------------------------------
clean_files() {
print_msg "- Cleaning previous version..."
rm -r "$PIALERT_HOME/back" 2>/dev/null || :
rm -r "$PIALERT_HOME/doc" 2>/dev/null || :
rm -r "$PIALERT_HOME/docs" 2>/dev/null || :
rm -r "$PIALERT_HOME/front" 2>/dev/null || :
rm -r "$PIALERT_HOME/install" 2>/dev/null || :
rm -r "$PIALERT_HOME/"*.txt 2>/dev/null || :
rm -r "$PIALERT_HOME/"*.md 2>/dev/null || :
}
# ------------------------------------------------------------------------------
# Check packages
# ------------------------------------------------------------------------------
check_packages() {
print_msg "- Checking package apt-utils..."
sudo apt-get install apt-utils -y 2>&1 >> "$LOG"
print_msg "- Checking package sqlite3..."
sudo apt-get install sqlite3 -y 2>&1 >> "$LOG"
print_msg "- Checking packages dnsutils & net-tools..."
sudo apt-get install dnsutils net-tools -y 2>&1 >> "$LOG"
}
# ------------------------------------------------------------------------------
# Download and uncompress Pi.Alert
# ------------------------------------------------------------------------------
download_pialert() {
if [ -f "$INSTALL_DIR/pialert_latest.tar" ] ; then
print_msg "- Deleting previous downloaded tar file"
rm -r "$INSTALL_DIR/pialert_latest.tar"
fi
print_msg "- Downloading update file..."
curl -Lo "$INSTALL_DIR/pialert_latest.tar" https://github.com/pucherot/Pi.Alert/raw/main/tar/pialert_latest.tar
echo ""
print_msg "- Uncompressing tar file"
tar xf "$INSTALL_DIR/pialert_latest.tar" -C "$INSTALL_DIR" \
--exclude='pialert/config/pialert.conf' \
--exclude='pialert/db/pialert.db' \
--exclude='pialert/log/*' \
--checkpoint=100 --checkpoint-action="ttyout=." 2>&1 >> "$LOG"
echo ""
print_msg "- Deleting downloaded tar file..."
rm -r "$INSTALL_DIR/pialert_latest.tar"
}
# ------------------------------------------------------------------------------
# Update conf file
# ------------------------------------------------------------------------------
update_config() {
print_msg "- Config backup..."
cp "$PIALERT_HOME/config/pialert.conf" "$PIALERT_HOME/config/pialert.conf.back" 2>&1 >> "$LOG"
print_msg "- Updating config file..."
sed -i '/VERSION/d' "$PIALERT_HOME/config/pialert.conf" 2>&1 >> "$LOG"
sed -i 's/PA_FRONT_URL/REPORT_DEVICE_URL/g' "$PIALERT_HOME/config/pialert.conf" 2>&1 >> "$LOG"
if ! grep -Fq PIALERT_PATH "$PIALERT_HOME/config/pialert.conf" ; then
echo "PIALERT_PATH = '$PIALERT_HOME'" >> "$PIALERT_HOME/config/pialert.conf"
fi
if ! grep -Fq QUERY_MYIP_SERVER "$PIALERT_HOME/config/pialert.conf" ; then
echo "QUERY_MYIP_SERVER = 'http://ipv4.icanhazip.com'" >> "$PIALERT_HOME/config/pialert.conf"
fi
if ! grep -Fq SCAN_SUBNETS "$PIALERT_HOME/config/pialert.conf" ; then
echo "SCAN_SUBNETS = '--localnet'" >> "$PIALERT_HOME/config/pialert.conf"
fi
}
# ------------------------------------------------------------------------------
# DB DDL
# ------------------------------------------------------------------------------
update_db() {
print_msg "- Updating DB permissions..."
sudo chgrp -R www-data $PIALERT_HOME/db 2>&1 >> "$LOG"
chmod -R 770 $PIALERT_HOME/db 2>&1 >> "$LOG"
print_msg "- Installing sqlite3..."
sudo apt-get install sqlite3 -y 2>&1 >> "$LOG"
print_msg "- Checking 'Parameters' table..."
TAB=`sqlite3 $PIALERT_HOME/db/pialert.db "SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name='Parameters' COLLATE NOCASE;"` 2>&1 >> "$LOG"
if [ "$TAB" == "0" ] ; then
print_msg " - Creating 'Parameters' table..."
sqlite3 $PIALERT_HOME/db/pialert.db "CREATE TABLE Parameters (par_ID STRING (50) PRIMARY KEY NOT NULL COLLATE NOCASE, par_Value STRING (250) );" 2>&1 >> "$LOG"
sqlite3 $PIALERT_HOME/db/pialert.db "CREATE INDEX IDX_par_ID ON Parameters (par_ID COLLATE NOCASE);" 2>&1 >> "$LOG"
fi
print_msg "- Checking Devices new columns..."
COL=`sqlite3 $PIALERT_HOME/db/pialert.db "SELECT COUNT(*) FROM PRAGMA_TABLE_INFO ('Devices') WHERE name='dev_NewDevice' COLLATE NOCASE";` 2>&1 >> "$LOG"
if [ "$COL" == "0" ] ; then
print_msg " - Adding column 'NewDevice' to 'Devices'..."
sqlite3 $PIALERT_HOME/db/pialert.db "ALTER TABLE Devices ADD COLUMN dev_NewDevice BOOLEAN NOT NULL DEFAULT (1) CHECK (dev_NewDevice IN (0, 1) );" 2>&1 >> "$LOG"
sqlite3 $PIALERT_HOME/db/pialert.db "CREATE INDEX IDX_dev_NewDevice ON Devices (dev_NewDevice);"
fi
COL=`sqlite3 $PIALERT_HOME/db/pialert.db "SELECT COUNT(*) FROM PRAGMA_TABLE_INFO ('Devices') WHERE name='dev_Location' COLLATE NOCASE";` 2>&1 >> "$LOG"
if [ "$COL" == "0" ] ; then
print_msg " - Adding column 'Location' to 'Devices'..."
sqlite3 $PIALERT_HOME/db/pialert.db "ALTER TABLE Devices ADD COLUMN dev_Location STRING(250) COLLATE NOCASE;" 2>&1 >> "$LOG"
fi
COL=`sqlite3 $PIALERT_HOME/db/pialert.db "SELECT COUNT(*) FROM PRAGMA_TABLE_INFO ('Devices') WHERE name='dev_Archived' COLLATE NOCASE";` 2>&1 >> "$LOG"
if [ "$COL" == "0" ] ; then
print_msg " - Adding column 'Archived / Hidden' to 'Devices'..."
sqlite3 $PIALERT_HOME/db/pialert.db "ALTER TABLE Devices ADD COLUMN dev_Archived BOOLEAN NOT NULL DEFAULT (0) CHECK (dev_Archived IN (0, 1) );" 2>&1 >> "$LOG"
sqlite3 $PIALERT_HOME/db/pialert.db "CREATE INDEX IDX_dev_Archived ON Devices (dev_Archived);" 2>&1 >> "$LOG"
fi
print_msg "- Cheking Internet scancycle..."
sqlite3 $PIALERT_HOME/db/pialert.db "UPDATE Devices set dev_ScanCycle=1, dev_AlertEvents=1, dev_AlertDeviceDown=1 WHERE dev_MAC='Internet' AND dev_ScanCycle=0;" 2>&1 >> "$LOG"
}
# ------------------------------------------------------------------------------
# Test Pi.Alert
# ------------------------------------------------------------------------------
test_pialert() {
print_msg "- Testing Pi.Alert HW vendors database update process..."
print_msg "*** PLEASE WAIT A COUPLE OF MINUTES..."
stdbuf -i0 -o0 -e0 $PYTHON_BIN $PIALERT_HOME/back/pialert.py update_vendors_silent 2>&1 | tee -ai "$LOG"
echo ""
print_msg "- Testing Pi.Alert Internet IP Lookup..."
stdbuf -i0 -o0 -e0 $PYTHON_BIN $PIALERT_HOME/back/pialert.py internet_IP 2>&1 | tee -ai "$LOG"
echo ""
print_msg "- Testing Pi.Alert Network scan..."
print_msg "*** PLEASE WAIT A COUPLE OF MINUTES..."
stdbuf -i0 -o0 -e0 $PYTHON_BIN $PIALERT_HOME/back/pialert.py 1 2>&1 | tee -ai "$LOG"
}
# ------------------------------------------------------------------------------
# Check Pi.Alert Installation Path
# ------------------------------------------------------------------------------
check_pialert_home() {
if [ ! -e "$PIALERT_HOME" ] ; then
process_error "Pi.Alert directory dosn't exists: $PIALERT_HOME"
fi
}
# ------------------------------------------------------------------------------
# Check Python versions available
# ------------------------------------------------------------------------------
check_python_version() {
print_msg "- Checking Python..."
if [ -f /usr/bin/python ] ; then
PYTHON_BIN="python"
elif [ -f /usr/bin/python3 ] ; then
PYTHON_BIN="python3"
else
process_error "Python NOT installed"
fi
}
# ------------------------------------------------------------------------------
# Move Logfile
# ------------------------------------------------------------------------------
move_logfile() {
NEWLOG="$PIALERT_HOME/log/$LOG"
mkdir -p "$PIALERT_HOME/log"
mv $LOG $NEWLOG
LOG="$NEWLOG"
NEWLOG=""
}
# ------------------------------------------------------------------------------
# Log
# ------------------------------------------------------------------------------
log() {
echo "$1" | tee -a "$LOG"
}
log_no_screen () {
echo "$1" >> "$LOG"
}
log_only_screen () {
echo "$1"
}
print_msg() {
log_no_screen ""
log "$1"
}
print_superheader() {
log ""
log "############################################################"
log " $1"
log "############################################################"
}
print_header() {
log ""
log "------------------------------------------------------------"
log " $1"
log "------------------------------------------------------------"
}
process_error() {
log ""
log "************************************************************"
log "************************************************************"
log "** ERROR UPDATING PI.ALERT **"
log "************************************************************"
log "************************************************************"
log ""
log "$1"
log ""
log "Use 'cat $LOG' to view update log"
log ""
exit 1
}
# ------------------------------------------------------------------------------
main
exit 0

View File

@@ -1 +1,10 @@
#-------------------------------------------------------------------------------
# Pi.Alert
# Open Source Network Guard / WIFI & LAN intrusion detector
#
# IP_changes.log - Back module. Logfile for Internet IP changes
#-------------------------------------------------------------------------------
# Puche 2021 pi.alert.application@gmail.com GNU GPLv3
#-------------------------------------------------------------------------------
2021-01-01 00:00:00 0.0.0.0 2021-01-01 00:00:00 0.0.0.0

View File

@@ -1,3 +1,12 @@
<!-- ---------------------------------------------------------------------------
# Pi.Alert
# Open Source Network Guard / WIFI & LAN intrusion detector
#
# repot_template.html - Back module. Template to email reporting in HTML format
#-------------------------------------------------------------------------------
# Puche 2021 pi.alert.application@gmail.com GNU GPLv3
#--------------------------------------------------------------------------- -->
<html> <html>
<head> <head>

25
tar/create_tar.sh Normal file
View File

@@ -0,0 +1,25 @@
#!/bin/sh
# ------------------------------------------------------------------------------
# Pi.Alert
# Open Source Network Guard / WIFI & LAN intrusion detector
#
# create_tar.sh - Create the tar file for installation
# ------------------------------------------------------------------------------
# Puche 2021 pi.alert.application@gmail.com GNU GPLv3
# ------------------------------------------------------------------------------
PIALERT_DEV_PATH=/media/WD_4TB/dev
cd $PIALERT_DEV_PATH
pwd
PIALERT_VERSION=`awk '$1=="VERSION" { print $3 }' pialert/config/version.conf | tr -d \'`
# ------------------------------------------------------------------------------
ls -l pialert/tar/pialert*.tar
tar tvf pialert/tar/pialert_latest.tar | wc -l
rm pialert/tar/pialert_*.tar
# ------------------------------------------------------------------------------
tar cvf pialert/tar/pialert_$PIALERT_VERSION.tar --exclude="pialert/tar" --exclude="pialert/.git" pialert | wc -l
ln -s pialert_$PIALERT_VERSION.tar pialert/tar/pialert_latest.tar
ls -l pialert/tar/pialert*.tar

View File

Binary file not shown.

View File

Binary file not shown.