You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

143 lines
3.3KB

  1. package main
  2. import (
  3. "encoding/base64"
  4. "encoding/json"
  5. "errors"
  6. "fmt"
  7. "math/rand"
  8. "net/http"
  9. "strconv"
  10. "strings"
  11. "time"
  12. )
  13. func crmpixelImage() (pixel []byte, err error) {
  14. b64pixel := "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4QcIBzEJ3JY/6wAAAAh0RVh0Q29tbWVudAD2zJa/AAAADUlEQVQI12NgYGBgAAAABQABXvMqOgAAAABJRU5ErkJggg=="
  15. pixel, err = base64.StdEncoding.DecodeString(b64pixel)
  16. return
  17. }
  18. func crmpixel(w http.ResponseWriter, r *http.Request) {
  19. cookie := crmpixelCookie(r)
  20. http.SetCookie(w, &cookie)
  21. //send out pixel 1x1 transparent png file
  22. pixel, err := crmpixelImage()
  23. if err == nil {
  24. w.Write(pixel)
  25. } else {
  26. fmt.Fprint(w, "decodig wrong")
  27. }
  28. }
  29. func crmpixelCookie(r *http.Request) (ret http.Cookie) {
  30. cookie, leadok := r.Cookie("biukop_cl") //crm lead
  31. if leadok != nil {
  32. ret, _ = createNewCookie(r)
  33. return
  34. }
  35. valid := isValidCookieBiukopCL(cookie.Value)
  36. if !valid {
  37. ret, _ = createNewCookie(r)
  38. return
  39. }
  40. //refresh expiration
  41. ret = *cookie
  42. ret.Expires = time.Now().Add(10 * 365 * 24 * time.Hour)
  43. return
  44. }
  45. func createNewCookie(r *http.Request) (ret http.Cookie, info crmdLead) {
  46. expiration := time.Now().Add(10 * 365 * 24 * time.Hour)
  47. info = crmCreateNewAnonymousLeadByHTTPRequest(r)
  48. cookieValue := buildBiukopCLValue(info.ID)
  49. ret = http.Cookie{Name: "biukop_cl", Value: cookieValue, Expires: expiration}
  50. return
  51. }
  52. func crmCreateNewAnonymousLeadByHTTPRequest(r *http.Request) (info crmdLead) {
  53. info.FirstName = "Anonymous"
  54. info.LastName = "User " + r.RemoteAddr
  55. info.Password = "Password"
  56. info.Status = "Anonymous"
  57. info.Description = "Anonymous user from " + r.RemoteAddr
  58. info.ForceDuplicate = true
  59. b, err := json.Marshal(info)
  60. if err != nil {
  61. return
  62. }
  63. entity, err := crmCreateEntity("Lead", b)
  64. if err == nil || isErrIndicateDuplicate(err) {
  65. info, _ = entity.(crmdLead)
  66. }
  67. return
  68. }
  69. func isValidCookieBiukopCL(cookieValue string) (valid bool) {
  70. valid = false
  71. //correctly split string
  72. s := strings.Split(cookieValue, "|")
  73. if len(s) != 4 || s[0] == "" {
  74. return
  75. }
  76. id, nonce, timestamp, signature := s[0], s[1], s[2], s[3]
  77. //check signature
  78. combined := id + nonce
  79. expected := calculateSignature(timestamp, combined, IntraAPIConfig.CRMSecrete)
  80. if expected != signature {
  81. return
  82. }
  83. ts, err := strconv.Atoi(timestamp)
  84. if err != nil {
  85. return
  86. }
  87. if timestampOldThan(int32(ts), 86400) { //older than 1 day
  88. //find lead data
  89. _, err := crmpixelLead(id)
  90. if err != nil {
  91. return
  92. }
  93. }
  94. valid = true
  95. return
  96. }
  97. func buildBiukopCLsignature(id, nonce string) (timestamp, signature string) {
  98. combined := id + nonce
  99. timestamp = fmt.Sprintf("%d", time.Now().Unix())
  100. signature = calculateSignature(timestamp, combined, IntraAPIConfig.CRMSecrete)
  101. return
  102. }
  103. func buildBiukopCLValue(id string) (ret string) {
  104. rand.Seed(time.Now().Unix())
  105. nonce := fmt.Sprintf("%d", rand.Intn(655352017))
  106. timestamp, signature := buildBiukopCLsignature(id, nonce)
  107. strs := []string{id, nonce, timestamp, signature} //order is very important
  108. ret = strings.Join(strs, "|")
  109. return
  110. }
  111. func crmpixelLead(id string) (info crmdLead, err error) {
  112. entity, err := crmGetEntity("Lead", id)
  113. if err != nil {
  114. return
  115. }
  116. info, ok := entity.(crmdLead)
  117. if !ok {
  118. err = errors.New("search lead, return a bad entity type")
  119. }
  120. return
  121. }