[ https://issues.apache.org/jira/browse/WICKET-1094?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12903856#action_12903856 ]
Hudson commented on WICKET-1094: -------------------------------- Integrated in Apache Wicket 1.4.x #129 (See [https://hudson.apache.org/hudson/job/Apache%20Wicket%201.4.x/129/]) > Values over-escaped by FormTester > --------------------------------- > > Key: WICKET-1094 > URL: https://issues.apache.org/jira/browse/WICKET-1094 > Project: Wicket > Issue Type: Bug > Affects Versions: 1.3.0-beta4 > Reporter: David Shepherdson > Assignee: Igor Vaynberg > Fix For: 1.4.11, 1.5-M2 > > > FormTester's constructor contains code that visits all components on the form > and calls setFormComponentValue(formComponent, formComponent.getValue()) (or > variations thereof), to store the component's value in the servlet request > parameters. However, by default, FormComponent's getValue() method uses > Strings.escapeMarkup(...) to encode any special characters, such as angle > brackets. This is fine in a 'real' environment, where a Web browser will be > responsible for displaying the escaped characters with their proper values, > and so the proper value will be the one that comes through when the form is > submitted; however, in the Wicket test environment, there isn't anything to > do that extra level of 'un-escaping', meaning there's a danger of the form > components being given escaped values when the form is submitted. > For example, we have a form that contains a text area, whose value contains a > URI enclosed in angle brackets, like so: > < http://test.com/ > > When we submit the form with a Web browser, the value set on the model is > exactly that string -- '< http://test.com/ >'. However, when we test our page > with FormTester, the FormTester constructor calls getValue() on the > component, which by default returns the escaped form: > < http://test.com/ > > When the form is submitted, this is the value set on the model, and so > comparisons to the original string fail. > (Extra spaces inserted into the strings above to make them display properly > in JIRA.) > However, if FormTester were to call setEscapeModelStrings(false) on the form > component before calling getValue() (and then restore the original escaping > setting afterwards), then the value that ends up being provided to the > component at the end would be the correct (unescaped) value, matching the > behaviour when using the page in a browser. > We have worked around this issue by overriding FormTester with a class that > performs a second traversal of the form component hierarchy after calling the > FormTester constructor, replacing the incorrectly escaped values with the > proper ones (changes marked with '// O-P'): > public OurFormTester(String path, Form workingForm, BaseWicketTester > wicketTester, boolean fillBlankString) { > super(path, workingForm, wicketTester, fillBlankString); > fixFormParameterValues(workingForm, fillBlankString); > } > > protected void fixFormParameterValues(Form workingForm, final boolean > fillBlankString) { > workingForm.visitFormComponents(new FormComponent.AbstractVisitor() > { > public void onFormComponent(final FormComponent formComponent) > { > // do nothing for invisible component > if (!formComponent.isVisibleInHierarchy()) > { > return; > } > // O-P Preserve old escaping value, then turn escaping off > // so that values aren't escaped unnecessarily. > boolean oldEscaping = formComponent.getEscapeModelStrings(); > formComponent.setEscapeModelStrings(false); > > // if component is text field and do not have exist value, > fill > // blank String if required > if (formComponent instanceof AbstractTextComponent) > { > if (Strings.isEmpty(formComponent.getValue())) > { > if (fillBlankString) > { > setFormComponentValue(formComponent, ""); > } > } > else > { > setFormComponentValue(formComponent, > formComponent.getValue()); > } > } > else if ( (formComponent instanceof DropDownChoice) || > (formComponent instanceof RadioChoice) || > (formComponent instanceof CheckBox)) > { > setFormComponentValue(formComponent, > formComponent.getValue()); > } > else if (formComponent instanceof ListMultipleChoice) > { > final String[] modelValues = > formComponent.getValue().split(FormComponent.VALUE_SEPARATOR); > for (int i = 0; i < modelValues.length; i++) > { > addFormComponentValue(formComponent, modelValues[i]); > } > } > else if (formComponent instanceof CheckGroup) > { > final Collection checkGroupValues = (Collection) > formComponent.getModelObject(); > formComponent.visitChildren(Check.class, new IVisitor() > { > public Object component(Component component) > { > > if > (checkGroupValues.contains(component.getModelObject())) > { > // O-P Preserve old escaping value, then turn > escaping off > // so that values aren't escaped > unnecessarily. > boolean oldEscaping = > component.getEscapeModelStrings(); > component.setEscapeModelStrings(false); > > addFormComponentValue(formComponent, ((Check) > component).getValue()); > > // O-P Restore the previous escaping setting. > component.setEscapeModelStrings(oldEscaping); > } > return CONTINUE_TRAVERSAL; > } > }); > } > > // O-P Restore the previous escaping setting. > formComponent.setEscapeModelStrings(oldEscaping); > } > }); > } -- This message is automatically generated by JIRA. - You can reply to this email to add a comment to the issue online.