windows installer fixes
CI Test Suite / Run Component Tests & Pipeline Verification (push) Successful in 1m17s
Release Binaries & Packages / Build & Release Standalone Binaries (Linux & Windows Cross-Compilation) (push) Successful in 4m15s

This commit is contained in:
2026-09-27 16:07:18 +02:00
parent fcba813edd
commit b79022bc41
13 changed files with 450 additions and 21 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

+50
View File
@@ -0,0 +1,50 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="100%" height="100%">
<defs>
<linearGradient id="bgGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#0E1A2E"/>
<stop offset="50%" stop-color="#08101E"/>
<stop offset="100%" stop-color="#040810"/>
</linearGradient>
<linearGradient id="cyanGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#00E5FF"/>
<stop offset="100%" stop-color="#0072FF"/>
</linearGradient>
<linearGradient id="emeraldGrad" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="#00FFA3"/>
<stop offset="100%" stop-color="#00E5FF"/>
</linearGradient>
<filter id="glow" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="12" result="blur"/>
<feMerge>
<feMergeNode in="blur"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
</defs>
<!-- Base Hexagon Shield -->
<polygon points="256,24 456,139 456,373 256,488 56,373 56,139"
fill="url(#bgGrad)" stroke="url(#cyanGrad)" stroke-width="8" filter="url(#glow)"/>
<!-- Inner Telemetry Grid / Ring -->
<polygon points="256,58 426,156 426,356 256,454 86,356 86,156"
fill="none" stroke="#162A45" stroke-width="3" stroke-dasharray="8 6"/>
<!-- Stylized L and Log Streams -->
<!-- Main Left Spine -->
<rect x="140" y="140" width="46" height="232" rx="10" fill="url(#cyanGrad)" filter="url(#glow)"/>
<!-- Base Log Floor -->
<rect x="140" y="326" width="220" height="46" rx="10" fill="url(#cyanGrad)" filter="url(#glow)"/>
<!-- Telemetry Pulse Wave 1 -->
<rect x="220" y="210" width="36" height="80" rx="8" fill="url(#emeraldGrad)"/>
<!-- Telemetry Pulse Wave 2 -->
<rect x="286" y="150" width="36" height="140" rx="8" fill="url(#cyanGrad)"/>
<!-- Connection Nodes / Spark Points -->
<circle cx="238" cy="190" r="7" fill="#00FFA3" filter="url(#glow)"/>
<circle cx="304" cy="130" r="7" fill="#00E5FF" filter="url(#glow)"/>
<circle cx="380" cy="349" r="8" fill="#00E5FF" filter="url(#glow)"/>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

+349
View File
@@ -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(
"<IIIHHIIIIII",
40, # biSize
width, # biWidth
height, # biHeight (positive = bottom-to-top)
1, # biPlanes
24, # biBitCount (24-bit BGR)
0, # biCompression (BI_RGB)
image_size, # biSizeImage
2835, # biXPelsPerMeter (72 DPI)
2835, # biYPelsPerMeter
0, # biClrUsed
0 # biClrImportant
)
data = bytearray()
pad = b"\x00" * padding
# BMP is stored bottom-to-top
for y in range(height - 1, -1, -1):
for x in range(width):
r, g, b = pixel_func(x, y, width, height)
data.extend(bytes([int(b) & 0xFF, int(g) & 0xFF, int(r) & 0xFF]))
data.extend(pad)
return header + info + bytes(data)
def create_png_rgba(width: int, height: int, pixel_func) -> 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("<HHH", 0, 1, count) # Reserved=0, Type=1 (ICO), Count
entries = bytearray()
offset = 6 + (16 * count)
image_data_blocks = []
for w, h, png_bytes in png_images:
size = len(png_bytes)
b_w = w if w < 256 else 0
b_h = h if h < 256 else 0
entry = struct.pack(
"<BBBBHHII",
b_w,
b_h,
0, # Color count
0, # Reserved
1, # Color planes
32, # Bits per pixel
size,
offset
)
entries.extend(entry)
image_data_blocks.append(png_bytes)
offset += size
return header + bytes(entries) + b"".join(image_data_blocks)
def generate_svg_logo() -> str:
"""Generates a high-quality SVG vector graphic for LOGAR."""
return """<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="100%" height="100%">
<defs>
<linearGradient id="bgGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#0E1A2E"/>
<stop offset="50%" stop-color="#08101E"/>
<stop offset="100%" stop-color="#040810"/>
</linearGradient>
<linearGradient id="cyanGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#00E5FF"/>
<stop offset="100%" stop-color="#0072FF"/>
</linearGradient>
<linearGradient id="emeraldGrad" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="#00FFA3"/>
<stop offset="100%" stop-color="#00E5FF"/>
</linearGradient>
<filter id="glow" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="12" result="blur"/>
<feMerge>
<feMergeNode in="blur"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
</defs>
<!-- Base Hexagon Shield -->
<polygon points="256,24 456,139 456,373 256,488 56,373 56,139"
fill="url(#bgGrad)" stroke="url(#cyanGrad)" stroke-width="8" filter="url(#glow)"/>
<!-- Inner Telemetry Grid / Ring -->
<polygon points="256,58 426,156 426,356 256,454 86,356 86,156"
fill="none" stroke="#162A45" stroke-width="3" stroke-dasharray="8 6"/>
<!-- Stylized L and Log Streams -->
<!-- Main Left Spine -->
<rect x="140" y="140" width="46" height="232" rx="10" fill="url(#cyanGrad)" filter="url(#glow)"/>
<!-- Base Log Floor -->
<rect x="140" y="326" width="220" height="46" rx="10" fill="url(#cyanGrad)" filter="url(#glow)"/>
<!-- Telemetry Pulse Wave 1 -->
<rect x="220" y="210" width="36" height="80" rx="8" fill="url(#emeraldGrad)"/>
<!-- Telemetry Pulse Wave 2 -->
<rect x="286" y="150" width="36" height="140" rx="8" fill="url(#cyanGrad)"/>
<!-- Connection Nodes / Spark Points -->
<circle cx="238" cy="190" r="7" fill="#00FFA3" filter="url(#glow)"/>
<circle cx="304" cy="130" r="7" fill="#00E5FF" filter="url(#glow)"/>
<circle cx="380" cy="349" r="8" fill="#00E5FF" filter="url(#glow)"/>
</svg>"""
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()
+3
View File
@@ -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
+9 -1
View File
@@ -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
+3
View File
@@ -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
+9 -1
View File
@@ -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 ---
+8
View File
@@ -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()