github.com/google/go-safeweb@v0.0.0-20231219055052-64d8cfc90fbb/safehttp/plugins/htmlinject/embed_1_16.go (about) 1 // Copyright 2020 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 //go:build go1.16 16 // +build go1.16 17 18 package htmlinject 19 20 import ( 21 "embed" 22 "fmt" 23 "io" 24 "io/fs" 25 "path/filepath" 26 27 "github.com/google/safehtml/template" 28 "github.com/google/safehtml/template/uncheckedconversions" 29 ) 30 31 // LoadGlobEmbed is like LoadGlob but works on an embedded filesystem. 32 func LoadGlobEmbed(tpl *template.Template, lcfg LoadConfig, pattern template.TrustedSource, fsys embed.FS) (*template.Template, error) { 33 return loadGlobFS(tpl, lcfg, pattern, fsys) 34 } 35 36 // TODO(clap): the rest of this file is a copy-paste of a lot of code. Unify this code path with that 37 // once we decide to drop support for Go version before 1.16 and we can use fs everywhere. 38 39 func loadGlobFS(tpl *template.Template, lcfg LoadConfig, pattern template.TrustedSource, fsys embed.FS) (*template.Template, error) { 40 filenames, err := fs.Glob(fsys, pattern.String()) 41 if err != nil { 42 return nil, err 43 } 44 if len(filenames) == 0 { 45 return nil, fmt.Errorf("pattern matches no files: %#q", pattern.String()) 46 } 47 var tts []template.TrustedSource 48 for _, fn := range filenames { 49 // The pattern expanded from a trusted source, so the expansion is still trusted. 50 tts = append(tts, uncheckedconversions.TrustedSourceFromStringKnownToSatisfyTypeContract(fn)) 51 } 52 return loadFilesFS(tpl, lcfg, fsys, tts...) 53 } 54 55 func loadFilesFS(tpl *template.Template, lcfg LoadConfig, fsys fs.FS, filenames ...template.TrustedSource) (*template.Template, error) { 56 // The naming juggling below is quite odd but is kept for consistency. 57 if len(filenames) == 0 { 58 return nil, fmt.Errorf("no files named in call to LoadFiles") 59 } 60 for _, fnts := range filenames { 61 fn := fnts.String() 62 f, err := fsys.Open(fn) 63 if err != nil { 64 return nil, err 65 } 66 b, err := io.ReadAll(f) 67 if err != nil { 68 return nil, err 69 } 70 name := filepath.Base(fn) 71 var t *template.Template 72 if tpl == nil { 73 tpl = template.New(name) 74 } 75 if name == tpl.Name() { 76 t = tpl 77 } else { 78 t = tpl.New(name) 79 } 80 // We are loading a file from a TrustedSource, so this conversion is safe. 81 tts := uncheckedconversions.TrustedTemplateFromStringKnownToSatisfyTypeContract(string(b)) 82 _, err = LoadTrustedTemplate(t, lcfg, tts) 83 if err != nil { 84 return nil, err 85 } 86 } 87 return tpl, nil 88 }