OLD | NEW |
(Empty) | |
| 1 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/st
rict.dtd"> |
| 2 <html> |
| 3 <head> |
| 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. |
| 8 function splitNum(s) { |
| 9 var results = new Array(); |
| 10 results[0] = 'None'; |
| 11 for (var i = 0; i < s.length; i++) { |
| 12 var substr = s.substr(0, i+1) |
| 13 if (isNaN(substr)) { |
| 14 // Not a number anymore. |
| 15 results[1] = s.substr(i) |
| 16 break; |
| 17 } else { |
| 18 // This is a number. update the results. |
| 19 results[0] = parseFloat(substr); |
| 20 } |
| 21 } |
| 22 return results; |
| 23 } |
| 24 |
| 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. |
| 28 // For example: |
| 29 // 100hello > 2goodbye |
| 30 // Numbers anywhere else in the string are compared using the normal |
| 31 // sort algorithm. |
| 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]; |
| 39 |
| 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) |
| 46 } |
| 47 |
| 48 // If only one starts with a number, we start with that one as |
| 49 // the lowest. |
| 50 if (isNaN(numA) == false) return -1 |
| 51 if (isNaN(numB) == false) return 1 |
| 52 |
| 53 // They are both strings. |
| 54 return (a < b) ? -1 : (a > b ? 1 : 0) |
| 55 } |
| 56 </script> |
| 57 </head> |
| 58 <body> |
| 59 <script type="application/javascript"> |
| 60 String.prototype.startsWith = function(str) { |
| 61 return (this.match('^' + str) == str) |
| 62 } |
| 63 |
| 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) { |
| 71 return ''; |
| 72 } |
| 73 |
| 74 // Find the beginning of the string |
| 75 begin = queryString.indexOf(parameterName); |
| 76 |
| 77 // If the parameter name is not found, skip it, otherwise return the |
| 78 // value. |
| 79 if (begin == -1) { |
| 80 return ''; |
| 81 } |
| 82 |
| 83 // Add the length (integer) to the beginning. |
| 84 begin += parameterName.length; |
| 85 |
| 86 // Multiple parameters are separated by the '&' sign. |
| 87 end = queryString.indexOf ('&', begin); |
| 88 |
| 89 if (end == -1) { |
| 90 end = queryString.length; |
| 91 } |
| 92 |
| 93 // Return the string. |
| 94 return unescape(queryString.substring(begin, end)); |
| 95 } |
| 96 |
| 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; |
| 100 } |
| 101 |
| 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>'); |
| 106 |
| 107 // Start the table for the results. |
| 108 document.write('<table style="border-spacing:15px 0px;">'); |
| 109 |
| 110 var sortOrder = getParameter('sort'); |
| 111 var sortLink = location.pathname + '?path=' + path; |
| 112 if (sortOrder != 'desc') { |
| 113 sortLink += '&sort=desc'; |
| 114 } |
| 115 |
| 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>'); |
| 125 |
| 126 // Display the 'go back' button. |
| 127 if (path != '') { |
| 128 var backpath = location.pathname; |
| 129 |
| 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); |
| 138 } |
| 139 } |
| 140 |
| 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>'); |
| 148 } |
| 149 |
| 150 // Set up the variables. |
| 151 var directories = new Array(); |
| 152 var files = new Array(); |
| 153 |
| 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'); |
| 159 |
| 160 // Get the main element. |
| 161 var results = xmlDoc.getElementsByTagName('ListBucketResult'); |
| 162 |
| 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)); |
| 168 } |
| 169 |
| 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'); |
| 178 files.push(obj); |
| 179 } |
| 180 } |
| 181 |
| 182 files.sort(alphanumCompare); |
| 183 directories.sort(alphanumCompare); |
| 184 |
| 185 // Reverse the list for a descending sort. |
| 186 if (sortOrder == 'desc') { |
| 187 files.reverse(); |
| 188 directories.reverse(); |
| 189 } |
| 190 |
| 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]; |
| 195 |
| 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>'); |
| 206 } |
| 207 |
| 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('.')); |
| 215 |
| 216 // Remove the entries we don't want to show. |
| 217 if (filename == '') { |
| 218 continue; |
| 219 } |
| 220 |
| 221 if (filename.indexOf('$folder$') >= 0) { |
| 222 continue; |
| 223 } |
| 224 |
| 225 // Display the row. |
| 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 + |
| 230 '</a></td>'); |
| 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>'); |
| 236 } |
| 237 |
| 238 // Close the table. |
| 239 document.write('<tr><th colspan="6"><hr></th></tr>'); |
| 240 document.write('</table>'); |
| 241 } |
| 242 |
| 243 var xmlstrings = new Array(); |
| 244 |
| 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, |
| 252 lastSlash + 1); |
| 253 if (!path) { |
| 254 path = location.pathname.substring(firstSlash + 1, lastSlash + 1); |
| 255 } |
| 256 |
| 257 var markerParam = ''; |
| 258 if (marker != '') { |
| 259 markerParam = '&marker=' + marker; |
| 260 } |
| 261 |
| 262 var http = new XMLHttpRequest(); |
| 263 http.open('GET', |
| 264 root + '?delimiter=/&prefix=' + path + markerParam, |
| 265 true); |
| 266 http.onreadystatechange = useHttpResponse; |
| 267 http.send(null); |
| 268 function useHttpResponse() { |
| 269 if (http.readyState == 4) { |
| 270 var xmlstring = http.responseText; |
| 271 xmlstrings.push(xmlstring); |
| 272 |
| 273 // Check if the data is truncated. if so, we need to request the |
| 274 // rest. |
| 275 var parser = new DOMParser(); |
| 276 var xmlDoc = parser.parseFromString(xmlstring, 'text/xml'); |
| 277 |
| 278 // Get the main element. |
| 279 var results = xmlDoc.getElementsByTagName('ListBucketResult'); |
| 280 |
| 281 // Get IsTruncated. |
| 282 var truncated = getNodeValue(results[0], 'IsTruncated'); |
| 283 var nextMarker = ''; |
| 284 if (truncated == 'true') { |
| 285 nextMarker = getNodeValue(results[0], 'NextMarker'); |
| 286 fetchAndDisplay(nextMarker); |
| 287 } else { |
| 288 displayList(xmlstrings, root, path, pathRoot); |
| 289 } |
| 290 } |
| 291 } |
| 292 } |
| 293 |
| 294 fetchAndDisplay(''); |
| 295 </script> |
| 296 </body> |
| 297 </html> |
OLD | NEW |