Silverstripe-framework: $ClassName template variable should be sanitised to remove slashes

Created on 10 Nov 2017  路  12Comments  路  Source: silverstripe/silverstripe-framework

Currently, the $ClassName template variable injects the entire, fully-qualified classname into the page. On SS4 this inevitably includes backslashes which are invalid in CSS class names.

Suggest that the ClassName should be sanitised with Convert::raw2htmlid() or similar before being sent to the template.

PRs:

affectv4 changminor efforeasy impaclow typbug typfrontend

Most helpful comment

You could add a $BaseName property to classname which skipped the namespace.

<body class="$ClassName.BaseName<% if not $Menu(2) %> no-sidebar<% end_if %>" <% if $i18nScriptDirection %>dir="$i18nScriptDirection"<% end_if %>>

And you could still use CSS rules like:

.HomePage h1 {
    font-size: 1.1em;
}

All 12 comments

For context this is coming from the default theme's Page.ss

<body class="$ClassName<% if not $Menu(2) %> no-sidebar<% end_if %>" <% if $i18nScriptDirection %>dir="$i18nScriptDirection"<% end_if %>>

Let's just remove it instead? :P

Removing it from the template doesn't cure the underlying issue though. If there's an expectation to be able to use the $ClassName in a template (as per SS3) then it's going to catch a lot of people out when they re-introduce the invalid code.

If fixing the specific issue is too onerous, would changing it to a different value be preferable? (something like $CSSClasses gives a cleaner output, albeit more verbose. At least this way, developers would have some guidance on what to use.

@tractorcow Could we add add something like the following to DBClassName instead?

public function forTemplate()
{
    return Convert::raw2htmlid($this->value);
}

I'd be more in favour of @kinglozzer's suggestion and have requested that in the pull request :)

@kinglozzer you are hard-baking in an assumption about front-end use to the inner dbfield; How do you know that $ClassName will be used as a css class name? It could be a value in a form. E.g.

<input type="radio" value="$ClassName" />

Which is now broken because we've stripped out slashes.

You could add a $BaseName property to classname which skipped the namespace.

<body class="$ClassName.BaseName<% if not $Menu(2) %> no-sidebar<% end_if %>" <% if $i18nScriptDirection %>dir="$i18nScriptDirection"<% end_if %>>

And you could still use CSS rules like:

.HomePage h1 {
    font-size: 1.1em;
}

That鈥檚 a fair point @tractorcow, I like your suggestion of adding an extra method to DBClassName to sanitise it 馃憤. Perhaps we could have both BaseName() and Sanitised() for the FQCN or something?

I agree with @tractorcow - there should be no assumption that $ClassName should be esacped as a .ATT as default.

Use $ClassName.ATT or some other valid escaping.

I think the issue is that slashes are valid in attributes, but not in CSS selectors.

Backslashes are valid in CSS, you just need to escape them e.g.

<body class="Namespace\PageType">
.Namespace\\PageType {}

But for what it's worth, I think adding BaseName() and/or Sanitised() would be a good idea as this will help keep selector lengths shorter.

Ok, I've updated this with a ShortName property instead.

Because of auto-escaping, this will be escaped as XML safely in the template anyway, but also won't have any slashes anymore. :)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

maxime-rainville picture maxime-rainville  路  3Comments

kinglozzer picture kinglozzer  路  4Comments

chillu picture chillu  路  3Comments

jonom picture jonom  路  5Comments

ntd picture ntd  路  4Comments