Forum Moderators: phranque

Message Too Old, No Replies

using %{REMOTE USER} in RewriteCond ConditionPattern

         

sunils

6:19 pm on Sep 19, 2007 (gmt 0)

10+ Year Member



I am new to this forum and mod_rewrite.

We host reports meant for about 1000 users under a directory tree like "D:\Reports\<username>\". We wanted to provide access to users folder through web so that :

1. A logged in user goes straight to his folder
2. No user does not get access to others folders.

I hoped that I could get this done using mod_rewrite. But, I am unable to form the right RewriteCondition/RewriteRule for this. What I tried to do was :
----------------------------------
Alias /Reports "D:\Reports"
<Directory D:/Reports>
AuthType Basic
AuthName "Nothing"
AuthBasicProvider file
AuthUserFile conf/passwd
Require valid-user

RewriteEngine on
RewriteBase /Reports
RewriteCond %{REQUEST_URI}!^/Reports/%{REMOTE_USER}.* [NC]
RewriteRule ^.*$ /Reports/${REMOTE_USER}/ [NC,R,NS,L]

Options Indexes Multiviews FollowSymLinks
IndexOptions +HTMLTable +IgnoreCase +NameWidth=*
IndexIgnore *.log *.old *.png *.db
Order allow,deny
Allow from all
</Directory>
----------------------------------
From the logs I see that %{REMOTE_USER} in RewriteCond ConditionPattern is not evaluated. Going thourgh the Apache documentation, I realise that I can use only a regex there. Here is an edited sample of the log :
----------------------------------
strip per-dir prefix: D:/Reports/SUNILS/ -> SUNILS/
applying pattern '^.*$' to uri 'SUNILS/'
RewriteCond: input='/Reports/sunils/' pattern='!^/Reports/%{REMOTE_USER}.*' [NC] => matched
rewrite 'SUNILS/' -> '/Reports/sunils/'
explicitly forcing redirect with [10.10.0.3...]
trying to replace prefix D:/Reports/ with /Reports
escaping [10.10.0.3...] for redirect
redirect to [10.10.0.3...] [REDIRECT/302]
----------------------------------

Can any one suggest how to do it right?

TIA

Sunil

jdMorgan

11:33 pm on Sep 19, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



The general problem is that you can't do a "compare" with mod_rewrite -- at least not on all OS platforms. It's only available on some versions of *nix -- those that support POSIX 1003.2 'atomic back-references' in regular expressions. On those OSes, you can use atomic back-references and take advantage of commutativity, that is, if A+A=A+B, then A=B. But since POSIX support is OS-specific, the technique is a poor one to plan a site on.

I'd suggest creating per-user directories, and having the reports appear in those private directories only after the user logs in to that directory (using mod_auth). You could also use per-user subdomains if that has any appeal to you or your users -- e.g. username.example.com/reports.

The report themselves could be generated and stored in a different location in the filespace, and only appear to be in a subdirectory of the user's subdirectory -- this implemented with mod_alias, an internal rewrite, or even *nix symbolic links.

Jim

[edited by: jdMorgan at 11:37 pm (utc) on Sep. 19, 2007]

sunils

6:00 am on Sep 22, 2007 (gmt 0)

10+ Year Member



Dear Jim

Thank you for your quick response (and sorry about my delayed reply).

1. Could you elaborate on the idea of per user directory - is there a way to ensure that a user logs into his own directory only, without per directory configuration specifying require user directive?
2. Per-user sub-domain is difficult in our situation.
3. We are on Windows and symbolic links are also not possible.

I considered another option. I tried :
--------------------------------
Alias /vfolders "D:\vfolders"
RewriteLog logs/rewrite.log
RewriteLogLevel 9
RewriteMap testmap "prg:c:/perl/bin/perl.exe c:/Apache2/bin/rewritemap.pl"
<Directory "D:/vfolders>
Options Indexes Multiviews FollowSymLinks
Order allow,deny
Allow from all

AuthType Basic
AuthName "Nothing"
AuthBasicProvider file
AuthUserFile conf/passwd
Require valid-user

