Skip to content

Commit 42d675e

Browse files
committed
HTML/URI encode path/content where possible
1 parent ed35314 commit 42d675e

File tree

6 files changed

+47
-45
lines changed

6 files changed

+47
-45
lines changed

opengrok-indexer/src/main/java/org/opengrok/indexer/web/Util.java

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,7 @@ private static boolean needsHtmlize(CharSequence q, boolean pre) {
350350
* Convenience method for {@code breadcrumbPath(urlPrefix, path, PATH_SEPARATOR)}.
351351
*
352352
* @param urlPrefix prefix to add to each url
353-
* @param path path to crack
353+
* @param path the full path from which the breadcrumb path is built
354354
* @return HTML markup for the breadcrumb or the path itself.
355355
*
356356
* @see #breadcrumbPath(String, String, char)
@@ -364,7 +364,7 @@ public static String breadcrumbPath(String urlPrefix, String path) {
364364
* {@code breadcrumbPath(urlPrefix, path, sep, "", false)}.
365365
*
366366
* @param urlPrefix prefix to add to each url
367-
* @param path path to crack
367+
* @param path the full path from which the breadcrumb path is built
368368
* @param sep separator to use to crack the given path
369369
*
370370
* @return HTML markup fro the breadcrumb or the path itself.
@@ -379,13 +379,13 @@ public static String breadcrumbPath(String urlPrefix, String path, char sep) {
379379
* {@code breadcrumbPath(urlPrefix, path, sep, "", false, path.endsWith(sep)}.
380380
*
381381
* @param urlPrefix prefix to add to each url
382-
* @param path path to crack
382+
* @param path the full path from which the breadcrumb path is built
383383
* @param sep separator to use to crack the given path
384384
* @param urlPostfix suffix to add to each url
385385
* @param compact if {@code true} the given path gets transformed into its
386-
* canonical form (.i.e. all '.' and '..' and double separators removed, but
386+
* canonical form (.i.e. all <code>'.'</code> and <code>'..'</code> and double separators removed, but
387387
* not always resolves to an absolute path) before processing starts.
388-
* @return HTML markup fro the breadcrumb or the path itself.
388+
* @return HTML markup for the breadcrumb or the path itself
389389
* @see #breadcrumbPath(String, String, char, String, boolean, boolean)
390390
* @see #getCanonicalPath(String, char)
391391
*/
@@ -408,12 +408,10 @@ public static String breadcrumbPath(String urlPrefix, String path,
408408
* neither whether the path [component] exists nor which type it is).
409409
*
410410
* @param urlPrefix what should be prepended to the constructed URL
411-
* @param path the full path from which the breadcrumb path is built.
412-
* @param sep the character that separates the path components in
413-
* <var>path</var>
411+
* @param path the full path from which the breadcrumb path is built
412+
* @param sep the character that separates the path components in <var>path</var>
414413
* @param urlPostfix what should be appended to the constructed URL
415-
* @param compact if {@code true}, a canonical path gets constructed before
416-
* processing.
414+
* @param compact if {@code true}, a canonical path gets constructed before processing.
417415
* @param isDir if {@code true} a "/" gets append to the last path
418416
* component's link and <var>sep</var> to its name
419417
* @return <var>path</var> if it resolves to an empty or "/" or {@code null}
@@ -431,8 +429,7 @@ public static String breadcrumbPath(String urlPrefix, String path,
431429
String prefix = urlPrefix == null ? "" : urlPrefix;
432430
String postfix = urlPostfix == null ? "" : urlPostfix;
433431
StringBuilder pwd = new StringBuilder(path.length() + pnames.length);
434-
StringBuilder markup
435-
= new StringBuilder((pnames.length + 3 >> 1) * path.length()
432+
StringBuilder markup = new StringBuilder((pnames.length + 3 >> 1) * path.length()
436433
+ pnames.length
437434
* (17 + prefix.length() + postfix.length()));
438435
int k = path.indexOf(pnames[0]);
@@ -445,9 +442,13 @@ public static String breadcrumbPath(String urlPrefix, String path,
445442
if (isDir || i < pnames.length - 1) {
446443
pwd.append(PATH_SEPARATOR);
447444
}
448-
markup.append(ANCHOR_LINK_START).append(prefix).append(pwd)
449-
.append(postfix).append(CLOSE_QUOTED_TAG).append(pnames[i])
450-
.append(ANCHOR_END);
445+
markup.append(ANCHOR_LINK_START).
446+
append(prefix).
447+
append(pwd).
448+
append(postfix).
449+
append(CLOSE_QUOTED_TAG).
450+
append(Util.htmlize(pnames[i])).
451+
append(ANCHOR_END);
451452
if (isDir || i < pnames.length - 1) {
452453
markup.append(sep);
453454
}
@@ -520,8 +521,7 @@ public static String getEmail(String author) {
520521

521522
/**
522523
* Remove all empty and {@code null} string elements from the given
523-
* <var>names</var> and optionally all redundant information like "." and
524-
* "..".
524+
* <var>names</var> and optionally all redundant information like <code>"."</code> and <code>".."</code>.
525525
*
526526
* @param names names to check
527527
* @param canonical if {@code true}, remove redundant elements as well.

opengrok-indexer/src/test/java/org/opengrok/indexer/web/UtilTest.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
*/
1919

2020
/*
21-
* Copyright (c) 2007, 2022, Oracle and/or its affiliates. All rights reserved.
21+
* Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved.
2222
* Portions Copyright (c) 2017, 2019, Chris Fraire <[email protected]>.
2323
*/
2424
package org.opengrok.indexer.web;
@@ -112,8 +112,7 @@ void breadcrumbPath() {
112112
// parent directories have a trailing slash in href
113113
assertEquals("<a href=\"/r/a/\">a</a>/<a href=\"/r/a/b\">b</a>",
114114
Util.breadcrumbPath("/r/", "a/b"));
115-
// if basename is a dir (ends with file seperator), href link also
116-
// ends with a '/'
115+
// if basename is a dir (ends with file separator), href link also ends with a '/'
117116
assertEquals("<a href=\"/r/a/\">a</a>/<a href=\"/r/a/b/\">b</a>/",
118117
Util.breadcrumbPath("/r/", "a/b/"));
119118
// should work the same way with a '.' as file separator
@@ -129,11 +128,15 @@ void breadcrumbPath() {
129128
// Prefix gets just prefixed as is and not mangled wrt. path -> "//"
130129
assertEquals("/<a href=\"/root//xx&project=y\">xx</a>",
131130
Util.breadcrumbPath("/root/", "../xx", '/', "&project=y", true));
132-
// relative pathes are resolved wrt. / , so path resolves to /a/c/d
131+
// relative paths are resolved wrt. / , so path resolves to /a/c/d
133132
assertEquals("/<a href=\"/r//a/\">a</a>/"
134133
+ "<a href=\"/r//a/c/\">c</a>/"
135134
+ "<a href=\"/r//a/c/d\">d</a>",
136135
Util.breadcrumbPath("/r/", "../a/b/../c//d", '/', "", true));
136+
// path components should be URI encoded and htmlized
137+
assertEquals("<a href=\"/root/foo/&project=y\">foo</a>/"
138+
+ "<a href=\"/root/foo/bar%3E&project=y\">bar&gt;</a>",
139+
Util.breadcrumbPath("/root/", "foo/bar>", '/', "&project=y", true));
137140
}
138141

139142
@Test

opengrok-web/src/main/webapp/history.jsp

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ information: Portions Copyright [yyyy] [name of copyright owner]
1818
1919
CDDL HEADER END
2020
21-
Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved.
21+
Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved.
2222
Portions Copyright 2011 Jens Elkner.
2323
Portions Copyright (c) 2018-2020, Chris Fraire <[email protected]>.
2424
--%>
@@ -59,7 +59,7 @@ org.opengrok.indexer.web.Util"
5959
6060
String path = cfg.getPath();
6161
62-
if (path.length() > 0) {
62+
if (!path.isEmpty()) {
6363
String primePath = path;
6464
Project project = cfg.getProject();
6565
if (project != null) {
@@ -148,7 +148,7 @@ include file="/httpheader.jspf"
148148
request.setAttribute("history.jsp-slider", Util.createSlider(startIndex, max, totalHits, request));
149149
%>
150150
<div id="Masthead">History log of
151-
<%= Util.breadcrumbPath(context + Prefix.XREF_P, path,'/',"",true,cfg.isDir()) %>
151+
<%= Util.breadcrumbPath(context + Prefix.XREF_P, path, '/', "", true, cfg.isDir()) %>
152152
(Results <span class="bold"> <%= totalHits != 0 ? startIndex + 1 : 0 %><%= startIndex + thisPageIndex
153153
%></span> of <span class="bold"><%= totalHits %></span>)
154154
</div>
@@ -231,11 +231,11 @@ document.domReady.push(function() {domReadyHistory();});
231231
<th><input type="submit" value=" Compare "/>
232232
<% if (hist.getHistoryEntries().size() > revision1Index && revision1Index >= 0) { %>
233233
<input type="hidden" id="input_r1" name="<%= QueryParameters.REVISION_1_PARAM %>"
234-
value="<%= path + '@' + hist.getHistoryEntries().get(revision1Index).getRevision() %>"/>
234+
value="<%= Util.uriEncodePath(path) + '@' + hist.getHistoryEntries().get(revision1Index).getRevision() %>"/>
235235
<% } %>
236236
<% if (hist.getHistoryEntries().size() > revision2Index && revision2Index >= 0) { %>
237237
<input type="hidden" id="input_r2" name="<%= QueryParameters.REVISION_2_PARAM %>"
238-
value="<%= path + '@' + hist.getHistoryEntries().get(revision2Index).getRevision() %>"/>
238+
value="<%= Util.uriEncodePath(path) + '@' + hist.getHistoryEntries().get(revision2Index).getRevision() %>"/>
239239
<% } %>
240240
</th><%
241241
}
@@ -259,11 +259,11 @@ document.domReady.push(function() {domReadyHistory();});
259259
int count=0;
260260
for (HistoryEntry entry : hist.getHistoryEntries(maxItems, startIndex)) {
261261
String dispRev = entry.getDisplayRevision();
262-
if (dispRev == null || dispRev.length() == 0) {
262+
if (dispRev == null || dispRev.isEmpty()) {
263263
dispRev = "";
264264
}
265265
String rev = entry.getRevision();
266-
if (rev == null || rev.length() == 0) {
266+
if (rev == null || rev.isEmpty()) {
267267
rev = "";
268268
}
269269
String tags = hist.getTags().get(rev);
@@ -323,7 +323,7 @@ document.domReady.push(function() {domReadyHistory();});
323323
data-revision-1="<%= revision1Index %>"
324324
data-revision-2="<%= (startIndex + count) %>"
325325
data-diff-revision="<%= QueryParameters.REVISION_2_PARAM %>"
326-
data-revision-path="<%= path + '@' + hist.getHistoryEntries().get(startIndex + count).getRevision() %>"
326+
data-revision-path="<%= Util.htmlize(path) + '@' + hist.getHistoryEntries().get(startIndex + count).getRevision() %>"
327327
<%
328328
if (count + startIndex < revision2Index || (count + startIndex > revision2Index && count + startIndex <= revision1Index - 1)) {
329329
// revision2 enabled
@@ -354,7 +354,7 @@ document.domReady.push(function() {domReadyHistory();});
354354
String author = entry.getAuthor();
355355
if (author == null) {
356356
%>(no author)<%
357-
} else if (userPage != null && userPage.length() > 0) {
357+
} else if (userPage != null && !userPage.isEmpty()) {
358358
String alink = Util.getEmail(author);
359359
%><a href="<%= userPage + Util.htmlize(alink) + userPageSuffix
360360
%>"><%= Util.htmlize(author)%></a><%
@@ -367,10 +367,10 @@ document.domReady.push(function() {domReadyHistory();});
367367
int summaryLength = Math.max(10, cfg.getRevisionMessageCollapseThreshold());
368368
String cout = Util.htmlize(entry.getMessage());
369369
370-
if (bugPage != null && bugPage.length() > 0 && bugPattern != null) {
370+
if (bugPage != null && !bugPage.isEmpty() && bugPattern != null) {
371371
cout = Util.linkifyPattern(cout, bugPattern, "$1", Util.completeUrl(bugPage + "$1", request));
372372
}
373-
if (reviewPage != null && reviewPage.length() > 0 && reviewPattern != null) {
373+
if (reviewPage != null && !reviewPage.isEmpty() && reviewPattern != null) {
374374
cout = Util.linkifyPattern(cout, reviewPattern, "$1", Util.completeUrl(reviewPage + "$1", request));
375375
}
376376
@@ -380,10 +380,10 @@ document.domReady.push(function() {domReadyHistory();});
380380
showSummary = true;
381381
coutSummary = coutSummary.substring(0, summaryLength - 1);
382382
coutSummary = Util.htmlize(coutSummary);
383-
if (bugPage != null && bugPage.length() > 0 && bugPattern != null) {
383+
if (bugPage != null && !bugPage.isEmpty() && bugPattern != null) {
384384
coutSummary = Util.linkifyPattern(coutSummary, bugPattern, "$1", Util.completeUrl(bugPage + "$1", request));
385385
}
386-
if (reviewPage != null && reviewPage.length() > 0 && reviewPattern != null) {
386+
if (reviewPage != null && !reviewPage.isEmpty() && reviewPattern != null) {
387387
coutSummary = Util.linkifyPattern(coutSummary, reviewPattern, "$1", Util.completeUrl(reviewPage + "$1", request));
388388
}
389389
}

opengrok-web/src/main/webapp/httpheader.jspf

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ information: Portions Copyright [yyyy] [name of copyright owner]
1818

1919
CDDL HEADER END
2020

21-
Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved.
21+
Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved.
2222
Portions Copyright 2011 Jens Elkner.
2323
Portions Copyright (c) 2017-2018, 2020, Chris Fraire <[email protected]>.
2424
Portions Copyright (c) 2020, Aleksandr Kirillov <[email protected]>.
@@ -38,6 +38,7 @@ to set the title of the document before the include directive for this fragment:
3838
org.opengrok.indexer.Info,
3939
org.opengrok.web.PageConfig,
4040
org.opengrok.indexer.web.Prefix,
41+
org.opengrok.indexer.web.Util,
4142
org.opengrok.web.Scripts"
4243
%><%
4344
/* ---------------------- httpheader.jsp start --------------------- */
@@ -92,8 +93,8 @@ org.opengrok.web.Scripts"
9293

9394
if (cfg.getPrefix().equals(Prefix.HIST_L)) {
9495
out.write("<link rel=\"alternate\" type=\"application/rss+xml\" " +
95-
"title=\"RSS feed for " + cfg.getPath() + "\" " +
96-
"href=\"" + ctxPath + Prefix.RSS_P + cfg.getPath() + "\" />");
96+
"title=\"RSS feed for " + Util.htmlize(cfg.getPath()) + "\" " +
97+
"href=\"" + ctxPath + Prefix.RSS_P + Util.uriEncodePath(cfg.getPath()) + "\" />");
9798
}
9899
%>
99100
<link rel="search" href="<%=ctxPath%>/opensearch"

opengrok-web/src/main/webapp/mast.jsp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ org.opengrok.indexer.web.Util"%>
6666
}
6767
6868
// set the default page title
69-
String path = cfg.getPath();
7069
cfg.setTitle(cfg.getPathTitle());
7170
}
7271
%>
@@ -94,19 +93,18 @@ include file="/httpheader.jspf"
9493
9594
String messages = "";
9695
if (cfg.getProject() != null) {
97-
messages = MessagesUtils.messagesToJson(cfg.getProject(),
98-
MessagesContainer.MESSAGES_MAIN_PAGE_TAG);
96+
messages = MessagesUtils.messagesToJson(cfg.getProject(), MessagesContainer.MESSAGES_MAIN_PAGE_TAG);
9997
}
10098
%>
10199
<a href="<%= context + Prefix.XREF_P %>/">xref</a>:
102-
<%= Util.breadcrumbPath(context + Prefix.XREF_P, path,'/',"",true,cfg.isDir()) %>
103-
<% if (rev.length() != 0) { %>
100+
<%= Util.breadcrumbPath(context + Prefix.XREF_P, path, '/', "", true, cfg.isDir()) %>
101+
<% if (!rev.isEmpty()) { %>
104102
(revision <%= Util.htmlize(rev) %>)
105103
<% } %>
106104
<span id="dtag">
107105
<%
108106
String dtag = cfg.getDefineTagsIndex();
109-
if (dtag.length() > 0) {
107+
if (!dtag.isEmpty()) {
110108
%> (<%= dtag %>)<%
111109
}
112110
%></span>

opengrok-web/src/main/webapp/more.jsp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ information: Portions Copyright [yyyy] [name of copyright owner]
1818
1919
CDDL HEADER END
2020
21-
Copyright (c) 2010, 2022, Oracle and/or its affiliates. All rights reserved.
21+
Copyright (c) 2010, 2025, Oracle and/or its affiliates. All rights reserved.
2222
Portions Copyright 2011 Jens Elkner.
2323
Portions Copyright (c) 2018, 2020, Chris Fraire <[email protected]>.
2424
@@ -99,7 +99,7 @@ org.opengrok.indexer.web.SearchHelper"
9999
*/
100100
Context sourceContext = new Context(tquery, qbuilder);
101101
sourceContext.toggleAlt();
102-
// SRCROOT is read with UTF-8 as a default.
102+
// Files under source root are read with UTF-8 as a default.
103103
try (Reader r = IOUtils.createBOMStrippedReader(
104104
new FileInputStream(resourceFile),
105105
StandardCharsets.UTF_8.name())) {

0 commit comments

Comments
 (0)