Release Candidate for 2.3.0

This commit is contained in:
Russel Yasol
2025-08-25 12:52:58 +08:00
parent dd59450e99
commit 95463202dd
190 changed files with 1051 additions and 261 deletions

View File

@@ -0,0 +1,103 @@
#!/bin/sh /etc/rc.common
START=48
STOP=11
USE_PROCD=1
# QuecManager Logging Management Service
# Handles log rotation, cleanup, and logging system initialization
start_service() {
echo "Starting QuecManager Logging Management..."
# Initialize centralized logging system
echo "Initializing centralized logging directories..."
# Source logger with error handling
if . /www/cgi-bin/services/quecmanager_logger.sh 2>/dev/null; then
qm_init_logs
LOGGER_AVAILABLE=1
else
echo "Warning: Could not load logger, creating directories manually"
mkdir -p "/tmp/quecmanager/logs/daemons" "/tmp/quecmanager/logs/services" "/tmp/quecmanager/logs/settings" "/tmp/quecmanager/logs/system" 2>/dev/null || true
LOGGER_AVAILABLE=0
fi
# Set proper permissions
chmod 755 "/tmp/quecmanager/logs" "/tmp/quecmanager/logs/daemons" "/tmp/quecmanager/logs/services" "/tmp/quecmanager/logs/settings" "/tmp/quecmanager/logs/system" 2>/dev/null || true
# Create status and readme files
cat > "/tmp/quecmanager/logs/status.json" <<EOF
{
"status": "initialized",
"timestamp": "$(date -u +"%Y-%m-%dT%H:%M:%SZ")",
"directories": {
"daemons": "/tmp/quecmanager/logs/daemons",
"services": "/tmp/quecmanager/logs/services",
"settings": "/tmp/quecmanager/logs/settings",
"system": "/tmp/quecmanager/logs/system"
}
}
EOF
chmod 644 "/tmp/quecmanager/logs/status.json" 2>/dev/null || true
# Create README for administrators
cat > "/tmp/quecmanager/logs/README.txt" <<EOF
QuecManager Centralized Logging
==============================
This directory contains organized log files for the QuecManager system.
Directory Structure:
- daemons/ - Background daemon logs (memory_daemon, ping_daemon, etc.)
- services/ - Service logs (quecwatch, quecprofile, etc.)
- settings/ - Configuration and settings script logs
- system/ - System-level logs and initialization
Log Format:
[YYYY-MM-DD HH:MM:SS] [LEVEL] [SCRIPT] [PID:xxxx] Message
Log Rotation:
- Files are automatically rotated when they exceed 500KB
- Up to 2 backup files are kept (.1, .2)
- Old backup files are cleaned up periodically
Web Access:
Use /cgi-bin/quecmanager/experimental/logs/fetch_logs.sh to view logs.
Maintenance:
Automatic cleanup runs every 6 hours via this service.
EOF
chmod 644 "/tmp/quecmanager/logs/README.txt" 2>/dev/null || true
# Log the initialization (only if logger is available)
if [ "$LOGGER_AVAILABLE" = "1" ]; then
qm_log_info "system" "quecmanager_logging" "Centralized logging system initialized"
fi
echo "Centralized logging directories initialized"
# Start periodic log cleanup daemon
echo "Starting periodic log cleanup daemon..."
procd_open_instance cleanup
procd_set_param command sh -c 'while true; do sleep 21600; /www/cgi-bin/services/cleanup_logs.sh; done'
procd_set_param respawn
procd_set_param stdout 1
procd_set_param stderr 1
procd_close_instance
echo "Log cleanup daemon started (runs every 6 hours)"
# Log the completion (only if logger is available)
if [ "$LOGGER_AVAILABLE" = "1" ]; then
qm_log_info "system" "quecmanager_logging" "QuecManager logging management started - cleanup every 6 hours"
fi
echo "QuecManager Logging Management started"
}
stop_service() {
# Log shutdown (only if logger is available)
if . /www/cgi-bin/services/quecmanager_logger.sh 2>/dev/null; then
qm_log_info "system" "quecmanager_logging" "QuecManager logging management stopping" 2>/dev/null || true
fi
# procd will handle stopping all instances automatically
echo "Stopping QuecManager Logging Management."
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
self.__BUILD_MANIFEST=function(r,e,t){return{__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},__routerFilterStatic:{numItems:33,errorRate:1e-4,numBits:633,numHashes:14,bitArray:[1,1,1,0,0,r,r,r,0,e,r,r,e,r,r,e,r,e,r,e,r,r,r,r,r,r,e,e,e,e,r,e,r,r,e,r,r,e,r,e,e,r,e,r,r,r,r,e,r,e,r,r,e,r,r,e,r,e,e,r,e,r,r,e,e,r,e,r,r,e,r,e,r,r,e,r,e,e,e,r,e,e,e,e,r,r,e,e,e,r,r,r,r,r,r,r,r,r,e,e,e,r,e,r,r,e,r,e,e,r,e,e,e,e,r,e,e,e,r,e,r,e,e,r,e,r,r,e,r,e,e,e,r,r,e,r,r,r,r,r,r,e,r,e,e,r,r,e,r,e,r,r,r,e,r,r,e,e,e,r,e,r,r,r,e,r,r,r,e,e,e,r,r,r,e,e,r,r,r,e,r,e,r,r,e,r,e,e,r,e,r,r,r,e,e,r,r,e,r,r,r,r,e,e,e,e,r,r,e,r,r,e,e,r,r,r,r,e,e,r,e,r,e,r,e,r,r,e,r,r,e,e,e,r,e,e,r,r,r,r,e,r,r,r,e,e,e,e,r,e,r,e,r,r,e,r,r,e,e,e,e,e,r,r,e,r,e,e,e,e,e,e,r,e,r,e,r,e,r,r,e,r,r,e,r,e,e,e,e,e,e,e,r,r,r,e,r,r,e,r,r,e,e,e,e,e,r,e,r,e,r,e,r,r,e,e,e,e,e,e,r,e,r,r,e,r,e,e,e,r,e,e,e,r,r,e,r,r,e,r,e,e,e,r,e,r,r,e,e,e,e,r,e,r,e,r,e,r,e,r,e,e,e,r,e,r,r,r,e,e,r,r,e,r,r,r,r,r,r,r,e,e,e,r,e,r,r,e,r,r,e,e,r,r,r,r,r,r,e,r,r,r,r,e,r,r,r,r,e,r,e,e,e,r,r,e,r,r,e,r,e,r,e,e,r,r,r,r,r,e,e,e,e,r,e,r,r,r,e,e,e,r,e,r,r,r,e,e,e,e,e,r,e,e,e,r,r,r,e,r,e,r,e,r,e,r,e,r,r,e,e,r,r,r,r,r,r,r,e,e,r,r,e,r,e,e,r,r,e,e,r,e,r,r,e,e,e,r,e,e,e,r,e,e,e,r,r,r,e,r,e,e,r,r,e,r,r,e,r,e,e,e,r,r,e,e,r,r,e,r,r,e,e,r,e,e,r,r,r,e,e,r,r,r,r,e,e,e,r,r,e,e,r,e,r,e,e,e,r,e,e,e,r,e,r,e,r,e,e,r,r,r,r,e,r,r,e,r,e,e,r,e,r,r,e,r,e,r,r,r,r,r,e,r,r,e,r,r,e,r,e,r,e,r,r,r,e,r,e,e,r,r,e,e,e,e,r,r,r,r,e,e,e,r,e,e,r,r,r,e,e,e,r]},__routerFilterDynamic:{numItems:e,errorRate:1e-4,numBits:e,numHashes:null,bitArray:[]},"/_error":["static/chunks/pages/_error-8219f0da6c3b58d9.js"],sortedPages:["/_app","/_error"]}}(1,0,0),self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB();

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[5665],{63881:(e,s,_)=>{Promise.resolve().then(_.bind(_,25621))}},e=>{var s=s=>e(e.s=s);e.O(0,[9980,7780,8885,3746,9464,3494,2487,2266,191,6035,7358],()=>s(63881)),_N_E=e.O()}]);

