Forum Moderators: phranque

Message Too Old, No Replies

logical operator OR with IF-ELSE

         

numnum

7:09 pm on Jan 2, 2012 (gmt 0)

10+ Year Member



Wondering if/how I can use an OR operator (or its equivalent) to include the same HTML content ("blah, blah" in the hypothetical below) on an SSI called to two or more specific directories, or ELSE something other than "blah, blah." Here's the inefficient way:

<!--#if expr="$REQUEST_URI = directory1/" -->
blah, blah
<!--#elif expr="$REQUEST_URI = directory2/" -->
blah, blah
<!--#else -->
something else
<!--#endif -->

Here's the gist of what I'm trying to do:

<!--#if expr="$REQUEST_URI = directory1/ OR directory2/" -->
blah, blah
<!--#else -->
something else
<!--#endif -->

I checked the Apache site, and I can't find the correct syntax, if what I want to do is possible at all (I'm not sure).

coopster

7:40 pm on Jan 2, 2012 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



Maybe you are just looking in the wrong place? It's under the Server Side Includes documentation, particularly the second link below for mod_include, under Flow Control Elements:

[httpd.apache.org...]
[httpd.apache.org...]

numnum

10:22 pm on Jan 2, 2012 (gmt 0)

10+ Year Member



I was on the Flow Control page at the Apache site. I just couldn't get anything to work, so I assumed I was completely wrong. Here's what that document suggests should work:

<!--#if expr="$REQUEST_URI = /directory1/ || /directory2/" -->
blah, blah
<!--#else -->
something else
<!--#endif -->

But I'm getting "blah, blah" in every directory, not just 1 and 2. I've tried all sorts of variations with additional quote wrapping, omitting slashes, using DOCUMENT_URI instead, ELIF instead of ELSE. Nothing's working. Hmmm.

(My ISP is running Apache 2.X, so I'm pretty sure that's not the problem -- it's ME.)

lucy24

4:25 am on Jan 3, 2012 (gmt 0)

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



Did you try it with parentheses? Something like

$REQUEST_URI = ( /directory1/ || /directory2/ )

but don't take my word for it on the exact spacing.

Disclaimer: I don't speak a word of Apache. But to me, the form

$REQUEST_URI = /directory1/ || /directory2/

looks as if it would mean

either the $REQUEST_URI is /directory1/
or /directory2/ exists

so the condition would always be met.

numnum

5:43 am on Jan 3, 2012 (gmt 0)

10+ Year Member



lucy24,

Good observation -- you're correct that the results under my syntax are as if the condition is always met. But I'm modeling the syntax on what is provided at the Apache site, so I'm stymied.

Parentheses (per your suggestion) return an error message. I tried curly brackets (braces) -- no error message, but the IF/ELSE operators don't kick in. (Again, it's as if the condition is always met).

Hmmm.

lucy24

7:07 am on Jan 3, 2012 (gmt 0)

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



Hmmm indeed. Did you try it both with and without spaces inside the parentheses? If I'm reading this right,

( test_condition )
true if test_condition is true

spaced parentheses have a special meaning-- which would explain the error message-- so to use them in the ordinary RegEx way they have to be unspaced. This sample line here

<!--#if expr="($a = test1) && ($b = test2)" -->

sure looks as if it means you can put things inside parentheses, doesn't it?

:: looking vaguely around for "no idea" [cosgan.de] emoticon ::

coopster

10:07 pm on Jan 6, 2012 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



It may also be attempting to read that first slash as your indication of this being a regular expression but I am grabbing at straws at this point. If I were writing it out I would probably go with ...
<!--#if expr="($REQUEST_URI = /^\/directory(1|2)\/$/)" -->

Here you can see that I begin and end the regular expression pattern with a slash delimiter (/pattern/). Delimiter is the term used to describe the enclosure character of a regular expression pattern. Then I have my beginning anchor, the caret (^). Next is my directory separator (the slash) which I had to escape first with the regular expression escape character, the backslash (\). Next my directory name ending in an (either|or) pattern of (1|2), for directory1 or directory2. Then the ending directory path separator (the slash again), which again needs to be escaped. Finally I anchor the end of my pattern with the dollar sign and my ending delimiter.

I realize this is a PHP manual page, but I just happened across it and it may give you some insight to what is going on in my message here in the event you get confused by my detail.

[php.net...]

As with any regular expression, there is more than one way to do it (TIMTOWTDI). You could also do something like this ...

<!--#if expr="($REQUEST_URI = /\/directory1\// || $REQUEST_URI = /\/directory2\//" -->


