Skip to content

Instantly share code, notes, and snippets.

@NuVivo314
Last active December 17, 2015 16:19
Show Gist options
  • Save NuVivo314/5637888 to your computer and use it in GitHub Desktop.
Save NuVivo314/5637888 to your computer and use it in GitHub Desktop.
golang, woof, file server.
/*
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**»
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**»
** A copy of the GNU General Public License is available at
** http://www.fsf.org/licenses/gpl.txt, you can also write to the
** Free Software Foundation, Inc., 59 Temple Place - Suite 330,
** Boston, MA 02111-1307, USA.
*/
/*
Woof one-shot server inspiration.
know issue:
- Wget user, wget use index.html name...
*/
package main
import (
"crypto/rand"
"crypto/sha1"
"flag"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"path"
"regexp"
"strings"
)
const (
keySize = 128
defaultPort = 7878
nbTest = 10
)
var (
regexpRobot = regexp.MustCompile(`.?robots.txt`)
regexpIp = regexp.MustCompile(`.*IP.*: (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})<.*`)
StringRandKey string
root string
)
func main() {
getIp()
if err := config(); err != nil {
return
}
StringRandKey = genUnicKey()
if fi, err := os.Stat(root); err == nil {
log.Printf("Select type: %b", fi.IsDir())
if fi.IsDir() {
http.HandleFunc(StringRandKey, dirServer)
} else {
http.HandleFunc(StringRandKey, fileServer)
}
}
http.HandleFunc("/", robotsServ)
for i := defaultPort; i < defaultPort + nbTest; i++ {
port := fmt.Sprintf("%d", i)
log.Printf("http://%s:%s%s", getIp(), port, StringRandKey)
log.Println(http.ListenAndServe(":" + port, nil))
}
}
func robotsServ(rw http.ResponseWriter, r *http.Request) {
if !robot(r.URL.String(), rw) {
http.NotFound(rw, r)
}
}
func dirServer(rw http.ResponseWriter, r *http.Request) {
if robot(r.URL.String(), rw) {
return
}
h := http.StripPrefix(StringRandKey, http.FileServer(http.Dir(root)))
log.Printf("[%s] %s", r.RemoteAddr, r.URL.String())
h.ServeHTTP(rw, r)
log.Printf("[%s] End http transfere", r.RemoteAddr)
}
func fileServer(rw http.ResponseWriter, r *http.Request) {
_, file := path.Split(root)
if robot(r.URL.String(), rw) {
return
}
if !strings.HasSuffix(r.URL.Path, file) {
http.Redirect(rw, r, file, http.StatusMovedPermanently)
return
}
d, err := os.OpenFile(root, os.O_RDONLY, os.ModeType)
if err != nil {
http.NotFound(rw, r)
return
}
fi, _ := d.Stat()
log.Printf("[%s] %s", r.RemoteAddr, r.URL.String())
rw.Header().Add("Content-Disposition", fmt.Sprintf("attachment; \"filename=%s\"", file))
http.ServeContent(rw, r, root, fi.ModTime(), d)
log.Printf("[%s] End http transfere", r.RemoteAddr)
}
func getIp() string {
r, err := http.Get("http://checkip.dyndns.com/")
if err != nil {
log.Println(err.Error())
return ""
}
data, err := ioutil.ReadAll(r.Body)
if err != nil {
log.Println(err.Error())
return ""
}
datas := regexpIp.FindAllStringSubmatch(string(data), -1)
return string(datas[0][1])
}
func robot(uri string, rw http.ResponseWriter) bool {
uri = strings.ToLower(uri)
if regexpRobot.MatchString(uri) {
rw.Header().Add("Content-Type", "text/plain")
fmt.Fprintf(rw, "User-Agent: *\nDisallow: /\n")
return true
}
return false
}
func config() error {
_, file := path.Split(os.Args[0])
flag.Parse()
root = flag.Arg(0)
if root == "" {
log.Printf("[usage] ./%s <directory|file>", file)
return fmt.Errorf("Fail to parse flag...")
}
_, err := os.Stat(root)
if err != nil {
log.Println("Bad file or directory name")
log.Printf("[usage] ./%s <directory|file>", file)
return fmt.Errorf("Fail to parse flag...")
}
return nil
}
func genUnicKey() string {
RandKey := make([]byte, keySize)
n, err := rand.Read(RandKey)
if n != keySize || err != nil {
log.Println("Fail")
return "/"
}
StringRandKey := string(sha1.New().Sum(RandKey))
StringRandKey = fmt.Sprintf("/%x/", StringRandKey[2:12])
return StringRandKey
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment