util.go 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. // Copyright (C) 2021 The Syncthing Authors.
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this file,
  5. // You can obtain one at https://mozilla.org/MPL/2.0/.
  6. package main
  7. import (
  8. "bytes"
  9. "compress/gzip"
  10. "fmt"
  11. "net"
  12. "net/http"
  13. "os"
  14. "path/filepath"
  15. "time"
  16. "github.com/syncthing/syncthing/lib/sha256"
  17. )
  18. // userIDFor returns a string we can use as the user ID for the purpose of
  19. // counting affected users. It's the truncated hash of a salt, the user
  20. // remote IP, and the current month.
  21. func userIDFor(req *http.Request) string {
  22. addr := req.RemoteAddr
  23. if fwd := req.Header.Get("x-forwarded-for"); fwd != "" {
  24. addr = fwd
  25. }
  26. if host, _, err := net.SplitHostPort(addr); err == nil {
  27. addr = host
  28. }
  29. now := time.Now().Format("200601")
  30. salt := "stcrashreporter"
  31. hash := sha256.Sum256([]byte(salt + addr + now))
  32. return fmt.Sprintf("%x", hash[:8])
  33. }
  34. // 01234567890abcdef... => 01/23
  35. func dirFor(base string) string {
  36. return filepath.Join(base[0:2], base[2:4])
  37. }
  38. func fullPathCompressed(root, reportID string) string {
  39. return filepath.Join(root, dirFor(reportID), reportID) + ".gz"
  40. }
  41. func compressAndWrite(bs []byte, fullPath string) error {
  42. // Compress the report for storage
  43. buf := new(bytes.Buffer)
  44. gw := gzip.NewWriter(buf)
  45. _, _ = gw.Write(bs) // can't fail
  46. gw.Close()
  47. // Create an output file with the compressed report
  48. return os.WriteFile(fullPath, buf.Bytes(), 0644)
  49. }