JavaScript: List Directory Contents With Apache Indexes

This can be useful if you are writing something that is entirely client-side and has to list the contents of directories on the web server. The only limitations are that:

  • the web server has to be running Apache with directory indexes enabled;
  • the directory to list has an index (e.g. there is no ‘index.html’ file in it); and
  • the directory to list has to be on the same domain as the script (browser security policies don’t allow cross site requests).
    Here is the code. It uses JQuery to make a AJAX request to the Apache directory index, and then parses it for links to the directory’s contents.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/*
 * Returns a list of the files in 'path' to the callback:
 * cb(error, ['file1', 'file2', ...])
 */
function apacheIndexList(path, cb) {
  $.ajax({
    url: path,
    success: function(data) {
      /* Sanity check: is this an Apache directory index?
       */
      data = $('<html>').html(data);
      if($('title', data)[0].innerHTML.substr(0, 8) !==
        "Index of")
        return cb("Bad Apache directory index: " + path);
      /* Get all the hrefs after the "Parent Directory"
       * link: these are the contents of the directory.
       */
      var passedParentLink = false;
      var files = $('a', data).filter(function(i, a) {
        if(passedParentLink)
          return true;
        if(a.innerHTML.trim() === "Parent Directory")
           passedParentLink = true;
        return false;
      });
      var tidied = $(files).map(function(i, a) {
        if(a.href.substr(-1) === '/')
            return a.href.split('/').slice(-2,-1) + '/';
        return a.href.split('/').pop();
      });
      cb(null, tidied);
    },
    error: function(jqXHR, error, errorThrown) {
      cb(error);
    }
  });
}

This can be tested on the console. First define a function ls:

1
2
3
4
5
6
function ls(d) {
apacheIndexList(d, function(e, l) {
if(e) throw e;
else console.log(l);
});
}

Then try listing the contents of some directories:

1
2
3
4
5
6
7
> ls('images/')
&lt; undefined
["img1.jpg", "img2.jpg", "img3.jpg", "thumbs/"]
> ls('images/thumbs/')
&lt; undefined
["img1.jpg", "img2.jpg", "img3.jpg"]