This is an automated email from the ASF dual-hosted git repository. papegaaij pushed a commit to branch wicket-10.x in repository https://gitbox.apache.org/repos/asf/wicket.git
commit b394325700368ff212ef3a46621a05fe1bd35c2e Author: Emond Papegaaij <[email protected]> AuthorDate: Thu Aug 20 12:32:01 2026 +0200 Say in the javadoc which methods have their value written to the markup as is Escaping in the render path is a convention among callers rather than something the path itself guarantees. replaceComponentTagBody and Response#write write what they are handed, and Label is safe only because it hands them getDefaultModelObjectAsString(). Where an overridable method's value reaches one of those writes, an implementation has to know that, and until now it had to work it out by reading the caller. Twenty-six methods now say so and name the escaping to apply: the body of an option points at escapeOptionHtml, everything else at Strings#escapeMarkup. The wording follows what the method does with the value. A getter returns it, a setter is handed it, appendOptionHtml and setOptionAttributes append it to the option buffer, the renderer methods write it to a Response, and escapeHtml decides whether the output of a template is escaped at all. Where the framework calls the method and the default implementation escapes correctly, the note says so and addresses the override instead, since relying on the default is not what puts anything at risk. That covers the three hooks of AbstractChoice: renderValue escapes the body of the option, setOptionAttributes escapes the id it writes, and getDefaultChoice returns no choice at all unless a subclass builds one. Methods whose caller escapes for them are left alone, since telling an implementation to escape there would have it encode twice: the display value methods of AbstractSingleSelectChoice, defaultNullLabel of the editable labels, the additional attributes of RadioChoice and CheckBoxMultipleChoice, and those of the palette. Include is left alone as well. What its method returns is the least of what that component does with the value it is given, and it is being looked at on its own. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> --- .../wicket/markup/html/form/AbstractChoice.java | 28 +++++++++++++++++ .../markup/html/form/CheckBoxMultipleChoice.java | 36 ++++++++++++++++++++++ .../wicket/markup/html/form/RadioChoice.java | 36 ++++++++++++++++++++++ .../html/navigation/paging/PagingNavigation.java | 12 ++++++++ .../wicket/markup/transformer/ITransformer.java | 6 ++++ .../autocomplete/AbstractAutoCompleteRenderer.java | 6 ++++ .../html/autocomplete/IAutoCompleteRenderer.java | 18 +++++++++++ .../extensions/breadcrumb/BreadCrumbBar.java | 6 ++++ .../wicket/velocity/VelocityContributor.java | 6 ++++ .../wicket/velocity/markup/html/VelocityPanel.java | 6 ++++ 10 files changed, 160 insertions(+) diff --git a/wicket-core/src/main/java/org/apache/wicket/markup/html/form/AbstractChoice.java b/wicket-core/src/main/java/org/apache/wicket/markup/html/form/AbstractChoice.java index afab72549e..a3b5e85898 100644 --- a/wicket-core/src/main/java/org/apache/wicket/markup/html/form/AbstractChoice.java +++ b/wicket-core/src/main/java/org/apache/wicket/markup/html/form/AbstractChoice.java @@ -386,6 +386,14 @@ public abstract class AbstractChoice<T, E> extends FormComponent<T> /** * Get a default choice to be rendered additionally to the choices available in the model. * + * <p> + * <b>The return value of an override is written to the markup as is, without escaping.</b> + * This implementation returns no choice at all, and the override in + * {@link AbstractSingleSelectChoice} escapes the body of the option it builds. An override + * that builds an option itself must escape the option body with + * {@link Strings#escapeMarkup(CharSequence)}. + * </p> + * * @param selectedValue * The currently selected value * @return Any default choice, such as "Choose One", depending on the subclass @@ -456,6 +464,13 @@ public abstract class AbstractChoice<T, E> extends FormComponent<T> /** * Generates and appends html for a single choice into the provided buffer * + * <p> + * <b>Whatever an override appends reaches the markup as is, without escaping.</b> This + * implementation escapes the body of the option it appends, according to + * {@link #getEscapeModelStrings()}. An override that assembles an option itself must do + * the same for whatever it puts there, with {@link Strings#escapeMarkup(CharSequence)}. + * </p> + * * @param buffer * Appending string buffer that will have the generated html appended * @param choice @@ -513,6 +528,13 @@ public abstract class AbstractChoice<T, E> extends FormComponent<T> /** * Sets the attributes of a single choice into the provided buffer. * + * <p> + * <b>Whatever an override appends reaches the markup as is, without escaping.</b> This + * implementation escapes the value of the id attribute it writes. An override that adds + * attributes of its own must escape their values with + * {@link Strings#escapeMarkup(CharSequence)}. + * </p> + * * @param buffer * Appending string buffer that will have the generated html appended * @param choice @@ -542,6 +564,12 @@ public abstract class AbstractChoice<T, E> extends FormComponent<T> /** * Method to override if you want special escaping of the options html. * + * <p> + * <b>The return value is written to the body of the option as is, without escaping.</b> An + * override that returns the display value without escaping it puts user input and other + * dynamic content into the page as markup. + * </p> + * * @param displayValue * @return The escaped display value */ diff --git a/wicket-core/src/main/java/org/apache/wicket/markup/html/form/CheckBoxMultipleChoice.java b/wicket-core/src/main/java/org/apache/wicket/markup/html/form/CheckBoxMultipleChoice.java index 4ba0fad523..840a7f69f6 100644 --- a/wicket-core/src/main/java/org/apache/wicket/markup/html/form/CheckBoxMultipleChoice.java +++ b/wicket-core/src/main/java/org/apache/wicket/markup/html/form/CheckBoxMultipleChoice.java @@ -232,6 +232,12 @@ public class CheckBoxMultipleChoice<T> extends ListMultipleChoice<T> } /** + * <p> + * <b>The return value is written to the markup as is, without escaping.</b> Any part of + * it that comes from user input or other dynamic content must be escaped with + * {@link Strings#escapeMarkup(CharSequence)}. + * </p> + * * @return Prefix to use before choice */ public String getPrefix() @@ -240,6 +246,12 @@ public class CheckBoxMultipleChoice<T> extends ListMultipleChoice<T> } /** + * <p> + * <b>The return value is written to the markup as is, without escaping.</b> Any part of + * it that comes from user input or other dynamic content must be escaped with + * {@link Strings#escapeMarkup(CharSequence)}. + * </p> + * * @param index * index of the choice * @param choice @@ -253,6 +265,12 @@ public class CheckBoxMultipleChoice<T> extends ListMultipleChoice<T> } /** + * <p> + * <b>The return value is written to the markup as is, without escaping.</b> Any part of + * it that comes from user input or other dynamic content must be escaped with + * {@link Strings#escapeMarkup(CharSequence)}. + * </p> + * * @param index * index of the choice * @param choice @@ -266,6 +284,12 @@ public class CheckBoxMultipleChoice<T> extends ListMultipleChoice<T> } /** + * <p> + * <b>The value passed here is written to the markup as is, without escaping.</b> Any + * part of it that comes from user input or other dynamic content must be escaped with + * {@link Strings#escapeMarkup(CharSequence)}. + * </p> + * * @param prefix * Prefix to use before choice * @return this @@ -284,6 +308,12 @@ public class CheckBoxMultipleChoice<T> extends ListMultipleChoice<T> } /** + * <p> + * <b>The return value is written to the markup as is, without escaping.</b> Any part of + * it that comes from user input or other dynamic content must be escaped with + * {@link Strings#escapeMarkup(CharSequence)}. + * </p> + * * @return Separator to use between radio options */ public String getSuffix() @@ -292,6 +322,12 @@ public class CheckBoxMultipleChoice<T> extends ListMultipleChoice<T> } /** + * <p> + * <b>The value passed here is written to the markup as is, without escaping.</b> Any + * part of it that comes from user input or other dynamic content must be escaped with + * {@link Strings#escapeMarkup(CharSequence)}. + * </p> + * * @param suffix * Separator to use between radio options * @return this diff --git a/wicket-core/src/main/java/org/apache/wicket/markup/html/form/RadioChoice.java b/wicket-core/src/main/java/org/apache/wicket/markup/html/form/RadioChoice.java index 60b6b27c67..079244ddaa 100644 --- a/wicket-core/src/main/java/org/apache/wicket/markup/html/form/RadioChoice.java +++ b/wicket-core/src/main/java/org/apache/wicket/markup/html/form/RadioChoice.java @@ -237,6 +237,12 @@ public class RadioChoice<T> extends AbstractSingleSelectChoice<T> } /** + * <p> + * <b>The return value is written to the markup as is, without escaping.</b> Any part of + * it that comes from user input or other dynamic content must be escaped with + * {@link Strings#escapeMarkup(CharSequence)}. + * </p> + * * @return Prefix to use before choice */ public String getPrefix() @@ -245,6 +251,12 @@ public class RadioChoice<T> extends AbstractSingleSelectChoice<T> } /** + * <p> + * <b>The return value is written to the markup as is, without escaping.</b> Any part of + * it that comes from user input or other dynamic content must be escaped with + * {@link Strings#escapeMarkup(CharSequence)}. + * </p> + * * @param index * index of the choice * @param choice @@ -258,6 +270,12 @@ public class RadioChoice<T> extends AbstractSingleSelectChoice<T> } /** + * <p> + * <b>The return value is written to the markup as is, without escaping.</b> Any part of + * it that comes from user input or other dynamic content must be escaped with + * {@link Strings#escapeMarkup(CharSequence)}. + * </p> + * * @param index * index of the choice * @param choice @@ -271,6 +289,12 @@ public class RadioChoice<T> extends AbstractSingleSelectChoice<T> } /** + * <p> + * <b>The value passed here is written to the markup as is, without escaping.</b> Any + * part of it that comes from user input or other dynamic content must be escaped with + * {@link Strings#escapeMarkup(CharSequence)}. + * </p> + * * @param prefix * Prefix to use before choice * @return this @@ -284,6 +308,12 @@ public class RadioChoice<T> extends AbstractSingleSelectChoice<T> } /** + * <p> + * <b>The return value is written to the markup as is, without escaping.</b> Any part of + * it that comes from user input or other dynamic content must be escaped with + * {@link Strings#escapeMarkup(CharSequence)}. + * </p> + * * @return Separator to use between radio options */ public String getSuffix() @@ -292,6 +322,12 @@ public class RadioChoice<T> extends AbstractSingleSelectChoice<T> } /** + * <p> + * <b>The value passed here is written to the markup as is, without escaping.</b> Any + * part of it that comes from user input or other dynamic content must be escaped with + * {@link Strings#escapeMarkup(CharSequence)}. + * </p> + * * @param suffix * Separator to use between radio options * @return this diff --git a/wicket-core/src/main/java/org/apache/wicket/markup/html/navigation/paging/PagingNavigation.java b/wicket-core/src/main/java/org/apache/wicket/markup/html/navigation/paging/PagingNavigation.java index 5abd724ee7..3980d8e914 100644 --- a/wicket-core/src/main/java/org/apache/wicket/markup/html/navigation/paging/PagingNavigation.java +++ b/wicket-core/src/main/java/org/apache/wicket/markup/html/navigation/paging/PagingNavigation.java @@ -187,6 +187,12 @@ public class PagingNavigation extends Loop /** * Gets the seperator. * + * <p> + * <b>The return value is written to the markup as is, without escaping.</b> Any part of + * it that comes from user input or other dynamic content must be escaped with + * {@link org.apache.wicket.util.string.Strings#escapeMarkup(CharSequence) Strings#escapeMarkup(CharSequence)}. + * </p> + * * @return the seperator */ public String getSeparator() @@ -228,6 +234,12 @@ public class PagingNavigation extends Loop /** * Sets the seperator. Null meaning, no separator at all. * + * <p> + * <b>The value passed here is written to the markup as is, without escaping.</b> Any + * part of it that comes from user input or other dynamic content must be escaped with + * {@link org.apache.wicket.util.string.Strings#escapeMarkup(CharSequence) Strings#escapeMarkup(CharSequence)}. + * </p> + * * @param separator * the seperator */ diff --git a/wicket-core/src/main/java/org/apache/wicket/markup/transformer/ITransformer.java b/wicket-core/src/main/java/org/apache/wicket/markup/transformer/ITransformer.java index b883e83516..e03a449150 100644 --- a/wicket-core/src/main/java/org/apache/wicket/markup/transformer/ITransformer.java +++ b/wicket-core/src/main/java/org/apache/wicket/markup/transformer/ITransformer.java @@ -32,6 +32,12 @@ public interface ITransformer * Will be invoked after all child components have been processed to allow for transforming the * markup generated. * + * <p> + * <b>The return value is written to the markup as is, without escaping.</b> Any part of + * it that comes from user input or other dynamic content must be escaped with + * {@link org.apache.wicket.util.string.Strings#escapeMarkup(CharSequence) Strings#escapeMarkup(CharSequence)}. + * </p> + * * @param component * The associated Wicket component * @param output diff --git a/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/autocomplete/AbstractAutoCompleteRenderer.java b/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/autocomplete/AbstractAutoCompleteRenderer.java index 1c0d3d0a5a..94afe108fa 100644 --- a/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/autocomplete/AbstractAutoCompleteRenderer.java +++ b/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/autocomplete/AbstractAutoCompleteRenderer.java @@ -74,6 +74,12 @@ public abstract class AbstractAutoCompleteRenderer<T> implements IAutoCompleteRe * Render the visual portion of the assist. Usually the html representing the assist choice * object is written out to the response use {@link Response#write(CharSequence)} * + * <p> + * <b>Whatever is written to the response reaches the markup as is, without escaping.</b> + * Any part of it that comes from user input or other dynamic content must be escaped + * before it is written, with {@link Strings#escapeMarkup(CharSequence)}. + * </p> + * * @param object * current assist choice * @param response diff --git a/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/autocomplete/IAutoCompleteRenderer.java b/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/autocomplete/IAutoCompleteRenderer.java index 3958a0a3fd..0e76791e5f 100644 --- a/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/autocomplete/IAutoCompleteRenderer.java +++ b/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/markup/html/autocomplete/IAutoCompleteRenderer.java @@ -66,6 +66,12 @@ public interface IAutoCompleteRenderer<T> extends IDetachable * Render the html fragment for the given completion object. Usually the html is written out by * calling {@link Response#write(CharSequence)}. * + * <p> + * <b>Whatever is written to the response reaches the markup as is, without escaping.</b> + * Any part of it that comes from user input or other dynamic content must be escaped + * before it is written, with {@link org.apache.wicket.util.string.Strings#escapeMarkup(CharSequence) Strings#escapeMarkup(CharSequence)}. + * </p> + * * @param object * completion choice object * @param response @@ -80,6 +86,12 @@ public interface IAutoCompleteRenderer<T> extends IDetachable * Render the html header fragment for the completion. Usually the html is written out by * calling {@link Response#write(CharSequence)}. * + * <p> + * <b>Whatever is written to the response reaches the markup as is, without escaping.</b> + * Any part of it that comes from user input or other dynamic content must be escaped + * before it is written, with {@link org.apache.wicket.util.string.Strings#escapeMarkup(CharSequence) Strings#escapeMarkup(CharSequence)}. + * </p> + * * @param response */ void renderHeader(Response response); @@ -88,6 +100,12 @@ public interface IAutoCompleteRenderer<T> extends IDetachable * Render the html footer fragment for the completion. Usually the html is written out by * calling {@link Response#write(CharSequence)}. * + * <p> + * <b>Whatever is written to the response reaches the markup as is, without escaping.</b> + * Any part of it that comes from user input or other dynamic content must be escaped + * before it is written, with {@link org.apache.wicket.util.string.Strings#escapeMarkup(CharSequence) Strings#escapeMarkup(CharSequence)}. + * </p> + * * @param response * @param count * The number of choices rendered diff --git a/wicket-extensions/src/main/java/org/apache/wicket/extensions/breadcrumb/BreadCrumbBar.java b/wicket-extensions/src/main/java/org/apache/wicket/extensions/breadcrumb/BreadCrumbBar.java index ec85ec0e20..e48f1aa560 100644 --- a/wicket-extensions/src/main/java/org/apache/wicket/extensions/breadcrumb/BreadCrumbBar.java +++ b/wicket-extensions/src/main/java/org/apache/wicket/extensions/breadcrumb/BreadCrumbBar.java @@ -245,6 +245,12 @@ public class BreadCrumbBar extends Panel implements IBreadCrumbModel } /** + * <p> + * <b>The return value is written to the markup as is, without escaping.</b> Any part of + * it that comes from user input or other dynamic content must be escaped with + * {@link org.apache.wicket.util.string.Strings#escapeMarkup(CharSequence) Strings#escapeMarkup(CharSequence)}. + * </p> + * * @return markup used as a separator between breadcrumbs. By default <code>/</code> is used, * but <code>>></code> is also a popular choice. */ diff --git a/wicket-velocity/src/main/java/org/apache/wicket/velocity/VelocityContributor.java b/wicket-velocity/src/main/java/org/apache/wicket/velocity/VelocityContributor.java index 64bf10c997..81d78fcd98 100644 --- a/wicket-velocity/src/main/java/org/apache/wicket/velocity/VelocityContributor.java +++ b/wicket-velocity/src/main/java/org/apache/wicket/velocity/VelocityContributor.java @@ -104,6 +104,12 @@ public class VelocityContributor extends Behavior } /** + * <p> + * <b>While this returns false, the output of the template is written to the markup as + * is, without escaping.</b> A template that interpolates user input or other dynamic + * content then puts it in the page unescaped. + * </p> + * * @return whether to escape HTML characters. The default value is false */ protected boolean escapeHtml() diff --git a/wicket-velocity/src/main/java/org/apache/wicket/velocity/markup/html/VelocityPanel.java b/wicket-velocity/src/main/java/org/apache/wicket/velocity/markup/html/VelocityPanel.java index 4ab790f3f2..986b6ef86a 100644 --- a/wicket-velocity/src/main/java/org/apache/wicket/velocity/markup/html/VelocityPanel.java +++ b/wicket-velocity/src/main/java/org/apache/wicket/velocity/markup/html/VelocityPanel.java @@ -186,6 +186,12 @@ public abstract class VelocityPanel extends Panel /** * Gets whether to escape HTML characters. * + * <p> + * <b>While this returns false, the output of the template is written to the markup as + * is, without escaping.</b> A template that interpolates user input or other dynamic + * content then puts it in the page unescaped. + * </p> + * * @return whether to escape HTML characters. The default value is false. */ protected boolean escapeHtml()