View File

@@ -1 +0,0 @@
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[5665],{63881:(e,s,_)=>{Promise.resolve().then(_.bind(_,87133))}},e=>{var s=s=>e(e.s=s);e.O(0,[9980,7780,8885,3746,9464,3494,2487,1209,191,6035,7358],()=>s(63881)),_N_E=e.O()}]);

View File

@@ -0,0 +1 @@
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[4808],{38448:(e,s,_)=>{Promise.resolve().then(_.bind(_,25621))}},e=>{var s=s=>e(e.s=s);e.O(0,[9980,7780,8885,3746,9464,3494,2487,2266,191,6035,7358],()=>s(38448)),_N_E=e.O()}]);

View File

@@ -1 +0,0 @@
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[4808],{38448:(e,s,_)=>{Promise.resolve().then(_.bind(_,87133))}},e=>{var s=s=>e(e.s=s);e.O(0,[9980,7780,8885,3746,9464,3494,2487,1209,191,6035,7358],()=>s(38448)),_N_E=e.O()}]);

View File

@@ -1 +0,0 @@
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[8248],{43421:(e,s,a)=>{Promise.resolve().then(a.bind(a,14938))},14938:(e,s,a)=>{"use strict";a.r(s),a.d(s,{default:()=>l});var t=a(20475);a(20107);var r=a(16118),c=a(9477),u=a.n(c);let l=e=>{let{children:s}=e,a=(0,r.usePathname)();return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)("div",{className:"mx-auto grid w-full max-w-6xl gap-2",children:(0,t.jsx)("h1",{className:"text-3xl font-semibold",children:"Custom Features"})}),(0,t.jsxs)("div",{className:"mx-auto grid w-full max-w-6xl items-start gap-6 md:grid-cols-[180px_1fr] lg:grid-cols-[250px_1fr]",children:[(0,t.jsxs)("nav",{className:"grid gap-4 text-sm text-muted-foreground","x-chunk":"dashboard-04-chunk-0",children:[(0,t.jsx)(u(),{href:"/dashboard/custom-features/quecwatch",className:"".concat("/dashboard/custom-features/quecwatch"===a?"font-semibold text-primary":"text-sm"),children:"QuecWatch"}),(0,t.jsx)(u(),{href:"/dashboard/custom-features/quecprofiles",className:"".concat("/dashboard/custom-features/quecprofiles"===a?"font-semibold text-primary":"text-sm"),children:"QuecProfiles"}),(0,t.jsx)(u(),{href:"/dashboard/custom-features/cell-scanner",className:"".concat("/dashboard/custom-features/cell-scanner"===a?"font-semibold text-primary":"text-sm"),children:"Cell Scanner"}),(0,t.jsx)(u(),{href:"/dashboard/custom-features/frequency-calculator",className:"".concat("/dashboard/custom-features/frequency-calculator"===a?"font-semibold text-primary":"text-sm"),children:"Frequency Calculator"})]}),s]})]})}},16118:(e,s,a)=>{"use strict";var t=a(65834);a.o(t,"usePathname")&&a.d(s,{usePathname:function(){return t.usePathname}}),a.o(t,"useRouter")&&a.d(s,{useRouter:function(){return t.useRouter}})}},e=>{var s=s=>e(e.s=s);e.O(0,[9477,191,6035,7358],()=>s(43421)),_N_E=e.O()}]);

