From 1be0f5f7b5e6cff8bcba2bf7d14bf2edb008c94f Mon Sep 17 00:00:00 2001 From: georgweiss Date: Mon, 20 Oct 2025 14:48:39 +0200 Subject: [PATCH 1/3] Escape HTML in Olog logs --- .../logbook/olog/ui/HtmlAwareController.java | 28 ++++++++++++------- .../olog/ui/HtmlAwareControllerTest.java | 18 ++++++++++++ 2 files changed, 36 insertions(+), 10 deletions(-) create mode 100644 app/logbook/olog/ui/src/test/java/org/phoebus/logbook/olog/ui/HtmlAwareControllerTest.java diff --git a/app/logbook/olog/ui/src/main/java/org/phoebus/logbook/olog/ui/HtmlAwareController.java b/app/logbook/olog/ui/src/main/java/org/phoebus/logbook/olog/ui/HtmlAwareController.java index 6799d69016..e6c68188af 100644 --- a/app/logbook/olog/ui/src/main/java/org/phoebus/logbook/olog/ui/HtmlAwareController.java +++ b/app/logbook/olog/ui/src/main/java/org/phoebus/logbook/olog/ui/HtmlAwareController.java @@ -29,30 +29,38 @@ public class HtmlAwareController { - private Parser parser; - private HtmlRenderer htmlRenderer; + private final Parser parser; + private final HtmlRenderer htmlRenderer; + /** + * Constructor to generate html code for HTML preview feature in LogEntryEditor or detailed log entry view. + * @param serviceUrl Olog service url + */ public HtmlAwareController(String serviceUrl){ - List extensions = - Arrays.asList(TablesExtension.create(), ImageAttributesExtension.create()); - this.parser = Parser.builder().extensions(extensions).build(); - htmlRenderer = HtmlRenderer.builder() - .attributeProviderFactory(context -> new OlogAttributeProvider(serviceUrl)) - .extensions(extensions).build(); + this(new OlogAttributeProvider(serviceUrl)); } /** - * To create HtmlAwareController object to generate html code for HTML preview feature in LogEntryEditor. + * Constructor to generate html code for HTML preview feature in LogEntryEditor or detailed log entry view. * @param serviceUrl Olog service url. * @param preview Set true when preview button is clicked. * @param attachments The current attachments list from AttachmentsEditorController. */ public HtmlAwareController(String serviceUrl, boolean preview, List attachments){ + this(new OlogAttributeProvider(serviceUrl, preview, attachments)); + } + + /** + * Private constructor to avoid code duplication. + * @param ologAttributeProvider The {@link OlogAttributeProvider} particular to the use case. + */ + private HtmlAwareController(OlogAttributeProvider ologAttributeProvider){ List extensions = Arrays.asList(TablesExtension.create(), ImageAttributesExtension.create()); this.parser = Parser.builder().extensions(extensions).build(); htmlRenderer = HtmlRenderer.builder() - .attributeProviderFactory(context -> new OlogAttributeProvider(serviceUrl, preview, attachments)) + .escapeHtml(true) + .attributeProviderFactory(context -> ologAttributeProvider) .extensions(extensions).build(); } diff --git a/app/logbook/olog/ui/src/test/java/org/phoebus/logbook/olog/ui/HtmlAwareControllerTest.java b/app/logbook/olog/ui/src/test/java/org/phoebus/logbook/olog/ui/HtmlAwareControllerTest.java new file mode 100644 index 0000000000..5042d9a88e --- /dev/null +++ b/app/logbook/olog/ui/src/test/java/org/phoebus/logbook/olog/ui/HtmlAwareControllerTest.java @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2025 European Spallation Source ERIC. + */ + +package org.phoebus.logbook.olog.ui; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class HtmlAwareControllerTest { + + @Test + public void testEscapeHtml(){ + HtmlAwareController htmlAwareController = new HtmlAwareController(""); + String escapedHtml = htmlAwareController.toHtml("

Paragraph

"); + assertEquals("

<br><p>Paragraph</p>

\n", escapedHtml); + } +} From e12e93cd3ee953ebd4619f1443f46eee72a80e15 Mon Sep 17 00:00:00 2001 From: georgweiss Date: Mon, 20 Oct 2025 14:54:25 +0200 Subject: [PATCH 2/3] Update documentation --- app/logbook/olog/ui/doc/index.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/logbook/olog/ui/doc/index.rst b/app/logbook/olog/ui/doc/index.rst index c0a535f4e2..b69b287a43 100644 --- a/app/logbook/olog/ui/doc/index.rst +++ b/app/logbook/olog/ui/doc/index.rst @@ -21,6 +21,12 @@ Features - Log entry viewers offer search capabilities based on meta data and content. +Missing features +---------------- +In contrast to other markup implementations, HTML tags are **not** supported. Any such tags entered by user will +be rendered as plain text. + + Launching the log entry editor ------------------------------ The log entry editor is launched as a non-modal window using one of the following methods: From adcfec5a9e096dc2a9ad749327cdd132dc85d7fd Mon Sep 17 00:00:00 2001 From: georgweiss Date: Mon, 20 Oct 2025 15:24:55 +0200 Subject: [PATCH 3/3] Show error dialog if search params are invalid --- .../java/org/phoebus/olog/es/api/OlogHttpClient.java | 11 ++++++++--- .../olog/ui/LogEntryCalenderViewController.java | 4 +++- .../logbook/olog/ui/LogEntryTableViewController.java | 7 +++++++ .../java/org/phoebus/logbook/olog/ui/Messages.java | 1 + .../org/phoebus/logbook/olog/ui/messages.properties | 1 + 5 files changed, 20 insertions(+), 4 deletions(-) diff --git a/app/logbook/olog/client-es/src/main/java/org/phoebus/olog/es/api/OlogHttpClient.java b/app/logbook/olog/client-es/src/main/java/org/phoebus/olog/es/api/OlogHttpClient.java index 059227cf88..308d4f2c13 100644 --- a/app/logbook/olog/client-es/src/main/java/org/phoebus/olog/es/api/OlogHttpClient.java +++ b/app/logbook/olog/client-es/src/main/java/org/phoebus/olog/es/api/OlogHttpClient.java @@ -260,9 +260,14 @@ private SearchResult findLogs(MultivaluedMap searchParams) throw .build(); try { HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); - OlogSearchResult searchResult = OlogObjectMappers.logEntryDeserializer.readValue(response.body(), OlogSearchResult.class); - return SearchResult.of(new ArrayList<>(searchResult.getLogs()), - searchResult.getHitCount()); + if(response.statusCode() == 200) { + OlogSearchResult searchResult = OlogObjectMappers.logEntryDeserializer.readValue(response.body(), OlogSearchResult.class); + return SearchResult.of(new ArrayList<>(searchResult.getLogs()), + searchResult.getHitCount()); + } + else{ + throw new RuntimeException(response.body()); + } } catch (Exception e) { LOGGER.log(Level.WARNING, "failed to retrieve log entries", e); throw new RuntimeException(e); diff --git a/app/logbook/olog/ui/src/main/java/org/phoebus/logbook/olog/ui/LogEntryCalenderViewController.java b/app/logbook/olog/ui/src/main/java/org/phoebus/logbook/olog/ui/LogEntryCalenderViewController.java index c6fe61f308..89d64c8815 100644 --- a/app/logbook/olog/ui/src/main/java/org/phoebus/logbook/olog/ui/LogEntryCalenderViewController.java +++ b/app/logbook/olog/ui/src/main/java/org/phoebus/logbook/olog/ui/LogEntryCalenderViewController.java @@ -34,6 +34,7 @@ import org.phoebus.logbook.SearchResult; import org.phoebus.logbook.olog.ui.query.OlogQuery; import org.phoebus.logbook.olog.ui.query.OlogQueryManager; +import org.phoebus.ui.dialog.ExceptionDetailsErrorDialog; import java.net.URL; import java.time.LocalDateTime; @@ -262,7 +263,8 @@ public void search() { }, (msg, ex) -> { searchInProgress.set(false); - }); + ExceptionDetailsErrorDialog.openError(agenda, Messages.SearchFailed, "", ex); + }); } public String getQuery() { diff --git a/app/logbook/olog/ui/src/main/java/org/phoebus/logbook/olog/ui/LogEntryTableViewController.java b/app/logbook/olog/ui/src/main/java/org/phoebus/logbook/olog/ui/LogEntryTableViewController.java index 78d19efce7..e01e0acfa7 100644 --- a/app/logbook/olog/ui/src/main/java/org/phoebus/logbook/olog/ui/LogEntryTableViewController.java +++ b/app/logbook/olog/ui/src/main/java/org/phoebus/logbook/olog/ui/LogEntryTableViewController.java @@ -25,6 +25,7 @@ import javafx.scene.control.Pagination; import javafx.scene.control.ProgressIndicator; import javafx.scene.control.SelectionMode; +import javafx.scene.control.SplitPane; import javafx.scene.control.TableCell; import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; @@ -60,6 +61,7 @@ import org.phoebus.security.store.SecureStore; import org.phoebus.security.tokens.ScopedAuthenticationToken; import org.phoebus.ui.dialog.DialogHelper; +import org.phoebus.ui.dialog.ExceptionDetailsErrorDialog; import java.io.IOException; import java.util.ArrayList; @@ -88,6 +90,10 @@ public class LogEntryTableViewController extends LogbookSearchController impleme @SuppressWarnings("unused") private GridPane viewSearchPane; + @SuppressWarnings("unused") + @FXML + private SplitPane splitPane; + // elements related to the table view of the log entries @FXML @SuppressWarnings("unused") @@ -420,6 +426,7 @@ public void search() { }, (msg, ex) -> { searchInProgress.set(false); + ExceptionDetailsErrorDialog.openError(splitPane, Messages.SearchFailed, "", ex); }); } diff --git a/app/logbook/olog/ui/src/main/java/org/phoebus/logbook/olog/ui/Messages.java b/app/logbook/olog/ui/src/main/java/org/phoebus/logbook/olog/ui/Messages.java index 60d2bd92cc..b6a741f161 100644 --- a/app/logbook/olog/ui/src/main/java/org/phoebus/logbook/olog/ui/Messages.java +++ b/app/logbook/olog/ui/src/main/java/org/phoebus/logbook/olog/ui/Messages.java @@ -55,6 +55,7 @@ public class Messages PreviewOpenErrorTitle, ReplyToLogEntry, RequestTooLarge, + SearchFailed, SelectFile, SelectFolder, ShowHideDetails, diff --git a/app/logbook/olog/ui/src/main/resources/org/phoebus/logbook/olog/ui/messages.properties b/app/logbook/olog/ui/src/main/resources/org/phoebus/logbook/olog/ui/messages.properties index 00cbf5904f..4fbc670c3b 100644 --- a/app/logbook/olog/ui/src/main/resources/org/phoebus/logbook/olog/ui/messages.properties +++ b/app/logbook/olog/ui/src/main/resources/org/phoebus/logbook/olog/ui/messages.properties @@ -94,6 +94,7 @@ ScalingFactor=Scaling Factor SearchButtonText=Search: Search=Search available: SearchAvailableItems=Search the list of available items. +SearchFailed=Search Failed SearchToolTip=Edit and press Enter to search Selected=Selected SelectFolder=Select Folder