Forum Moderators: coopster

Message Too Old, No Replies

How can I create a source listing from my live scripts?

Using mod_rewrite to fake up a php source directory listing

         

coopster

3:33 pm on Feb 2, 2007 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



I started a little project 3 years ago after reading the following example in the Apache mod_rewrite [httpd.apache.org] documentation:


'type¦T=MIME-type' (force MIME type) 
Force the MIME-type of the target file to be MIME-type. This can be used to set up the content-type based on some conditions. For example, the following snippet allows .php files to be displayed by mod_php if they are called with the .phps extension:

RewriteRule ^(.+\.php)s$ $1 [T=application/x-httpd-php-source]

I played around with it for a few hours but after hitting a rough spot I never got around to having another look at this little side project. As I was doing some cleanup today I came across the code again and my notes. And of course I had to fiddle with it one more time but ended up empty again. I thought I would throw what I had out here to the community and see if anybody else has any ideas on the issue.

I have a directory of PHP scripts. Every entry in the directory has a .php extension. Often times I would like to view the source for the script through the browser as well. PHP has a nice little application handler for doing just that, simply save your script with a .phps extension and when clicked, the MIME type application handler will show highlighted PHP source (as long as you have enabled it in your configuration). OK, but I don't want to save each and every script twice, once with a .php extension and once with a .phps extension. I thought, let's turn to Apache and see what we can do.

I wrote a quick little PHP application that reads the directory and creates a table of the PHP scripts. The script itself appears in the first column and a link in the right column to the fake .phps source document. Looks something like this (source for script included below, put it in the same directory as your scripts):

+--------+---------+ 
¦ script ¦ source ¦
+--------+---------+
¦ aa.php ¦ aa.phps ¦
¦ bb.php ¦ bb.phps ¦
+--------+---------+
<?php
$count = 0;
$dir = '';
$d = dir('./');
while (false!== ($filename = $d->read())) {
if (substr($filename, -4) == '.php') {
$new_name = preg_replace('/^([^.]+\.php)$/', "$1s", $filename);
$dir .= "<tr>\n\t\t<td>" . $count++ . "</td>\n\t\t<td><a href=\"$filename\">$filename</a></td>\n\t\t<td><a href=\"$new_name\">$new_name</a></td>\n\t</tr>";
}
}
$d->close();
?>
<html><head><title>PHP Scripts</title></head><body>
<table>
<tr>
<td>#</td>
<td>run script</td>
<td>view source</td>
</tr>
<?php print $dir;?>
</table>
</body></html>

Now, in a per-directory override file (.htaccess), I've thrown in the following...

Options +FollowSymLinks 
RewriteEngine on
RewriteRule ^([^.]+\.php)s$ $1 [T=application/x-httpd-php-source]

However, upon clicking the source link in the right column, the PHP parser processes the script rather than displaying the highlighted source code. I cranked up the RewriteLog to level 9 and here is the process ...

  1. strip per-dir prefix: /document/root/aa.phps -> aa.phps
  2. applying pattern '^([^.]+\.php)s$' to uri 'aa.phps'
  3. rewrite aa.phps -> aa.php
  4. add per-dir prefix: aa.php -> /document/root/aa.php
  5. remember /document/root/aa.php to have MIME-type 'application/x-httpd-php-source'
  6. strip document_root prefix: /document/root/aa.php -> /intranet/snippets/aa.php
  7. internal redirect with /intranet/snippets/aa.php [INTERNAL REDIRECT]
  8. strip per-dir prefix: /document/root/aa.php -> aa.php
  9. applying pattern '^([^.]+\.php)s$' to uri 'aa.php'
  10. pass through /document/root/aa.php

Anybody have any insight as to what is going on?

eelixduppy

9:05 pm on Feb 2, 2007 (gmt 0)



Hey coopster!


Often times I would like to view the source for the script through the browser as well.

I'm curious as to why you want to take this approach. Why wouldn't you want to make your life easier by using a function such as highlight_file [us2.php.net]? It essentially achieves the same thing.

But to answer your question, I have no idea, either. ;)

coopster

2:42 am on Feb 5, 2007 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



Yeah, I was going to mention something when I first posted but the message was already getting a bit lengthy. I'll address it now though. It isn't the end goal so much this time as I can easily perform workarounds using functions as you mentioned, it is more the application of what I know should work based on the methods being applied.

I wouldn't say the 'highlight_file' approach would be easier though as I would still need to code up a directory list, but then I would also need to

  1. read the file into memory
  2. and then apply the function to a string variable
  3. before generating output.
Whereas if I invoke Apache's built-in module I merely need to click the link to the 'fake' .phps file -- no further scripting required.

All that said, the problem, I believe, lies in the handler after the redirect. mod_rewrite states that ...


API Phases

First you have to understand that when Apache processes a HTTP request it does this in phases. A hook for each of these phases is provided by the Apache API. Mod_rewrite uses two of these hooks: the URL-to-filename translation hook which is used after the HTTP request has been read but before any authorization starts and the Fixup hook which is triggered after the authorization phases and after the per-directory config files (.htaccess) have been read, but before the content handler is activated.

I find that it works like a dream once I add a 'php' extension to the source handler ...

AddType application/x-httpd-php-source phps php
... but therein lies the catch! How do you process the files and see their source code at the same time? I have an idea, am going to test. Not until tomorrow though, been a long weekend ...

eelixduppy

9:46 pm on Feb 8, 2007 (gmt 0)



Looks like you've stumped everyone, coopster. Have you had any luck with this? I'm interested :)

coopster

9:57 pm on Feb 18, 2007 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



No, not yet. I was fiddling around with a LocationMatch [httpd.apache.org] container to see if I could get something going that way ... no love yet.

jatar_k

1:34 pm on Feb 19, 2007 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



so what you're saying is that you want to click on the fake url in your dir list and have apache force a php file to show as source by forcing the mime type

are we thinking the mime type isn't forced properly due to the content handler not being activated?

you need jdMorgan ;)

coopster

4:27 pm on Feb 19, 2007 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



hehe, jd and I already discussed the topic. I'm thinking that the handler is kicking in again after the rewrite code in the Apache hooks, and NOT retaining the fact that I forced the MIME type.