RewriteEngine on
RewriteBase /vfolders/
RewriteCond ${testmap:%{REQUEST_URI}:%{REMOTE_USER}} ^REWRITE$[NC]
RewriteRule ^.*$/vfolders/%{REMOTE_USER}/ [R,L,NS]
</Directory>
---------------------------------
# C:/Apache2/bin/rewritemap.pl listing :
$¦=1;
while(<STDIN>){
chomp; my ($URI,$USER)=(split /:/);
print "REWRITE\n" unless $URI=~/^\/vfolders\/$USER/;
}
---------------------------------
and edited output of rewrite.log on "curl -u sunils:password [localhost...] is :
---------------------------------
11:26:40 initial (3) [perdir D:/vfolders/] add path info postfix: D:/vfolders/abcd -> D:/vfolders/abcd/
11:26:40 initial (3) [perdir D:/vfolders/] strip per-dir prefix: D:/vfolders/abcd/ -> abcd/
11:26:40 initial (3) [perdir D:/vfolders/] applying pattern '^.*$' to uri 'abcd/'
11:26:40 initial (5) map lookup FAILED: map=testmap key=/vfolders/abcd/:sunils
11:26:40 initial (4) [perdir D:/vfolders/] RewriteCond: input='' pattern='^REWRITE$' [NC] => not-matched
11:26:40 initial (1) [perdir D:/vfolders/] pass through D:/vfolders/abcd
---------------------------------
Apparently rewritemap program is not executed and consequently RewriteCond had a '' to compare with pattern. I tried rewritemap.exe (compiled version) too. Is there any other directive on which execution of prg:program would depend?

Regards

Sunil

sunils

1:00 pm on Sep 25, 2007 (gmt 0)

10+ Year Member



Can any one give me some clue on this issue?

TIA

Sunil

jdMorgan

1:25 pm on Sep 25, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I notice that you did not define the "path to PERL" in your script. This is almost always required.

The very first line of the .pl file should be something like


#!/usr/local/bin/perl

with the filepath adjusted as appropriate for your server.

Jim

sunils

1:59 pm on Sep 25, 2007 (gmt 0)

10+ Year Member



Dear Jim,

Well, my OS is Windows. #! does not apply there, right?

As you can see the line in httpd.conf includes path to interpreter :

RewriteMap testmap "prg:c:/perl/bin/perl.exe c:/Apache2/bin/rewritemap.pl"

Besides, as I had mentioned earlier, I tried rewritemap.exe (compiled with pp) as :

RewriteMap testmap "prg:c:/Apache2/bin/rewritemap.exe"

Both failed to work with "map lookup FAILED: map=testmap" message in the log. And, the script works as expected when run from command line.

I am clueless!

Regards

Sunil

jdMorgan

2:40 pm on Sep 25, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



The syntax of your RewriteMap directive isn't quite right; The second parameter is the default value to return if the map lookup fails. It is not a parameter to be passed to the lookup map. So you either want to leave it out, or to specify a default return value, such as "NOREWRITE" there, preceded by a solid pipe character and not by a colon.

RewriteEngine on
RewriteBase /
RewriteCond [b]${testmap:%{REQUEST_URI}}[/b] ^REWRITE$[NC]
RewriteCond $1 !^/vfolders/
RewriteRule (.*) /vfolders/%{REMOTE_USER}/$1 [L]

There were a few problems with the rule, and I added a second RewriteCond just in case it might be needed to prevent a loop -- I have found that [NS] does not work to prevent such looping, at least not in .htaccess files.

Also, check that RewriteBase directive...

You might actually want to consider commenting out the RewriteBase and the RewriteMap reference, testing until the rest works, and then adding them back in one-at-a-time. RewriteMaps are hard to debug, because so many little things can cause an error.

Jim

sunils

3:36 pm on Sep 25, 2007 (gmt 0)

10+ Year Member



Jim,

I intended to pass REQUEST_URI and REMOTE_USER concatenated by a ":" with no default value; then only I can check if the request is OK - that username and /vfolders/username are matching. The way I understood the documentation on rewritemap is, %{REWRITE_URI}:%{REMOTE_USER} will be evaluated to first parameter. This inference seems to be correct because of log entries like :

11:26:40 initial (5) map lookup FAILED: map=testmap key=/vfolders/abcd/:sunils

Key is evaluated correctly to "/vfolders/abcd/:sunils"

In my case default '' is returned due to lookup failure (default in absence of "¦default" in rewritemap)

I feel that the perl script is failing to get executed.

If it matters, I am using binary from [apachelounge.com...]
Server version:Apache/2.2.4 (Win32)
Server built: Feb 24 2007 13:17:21

I had tested without RewriteMap and RewriteBase already; the only place where it does not work as expected seems to be at the RewriteMap.

Regards

Sunil

sunils

3:15 am on Sep 26, 2007 (gmt 0)

10+ Year Member



Jim,

