// bv : binaire correspondant à l'encodage json d'un MessageIn // TODO baser le hash sur la couche, et ne stocker que la couche réencodée en json func (ms *MapServer) stockeVue(idVoyeur uint, mdprVoyeur string, bv []byte, couche *bra.Couche) (nouveau bool) { dirBase := ms.répertoireCartesBraldun(idVoyeur, mdprVoyeur) hasher := sha1.New() hasher.Write(bv) sha := base64.URLEncoding.EncodeToString(hasher.Sum(nil)) //log.Println(" hash:",sha) dir := dirBase + "/" + time.Now().Format("2006/01/02") path := dir + "/carte-" + sha + ".json" if _, err := os.Stat(path); err != nil { // nouveau fichier, donc nouvelle vue //log.Println(" nouveau hash") //> on sauvegarde le fichier json os.MkdirAll(dir, 0777) f, _ := os.Create(path) defer f.Close() f.Write(bv) //> on crée ou enrichit l'image png correspondant à la couche bra.EnrichitCouchePNG(dirBase, couche, TAILLE_CACHE_PNG) return true } return false }
func main() { cmd := os.Args[1] flags := flag.NewFlagSet(cmd, flag.ExitOnError) in := flags.String("in", "", "source des données") out := flags.String("out", "", "répertoire de sortie (pour la commande png)") id := flags.Int("id", 0, "id braldun") mdpr := flags.String("mdpr", "", "mot de passe restreint") data := flags.String("data", "", "chemin de base du stockage (contient en principe des répertoires 'private', 'public' et 'cartes')") flags.Parse(os.Args[2:]) var err error switch cmd { case "palette": bra.ExportePalettePng(os.Stdout) case "stats": if *data == "" { log.Println("Chemin de stockage non précisé (nécessaire pour lire bralduns.csv et communautes.csv)") } else { memmap, err := bra.ChargeDonnéesStatiquesPubliques(filepath.Join(*data, "public"), true) if err != nil { log.Fatal(err) } log.Println(len(memmap.Bralduns), "bralduns") } case "vue": if *id == 0 { log.Println("Id du braldun non précisé") } else if *mdpr == "" { log.Println("Mot de passe restreint non précisé") } else if *data == "" { log.Println("Chemin de stockage non précisé (nécessaire pour lire bralduns.csv et communautes.csv)") } else { dv, err := bra.VueParScriptPublic(uint(*id), *mdpr, filepath.Join(*data, "public")) if err != nil { log.Fatal(err) } bout, err := json.Marshal(dv) if err != nil { log.Fatal(err) } os.Stdout.Write(bout) } case "etat": if *id == 0 { log.Println("Id du braldun non précisé") } else if *mdpr == "" { log.Println("Mot de passe restreint non précisé") } else { état, err := bra.EtatBraldunParScriptPublic(uint(*id), *mdpr) if err != nil { log.Fatal(err) } bout, err := json.Marshal(état) if err != nil { log.Fatal(err) } os.Stdout.Write(bout) } case "check": if *id == 0 { log.Println("Id du braldun non précisé") } else if *mdpr == "" { log.Println("Mot de passe restreint non précisé") } else { auth, err := bra.AuthentifieCompteParScriptPublic(uint(*id), *mdpr) if err != nil { log.Println("Unable to authenticate", err) } else { log.Println("Autentication : ", auth) } } case "png": if *in == "" { log.Println("Source de données non précisée (in devrait être le chemin d'un fichier json)") } else { dir := *out cheminsIn := strings.Split(*in, ";") if dir == "" { dir, _ = filepath.Split(cheminsIn[0]) cheminsIn = cheminsIn[1:] } dir, err = filepath.Abs(dir) if err != nil { log.Fatal(err) } for _, cheminIn := range cheminsIn { cheminIn, err = filepath.Abs(cheminIn) if err != nil { log.Fatal(err) } if filepath.Ext(cheminIn) == ".json" { filein, err := os.Open(*in) if err != nil { log.Fatal(err) } defer filein.Close() messin := new(bra.MessageIn) bin, _ := ioutil.ReadAll(filein) err = json.Unmarshal(bin, messin) if err != nil { log.Fatal(err) } if messin.Vue == nil || len(messin.Vue.Couches) == 0 { log.Fatal(" Pas de données de vue") } bra.EnrichitCouchePNG(dir, messin.Vue.Couches[0], 0) } else { // si pas json on suppose pour l'instant qu'il s'agit d'un répertoire de fichiers png log.Println("********\nEnrichitCouchesPNG", dir, cheminIn) err = bra.EnrichitCouchesPNG(dir, cheminIn) if err != nil { log.Fatal(err) } } } } default: fmt.Println("Syntaxe :") fmt.Println(" > braldopadmin [{check|palette|png|etat|vue}] [paramètres]") fmt.Println("Paramètres :") flags.PrintDefaults() fmt.Println("Exemples :") fmt.Println(" > braldopadmin palette") fmt.Println(" exporte sur stdout la palette des couleurs des fonds à utiliser dans le javascript pour décoder les png") fmt.Println(" > braldopadmin png -in tata/toto.json") fmt.Println(" construit un png (tata/couchexx.png) dont le contenu correspond à la Couche encodée dans le fichier tata/toto.json") fmt.Println(" > braldopadmin png -in toto;tutu -out titi") fmt.Println(" enrichit (ou crée) les fichiers titi/couchexx.png à partir des données couchexx.png des répertoires toto et tutu") fmt.Println(" > braldopadmin check -id 754 -mdpr XXXX") fmt.Println(" vérifie que le braldun 754 est connu de Braldahim et a bien le mot de passe restreint XXXX") fmt.Println(" > braldopadmin vue -id 754 -mdpr XXXX") fmt.Println(" renvoie en json la vue du braldun obtenue par script public braldahim") fmt.Println(" > braldopadmin etat -id 754 -mdpr XXXX") fmt.Println(" renvoie en json l'état du braldun obtenu par script public braldahim") fmt.Println("Attention : certaines de ces commandes font des requêtes au serveur sp.braldahim.com et décrémentent le nombre de requêtes possibles pour la journée pour le braldun en question.") } fmt.Println() }
func (ms *MapServer) ServeHTTP(w http.ResponseWriter, hr *http.Request) { startTime := time.Now().UnixNano() defer func() { log.Printf(" durée totale traitement requête : %d ms\n", (time.Now().UnixNano()-startTime)/1e6) }() w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Access-Control-Request-Method", "GET") w.Header().Set("content-type", "application/x-javascript") //> analyse et vérification de la requête hr.ParseForm() in := new(bra.MessageIn) out := new(bra.MessageOut) defer envoieRéponse(w, out) bin := ([]byte)(getFormValue(hr, "in")) err := json.Unmarshal(bin, in) if err != nil { out.Erreur = "Erreur décodage : " + err.Error() log.Println("Erreur décodage : ", err.Error()) return } out.Text = vérifieVersion(in.Version) if in.IdBraldun == 0 || len(in.Mdpr) != 64 { log.Println("IdBraldun ou Mot de passe restreint invalide") return } dirBase := ms.répertoireCartesBraldun(in.IdBraldun, in.Mdpr) log.Println("Requête Braldun ", in.IdBraldun) var couche *bra.Couche if in.Vue == nil || len(in.Vue.Couches) == 0 { log.Println(" Pas de données de vue") } else { couche = in.Vue.Couches[0] } //> récupération du compte braldop authentifié et du tableau des amis var cb *bra.CompteBraldop var amis []*bra.CompteBraldop con, err := ms.bd.DB() defer con.Close() if err != nil { log.Println("Erreur à la connexion bd", err) out.Text = "Erreur Braldop : connexion BD" return } cb, errmess := con.AuthentifieCompte(in.IdBraldun, in.Mdpr, true) if errmess != "" { out.Text = "Une erreur s'est produite durant l'authentification sur Braldop : <i>" + errmess + "</i><br>Contactez Canopée du Haut-Rac pour plus d'informations." return // on a besoin du compte } log.Println(" compte authentifié") amis, err = con.Amis(cb.IdBraldun) if err != nil { log.Println(" erreur durant récupération amis") } log.Println(" commande :", in.Cmd) //> stockage éventuel de l'état du braldun if in.Etat != nil && in.Etat.PVMax > 0 { log.Println(" Reçu état braldun") in.Etat.IdBraldun = in.IdBraldun err = con.StockeEtatBraldun(in.Etat) if err != nil { log.Println(" Erreur stokage état braldun :", err) } } //> stockage éventuel des données de vue if couche != nil && len(in.Vue.Vues) == 1 { if in.Vue.Vues[0].Voyeur != in.IdBraldun { log.Println(" Erreur : Reçu vue de", in.Vue.Vues[0].Voyeur, " dans un message de", in.IdBraldun) } else { ms.mdb.Reçoit(in.Vue.Vues[0]) if ms.stockeVue(in.IdBraldun, in.Mdpr, bin, couche) { //> on s'occupe aussi des amis for _, ami := range amis { log.Println(" enrichissement carte ami ", ami.IdBraldun, " lancé en goroutine") go bra.EnrichitCouchePNG(ms.répertoireCartesBraldun(ami.IdBraldun, ami.Mdpr), couche, TAILLE_CACHE_PNG) } } else { log.Println(" Carte inchangée") } } } if in.Cmd == "carte" || in.Cmd == "" { // pour la compatibilité ascendante, la commande est provisoirement optionnelle //> récupération et stockage, si demandé, de la vue et de l'état d'un autre braldun if in.Action == "maj" && in.Cible > 0 { log.Println(" Demande mise à jour de", in.Cible) if !ms.mdb.MajPossible(in.Cible) { log.Println(" Impossible de mettre à jour la vue de", in.Cible) } else { cc, errstr := con.GetCompteExistant(in.Cible) if errstr != "" { log.Println(" erreur durant la récupération du compte de", in.Cible) } else { // TODO utiliser des goroutines pour paralléliser les deux requêtes (vue et profil) ? //> récupération de l'état log.Println(" Demande de l'état par script public") eb, err := bra.EtatBraldunParScriptPublic(in.Cible, cc.Mdpr) if err != nil { log.Println(" erreur durant la récupération par script public de l'état de", in.Cible) } else if eb == nil || eb.PVMax == 0 { log.Println(" état invalide") } else { err = con.StockeEtatBraldun(eb) if err != nil { log.Println(" erreur durant le stockage de l'état de", in.Cible) } } //> récupération de la vue log.Println(" Demande de la vue par script public") dv, err := bra.VueParScriptPublic(in.Cible, cc.Mdpr, filepath.Join(ms.répertoireDonnées, "public")) if err != nil { log.Println(" erreur durant la récupération par script public de la vue de", in.Cible) } else if len(dv.Vues) < 1 { log.Println(" échec : pas de vue") } else { log.Println(" Vue reçue") ms.mdb.Reçoit(dv.Vues[0]) if dv.Vues[0].Voyeur != in.Cible { log.Println(" mauvais voyeur dans vue reçue : %d", dv.Vues[0].Voyeur) dv.Vues[0].Voyeur = in.Cible } spin := new(bra.MessageIn) // on crée un messageIn car c'est sous ce format que sont stockés les données des bralduns spin.IdBraldun = in.Cible spin.Mdpr = cc.Mdpr spin.Vue = dv spin.Action = in.Action spin.Cmd = "sp_vue" spin.Version = versionActuelleExtension.String() bspin, err := json.Marshal(spin) if err != nil { log.Println(" erreur durant l'encodage en json de ", in.Cible) } else { if ms.stockeVue(in.Cible, cc.Mdpr, bspin, dv.Couches[0]) { camis, err := con.Amis(in.Cible) if err != nil { log.Println(" erreur durant récupération des amis de", in.Cible) } else { log.Printf(" Amis de %d : \n", in.Cible) for _, a := range camis { log.Println(" ", a.IdBraldun) } for _, cami := range camis { log.Println(" enrichissement carte ", cami.IdBraldun) bra.EnrichitCouchePNG(ms.répertoireCartesBraldun(cami.IdBraldun, cami.Mdpr), dv.Couches[0], TAILLE_CACHE_PNG) } } } } } } } } //> renseignements sur les couches disponibles out.ZConnus, err = bra.CouchesPNGDisponibles(dirBase) if err != nil { log.Println(" erreur durant la détermination des couches disponibles") } //> renvoi des données de vues provenant des amis log.Println(" Préparation Données vue pour le retour") log.Printf(" Amis de %d : \n", in.IdBraldun) for _, a := range amis { log.Println(" ", a.IdBraldun) } if amis != nil { vues := ms.mdb.Fusionne(in.IdBraldun, amis) log.Printf(" %d vues en retour\n", len(vues)) if len(vues) > 0 { out.DV = new(bra.DonnéesVue) out.DV.Vues = vues } } //> renvoi de l'état des amis if len(amis) > 0 { out.Etats = make([]*bra.EtatBraldun, 0, len(amis)) for _, ami := range amis { eb, err := con.EtatBraldun(ami.IdBraldun) if err != nil { log.Println(" Erreur à la récupération de l'état de", ami.IdBraldun, ":", err) } else if eb != nil { out.Etats = append(out.Etats, eb) } } } //> renvoi de la carte en png log.Println(" ZRequis : ", in.ZRequis) out.Z = in.ZRequis cheminLocalImage := fmt.Sprintf("%s/%d-%s/couche%d.png", ms.répertoireCartes, in.IdBraldun, in.Mdpr, in.ZRequis) if f, err := os.Open(cheminLocalImage); err == nil { defer f.Close() bytes, _ := ioutil.ReadAll(f) out.PngCouche = "data:image/png;base64," + base64.StdEncoding.EncodeToString(bytes) } } else if in.Cmd == "partages" { if in.Action != "" && in.Cible > 0 { con.ModifiePartage(in.IdBraldun, in.Cible, in.Action) } out.Partages, err = con.Partages(in.IdBraldun) if err != nil { log.Println(" erreur à la récupération des partages :", err) } } }