From: Urban Wallasch Date: Wed, 3 Apr 2019 19:13:43 +0000 (+0200) Subject: * initial commit X-Git-Tag: v0.1~6 X-Git-Url: https://git.packet-gain.de/?a=commitdiff_plain;h=2a75bc00f8460f2280d53ab85f409009da4cd83f;p=gogopherd.git * initial commit --- 2a75bc00f8460f2280d53ab85f409009da4cd83f diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e4e58c6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +gogopherd +stuff diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..9d4c0ba --- /dev/null +++ b/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2016, Urban Wallasch +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..1603da1 --- /dev/null +++ b/Makefile @@ -0,0 +1,29 @@ +####################################### +## Makefile for project: gogopherd ## +####################################### + +PROJECT := gogopherd + +GOBLD := go build + +BIN := $(PROJECT) +SRC := $(wildcard *.go) +SELF := $(lastword $(MAKEFILE_LIST)) + + +.PHONY: all clean distclean + +all: $(BIN) + +$(BIN): $(SRC) $(SELF) + $(GOBLD) $(SRVSRC) + +clean: + $(RM) $(BIN) + +distclean: clean + + +########### +## EOF ## +########### diff --git a/dummy.txt b/dummy.txt new file mode 100644 index 0000000..e2da9dc --- /dev/null +++ b/dummy.txt @@ -0,0 +1,2 @@ +Hello, world! +Delirium Solarium Besenstiel diff --git a/gogopherd.go b/gogopherd.go new file mode 100644 index 0000000..c1aadd7 --- /dev/null +++ b/gogopherd.go @@ -0,0 +1,156 @@ +/* + * This file is part of the gogopherd project. + * + * Copyright 2019 Urban Wallasch + * See LICENSE file for more details. + * + */ +/* + * Gogopherd- a minimalistic gopher server written in Go. + * + * Changelog: + * 2019-04-03 Initial version. + */ + +package main + +import ( + "bufio" + "flag" + "fmt" + "io/ioutil" + "log" + "net" + "os" + "strings" +) + +var ( + index []string + logger *log.Logger + tracer *log.Logger +) + +var cfg = struct { + bindIface string + bindPortTcp string + fqdn string + docRoot string + indexFile string + verbose bool +}{ + bindIface: "localhost", + bindPortTcp: "7070", + fqdn: "localhost", + docRoot: ".", + indexFile: "index.gox", + verbose: false, +} + +func initialize() { + flag.StringVar(&cfg.bindIface, "i", cfg.bindIface, "interface to bind to") + flag.StringVar(&cfg.bindPortTcp, "p", cfg.bindPortTcp, "TCP port to listen on") + flag.StringVar(&cfg.docRoot, "d", cfg.docRoot, "document root directory") + flag.StringVar(&cfg.indexFile, "x", cfg.indexFile, "index file") + flag.BoolVar(&cfg.verbose, "v", cfg.verbose, "produce verbose output") + flag.Parse() + if 0 != len(flag.Args()) { + fmt.Println("unrecognized options: ", flag.Args()) + flag.Usage() + os.Exit(1) + } + + logger = log.New(os.Stderr, "", log.Ldate|log.Ltime|log.Lshortfile) + if cfg.verbose { + tracer = log.New(os.Stderr, "", log.Ldate|log.Ltime|log.Lshortfile) + } else { + tracer = log.New(ioutil.Discard, "", 0) + } + + tracer.Print("interface: ", cfg.bindIface) + tracer.Print("TCP port: ", cfg.bindPortTcp) + tracer.Print("doc root: ", cfg.docRoot) + tracer.Print("index file: ", cfg.indexFile) + tracer.Print("verbose: ", cfg.verbose) +} + +func checkFatal(err error, msg string) { + if err != nil { + logger.Print(msg, ": ", err.Error()) + os.Exit(1) + } +} + +func check(err error, msg string)(error) { + if err != nil { + tracer.Print(msg, ": ", err.Error()) + } + return err +} + +func getErrorString(code string) (string) { + // TODO flesh this out + res := "Error: " + code + " Resource not found. " + return res; +} + +func sanitizeSelector(selector string) (string) { + selector = strings.Replace(selector, "\r", "", -1) + selector = strings.Replace(selector, "\n", "", -1) + selector = strings.Replace(selector, "../", "/", -1) + selector = strings.Replace(selector, "//", "/", -1) + selector = strings.Replace(selector, "//", "/", -1) + return selector +} + +func getResource(selector string) ([]byte, error) { + if ( selector == "" || selector == "/" ) { + selector = cfg.indexFile + } + resPath := cfg.docRoot + "/" + selector + res, err := ioutil.ReadFile(resPath) + if check(err,"ReadFile " + resPath) != nil { res = []byte(""); } + return res, err; +} + +func handleRequest(conn net.Conn) { + defer conn.Close() + reply := []byte("") + req, err := bufio.NewReader(conn).ReadString('\n') + if ( check(err,"ReadString") != nil ) { + return + } else { + tracer.Print("request: '", req, "'") + selector := sanitizeSelector(req) + tracer.Print("selector: '", selector, "'") + reply, err = getResource(selector) + if ( err != nil ) { reply = []byte(getErrorString("404") + selector) } + } + conn.Write(reply) +} + +func serveTCP(sock net.Listener) { + for { + conn, err := sock.Accept() + checkFatal(err, "Accept") + tracer.Print("TCP connect from ", conn.RemoteAddr()) + go handleRequest(conn) + } +} + +func main() { + initialize() + bindaddr := cfg.bindIface + ":" + cfg.bindPortTcp + tsock, err := net.Listen("tcp", bindaddr) + checkFatal(err, "net.Listen tcp " + bindaddr) + defer tsock.Close() + tracer.Print("listening on TCP ", bindaddr) + go serveTCP(tsock) + // send ready signal + fmt.Println("") + // exit on any input on stdin + reader := bufio.NewReader(os.Stdin) + reader.ReadRune() +} + +/* EOF */ diff --git a/index.gox b/index.gox new file mode 100644 index 0000000..ded7352 --- /dev/null +++ b/index.gox @@ -0,0 +1,5 @@ +iWelcome to gogopherd on localhost +i--------------------------------- +0dummy.txt /dummy.txt localhost 7070 +0gogopherd source code /gogopherd.go localhost 7070 +9gogopherd binary /gogopherd localhost 7070