Add_Directory_and_ProfilePicture #9
|
@ -24,43 +24,39 @@ import (
|
||||||
"github.com/nfnt/resize"
|
"github.com/nfnt/resize"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const PROFILE_PICTURE_FIELD_NAME = "profilePicture"
|
||||||
|
|
||||||
//Upload image through guichet server.
|
//Upload image through guichet server.
|
||||||
func uploadImage(w http.ResponseWriter, r *http.Request, login *LoginStatus) (bool, string, error) {
|
func uploadImage(w http.ResponseWriter, r *http.Request, login *LoginStatus) (string, error) {
|
||||||
file, _, err := r.FormFile("image")
|
file, _, err := r.FormFile("image")
|
||||||
|
|
||||||
if err == http.ErrMissingFile {
|
if err == http.ErrMissingFile {
|
||||||
return false, "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, "", err
|
return "", err
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
fileType, err := checkImage(file)
|
err = checkImage(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, "", err
|
return "", err
|
||||||
}
|
|
||||||
if fileType == "" {
|
|
||||||
return false, "", nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
buff := bytes.NewBuffer([]byte{})
|
buff := bytes.NewBuffer([]byte{})
|
||||||
buff_thumbnail := bytes.NewBuffer([]byte{})
|
buff_thumbnail := bytes.NewBuffer([]byte{})
|
||||||
err = resizeThumb(file, buff, buff_thumbnail)
|
err = resizeThumb(file, buff, buff_thumbnail)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
mc, err := newMimioClient()
|
mc, err := newMinioClient()
|
||||||
if err != nil {
|
if err != nil || mc == nil {
|
||||||
return false, "", err
|
return "", err
|
||||||
}
|
|
||||||
if mc == nil {
|
|
||||||
return false, "", err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var name, nameFull string
|
var name, nameFull string
|
||||||
|
|
||||||
if nameConsul := login.UserEntry.GetAttributeValue("profilImage"); nameConsul != "" {
|
if nameConsul := login.UserEntry.GetAttributeValue(PROFILE_PICTURE_FIELD_NAME); nameConsul != "" {
|
||||||
name = nameConsul
|
name = nameConsul
|
||||||
nameFull = "full_" + name
|
nameFull = "full_" + name
|
||||||
} else {
|
} else {
|
||||||
|
@ -68,34 +64,34 @@ func uploadImage(w http.ResponseWriter, r *http.Request, login *LoginStatus) (bo
|
||||||
nameFull = "full_" + name
|
nameFull = "full_" + name
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = mc.PutObject(context.Background(), "bottin-pictures", name, buff_thumbnail, int64(buff_thumbnail.Len()), minio.PutObjectOptions{
|
_, err = mc.PutObject(context.Background(), config.S3_Bucket, name, buff_thumbnail, int64(buff_thumbnail.Len()), minio.PutObjectOptions{
|
||||||
ContentType: "image/jpeg",
|
ContentType: "image/jpeg",
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = mc.PutObject(context.Background(), "bottin-pictures", nameFull, buff, int64(buff.Len()), minio.PutObjectOptions{
|
_, err = mc.PutObject(context.Background(), config.S3_Bucket, nameFull, buff, int64(buff.Len()), minio.PutObjectOptions{
|
||||||
ContentType: "image/jpeg",
|
ContentType: "image/jpeg",
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
return true, name, nil
|
return name, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newMimioClient() (*minio.Client, error) {
|
func newMinioClient() (*minio.Client, error) {
|
||||||
endpoint := config.Endpoint
|
endpoint := config.S3_Endpoint
|
||||||
accessKeyID := config.AccesKey
|
accessKeyID := config.S3_AccesKey
|
||||||
secretKeyID := config.SecretKey
|
secretKeyID := config.S3_SecretKey
|
||||||
useSSL := true
|
useSSL := true
|
||||||
|
|
||||||
//Initialize Minio
|
//Initialize Minio
|
||||||
minioCLient, err := minio.New(endpoint, &minio.Options{
|
minioCLient, err := minio.New(endpoint, &minio.Options{
|
||||||
Creds: credentials.NewStaticV4(accessKeyID, secretKeyID, ""),
|
Creds: credentials.NewStaticV4(accessKeyID, secretKeyID, ""),
|
||||||
Secure: useSSL,
|
Secure: useSSL,
|
||||||
Region: "garage",
|
Region: config.S3_Region,
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -106,11 +102,11 @@ func newMimioClient() (*minio.Client, error) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkImage(file multipart.File) (string, error) {
|
func checkImage(file multipart.File) error {
|
||||||
buff := make([]byte, 512) //Detect read only the first 512 bytes
|
buff := make([]byte, 512) //Detect read only the first 512 bytes
|
||||||
_, err := file.Read(buff)
|
_, err := file.Read(buff)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return err
|
||||||
}
|
}
|
||||||
file.Seek(0, 0)
|
file.Seek(0, 0)
|
||||||
|
|
||||||
|
@ -118,9 +114,9 @@ func checkImage(file multipart.File) (string, error) {
|
||||||
fileType = strings.Split(fileType, "/")[0]
|
fileType = strings.Split(fileType, "/")[0]
|
||||||
switch fileType {
|
switch fileType {
|
||||||
case "image":
|
case "image":
|
||||||
return fileType, nil
|
return nil
|
||||||
default:
|
default:
|
||||||
return "", errors.New("bad type")
|
return errors.New("bad type")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -128,17 +124,6 @@ func checkImage(file multipart.File) (string, error) {
|
||||||
func resizeThumb(file multipart.File, buff, buff_thumbnail *bytes.Buffer) error {
|
func resizeThumb(file multipart.File, buff, buff_thumbnail *bytes.Buffer) error {
|
||||||
file.Seek(0, 0)
|
file.Seek(0, 0)
|
||||||
images, _, err := image.Decode(file)
|
images, _, err := image.Decode(file)
|
||||||
if err != nil {
|
|
||||||
return errors.New("Decode: " + err.Error())
|
|
||||||
}
|
|
||||||
//Encode image to jpeg a first time to eliminate all problems
|
|
||||||
err = jpeg.Encode(buff, images, &jpeg.Options{
|
|
||||||
Quality: 100, //Between 1 to 100, higher is better
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
images, _, err = image.Decode(buff)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -164,7 +149,6 @@ func handleDownloadImage(w http.ResponseWriter, r *http.Request) {
|
||||||
//Get input value by user
|
//Get input value by user
|
||||||
dn := mux.Vars(r)["name"]
|
dn := mux.Vars(r)["name"]
|
||||||
size := mux.Vars(r)["size"]
|
size := mux.Vars(r)["size"]
|
||||||
|
|
||||||
//Check login
|
//Check login
|
||||||
login := checkLogin(w, r)
|
login := checkLogin(w, r)
|
||||||
if login == nil {
|
if login == nil {
|
||||||
|
@ -173,11 +157,12 @@ func handleDownloadImage(w http.ResponseWriter, r *http.Request) {
|
||||||
var imageName string
|
var imageName string
|
||||||
if dn != "unknown_profile" {
|
if dn != "unknown_profile" {
|
||||||
//Search values with ldap and filter
|
//Search values with ldap and filter
|
||||||
|
|
||||||
searchRequest := ldap.NewSearchRequest(
|
searchRequest := ldap.NewSearchRequest(
|
||||||
dn,
|
dn,
|
||||||
ldap.ScopeBaseObject, ldap.NeverDerefAliases, 0, 0, false,
|
ldap.ScopeBaseObject, ldap.NeverDerefAliases, 0, 0, false,
|
||||||
"(objectclass=*)",
|
"(objectclass=*)",
|
||||||
[]string{"profilImage"},
|
[]string{PROFILE_PICTURE_FIELD_NAME},
|
||||||
nil)
|
nil)
|
||||||
|
|
||||||
sr, err := login.conn.Search(searchRequest)
|
sr, err := login.conn.Search(searchRequest)
|
||||||
|
@ -189,9 +174,9 @@ func handleDownloadImage(w http.ResponseWriter, r *http.Request) {
|
||||||
http.Error(w, fmt.Sprintf("Not found user: %s cn: %s and numberEntries: %d", dn, strings.Split(dn, ",")[0], len(sr.Entries)), http.StatusInternalServerError)
|
http.Error(w, fmt.Sprintf("Not found user: %s cn: %s and numberEntries: %d", dn, strings.Split(dn, ",")[0], len(sr.Entries)), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
imageName = sr.Entries[0].GetAttributeValue("profilImage")
|
imageName = sr.Entries[0].GetAttributeValue(PROFILE_PICTURE_FIELD_NAME)
|
||||||
if imageName == "" {
|
if imageName == "" {
|
||||||
http.Error(w, "User doesn't have profile image", http.StatusInternalServerError)
|
http.Error(w, "User doesn't have profile image", http.StatusNotFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -201,9 +186,8 @@ func handleDownloadImage(w http.ResponseWriter, r *http.Request) {
|
||||||
if size == "full" {
|
if size == "full" {
|
||||||
imageName = "full_" + imageName
|
imageName = "full_" + imageName
|
||||||
}
|
}
|
||||||
|
|
||||||
//Get the object after connect MC
|
//Get the object after connect MC
|
||||||
mc, err := newMimioClient()
|
mc, err := newMinioClient()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "MinioClient: "+err.Error(), http.StatusInternalServerError)
|
http.Error(w, "MinioClient: "+err.Error(), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
|
@ -216,29 +200,17 @@ func handleDownloadImage(w http.ResponseWriter, r *http.Request) {
|
||||||
defer obj.Close()
|
defer obj.Close()
|
||||||
objStat, err := obj.Stat()
|
objStat, err := obj.Stat()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "MinioObjet: "+err.Error(), http.StatusInternalServerError)
|
http.Error(w, "MiniObjet: "+err.Error(), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//Send JSON through xhttp
|
//Send JSON through xhttp
|
||||||
w.Header().Set("Content-Type", objStat.ContentType)
|
w.Header().Set("Content-Type", objStat.ContentType)
|
||||||
w.Header().Set("Content-Length", strconv.Itoa(int(objStat.Size)))
|
w.Header().Set("Content-Length", strconv.Itoa(int(objStat.Size)))
|
||||||
//http.Error(w, fmt.Sprintf("Length buffer: %d", objStat.Size), http.StatusInternalServerError)
|
//Copy obj in w
|
||||||
buff := make([]byte, objStat.Size)
|
writting, err := io.Copy(w, obj)
|
||||||
|
if writting != objStat.Size || err != nil {
|
||||||
obj.Seek(0, 0)
|
http.Error(w, fmt.Sprintf("WriteBody: %s, bytes wrote %d on %d", err.Error(), writting, objStat.Size), http.StatusInternalServerError)
|
||||||
n, err := obj.Read(buff)
|
|
||||||
if err != nil && err != io.EOF {
|
|
||||||
http.Error(w, fmt.Sprintf("Read Error: %s, bytes Read: %d, bytes in file: %d", err.Error(), n, objStat.Size), http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if int64(n) != objStat.Size {
|
|
||||||
http.Error(w, fmt.Sprintf("Read %d bytes on %d bytes", n, objStat.Size), http.StatusInternalServerError)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := w.Write(buff); err != nil {
|
|
||||||
http.Error(w, "WriteBody: "+err.Error(), http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
21
directory.go
|
@ -22,8 +22,8 @@ func handleDirectory(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type SearchResult struct {
|
type SearchResult struct {
|
||||||
Identifiant string `json:"identifiant"`
|
Id string `json:"id"`
|
||||||
erwan marked this conversation as resolved
Outdated
|
|||||||
Name string `json:"name"`
|
Displayname string `json:"displayname"`
|
||||||
erwan marked this conversation as resolved
Outdated
lx
commented
C'est le displayname que tu prends depuis le LDAP? Dans ce cas il faudrait appeller ça C'est le displayname que tu prends depuis le LDAP? Dans ce cas il faudrait appeller ça `DisplayName`
|
|||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
DN string `json:"dn"`
|
DN string `json:"dn"`
|
||||||
|
@ -61,15 +61,16 @@ func handleSearch(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//Transform the researh's result in a correct struct to send HSON
|
//Transform the researh's result in a correct struct to send JSON
|
||||||
var result Results
|
var result Results
|
||||||
for _, values := range sr.Entries {
|
for _, values := range sr.Entries {
|
||||||
|
|
||||||
if strings.Contains(values.GetAttributeValue("cn"), input) {
|
if strings.Contains(values.GetAttributeValue(config.UserNameAttr), input) || strings.Contains(values.GetAttributeValue("displayname"), input) ||
|
||||||
erwan marked this conversation as resolved
Outdated
lx
commented
1. Ce n'est pas toujours `cn` l'attribut qui contient l'identifiant de la personne, c'est le paramètre `config.UserNameAttr` qui te donne le bon attribut à checker
2. On aimerait aussi chercher dans le displayname, et peut-être aussi le mail
|
|||||||
|
(values.GetAttributeValue("email") != "" && strings.Contains(values.GetAttributeValue("email"), input)) {
|
||||||
result = Results{
|
result = Results{
|
||||||
Search: append(result.Search, SearchResult{
|
Search: append(result.Search, SearchResult{
|
||||||
erwan marked this conversation as resolved
Outdated
lx
commented
Idem, c'est pas Idem, c'est pas `cn` chez tout le monde
|
|||||||
Identifiant: values.GetAttributeValue("cn"),
|
Id: values.GetAttributeValue(config.UserNameAttr),
|
||||||
Name: values.GetAttributeValue("displayname"),
|
Displayname: values.GetAttributeValue("displayname"),
|
||||||
Email: values.GetAttributeValue("email"),
|
Email: values.GetAttributeValue("email"),
|
||||||
Description: values.GetAttributeValue("description"),
|
Description: values.GetAttributeValue("description"),
|
||||||
DN: values.DN,
|
DN: values.DN,
|
||||||
|
@ -80,13 +81,7 @@ func handleSearch(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
if result.Search == nil {
|
if result.Search == nil {
|
||||||
result = Results{
|
result = Results{
|
||||||
Search: append(result.Search, SearchResult{
|
Search: append(result.Search, SearchResult{}),
|
||||||
Identifiant: "",
|
|
||||||
Name: "",
|
|
||||||
Email: "",
|
|
||||||
Description: "",
|
|
||||||
DN: "",
|
|
||||||
}),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
13
main.go
|
@ -44,9 +44,11 @@ type ConfigFile struct {
|
||||||
GroupCanInvite string `json:"group_can_invite"`
|
GroupCanInvite string `json:"group_can_invite"`
|
||||||
GroupCanAdmin string `json:"group_can_admin"`
|
GroupCanAdmin string `json:"group_can_admin"`
|
||||||
|
|
||||||
Endpoint string `json:"endpoint"`
|
S3_Endpoint string `json:"s3_endpoint"`
|
||||||
erwan marked this conversation as resolved
Outdated
lx
commented
Endpoint de quoi? Il faudrait appeller ça Endpoint de quoi? Il faudrait appeller ça `S3Endpoint` pour être clair, et les autres les appeller `S3AccessKey` et `S3SecretKey`.
|
|||||||
AccesKey string `json:"acces_key"`
|
S3_AccesKey string `json:"s3_acces_key"`
|
||||||
SecretKey string `json:"secret_key"`
|
S3_SecretKey string `json:"s3_secret_key"`
|
||||||
|
S3_Region string `json:"s3_region"`
|
||||||
|
S3_Bucket string `json:"s3_bucket"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var configFlag = flag.String("config", "./config.json", "Configuration file path")
|
var configFlag = flag.String("config", "./config.json", "Configuration file path")
|
||||||
|
@ -250,7 +252,7 @@ func checkLogin(w http.ResponseWriter, r *http.Request) *LoginStatus {
|
||||||
login_info.DN,
|
login_info.DN,
|
||||||
ldap.ScopeBaseObject, ldap.NeverDerefAliases, 0, 0, false,
|
ldap.ScopeBaseObject, ldap.NeverDerefAliases, 0, 0, false,
|
||||||
erwan marked this conversation as resolved
Outdated
lx
commented
pas de français ! appller ça pas de français ! appller ça `profilePicture` et non `profilImage`
|
|||||||
requestKind,
|
requestKind,
|
||||||
[]string{"dn", "displayname", "givenname", "sn", "mail", "memberof", "visibility", "description", "profilImage"},
|
[]string{"dn", "displayname", "givenname", "sn", "mail", "memberof", "visibility", "description", PROFILE_PICTURE_FIELD_NAME},
|
||||||
nil)
|
nil)
|
||||||
|
|
||||||
sr, err := l.Search(searchRequest)
|
sr, err := l.Search(searchRequest)
|
||||||
|
@ -398,9 +400,6 @@ func handleLogin(w http.ResponseWriter, r *http.Request) *LoginInfo {
|
||||||
session.Values["login_password"] = password
|
session.Values["login_password"] = password
|
||||||
session.Values["login_dn"] = user_dn
|
session.Values["login_dn"] = user_dn
|
||||||
|
|
||||||
erwan marked this conversation as resolved
Outdated
lx
commented
je pense que tu peux enlever ça du coup je pense que tu peux enlever ça du coup
|
|||||||
//Add Value MessageID
|
|
||||||
session.Values["MessageID"] = uint32(0)
|
|
||||||
|
|
||||||
err = session.Save(r, w)
|
err = session.Save(r, w)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
|
|
@ -56,12 +56,12 @@ func handleProfile(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
data.Visibility = visible
|
data.Visibility = visible
|
||||||
|
|
||||||
ok, name, err := uploadImage(w, r, login)
|
name, err := uploadImage(w, r, login)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
data.ErrorMessage = err.Error()
|
data.ErrorMessage = err.Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
if ok {
|
if name != "" {
|
||||||
data.NameImage = name
|
data.NameImage = name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,8 +71,8 @@ func handleProfile(w http.ResponseWriter, r *http.Request) {
|
||||||
modify_request.Replace("sn", []string{data.Surname})
|
modify_request.Replace("sn", []string{data.Surname})
|
||||||
modify_request.Replace("description", []string{data.Description})
|
modify_request.Replace("description", []string{data.Description})
|
||||||
modify_request.Replace("visibility", []string{data.Visibility})
|
modify_request.Replace("visibility", []string{data.Visibility})
|
||||||
if ok {
|
if name != "" {
|
||||||
modify_request.Replace("profilImage", []string{data.NameImage})
|
modify_request.Replace(PROFILE_PICTURE_FIELD_NAME, []string{data.NameImage})
|
||||||
}
|
}
|
||||||
|
|
||||||
err = login.conn.Modify(modify_request)
|
err = login.conn.Modify(modify_request)
|
||||||
|
|
|
@ -23,20 +23,20 @@ function searchDirectory() {
|
||||||
var row = table.insertRow(0);
|
var row = table.insertRow(0);
|
||||||
var urlName = row.insertCell(0);
|
var urlName = row.insertCell(0);
|
||||||
var identifiant = row.insertCell(1);
|
var identifiant = row.insertCell(1);
|
||||||
var name = row.insertCell(2);
|
var displayname = row.insertCell(2);
|
||||||
var email = row.insertCell(3);
|
var email = row.insertCell(3);
|
||||||
var description = row.insertCell(4);
|
var description = row.insertCell(4);
|
||||||
description.setAttribute("style", "word-break: break-all;");
|
description.setAttribute("style", "word-break: break-all;");
|
||||||
|
|
||||||
if (jsonResponse.search[i].dn.localeCompare("")!=0) {
|
if (jsonResponse.search[i].dn.localeCompare("")!=0) {
|
||||||
urlName.innerHTML = `<object data="/image/${jsonResponse.search[i].dn}/little" class=".img-thumbnail"><image src="/image/unknown_profile/little" class=".img-thumbnail"></object>`
|
urlName.innerText = `<object data="/image/${jsonResponse.search[i].dn}/little" class=".img-thumbnail"><image src="/image/unknown_profile/little" class=".img-thumbnail"></object>`
|
||||||
}else {
|
}else {
|
||||||
urlName.innerHTML=""
|
urlName.innerText=""
|
||||||
}
|
}
|
||||||
identifiant.innerHTML = `<a href="/admin/ldap/${jsonResponse.search[i].dn}">${jsonResponse.search[i].identifiant}</a>`
|
identifiant.innerText = `<a href="/admin/ldap/${jsonResponse.search[i].dn}">${jsonResponse.search[i].id}</a>`
|
||||||
name.innerHTML = jsonResponse.search[i].name
|
displayname.innerText = jsonResponse.search[i].displayname
|
||||||
email.innerHTML = jsonResponse.search[i].email
|
email.innerText = jsonResponse.search[i].email
|
||||||
description.innerHTML = jsonResponse.search[i].description
|
description.innerText = jsonResponse.search[i].description
|
||||||
lx
commented
faudrait utiliser innerText plutôt que innerHTML, sinon on peut trivialement faire une injection de script faudrait utiliser innerText plutôt que innerHTML, sinon on peut trivialement faire une injection de script
erwan
commented
?? une injection de script dans un JS ? je ne comprends pas bien. J'ai quand-même appliqué tes modifications. Mais je ne serais pas contre plus de détails. ?? une injection de script dans un JS ? je ne comprends pas bien. J'ai quand-même appliqué tes modifications. Mais je ne serais pas contre plus de détails.
lx
commented
Imagine dans ma description je met Avec Avec Imagine dans ma description je met `<script>alert('coucou')</script>`.
Avec `innerText`, ça apparait tel quel.
Avec `innerHTML`, quand quelqu'un affiche mon profil, ça lui fait une popup qui affiche coucou.
erwan
commented
Donc si je comprends bien, si un utilisateur crée un compte qui se nomme Donc si je comprends bien, si un utilisateur crée un compte qui se nomme `<script>alert('coucou')</script>` alors à chaque fois qu'on le cherchera sur l'annuaire ça produira cette pop-up ?
|
|||||||
|
|
||||||
}
|
}
|
||||||
old_table.parentNode.replaceChild(table, old_table)
|
old_table.parentNode.replaceChild(table, old_table)
|
||||||
|
|
L'identifiant, c'est le CN ? Dans tous les cas
Identifiant
c'est un mot français, il faudrait appeller ça plutôt justeId
.