Beispiel #1
0
// extractFile extracts zip.File to file system.
func extractFile(f *zip.File, destPath string) error {
	filePath := path.Join(destPath, f.Name)
	os.MkdirAll(path.Dir(filePath), os.ModePerm)

	rc, err := f.Open()
	if err != nil {
		return err
	}
	defer rc.Close()

	fw, err := os.Create(filePath)
	if err != nil {
		return err
	}
	defer fw.Close()

	if _, err = io.Copy(fw, rc); err != nil {
		return err
	}

	// Skip symbolic links.
	if f.FileInfo().Mode()&os.ModeSymlink != 0 {
		return nil
	}
	// Set back file information.
	if err = os.Chtimes(filePath, f.ModTime(), f.ModTime()); err != nil {
		return err
	}
	return os.Chmod(filePath, f.FileInfo().Mode())
}
Beispiel #2
0
func zipAttr(f *zip.File, a *fuse.Attr) {
	a.Size = f.UncompressedSize64
	a.Mode = f.Mode()
	a.Mtime = f.ModTime()
	a.Ctime = f.ModTime()
	a.Crtime = f.ModTime()
}
Beispiel #3
0
// serveStandard extracts the file from the zip file to a temporary
// location and serves it using the std library. This only happens
// for more complicated requests, such as range requests.
func serveStandard(w http.ResponseWriter, r *http.Request, f *zip.File) {
	tempFile, err := createTempFile(f)
	if err != nil {
		internalServerError(w, r, err)
		return
	}
	defer func() {
		tempFile.Close()
		os.Remove(tempFile.Name())
	}()

	http.ServeContent(w, r, f.Name, f.ModTime(), tempFile)
}
Beispiel #4
0
func unzipFile(f *zip.File, destPath string) error {
	pathSeparator := string(os.PathSeparator)

	rc, err := f.Open()
	if err != nil {
		return err
	}
	defer func() {
		if err := rc.Close(); err != nil {
			log.Println(err)
		}
	}()

	filePath := sanitize(f.Name)
	sepInd := strings.LastIndex(filePath, pathSeparator)

	// If the file is a subdirectory, it creates it before attempting to
	// create the actual file
	if sepInd > -1 {
		directory := filePath[0:sepInd]
		if err := os.MkdirAll(filepath.Join(destPath, directory), 0740); err != nil {
			return err
		}
	}

	file, err := os.Create(filepath.Join(destPath, filePath))
	if err != nil {
		return err
	}

	defer func() {
		if err := file.Close(); err != nil {
			log.Println(err)
		}
	}()

	file.Chmod(f.Mode())
	os.Chtimes(file.Name(), time.Now(), f.ModTime())

	if _, err := io.CopyN(file, rc, int64(f.UncompressedSize64)); err != nil {
		return err
	}

	return nil
}
Beispiel #5
0
func parse(rd readerAt, progress func(progress float64), makeCanvas func(seqID int, layer *psd.Layer)) (*root, error) {
	var r root
	s := time.Now().UnixNano()

	if rd.Size() < 4 {
		return nil, errors.New("unsupported file type")
	}
	var head [4]byte
	if _, err := rd.ReadAt(head[:], 0); err != nil {
		return nil, err
	}
	var psdReader *genericProgressReader
	switch string(head[:]) {
	case "PK\x03\x04": // zip archive
		zr, err := zip.NewReader(rd, rd.Size())
		if err != nil {
			return nil, err
		}
		var psdf, pfvf, txtf *zip.File
		for _, f := range zr.File {
			if psdf == nil && strings.ToLower(f.Name[len(f.Name)-4:]) == ".psd" {
				psdf = f
				continue
			}
			if psdf == nil && strings.ToLower(f.Name[len(f.Name)-4:]) == ".psb" {
				psdf = f
				continue
			}
			if pfvf == nil && strings.ToLower(f.Name[len(f.Name)-4:]) == ".pfv" {
				pfvf = f
				continue
			}
			if txtf == nil && strings.ToLower(f.Name[len(f.Name)-4:]) == ".txt" {
				txtf = f
				continue
			}
		}
		if psdf == nil {
			return nil, errors.New("psd file is not found from given zip archive")
		}

		if pfvf != nil {
			var pfvr io.ReadCloser
			pfvr, err = pfvf.Open()
			if err != nil {
				return nil, err
			}
			defer pfvr.Close()
			r.PFVModDate = pfvf.ModTime().Unix()
			r.PFV, err = readTextFile(pfvr)
			if err != nil {
				return nil, err
			}
		}

		if txtf != nil {
			var txtr io.ReadCloser
			txtr, err = txtf.Open()
			if err != nil {
				return nil, err
			}
			defer txtr.Close()
			r.Readme, err = readTextFile(txtr)
			if err != nil {
				return nil, err
			}
		}

		rc, err := zipFileOpenFast(rd, psdf, 1024*1024*100)
		if err != nil {
			return nil, err
		}
		defer rc.Close()
		psdReader = &genericProgressReader{
			R:        rc,
			Hash:     md5.New(),
			Progress: progress,
			size:     int(psdf.UncompressedSize64),
		}
	case "7z\xbc\xaf": // 7z archive
		return nil, errors.New("7z archive is not supported")
	case "8BPS": // psd file
		psdReader = &genericProgressReader{
			R:        bufio.NewReaderSize(rd, 1024*1024*2),
			Hash:     md5.New(),
			Progress: progress,
			size:     int(rd.Size()),
		}
		break
	default:
		return nil, errors.New("unsupported file type")
	}
	psdImg, _, err := psd.Decode(psdReader, &psd.DecodeOptions{
		LayerImageLoaded: func(layer *psd.Layer, index int, total int) {
			makeCanvas(index, layer)
			layer.Picker = nil
			layer.Channel = nil
		},
		SkipMergedImage: true,
	})
	if err != nil {
		return nil, err
	}
	e := time.Now().UnixNano()
	progress(1)
	log.Println("decode PSD structure:", (e-s)/1e6)

	if psdImg.Config.ColorMode != psd.ColorModeRGB {
		return nil, errors.New("Unsupported color mode")
	}

	s = time.Now().UnixNano()
	r.Hash = fmt.Sprintf("%x", psdReader.Sum())
	if err = r.Build(psdImg); err != nil {
		return nil, err
	}
	e = time.Now().UnixNano()
	log.Println("build layer tree:", (e-s)/1e6)
	return &r, nil
}