Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

List server directory using JavaScript XHR

When I asked the question can javascript list files on the server, everyone answered with "javascript cannot access server filesystem because it is a client-side scripting language". But I thought that answer is only partially true, because browser can list the contents of the server directory if dirlisting is enabled. So, I decided to try to parse that output - no need to use cgi when you can already see the data you need in xml format. So here is what I did:

I am using lighttpd, and important entries in lighttpd.conf are:

dir-listing.activate    = "enable"                 #enables directory listing
dir-listing.auto-layout = "disable"                #simplifies the list style
mimetype.assign         = ( ".xml" => "text/xml" ) #deals with xmls

test.xml used to test XHR looks like this:

<?xml version="1.0"?>
<anchors>
 <a>foo</a>
 <a>bar</a>
</anchors>

Directory listing page, created by lighttpd mod_dirlisting.so:

<?xml version="1.0" encoding="iso-8859-1"?>
<h2>Index of /directory/</h2>
<div class="list">
<table summary="Directory Listing" cellpadding="0" cellspacing="0">
<thead><tr><th class="n">Name</th><th class="m">Last Modified</th><th class="s">Size</th><th class="t">Type</th></tr></thead>
<tbody>
<tr><td class="n"><a href="../">Parent Directory</a>/</td><td class="m">&nbsp;</td><td class="s">- &nbsp;</td><td class="t">Directory</td></tr>
<tr><td class="n"><a href="foo">foo</a></td><td class="m">2015-Jan-03 13:24:12</td><td class="s">39.4K</td><td class="t">application/octet-stream</td></tr>
</tbody>
</table>
</div>

test.html page used to create XHR:

<html><head></head><body><script>

 if (window.XMLHttpRequest) var request = new XMLHttpRequest();
 else var request = new ActiveXObject('Microsoft.XMLHTTP');
 request.open('post', 'test.xml', true);
 request.send();
 if (request) request.onreadystatechange = function() alert(request.responseXML.getElementsByTagName('a')[1].childNodes[0].nodeValue);

</script></body></html>

All of which work fine (you get 'foo' in an alert box), but when I request.open directory instead of xml, I get nothing, not even in error console.

like image 650
Ulrik Avatar asked Oct 19 '22 19:10

Ulrik


1 Answers

You have a couple of issues with your code. For starters, in your JavaScript you are accessing request.responseXML before request.readyState is 4. At this point, that property should not be available, so you should be getting some errors on that. This can be fixed fairly easily.

if (window.XMLHttpRequest) var request = new XMLHttpRequest();
else var request = new ActiveXObject('Microsoft.XMLHTTP');

request.open('post', 'dir/', true);
request.send();

request.onreadystatechange = function() {
    if (request.readyState === 4) {
        alert(request.responseXML.getElementsByTagName('a')[1].childNodes[0].nodeValue);
    }
}

However, you have another issue. You are trying to parse your output as XML, but it is not a valid XML document, or a valid HTML document for that matter. You would need to have another element wrapping the output for it to be a valid XML document, as there can only be one root node. Additionally, &nbsp; is not supported in XML, so that would also need to be removed or replaced. Something like the following would work.

<?xml version="1.0" encoding="iso-8859-1"?>
<xml>
<h2>Index of /directory/</h2>
<div class="list">
<table summary="Directory Listing" cellpadding="0" cellspacing="0">
<thead><tr><th class="n">Name</th><th class="m">Last Modified</th><th class="s">Size</th><th class="t">Type</th></tr></thead>
<tbody>
<tr><td class="n"><a href="../">Parent Directory</a>/</td><td class="m"></td><td class="s">- </td><td class="t">Directory</td></tr>
<tr><td class="n"><a href="foo">foo</a></td><td class="m">2015-Jan-03 13:24:12</td><td class="s">39.4K</td><td class="t">application/octet-stream</td></tr>
</tbody>
</table>
</div>
</xml>

You might also be interested in using the responseType property of the XMLHttpRequest. If you set this property to 'document', you can parse HTML response, rather than XML response.

request.open('post', 'dir/', true);
request.responseType = 'document';
request.send();
like image 132
Alexander O'Mara Avatar answered Oct 22 '22 09:10

Alexander O'Mara