1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
import algorithm
import os
import streams
import times
import loader/connecterror
import loader/dirlist
import loader/headers
import loader/loaderhandle
import types/url
proc loadDir(handle: LoaderHandle, url: URL, path: string) =
template t(body: untyped) =
if not body:
return
var path = path
if path[^1] != '/': #TODO dos/windows
path &= '/'
var base = $url
if base[^1] != '/': #TODO dos/windows
base &= '/'
t handle.sendResult(0)
t handle.sendStatus(200) # ok
t handle.sendHeaders(newHeaders({"Content-Type": "text/html"}))
t handle.sendData("""
<HTML>
<HEAD>
<BASE HREF="""" & base & """">
<TITLE>Directory list of """ & path & """</TITLE>
</HEAD>
<BODY>
<H1>Directory list of """ & path & """</H1>
<PRE>
""")
var fs: seq[(PathComponent, string)]
for pc, file in walkDir(path, relative = true):
fs.add((pc, file))
fs.sort(cmp = proc(a, b: (PathComponent, string)): int = cmp(a[1], b[1]))
var items: seq[DirlistItem]
for (pc, file) in fs:
let fullpath = path / file
var info: FileInfo
try:
info = getFileInfo(fullpath, followSymlink = false)
except OSError:
continue
let modified = $info.lastWriteTime.local().format("MMM/dd/yyyy HH:MM")
case pc
of pcDir:
items.add(DirlistItem(
t: ITEM_DIR,
name: file,
modified: modified
))
of pcFile:
items.add(DirlistItem(
t: ITEM_FILE,
name: file,
modified: modified,
nsize: int(info.size)
))
of pcLinkToDir, pcLinkToFile:
var target = expandSymlink(fullpath)
if pc == pcLinkToDir:
target &= '/'
items.add(DirlistItem(
t: ITEM_LINK,
name: file,
modified: modified,
linkto: target
))
t handle.sendData(makeDirlist(items))
t handle.sendData("\n</PRE>\n</BODY>\n</HTML>\n")
proc loadSymlink(handle: LoaderHandle, path: string) =
template t(body: untyped) =
if not body:
return
t handle.sendResult(0)
t handle.sendStatus(200) # ok
t handle.sendHeaders(newHeaders({"Content-Type": "text/html"}))
let sl = expandSymlink(path)
t handle.sendData("""
<HTML>
<HEAD>
<TITLE>Symlink view<TITLE>
</HEAD>
<BODY>
Symbolic link to <A HREF="""" & sl & """">""" & sl & """</A></br>
</BODY>
</HTML>""")
proc loadFile(handle: LoaderHandle, istream: Stream) =
template t(body: untyped) =
if not body:
return
t handle.sendResult(0)
t handle.sendStatus(200) # ok
t handle.sendHeaders(newHeaders())
while not istream.atEnd:
const bufferSize = 4096
var buffer {.noinit.}: array[bufferSize, char]
while true:
let n = readData(istream, addr buffer[0], bufferSize)
if n == 0:
break
t handle.sendData(addr buffer[0], n)
if n < bufferSize:
break
proc loadFilePath*(handle: LoaderHandle, url: URL, path: string) =
let istream = newFileStream(path, fmRead)
if istream == nil:
if dirExists(path):
handle.loadDir(url, path)
elif symlinkExists(path):
handle.loadSymlink(path)
else:
discard handle.sendResult(ERROR_FILE_NOT_FOUND)
else:
handle.loadFile(istream)
|