func FetchBin(w http.ResponseWriter, r *http.Request, cfg config.Configuration, ctx model.Context) { w.Header().Set("Cache-Control", "s-maxage=15") w.Header().Set("Vary", "Content-Type") var status = 200 params := mux.Vars(r) bin := params["bin"] if err := verifyBin(bin); err != nil { http.Error(w, "Invalid bin", 400) return } event := ctx.Events.New(ctx.RemoteAddr, []string{"bin", "view"}, bin, "") defer event.Done() var err error b, err := ctx.Backend.GetBinMetaData(bin) if err != nil { if ctx.Backend.BinExists(bin) { ctx.Log.Println(err) event.Update(err.Error(), 2) http.Error(w, "Internal Server Error", http.StatusInternalServerError) return } else { // This bin does not exist (but can be created) event.Update("Bin does not exist", 1) status = 404 b = ctx.Backend.NewBin(bin) } } if b.Expired { http.Error(w, "This bin expired "+b.ExpiresReadable+".", 410) return } ctx.Metrics.Incr("total-view-bin") ctx.Metrics.Incr("bin-view bin=" + bin + " referer=" + r.Header.Get("Referer")) if r.Header.Get("Accept") == "application/json" { w.Header().Set("Content-Type", "application/json") output.JSONresponse(w, status, b, ctx) return } else { if len(b.Files) == 0 { output.HTMLresponse(w, "newbin", status, b, ctx) } else { output.HTMLresponse(w, "viewbin", status, b, ctx) } return } }
func AdminCounters(w http.ResponseWriter, r *http.Request, cfg config.Configuration, ctx model.Context) { w.Header().Set("Vary", "Content-Type") w.Header().Set("Cache-Control", "s-maxage=0, max-age=0") var status = 200 event := ctx.Events.New(ctx.RemoteAddr, []string{"admin", "counters"}, "", "") event.Update(r.Header.Get("user-agent"), 0) defer event.Done() stats := ctx.Metrics.GetStats() type Out struct { Counters map[string]int64 Uptime time.Duration UptimeReadable string Now time.Time } data := Out{ Counters: stats, Uptime: ctx.Metrics.Uptime(), UptimeReadable: humanize.Time(ctx.Metrics.StartTime()), Now: time.Now().UTC(), } if r.Header.Get("Accept") == "application/json" { w.Header().Set("Content-Type", "application/json") output.JSONresponse(w, status, data, ctx) } else { output.HTMLresponse(w, "counters", status, data, ctx) } return }
func FetchAlbum(w http.ResponseWriter, r *http.Request, cfg config.Configuration, ctx model.Context) { w.Header().Set("Cache-Control", "s-maxage=30") params := mux.Vars(r) bin := params["bin"] if err := verifyBin(bin); err != nil { http.Error(w, "Invalid bin", 400) return } b, err := ctx.Backend.GetBinMetaData(bin) if err != nil { ctx.Log.Println(err) http.Error(w, "Internal Server Error", http.StatusInternalServerError) return } if b.Expired { http.Error(w, "This bin expired "+b.ExpiresReadable+".", 410) return } ctx.Metrics.Incr("total-view-album") ctx.Metrics.Incr("album-view bin=" + bin + " referer=" + r.Header.Get("Referer")) var status = 200 output.HTMLresponse(w, "viewalbum", status, b, ctx) return }
func AdminEvents(w http.ResponseWriter, r *http.Request, cfg config.Configuration, ctx model.Context) { w.Header().Set("Vary", "Content-Type") w.Header().Set("Cache-Control", "s-maxage=0, max-age=0") var status = 200 event := ctx.Events.New(ctx.RemoteAddr, []string{"admin", "events"}, "", "") event.Update(r.Header.Get("user-agent"), 0) defer event.Done() //u, err := url.Parse(r.RequestURI) //if err != nil { // ctx.Log.Println(err) //} //queryParams, err := url.ParseQuery(u.RawQuery) //if err != nil { // ctx.Log.Println(err) //} //filter := metrics.Event{ // Bin: queryParams.Get("bin"), // Category: queryParams.Get("category"), // Filename: queryParams.Get("filename"), // RemoteAddr: queryParams.Get("remoteaddr"), // URL: queryParams.Get("url"), //} type Out struct { Events []events.Event Uptime time.Duration UptimeReadable string Now time.Time } data := Out{ Events: ctx.Events.GetAllEvents(0, 10000), Uptime: ctx.Metrics.Uptime(), UptimeReadable: humanize.Time(ctx.Metrics.StartTime()), Now: time.Now().UTC(), } if r.Header.Get("Accept") == "application/json" { w.Header().Set("Content-Type", "application/json") output.JSONresponse(w, status, data, ctx) } else { output.HTMLresponse(w, "events", status, data, ctx) } return }
func Readme(w http.ResponseWriter, r *http.Request, cfg config.Configuration, ctx model.Context) { var status = 200 w.Header().Set("Cache-Control", "s-maxage=3600") type Out struct { Uptime time.Duration UptimeReadable string Now time.Time } data := Out{ Uptime: ctx.Metrics.Uptime(), UptimeReadable: humanize.Time(ctx.Metrics.StartTime()), Now: time.Now().UTC(), } output.HTMLresponse(w, "readme", status, data, ctx) }
func AdminBins(w http.ResponseWriter, r *http.Request, cfg config.Configuration, ctx model.Context) { w.Header().Set("Vary", "Content-Type") w.Header().Set("Cache-Control", "s-maxage=0, max-age=0") var status = 200 event := ctx.Events.New(ctx.RemoteAddr, []string{"admin", "bins"}, "", "") event.Update(r.Header.Get("user-agent"), 0) defer event.Done() //event := metrics.Event{ // Category: "admin-login", // RemoteAddr: ctx.RemoteAddr, // Text: r.Header.Get("user-agent"), // URL: r.RequestURI, //} //ctx.Metrics.AddEvent(event) bins := ctx.Backend.GetBinsMetaData() type Out struct { Bins []fs.Bin BinsReadable string Uptime time.Duration UptimeReadable string Now time.Time } data := Out{ Bins: bins, BinsReadable: humanize.Comma(int64(len(bins))), Uptime: ctx.Metrics.Uptime(), UptimeReadable: humanize.Time(ctx.Metrics.StartTime()), Now: time.Now().UTC(), } if r.Header.Get("Accept") == "application/json" { w.Header().Set("Content-Type", "application/json") output.JSONresponse(w, status, data, ctx) } else { output.HTMLresponse(w, "bins", status, data, ctx) } return }
func NewBin(w http.ResponseWriter, r *http.Request, cfg config.Configuration, ctx model.Context) { w.Header().Set("Cache-Control", "s-maxage=0, max-age=0") w.Header().Set("Vary", "Content-Type") // XXX: Should ensure that the bin does not exist from before. bin := randomString(cfg.DefaultBinLength) b := ctx.Backend.NewBin(bin) ctx.Metrics.Incr("total-new-bin") var status = 200 if r.Header.Get("Accept") == "application/json" { w.Header().Set("Content-Type", "application/json") output.JSONresponse(w, status, b, ctx) } else { output.HTMLresponse(w, "newbin", status, b, ctx) } return }
func FetchTag(w http.ResponseWriter, r *http.Request, cfg config.Configuration, ctx model.Context) { var err error params := mux.Vars(r) t := model.Tag{} err = t.SetTag(params["tag"]) if err != nil { ctx.Log.Println(err) http.Error(w, "Invalid tag", 400) return } t.SetTagDir(cfg.Filedir) t.CalculateExpiration(cfg.Expiration) if t.TagDirExists() { expired, err := t.IsExpired(cfg.Expiration) if err != nil { ctx.Log.Println(err) http.Error(w, "Internal server error", 500) return } if expired { ctx.Log.Println("Expired: " + t.ExpirationReadable) http.Error(w, "This tag has expired.", 410) return } err = t.StatInfo() if err != nil { ctx.Log.Println(err) http.Error(w, "Internal Server Error", 500) return } err = t.List(cfg.Baseurl) if err != nil { ctx.Log.Println(err) http.Error(w, "Error reading the tag contents.", 404) return } } //t.GenerateLinks(cfg.Baseurl) headers := make(map[string]string) headers["Cache-Control"] = "max-age=1" var status = 200 if r.Header.Get("Content-Type") == "application/zip" || r.FormValue("o") == "zip" { headers["Content-Type"] = "application/zip" // Generate a map of paths to add to the zip response var paths []string for _, f := range t.Files { path := filepath.Join(f.TagDir, f.Filename) paths = append(paths, path) } output.ZIPresponse(w, status, t.Tag, headers, paths, ctx) return } if r.Header.Get("Content-Type") == "application/json" { headers["Content-Type"] = "application/json" output.JSONresponse(w, status, headers, t, ctx) return } else { output.HTMLresponse(w, "viewtag", status, headers, t, ctx) return } }
func AdminDashboard(w http.ResponseWriter, r *http.Request, cfg config.Configuration, ctx model.Context) { w.Header().Set("Vary", "Content-Type") w.Header().Set("Cache-Control", "s-maxage=0, max-age=0") var status = 200 eventsInProgress := ctx.Events.GetEventsInProgress(0, 0) event := ctx.Events.New(ctx.RemoteAddr, []string{"admin", "dashboard"}, "", "") event.Update(r.Header.Get("user-agent"), 0) defer event.Done() logins := ctx.Events.GetEventsByTags([]string{"admin"}, 0, 3) bins := ctx.Backend.GetBinsMetaData() stats := ctx.Metrics.GetStats() // Detect time limit for showing recent events limitTime := time.Now().UTC().Add(-48 * time.Hour) if len(logins) >= 2 { limitTime = logins[1].StartTime() } var recentUploads []events.Event uploads := ctx.Events.GetEventsByTags([]string{"upload"}, 0, 0) for _, f := range uploads { if f.StartTime().After(limitTime) { if f.IsDone() && f.Status() == 0 { recentUploads = append(recentUploads, f) } } } var recentEvents []events.Event allEvents := ctx.Events.GetAllEvents(1, 0) for _, e := range allEvents { if e.StartTime().After(limitTime) { recentEvents = append(recentEvents, e) } } type Out struct { Bins []fs.Bin BinsReadable string Events []events.Event EventsInProgress []events.Event Uploads []events.Event Files int FilesReadable string Bytes int64 BytesReadable string Stats map[string]int64 Logins []events.Event Uptime time.Duration UptimeReadable string Now time.Time } var files int var bytes int64 for _, b := range bins { files = files + len(b.Files) bytes = bytes + b.Bytes } data := Out{ Bins: bins, Events: recentEvents, EventsInProgress: eventsInProgress, Uploads: recentUploads, Files: files, Bytes: bytes, BytesReadable: humanize.Bytes(uint64(bytes)), BinsReadable: humanize.Comma(int64(len(bins))), FilesReadable: humanize.Comma(int64(files)), Stats: stats, Logins: logins, Uptime: ctx.Metrics.Uptime(), UptimeReadable: humanize.Time(ctx.Metrics.StartTime()), Now: time.Now().UTC(), } if r.Header.Get("Accept") == "application/json" { w.Header().Set("Content-Type", "application/json") output.JSONresponse(w, status, data, ctx) } else { output.HTMLresponse(w, "dashboard", status, data, ctx) } return }