v / vlib / net / http / file / folder_index.v
118 lines · 111 sloc · 3.58 KB · 808ede5d9d00c8f2c218788c2ce74007a983507a
Raw
1module file
2
3import os
4import time
5import strings
6
7const myexe = os.executable()
8const myexe_prefix = os.file_name(myexe.all_before_last('.'))
9
10fn 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
25fn 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
37fn 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
43fn 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
55fn 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