Styling Apache directory listings
In this post you will find how to make stylish listing generated by the Apache server. This is not just another CSS solution. The trick is in configuring Apache to generate XML directory list and to use browser (IE, FF, Opera, Safari ...) to transform XML to the HTML. You will have full freedom to modify and style auto generated directory listings.
- Edit httpd.conf
- Create header.html file
- Set execute permission to the header.html
- Create stylesheet.xsl
- Conclusion
1. Edit httpd.conf
Open httpd.conf file and edit IndexOptions and HeaderName directive.
# create XHTML table IndexOptions XHTML HTMLtable # avoid duplicated <html><body> and no column sorting IndexOptions SuppressHTMLPreamble SuppressColumnSorting # place folders first IndexOptions FoldersFirst # add text/xml HTTP header IndexOptions Type=text/xml # define absolute path to the header file HeaderName /header.html
If you want to have current directory displayed as a page title, please add +Includes to the Options directive - this will enable SSI, but Apache will not parse files until you define SSI files. SSI files can be marked by extension like shtml or by execute bit. In this example, I marked SSI files with execution bit. Don't forget to set execute permission to the SSI file or it will not be processed.
# parse SSI directives in files with the execute bit set XBitHack on
Check if directory listing is enabled by Indexes option in Options directive.
# The Options directive is both complicated and important. Please see # http://httpd.apache.org/docs/2.2/mod/core.html#options # for more information. Options Indexes ...
2. Create header.html file
header.html contains beginning of the XML listing. The rest of XML will be generated by Apache. XML has defined stylesheet and defined nbsp entity because Apache writes nbsp in emtpy table cells. Last line is a SSI directive, and if you need any other server variable, just wrap it within XML tag.
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp " "> ]> <?xml-stylesheet type="text/xsl" href="/stylesheet.xsl"?> <html><body> <request_uri><!--#echo var="REQUEST_URI" --></request_uri>
3. Set execute permission to the header.html
It is important to set execute permission to the header.html because Apache will process header file and execute line with REQUEST_URI. If you don't need "current directory" info or any other dynamics in header file, you can skip this step and omit +Includes / XBitHack in httpd.conf. On the other hand, if Apache "knows" PHP, and you aren't satisfied with static header.html, you can write PHP header file and you should name it header.php
<? print '<?xml version="1.0" encoding="utf-8"?>' ?> <? print '<!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp " "> ]>' ?> <? print '<?xml-stylesheet type="text/xsl" href="/stylesheet.xsl"?>' ?> <html><body> <request_uri><?= $_SERVER['REQUEST_URI'] ?></request_uri>
For PHP header file, you don't need +Includes / XBitHack in httpd.conf because Apache has defined PHP interpreter to handle files with a php extension.
4. Create stylesheet.xsl
Here is a simple stylesheet.xsl to process dynamically generated XML. Please save stylesheet.xsl to the document root or change path in the header file. After directory request, Apache will respond with XML. Browser will start to process XML and make request for stylesheet.xsl file. With requested XML and stylesheet.xsl, browser will render HTML page. If you click on View page source, you will not see finished HTML, but XML generated by Apache.
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" encoding="utf-8"
doctype-public="-//W3C//DTD HTML 4.01//EN"
doctype-system="http://www.w3.org/TR/html4/strict.dtd" />
<xsl:template match="/html/body">
<html>
<head>
<title>Directory: <xsl:value-of select="request_uri"/></title>
<style>
body {font-family: sans-serif; text-align: center;}
table {margin: 0px auto; border-collapse: collapse;}
td {border: 1px solid lightgrey;}
a, a:visited {color: #ff6600; text-decoration: none;}
a:hover {text-decoration: underline;}
</style>
</head>
<body>
<h2>Directory: <xsl:value-of select="request_uri"/></h2>
<table>
<!-- define table column width -->
<colgroup>
<col width="50"/> <!-- icon -->
<col width="400"/> <!-- link -->
<col width="180"/> <!-- last modified -->
<col width="50"/> <!-- size -->
</colgroup>
<!-- process 'tr' rows with td only (skip th rows) -->
<xsl:apply-templates select="table/tr[td]"/>
</table>
</body>
</html>
</xsl:template>
<!-- print table rows -->
<xsl:template match="tr">
<tr>
<td align="center"><xsl:copy-of select="td[position()=1]/*"/></td>
<td align="left"><xsl:copy-of select="td[position()=2]/a"/></td>
<td align="center"><xsl:value-of select="td[position()=3]"/></td>
<td align="right"><xsl:value-of select="td[position()=4]"/></td>
</tr>
</xsl:template>
</xsl:stylesheet>
5. Conclusion
Described procedure may seem complicated, but it all boils down to the two files and a couple of lines in the httpd.conf file. First file is header file - static HTML or HTML with SSI or PHP (depends what you need). And the second file is XSL. Place files inside document root and make absolute reference to them in HeaderName directive and in header file. After files are created and Apache is configured, you should have a styled directory listing page.
I hope you might find this post useful.
Cheers!
Related posts
- Create XML from directory list with Apache
- Hide parent directory in Apache
- From MySQL to HTML with PHP and XML
- Log PHP errors to the separate file
- From MySQL to XML with PHP
How do I get the "root-style" for directories within my root-files-directory, Did I miss something?
And is it possible to have icons for mime-types? Thy are linked in the sites source, but do not appear on the site itself.
Apart from that, very nice! And thanks in advance!
@dirch - You have to set Indexes in Options directive, otherwise Apache will return "HTTP 403 - Forbidden" instead of directory list. More about Options can be read on Options Directive. Mime-type icons should be displayed by default after enabling directory listing. In Fedora distribution, icons are located in /var/www/icons and the icon mapping is defined in httpd.conf by AddIcon* directives.
Thanks for your reply!
To be more precise, and maybe you find my mistake, here is the link to my files directory http://mjhp.net/files/ . As you can see there are no icons. In the source i saw that they are expected to be in /icons, so i've created that one and copied a set of icons there (of course they are readable by everyone).
My .htaccess looks like that:
Options +Indexes
IndexOptions FancyIndexing
IndexOptions XHTML
IndexOptions HTMLtable
IndexOptions SuppressHTMLPreamble
IndexOptions SuppressColumnSorting
IndexOptions FoldersFirst
IndexOptions IconsAreLinks
IndexOptions NameWidth=*
IndexOptions Type=text/xml
IndexIgnore ..
HeaderName HEADER.html
The other files (stylesheet an HEADER.html are copied from your site.
ah, the server is running FreeBSD 7.1-STABLE
Thanks!
@dirch - Error was in stylesheet.xsl in "tr" template. Please look at the first xsl:copy-of line (responsible for the column with icons).
Before todays update, line was looked like:
<td align="center"><xsl:copy-of select="td[position()=1]/img"/></td>
and that was wrong. So, if you need icon and link, you should please replace "img" with "*" (as I updated stylesheet.xsl in this post)
<td align="center"><xsl:copy-of select="td[position()=1]/*"/></td>
Or if you need only icon, then you can write "a/img".
<td align="center"><xsl:copy-of select="td[position()=1]/a/img"/></td>
Thank you for pointing to the icon problem.
Bye!
It's me who has to thank you!
My other "problem" looks like that http://mjhp.net/files/nostyle/. As you can see there is no style at all. Of course i could put my header and all that into every directory i create, but maybe there is another option to have the same style in the root directory and all subdirectories.
@dirch - I think you have to set absolute path to the HEADER.html file. Instead of:
HeaderName HEADER.html
try with:
HeaderName /files/HEADER.html
Hope this will solve problem and all subdirectories will be styled as root dir.
Thats it. Sometimes i wonder how dumb me can be... Thanks a lot!
btw: really nice site, keep up the good work!
[...] http://www.redips.net/apache/styling-directory-listings/comment-page-1/ [...]