<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta content="text/html; charset=iso-8859-1" http-equiv="Content-Type">
<script language="javascript">
// Split a string in 2 parts. The first is the leading number, if any,
// the second is the string following the numbers.
function splitNum(s) {
var results = new Array();
results[0] = 'None';
for (var i = 0; i < s.length; i++) {
var substr = s.substr(0, i+1)
if (isNaN(substr)) {
// Not a number anymore.
results[1] = s.substr(i)
break;
} else {
// This is a number. update the results.
results[0] = parseFloat(substr);
}
}
return results;
}
// Compare 2 strings using a custom alphanumerical algorithm.
// This is similar to a normal string sort, except that we sort
// first by leading digits, if any.
// For example:
// 100hello > 2goodbye
// Numbers anywhere else in the string are compared using the normal
// sort algorithm.
function alphanumCompare(a, b) {
var parsedA = splitNum(a);
var parsedB = splitNum(b);
var numA = parsedA[0];
var numB = parsedB[0];
var strA = parsedA[1];
var strB = parsedB[1];
if (isNaN(numA) == false && isNaN(numB) == false) {
// They both start with numbers.
if (numA < numB) return -1;
if (numA > numB) return 1;
// Identical. Fallback to string.
return (strA < strB) ? -1 : (strA > strB ? 1 : 0)
}
// If only one starts with a number, we start with that one as
// the lowest.
if (isNaN(numA) == false) return -1
if (isNaN(numB) == false) return 1
// They are both strings.
return (a < b) ? -1 : (a > b ? 1 : 0)
}
</script>
</head>
<body>
<script type="application/javascript">
String.prototype.startsWith = function(str) {
return (this.match('^' + str) == str)
}
// Helper function to retrieve the value of a GET query parameter.
// Greatly inspired from http://alturl.com/8rj7a
function getParameter(parameterName) {
// Add '=' to the parameter name (i.e. parameterName=value)
var parameterName = parameterName + '=';
var queryString = window.location.search.substring(1);
if (queryString.length <= 0) {
return '';
}
// Find the beginning of the string
begin = queryString.indexOf(parameterName);
// If the parameter name is not found, skip it, otherwise return the
// value.
if (begin == -1) {
return '';
}
// Add the length (integer) to the beginning.
begin += parameterName.length;
// Multiple parameters are separated by the '&' sign.
end = queryString.indexOf ('&', begin);
if (end == -1) {
end = queryString.length;
}
// Return the string.
return unescape(queryString.substring(begin, end));
}
// Given a tag and a node, returns the value for this tag on this node.
function getNodeValue(node, tag) {
return node.getElementsByTagName(tag)[0].firstChild.nodeValue;
}
// Displays the directory listing given the XML and path.
function displayList(xmlstring, root, path, pathRoot) {
// Display the header
document.write('<h1>Index of /' + path + '</h1>');
// Start the table for the results.
document.write('<table style="border-spacing:15px 0px;">');
var sortOrder = getParameter('sort');
var sortLink = location.pathname + '?path=' + path;
if (sortOrder != 'desc') {
sortLink += '&sort=desc';
}
// Display the table header.
document.write('<tr><th><img src="' + root + pathRoot +
'icons/blank.gif" alt="[ICO]"></th>');
document.write('<th><a href="' + sortLink + '">Name</a></th>');
document.write('<th>Last modified</th>');
document.write('<th>Size</th>');
document.write('<th>Storage Class</th>');
document.write('<th>ETag</th></tr>');
document.write('<tr><th colspan="6"><hr></th></tr>');
// Display the 'go back' button.
if (path != '') {
var backpath = location.pathname;
// If there is more than one section delimited by '/' in the current
// path we truncate the last section and append the rest to backpath.
var delimiter = path.lastIndexOf('/');
if (delimiter >= 0) {
delimiter = path.substr(0, delimiter).lastIndexOf('/');
if (delimiter >= 0) {
backpath += '?path=';
backpath += path.substr(0, delimiter+1);
}
}
document.write('<tr><td valign="top"><img src="' + root + pathRoot +
'icons/back.gif" alt="[DIR]"></td>');
document.write('<td><a href="');
document.write(backpath);
document.write('">Parent Directory</a></td>');
document.write('<td> </td>');
document.write('<td align="right"> - </td></tr>');
}
// Set up the variables.
var directories = new Array();
var files = new Array();
for (var iter = 0; iter < xmlstrings.length; iter++) {
var xmlstring = xmlstrings[iter];
// Parse the XML output.
var parser = new DOMParser();
var xmlDoc = parser.parseFromString(xmlstring, 'text/xml');
// Get the main element.
var results = xmlDoc.getElementsByTagName('ListBucketResult');
// Get all the directories.
var prefixes = results[0].getElementsByTagName('CommonPrefixes');
for (var i = 0; i < prefixes.length; i++) {
var prefix = getNodeValue(prefixes[i], 'Prefix');
directories.push(prefix.substr(path.length));
}
// Get all the files.
var contents = results[0].getElementsByTagName('Contents');
for (var i = 0; i < contents.length; i++) {
var obj = new Object();
obj.keyName = getNodeValue(contents[i], 'Key');
obj.lastModified = getNodeValue(contents[i], 'LastModified');
obj.eTag = getNodeValue(contents[i], 'ETag');
obj.size = getNodeValue(contents[i], 'Size');
files.push(obj);
}
}
files.sort(alphanumCompare);
directories.sort(alphanumCompare);
// Reverse the list for a descending sort.
if (sortOrder == 'desc') {
files.reverse();
directories.reverse();
}
// Display the directories.
for (var i = 0; i < directories.length; i++) {
var lnk = location.pathname.substr(0, location.pathname.indexOf('?'));
lnk += '?path=' + path + directories[i];
document.write('<tr>');
document.write('<td valign="top"><img src="' + root + pathRoot +
'icons/folder.gif" alt="[DIR]"></td>');
document.write('<td><a href="' + lnk + '">' +
directories[i].split('/')[0] + '</a></td>');
document.write('<td align="right">-</td>');
document.write('<td align="right">-</td>');
document.write('<td align="right">-</td>');
document.write('<td align="right">-</td>');
document.write('</tr>');
}
// Display the files.
for (var i = 0; i < files.length; i++) {
var link = root + files[i].keyName;
var filename = files[i].keyName.substr(path.length);
var size = files[i].size / 1024 / 1024;
var lastModified = files[i].lastModified.replace('T', ' ');
lastModified = lastModified.substr(0, lastModified.indexOf('.'));
// Remove the entries we don't want to show.
if (filename == '') {
continue;
}
if (filename.indexOf('$folder$') >= 0) {
continue;
}
// Display the row.
document.write('<tr>');
document.write('<td valign="top"><img src="' + root + pathRoot +
'icons/binary.gif" alt="[DIR]"></td>');
document.write('<td><a href="' + link + '">' + filename +
'</a></td>');
document.write('<td align="right">' + lastModified + '</td>');
document.write('<td align="right">' + size.toFixed(2) + 'MB</td>');
document.write('<td align="right"><pre>' +
files[i].eTag.split('"')[1] + '</pre></td>');
document.write('</tr>');
}
// Close the table.
document.write('<tr><th colspan="6"><hr></th></tr>');
document.write('</table>');
}
var xmlstrings = new Array();
function fetchAndDisplay(marker) {
var path = getParameter('path');
var lastSlash = location.pathname.lastIndexOf("/");
var filename = location.pathname.substring(lastSlash + 1);
var firstSlash = location.pathname.indexOf("/", 1);
var root = location.pathname.substring(0, firstSlash + 1);
var pathRoot = location.pathname.substring(firstSlash + 1,
lastSlash + 1);
if (!path) {
path = location.pathname.substring(firstSlash + 1, lastSlash + 1);
}
var markerParam = '';
if (marker != '') {
markerParam = '&marker=' + marker;
}
var http = new XMLHttpRequest();
http.open('GET',
root + '?delimiter=/&prefix=' + path + markerParam,
true);
http.onreadystatechange = useHttpResponse;
http.send(null);
function useHttpResponse() {
if (http.readyState == 4) {
var xmlstring = http.responseText;
xmlstrings.push(xmlstring);
// Check if the data is truncated. if so, we need to request the
// rest.
var parser = new DOMParser();
var xmlDoc = parser.parseFromString(xmlstring, 'text/xml');
// Get the main element.
var results = xmlDoc.getElementsByTagName('ListBucketResult');
// Get IsTruncated.
var truncated = getNodeValue(results[0], 'IsTruncated');
var nextMarker = '';
if (truncated == 'true') {
nextMarker = getNodeValue(results[0], 'NextMarker');
fetchAndDisplay(nextMarker);
} else {
displayList(xmlstrings, root, path, pathRoot);
}
}
}
}
fetchAndDisplay('');
</script>
</body>
</html>