mirror of https://github.com/YGGverse/nexd.git
yggverse
7 months ago
commit
a3ffecb1db
4 changed files with 186 additions and 0 deletions
@ -0,0 +1,22 @@
@@ -0,0 +1,22 @@
|
||||
MIT License |
||||
|
||||
Copyright (c) 2023 m15o |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of |
||||
this software and associated documentation files (the "Software"), to deal in |
||||
the Software without restriction, including without limitation the rights to |
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies |
||||
of the Software, and to permit persons to whom the Software is furnished to do |
||||
so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice (including the next |
||||
paragraph) shall be included in all copies or substantial portions of the |
||||
Software. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
SOFTWARE. |
@ -0,0 +1,2 @@
@@ -0,0 +1,2 @@
|
||||
build: |
||||
GOARCH=amd64 go build -o nexd nexd.go |
@ -0,0 +1,19 @@
@@ -0,0 +1,19 @@
|
||||
# nexd - Server for Nex Protocol written in Go |
||||
|
||||
Unofficial GIT build of [nexd](https://hg.sr.ht/~m15o/nexd) Mercurial repository. |
||||
|
||||
Includes [nex-pfm](https://hg.sr.ht/~m15o/nex-pfm) + modified for Linux / amd64 makefile version. |
||||
|
||||
## Install |
||||
|
||||
* `git clone https://github.com/YGGverse/nexd.git` |
||||
* `cd nexd` |
||||
* `make` |
||||
|
||||
## Launch |
||||
|
||||
``` |
||||
nexd path/to/destination/folder |
||||
``` |
||||
|
||||
* server open `index` file by default, directory listing instead |
@ -0,0 +1,143 @@
@@ -0,0 +1,143 @@
|
||||
package main |
||||
|
||||
import ( |
||||
"bufio" |
||||
"io" |
||||
"io/fs" |
||||
"log" |
||||
"net" |
||||
"os" |
||||
"path" |
||||
"sort" |
||||
"strings" |
||||
) |
||||
|
||||
func write(w io.Writer, s string) (int, error) { |
||||
return w.Write([]byte(s + "\n")) |
||||
} |
||||
|
||||
type Handler struct { |
||||
FS fs.FS |
||||
} |
||||
|
||||
func (h *Handler) handleDir(p string, w io.Writer) error { |
||||
if header, err := fs.ReadFile(h.FS, path.Join(p, ".header")); err == nil { |
||||
write(w, string(header)) |
||||
} |
||||
modified := true |
||||
if _, err := fs.Stat(h.FS, path.Join(p, ".modified")); err != nil { |
||||
modified = false |
||||
} |
||||
asc := false |
||||
if _, err := fs.Stat(h.FS, path.Join(p, ".desc")); err != nil { |
||||
asc = true |
||||
} |
||||
dirents, err := fs.ReadDir(h.FS, p) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
sort.Slice(dirents, func(i, j int) bool { |
||||
if modified { |
||||
st1, err := dirents[i].Info() |
||||
if err != nil { |
||||
return false |
||||
} |
||||
st2, err := dirents[j].Info() |
||||
if err != nil { |
||||
return false |
||||
} |
||||
return st1.ModTime().After(st2.ModTime()) |
||||
} else if asc { |
||||
return dirents[i].Name() < dirents[j].Name() |
||||
} else { |
||||
return dirents[i].Name() > dirents[j].Name() |
||||
} |
||||
}) |
||||
for _, entry := range dirents { |
||||
name := entry.Name() |
||||
if strings.HasPrefix(name, ".") { |
||||
continue |
||||
} |
||||
i, err := entry.Info() |
||||
if err != nil { |
||||
continue |
||||
} |
||||
if i.Mode()&(1<<2) == 0 { |
||||
continue |
||||
} |
||||
if entry.IsDir() { |
||||
name += "/" |
||||
} |
||||
if _, err := write(w, "=> "+name); err != nil { |
||||
return err |
||||
} |
||||
} |
||||
return nil |
||||
} |
||||
|
||||
func (h *Handler) Handle(p string, w io.Writer) error { |
||||
if p == "/" || p == "" { |
||||
p = "." |
||||
} else { |
||||
p = strings.Trim(p, "/") |
||||
} |
||||
|
||||
f, err := h.FS.Open(p) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
defer f.Close() |
||||
|
||||
stat, err := f.Stat() |
||||
if err != nil { |
||||
return err |
||||
} |
||||
|
||||
if stat.IsDir() { |
||||
index, err := h.FS.Open(path.Join(p, "index")) |
||||
if err != nil { |
||||
return h.handleDir(p, w) |
||||
} |
||||
defer index.Close() |
||||
f = index |
||||
} |
||||
|
||||
_, err = io.Copy(w, f) |
||||
return err |
||||
} |
||||
|
||||
func serve(h *Handler, rw io.ReadWriteCloser) { |
||||
defer rw.Close() |
||||
scanner := bufio.NewScanner(rw) |
||||
scanner.Scan() |
||||
sel := scanner.Text() |
||||
if err := h.Handle(sel, rw); err != nil { |
||||
rw.Write([]byte("document not found")) |
||||
log.Println(err) |
||||
} |
||||
} |
||||
|
||||
func listenAndServe(h *Handler) error { |
||||
l, err := net.Listen("tcp", ":1900") |
||||
if err != nil { |
||||
return err |
||||
} |
||||
defer l.Close() |
||||
|
||||
for { |
||||
rw, err := l.Accept() |
||||
if err != nil { |
||||
return err |
||||
} |
||||
go serve(h, rw) |
||||
} |
||||
} |
||||
|
||||
func main() { |
||||
if len(os.Args) < 2 { |
||||
log.Fatal("usage: nexd path") |
||||
} |
||||
|
||||
h := Handler{FS: os.DirFS(os.Args[1])} |
||||
log.Fatal(listenAndServe(&h)) |
||||
} |
Loading…
Reference in new issue