An app written in GoLang to find people using location services on smartphones.
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.

258 lines
8.1KB

  1. package main
  2. import (
  3. "net/http"
  4. "html/template"
  5. "log"
  6. "encoding/json"
  7. "io/ioutil"
  8. "regexp"
  9. "github.com/go-redis/redis"
  10. "time"
  11. "strconv"
  12. "crypto/rand"
  13. )
  14. type location_set struct {
  15. Latitude float64 `json:"latitude"`
  16. Longitude float64 `json:"longitude"`
  17. Id string `json:"id"`
  18. Key string `json:"key"`
  19. }
  20. type item_key struct {
  21. Id string
  22. Key string
  23. }
  24. func setlocation(w http.ResponseWriter, r *http.Request){
  25. item := item_key{r.FormValue("id"), r.FormValue("key")}
  26. t, err := template.ParseFiles("setlocation.html")
  27. if err != nil {
  28. log.Print("template parsing error: ", err)
  29. }
  30. err = t.Execute(w, item)
  31. if err != nil {
  32. log.Print("template executing error: ", err)
  33. }
  34. }
  35. func getlocation(w http.ResponseWriter, r *http.Request){
  36. item := item_key{r.FormValue("id"), r.FormValue("key")}
  37. t, err := template.ParseFiles("getlocation.html")
  38. if err != nil {
  39. log.Print("template parsing error: ", err)
  40. }
  41. err = t.Execute(w, item)
  42. if err != nil {
  43. log.Print("template executing error: ", err)
  44. }
  45. }
  46. func managelocations(w http.ResponseWriter, r *http.Request){
  47. t, err := template.ParseFiles("managelocations.html")
  48. if err != nil {
  49. log.Print("template parsing error: ", err)
  50. }
  51. err = t.Execute(w, nil)
  52. if err != nil {
  53. log.Print("template executing error: ", err)
  54. }
  55. }
  56. func api_location(w http.ResponseWriter, r *http.Request){
  57. switch r.Method {
  58. case "GET":
  59. id := r.FormValue("id")
  60. key := r.FormValue("key")
  61. id_exists := check_item_key(id, key)
  62. if id_exists != true {
  63. w.WriteHeader(http.StatusNotFound)
  64. w.Write([]byte(http.StatusText(http.StatusNotFound) + "\n"))
  65. return
  66. }
  67. latitude, latitude_err := read_key("latitude-" + id)
  68. if latitude_err != true {
  69. w.WriteHeader(http.StatusNoContent)
  70. w.Write([]byte(http.StatusText(http.StatusNoContent) + "\n"))
  71. return
  72. }
  73. longitude, longitude_err := read_key("longitude-" + id)
  74. if longitude_err != true {
  75. w.WriteHeader(http.StatusNoContent)
  76. w.Write([]byte(http.StatusText(http.StatusNoContent) + "\n"))
  77. return
  78. }
  79. output, marshal_err := json.Marshal(map[string]float64{"latitude": latitude, "longitude": longitude})
  80. if marshal_err != nil {
  81. w.WriteHeader(http.StatusInternalServerError)
  82. w.Write([]byte(http.StatusText(http.StatusInternalServerError) + "\n"))
  83. return
  84. }
  85. w.Write([]byte(output))
  86. return
  87. case "POST":
  88. body, err := ioutil.ReadAll(r.Body)
  89. if err != nil {
  90. w.WriteHeader(http.StatusBadRequest)
  91. w.Write([]byte(http.StatusText(http.StatusBadRequest) + "\n"))
  92. return
  93. }
  94. var location_data location_set
  95. location_err := json.Unmarshal(body, &location_data)
  96. if location_err != nil {
  97. w.WriteHeader(http.StatusBadRequest)
  98. w.Write([]byte(http.StatusText(http.StatusBadRequest) + "\n"))
  99. return
  100. }
  101. id_exists := check_item_key(location_data.Id, location_data.Key)
  102. if id_exists != true {
  103. w.WriteHeader(http.StatusNotFound)
  104. w.Write([]byte(http.StatusText(http.StatusNotFound) + "\n"))
  105. return
  106. }
  107. latitude_written := write_key("latitude-" + location_data.Id, location_data.Latitude)
  108. if latitude_written != true {
  109. w.WriteHeader(http.StatusInternalServerError)
  110. w.Write([]byte(http.StatusText(http.StatusInternalServerError) + "\n"))
  111. return
  112. }
  113. longitude_written := write_key("longitude-" + location_data.Id, location_data.Longitude)
  114. if longitude_written != true {
  115. w.WriteHeader(http.StatusInternalServerError)
  116. w.Write([]byte(http.StatusText(http.StatusInternalServerError) + "\n"))
  117. return
  118. }
  119. w.WriteHeader(http.StatusCreated)
  120. w.Write([]byte(http.StatusText(http.StatusCreated) + "\n"))
  121. return
  122. default:
  123. w.WriteHeader(http.StatusNotImplemented)
  124. w.Write([]byte(http.StatusText(http.StatusNotImplemented) + "\n"))
  125. }
  126. }
  127. func api_createid(w http.ResponseWriter, r *http.Request){
  128. switch r.Method {
  129. case "GET":
  130. id, id_err := genrandomstring(10)
  131. if id_err != nil {
  132. w.WriteHeader(http.StatusInternalServerError)
  133. w.Write([]byte(http.StatusText(http.StatusInternalServerError) + "\n"))
  134. return
  135. }
  136. key, key_err := genrandomstring(32)
  137. if key_err != nil {
  138. w.WriteHeader(http.StatusInternalServerError)
  139. w.Write([]byte(http.StatusText(http.StatusInternalServerError) + "\n"))
  140. return
  141. }
  142. client := redis.NewClient(&redis.Options{
  143. Addr: "localhost:6379",
  144. Password: "", // no password set
  145. DB: 0, // use default DB
  146. })
  147. _, err := client.Get("key-" + id).Result()
  148. if err == nil {
  149. w.WriteHeader(http.StatusInternalServerError)
  150. w.Write([]byte(http.StatusText(http.StatusInternalServerError) + "\n"))
  151. return
  152. }
  153. writekey_err := client.Set("key-" + id, key, 30 * time.Minute).Err()
  154. if writekey_err != nil {
  155. w.WriteHeader(http.StatusInternalServerError)
  156. w.Write([]byte(http.StatusText(http.StatusInternalServerError) + "\n"))
  157. return
  158. }
  159. output, marshal_err := json.Marshal(map[string]string{"id": id, "key": key})
  160. if marshal_err != nil {
  161. w.WriteHeader(http.StatusInternalServerError)
  162. w.Write([]byte(http.StatusText(http.StatusInternalServerError) + "\n"))
  163. return
  164. }
  165. w.WriteHeader(http.StatusOK)
  166. w.Write([]byte(output))
  167. return
  168. default:
  169. w.WriteHeader(http.StatusNotImplemented)
  170. w.Write([]byte(http.StatusText(http.StatusNotImplemented) + "\n"))
  171. }
  172. }
  173. func check_item_key(id string, key string) bool {
  174. id_safe, _ := regexp.MatchString(`^[a-zA-Z0-9]{10}$`, id)
  175. if id_safe != true {
  176. return false
  177. }
  178. key_safe, _ := regexp.MatchString(`^[a-zA-Z0-9]{32}$`, key)
  179. if key_safe != true {
  180. return false
  181. }
  182. client := redis.NewClient(&redis.Options{
  183. Addr: "localhost:6379",
  184. Password: "", // no password set
  185. DB: 0, // use default DB
  186. })
  187. item, err := client.Get("key-" + id).Result()
  188. if err != nil {
  189. return false
  190. }
  191. if key != item {
  192. return false
  193. }
  194. return true
  195. }
  196. func write_key(id string, item float64) bool {
  197. client := redis.NewClient(&redis.Options{
  198. Addr: "localhost:6379",
  199. Password: "", // no password set
  200. DB: 0, // use default DB
  201. })
  202. err := client.Set(id, item, 30 * time.Minute).Err()
  203. if err != nil {
  204. return false
  205. }
  206. return true
  207. }
  208. func read_key(id string) (float64, bool) {
  209. client := redis.NewClient(&redis.Options{
  210. Addr: "localhost:6379",
  211. Password: "", // no password set
  212. DB: 0, // use default DB
  213. })
  214. item, err := client.Get(id).Result()
  215. if err != nil {
  216. return 0, false
  217. }
  218. item_float, conv_err := strconv.ParseFloat(item, 64)
  219. if conv_err != nil {
  220. return 0, false
  221. }
  222. return item_float, true
  223. }
  224. func genrandomstring(length int) (string, error) {
  225. const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
  226. output := make([]byte, length)
  227. _, err := rand.Read(output)
  228. if err != nil {
  229. return "", err
  230. }
  231. for i, b := range output {
  232. output[i] = charset[b%byte(len(charset))]
  233. }
  234. return string(output), nil
  235. }
  236. func main() {
  237. http.HandleFunc("/managelocations.html", managelocations)
  238. http.HandleFunc("/setlocation.html", setlocation)
  239. http.HandleFunc("/getlocation.html", getlocation)
  240. http.HandleFunc("/api/createitem", api_createid)
  241. http.HandleFunc("/api/location", api_location)
  242. http.ListenAndServe("127.0.0.1:8080", nil)
  243. }