package service import ( "context" "io/fs" "net/url" "path" "strings" "syscall" "git.sr.ht/~gabrielgio/img/pkg/database/repository" "git.sr.ht/~gabrielgio/img/pkg/list" ) type ( FileSystemController struct { fsRepository repository.FileSystemRepository userRepository repository.UserRepository } DirectoryParam struct { Name string UrlEncodedPath string } FileParam struct { UrlEncodedPath string Info fs.FileInfo } Page struct { History []*DirectoryParam Files []*FileParam } ) func (f *FileParam) GetUid() int { if stat, ok := f.Info.Sys().(*syscall.Stat_t); ok { return int(stat.Uid) } return 0 } func (f *FileParam) GetGid() int { if stat, ok := f.Info.Sys().(*syscall.Stat_t); ok { return int(stat.Gid) } return 0 } func NewFileSystemController( fsRepository repository.FileSystemRepository, userRepository repository.UserRepository, ) *FileSystemController { return &FileSystemController{ fsRepository: fsRepository, userRepository: userRepository, } } func getHistory(filepath string) []*DirectoryParam { var ( paths = strings.Split(filepath, "/") result = make([]*DirectoryParam, 0, len(paths)) acc = "" ) // add root folder result = append(result, &DirectoryParam{ Name: "...", UrlEncodedPath: "", }) if len(paths) == 1 && paths[0] == "" { return result } for _, p := range paths { acc = path.Join(acc, p) result = append(result, &DirectoryParam{ Name: p, UrlEncodedPath: url.QueryEscape(acc), }) } return result } func (self *FileSystemController) GetPage(ctx context.Context, userID uint, filepath string) (*Page, error) { userPath, err := self.userRepository.GetPathFromUserID(ctx, userID) if err != nil { return nil, err } decodedPath, err := url.QueryUnescape(filepath) if err != nil { return nil, err } fullPath := path.Join(userPath, decodedPath) files, err := self.fsRepository.List(fullPath) if err != nil { return nil, err } params := list.Map(files, func(info fs.FileInfo) *FileParam { fullPath := path.Join(decodedPath, info.Name()) scapedFullPath := url.QueryEscape(fullPath) return &FileParam{ Info: info, UrlEncodedPath: scapedFullPath, } }) return &Page{ Files: params, History: getHistory(decodedPath), }, nil }