View File

@@ -0,0 +1 @@
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[8248],{43421:(e,s,a)=>{Promise.resolve().then(a.bind(a,14938))},14938:(e,s,a)=>{"use strict";a.r(s),a.d(s,{default:()=>l});var t=a(20475);a(20107);var r=a(16118),c=a(9477),u=a.n(c);let l=e=>{let{children:s}=e,a=(0,r.usePathname)();return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)("div",{className:"mx-auto grid w-full max-w-6xl gap-2",children:(0,t.jsx)("h1",{className:"text-3xl font-semibold",children:"Custom Features"})}),(0,t.jsxs)("div",{className:"mx-auto grid w-full max-w-6xl items-start gap-6 md:grid-cols-[180px_1fr] lg:grid-cols-[250px_1fr]",children:[(0,t.jsxs)("nav",{className:"grid gap-4 text-sm text-muted-foreground","x-chunk":"dashboard-04-chunk-0",children:[(0,t.jsx)(u(),{href:"/dashboard/custom-features/quecwatch",className:"".concat("/dashboard/custom-features/quecwatch/"===a?"font-semibold text-primary":"text-sm"),children:"QuecWatch"}),(0,t.jsx)(u(),{href:"/dashboard/custom-features/quecprofiles",className:"".concat("/dashboard/custom-features/quecprofiles/"===a?"font-semibold text-primary":"text-sm"),children:"QuecProfiles"}),(0,t.jsx)(u(),{href:"/dashboard/custom-features/cell-scanner",className:"".concat("/dashboard/custom-features/cell-scanner/"===a?"font-semibold text-primary":"text-sm"),children:"Cell Scanner"}),(0,t.jsx)(u(),{href:"/dashboard/custom-features/frequency-calculator",className:"".concat("/dashboard/custom-features/frequency-calculator/"===a?"font-semibold text-primary":"text-sm"),children:"Frequency Calculator"})]}),s]})]})}},16118:(e,s,a)=>{"use strict";var t=a(65834);a.o(t,"usePathname")&&a.d(s,{usePathname:function(){return t.usePathname}}),a.o(t,"useRouter")&&a.d(s,{useRouter:function(){return t.useRouter}})}},e=>{var s=s=>e(e.s=s);e.O(0,[9477,191,6035,7358],()=>s(43421)),_N_E=e.O()}]);