I have tried my configuration with just released Apache 2.2.6 win32 binary from ASF also (http://www.trieuvan.com/apache/httpd/binaries/win32/apache_2.2.6-win32-x86-openssl-0.9.8e.msi)

Results are the same.

Regs

Sunil

jdMorgan

4:14 am on Sep 26, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I'm not the world's best PERL coder or debugger, but there appear to be several things missing from your PERL script. I'd suggest something more like:

# C:/Apache2/bin/rewritemap.pl listing :
$¦=1;
while (my $inpvars = <STDIN>)
{
chomp ($inpvars);
my ($URI,$USER) = split(/:/, $inpvars);
print "REWRITE\n" unless $URI=~/^\/vfolders\/$USER/;
}

I'm not sure if that fixes all the script problems or not, but it may get you closer.

Jim

sunils

5:06 am on Sep 26, 2007 (gmt 0)

10+ Year Member



Dear Jim,

I had tested the script rewritemap.pl earlier from command line and it worked as expected. Like your script, I also did not code for any output unless the URI needed rewriting. BOTH scripts are behaving in the same way from command line. Here is a sample :
-------------------------
C:\Apache2\bin>perl rewritemap-jim.pl
/vfolders/sunils:sunils
/vfolders/sunils:shruthi
REWRITE
^Z^Z

C:\Apache2\bin>perl rewritemap.pl
/vfolders/sunils:sunils
/vfolders/sunils:shruthi
REWRITE
^Z^Z
---------------------------
Still it looks like the rewritemap program is just not being run. What ever you give there, even if it a non-existing program, apache does not say a word about it in the error logs....

Regs

Sunil

jdMorgan

1:05 pm on Sep 26, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Sunil,

It's unlikely that I am going to be able to come up with a "magic" fix that suddenly makes this all work -- All I can do is make suggestions. However, there are a lot of clues here and if you look, you may see something that is not obvious to me as an 'outsider' who does not have access to all the information you do.

Another thing you can do is to modify the rules and the script slightly -- even moving away from the actual solution you want to end up with, in order to facilitate testing. So, today's suggestion is to make the script always outputs something, so you can verify that it it keeps running forever (as it should) and that it is being invoked:


# C:/Apache2/bin/rewritemap.pl listing :
$¦=1;
while (my $inpvars = <STDIN>)
{
chomp ($inpvars);
my ($URI,$USER) = split(/:/, $inpvars);
if ($URI = ~/^\/vfolders\/$USER/)
{
print ("NOREWRITE\n");
}
else
{
print ("REWRITE\n");
}
}

Also I note the message "Strip per-dir" prefix in the rewritelog, and it is stripping the 'vfolders' path-part. It seems to me that this will affect your map lookup, since 'vfolders' will no londer be part of REQUEST_URI. So either the 'method' needs to change, or you may need to re-architect the file layout from document_root down a bit. And why is it doing *anything* "per-dir"? -- That's an .htaccess thing. This code is in httpd.conf, right?

Jim

sunils

2:50 pm on Sep 26, 2007 (gmt 0)

10+ Year Member



Dear Jim,

1. Yes, there is no .htaccess file anywhere in the test server, all config is in httpd.conf.
2. I agree that the two entries ("strip per-dir prefix" and "applying pattern '^.*$' to uri") are unexpected. Despite this, the key passwd to map is correct. (map lookup FAILED: map=testmap key=/vfolders/shruthi/:sunils)
3. I tried the script you suggested slightly modified as below:

-------------------c:/Apache2/bin/rewritemap-jim.pl listing
$¦=1;
open(tmp,">>c:/Apache2/logs/rewritemap.log") or die;
print tmp time()," -------- RewriteMap program STARTED ----------\n";
while (my $inpvars = <STDIN>) {
chomp ($inpvars);
print tmp time()," inpvars=$inpvars\n";
my ($URI,$USER) = split(/:/, $inpvars);
print tmp time()," URI=$URI, USER=$USER\n";
if ($URI=~/^\/vfolders\/$USER/) {
print ("NOREWRITE\n");
} else { print ("REWRITE\n"); }
}
print tmp time()," -------- RewriteMap program ENDED ------------\n";
close tmp;
-------------------
Just tried to log what happens inside the script into rewritemap.log. However, the rewritemap.log does not even get created when we run apache. From command line the script works as expected and creates the log all right. rewrite map has entries as before - "map lookup FAILED", and the rewritecond fails as the comparison - as before - is against ''. (RewriteCond: input='' pattern='^REWRITE$' [NC] => not-matched)

It is almost obvious that the RewriteMap program did not get launched.

Regards,

Sunil

jdMorgan

3:12 pm on Sep 26, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Probably a general "file permissions" or "Local Security Policy" problem under Windows, then... Hopefully someone who runs Apache on Windows can help...

You might want to check the Windows Event Viewer and see if there are any execution-attempt errors logged there.

Jim

sunils

3:30 pm on Sep 26, 2007 (gmt 0)

10+ Year Member



Dear Jim,

I think we are stuck. There is no file permission/local security policy issue on the test machine. And no entry in the EventLog too.

I will repost this issue here as a rewritemap issue on win32 and lets hope that some one has gone through this before.

I am now planning to look for some work around like Squid-2.6 in reverse proxy config with url_rewrite moving the authentication from apache to reverse proxy.

Thank you very much.

Regards

Sunil

sunils

6:08 am on Oct 1, 2007 (gmt 0)

10+ Year Member



Discussion on this thread is continuing at [webmasterworld.com...]