Added simple eventlog.

This commit is contained in:
Jakob Friedl
2025-09-19 11:43:14 +02:00
parent 3173122878
commit 6b41efe1ed
6 changed files with 167 additions and 92 deletions

View File

@@ -26,30 +26,6 @@ proc getText(item: ConsoleItem): cstring =
else:
return fmt"{$item.itemType}{item.text}".string
proc print(item: ConsoleItem) =
if item.timestamp > 0:
let timestamp = item.timestamp.fromUnix().format("dd-MM-yyyy HH:mm:ss")
igTextColored(vec4(0.6f, 0.6f, 0.6f, 1.0f), fmt"[{timestamp}]".cstring)
igSameLine(0.0f, 0.0f)
# https://rgbcolorpicker.com/0-1
case item.itemType:
of LOG_INFO:
igTextColored(CONSOLE_INFO, $item.itemType)
of LOG_ERROR:
igTextColored(CONSOLE_ERROR, $item.itemType)
of LOG_SUCCESS:
igTextColored(CONSOLE_SUCCESS, $item.itemType)
of LOG_WARNING:
igTextColored(CONSOLE_WARNING, $item.itemType)
of LOG_COMMAND:
igTextColored(CONSOLE_COMMAND, $item.itemType)
of LOG_OUTPUT:
igTextColored(vec4(0.0f, 0.0f, 0.0f, 0.0f), $item.itemType)
igSameLine(0.0f, 0.0f)
igTextUnformatted(item.text.cstring, nil)
proc getNumLines(data: pointer): csize_t {.cdecl.} =
if data.isNil:
return 0
@@ -133,7 +109,45 @@ proc callback(data: ptr ImGuiInputTextCallbackData): cint {.cdecl.} =
discard
else: discard
#[
API to add new console item
]#
proc addItem*(component: ConsoleComponent, itemType: LogType, data: string) =
for line in data.split("\n"):
component.console.items.add(ConsoleItem(
timestamp: if itemType == LOG_OUTPUT: 0 else: now().toTime().toUnix(),
itemType: itemType,
text: line
))
#[
Drawing
]#
proc print(item: ConsoleItem) =
if item.timestamp > 0:
let timestamp = item.timestamp.fromUnix().format("dd-MM-yyyy HH:mm:ss")
igTextColored(vec4(0.6f, 0.6f, 0.6f, 1.0f), fmt"[{timestamp}]".cstring)
igSameLine(0.0f, 0.0f)
case item.itemType:
of LOG_INFO, LOG_INFO_SHORT:
igTextColored(CONSOLE_INFO, $item.itemType)
of LOG_ERROR, LOG_ERROR_SHORT:
igTextColored(CONSOLE_ERROR, $item.itemType)
of LOG_SUCCESS, LOG_SUCCESS_SHORT:
igTextColored(CONSOLE_SUCCESS, $item.itemType)
of LOG_WARNING, LOG_WARNING_SHORT:
igTextColored(CONSOLE_WARNING, $item.itemType)
of LOG_COMMAND:
igTextColored(CONSOLE_COMMAND, $item.itemType)
of LOG_OUTPUT:
igTextColored(vec4(0.0f, 0.0f, 0.0f, 0.0f), $item.itemType)
igSameLine(0.0f, 0.0f)
igTextUnformatted(item.text.cstring, nil)
proc draw*(component: ConsoleComponent) =
igBegin(fmt"[{component.agent.agentId}] {component.agent.username}@{component.agent.hostname}", addr component.showConsole, 0)
defer: igEnd()
@@ -177,6 +191,7 @@ proc draw*(component: ConsoleComponent) =
igText("Press CTRL+F to focus console filter.")
igText("Use \",\" as a delimiter to filter for multiple values.")
igText("Use \"-\" to exclude values.")
igText("Example: \"-warning,a,b\" returns all lines that do not include \"warning\" but include \"a\" or \"b\".")
igEndTooltip()
if igIsWindowFocused(ImGui_FocusedFlags_ChildWindows.int32) and io.KeyCtrl and igIsKeyPressed_Bool(ImGuiKey_F, false):
@@ -237,45 +252,15 @@ proc draw*(component: ConsoleComponent) =
if igInputText("##Input", addr component.inputBuffer[0], MAX_INPUT_LENGTH, inputFlags, callback, cast[pointer](component)):
let command = $(addr component.inputBuffer[0]).cstring
var commandItem = ConsoleItem(
timestamp: now().toTime().toUnix(),
itemType: LOG_COMMAND,
text: command
)
component.console.items.add(commandItem)
component.addItem(LOG_COMMAND, command)
# For testing
commandItem = ConsoleItem(
timestamp: now().toTime().toUnix(),
itemType: LOG_ERROR,
text: "error"
)
component.console.items.add(commandItem)
commandItem = ConsoleItem(
timestamp: now().toTime().toUnix(),
itemType: LOG_SUCCESS,
text: "success"
)
component.console.items.add(commandItem)
commandItem = ConsoleItem(
timestamp: now().toTime().toUnix(),
itemType: LOG_WARNING,
text: "warn"
)
component.console.items.add(commandItem)
commandItem = ConsoleItem(
timestamp: 0,
itemType: LOG_OUTPUT,
text: "output"
)
component.console.items.add(commandItem)
commandItem = ConsoleItem(
timestamp: now().toTime().toUnix(),
itemType: LOG_INFO,
text: "info"
)
component.console.items.add(commandItem)
component.addItem(LOG_ERROR, "error message")
component.addItem(LOG_SUCCESS, "success message")
component.addItem(LOG_INFO, "info message")
component.addItem(LOG_WARNING, "warning message")
component.addItem(LOG_OUTPUT, "error message\nLong output\n\tindented output\nasdasd")
# TODO: Handle command execution
# console.handleCommand(command)
@@ -295,4 +280,4 @@ proc draw*(component: ConsoleComponent) =
]#
let sessionInfo = fmt"{component.agent.username}@{component.agent.hostname}.{component.agent.domain} [{component.agent.ip}] [{component.agent.process}/{$component.agent.pid}]"
igTextColored(vec4(0.75f, 0.75f, 0.75f, 1.0f), sessionInfo)

