Skip to main content

for_css_url

Function for_css_url 

Source
pub fn for_css_url(input: &str) -> String
Expand description

encodes input for safe embedding in a CSS url() value.

whatever the input, url(<output>) is exactly one url-token: nothing can terminate it early or turn it into a bad-url-token. the CSS parser unescapes the value before resolving it, so a URL that genuinely contains (, ) or a space still points at the same resource.

the URL must be validated before encoding (e.g., ensure the scheme is allowed). encoding only prevents syntax breakout, not malicious URLs.

§encoded characters

everything for_css_string encodes, plus space (U+0020).

§examples

use contextual_encoder::for_css_url;

assert_eq!(for_css_url("image.png"), "image.png");
// b is a hex digit, so trailing space after \27
assert_eq!(for_css_url("a'b"), r"a\27 b");
assert_eq!(for_css_url("a(b)"), r"a\28 b\29 ");
Examples found in repository?
examples/contexts.rs (line 86)
18fn main() {
19    let input = r#"<script>alert("xss")</script>"#;
20
21    println!("input: {input}");
22    println!();
23
24    // -----------------------------------------------------------------------
25    // comparison: same input across all encoders
26    // -----------------------------------------------------------------------
27
28    // html text content AND quoted attributes (safe default when unsure)
29    println!("--- html ---");
30    println!("  for_html:                     {}", for_html(input));
31
32    // html text nodes only — does NOT encode quotes, so never use in attributes
33    println!(
34        "  for_html_content:             {}",
35        for_html_content(input)
36    );
37
38    // quoted attribute values only — does NOT encode >, slightly more minimal
39    println!(
40        "  for_html_attribute:           {}",
41        for_html_attribute(input)
42    );
43
44    // unquoted attribute values — most aggressive, encodes whitespace/grave/etc.
45    println!(
46        "  for_html_unquoted_attribute:  {}",
47        for_html_unquoted_attribute(input)
48    );
49    println!();
50
51    // universal js encoder — safe in event attrs, <script> blocks, and .js files
52    println!("--- javascript ---");
53    println!("  for_javascript:               {}", for_javascript(input));
54
55    // html event attributes (onclick="...") — does not escape /
56    println!(
57        "  for_javascript_attribute:     {}",
58        for_javascript_attribute(input)
59    );
60
61    // <script> blocks — uses \" and \' (not safe in html attributes)
62    println!(
63        "  for_javascript_block:         {}",
64        for_javascript_block(input)
65    );
66
67    // standalone .js files — minimal, NOT safe in any html context
68    println!(
69        "  for_javascript_source:        {}",
70        for_javascript_source(input)
71    );
72
73    // ES6 template literals (`...`) — escapes backtick and ${} interpolation
74    let template_input = r#"`Hello ${name}`, welcome</script>"#;
75    println!(
76        "  for_js_template:              {}",
77        for_js_template(template_input)
78    );
79    println!();
80
81    // quoted css string values, e.g., content: "..." or font-family: "..."
82    println!("--- css ---");
83    println!("  for_css_string:               {}", for_css_string(input));
84
85    // css url() values, quoted or unquoted — like for_css_string plus space
86    println!("  for_css_url:                  {}", for_css_url(input));
87    println!();
88
89    // uri component (query params, path segments) — NOT for full urls
90    println!("--- uri ---");
91    println!(
92        "  for_uri_component:            {}",
93        for_uri_component(input)
94    );
95
96    // form-urlencoded value (WHATWG) — space→+, different safe set from RFC 3986
97    println!(
98        "  for_form_urlencoded:          {}",
99        for_form_urlencoded(input)
100    );
101    println!();
102
103    // xml 1.0 aliases — identical to the html encoders
104    println!("--- xml 1.0 ---");
105    println!("  for_xml:                      {}", for_xml(input));
106    println!("  for_xml_content:              {}", for_xml_content(input));
107    println!(
108        "  for_xml_attribute:            {}",
109        for_xml_attribute(input)
110    );
111
112    // xml-only contexts
113    println!("  for_xml_comment:              {}", for_xml_comment(input));
114    println!("  for_cdata:                    {}", for_cdata(input));
115    println!();
116
117    // xml 1.1 — restricted chars get &#xHH; instead of space
118    println!("--- xml 1.1 ---");
119    let xml11_input = "a\x01b<c>";
120    println!("  for_xml11:                    {}", for_xml11(xml11_input));
121    println!(
122        "  for_xml11_content:            {}",
123        for_xml11_content(xml11_input)
124    );
125    println!(
126        "  for_xml11_attribute:          {}",
127        for_xml11_attribute(xml11_input)
128    );
129    println!();
130
131    // rust literals — \xHH escapes, UTF-8 byte encoding for byte strings
132    println!("--- rust ---");
133    println!("  for_rust_string:              {}", for_rust_string(input));
134    println!(
135        "  for_rust_byte_string:         {}",
136        for_rust_byte_string(input)
137    );
138    // unlike the others, this encoder takes exactly one character
139    println!("  for_rust_char(\"'\"):           {}", for_rust_char("'"));
140    println!(
141        "  for_rust_char_checked(input): {:?}",
142        for_rust_char_checked(input)
143    );
144    println!();
145
146    // json string value — \\uXXXX escapes for control chars and specials
147    println!("--- json ---");
148    println!("  for_json:                     {}", for_json(input));
149    println!();
150
151    // sql string literals — single-quote doubling (standard) or backslash escaping (mysql)
152    println!("--- sql ---");
153    println!("  for_sql:                      {}", for_sql(input));
154    println!(
155        "  for_sql_backslash:            {}",
156        for_sql_backslash(input)
157    );
158
159    // -----------------------------------------------------------------------
160    // practical: one realistic input per sink, correct encoder for each
161    // -----------------------------------------------------------------------
162
163    let user_name = r#"Bob <img src=x onerror="alert(1)">"#;
164    let user_query = "hello world & goodbye";
165    let user_text = r#"hi from </script><script>alert(1)</script>"#;
166    let user_css_text = r#"hello "css" \ test"#;
167
168    println!("--- practical usage ---");
169
170    // html text node — for_html_content is the right encoder
171    println!(r#"  <p>{}</p>"#, for_html_content(user_name));
172
173    // nested context: uri component inside an html attribute.
174    // encode from inside out: first percent-encode the query value,
175    // then html-attribute-encode the entire href.
176    let href = format!("/search?q={}", for_uri_component(user_query));
177    println!(r#"  <a href="{}">search</a>"#, for_html_attribute(&href),);
178
179    // actual css string context: a quoted content value in a stylesheet
180    println!(
181        r#"  <style>.msg::after {{ content: "{}"; }}</style>"#,
182        for_css_string(user_css_text),
183    );
184
185    // javascript string inside an event-handler attribute
186    println!(
187        r#"  <button onclick="greet('{}');">hi</button>"#,
188        for_javascript_attribute(user_text),
189    );
190}