mirror of https://github.com/Xhofe/alist
				
				
				
			
		
			
				
	
	
		
			115 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Go
		
	
	
			
		
		
	
	
			115 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Go
		
	
	
| // Copyright 2014 The Go Authors. All rights reserved.
 | |
| // Use of this source code is governed by a BSD-style
 | |
| // license that can be found in the LICENSE file.
 | |
| 
 | |
| package webdav
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"net/http"
 | |
| 	"path"
 | |
| 	"path/filepath"
 | |
| 
 | |
| 	"github.com/alist-org/alist/v3/internal/fs"
 | |
| 	"github.com/alist-org/alist/v3/internal/model"
 | |
| 	"github.com/alist-org/alist/v3/internal/op"
 | |
| )
 | |
| 
 | |
| // slashClean is equivalent to but slightly more efficient than
 | |
| // path.Clean("/" + name).
 | |
| func slashClean(name string) string {
 | |
| 	if name == "" || name[0] != '/' {
 | |
| 		name = "/" + name
 | |
| 	}
 | |
| 	return path.Clean(name)
 | |
| }
 | |
| 
 | |
| // moveFiles moves files and/or directories from src to dst.
 | |
| //
 | |
| // See section 9.9.4 for when various HTTP status codes apply.
 | |
| func moveFiles(ctx context.Context, src, dst string, overwrite bool) (status int, err error) {
 | |
| 	srcDir := path.Dir(src)
 | |
| 	dstDir := path.Dir(dst)
 | |
| 	srcName := path.Base(src)
 | |
| 	dstName := path.Base(dst)
 | |
| 	if srcDir == dstDir {
 | |
| 		err = fs.Rename(ctx, src, dstName)
 | |
| 	} else {
 | |
| 		err = fs.Move(ctx, src, dstDir)
 | |
| 		if err != nil {
 | |
| 			return http.StatusInternalServerError, err
 | |
| 		}
 | |
| 		if srcName != dstName {
 | |
| 			err = fs.Rename(ctx, path.Join(dstDir, srcName), dstName)
 | |
| 		}
 | |
| 	}
 | |
| 	if err != nil {
 | |
| 		return http.StatusInternalServerError, err
 | |
| 	}
 | |
| 	// TODO if there are no files copy, should return 204
 | |
| 	return http.StatusCreated, nil
 | |
| }
 | |
| 
 | |
| // copyFiles copies files and/or directories from src to dst.
 | |
| //
 | |
| // See section 9.8.5 for when various HTTP status codes apply.
 | |
| func copyFiles(ctx context.Context, src, dst string, overwrite bool) (status int, err error) {
 | |
| 	_, err = fs.Copy(ctx, src, dst)
 | |
| 	if err != nil {
 | |
| 		return http.StatusInternalServerError, err
 | |
| 	}
 | |
| 	// TODO if there are no files copy, should return 204
 | |
| 	return http.StatusCreated, nil
 | |
| }
 | |
| 
 | |
| // walkFS traverses filesystem fs starting at name up to depth levels.
 | |
| //
 | |
| // Allowed values for depth are 0, 1 or infiniteDepth. For each visited node,
 | |
| // walkFS calls walkFn. If a visited file system node is a directory and
 | |
| // walkFn returns path.SkipDir, walkFS will skip traversal of this node.
 | |
| func walkFS(ctx context.Context, depth int, name string, info model.Obj, walkFn func(reqPath string, info model.Obj, err error) error) error {
 | |
| 	// This implementation is based on Walk's code in the standard path/path package.
 | |
| 	err := walkFn(name, info, nil)
 | |
| 	if err != nil {
 | |
| 		if info.IsDir() && err == filepath.SkipDir {
 | |
| 			return nil
 | |
| 		}
 | |
| 		return err
 | |
| 	}
 | |
| 	if !info.IsDir() || depth == 0 {
 | |
| 		return nil
 | |
| 	}
 | |
| 	if depth == 1 {
 | |
| 		depth = 0
 | |
| 	}
 | |
| 	meta, _ := op.GetNearestMeta(name)
 | |
| 	// Read directory names.
 | |
| 	objs, err := fs.List(context.WithValue(ctx, "meta", meta), name, &fs.ListArgs{})
 | |
| 	//f, err := fs.OpenFile(ctx, name, os.O_RDONLY, 0)
 | |
| 	//if err != nil {
 | |
| 	//	return walkFn(name, info, err)
 | |
| 	//}
 | |
| 	//fileInfos, err := f.Readdir(0)
 | |
| 	//f.Close()
 | |
| 	if err != nil {
 | |
| 		return walkFn(name, info, err)
 | |
| 	}
 | |
| 
 | |
| 	for _, fileInfo := range objs {
 | |
| 		filename := path.Join(name, fileInfo.GetName())
 | |
| 		if err != nil {
 | |
| 			if err := walkFn(filename, fileInfo, err); err != nil && err != filepath.SkipDir {
 | |
| 				return err
 | |
| 			}
 | |
| 		} else {
 | |
| 			err = walkFS(ctx, depth, filename, fileInfo, walkFn)
 | |
| 			if err != nil {
 | |
| 				if !fileInfo.IsDir() || err != filepath.SkipDir {
 | |
| 					return err
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 	return nil
 | |
| }
 |