package main import ( "encoding/base64" "encoding/json" "errors" "fmt" "math/rand" "net/http" "strconv" "strings" "time" ) func crmpixelImage() (pixel []byte, err error) { b64pixel := "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4QcIBzEJ3JY/6wAAAAh0RVh0Q29tbWVudAD2zJa/AAAADUlEQVQI12NgYGBgAAAABQABXvMqOgAAAABJRU5ErkJggg==" pixel, err = base64.StdEncoding.DecodeString(b64pixel) return } func crmpixel(w http.ResponseWriter, r *http.Request) { cookie := crmpixelCookie(r) http.SetCookie(w, &cookie) //send out pixel 1x1 transparent png file pixel, err := crmpixelImage() if err == nil { w.Write(pixel) } else { fmt.Fprint(w, "decodig wrong") } } func crmpixelCookie(r *http.Request) (ret http.Cookie) { cookie, leadok := r.Cookie("biukop_cl") //crm lead if leadok != nil { ret, _ = createNewCookie(r) return } valid := isValidCookieBiukopCL(cookie.Value) if !valid { ret, _ = createNewCookie(r) return } //refresh expiration ret = *cookie ret.Expires = time.Now().Add(10 * 365 * 24 * time.Hour) return } func createNewCookie(r *http.Request) (ret http.Cookie, info crmdLead) { expiration := time.Now().Add(10 * 365 * 24 * time.Hour) info = crmCreateNewAnonymousLeadByHTTPRequest(r) cookieValue := buildBiukopCLValue(info.ID) ret = http.Cookie{Name: "biukop_cl", Value: cookieValue, Expires: expiration} return } func crmCreateNewAnonymousLeadByHTTPRequest(r *http.Request) (info crmdLead) { info.FirstName = "Anonymous" info.LastName = "User " + r.RemoteAddr info.Password = "Password" info.Status = "Anonymous" info.Description = "Anonymous user from " + r.RemoteAddr info.ForceDuplicate = true b, err := json.Marshal(info) if err != nil { return } entity, err := crmCreateEntity("Lead", b) if err == nil || isErrIndicateDuplicate(err) { info, _ = entity.(crmdLead) } return } func isValidCookieBiukopCL(cookieValue string) (valid bool) { valid = false //correctly split string s := strings.Split(cookieValue, "|") if len(s) != 4 || s[0] == "" { return } id, nonce, timestamp, signature := s[0], s[1], s[2], s[3] //check signature combined := id + nonce expected := calculateSignature(timestamp, combined, IntraAPIConfig.CRMSecrete) if expected != signature { return } ts, err := strconv.Atoi(timestamp) if err != nil { return } if timestampOldThan(int32(ts), 86400) { //older than 1 day //find lead data _, err := crmpixelLead(id) if err != nil { return } } valid = true return } func buildBiukopCLsignature(id, nonce string) (timestamp, signature string) { combined := id + nonce timestamp = fmt.Sprintf("%d", time.Now().Unix()) signature = calculateSignature(timestamp, combined, IntraAPIConfig.CRMSecrete) return } func buildBiukopCLValue(id string) (ret string) { rand.Seed(time.Now().Unix()) nonce := fmt.Sprintf("%d", rand.Intn(655352017)) timestamp, signature := buildBiukopCLsignature(id, nonce) strs := []string{id, nonce, timestamp, signature} //order is very important ret = strings.Join(strs, "|") return } func crmpixelLead(id string) (info crmdLead, err error) { entity, err := crmGetEntity("Lead", id) if err != nil { return } info, ok := entity.(crmdLead) if !ok { err = errors.New("search lead, return a bad entity type") } return }