| 1 | module file |
| 2 | |
| 3 | import os |
| 4 | import time |
| 5 | import strings |
| 6 | |
| 7 | const myexe = os.executable() |
| 8 | const myexe_prefix = os.file_name(myexe.all_before_last('.')) |
| 9 | |
| 10 | fn get_folder_index_html(requested_file_path string, uri_path string, filter_myexe bool) string { |
| 11 | sw := time.new_stopwatch() |
| 12 | mut files := os.ls(requested_file_path) or { [] } |
| 13 | if filter_myexe { |
| 14 | files = files.filter(!it.contains(myexe_prefix)) |
| 15 | } |
| 16 | mut sb := strings.new_builder(files.len * 200) |
| 17 | write_page_header(mut sb, uri_path) |
| 18 | write_page_crumbs(mut sb, uri_path) |
| 19 | write_page_table(mut sb, uri_path, requested_file_path, mut files) |
| 20 | sb.writeln('<p>Server time: <b>${time.now().format_ss()}</b>, generated in <b>${sw.elapsed().microseconds():6}µs</b></p>') |
| 21 | write_page_footer(mut sb, uri_path) |
| 22 | return sb.str() |
| 23 | } |
| 24 | |
| 25 | fn write_page_header(mut sb strings.Builder, uri_path string) { |
| 26 | // html boilerplate for the header |
| 27 | sb.writeln('<!DOCTYPE html>') |
| 28 | sb.writeln('<html lang="en">') |
| 29 | sb.writeln('<head>') |
| 30 | sb.writeln('<meta charset="utf-8">') |
| 31 | sb.writeln('<title>Index of local folder ${uri_path}</title>') |
| 32 | sb.writeln('<link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon" />') |
| 33 | sb.writeln('</head>') |
| 34 | sb.writeln('<body>') |
| 35 | } |
| 36 | |
| 37 | fn write_page_footer(mut sb strings.Builder, _uri_path string) { |
| 38 | // html boilerplate for the footer |
| 39 | sb.writeln('</body>') |
| 40 | sb.writeln('</html>') |
| 41 | } |
| 42 | |
| 43 | fn write_page_crumbs(mut sb strings.Builder, uri_path string) { |
| 44 | crumbs := uri_path.split('/') |
| 45 | mut crlinks := []string{cap: crumbs.len} |
| 46 | for cridx, crumb in crumbs { |
| 47 | cr_so_far := crumbs#[0..cridx + 1].join('/') |
| 48 | // eprintln('> cr_so_far: ${cr_so_far:20} | crumb: ${crumb:20}') |
| 49 | crlinks << '<a href="/${cr_so_far}">${crumb}</a>' |
| 50 | } |
| 51 | crlinks_text := crlinks.join(' / ') |
| 52 | sb.writeln('<h2>Index of <a href="/">/</a> ${crlinks_text} :</h2>') |
| 53 | } |
| 54 | |
| 55 | fn write_page_table(mut sb strings.Builder, uri_path string, requested_file_path string, mut files []string) { |
| 56 | files.sort() |
| 57 | sb.writeln('<table>') |
| 58 | sb.writeln('<tr>') |
| 59 | sb.writeln('<th align="left" style="width: 100px">Size</th>') |
| 60 | sb.writeln('<th align="left" style="width: 200px">Last modified</th>') |
| 61 | sb.writeln('<th align="left">Name</th>') |
| 62 | sb.writeln('</tr>') |
| 63 | if uri_path == '' { |
| 64 | sb.writeln('<tr>') |
| 65 | sb.writeln('<td>---</td>') |
| 66 | sb.writeln('<td>---</td>') |
| 67 | sb.writeln('<td>---</td>') |
| 68 | sb.writeln('</tr>') |
| 69 | } else { |
| 70 | sb.writeln('<tr>') |
| 71 | sb.writeln('<td></td>') |
| 72 | sb.writeln('<td></td>') |
| 73 | sb.writeln('<td><a href="/${uri_path}/..">..</td>') |
| 74 | sb.writeln('</tr>') |
| 75 | } |
| 76 | mut entities := []Entity{cap: files.len} |
| 77 | for fname in files { |
| 78 | path := os.join_path(requested_file_path, fname) |
| 79 | entities << path_to_entity(path, uri_path) |
| 80 | } |
| 81 | entities.sort_with_compare(fn (a &Entity, b &Entity) int { |
| 82 | if a.typ == b.typ { |
| 83 | if a.fname < b.fname { |
| 84 | return -1 |
| 85 | } |
| 86 | if a.fname > b.fname { |
| 87 | return 1 |
| 88 | } |
| 89 | return 0 |
| 90 | } |
| 91 | if a.typ == .directory { |
| 92 | return -1 |
| 93 | } |
| 94 | return 1 |
| 95 | }) |
| 96 | for entity in entities { |
| 97 | if entity.typ == .directory { |
| 98 | sb.writeln('<tr>') |
| 99 | sb.writeln('<td></td>') |
| 100 | sb.writeln('<td>${entity.mod_time.format_ss()}</td>') |
| 101 | sb.writeln('<td><a href="${entity.url}">${entity.fname}/</a></td>') |
| 102 | sb.writeln('</tr>') |
| 103 | } else if entity.typ == .symbolic_link { |
| 104 | sb.writeln('<tr>') |
| 105 | sb.writeln('<td>${entity.size}</td>') |
| 106 | sb.writeln('<td>${entity.mod_time.format_ss()}</td>') |
| 107 | sb.writeln('<td><a href="${entity.url}">${entity.fname}@</a></td>') |
| 108 | sb.writeln('</tr>') |
| 109 | } else { |
| 110 | sb.writeln('<tr>') |
| 111 | sb.writeln('<td>${entity.size}</td>') |
| 112 | sb.writeln('<td>${entity.mod_time.format_ss()}</td>') |
| 113 | sb.writeln('<td><a href="${entity.url}">${entity.fname}</a></td>') |
| 114 | sb.writeln('</tr>') |
| 115 | } |
| 116 | } |
| 117 | sb.writeln('</table>') |
| 118 | } |
| 119 | |