package server import ( "net/http" "strings" ) // handleImage serves images for model records. // Mirrors: odoo/addons/web/controllers/binary.py content_image() // For now, return SVG placeholders that look like real Odoo avatars. func (s *Server) handleImage(w http.ResponseWriter, r *http.Request) { field := r.URL.Query().Get("field") model := r.URL.Query().Get("model") // Also parse path-style URLs: /web/image/res.partner/2/avatar_128 path := strings.TrimPrefix(r.URL.Path, "/web/image/") if model == "" && path != "" && path != r.URL.Path { pathParts := strings.Split(path, "/") if len(pathParts) >= 3 { model = pathParts[0] field = pathParts[2] } else if len(pathParts) >= 1 { model = pathParts[0] } } // Company logo: return a styled SVG with company initial if model == "res.company" && (field == "logo" || field == "logo_web") { w.Header().Set("Content-Type", "image/svg+xml") w.Header().Set("Cache-Control", "public, max-age=3600") w.Write([]byte(` Odoo `)) return } // User avatar: return a colored circle with initial if (model == "res.partner" || model == "res.users") && (field == "avatar_128" || field == "avatar_256" || field == "image_128" || field == "image_256" || strings.HasPrefix(field, "avatar") || strings.HasPrefix(field, "image")) { w.Header().Set("Content-Type", "image/svg+xml") w.Header().Set("Cache-Control", "public, max-age=3600") w.Write([]byte(` U `)) return } // Default: 1x1 transparent PNG w.Header().Set("Content-Type", "image/png") w.Header().Set("Cache-Control", "public, max-age=3600") png := []byte{ 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0x15, 0xc4, 0x89, 0x00, 0x00, 0x00, 0x0a, 0x49, 0x44, 0x41, 0x54, 0x78, 0x9c, 0x62, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0xe5, 0x27, 0xde, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, } w.Write(png) }