Forum Moderators: phranque

Message Too Old, No Replies

More fun with [E], escaping quotes

         

csdude55

7:10 pm on Feb 11, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Shout out to @w3dk for telling me this one:

Instead of backslash escaping spaces, you can surround the entire flags argument with double quotes:
"[E=example:Lorem ipsum dolor sit amet consectetur]"


Now I'm expanding upon that...

I'm setting a variable that's a string like this:

<H3 data-logo onClick="location.href='%{ENV:home}';">${lc:$1}</H3>


It's actually a bit longer than that, but I'm cutting out a chunk of it for this post. I originally had it as a switch-case in PHP, but processing it this way seems to be notably faster. Note that the string has both double-quotes and single-quotes, though.

So at first I did it like this:

RewriteRule ^ - [E=foo:<H3\ data-logo\ onClick="location.href=\ '%{ENV:home}';">${lc:$1}</H3>]


and now, based on @w3dk 's explanation, I'm trying to do it like this:

RewriteRule ^ - '[E=foo:<H3 data-logo onClick="location.href='%{ENV:home}';">${lc:$1}</H3>]'


In testing, though, I discovered that these all throw an error of RewriteRule: bad flag delimiters:

# Using \ to escape the nested '
RewriteRule ^ - '[E=foo:<H3 data-logo onClick="location.href= \'%{ENV:home}\';">${lc:$1}</H3>]'

# Double-escaping
RewriteRule ^ - '[E=foo:<H3 data-logo onClick="location.href= \\'%{ENV:home}\\';">${lc:$1}</H3>]'

# Triple-escaping
RewriteRule ^ - '[E=foo:<H3 data-logo onClick="location.href= \\\'%{ENV:home}\\\';">${lc:$1}</H3>]'

# Using a double quote to wrap, then escaping the doubles instead
RewriteRule ^ - "[E=foo:<H3 data-logo onClick=\"location.href= '%{ENV:home}';\">${lc:$1}</H3>]"

# Using a tilde to wrap instead of '
RewriteRule ^ - `[E=foo:<H3 data-logo onClick="location.href= '%{ENV:home}';">${lc:$1}</H3>]`


I know that I could encode it with something like %squot; (or anything, really) and then use str_replace in PHP to swap it back to a single quote, but that would kinda defeat the purpose. So before I give up and go back to escaping the whitespaces with no wrapping quotes, is there some other way of escaping the nested quotes that I'm overlooking?

w3dk

7:29 pm on Feb 22, 2021 (gmt 0)

10+ Year Member Top Contributors Of The Month



It looks like you are going beyond what "simple environment variables" are meant to be used for.

If you have an environment variable value that should contain all three... spaces, single-quotes and double-quotes, then it does look like you would need to revert to backslash escaping the literal spaces. The single and double-quotes can then be used as-is in the env var value.

However, you can also build up the final value using multiple directives to avoid complex escaping. For example:


RewriteRule ^ - [E=foo:"location.href='%{ENV:home}';"]
RewriteRule ^ - "[E=foo:<H3 data-logo onClick=%{ENV:foo}>${lc:$1}</H3>]"


(The space after "location.href=" is not required, so this simplifies the first assignment.)


I'm setting a variable that's a string like this:
<H3 data-logo onClick="location.href='%{ENV:home}';">${lc:$1}</H3>



I assume you are expecting "%{ENV:home}" and "${lc:$1}" to be evaluated before the value is assigned to the env var (ie. you don't want to store this literal text in the env var?!), but what is "$1" supposed to refer to in this example? (In the examples you posted, the $1 backreference is always empty.)

csdude55

8:29 pm on Feb 22, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



It looks like you are going beyond what "simple environment variables" are meant to be used for.

Yes and no. What I have is 55 domains parked on top of a main domain, and I used to use PHP to read the domain name and then set variables based on that domain. If the user was at the default domain then I would use the second level of the URL; eg, example.com/no_domain

What I found, though, was that I was shaving a good amount of time off of every pageview by moving it to Apache. So it's not REALLY that complex, just lengthy.

I assume you are expecting "%{ENV:home}" and "${lc:$1}" to be evaluated before the value is assigned to the env var (ie. you don't want to store this literal text in the env var?!), but what is "$1" supposed to refer to in this example? (In the examples you posted, the $1 backreference is always empty.)

Oops, sorry about that! I was trying to make things easier to read for you, and just made it harder :-/

The actual code looks like this:

# %{ENV:domain} is determined earlier
RewriteCond %{ENV:domain} ^example?$

# I also let the user define the domain with example.com?default=whatever
RewriteCond %{QUERY_STRING} !(?:^|&)default=[a-z]+ [NC]

# define all of the allowed first-level pages
# if it's not one of these then the first level must be one of the pre-defined possibilities
RewriteCond %{REQUEST_URI} !^/(?:lorem|ipsum|53_others)[/$] [NC]

# $1 is the first level of the URL
# %{ENV:home} is defined earlier, too
# I actually set 4 variables here, so this is abbreviated to the relevant part
RewriteRule ^/([a-z]+) - [E=foo:<H3\ data-logo\ onClick="location.href='%{ENV:home}';">${lc:$1}</H3>]


However, you can also build up the final value using multiple directives to avoid complex escaping.

That's pretty slick :-) I wouldn't need the "location.href=whatever" unless these 3 conditions match, but there's no reason that I couldn't create it ahead of time and just not use it if they don't match. Eg,

RewriteRule ^ - [E=bar:"location.href='%{ENV:home}';"]

RewriteCond %{ENV:domain} ^example?$
RewriteCond %{QUERY_STRING} !(?:^|&)default=[a-z]+ [NC]
RewriteCond %{REQUEST_URI} !^/(?:lorem|ipsum|53_others)[/$] [NC]
RewriteRule ^/([a-z]+) - "[E=foo:<H3 data-logo onClick=%{ENV:bar}>${lc:$1}</H3>]"