package webcontroller import ( "fmt" "html" "io" "io/ioutil" "net/http" "net/url" "path/filepath" "strings" "fornaxian.com/pixeldrain-web/pixelapi" "github.com/Fornaxian/log" "github.com/julienschmidt/httprouter" "github.com/timakin/gonvert" ) // ServeFilePreview controller for GET /u/:id/preview func (wc *WebController) serveFilePreview(w http.ResponseWriter, r *http.Request, p httprouter.Params) { if p.ByName("id") == "demo" { serveFilePreviewDemo(w) // Required for a-ads.com quality check return } var api = pixelapi.New(wc.conf.APIURLInternal, "") inf, err := api.GetFileInfo(p.ByName("id")) // TODO: Error handling if err != nil { wc.serveNotFound(w, r) return } var fp = filePreview{ APIURL: wc.conf.APIURLExternal, PixelAPI: api, } io.WriteString(w, fp.run(inf)) } type filePreview struct { FileInfo *pixelapi.FileInfo FileURL string DownloadURL string APIURL string PixelAPI *pixelapi.PixelAPI } func (f filePreview) run(inf *pixelapi.FileInfo) string { f.FileInfo = inf f.FileURL = f.APIURL + "/file/" + f.FileInfo.ID f.DownloadURL = f.APIURL + "/file/" + f.FileInfo.ID + "?download" if strings.HasPrefix(f.FileInfo.MimeType, "image") { return f.image() } if strings.HasPrefix(f.FileInfo.MimeType, "video") { return f.video() } if strings.HasPrefix(f.FileInfo.MimeType, "audio") { return f.audio() } if strings.HasPrefix(f.FileInfo.MimeType, "text") { return f.text() } switch f.FileInfo.MimeType { case "application/ogg": return f.audio() case "application/matroska", "application/x-matroska": return f.video() case "application/pdf", "application/x-pdf": return f.pdf() case "application/octet-stream": // Fallback for when mime type not recognized switch filepath.Ext(f.FileInfo.Name) { case ".mp3": return f.audio() case ".mp4": return f.video() } } // none of the mime type checks triggered, so we return the default page return f.def() } func (f filePreview) image() string { return fmt.Sprintf(`
`, f.FileURL) } func (f filePreview) audio() string { return fmt.Sprintf(`


Audio
%s

`, f.FileInfo.Name, f.FileURL, ) } func (f filePreview) video() string { return fmt.Sprintf(`
`, f.FileURL, ) } func (f filePreview) pdf() string { u, _ := url.Parse(f.FileURL) return f.frame("/res/misc/pdf-viewer/web/viewer.html?file=" + u.String()) } func (f filePreview) text() string { htmlOut := `
%s
` if f.FileInfo.Size > 1e6 { // Prevent out of memory errors return fmt.Sprintf(htmlOut, "", "File is too large to view online.\nPlease download and view it locally.", ) } body, err := f.PixelAPI.GetFile(f.FileInfo.ID) if err != nil { log.Error("Can't download text file for preview: %s", err) return fmt.Sprintf(htmlOut, "", "An error occurred while downloading this file.", ) } defer body.Close() bodyBytes, err := ioutil.ReadAll(body) if err != nil { log.Error("Can't read text file for preview: %s", err) return fmt.Sprintf(htmlOut, "", "An error occurred while reading this file.", ) } converter := gonvert.New(string(bodyBytes), gonvert.UTF8) result, err := converter.Convert() if err != nil { log.Debug("Unable to decode text file: %s", err) return fmt.Sprintf(htmlOut, "", "This file is using an unknown character encoding.\nPlease download it and view it locally.", ) } result = html.EscapeString(result) var prettyPrint string if f.FileInfo.MimeType != "text/plain" { prettyPrint = "prettyprint linenums" htmlOut += `` } return fmt.Sprintf(htmlOut, prettyPrint, result) } func (f filePreview) frame(url string) string { return fmt.Sprintf(`