2023-12-01 23:47:00 +00:00
|
|
|
package files
|
2023-06-15 01:08:09 +00:00
|
|
|
|
|
|
|
import (
|
2023-08-12 16:30:41 +00:00
|
|
|
"math/rand"
|
2023-06-15 01:08:09 +00:00
|
|
|
"os"
|
|
|
|
"path/filepath"
|
2023-06-18 15:04:31 +00:00
|
|
|
"sort"
|
2023-06-15 01:08:09 +00:00
|
|
|
"strings"
|
2023-06-16 17:29:43 +00:00
|
|
|
"sync"
|
2023-06-15 01:08:09 +00:00
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
2023-06-16 17:29:43 +00:00
|
|
|
var (
|
2023-09-30 14:18:21 +00:00
|
|
|
sessionInProgress sync.Map
|
2023-12-01 23:47:00 +00:00
|
|
|
maxSearchResults = 100
|
2023-06-16 17:29:43 +00:00
|
|
|
)
|
2023-06-15 01:08:09 +00:00
|
|
|
|
2023-09-30 14:18:21 +00:00
|
|
|
func (si *Index) Search(search string, scope string, sourceSession string) ([]string, map[string]map[string]bool) {
|
2023-10-18 15:32:22 +00:00
|
|
|
if scope == "" {
|
|
|
|
scope = "/"
|
|
|
|
}
|
2023-07-21 22:41:24 +00:00
|
|
|
runningHash := generateRandomHash(4)
|
|
|
|
sessionInProgress.Store(sourceSession, runningHash) // Store the value in the sync.Map
|
2023-06-18 15:04:31 +00:00
|
|
|
searchOptions := ParseSearch(search)
|
2023-07-13 02:23:29 +00:00
|
|
|
fileListTypes := make(map[string]map[string]bool)
|
2023-10-18 15:32:22 +00:00
|
|
|
matching := []string{}
|
2023-12-01 23:47:00 +00:00
|
|
|
count := 0
|
|
|
|
|
2023-06-18 15:04:31 +00:00
|
|
|
for _, searchTerm := range searchOptions.Terms {
|
2023-07-04 23:55:15 +00:00
|
|
|
if searchTerm == "" {
|
|
|
|
continue
|
|
|
|
}
|
2023-12-01 23:47:00 +00:00
|
|
|
si.mu.Lock()
|
|
|
|
defer si.mu.Unlock()
|
|
|
|
for dirName, dir := range si.Directories {
|
|
|
|
isDir := true
|
|
|
|
files := strings.Split(dir.Files, ";")
|
|
|
|
value, found := sessionInProgress.Load(sourceSession)
|
|
|
|
if !found || value != runningHash {
|
|
|
|
return []string{}, map[string]map[string]bool{}
|
|
|
|
}
|
|
|
|
if count > maxSearchResults {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
pathName := scopedPathNameFilter(dirName, scope, isDir)
|
|
|
|
if pathName == "" {
|
|
|
|
continue // path not matched
|
|
|
|
}
|
2023-09-30 14:18:21 +00:00
|
|
|
|
2023-12-01 23:47:00 +00:00
|
|
|
fileTypes := map[string]bool{}
|
|
|
|
matches, fileType := containsSearchTerm(dirName, searchTerm, *searchOptions, isDir, fileTypes)
|
|
|
|
if matches {
|
|
|
|
fileListTypes[pathName] = fileType
|
|
|
|
matching = append(matching, pathName)
|
|
|
|
count++
|
2023-09-30 14:18:21 +00:00
|
|
|
}
|
2023-12-01 23:47:00 +00:00
|
|
|
isDir = false
|
|
|
|
for _, file := range files {
|
|
|
|
if file == "" {
|
|
|
|
continue
|
|
|
|
}
|
2023-08-17 21:46:49 +00:00
|
|
|
value, found := sessionInProgress.Load(sourceSession)
|
|
|
|
if !found || value != runningHash {
|
|
|
|
return []string{}, map[string]map[string]bool{}
|
|
|
|
}
|
2023-12-01 23:47:00 +00:00
|
|
|
|
2023-09-30 14:18:21 +00:00
|
|
|
if count > maxSearchResults {
|
2023-08-17 21:46:49 +00:00
|
|
|
break
|
|
|
|
}
|
2023-12-01 23:47:00 +00:00
|
|
|
fullName := pathName + file
|
2023-10-23 00:23:38 +00:00
|
|
|
fileTypes := map[string]bool{}
|
2023-12-01 23:47:00 +00:00
|
|
|
|
|
|
|
matches, fileType := containsSearchTerm(fullName, searchTerm, *searchOptions, isDir, fileTypes)
|
2023-07-21 22:41:24 +00:00
|
|
|
if !matches {
|
|
|
|
continue
|
|
|
|
}
|
2023-12-01 23:47:00 +00:00
|
|
|
|
|
|
|
fileListTypes[fullName] = fileType
|
|
|
|
matching = append(matching, fullName)
|
2023-07-21 22:41:24 +00:00
|
|
|
count++
|
2023-07-13 02:23:29 +00:00
|
|
|
}
|
2023-06-15 01:08:09 +00:00
|
|
|
}
|
|
|
|
}
|
2023-06-16 17:29:43 +00:00
|
|
|
// Sort the strings based on the number of elements after splitting by "/"
|
2023-07-17 05:17:52 +00:00
|
|
|
sort.Slice(matching, func(i, j int) bool {
|
|
|
|
parts1 := strings.Split(matching[i], "/")
|
|
|
|
parts2 := strings.Split(matching[j], "/")
|
2023-06-16 17:29:43 +00:00
|
|
|
return len(parts1) < len(parts2)
|
|
|
|
})
|
2023-07-17 05:17:52 +00:00
|
|
|
return matching, fileListTypes
|
2023-06-15 01:08:09 +00:00
|
|
|
}
|
|
|
|
|
2023-10-23 00:23:38 +00:00
|
|
|
func scopedPathNameFilter(pathName string, scope string, isDir bool) string {
|
2023-08-17 21:46:49 +00:00
|
|
|
scope = strings.TrimPrefix(scope, "/")
|
2023-10-18 15:32:22 +00:00
|
|
|
pathName = strings.TrimPrefix(pathName, "/")
|
2023-10-23 00:23:38 +00:00
|
|
|
pathName = strings.TrimSuffix(pathName, "/")
|
2023-06-15 15:30:49 +00:00
|
|
|
if strings.HasPrefix(pathName, scope) {
|
2023-10-23 00:23:38 +00:00
|
|
|
pathName = strings.TrimPrefix(pathName, scope)
|
|
|
|
if isDir {
|
|
|
|
pathName = pathName + "/"
|
|
|
|
}
|
2023-08-17 21:46:49 +00:00
|
|
|
} else {
|
2023-10-23 00:23:38 +00:00
|
|
|
pathName = "" // return not matched
|
2023-06-15 15:30:49 +00:00
|
|
|
}
|
2023-08-17 21:46:49 +00:00
|
|
|
return pathName
|
2023-06-15 15:30:49 +00:00
|
|
|
}
|
|
|
|
|
2023-10-18 15:32:22 +00:00
|
|
|
func containsSearchTerm(pathName string, searchTerm string, options SearchOptions, isDir bool, fileTypes map[string]bool) (bool, map[string]bool) {
|
2023-07-21 22:41:24 +00:00
|
|
|
conditions := options.Conditions
|
2023-08-12 16:30:41 +00:00
|
|
|
path := getLastPathComponent(pathName)
|
|
|
|
// Convert to lowercase once
|
|
|
|
if !conditions["exact"] {
|
2023-08-12 19:41:59 +00:00
|
|
|
path = strings.ToLower(path)
|
2023-10-09 22:24:48 +00:00
|
|
|
searchTerm = strings.ToLower(searchTerm)
|
2023-08-12 16:30:41 +00:00
|
|
|
}
|
2023-10-09 22:24:48 +00:00
|
|
|
if strings.Contains(path, searchTerm) {
|
2023-08-12 16:30:41 +00:00
|
|
|
// Calculate fileSize only if needed
|
|
|
|
var fileSize int64
|
|
|
|
matchesAllConditions := true
|
2023-08-12 19:41:59 +00:00
|
|
|
extension := filepath.Ext(path)
|
2023-10-18 15:32:22 +00:00
|
|
|
for _, k := range AllFiletypeOptions {
|
|
|
|
if IsMatchingType(extension, k) {
|
|
|
|
fileTypes[k] = true
|
|
|
|
}
|
2023-10-09 22:24:48 +00:00
|
|
|
}
|
2023-08-12 16:30:41 +00:00
|
|
|
fileTypes["dir"] = isDir
|
|
|
|
for t, v := range conditions {
|
|
|
|
if t == "exact" {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
var matchesCondition bool
|
2023-07-21 22:41:24 +00:00
|
|
|
switch t {
|
2023-08-12 16:30:41 +00:00
|
|
|
case "larger":
|
2023-10-09 22:24:48 +00:00
|
|
|
if fileSize == 0 {
|
|
|
|
fileSize = getFileSize(pathName)
|
|
|
|
}
|
2023-09-30 14:18:21 +00:00
|
|
|
matchesCondition = fileSize > int64(options.LargerThan)*bytesInMegabyte
|
2023-08-12 16:30:41 +00:00
|
|
|
case "smaller":
|
2023-10-09 22:24:48 +00:00
|
|
|
if fileSize == 0 {
|
|
|
|
fileSize = getFileSize(pathName)
|
|
|
|
}
|
2023-09-30 14:18:21 +00:00
|
|
|
matchesCondition = fileSize < int64(options.SmallerThan)*bytesInMegabyte
|
2023-08-12 16:30:41 +00:00
|
|
|
default:
|
|
|
|
matchesCondition = v == fileTypes[t]
|
2023-07-21 22:41:24 +00:00
|
|
|
}
|
2023-08-12 16:30:41 +00:00
|
|
|
if !matchesCondition {
|
2023-07-31 22:20:14 +00:00
|
|
|
matchesAllConditions = false
|
|
|
|
}
|
2023-07-21 22:41:24 +00:00
|
|
|
}
|
2023-07-31 22:20:14 +00:00
|
|
|
return matchesAllConditions, fileTypes
|
2023-07-21 22:41:24 +00:00
|
|
|
}
|
2023-08-12 16:30:41 +00:00
|
|
|
// Clear variables and return
|
2023-07-21 22:41:24 +00:00
|
|
|
return false, map[string]bool{}
|
2023-07-13 02:23:29 +00:00
|
|
|
}
|
|
|
|
|
2023-07-21 22:41:24 +00:00
|
|
|
func getFileSize(filepath string) int64 {
|
2023-08-12 16:30:41 +00:00
|
|
|
fileInfo, err := os.Stat(rootPath + "/" + filepath)
|
2023-07-21 22:41:24 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
return fileInfo.Size()
|
|
|
|
}
|
|
|
|
|
2023-06-15 01:08:09 +00:00
|
|
|
func getLastPathComponent(path string) string {
|
|
|
|
// Use filepath.Base to extract the last component of the path
|
|
|
|
return filepath.Base(path)
|
2023-06-18 15:04:31 +00:00
|
|
|
}
|
2023-07-21 22:41:24 +00:00
|
|
|
|
|
|
|
func generateRandomHash(length int) string {
|
|
|
|
const charset = "abcdefghijklmnopqrstuvwxyz0123456789"
|
2023-09-25 01:03:09 +00:00
|
|
|
rand.New(rand.NewSource(time.Now().UnixNano()))
|
2023-07-21 22:41:24 +00:00
|
|
|
result := make([]byte, length)
|
|
|
|
for i := range result {
|
|
|
|
result[i] = charset[rand.Intn(len(charset))]
|
|
|
|
}
|
|
|
|
return string(result)
|
|
|
|
}
|