Ejemplo n.º 1
0
func DelGob(w http.ResponseWriter, r *http.Request) {
	gslog.Debug("HANDLER: DelGob called with header: %+v, host: %s, requestURI: %s, remoteAddr: %s", r.Header, r.Host, r.RequestURI, r.RemoteAddr)
	params := r.URL.Query()
	token := params.Get(":token")
	if !validToken(token) {
		returnHTTPError(w, "DelGob", token+" not found", http.StatusNotFound)
		return
	}
	uid, err := store.TokenToUID(token)
	if err != nil {
		gslog.Error("HANDLER: delete gob failed with error: %s", err.Error())
		returnHTTPError(w, "DelGob", "failed to delete gob", http.StatusInternalServerError)
		return
	}
	if uid == "" {
		returnHTTPError(w, "DelGob", token+" not found", http.StatusNotFound)
		return
	}
	err = store.DelGob(uid)
	if err != nil {
		gslog.Error("HANDLER: delete gob failed with error: %s", err.Error())
		returnHTTPError(w, "DelGob", "failed to delete gob", http.StatusInternalServerError)
		return
	}

	pageType := getPageType(r)
	pageBytes, err := templ.GetMessPage(pageType, "successfully deleted "+uid)
	w.Write(pageBytes)
}
Ejemplo n.º 2
0
func GetHorde(w http.ResponseWriter, r *http.Request) {
	gslog.Debug("HANDLER: GetHorde called with header: %+v, host: %s, requestURI: %s, remoteAddr: %s", r.Header, r.Host, r.RequestURI, r.RemoteAddr)
	params := r.URL.Query()
	hordeName := params.Get(":horde")
	if !validHordeName(hordeName) {
		returnHTTPError(w, "GetHorde", hordeName+" not found", http.StatusNotFound)
		return
	}
	horde, err := store.GetHorde(hordeName)
	if err != nil {
		gslog.Error("HANDLER: failed to get horde with error: %s", err.Error())
		returnHTTPError(w, "GetHorde", "failed to get horde", http.StatusInternalServerError)
		return
	}
	if len(horde) == 0 {
		returnHTTPError(w, "GetHorde", hordeName+" not found", http.StatusNotFound)
		return
	}
	pageType := getPageType(r)
	pageBytes, err := templ.GetHordePage(getScheme(r), pageType, hordeName, horde)
	if err != nil {
		gslog.Error("HANDLER: failed to get horde with error: %s", err.Error())
		returnHTTPError(w, "GetHorde", "failed to get horde", http.StatusInternalServerError)
		return
	}
	w.Write(pageBytes)
}
Ejemplo n.º 3
0
func PostGob(w http.ResponseWriter, r *http.Request) {
	gslog.Debug("HANDLER: PostGob called with header: %+v, host: %s, requestURI: %s, remoteAddr: %s", r.Header, r.Host, r.RequestURI, r.RemoteAddr)
	gobData := getGobData(w, r)
	if len(gobData) == 0 {
		returnHTTPError(w, "PostGob", "gob empty", http.StatusBadRequest)
		return
	}

	ip := getIpAddress(r)
	uid, token, err := store.PutGob(gobData, ip)
	gslog.Debug("HANDLER: PostGob uid: %s, ip: %s, token: %s", uid, ip, token)
	if err != nil {
		gslog.Error("HANDLER: post gob failed with error: %s", err.Error())
		returnHTTPError(w, "PostGob", "failed to save gob", http.StatusInternalServerError)
		return
	}

	pageType := getPageType(r)
	pageBytes, err := templ.GetURLPage(getScheme(r), pageType, uid, token)
	if err != nil {
		gslog.Error("HANDLER: post gob failed with error: %s", err.Error())
		returnHTTPError(w, "GetHorde", "failed to save gob", http.StatusInternalServerError)
		return
	}
	w.Write(pageBytes)
}
Ejemplo n.º 4
0
// setTTL sets the expire time for the uid based on the size.  Expects to be
// run in a goroutine, so it does not return an error.  It instead logs it.
// TODO: should I be passing the client in?
func (redisStore *RedisStore) setTTLRoutine(client *pool.Client, gobInfo *storage.GobInfo, data []byte) {
	defer redisStore.Put(client)
	ttl := calculateTTL(data)
	if i, _ := client.Cmd("EXPIRE", gobKey(gobInfo.UID), ttl).Int(); i == 0 {
		gslog.Error("REDIS: could not set expire time for key '%s' to %d seconds", gobKey(gobInfo.UID), ttl)
	}
	if i, _ := client.Cmd("EXPIRE", gobInfoKey(gobInfo.UID), ttl).Int(); i == 0 {
		gslog.Error("REDIS: could not set expire time for key '%s' to %d seconds", gobInfoKey(gobInfo.UID), ttl)
	}
	if i, _ := client.Cmd("EXPIRE", tokenKey(gobInfo.Token), ttl).Int(); i == 0 {
		gslog.Error("REDIS: could not set expire time for key '%s' to %d seconds", tokenKey(gobInfo.Token), ttl)
	}
}
Ejemplo n.º 5
0
func PostHordeGob(w http.ResponseWriter, r *http.Request) {
	gslog.Debug("HANDLER: PostHordeGob called with header: %+v, host: %s, requestURI: %s, remoteAddr: %s", r.Header, r.Host, r.RequestURI, r.RemoteAddr)
	params := r.URL.Query()
	hordeName := params.Get(":horde")
	if !validHordeName(hordeName) {
		returnHTTPError(w, "PostHordeGob", "horde name can only contain up to "+strconv.Itoa(HORDE_MAX_LEN)+" alphanumeric characters", http.StatusNotFound)
		return
	}
	gobData := getGobData(w, r)
	if len(gobData) == 0 {
		returnHTTPError(w, "PostHordeGob", "gob empty", http.StatusBadRequest)
		return
	}
	ip := getIpAddress(r)
	uid, token, err := store.PutHordeGob(hordeName, gobData, ip)
	gslog.Debug("HANDLER: uid: %s, ip: %s", uid, ip)
	if err != nil {
		gslog.Error("HANDLER: put horde gob failed with error: %s", err.Error())
		returnHTTPError(w, "PostHordeGob", "failed to save gob", http.StatusInternalServerError)
		return
	}

	pageType := getPageType(r)
	pageBytes, err := templ.GetURLPage(getScheme(r), pageType, uid, token)
	w.Write(pageBytes)
}
Ejemplo n.º 6
0
func (redisStore *RedisStore) deleteExpireRoutine(client *pool.Client, key string) {
	err := deleteExpire(client, key)
	if err != nil {
		gslog.Error("REDIS: could not set expire time for deleted key '%s' with error: %s", key)
		return
	}
	redisStore.Put(client)
}
Ejemplo n.º 7
0
func GetForm(w http.ResponseWriter, r *http.Request) {
	gslog.Debug("HANDLER: GetForm called with header: %+v, host: %s, requestURI: %s, remoteAddr: %s", r.Header, r.Host, r.RequestURI, r.RemoteAddr)
	pageBytes, err := templ.GetFormPage(getScheme(r))
	if err != nil {
		gslog.Error("HANDLER: failed to get form with error: %s", err.Error())
		returnHTTPError(w, "GetRoot", "failed to get form", http.StatusInternalServerError)
		return
	}
	w.Write(pageBytes)
}
Ejemplo n.º 8
0
func GetGob(w http.ResponseWriter, r *http.Request) {
	gslog.Debug("HANDLER: GetGob called with header: %+v, host: %s, requestURI: %s, remoteAddr: %s", r.Header, r.Host, r.RequestURI, r.RemoteAddr)
	params := r.URL.Query()
	uid := params.Get(":uid")
	if !validUID(uid) {
		returnHTTPError(w, "GetGob", uid+" not found", http.StatusNotFound)
		return
	}
	data, _, err := store.GetGob(uid)
	if err != nil {
		gslog.Error("HANDLER: failed to get gob with error: " + err.Error())
		returnHTTPError(w, "GetGob", "failed to get gob", http.StatusInternalServerError)
		return
	}
	if len(data) == 0 {
		returnHTTPError(w, "GetGob", uid+" not found", http.StatusNotFound)
		return
	}
	// Firgure out language parameter
	lang := getLanguage(r)

	if lang == "" {
		gslog.Debug("HANDLER: GetGob writing data")
		w.Write(data)
		return
	}
	contentType := http.DetectContentType(data)
	// If data is a valid content type for syntax highlighting
	if textContentTypeReg.MatchString(contentType) {
		data, err = templ.GetGobPage(lang, data)
		if err != nil {
			gslog.Error("HANDLER: failed to get gob page with error: %s", err.Error())
			returnHTTPError(w, "GetGob", "failed to get gob", http.StatusInternalServerError)
			return
		}
	}

	w.Write(data)
}
Ejemplo n.º 9
0
func AppendGob(w http.ResponseWriter, r *http.Request) {
	gslog.Debug("HANDLER: AppendGob called with header: %+v, host: %s, requestURI: %s, remoteAddr: %s", r.Header, r.Host, r.RequestURI, r.RemoteAddr)
	params := r.URL.Query()
	token := params.Get(":token")
	if !validToken(token) {
		returnHTTPError(w, "AppendGob", token+" not found", http.StatusNotFound)
		return
	}
	gobData := getGobData(w, r)
	if len(gobData) == 0 {
		returnHTTPError(w, "AppendGob", "gob empty", http.StatusBadRequest)
		return
	}
	ip := getIpAddress(r)
	uid, err := store.TokenToUID(token)
	gslog.Debug("HANDLER: AppendGob uid: %s, ip: %s, token: %s", uid, ip, token)
	if err != nil {
		gslog.Error("HANDLER: append gob failed with error: %s", err.Error())
		returnHTTPError(w, "AppendGob", "failed to append gob", http.StatusInternalServerError)
		return
	}
	if uid == "" {
		returnHTTPError(w, "AppendGob", token+" not found", http.StatusNotFound)
		return
	}
	err = store.AppendGob(uid, gobData)
	if err != nil {
		gslog.Error("HANDLER: append gob failed with error: %s", err.Error())
		returnHTTPError(w, "AppendGob", "failed to append gob", http.StatusInternalServerError)
		return
	}

	pageType := getPageType(r)
	// TODO: Should I tell them what gob they appended? Maybe a security flaw
	pageBytes, err := templ.GetMessPage(pageType, "successfully appended "+uid)
	w.Write(pageBytes)
}
Ejemplo n.º 10
0
// deleteExpire modifies the key so that it is inaccessble via normal methods
// and sets the TTL to a week
func deleteExpire(client *pool.Client, key string) error {
	// Make gob inaccessble using normal key
	reply := client.Cmd("RENAME", key, deletedKey(key))
	if reply.Err != nil {
		return reply.Err
	}
	reply = client.Cmd("EXPIRE", deletedKey(key), DEL_TTL)
	if reply.Err != nil {
		return reply.Err
	}
	if i, _ := reply.Int(); i == 0 {
		gslog.Error("REDIS: could not set expire time for deleted key '%s'", key)
	}
	return nil
}
Ejemplo n.º 11
0
func GetGobPage(language string, data []byte) ([]byte, error) {
	if language == "markdown" {
		p := &MDPage{
			Title:    "gob: " + language + " syntax highlighted",
			Language: language,
			Data:     htmlTemplate.HTML(string(data)),
		}
		return executeTemplate("HTML", "mdPage", p)
	}
	pygments.Binary(pygmentizePath)
	opts := pygments.Options{
		"linenos":  "table",
		"encoding": "utf-8",
	}
	code, err := pygments.Highlight(string(data), language, "html", opts)
	if err != nil {
		gslog.Error("Failed to highlight code: " + err.Error())
		// Syntax highlighting has failed, so just display the raw data
		return data, nil
	}
	p := &GobPage{Title: "gob: " + language + " syntax highlighted", Language: language, Data: htmlTemplate.HTML(code)}
	return executeTemplate("HTML", "gobPage", p)
}
Ejemplo n.º 12
0
func main() {
	//if conf.ShowVers {
	//	println("Commit: " + buildCommit)
	//	println("Date:   " + buildDate)
	//	os.Exit(0)
	//}

	gslog.Info("Goblin started [build commit: %s, build date: %s]", buildCommit, buildDate)

	if err := conf.Parse(); err != nil {
		gslog.Fatal("MAIN: failed to parse conf with error: %s", err.Error())
	}

	gslog.SetMinimumLevel(conf.GetStr("loglevel"))
	if logFile := conf.GetStr("logfile"); logFile != "" {
		gslog.SetLogFile(logFile)
	}

	storeType, storeConf := conf.GetStr("storetype"), conf.GetStr("storeconf")
	uidLen, tokenLen := conf.GetInt("uidlength"), conf.GetInt("tokenlength")
	handler.Initialize(uidLen, tokenLen)
	if err := store.Initialize(storeType, storeConf, uidLen, tokenLen); err != nil {
		gslog.Fatal("MAIN: failed to initialize storage with error: %s", err.Error())
	}
	htmlTemps, textTemps := conf.GetStr("htmltemplates"), conf.GetStr("texttemplates")
	domain := conf.GetStr("domain")
	pygmentizePath := conf.GetStr("pygmentizepath")
	if err := templ.Initialize(htmlTemps, textTemps, domain, pygmentizePath); err != nil {
		gslog.Fatal("MAIN: failed to initialize templates with error: %s", err.Error())
	}

	// Setup route handlers
	mux := pat.New()
	mux.Get("/", http.HandlerFunc(handler.GetRoot))
	mux.Get("/:uid", http.HandlerFunc(handler.GetGob))
	mux.Get("/delete/:token", http.HandlerFunc(handler.DelGob))
	mux.Post("/append/:token", http.HandlerFunc(handler.AppendGob))
	mux.Get("/horde/:horde", http.HandlerFunc(handler.GetHorde))
	mux.Get("/new/gob", http.HandlerFunc(handler.GetForm))
	mux.Post("/", http.HandlerFunc(handler.PostGob))
	// TODO: Should I post to /horde/:horde
	mux.Post("/:horde", http.HandlerFunc(handler.PostHordeGob))

	http.Handle("/", mux)

	// Mandatory root-based resources
	staticPath := conf.GetStr("staticpath")
	serveSingle("/browserconfig.xml", filepath.Join(staticPath, "browserconfig.xml"))
	serveSingle("/robots.txt", filepath.Join(staticPath, "robots.txt"))
	serveSingle("/sitemap.xml", filepath.Join(staticPath, "sitemap.xml"))
	serveSingle("/apple-touch-icon-114x114.png", filepath.Join(staticPath, "img/apple-touch-icon-114x114.png"))
	serveSingle("/apple-touch-icon-120x120.png", filepath.Join(staticPath, "img/apple-touch-icon-120x120.png"))
	serveSingle("/apple-touch-icon-144x144.png", filepath.Join(staticPath, "img/apple-touch-icon-144x144.png"))
	serveSingle("/apple-touch-icon-152x152.png", filepath.Join(staticPath, "img/apple-touch-icon-152x152.png"))
	serveSingle("/apple-touch-icon-57x57.png", filepath.Join(staticPath, "img/apple-touch-icon-57x57.png"))
	serveSingle("/apple-touch-icon-60x60.png", filepath.Join(staticPath, "img/apple-touch-icon-60x60.png"))
	serveSingle("/apple-touch-icon-72x72.png", filepath.Join(staticPath, "img/apple-touch-icon-72x72.png"))
	serveSingle("/apple-touch-icon-76x76.png", filepath.Join(staticPath, "img/apple-touch-icon-76x76.png"))
	serveSingle("/apple-touch-icon.png", filepath.Join(staticPath, "img/apple-touch-icon.png"))
	serveSingle("/apple-touch-icon-precomposed.png", filepath.Join(staticPath, "img/apple-touch-icon-precomposed.png"))
	serveSingle("/favicon-160x160.png", filepath.Join(staticPath, "img/favicon-160x160.png"))
	serveSingle("/favicon-16x16.png", filepath.Join(staticPath, "img/favicon-16x16.png"))
	serveSingle("/favicon-196x196.png", filepath.Join(staticPath, "img/favicon-196x196.png"))
	serveSingle("/favicon-32x32.png", filepath.Join(staticPath, "img/favicon-32x32.png"))
	serveSingle("/favicon-96x96.png", filepath.Join(staticPath, "img/favicon-96x96.png"))
	serveSingle("/favicon.ico", filepath.Join(staticPath, "img/favicon.ico"))
	serveSingle("/mstile-144x144.png", filepath.Join(staticPath, "img/mstile-144x144.png"))
	serveSingle("/mstile-150x150.png", filepath.Join(staticPath, "img/mstile-150x150.png"))
	serveSingle("/mstile-310x150.png", filepath.Join(staticPath, "img/mstile-310x150.png"))
	serveSingle("/mstile-310x310.png", filepath.Join(staticPath, "img/mstile-310x310.png"))
	serveSingle("/mstile-70x70.png", filepath.Join(staticPath, "img/mstile-70x70.png"))

	// Normal static resources
	http.Handle("/static/", http.StripPrefix("/static", http.FileServer(http.Dir(staticPath))))

	listenOn := conf.GetStr("listen")
	gslog.Info("MAIN: Listening on %s...", listenOn)
	c := make(chan error)
	go listenAndServer(listenOn, c)

	// Set up listening for os signals
	shutdownCh := make(chan os.Signal, 5)
	// TODO: What signals for Windows if any?
	signal.Notify(shutdownCh, syscall.SIGINT, syscall.SIGKILL)
	// Set up listening for os signals
	reloadCh := make(chan os.Signal, 5)
	signal.Notify(reloadCh, syscall.SIGUSR2)
	for {
		select {
		case <-reloadCh:
			gslog.Info("MAIN: reloading")
			if err := conf.Parse(); err != nil {
				gslog.Error("MAIN: failed to parse conf with error: %s", err.Error())
				break
			}

			gslog.SetMinimumLevel(conf.GetStr("loglevel"))
			if logFile := conf.GetStr("logfile"); logFile != "" {
				gslog.SetLogFile(logFile)
			}

			storeConf = conf.GetStr("storeconf")
			uidLen, tokenLen = conf.GetInt("uidlength"), conf.GetInt("tokenlength")
			handler.Initialize(uidLen, tokenLen)
			store.Configure(storeConf, uidLen, tokenLen)

			htmlTemps, textTemps = conf.GetStr("htmltemplates"), conf.GetStr("texttemplates")
			domain = conf.GetStr("domain")
			pygmentizePath := conf.GetStr("pygmentizepath")
			if err := templ.Reload(htmlTemps, textTemps, domain, pygmentizePath); err != nil {
				gslog.Error("MAIN: failed to reload templates with error: %s", err.Error())
			}
		case <-shutdownCh:
			gslog.Info("MAIN: Syscall recieved, shutting down...")
			gslog.Flush()
			os.Exit(0)
		case err := <-c:
			gslog.Error("MAIN: ListenAndServe: %s", err)
			gslog.Fatal("MAIN: Failed to start server, exiting...")
		}
	}
}