View File

@@ -1 +1 @@
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[3075],{87390:(e,s,a)=>{Promise.resolve().then(a.bind(a,31753))},31753:(e,s,a)=>{"use strict";a.r(s),a.d(s,{default:()=>d});var t=a(20475);a(20107);var r=a(16118),l=a(9477),n=a.n(l);let d=e=>{let{children:s}=e,a=(0,r.usePathname)();return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)("div",{className:"mx-auto grid w-full max-w-6xl gap-2",children:(0,t.jsx)("h1",{className:"text-3xl font-semibold",children:"Experimental"})}),(0,t.jsxs)("div",{className:"mx-auto grid w-full max-w-6xl items-start gap-6 md:grid-cols-[180px_1fr] lg:grid-cols-[250px_1fr]",children:[(0,t.jsxs)("nav",{className:"grid gap-4 text-sm text-muted-foreground","x-chunk":"dashboard-04-chunk-0",children:[(0,t.jsx)(n(),{href:"/dashboard/experimental/network-insights",className:"".concat("/dashboard/experimental/network-insights/"===a?"font-semibold text-primary":"text-sm"),children:"Network Insights"}),(0,t.jsx)(n(),{href:"/dashboard/experimental/keep-alive",className:"".concat("/dashboard/experimental/keep-alive/"===a?"font-semibold text-primary":"text-sm"),children:"Keep Alive"}),(0,t.jsx)(n(),{href:"/dashboard/experimental/scheduled-reboot",className:"".concat("/dashboard/experimental/scheduled-reboot/"===a?"font-semibold text-primary":"text-sm"),children:"Scheduled Reboot"})]}),s]})]})}},16118:(e,s,a)=>{"use strict";var t=a(65834);a.o(t,"usePathname")&&a.d(s,{usePathname:function(){return t.usePathname}}),a.o(t,"useRouter")&&a.d(s,{useRouter:function(){return t.useRouter}})}},e=>{var s=s=>e(e.s=s);e.O(0,[9477,191,6035,7358],()=>s(87390)),_N_E=e.O()}]);
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[3075],{87390:(e,s,a)=>{Promise.resolve().then(a.bind(a,31753))},31753:(e,s,a)=>{"use strict";a.r(s),a.d(s,{default:()=>n});var t=a(20475);a(20107);var r=a(16118),l=a(9477),d=a.n(l);let n=e=>{let{children:s}=e,a=(0,r.usePathname)();return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)("div",{className:"mx-auto grid w-full max-w-6xl gap-2",children:(0,t.jsx)("h1",{className:"text-3xl font-semibold",children:"Experimental"})}),(0,t.jsxs)("div",{className:"mx-auto grid w-full max-w-6xl items-start gap-6 md:grid-cols-[180px_1fr] lg:grid-cols-[250px_1fr]",children:[(0,t.jsxs)("nav",{className:"grid gap-4 text-sm text-muted-foreground","x-chunk":"dashboard-04-chunk-0",children:[(0,t.jsx)(d(),{href:"/dashboard/experimental/network-insights",className:"".concat("/dashboard/experimental/network-insights/"===a?"font-semibold text-primary":"text-sm"),children:"Network Insights"}),(0,t.jsx)(d(),{href:"/dashboard/experimental/keep-alive",className:"".concat("/dashboard/experimental/keep-alive/"===a?"font-semibold text-primary":"text-sm"),children:"Keep Alive"}),(0,t.jsx)(d(),{href:"/dashboard/experimental/scheduled-reboot",className:"".concat("/dashboard/experimental/scheduled-reboot/"===a?"font-semibold text-primary":"text-sm"),children:"Scheduled Reboot"}),(0,t.jsx)(d(),{href:"/dashboard/experimental/logs",className:"".concat("/dashboard/experimental/logs/"===a?"font-semibold text-primary":"text-sm"),children:"Logs"})]}),s]})]})}},16118:(e,s,a)=>{"use strict";var t=a(65834);a.o(t,"usePathname")&&a.d(s,{usePathname:function(){return t.usePathname}}),a.o(t,"useRouter")&&a.d(s,{useRouter:function(){return t.useRouter}})}},e=>{var s=s=>e(e.s=s);e.O(0,[9477,191,6035,7358],()=>s(87390)),_N_E=e.O()}]);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
self.__BUILD_MANIFEST=function(r,e,t){return{__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},__routerFilterStatic:{numItems:32,errorRate:1e-4,numBits:614,numHashes:14,bitArray:[0,1,1,1,0,r,0,e,e,r,r,e,e,r,r,e,r,r,e,e,e,r,r,e,r,r,e,e,r,r,r,r,r,e,r,e,r,r,r,r,e,e,r,e,r,r,e,r,e,r,r,e,e,e,r,e,e,e,e,r,e,e,r,r,r,e,e,e,e,e,r,r,r,r,r,r,e,r,e,r,r,r,e,r,e,r,e,e,r,r,r,e,e,r,r,e,e,r,r,r,r,e,e,r,r,r,r,e,r,e,r,r,e,r,r,e,r,r,r,r,r,e,e,r,r,e,e,e,e,e,r,r,e,r,e,r,r,r,r,e,e,e,e,e,r,r,r,e,r,e,e,e,r,r,r,r,r,e,e,e,e,r,e,e,e,e,e,r,r,e,e,e,e,e,r,e,e,e,r,r,e,e,r,r,e,r,e,e,r,e,r,e,e,e,e,r,r,e,r,e,e,e,e,r,e,r,e,r,r,r,r,e,e,e,e,r,r,r,e,e,r,r,e,r,e,r,e,r,r,r,e,r,r,e,e,e,e,e,e,e,r,r,e,r,e,r,e,e,e,e,r,e,r,r,r,e,r,e,e,r,e,r,r,e,e,r,r,r,r,e,e,e,e,e,r,e,r,r,e,e,r,e,r,e,r,r,e,e,e,r,e,r,e,r,r,e,e,r,e,r,r,r,r,e,r,e,r,e,r,e,e,e,e,e,e,e,r,r,e,r,r,e,e,e,e,r,r,r,e,e,e,e,e,e,e,e,e,r,e,e,r,e,r,r,r,r,r,r,e,r,e,e,e,e,r,r,r,r,r,e,r,e,r,r,e,r,r,r,r,e,e,e,r,r,e,r,r,r,e,r,r,e,e,e,r,r,r,e,e,e,e,e,e,r,e,r,r,r,r,e,e,e,r,r,r,e,e,e,r,r,e,r,r,e,r,r,e,e,r,r,e,r,e,r,e,e,r,r,e,e,r,r,r,e,e,r,r,r,r,r,e,e,r,e,r,e,r,e,e,e,r,r,e,e,r,r,r,e,r,e,e,r,r,e,r,r,r,r,r,r,e,r,e,e,r,r,e,e,r,r,r,e,r,r,r,r,r,r,r,r,e,r,r,e,r,r,e,e,r,r,e,r,r,e,e,r,r,r,e,e,r,r,r,e,r,r,e,r,r,r,r,e,e,e,r,r,r,e,e,r,e,e,r,r,r,r,e,e,r,r,e,r,e,r,e,e,r,e,r,r,e,r,r,e,e,r,r,r,e,r,r,r,e,r,e,r,e,r,r,r,e,r,e,r,r,r,r,e,e,r,e,e,e,r,r,r,e,r,e,r,e,r,e,e,r,e,r,e,r,r,r,r,e,r,r,e,r,r,e,e,e,r,e,r]},__routerFilterDynamic:{numItems:e,errorRate:1e-4,numBits:e,numHashes:null,bitArray:[]},"/_error":["static/chunks/pages/_error-8219f0da6c3b58d9.js"],sortedPages:["/_app","/_error"]}}(1,0,0),self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB();

