manager.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. package caplets
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. "os"
  6. "path/filepath"
  7. "sort"
  8. "strings"
  9. "sync"
  10. "github.com/evilsocket/islazy/fs"
  11. )
  12. var (
  13. cache = make(map[string]*Caplet)
  14. cacheLock = sync.Mutex{}
  15. )
  16. func List() []*Caplet {
  17. caplets := make([]*Caplet, 0)
  18. for _, searchPath := range LoadPaths {
  19. files, _ := filepath.Glob(searchPath + "/*" + Suffix)
  20. files2, _ := filepath.Glob(searchPath + "/*/*" + Suffix)
  21. for _, fileName := range append(files, files2...) {
  22. if _, err := os.Stat(fileName); err == nil {
  23. base := strings.Replace(fileName, searchPath+string(os.PathSeparator), "", -1)
  24. base = strings.Replace(base, Suffix, "", -1)
  25. if caplet, err := Load(base); err != nil {
  26. fmt.Fprintf(os.Stderr, "wtf: %v\n", err)
  27. } else {
  28. caplets = append(caplets, caplet)
  29. }
  30. }
  31. }
  32. }
  33. sort.Slice(caplets, func(i, j int) bool {
  34. return strings.Compare(caplets[i].Name, caplets[j].Name) == -1
  35. })
  36. return caplets
  37. }
  38. func Load(name string) (*Caplet, error) {
  39. cacheLock.Lock()
  40. defer cacheLock.Unlock()
  41. if caplet, found := cache[name]; found {
  42. return caplet, nil
  43. }
  44. baseName := name
  45. names := []string{}
  46. if !strings.HasSuffix(name, Suffix) {
  47. name += Suffix
  48. }
  49. if !filepath.IsAbs(name) {
  50. for _, path := range LoadPaths {
  51. names = append(names, filepath.Join(path, name))
  52. }
  53. } else {
  54. names = append(names, name)
  55. }
  56. for _, fileName := range names {
  57. if stats, err := os.Stat(fileName); err == nil {
  58. cap := &Caplet{
  59. Script: newScript(fileName, stats.Size()),
  60. Name: baseName,
  61. Scripts: make([]Script, 0),
  62. }
  63. cache[name] = cap
  64. if reader, err := fs.LineReader(fileName); err != nil {
  65. return nil, fmt.Errorf("error reading caplet %s: %v", fileName, err)
  66. } else {
  67. for line := range reader {
  68. cap.Code = append(cap.Code, line)
  69. }
  70. // the caplet has a dedicated folder
  71. if strings.Contains(baseName, "/") || strings.Contains(baseName, "\\") {
  72. dir := filepath.Dir(fileName)
  73. // get all secondary .cap and .js files
  74. if files, err := ioutil.ReadDir(dir); err == nil && len(files) > 0 {
  75. for _, f := range files {
  76. subFileName := filepath.Join(dir, f.Name())
  77. if subFileName != fileName && (strings.HasSuffix(subFileName, ".cap") || strings.HasSuffix(subFileName, ".js")) {
  78. if reader, err := fs.LineReader(subFileName); err == nil {
  79. script := newScript(subFileName, f.Size())
  80. for line := range reader {
  81. script.Code = append(script.Code, line)
  82. }
  83. cap.Scripts = append(cap.Scripts, script)
  84. }
  85. }
  86. }
  87. }
  88. }
  89. }
  90. return cap, nil
  91. }
  92. }
  93. return nil, fmt.Errorf("caplet %s not found", name)
  94. }