// 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()) }
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() }
// 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) }
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 }
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 }