示例#1
0
// FixContentType ensures proper content-type
// (uses mimemagic for "" and application/octet-stream)
func FixContentType(body []byte, contentType, fileName string) string {
	switch contentType {
	case "application/x-zip-compressed":
		return "application/zip"
	case "application/x-rar-compressed":
		return "application/rar"
	case "", "application/octet-stream", "application/pdf", "application/x-as400attachment", "application/save-as":
		//log.Printf("body=%s", body)
		if nct := mimemagic.Match(contentType, body); nct != "" {
			return nct
		}
	}
	if GetConverter(contentType, nil) == nil { // no converter for this
		if nct := mimemagic.Match(contentType, body); nct != "" {
			return nct
		}
	}
	if fileName != "" &&
		(contentType == "" || contentType == "application/octet-stream" ||
			GetConverter(contentType, nil) == nil) {
		if i := strings.LastIndex(fileName, "."); i >= 0 {
			if nct, ok := ExtContentType[fileName[i+1:]]; ok {
				return nct
			}
			if nct := mime.TypeByExtension(fileName[i:]); nct != "" {
				return nct
			}
		}
	}
	//log.Printf("ct=%s ==> %s", ct, contentType)
	return contentType
}
示例#2
0
func guessMime(path string, buf []byte) string {
	s := mimemagic.Match("", buf)
	if s == "" {
		s = mime.TypeByExtension(filepath.Ext(path))
	}
	for _, extension := range TextFileExtensions {
		if extension == filepath.Ext(path) {
			return "text/generic"
		}
	}
	return s
}
func main() {
	b := make([]byte, 1024)
	for _, fn := range os.Args {
		f, e := os.Open(fn)
		if e != nil {
			panic(e)
		}
		f.Read(b)
		fmt.Printf("%-30s %s\n", mimemagic.Match("", b), fn)
		f.Close()
	}
}
示例#4
0
func processUpload(upReq UploadRequest) (upload Upload, err error) {
	// Determine the appropriate filename, then write to disk
	barename, extension := barePlusExt(upReq.filename)

	if upReq.randomBarename || len(barename) == 0 {
		barename = generateBarename()
	}

	var header []byte
	if len(extension) == 0 {
		// Pull the first 512 bytes off for use in MIME detection
		header = make([]byte, 512)
		n, _ := upReq.src.Read(header)
		if n == 0 {
			return upload, errors.New("Empty file")
		}
		header = header[:n]

		// Determine the type of file from header
		mimetype := mimemagic.Match("", header)

		// If the mime type is in our map, use that
		// otherwise just use "ext"
		if val, exists := mimeToExtension[mimetype]; exists {
			extension = val
		} else {
			extension = "ext"
		}
	}

	upload.Filename = strings.Join([]string{barename, extension}, ".")

	_, err = os.Stat(path.Join(Config.filesDir, upload.Filename))

	fileexists := err == nil
	// Check if the delete key matches, in which case overwrite
	if fileexists {
		metad, merr := metadataRead(upload.Filename)
		if merr == nil {
			if upReq.deletionKey == metad.DeleteKey {
				fileexists = false
			}
		}
	}

	for fileexists {
		counter, err := strconv.Atoi(string(barename[len(barename)-1]))
		if err != nil {
			barename = barename + "1"
		} else {
			barename = barename[:len(barename)-1] + strconv.Itoa(counter+1)
		}
		upload.Filename = strings.Join([]string{barename, extension}, ".")

		_, err = os.Stat(path.Join(Config.filesDir, upload.Filename))
		fileexists = err == nil
	}

	if fileBlacklist[strings.ToLower(upload.Filename)] {
		return upload, errors.New("Prohibited filename")
	}

	dst, err := os.Create(path.Join(Config.filesDir, upload.Filename))
	if err != nil {
		return
	}
	defer dst.Close()

	// Get the rest of the metadata needed for storage
	var expiry time.Time
	if upReq.expiry == 0 {
		expiry = neverExpire
	} else {
		expiry = time.Now().Add(upReq.expiry)
	}

	bytes, err := io.Copy(dst, io.MultiReader(bytes.NewReader(header), upReq.src))
	if bytes == 0 {
		os.Remove(path.Join(Config.filesDir, upload.Filename))
		return upload, errors.New("Empty file")

	} else if err != nil {
		os.Remove(path.Join(Config.filesDir, upload.Filename))
		return
	} else if bytes > Config.maxSize {
		os.Remove(path.Join(Config.filesDir, upload.Filename))
		return upload, errors.New("File too large")
	}

	upload.Metadata, err = generateMetadata(upload.Filename, expiry, upReq.deletionKey)
	if err != nil {
		os.Remove(path.Join(Config.filesDir, upload.Filename))
		os.Remove(path.Join(Config.metaDir, upload.Filename))
		return
	}
	err = metadataWrite(upload.Filename, &upload.Metadata)
	if err != nil {
		os.Remove(path.Join(Config.filesDir, upload.Filename))
		os.Remove(path.Join(Config.metaDir, upload.Filename))
		return
	}
	return
}
示例#5
0
func fileDisplayHandler(c web.C, w http.ResponseWriter, r *http.Request) {
	fileName := c.URLParams["name"]
	filePath := path.Join(Config.filesDir, fileName)
	fileInfo, err := os.Stat(filePath)

	if !fileExistsAndNotExpired(fileName) {
		notFoundHandler(c, w, r)
		return
	}

	expiry, _ := metadataGetExpiry(fileName)
	var expiryHuman string
	if !expiry.IsZero() {
		expiryHuman = humanize.RelTime(time.Now(), expiry, "", "")
	}
	sizeHuman := humanize.Bytes(uint64(fileInfo.Size()))
	extra := make(map[string]string)

	file, _ := os.Open(filePath)
	header := make([]byte, 512)
	file.Read(header)
	file.Close()

	mimetype := mimemagic.Match("", header)
	extension := strings.TrimPrefix(filepath.Ext(fileName), ".")

	if strings.EqualFold("application/json", r.Header.Get("Accept")) {
		js, _ := json.Marshal(map[string]string{
			"filename": fileName,
			"mimetype": mimetype,
			"expiry":   strconv.FormatInt(expiry.Unix(), 10),
			"size":     strconv.FormatInt(fileInfo.Size(), 10),
		})
		w.Write(js)
		return
	}

	var tpl *pongo2.Template

	if strings.HasPrefix(mimetype, "image/") {
		tpl = Templates["display/image.html"]
	} else if strings.HasPrefix(mimetype, "video/") {
		tpl = Templates["display/video.html"]
	} else if strings.HasPrefix(mimetype, "audio/") {
		tpl = Templates["display/audio.html"]
	} else if mimetype == "application/pdf" {
		tpl = Templates["display/pdf.html"]
	} else if supportedBinExtension(extension) {
		if fileInfo.Size() < maxDisplayFileSizeBytes {
			bytes, err := ioutil.ReadFile(filePath)
			if err != nil {
				tpl = Templates["display/file.html"]
			} else {
				extra["extension"] = extension
				extra["lang_hl"], extra["lang_ace"] = extensionToHlAndAceLangs(extension)
				extra["contents"] = string(bytes)
				tpl = Templates["display/bin.html"]
			}
		} else {
			tpl = Templates["display/file.html"]
		}
	} else {
		tpl = Templates["display/file.html"]
	}

	err = tpl.ExecuteWriter(pongo2.Context{
		"mime":     mimetype,
		"filename": fileName,
		"size":     sizeHuman,
		"expiry":   expiryHuman,
		"extra":    extra,
	}, w)

	if err != nil {
		oopsHandler(c, w, r, RespHTML, "")
	}
}
示例#6
0
func generateMetadata(fName string, exp time.Time, delKey string) (m Metadata, err error) {
	file, err := fileBackend.Open(fName)
	if err != nil {
		return
	}
	defer file.Close()

	m.Size, err = fileBackend.Size(fName)
	if err != nil {
		return
	}

	m.Expiry = exp

	if delKey == "" {
		m.DeleteKey = uniuri.NewLen(30)
	} else {
		m.DeleteKey = delKey
	}

	// Get first 512 bytes for mimetype detection
	header := make([]byte, 512)
	file.Read(header)

	m.Mimetype = mimemagic.Match("", header)

	if m.Mimetype == "" {
		// Check if the file seems anything like text
		if printable(header) {
			m.Mimetype = "text/plain"
		} else {
			m.Mimetype = "application/octet-stream"
		}
	}

	// Compute the sha256sum
	hasher := sha256.New()
	file.Seek(0, 0)
	_, err = io.Copy(hasher, file)
	if err == nil {
		m.Sha256sum = hex.EncodeToString(hasher.Sum(nil))
	}
	file.Seek(0, 0)

	// If archive, grab list of filenames
	if m.Mimetype == "application/x-tar" {
		tReadr := tar.NewReader(file)
		for {
			hdr, err := tReadr.Next()
			if err == io.EOF || err != nil {
				break
			}
			if hdr.Typeflag == tar.TypeDir || hdr.Typeflag == tar.TypeReg {
				m.ArchiveFiles = append(m.ArchiveFiles, hdr.Name)
			}
		}
		sort.Strings(m.ArchiveFiles)
	} else if m.Mimetype == "application/x-gzip" {
		gzf, err := gzip.NewReader(file)
		if err == nil {
			tReadr := tar.NewReader(gzf)
			for {
				hdr, err := tReadr.Next()
				if err == io.EOF || err != nil {
					break
				}
				if hdr.Typeflag == tar.TypeDir || hdr.Typeflag == tar.TypeReg {
					m.ArchiveFiles = append(m.ArchiveFiles, hdr.Name)
				}
			}
			sort.Strings(m.ArchiveFiles)
		}
	} else if m.Mimetype == "application/x-bzip" {
		bzf := bzip2.NewReader(file)
		tReadr := tar.NewReader(bzf)
		for {
			hdr, err := tReadr.Next()
			if err == io.EOF || err != nil {
				break
			}
			if hdr.Typeflag == tar.TypeDir || hdr.Typeflag == tar.TypeReg {
				m.ArchiveFiles = append(m.ArchiveFiles, hdr.Name)
			}
		}
		sort.Strings(m.ArchiveFiles)
	} else if m.Mimetype == "application/zip" {
		zf, err := zip.NewReader(file, m.Size)
		if err == nil {
			for _, f := range zf.File {
				m.ArchiveFiles = append(m.ArchiveFiles, f.Name)
			}
		}
		sort.Strings(m.ArchiveFiles)
	}

	return
}
示例#7
0
func processUpload(upReq UploadRequest) (upload Upload, err error) {
	// Determine the appropriate filename, then write to disk
	barename, extension := barePlusExt(upReq.filename)

	if upReq.randomBarename || len(barename) == 0 {
		barename = generateBarename()
	}

	var header []byte
	if len(extension) == 0 {
		// Pull the first 512 bytes off for use in MIME detection
		header = make([]byte, 512)
		n, err := upReq.src.Read(header)
		if n == 0 || err != nil {
			return upload, errors.New("Empty file")
		}
		header = header[:n]

		// Determine the type of file from header
		mimetype := mimemagic.Match("", header)

		// If the mime type is in our map, use that
		// otherwise just use "ext"
		if val, exists := mimeToExtension[mimetype]; exists {
			extension = val
		} else {
			extension = "ext"
		}
	}

	upload.Filename = strings.Join([]string{barename, extension}, ".")

	_, err = os.Stat(path.Join(Config.filesDir, upload.Filename))

	fileexists := err == nil
	for fileexists {
		counter, err := strconv.Atoi(string(barename[len(barename)-1]))
		if err != nil {
			barename = barename + "1"
		} else {
			barename = barename[:len(barename)-1] + strconv.Itoa(counter+1)
		}
		upload.Filename = strings.Join([]string{barename, extension}, ".")

		_, err = os.Stat(path.Join(Config.filesDir, upload.Filename))
		fileexists = err == nil
	}

	if fileBlacklist[strings.ToLower(upload.Filename)] {
		return upload, errors.New("Prohibited filename")
	}

	dst, err := os.Create(path.Join(Config.filesDir, upload.Filename))
	if err != nil {
		return
	}
	defer dst.Close()

	// Get the rest of the metadata needed for storage
	if upReq.expiry != 0 {
		upload.Expiry = time.Now().Add(upReq.expiry)
	}

	// If no delete key specified, pick a random one.
	if upReq.deletionKey == "" {
		upload.DeleteKey = uniuri.NewLen(30)
	} else {
		upload.DeleteKey = upReq.deletionKey
	}

	metadataWrite(upload.Filename, &upload)

	bytes, err := io.Copy(dst, io.MultiReader(bytes.NewReader(header), upReq.src))
	if bytes == 0 {
		os.Remove(path.Join(Config.filesDir, upload.Filename))
		os.Remove(path.Join(Config.metaDir, upload.Filename))
		return upload, errors.New("Empty file")

	} else if err != nil {
		os.Remove(path.Join(Config.filesDir, upload.Filename))
		os.Remove(path.Join(Config.metaDir, upload.Filename))
		return
	}

	upload.Size = bytes
	return
}
示例#8
0
func detectContentType(sample []byte) (string, error) {
	return mimemagic.Match("", sample), nil
}