directory.go 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. package detect
  2. import (
  3. "io"
  4. "os"
  5. "strings"
  6. "github.com/h2non/filetype"
  7. "github.com/zricethezav/gitleaks/v8/report"
  8. "github.com/zricethezav/gitleaks/v8/sources"
  9. )
  10. func (d *Detector) DetectFiles(paths <-chan sources.ScanTarget) ([]report.Finding, error) {
  11. for pa := range paths {
  12. p := pa
  13. d.Sema.Go(func() error {
  14. f, err := os.Open(p.Path)
  15. if err != nil {
  16. return err
  17. }
  18. defer f.Close()
  19. // Buffer to hold file chunks
  20. buf := make([]byte, chunkSize)
  21. totalLines := 0
  22. for {
  23. n, err := f.Read(buf)
  24. if err != nil && err != io.EOF {
  25. return err
  26. }
  27. if n == 0 {
  28. break
  29. }
  30. // TODO: optimization could be introduced here
  31. mimetype, err := filetype.Match(buf[:n])
  32. if err != nil {
  33. return err
  34. }
  35. if mimetype.MIME.Type == "application" {
  36. return nil // skip binary files
  37. }
  38. // Count the number of newlines in this chunk
  39. linesInChunk := strings.Count(string(buf[:n]), "\n")
  40. totalLines += linesInChunk
  41. fragment := Fragment{
  42. Raw: string(buf[:n]),
  43. FilePath: p.Path,
  44. }
  45. if p.Symlink != "" {
  46. fragment.SymlinkFile = p.Symlink
  47. }
  48. for _, finding := range d.Detect(fragment) {
  49. // need to add 1 since line counting starts at 1
  50. finding.StartLine += (totalLines - linesInChunk) + 1
  51. finding.EndLine += (totalLines - linesInChunk) + 1
  52. d.addFinding(finding)
  53. }
  54. }
  55. return nil
  56. })
  57. }
  58. if err := d.Sema.Wait(); err != nil {
  59. return d.findings, err
  60. }
  61. return d.findings, nil
  62. }