... I'll stop here. Hopefully this makes sense.

numnum

6:41 am on Jan 8, 2012 (gmt 0)

10+ Year Member



coopster, Thanks very, very much for taking the time to draft such a detailed response. I'm not worthy.

I'll get back to working on this problem within a few days and post the results.

lucy24

7:42 am on Jan 8, 2012 (gmt 0)

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



I thought Apache never escaped forward-slashes :(

coopster

2:49 pm on Jan 10, 2012 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



Apache mod_include incorporates the PCRE (Perl Compatible Regular Expression) engine so you play by PCRE rules. There is a statement on the mod_include documentation that alludes to this feature:

Compare string1 with string2. If string2 has the form /string2/ then it is treated as a regular expression. Regular expressions are implemented by the PCRE engine and have the same syntax as those in perl 5.

lucy24

11:24 pm on Jan 10, 2012 (gmt 0)

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



It's not RegEx as such, it's mod_include. (Unnerving, btw, because I think of escaped slashes as a javascript feature.) Neither slashes nor literal spaces normally have to be escaped in Regular Expressions; it's only needed when the character itself has meaning. The key rule is actually on the mod_include page itself-- which is good, because Apache has carelessly linked to a blog page (which changes daily) rather than to the unchanging Perldocs page. Baaaad Apache.

Escaping slashes in regex strings

All slashes which are not intended to act as delimiters in your regex must be escaped. This is regardless of their meaning to the regex engine.

At the same time it's clear from their own examples that / doesn't have to mean "we are now entering Regular Expressions mode". There are tons of this kind of thing:

<!--#if expr='"$DOCUMENT_URI" = "/foo/file.html"' -->

Where are your directories actually located? It looks as if the only options are:

url without leading slash = in or below your current directory (the document itself, not the file you're writing this in)
url with leading slash = site-absolute

If you say

<!--#if expr='"$REQUEST_URI" = "/directory1" || "$REQUEST_URI" = "/directory1"' -->

does it wig out and think you're going into Regular Expressions? Come to think of it, you may have to go into Regular Expressions if "directory1" really means "either directory1 itself, or anything contained within directory1".

coopster

4:07 pm on Jan 12, 2012 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



It's not RegEx as such, it's mod_include.


Could be, and you are likely correct. I didn't pull the source to examine and confirm but I'm guessing mod_include probably knew it needed some type of indicator that it should invoke the regular expression engine and so it decided to use the default delimiter and the only way it would know where the pattern begins and ends is to locate the ending delimiter. Then the only way to use the delimiter within the pattern then is to escape it. This is quite common and you'll notice it invoked in all kinds of programming languages and APIs for those languages.

Good catch on that note on the Apache docs regarding escaping slashes. That solidified it. I prefer the text man page for PCRE:
[pcre.org...]
A bit more primitive but I'm quite accustomed to the format. Perl does a great job on the perldocs too though. I agree, that Perl 5 link should be pulled or changed.


At the same time it's clear from their own examples that / doesn't have to mean "we are now entering Regular Expressions mode". There are tons of this kind of thing:

<!--#if expr='"$DOCUMENT_URI" = "/foo/file.html"' -->


Actually, yes it still does mean that you are going to enter PCRE mode. The pattern you show here and in the examples to which you refer are not starting with a slash but they start with a double quotation mark. Easy to miss at first glance, but it is indeed there. Take a look at the second half of the comparison expression as it does not start with a slash but a double quotation mark:

"/foo/file.html"


... which in turn ends up in the expression being tested as a string comparison returning boolean true or false.

The REQUEST_URI is always going to start with a directory separator. It's root-relative. However, it may or may not be present too, depending on the http server and server configuration. I believe it was introduced originally with Apache and mod_rewrite but I cannot recall. It is an extension to the CGI standard. I would expect it to be there myself but in the event it does not work perhaps one of the other variables should be used, particularly DOCUMENT_URI, because that would always be available when using mod_include.

If you are curious about other CGI variables, the Apache documentation for CGI has some environment variables listed in the provisions area and then a link to the CGI spec where the other variables are listed. You can also pull the RFC on CGI. I listed some resources below. on a completely off-topic note, I linked to the Apache 2.2 docs earlier in this thread and should really be linking to the trunk documentation because the links to the CGI spec on the earlier Apache docs are now gone; updated documentation is always available on the Apache trunk docs

mod_cgi: [httpd.apache.org...]
RFC: [ietf.org...]
Apache environment variables: [httpd.apache.org...]
mod_rewrite: [httpd.apache.org...]