View File

@@ -0,0 +1,2 @@
[ZoneTransfer]
ZoneId=3

View File

@@ -0,0 +1,2 @@
[ZoneTransfer]
ZoneId=3

View File

@@ -0,0 +1,2 @@
[ZoneTransfer]
ZoneId=3

View File

@@ -0,0 +1,220 @@
#!/bin/sh
# QuecManager Log Viewer API
# Provides centralized log access for the web interface
. /www/cgi-bin/services/quecmanager_logger.sh
# CGI Headers
printf "Content-Type: application/json\r\n"
printf "Access-Control-Allow-Origin: *\r\n"
printf "Access-Control-Allow-Methods: GET, POST, OPTIONS\r\n"
printf "Access-Control-Allow-Headers: Content-Type\r\n"
printf "\r\n"
# Initialize logs if needed
qm_init_logs
# Parse query parameters
QUERY_STRING="${QUERY_STRING:-}"
CATEGORY=""
SCRIPT=""
LEVEL=""
LINES="50"
SINCE=""
# Simple parameter parsing
if [ -n "$QUERY_STRING" ]; then
for param in $(echo "$QUERY_STRING" | tr '&' ' '); do
case "$param" in
category=*)
CATEGORY=$(echo "$param" | cut -d'=' -f2 | sed 's/%20/ /g' | tr -d '"')
;;
script=*)
SCRIPT=$(echo "$param" | cut -d'=' -f2 | sed 's/%20/ /g' | tr -d '"')
;;
level=*)
LEVEL=$(echo "$param" | cut -d'=' -f2 | sed 's/%20/ /g' | tr -d '"')
;;
lines=*)
LINES=$(echo "$param" | cut -d'=' -f2 | tr -d '"')
;;
since=*)
SINCE=$(echo "$param" | cut -d'=' -f2 | sed 's/%20/ /g' | tr -d '"')
;;
esac
done
fi
# Validate lines parameter
if ! echo "$LINES" | grep -qE '^[0-9]+$' || [ "$LINES" -gt 1000 ]; then
LINES="50"
fi
# Function to get available categories
get_categories() {
printf '{\n'
printf ' "categories": [\n'
if [ -d "$QM_LOG_DAEMONS" ]; then
printf ' "daemons"'
[ -d "$QM_LOG_SERVICES" ] || [ -d "$QM_LOG_SETTINGS" ] || [ -d "$QM_LOG_SYSTEM" ] && printf ','
printf '\n'
fi
if [ -d "$QM_LOG_SERVICES" ]; then
printf ' "services"'
[ -d "$QM_LOG_SETTINGS" ] || [ -d "$QM_LOG_SYSTEM" ] && printf ','
printf '\n'
fi
if [ -d "$QM_LOG_SETTINGS" ]; then
printf ' "settings"'
[ -d "$QM_LOG_SYSTEM" ] && printf ','
printf '\n'
fi
if [ -d "$QM_LOG_SYSTEM" ]; then
printf ' "system"\n'
fi
printf ' ]\n'
printf '}\n'
}
# Function to get available scripts for a category
get_scripts() {
local cat_dir=""
case "$CATEGORY" in
"daemons") cat_dir="$QM_LOG_DAEMONS" ;;
"services") cat_dir="$QM_LOG_SERVICES" ;;
"settings") cat_dir="$QM_LOG_SETTINGS" ;;
"system") cat_dir="$QM_LOG_SYSTEM" ;;
*)
printf '{"error": "Invalid category"}\n'
return 1
;;
esac
if [ ! -d "$cat_dir" ]; then
printf '{"scripts": []}\n'
return 0
fi
printf '{\n'
printf ' "scripts": [\n'
first=true
for logfile in "$cat_dir"/*.log; do
if [ -f "$logfile" ]; then
if [ "$first" = "false" ]; then
printf ',\n'
fi
script_name=$(basename "$logfile" .log)
printf ' "%s"' "$script_name"
first=false
fi
done
printf '\n ]\n'
printf '}\n'
}
# Function to get log entries
get_logs() {
local logfile=""
if [ -n "$CATEGORY" ] && [ -n "$SCRIPT" ]; then
logfile=$(qm_get_logfile "$CATEGORY" "$SCRIPT")
else
printf '{"error": "Category and script parameters required"}\n'
return 1
fi
if [ ! -f "$logfile" ]; then
printf '{"entries": [], "total": 0}\n'
return 0
fi
# Get log entries with optional filtering
local temp_file="/tmp/quecmanager_log_view.$$"
# Start with all entries
cat "$logfile" > "$temp_file" 2>/dev/null
# Filter by level if specified
if [ -n "$LEVEL" ]; then
grep "\[$LEVEL\]" "$temp_file" > "${temp_file}.filtered" 2>/dev/null || touch "${temp_file}.filtered"
mv "${temp_file}.filtered" "$temp_file"
fi
# Filter by time if specified (simple grep for now)
if [ -n "$SINCE" ]; then
grep "$SINCE" "$temp_file" > "${temp_file}.filtered" 2>/dev/null || touch "${temp_file}.filtered"
mv "${temp_file}.filtered" "$temp_file"
fi
# Get total count
local total_count=$(wc -l < "$temp_file" 2>/dev/null || echo "0")
# Get last N lines
tail -n "$LINES" "$temp_file" > "${temp_file}.final" 2>/dev/null || touch "${temp_file}.final"
printf '{\n'
printf ' "entries": [\n'
first=true
while IFS= read -r line; do
if [ -n "$line" ]; then
if [ "$first" = "false" ]; then
printf ',\n'
fi
# Parse log line (format: [timestamp] [level] [script] [pid] message)
timestamp=$(echo "$line" | sed -n 's/^\[\([^]]*\)\].*/\1/p')
level=$(echo "$line" | sed -n 's/^[^]]*\] \[\([^]]*\)\].*/\1/p')
script=$(echo "$line" | sed -n 's/^[^]]*\] [^]]*\] \[\([^]]*\)\].*/\1/p')
pid=$(echo "$line" | sed -n 's/^[^]]*\] [^]]*\] [^]]*\] \[PID:\([^]]*\)\].*/\1/p')
message=$(echo "$line" | sed 's/^[^]]*\] [^]]*\] [^]]*\] [^]]*\] //')
# Escape quotes in message
message=$(echo "$message" | sed 's/"/\\"/g')
printf ' {\n'
printf ' "timestamp": "%s",\n' "$timestamp"
printf ' "level": "%s",\n' "$level"
printf ' "script": "%s",\n' "$script"
printf ' "pid": "%s",\n' "$pid"
printf ' "message": "%s"\n' "$message"
printf ' }'
first=false
fi
done < "${temp_file}.final"
printf '\n ],\n'
printf ' "total": %s,\n' "$total_count"
printf ' "showing": %s\n' "$LINES"
printf '}\n'
# Cleanup temp files
rm -f "$temp_file" "${temp_file}.filtered" "${temp_file}.final" 2>/dev/null || true
}
# Main logic
case "$REQUEST_METHOD" in
"GET")
if [ -z "$CATEGORY" ]; then
# Return available categories
get_categories
elif [ -z "$SCRIPT" ]; then
# Return available scripts for category
get_scripts
else
# Return log entries
get_logs
fi
;;
"OPTIONS")
# Handle CORS preflight
exit 0
;;
*)
printf '{"error": "Method not allowed"}\n'
;;
esac

View File

@@ -0,0 +1,2 @@
[ZoneTransfer]
ZoneId=3

View File

@@ -0,0 +1,2 @@
[ZoneTransfer]
ZoneId=3

View File

@@ -0,0 +1,2 @@
[ZoneTransfer]
ZoneId=3

View File

@@ -0,0 +1,2 @@
[ZoneTransfer]
ZoneId=3

Some files were not shown because too many files have changed in this diff Show More