directory.go 1.9 KB

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