2022-12-12 19:40:43 +03:00
|
|
|
package admin
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"net/http"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
|
|
|
|
"github.com/owncast/owncast/config"
|
|
|
|
"github.com/owncast/owncast/utils"
|
2024-07-02 08:17:10 +03:00
|
|
|
"github.com/owncast/owncast/webserver/handlers/generated"
|
2024-07-02 07:44:37 +03:00
|
|
|
webutils "github.com/owncast/owncast/webserver/utils"
|
2022-12-12 19:40:43 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
// UploadCustomEmoji allows POSTing a new custom emoji to the server.
|
|
|
|
func UploadCustomEmoji(w http.ResponseWriter, r *http.Request) {
|
|
|
|
if !requirePOST(w, r) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-07-02 08:17:10 +03:00
|
|
|
emoji := new(generated.UploadCustomEmojiJSONBody)
|
2022-12-12 19:40:43 +03:00
|
|
|
|
|
|
|
if err := json.NewDecoder(r.Body).Decode(emoji); err != nil {
|
2024-07-02 07:44:37 +03:00
|
|
|
webutils.WriteSimpleResponse(w, false, err.Error())
|
2022-12-12 19:40:43 +03:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-07-02 08:17:10 +03:00
|
|
|
bytes, _, err := utils.DecodeBase64Image(*emoji.Data)
|
2022-12-12 19:40:43 +03:00
|
|
|
if err != nil {
|
2024-07-02 07:44:37 +03:00
|
|
|
webutils.WriteSimpleResponse(w, false, err.Error())
|
2022-12-12 19:40:43 +03:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Prevent path traversal attacks
|
2024-07-02 08:17:10 +03:00
|
|
|
emojiFileName := filepath.Base(*emoji.Name)
|
2022-12-17 07:22:21 +03:00
|
|
|
targetPath := filepath.Join(config.CustomEmojiPath, emojiFileName)
|
2022-12-12 19:40:43 +03:00
|
|
|
|
2022-12-17 07:22:21 +03:00
|
|
|
err = os.MkdirAll(config.CustomEmojiPath, 0o700)
|
2022-12-12 19:40:43 +03:00
|
|
|
if err != nil {
|
2024-07-02 07:44:37 +03:00
|
|
|
webutils.WriteSimpleResponse(w, false, err.Error())
|
2022-12-12 19:40:43 +03:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if utils.DoesFileExists(targetPath) {
|
2024-07-02 07:44:37 +03:00
|
|
|
webutils.WriteSimpleResponse(w, false, fmt.Sprintf("An emoji with the name %q already exists", emojiFileName))
|
2022-12-12 19:40:43 +03:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if err = os.WriteFile(targetPath, bytes, 0o600); err != nil {
|
2024-07-02 07:44:37 +03:00
|
|
|
webutils.WriteSimpleResponse(w, false, err.Error())
|
2022-12-12 19:40:43 +03:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-07-02 07:44:37 +03:00
|
|
|
webutils.WriteSimpleResponse(w, true, fmt.Sprintf("Emoji %q has been uploaded", emojiFileName))
|
2022-12-12 19:40:43 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// DeleteCustomEmoji deletes a custom emoji.
|
|
|
|
func DeleteCustomEmoji(w http.ResponseWriter, r *http.Request) {
|
|
|
|
if !requirePOST(w, r) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
type deleteEmoji struct {
|
|
|
|
Name string `json:"name"`
|
|
|
|
}
|
|
|
|
|
|
|
|
emoji := new(deleteEmoji)
|
|
|
|
|
|
|
|
if err := json.NewDecoder(r.Body).Decode(emoji); err != nil {
|
2024-07-02 07:44:37 +03:00
|
|
|
webutils.WriteSimpleResponse(w, false, err.Error())
|
2022-12-12 19:40:43 +03:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2022-12-17 07:22:21 +03:00
|
|
|
targetPath := filepath.Join(config.CustomEmojiPath, emoji.Name)
|
2022-12-12 19:40:43 +03:00
|
|
|
|
2024-01-21 06:48:52 +03:00
|
|
|
if !filepath.IsLocal(targetPath) {
|
2024-07-02 07:44:37 +03:00
|
|
|
webutils.WriteSimpleResponse(w, false, "Emoji path is not valid")
|
2024-01-21 06:48:52 +03:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2022-12-12 19:40:43 +03:00
|
|
|
if err := os.Remove(targetPath); err != nil {
|
|
|
|
if os.IsNotExist(err) {
|
2024-07-02 07:44:37 +03:00
|
|
|
webutils.WriteSimpleResponse(w, false, fmt.Sprintf("Emoji %q doesn't exist", emoji.Name))
|
2022-12-12 19:40:43 +03:00
|
|
|
} else {
|
2024-07-02 07:44:37 +03:00
|
|
|
webutils.WriteSimpleResponse(w, false, err.Error())
|
2022-12-12 19:40:43 +03:00
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-07-02 07:44:37 +03:00
|
|
|
webutils.WriteSimpleResponse(w, true, fmt.Sprintf("Emoji %q has been deleted", emoji.Name))
|
2022-12-12 19:40:43 +03:00
|
|
|
}
|