Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

133 lines
3.2KB

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