package classes import ( "context" "regexp" "strings" ) // VerificationNamePattern is the form of a verification file name (D-05, // T-32-21): no slashes, an html, txt or xml extension. const VerificationNamePattern = `[A-Za-z0-9._-]+\.(html|txt|xml)` var verificationName = regexp.MustCompile(`^` + VerificationNamePattern + `$`) // VerificationFile is one stored search-engine verification file. type VerificationFile struct { Name string Body string ContentType string } // verificationTypes are the content types per extension. var verificationTypes = map[string]string{ ".html": "text/html; charset=utf-8", ".txt": "text/plain; charset=utf-8", ".xml": "application/xml; charset=utf-8", } // VerificationFileByName returns the verification file stored in the SEO // settings under name (D-05, D-103), found false for an unknown or // malformed name. The frontend serves it at the site root (Phase 33); the // plugin never registers a root route for it. func (s *Service) VerificationFileByName(ctx context.Context, name string) (VerificationFile, bool, error) { if !verificationName.MatchString(name) { return VerificationFile{}, false, nil } db, err := s.DB(ctx) if err != nil { return VerificationFile{}, false, err } settings, err := LoadSettings(db) if err != nil { return VerificationFile{}, false, err } for _, f := range settings.Files() { if strings.TrimSpace(f.Filename) != name { continue } ext := name[strings.LastIndex(name, "."):] return VerificationFile{Name: name, Body: f.Body, ContentType: verificationTypes[strings.ToLower(ext)]}, true, nil } return VerificationFile{}, false, nil }