diff --git a/.gitignore b/.gitignore index ee2774fd..6935b232 100644 --- a/.gitignore +++ b/.gitignore @@ -6,7 +6,7 @@ rice-box.go /filebrowser /filebrowser.exe /dist -/src/backend/vendor/* +/src/backend/vendor .DS_Store node_modules diff --git a/Dockerfile b/Dockerfile index a6feaaf8..d8ae4f28 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,8 @@ -FROM node:14.21-slim as nbuild +FROM node:slim as nbuild WORKDIR /app -COPY ./src/frontend ./ +COPY ./src/frontend/package*.json ./ RUN npm i +COPY ./src/frontend/ ./ RUN npm run build FROM golang:alpine as base diff --git a/src/backend/http/search.go b/src/backend/http/search.go index 0a05c0ad..304da28b 100644 --- a/src/backend/http/search.go +++ b/src/backend/http/search.go @@ -8,12 +8,17 @@ import ( var searchHandler = withUser(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) { response := []map[string]interface{}{} query := r.URL.Query().Get("query") - files, dirs := search.SearchAllIndexes(query, r.URL.Path) - for _,v := range(files){ - response = append(response, map[string]interface{}{ - "dir": false, - "path": v, - }) + files, dirs, fileTypes := search.SearchAllIndexes(query, r.URL.Path) + for _,path := range(files){ + f := fileTypes[path] + responseObj := map[string]interface{}{ + "dir" : false, + "path" : path, + } + for _,filterType := range(search.FilterableTypes) { + if f[filterType] { responseObj[filterType] = f[filterType] } + } + response = append(response,responseObj) } for _,v := range(dirs){ response = append(response, map[string]interface{}{ diff --git a/src/backend/search/conditions.go b/src/backend/search/conditions.go index 9c7e3a58..025d37bb 100644 --- a/src/backend/search/conditions.go +++ b/src/backend/search/conditions.go @@ -11,6 +11,8 @@ var documentTypes = []string{ ".word", ".pdf", ".txt", + ".doc", + ".docx", } var compressedFile = []string{ @@ -45,7 +47,6 @@ func ParseSearch(value string) *searchOptions { if len(filterType) == 1 { continue } - switch filterType[1] { case "image": opts.Conditions["image"] = true @@ -55,8 +56,8 @@ func ParseSearch(value string) *searchOptions { opts.Conditions["video"] = true case "doc": opts.Conditions["doc"] = true - case "zip": - opts.Conditions["zip"] = true + case "archive": + opts.Conditions["archive"] = true } } diff --git a/src/backend/search/indexing.go b/src/backend/search/indexing.go index 21d70335..2bd281f8 100644 --- a/src/backend/search/indexing.go +++ b/src/backend/search/indexing.go @@ -13,7 +13,8 @@ import ( var ( rootPath string = "/srv" - indexes map[string][]string + indexes = map[string][]string{} + FilterableTypes = []string{"audio","image","video","doc","archive"} mutex sync.RWMutex lastIndexed time.Time ) @@ -21,6 +22,8 @@ var ( func InitializeIndex(intervalMinutes uint32) { // Initialize the indexes map indexes = make(map[string][]string) + indexes["dirs"] = []string{} + indexes["files"] = []string{} var numFiles, numDirs int log.Println("Indexing files...") lastIndexedStart := time.Now() @@ -79,78 +82,80 @@ func indexFiles(path string, numFiles *int, numDirs *int) (int, int, error) { for _, file := range files { if file.IsDir() { *numDirs++ - indexFiles(path+"/"+file.Name(), numFiles, numDirs) + addToIndex(path, file.Name(), true) + indexFiles(path+"/"+file.Name(), numFiles, numDirs) // recursive + } else { + *numFiles++ + addToIndex(path, file.Name(), false) } - *numFiles++ - addToIndex(path, file.Name()) } return *numFiles, *numDirs, nil } -func addToIndex(path string, fileName string) { +func addToIndex(path string, fileName string, isDir bool) { mutex.Lock() defer mutex.Unlock() path = strings.TrimPrefix(path, rootPath+"/") path = strings.TrimSuffix(path, "/") + adjustedPath := path + "/" + fileName if path == rootPath { - path = "/" + adjustedPath = fileName } - info, exists := indexes[path] - if !exists { - info = []string{} + if isDir { + indexes["dirs"] = append(indexes["dirs"], adjustedPath) + }else{ + indexes["files"] = append(indexes["files"], adjustedPath) } - info = append(info, fileName) - indexes[path] = info } -func SearchAllIndexes(search string, scope string) ([]string, []string) { +func SearchAllIndexes(search string, scope string) ([]string, []string, map[string]map[string]bool) { searchOptions := ParseSearch(search) mutex.RLock() defer mutex.RUnlock() + fileListTypes := make(map[string]map[string]bool) var matchingFiles []string var matchingDirs []string - maximum := 100 - count := 0 + maximum := 125 + for _, searchTerm := range searchOptions.Terms { if searchTerm == "" { continue } + count := 0 // Iterate over the indexes - for dirName, v := range indexes { + for _, dirName := range indexes["dirs"] { if count > maximum { break } - searchItems := v - // Iterate over the path names - for _, pathName := range searchItems { - if count > maximum { - break - } - if dirName != "/" { - pathName = dirName + "/" + pathName - } - // Check if the path name contains the search term - if !containsSearchTerm(pathName, searchTerm, searchOptions.Conditions) { - continue - } - pathName = scopedPathNameFilter(pathName, scope) - if pathName == "" { - continue - } - count++ - matchingFiles = append(matchingFiles, pathName) - } - // Check if the path name contains the search term - if !containsSearchTerm(dirName, searchTerm, searchOptions.Conditions) { - continue - } pathName := scopedPathNameFilter(dirName, scope) if pathName == "" { continue } + matches, _ := containsSearchTerm(pathName, searchTerm, searchOptions.Conditions) + if !matches { + continue + } count++ matchingDirs = append(matchingDirs, pathName) } + count = 0 + for _, fileName := range indexes["files"] { + if count > maximum { + break + } + pathName := scopedPathNameFilter(fileName, scope) + if pathName == "" { + continue + } + // Check if the path name contains the search term + matches, fileType := containsSearchTerm(pathName, searchTerm, searchOptions.Conditions) + if !matches { + continue + } + matchingFiles = append(matchingFiles, pathName) + fileListTypes[pathName] = fileType + count++ + } } // Sort the strings based on the number of elements after splitting by "/" sort.Slice(matchingFiles, func(i, j int) bool { @@ -164,7 +169,7 @@ func SearchAllIndexes(search string, scope string) ([]string, []string) { parts2 := strings.Split(matchingDirs[j], "/") return len(parts1) < len(parts2) }) - return matchingFiles, matchingDirs + return matchingFiles, matchingDirs, fileListTypes } func scopedPathNameFilter(pathName string, scope string) string { @@ -177,51 +182,51 @@ func scopedPathNameFilter(pathName string, scope string) string { return pathName } -func containsSearchTerm(pathName string, searchTerm string, conditions map[string]bool) bool { - path := getLastPathComponent(pathName) +func containsSearchTerm(pathName string, searchTerm string, conditions map[string]bool) (bool, map[string]bool) { + path := getLastPathComponent(pathName) + fileTypes := map[string]bool{} + matchesCondition := false + extension := filepath.Ext(strings.ToLower(path)) + mimetype := mime.TypeByExtension(extension) + filterTypes := FilterableTypes + fileTypes["audio"] = strings.HasPrefix(mimetype, "audio") + fileTypes["image"] = strings.HasPrefix(mimetype, "image") + fileTypes["video"] = strings.HasPrefix(mimetype, "video") + fileTypes["doc"] = isDoc(extension) + fileTypes["archive"] = isArchive(extension) + anyFilter := false + for _,t := range(filterTypes){ + if conditions[t] { + anyFilter = true + matchesCondition = fileTypes[t] + } + } + if !anyFilter { + matchesCondition = true + } if !conditions["exact"] { path = strings.ToLower(path) searchTerm = strings.ToLower(searchTerm) } - matchesCondition := true - if conditions["audio"] { - extension := filepath.Ext(path) - mimetype := mime.TypeByExtension(extension) - matchesCondition = strings.HasPrefix(mimetype, "audio") - } - if conditions["video"] { - extension := filepath.Ext(path) - mimetype := mime.TypeByExtension(extension) - matchesCondition = strings.HasPrefix(mimetype, "video") - } - if conditions["image"] { - extension := filepath.Ext(path) - mimetype := mime.TypeByExtension(extension) - matchesCondition = strings.HasPrefix(mimetype, "image") - } - if conditions["doc"] { - extension := filepath.Ext(path) - for _, typefile := range documentTypes { - if extension == typefile { - matchesCondition = true - continue - } else { - matchesCondition = false - } + return strings.Contains(path, searchTerm) && matchesCondition, fileTypes +} + +func isDoc(extension string) bool { + for _, typefile := range documentTypes { + if extension == typefile { + return true } - } - if conditions["zip"] { - extension := filepath.Ext(path) - for _, typefile := range compressedFile { - if extension == typefile { - matchesCondition = true - continue - } else { - matchesCondition = false - } + } + return false +} + +func isArchive(extension string) bool { + for _, typefile := range compressedFile { + if extension == typefile { + return true } - } - return strings.Contains(path, searchTerm) && matchesCondition + } + return false } func getLastPathComponent(path string) string { diff --git a/src/frontend/src/components/Search.vue b/src/frontend/src/components/Search.vue index ab2ec4a9..09cac6dd 100644 --- a/src/frontend/src/components/Search.vue +++ b/src/frontend/src/components/Search.vue @@ -24,7 +24,9 @@
{{ text }}
@@ -48,11 +50,16 @@