1 <!DOCTYPE html PUBLIC
"-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
4 <meta content=
"text/html; charset=iso-8859-1" http-equiv=
"Content-Type">
5 <script language=
"javascript">
6 // Split a string in 2 parts. The first is the leading number, if any,
7 // the second is the string following the numbers.
9 var results
= new Array();
11 for (var i
= 0; i
< s
.length
; i
++) {
12 var substr
= s
.substr(0, i
+1)
14 // Not a number anymore.
15 results
[1] = s
.substr(i
)
18 // This is a number. update the results.
19 results
[0] = parseFloat(substr
);
25 // Compare 2 strings using a custom alphanumerical algorithm.
26 // This is similar to a normal string sort, except that we sort
27 // first by leading digits, if any.
29 // 100hello > 2goodbye
30 // Numbers anywhere else in the string are compared using the normal
32 function alphanumCompare(a
, b
) {
33 var parsedA
= splitNum(a
);
34 var parsedB
= splitNum(b
);
35 var numA
= parsedA
[0];
36 var numB
= parsedB
[0];
37 var strA
= parsedA
[1];
38 var strB
= parsedB
[1];
40 if (isNaN(numA
) == false && isNaN(numB
) == false) {
41 // They both start with numbers.
42 if (numA
< numB
) return -1;
43 if (numA
> numB
) return 1;
44 // Identical. Fallback to string.
45 return (strA
< strB
) ? -1 : (strA
> strB
? 1 : 0)
48 // If only one starts with a number, we start with that one as
50 if (isNaN(numA
) == false) return -1
51 if (isNaN(numB
) == false) return 1
53 // They are both strings.
54 return (a
< b
) ? -1 : (a
> b
? 1 : 0)
59 <script type=
"application/javascript">
60 String.prototype.startsWith = function(str) {
61 return (this.match('^' + str) == str)
64 // Helper function to retrieve the value of a GET query parameter.
65 // Greatly inspired from http://alturl.com/
8rj7a
66 function getParameter(parameterName) {
67 // Add '=' to the parameter name (i.e. parameterName=value)
68 var parameterName = parameterName + '=';
69 var queryString = window.location.search.substring(
1);
70 if (queryString.length <=
0) {
74 // Find the beginning of the string
75 begin = queryString.indexOf(parameterName);
77 // If the parameter name is not found, skip it, otherwise return the
83 // Add the length (integer) to the beginning.
84 begin += parameterName.length;
86 // Multiple parameters are separated by the '&' sign.
87 end = queryString.indexOf ('&', begin);
90 end = queryString.length;
94 return unescape(queryString.substring(begin, end));
97 // Given a tag and a node, returns the value for this tag on this node.
98 function getNodeValue(node, tag) {
99 return node.getElementsByTagName(tag)[
0].firstChild.nodeValue;
102 // Displays the directory listing given the XML and path.
103 function displayList(xmlstring, root, path, pathRoot) {
104 // Display the header
105 document.write('
<h1>Index of /' + path + '
</h1>');
107 // Start the table for the results.
108 document.write('
<table style=
"border-spacing:15px 0px;">');
110 var sortOrder = getParameter('sort');
111 var sortLink = location.pathname + '?path=' + path;
112 if (sortOrder != 'desc') {
113 sortLink += '&sort=desc';
116 // Display the table header.
117 document.write('
<tr><th><img src=
"' + root + pathRoot +
118 'icons/blank.gif" alt=
"[ICO]"></th>');
119 document.write('
<th><a href=
"' + sortLink + '">Name
</a></th>');
120 document.write('
<th>Last modified
</th>');
121 document.write('
<th>Size
</th>');
122 document.write('
<th>Storage Class
</th>');
123 document.write('
<th>ETag
</th></tr>');
124 document.write('
<tr><th colspan=
"6"><hr></th></tr>');
126 // Display the 'go back' button.
128 var backpath = location.pathname;
130 // If there is more than one section delimited by '/' in the current
131 // path we truncate the last section and append the rest to backpath.
132 var delimiter = path.lastIndexOf('/');
133 if (delimiter
>=
0) {
134 delimiter = path.substr(
0, delimiter).lastIndexOf('/');
135 if (delimiter
>=
0) {
136 backpath += '?path=';
137 backpath += path.substr(
0, delimiter+
1);
141 document.write('
<tr><td valign=
"top"><img src=
"' + root + pathRoot +
142 'icons/back.gif" alt=
"[DIR]"></td>');
143 document.write('
<td><a href=
"');
144 document.write(backpath);
145 document.write('">Parent Directory
</a></td>');
146 document.write('
<td> </td>');
147 document.write('
<td align=
"right"> -
</td></tr>');
150 // Set up the variables.
151 var directories = new Array();
152 var files = new Array();
154 for (var iter =
0; iter < xmlstrings.length; iter++) {
155 var xmlstring = xmlstrings[iter];
156 // Parse the XML output.
157 var parser = new DOMParser();
158 var xmlDoc = parser.parseFromString(xmlstring, 'text/xml');
160 // Get the main element.
161 var results = xmlDoc.getElementsByTagName('ListBucketResult');
163 // Get all the directories.
164 var prefixes = results[
0].getElementsByTagName('CommonPrefixes');
165 for (var i =
0; i < prefixes.length; i++) {
166 var prefix = getNodeValue(prefixes[i], 'Prefix');
167 directories.push(prefix.substr(path.length));
170 // Get all the files.
171 var contents = results[
0].getElementsByTagName('Contents');
172 for (var i =
0; i < contents.length; i++) {
173 var obj = new Object();
174 obj.keyName = getNodeValue(contents[i], 'Key');
175 obj.lastModified = getNodeValue(contents[i], 'LastModified');
176 obj.eTag = getNodeValue(contents[i], 'ETag');
177 obj.size = getNodeValue(contents[i], 'Size');
182 files.sort(alphanumCompare);
183 directories.sort(alphanumCompare);
185 // Reverse the list for a descending sort.
186 if (sortOrder == 'desc') {
188 directories.reverse();
191 // Display the directories.
192 for (var i =
0; i < directories.length; i++) {
193 var lnk = location.pathname.substr(
0, location.pathname.indexOf('?'));
194 lnk += '?path=' + path + directories[i];
196 document.write('
<tr>');
197 document.write('
<td valign=
"top"><img src=
"' + root + pathRoot +
198 'icons/folder.gif" alt=
"[DIR]"></td>');
199 document.write('
<td><a href=
"' + lnk + '">' +
200 directories[i].split('/')[
0] + '
</a></td>');
201 document.write('
<td align=
"right">-
</td>');
202 document.write('
<td align=
"right">-
</td>');
203 document.write('
<td align=
"right">-
</td>');
204 document.write('
<td align=
"right">-
</td>');
205 document.write('
</tr>');
208 // Display the files.
209 for (var i =
0; i < files.length; i++) {
210 var link = root + files[i].keyName;
211 var filename = files[i].keyName.substr(path.length);
212 var size = files[i].size /
1024 /
1024;
213 var lastModified = files[i].lastModified.replace('T', ' ');
214 lastModified = lastModified.substr(
0, lastModified.indexOf('.'));
216 // Remove the entries we don't want to show.
217 if (filename == '') {
221 if (filename.indexOf('$folder$')
>=
0) {
226 document.write('
<tr>');
227 document.write('
<td valign=
"top"><img src=
"' + root + pathRoot +
228 'icons/binary.gif" alt=
"[DIR]"></td>');
229 document.write('
<td><a href=
"' + link + '">' + filename +
231 document.write('
<td align=
"right">' + lastModified + '
</td>');
232 document.write('
<td align=
"right">' + size.toFixed(
2) + 'MB
</td>');
233 document.write('
<td align=
"right"><pre>' +
234 files[i].eTag.split('
"')[1] + '</pre></td>');
235 document.write('</tr>');
239 document.write('<tr><th colspan="6"><hr></th></tr>');
240 document.write('</table>');
243 var xmlstrings = new Array();
245 function fetchAndDisplay(marker) {
246 var path = getParameter('path');
247 var lastSlash = location.pathname.lastIndexOf("/
");
248 var filename = location.pathname.substring(lastSlash + 1);
249 var firstSlash = location.pathname.indexOf("/
", 1);
250 var root = location.pathname.substring(0, firstSlash + 1);
251 var pathRoot = location.pathname.substring(firstSlash + 1,
254 path = location.pathname.substring(firstSlash + 1, lastSlash + 1);
257 var markerParam = '';
259 markerParam = '&marker=' + marker;
262 var http = new XMLHttpRequest();
264 root + '?delimiter=/&prefix=' + path + markerParam,
266 http.onreadystatechange = useHttpResponse;
268 function useHttpResponse() {
269 if (http.readyState == 4) {
270 var xmlstring = http.responseText;
271 xmlstrings.push(xmlstring);
273 // Check if the data is truncated. if so, we need to request the
275 var parser = new DOMParser();
276 var xmlDoc = parser.parseFromString(xmlstring, 'text/xml');
278 // Get the main element.
279 var results = xmlDoc.getElementsByTagName('ListBucketResult');
282 var truncated = getNodeValue(results[0], 'IsTruncated');
284 if (truncated == 'true') {
285 nextMarker = getNodeValue(results[0], 'NextMarker');
286 fetchAndDisplay(nextMarker);
288 displayList(xmlstrings, root, path, pathRoot);