View File

@@ -1,19 +1,109 @@
import times
import strformat, strutils, times
import imguin/[cimgui, glfw_opengl, simple]
import ../utils/appImGui
import ../../common/[types]
import ../utils/[appImGui, colors]
import ../../common/types
type
EventlogComponent = ref object of RootObj
title: string
log*: ConsoleItems
textSelect: ptr TextSelect
proc getText(item: ConsoleItem): cstring =
if item.timestamp > 0:
let timestamp = item.timestamp.fromUnix().format("dd-MM-yyyy HH:mm:ss")
return fmt"[{timestamp}]{$item.itemType}{item.text}".string
else:
return fmt"{$item.itemType}{item.text}".string
proc getNumLines(data: pointer): csize_t {.cdecl.} =
if data.isNil:
return 0
let log = cast[ConsoleItems](data)
return log.items.len().csize_t
proc getLineAtIndex(i: csize_t, data: pointer, outLen: ptr csize_t): cstring {.cdecl.} =
if data.isNil:
return nil
let log = cast[ConsoleItems](data)
let line = log.items[i].getText()
if not outLen.isNil:
outLen[] = line.len.csize_t
return line
proc Eventlog*(title: string): EventlogComponent =
result = new EventlogComponent
result.title = title
result.log = new ConsoleItems
result.log.items = @[]
result.textSelect = textselect_create(getLineAtIndex, getNumLines, cast[pointer](result.log), 0)
#[
API to add new log entry
]#
proc addItem*(component: EventlogComponent, itemType: LogType, data: string) =
for line in data.split("\n"):
component.log.items.add(ConsoleItem(
timestamp: if itemType == LOG_OUTPUT: 0 else: now().toTime().toUnix(),
itemType: itemType,
text: line
))
#[
Drawing
]#
proc print(item: ConsoleItem) =
if item.timestamp > 0:
let timestamp = item.timestamp.fromUnix().format("dd-MM-yyyy HH:mm:ss")
igTextColored(vec4(0.6f, 0.6f, 0.6f, 1.0f), fmt"[{timestamp}]".cstring)
igSameLine(0.0f, 0.0f)
case item.itemType:
of LOG_INFO, LOG_INFO_SHORT:
igTextColored(CONSOLE_INFO, $item.itemType)
of LOG_ERROR, LOG_ERROR_SHORT:
igTextColored(CONSOLE_ERROR, $item.itemType)
of LOG_SUCCESS, LOG_SUCCESS_SHORT:
igTextColored(CONSOLE_SUCCESS, $item.itemType)
of LOG_WARNING, LOG_WARNING_SHORT:
igTextColored(CONSOLE_WARNING, $item.itemType)
of LOG_COMMAND:
igTextColored(CONSOLE_COMMAND, $item.itemType)
of LOG_OUTPUT:
igTextColored(vec4(0.0f, 0.0f, 0.0f, 0.0f), $item.itemType)
igSameLine(0.0f, 0.0f)
igTextUnformatted(item.text.cstring, nil)
proc draw*(component: EventlogComponent, showComponent: ptr bool) =
igSetNextWindowSize(vec2(800, 600), ImGuiCond_Once.int32)
igBegin(component.title, showComponent, 0)
defer: igEnd()
igText("Eventlog")
try:
# Set styles of the eventlog window
igPushStyleColor_Vec4(ImGui_Col_FrameBg.int32, vec4(0.1f, 0.1f, 0.1f, 1.0f))
igPushStyleColor_Vec4(ImGui_Col_ScrollbarBg.int32, vec4(0.1f, 0.1f, 0.1f, 1.0f))
igPushStyleColor_Vec4(ImGui_Col_Border.int32, vec4(0.2f, 0.2f, 0.2f, 1.0f))
igPushStyleVar_Float(ImGui_StyleVar_FrameBorderSize .int32, 1.0f)
let childWindowFlags = ImGuiChildFlags_NavFlattened.int32 or ImGui_ChildFlags_Borders.int32 or ImGui_ChildFlags_AlwaysUseWindowPadding.int32 or ImGuiChildFlags_FrameStyle.int32
if igBeginChild_Str("##Log", vec2(-1.0f, -1.0f), childWindowFlags, ImGuiWindowFlags_HorizontalScrollbar.int32):
# Display eventlog items
for item in component.log.items:
item.print()
component.textSelect.textselect_update()
# Auto-scroll to bottom
if igGetScrollY() >= igGetScrollMaxY():
igSetScrollHereY(1.0f)
except IndexDefect:
# CTRL+A crashes when no items are in the eventlog
discard
finally:
igPopStyleColor(3)
igPopStyleVar(1)
igEndChild()

View File

@@ -46,6 +46,7 @@ proc draw*(component: ListenersTableComponent, showComponent: ptr bool) =
let listener = component.startListenerModal.draw()
if listener != nil:
# TODO: Start listener
component.listeners.add(listener)
#[