Mon, 22 Sep 2025 20:00:59 +0200
fix missing HTML escape in RSS feed description and accidental diff in titles
fixes #724 fixes #729
--- a/src/main/kotlin/de/uapcore/lightpit/Constants.kt Mon Sep 15 20:13:22 2025 +0200 +++ b/src/main/kotlin/de/uapcore/lightpit/Constants.kt Mon Sep 22 20:00:59 2025 +0200 @@ -29,7 +29,7 @@ /** * A data in yyyy-mm-dd format to identify the release. */ - const val VERSION_DATE = "2025-09-14" + const val VERSION_DATE = "2025-09-22" /** * The path where the JSP files reside.
--- a/src/main/kotlin/de/uapcore/lightpit/servlet/FeedServlet.kt Mon Sep 15 20:13:22 2025 +0200 +++ b/src/main/kotlin/de/uapcore/lightpit/servlet/FeedServlet.kt Mon Sep 22 20:00:59 2025 +0200 @@ -54,11 +54,14 @@ .mergeOriginalRevised(true) .inlineDiffByWord(true) .reportLinesUnchanged(true) + .lineNormalizer { it } // do not normalize - we escape the HTML ourselves .oldTag { start -> if (start) "<strike style=\"color:red\">" else "</strike>" } .newTag { start -> if (start) "<i style=\"color: green\">" else "</i>" } .build() ) + fun escapeHtml(s: String): String = s.replace("&", "&").replace("<", "<").replace(">", ">") + fun calculateDiff(earlier: String, later: String): String = diffGenerator.generateDiffRows( earlier.replace("\r", "").split("\n"), @@ -76,40 +79,50 @@ CommentDiff( issueid = data.issueid, id = data.commentid, - project = data.project, - currentSubject = data.subject, - comment = data.comment.replace("\r", "") + project = escapeHtml(data.project), + currentSubject = escapeHtml(data.subject), + comment = escapeHtml(data.comment.replace("\r", "")) ) private fun diffContent(cur: IssueCommentHistoryEntry, next: IssueCommentHistoryEntry) = CommentDiff( issueid = cur.issueid, id = cur.commentid, - project = cur.project, - currentSubject = cur.subject, - comment = calculateDiff(next.comment, cur.comment) + project = escapeHtml(cur.project), + currentSubject = escapeHtml(cur.subject), + comment = calculateDiff(escapeHtml(next.comment), escapeHtml(cur.comment)) ) - private fun fullContent(http: HttpRequest, issue: IssueHistoryEntry) = IssueDiff( - id = issue.issueid, - project = issue.project, - component = issue.component, - status = http.i18n("issue.status."+issue.status.name), - category = http.i18n("issue.category."+issue.category.name), - subject = issue.subject, - description = issue.description, - assignee = issue.assignee, - eta = issue.eta?.let { SimpleDateFormat("dd.MM.yyyy").format(it) } ?: "", - affected = issue.affected, - resolved = issue.resolved - ) + private fun fullContent(http: HttpRequest, issue: IssueHistoryEntry): IssueDiff { + val status = http.i18n("issue.status."+issue.status.name) + val category = http.i18n("issue.category."+issue.category.name) + val subject = escapeHtml(issue.subject) + return IssueDiff( + id = issue.issueid, + project = escapeHtml(issue.project), + currentSubject = subject, + currentCategory = category, + component = escapeHtml(issue.component), + status = status, + category = category, + subject = escapeHtml(issue.subject), + description = escapeHtml(issue.description), + assignee = escapeHtml(issue.assignee), + eta = issue.eta?.let { SimpleDateFormat("dd.MM.yyyy").format(it) } ?: "", + affected = escapeHtml(issue.affected), + resolved = escapeHtml(issue.resolved) + ) + } private fun diffContent(http: HttpRequest, cur: IssueHistoryEntry, next: IssueHistoryEntry): IssueDiff { val earlier = fullContent(http, next) val later = fullContent(http, cur) + // no need to escape HTML again, because fullContent already did it return IssueDiff( id = later.id, project = later.project, + currentSubject = later.subject, + currentCategory = later.category, subject = calculateDiff(earlier.subject, later.subject), component = calculateDiff(earlier.component, later.component), status = calculateDiff(earlier.status, later.status),
--- a/src/main/kotlin/de/uapcore/lightpit/viewmodel/Feeds.kt Mon Sep 15 20:13:22 2025 +0200 +++ b/src/main/kotlin/de/uapcore/lightpit/viewmodel/Feeds.kt Mon Sep 22 20:00:59 2025 +0200 @@ -34,19 +34,18 @@ class IssueDiff( val id: Int, val project: String, - var component: String, - var status: String, - var category: String, - var subject: String, - var description: String, - var assignee: String, - var eta: String, - var affected: String, - var resolved: String, -) { - var currentCategory: String = category - val currentSubject: String = subject -} + val currentSubject: String, + val currentCategory: String, + val component: String, + val status: String, + val category: String, + val subject: String, + val description: String, + val assignee: String, + val eta: String, + val affected: String, + val resolved: String, +) class CommentDiff( val issueid: Int,
--- a/src/main/webapp/WEB-INF/changelogs/changelog-de.jspf Mon Sep 15 20:13:22 2025 +0200 +++ b/src/main/webapp/WEB-INF/changelogs/changelog-de.jspf Mon Sep 22 20:00:59 2025 +0200 @@ -36,6 +36,7 @@ <li>Die Vorschläge in den Suchfeldern für Vorgänge sind nun absteigend nach Vorgangsnummer sortiert.</li> <li>Die Standardkategorie für neue Vorgänge in veröffentlichten Versionen ist nun "Fehler" anstelle von "Feature".</li> <li>Fehlerhafte Delta-Anzeige in RSS-Feeds behoben.</li> + <li>Ungefiltertes HTML aus Vorgangsbeschreibungen in RSS-Feeds behoben.</li> <li>Vorgänge können nicht länger mit sich selbst verlinkt werden.</li> <li>Fehler in der Deutschen Übersetzung behoben.</li> </ul>
--- a/src/main/webapp/WEB-INF/changelogs/changelog.jspf Mon Sep 15 20:13:22 2025 +0200 +++ b/src/main/webapp/WEB-INF/changelogs/changelog.jspf Mon Sep 22 20:00:59 2025 +0200 @@ -36,6 +36,7 @@ <li>Change that issues suggested by the search boxes are now sorted by ID in descending order.</li> <li>Change that the default category for new issues in released versions is Bug instead of Feature.</li> <li>Fix wrong diffs in RSS feed.</li> + <li>Fix unescaped HTML in RSS feed.</li> <li>Fix that issues could relate to themselves.</li> <li>Fix errors in the German translation.</li> </ul>