package api import ( "encoding/base64" "errors" "net/http" "strings" "gardomatic.kleiax.de/internal/storage" ) func (app *application) resolveImage(gardenID int, data string, selectedID *int, userID int, source string) (*int, error) { if strings.TrimSpace(data) == "" { if selectedID == nil { return nil, nil } if _, err := app.models.Images.Get(gardenID, *selectedID); err != nil { return nil, err } return selectedID, nil } comma := strings.IndexByte(data, ',') if comma < 1 || !strings.HasPrefix(data, "data:image/") || !strings.HasSuffix(data[:comma], ";base64") { return nil, errors.New("invalid image data") } mediaType := strings.TrimSuffix(strings.TrimPrefix(data[:comma], "data:"), ";base64") decoded, err := base64.StdEncoding.DecodeString(data[comma+1:]) if err != nil || len(decoded) == 0 || len(decoded) > storage.MaxImageSize { return nil, errors.New("invalid image data") } image, err := app.models.Images.Insert(storage.Image{GardenID: gardenID, MediaType: mediaType, Data: decoded, Source: source, CreatedBy: userID}) if err != nil { return nil, err } return &image.ID, nil } func (app *application) recordImageAssignment(change storage.ImageAssignment) error { if app.models.Images == nil { return nil } return app.models.Images.RecordAssignment(change) } func (app *application) listImagesHandler(w http.ResponseWriter, r *http.Request) { gardenID, _ := app.readGardenIDParam(r) images, err := app.models.Images.GetAllForGarden(gardenID, storage.ImageFilter{Source: r.URL.Query().Get("source"), Query: r.URL.Query().Get("q")}) if err != nil { app.serverErrorResponse(w, r, err) return } if err = app.writeJSON(w, http.StatusOK, envelope{"images": images}, nil); err != nil { app.serverErrorResponse(w, r, err) } } func (app *application) showImageHandler(w http.ResponseWriter, r *http.Request) { gardenID, _ := app.readGardenIDParam(r) id, err := app.readNamedIDParam(r, "imageID") if err != nil { app.notFoundResponse(w, r) return } image, err := app.models.Images.Get(gardenID, id) if err != nil { app.respondToEntityModelError(w, r, err) return } w.Header().Set("Content-Type", image.MediaType) w.Header().Set("Cache-Control", "private, max-age=86400") _, _ = w.Write(image.Data) }