diff --git a/compilation/assets/logo.ico b/compilation/assets/logo.ico new file mode 100644 index 0000000..179d4ad Binary files /dev/null and b/compilation/assets/logo.ico differ diff --git a/compilation/assets/logo.png b/compilation/assets/logo.png new file mode 100644 index 0000000..98c1fcf Binary files /dev/null and b/compilation/assets/logo.png differ diff --git a/compilation/assets/logo.svg b/compilation/assets/logo.svg new file mode 100644 index 0000000..e6261f3 --- /dev/null +++ b/compilation/assets/logo.svg @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/compilation/assets/logo_256x256.png b/compilation/assets/logo_256x256.png new file mode 100644 index 0000000..c530a5a Binary files /dev/null and b/compilation/assets/logo_256x256.png differ diff --git a/compilation/assets/wizard_header.bmp b/compilation/assets/wizard_header.bmp new file mode 100644 index 0000000..5694f1d Binary files /dev/null and b/compilation/assets/wizard_header.bmp differ diff --git a/compilation/assets/wizard_sidebar.bmp b/compilation/assets/wizard_sidebar.bmp new file mode 100644 index 0000000..e88d01e Binary files /dev/null and b/compilation/assets/wizard_sidebar.bmp differ diff --git a/compilation/generate_branding_assets.py b/compilation/generate_branding_assets.py new file mode 100644 index 0000000..17034e4 --- /dev/null +++ b/compilation/generate_branding_assets.py @@ -0,0 +1,349 @@ +""" +LOGAR Branding & Installer Graphics Generator +Generates clean, professional SVG, PNG, ICO, and BMP visual assets for +LOGAR installers (Inno Setup & NSIS), application icons, and WebUI branding. +Zero external dependencies required (uses standard library zlib and struct). +""" + +import os +import math +import zlib +import struct + +ASSETS_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "assets") +os.makedirs(ASSETS_DIR, exist_ok=True) + + +def create_bmp_24bit(width: int, height: int, pixel_func) -> bytes: + """Generates an uncompressed 24-bit RGB BMP image.""" + row_bytes = width * 3 + padding = (4 - (row_bytes % 4)) % 4 + image_size = (row_bytes + padding) * height + file_size = 14 + 40 + image_size + + # BITMAPFILEHEADER (14 bytes) + header = struct.pack( + "<2sIHHI", + b"BM", + file_size, + 0, 0, + 54 # Offset to pixel data + ) + + # BITMAPINFOHEADER (40 bytes) + info = struct.pack( + " bytes: + """Generates a standard 32-bit RGBA PNG image.""" + raw_scanlines = bytearray() + for y in range(height): + raw_scanlines.append(0) # Filter type 0 (None) + for x in range(width): + r, g, b, a = pixel_func(x, y, width, height) + raw_scanlines.extend(bytes([int(r) & 0xFF, int(g) & 0xFF, int(b) & 0xFF, int(a) & 0xFF])) + + compressed = zlib.compress(bytes(raw_scanlines), level=9) + + def chunk(tag: bytes, data: bytes) -> bytes: + chk = tag + data + crc = zlib.crc32(chk) & 0xFFFFFFFF + return struct.pack(">I", len(data)) + chk + struct.pack(">I", crc) + + ihdr = struct.pack(">IIBBBBB", width, height, 8, 6, 0, 0, 0) + png_bytes = b"\x89PNG\r\n\x1a\n" + chunk(b"IHDR", ihdr) + chunk(b"IDAT", compressed) + chunk(b"IEND", b"") + return png_bytes + + +def draw_logo_rgba(x: int, y: int, w: int, h: int) -> tuple: + """Renders a sleek modern cyberpunk hexagon shield and pulse log streams.""" + nx = (x - w / 2) / (w / 2) + ny = (y - h / 2) / (h / 2) + dist = math.sqrt(nx * nx + ny * ny) + + if dist > 0.98: + return 0, 0, 0, 0 + + # Background rounded container / shield + # Hexagon radius + angle = math.atan2(ny, nx) + hex_radius = 0.88 / (math.cos((angle % (math.pi / 3)) - (math.pi / 6)) + 0.001) + + if dist > hex_radius: + # Subtle anti-aliased edge + if dist < hex_radius + 0.05: + alpha = max(0.0, min(1.0, (hex_radius + 0.05 - dist) / 0.05)) + return 11, 25, 44, int(alpha * 255) + return 0, 0, 0, 0 + + # Gradient background: Dark Slate Blue to Navy + grad_t = (ny + 1) / 2 + bg_r = int(12 * (1 - grad_t) + 6 * grad_t) + bg_g = int(24 * (1 - grad_t) + 14 * grad_t) + bg_b = int(48 * (1 - grad_t) + 32 * grad_t) + + # Hexagon outer border (Cyber Cyan / Emerald highlight) + if dist > hex_radius - 0.06: + glow_t = (nx + 1) / 2 + br = int(0 * (1 - glow_t) + 0 * glow_t) + bg = int(229 * (1 - glow_t) + 160 * glow_t) + bb = int(255 * (1 - glow_t) + 255 * glow_t) + return br, bg, bb, 255 + + # Center stylized 'L' log symbol and dynamic telemetry bars + # Bar 1 (Left Log Stream): x in [-0.45, -0.25], y in [-0.5, 0.4] + if -0.42 <= nx <= -0.22 and -0.45 <= ny <= 0.45: + # Cyan gradient + v = (ny + 0.45) / 0.9 + return int(0), int(220 * (1 - v) + 140 * v), int(255), 255 + + # Bar 2 (Bottom Base of 'L'): x in [-0.42, 0.35], y in [0.25, 0.45] + if -0.42 <= nx <= 0.35 and 0.25 <= ny <= 0.45: + v = (nx + 0.42) / 0.77 + return int(0), int(220 * (1 - v) + 180 * v), int(255), 255 + + # Bar 3 (Central Stream Wave 1): x in [-0.10, 0.08], y in [-0.30, 0.12] + if -0.10 <= nx <= 0.08 and -0.30 <= ny <= 0.12: + return 0, 240, 255, 255 + + # Bar 4 (Central Stream Wave 2): x in [0.18, 0.36], y in [-0.50, 0.12] + if 0.18 <= nx <= 0.36 and -0.50 <= ny <= 0.12: + return 0, 180, 255, 255 + + # Subtle inner grid dots / pulse nodes + grid_x = (nx * 10) % 1 + grid_y = (ny * 10) % 1 + if 0.45 <= grid_x <= 0.55 and 0.45 <= grid_y <= 0.55: + return bg_r + 20, bg_g + 30, bg_b + 50, 255 + + return bg_r, bg_g, bg_b, 255 + + +def draw_wizard_header_bgr(x: int, y: int, w: int, h: int) -> tuple: + """Renders 150x57 BMP header graphic.""" + # Dark modern gradient background + t = x / w + r = int(14 * (1 - t) + 8 * t) + g = int(24 * (1 - t) + 16 * t) + b = int(44 * (1 - t) + 30 * t) + + # Right-aligned emblem icon in header + icon_center_x = w - 35 + icon_center_y = h / 2 + dx = (x - icon_center_x) / 22 + dy = (y - icon_center_y) / 22 + d = math.sqrt(dx * dx + dy * dy) + + if d < 0.95: + # Render miniature emblem + er, eg, eb, ea = draw_logo_rgba(int((dx + 1) * 32), int((dy + 1) * 32), 64, 64) + if ea > 128: + return er, eg, eb + + # Decorative bottom accent line (Cyan gradient) + if y >= h - 2: + return 0, int(200 * t + 55), 255 + + return r, g, b + + +def draw_wizard_sidebar_bgr(x: int, y: int, w: int, h: int) -> tuple: + """Renders 164x314 BMP sidebar graphic for NSIS / Inno Setup.""" + t_y = y / h + t_x = x / w + + # Deep cyber navy to midnight blue vertical gradient + r = int(10 * (1 - t_y) + 4 * t_y) + g = int(22 * (1 - t_y) + 12 * t_y) + b = int(48 * (1 - t_y) + 26 * t_y) + + # Subtle telemetry grid / stream lines + if int(x) % 18 == 0 or int(y) % 24 == 0: + r = min(255, r + 8) + g = min(255, g + 14) + b = min(255, b + 25) + + # Decorative node glow in top region + emblem_cx = w / 2 + emblem_cy = 90 + edx = (x - emblem_cx) / 44 + edy = (y - emblem_cy) / 44 + ed = math.sqrt(edx * edx + edy * edy) + + if ed < 0.98: + er, eg, eb, ea = draw_logo_rgba(int((edx + 1) * 64), int((edy + 1) * 64), 128, 128) + if ea > 128: + return er, eg, eb + + # Glowing pulse lines streaming downwards from the emblem + if 55 <= x <= 110 and y > 150: + line_idx = int((x - 55) / 14) + line_offset = (line_idx * 37 + int(y * 0.4)) % 100 + if line_offset < 30: + glow = math.sin((line_offset / 30) * math.pi) + g = min(255, int(g + 160 * glow)) + b = min(255, int(b + 220 * glow)) + + # Bottom accent band + if y >= h - 4: + accent_t = x / w + return 0, int(220 * accent_t), 255 + + return r, g, b + + +def generate_ico_file(png_images: list) -> bytes: + """Packs multiple PNG images into a valid Windows .ico container.""" + count = len(png_images) + header = struct.pack(" str: + """Generates a high-quality SVG vector graphic for LOGAR.""" + return """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +""" + + +def main(): + print("[*] Generating high-resolution branding assets for LOGAR...") + + # 1. Generate SVG Logo + svg_path = os.path.join(ASSETS_DIR, "logo.svg") + with open(svg_path, "w", encoding="utf-8") as f: + f.write(generate_svg_logo()) + print(f"[+] Saved SVG logo: {svg_path}") + + # 2. Generate PNG images of various sizes + png_sizes = [16, 32, 48, 64, 128, 256, 512] + png_buffers = [] + for s in png_sizes: + png_data = create_png_rgba(s, s, draw_logo_rgba) + png_buffers.append((s, s, png_data)) + if s in [256, 512]: + out_p = os.path.join(ASSETS_DIR, f"logo_{s}x{s}.png" if s != 512 else "logo.png") + with open(out_p, "wb") as f: + f.write(png_data) + print(f"[+] Saved PNG logo: {out_p}") + + # 3. Generate Windows ICO File + ico_path = os.path.join(ASSETS_DIR, "logo.ico") + ico_data = generate_ico_file(png_buffers[:-1]) # Up to 256x256 + with open(ico_path, "wb") as f: + f.write(ico_data) + print(f"[+] Saved Windows Icon (.ico): {ico_path}") + + # 4. Generate NSIS / Inno Setup Wizard Header Bitmap (150x57) + header_bmp_path = os.path.join(ASSETS_DIR, "wizard_header.bmp") + header_bmp_data = create_bmp_24bit(150, 57, draw_wizard_header_bgr) + with open(header_bmp_path, "wb") as f: + f.write(header_bmp_data) + print(f"[+] Saved Wizard Header Bitmap: {header_bmp_path}") + + # 5. Generate NSIS / Inno Setup Wizard Sidebar Bitmap (164x314) + sidebar_bmp_path = os.path.join(ASSETS_DIR, "wizard_sidebar.bmp") + sidebar_bmp_data = create_bmp_24bit(164, 314, draw_wizard_sidebar_bgr) + with open(sidebar_bmp_path, "wb") as f: + f.write(sidebar_bmp_data) + print(f"[+] Saved Wizard Sidebar Bitmap: {sidebar_bmp_path}") + + print("[+] All LOGAR branding and installer graphics generated successfully.") + + +if __name__ == "__main__": + main() diff --git a/compilation/installer_client.iss b/compilation/installer_client.iss index b90e7b0..0480ca5 100644 --- a/compilation/installer_client.iss +++ b/compilation/installer_client.iss @@ -12,6 +12,9 @@ PrivilegesRequired=admin Compression=lzma SolidCompression=yes WizardStyle=modern +SetupIconFile=assets\logo.ico +WizardImageFile=assets\wizard_sidebar.bmp +WizardSmallImageFile=assets\wizard_header.bmp VersionInfoCompany=LOGAR Security Systems VersionInfoDescription=LOGAR Windows Edge Log Forwarder Setup VersionInfoVersion=0.3.2.0 diff --git a/compilation/installer_client.nsi b/compilation/installer_client.nsi index d49b80e..bc7e768 100644 --- a/compilation/installer_client.nsi +++ b/compilation/installer_client.nsi @@ -7,7 +7,7 @@ OutFile "../dist/LOGAR-Client-Setup.exe" InstallDir "$PROGRAMFILES64\LOGAR" RequestExecutionLevel admin -BrandingText "LOGAR Enterprise SIEM & Edge Forwarder" +BrandingText "LOGAR Centralized Log Aggregator & Forwarder" VIProductVersion "0.3.2.0" VIAddVersionKey "ProductName" "LOGAR Client" @@ -17,6 +17,14 @@ VIAddVersionKey "FileDescription" "LOGAR Windows Edge Log Forwarder Setup" VIAddVersionKey "FileVersion" "0.3.2.0" VIAddVersionKey "ProductVersion" "0.3.2.0" +# --- Visual Graphics & Branding --- +!define MUI_ICON "assets/logo.ico" +!define MUI_UNICON "assets/logo.ico" +!define MUI_HEADERIMAGE +!define MUI_HEADERIMAGE_BITMAP "assets/wizard_header.bmp" +!define MUI_WELCOMEFINISHPAGE_BITMAP "assets/wizard_sidebar.bmp" +!define MUI_UNWELCOMEFINISHPAGE_BITMAP "assets/wizard_sidebar.bmp" + Var DATADIR Var CFGFILE Var CfgDialog diff --git a/compilation/installer_server.iss b/compilation/installer_server.iss index 7714f37..3528a94 100644 --- a/compilation/installer_server.iss +++ b/compilation/installer_server.iss @@ -12,6 +12,9 @@ PrivilegesRequired=admin Compression=lzma SolidCompression=yes WizardStyle=modern +SetupIconFile=assets\logo.ico +WizardImageFile=assets\wizard_sidebar.bmp +WizardSmallImageFile=assets\wizard_header.bmp VersionInfoCompany=LOGAR Security Systems VersionInfoDescription=LOGAR Cloud Hub & TCP Ingestion Server Setup VersionInfoVersion=0.3.2.0 diff --git a/compilation/installer_server.nsi b/compilation/installer_server.nsi index 6b74359..025afd7 100644 --- a/compilation/installer_server.nsi +++ b/compilation/installer_server.nsi @@ -6,7 +6,7 @@ OutFile "../dist/LOGAR-Server-Setup.exe" InstallDir "$PROGRAMFILES64\LOGAR-Server" RequestExecutionLevel admin -BrandingText "LOGAR Enterprise SIEM & Log Ingestion" +BrandingText "LOGAR Centralized Log Aggregator & Ingestion Hub" VIProductVersion "0.3.2.0" VIAddVersionKey "ProductName" "LOGAR Server" @@ -16,6 +16,14 @@ VIAddVersionKey "FileDescription" "LOGAR Cloud Hub & TCP Ingestion Server Setup" VIAddVersionKey "FileVersion" "0.3.2.0" VIAddVersionKey "ProductVersion" "0.3.2.0" +# --- Visual Graphics & Branding --- +!define MUI_ICON "assets/logo.ico" +!define MUI_UNICON "assets/logo.ico" +!define MUI_HEADERIMAGE +!define MUI_HEADERIMAGE_BITMAP "assets/wizard_header.bmp" +!define MUI_WELCOMEFINISHPAGE_BITMAP "assets/wizard_sidebar.bmp" +!define MUI_UNWELCOMEFINISHPAGE_BITMAP "assets/wizard_sidebar.bmp" + Var DATADIR # --- UI Pages --- diff --git a/compilation/package_dist.py b/compilation/package_dist.py index 98fbc35..97ba729 100644 --- a/compilation/package_dist.py +++ b/compilation/package_dist.py @@ -35,6 +35,14 @@ def clean_and_prep(): pass os.makedirs(BUILD_TEMP, exist_ok=True) + # Generate or verify branding images and icons + branding_script = os.path.join(ROOT_DIR, "compilation", "generate_branding_assets.py") + if os.path.exists(branding_script): + try: + subprocess.run([sys.executable, branding_script], cwd=os.path.join(ROOT_DIR, "compilation"), check=False) + except Exception: + pass + def calculate_sha256(filepath): h = hashlib.sha256() diff --git a/src/Server.py b/src/Server.py index 324cb61..10c0662 100644 --- a/src/Server.py +++ b/src/Server.py @@ -1327,7 +1327,15 @@ def login_page(request: Request): - 🛰️ + + + + + + + + + LOGAR Server Hub Fleet Ingestion & Centralized Provisioning @@ -2418,10 +2426,18 @@ def serve_webui(request: Request = None): - 🛰️ + + + + + + + + + LOGAR Fleet Hub - Fleet Log Aggregation & Centralized AI Provisioning + Fleet Log Aggregation & Centralized Provisioning @@ -2596,7 +2612,6 @@ def serve_webui(request: Request = None): PKI & Seat Synchronization: 📥 Import License (.lic) - 📋 Copy CA CSR 🔄 Sync & Renew via mTLS @@ -2754,21 +2769,6 @@ def serve_webui(request: Request = None): window.location.href = '/api/license/export-lic'; }} - async function copyCaCsr() {{ - try {{ - const res = await fetch('/api/license/csr'); - if (res.ok) {{ - const data = await res.json(); - navigator.clipboard.writeText(data.csr); - showAlert('CA CSR copied to clipboard!'); - }} else {{ - alert('Failed to fetch CA CSR'); - }} - }} catch (err) {{ - alert('Error fetching CA CSR: ' + err.message); - }} - }} - function handleLicFile(event) {{ const file = event.target.files[0]; if (!file) return;