change to text/template

This commit is contained in:
Ronni Skansing
2025-09-19 00:29:31 +02:00
parent 1759e0c985
commit 1aab0e499c
6 changed files with 66 additions and 64 deletions

View File

@@ -12,7 +12,7 @@ import (
"os"
"path/filepath"
"strings"
"text/template"
textTmpl "text/template"
"time"
"github.com/go-errors/errors"
@@ -316,7 +316,7 @@ func (s *Server) Handler(c *gin.Context) {
return
}
// TODO extract this into another method, maybe file
t, err := template.
t, err := textTmpl.
New("staticContent").
Funcs(service.TemplateFuncs()).
Parse(string(domain.PageNotFoundContent))
@@ -363,7 +363,7 @@ func (s *Server) Handler(c *gin.Context) {
c.Abort()
return
}
t, err := template.
t, err := textTmpl.
New("staticContent").
Funcs(service.TemplateFuncs()).
Parse(domain.PageContent)
@@ -421,7 +421,7 @@ func (s *Server) handlerNotFound(c *gin.Context) {
c.Status(http.StatusNotFound)
return
}
t := template.New("staticContent")
t := textTmpl.New("staticContent")
t = t.Funcs(service.TemplateFuncs())
tmpl, err := t.Parse(string(domain.PageNotFoundContent))
if err != nil {
@@ -919,7 +919,9 @@ func (s *Server) renderDenyPage(
if err != nil {
return fmt.Errorf("failed to get landing page: %s", err)
}
tmpl, err := template.New("page").Parse(page.Content.MustGet().String())
tmpl, err := textTmpl.New("page").
Funcs(service.TemplateFuncs()).
Parse(page.Content.MustGet().String())
if err != nil {
return fmt.Errorf("failed to parse page template: %s", err)
}

View File

@@ -5,11 +5,11 @@ import (
"bytes"
"embed"
"fmt"
"html/template"
"os"
"os/exec"
"path/filepath"
"strings"
"text/template"
"time"
)

View File

@@ -5,10 +5,10 @@ import (
"context"
"encoding/json"
"fmt"
"html/template"
"io"
"net/http"
"strings"
"text/template"
"time"
"github.com/go-errors/errors"
@@ -651,6 +651,7 @@ func (a *APISender) buildHeader(
if err != nil {
return nil, fmt.Errorf("failed to parse header value: %s", err)
}
valueTemplate = valueTemplate.Funcs(TemplateFuncs())
var value bytes.Buffer
if err := valueTemplate.Execute(&value, nil); err != nil {
return nil, fmt.Errorf("failed to execute value template: %s", err)
@@ -767,9 +768,7 @@ func (a *APISender) buildRequest(
}
// Remove the newline that Encode adds and the surrounding quotes
jsonStr := strings.TrimSpace(buf.String())
// Mark as safe HTML so template won't escape it
(*t)["Content"] = template.HTML(jsonStr[1 : len(jsonStr)-1])
(*t)["Content"] = jsonStr[1 : len(jsonStr)-1]
contentTemplate := template.New("content")
contentTemplate = contentTemplate.Funcs(TemplateFuncs())
contentTemplate, err = contentTemplate.Parse(apiSender.RequestBody.MustGet().String())

View File

@@ -1,17 +1,18 @@
package service
import (
"bytes"
"context"
"crypto/tls"
"errors"
"fmt"
"html/template"
"math/rand"
"os"
"path/filepath"
"slices"
"sort"
"strings"
"text/template"
"time"
go_errors "github.com/go-errors/errors"
@@ -1951,11 +1952,13 @@ func (c *Campaign) sendCampaignMessages(
email,
nil,
)
err = m.SetBodyHTMLTemplate(mailTmpl, t)
var bodyBuffer bytes.Buffer
err = mailTmpl.Execute(&bodyBuffer, t)
if err != nil {
c.Logger.Errorw("failed to set body html template", "error", err)
c.Logger.Errorw("failed to execute mail template", "error", err)
return errs.Wrap(err)
}
m.SetBodyString("text/html", bodyBuffer.String())
// attachments
attachments := email.Attachments
for _, attachment := range attachments {
@@ -3281,11 +3284,13 @@ func (c *Campaign) sendSingleEmailSMTP(
nil,
)
err = m.SetBodyHTMLTemplate(mailTmpl, t)
var bodyBuffer bytes.Buffer
err = mailTmpl.Execute(&bodyBuffer, t)
if err != nil {
c.Logger.Errorw("failed to set body html template", "error", err)
c.Logger.Errorw("failed to execute mail template", "error", err)
return errs.Wrap(err)
}
m.SetBodyString("text/html", bodyBuffer.String())
// handle attachments
attachments := email.Attachments

View File

@@ -1,13 +1,14 @@
package service
import (
"bytes"
"context"
"crypto/tls"
"fmt"
"html/template"
"os"
"path/filepath"
"strings"
"text/template"
"github.com/go-errors/errors"
@@ -597,11 +598,13 @@ func (m *Email) SendTestEmail(
email,
nil,
)
err = msg.SetBodyHTMLTemplate(mailTmpl, t)
var bodyBuffer bytes.Buffer
err = mailTmpl.Execute(&bodyBuffer, t)
if err != nil {
m.Logger.Errorw("failed to set body html template", "error", err)
return errs.Wrap(err)
m.Logger.Errorw("failed to execute mail template", "error", err)
return err
}
msg.SetBodyString("text/html", bodyBuffer.String())
// attachments
attachments := email.Attachments
for _, attachment := range attachments {

View File

@@ -5,10 +5,10 @@ import (
"encoding/base64"
"fmt"
"html"
"html/template"
"io"
"math/rand"
"strings"
"text/template"
"time"
"github.com/go-errors/errors"
@@ -58,15 +58,13 @@ func (t *Template) CreateMail(
baseURL,
campaignRecipient.ID.MustGet().String(),
)
// #nosec
trackingPixelMarkup := template.HTML(trackingPixel)
return t.newTemplateDataMap(
idKey,
baseURL,
url,
campaignRecipient.Recipient,
trackingPixelPath,
trackingPixelMarkup,
trackingPixel,
email,
apiSender,
)
@@ -74,7 +72,6 @@ func (t *Template) CreateMail(
// ValidatePageTemplate validates that a page template can be parsed and executed without errors
func (t *Template) ValidatePageTemplate(content string) error {
// use the same parsing approach as CreatePhishingPage but without executing
_, err := template.New("validation").
Funcs(TemplateFuncs()).
Parse(content)
@@ -94,7 +91,6 @@ func (t *Template) ValidatePageTemplate(content string) error {
// ValidateEmailTemplate validates that an email template can be parsed and executed without errors
func (t *Template) ValidateEmailTemplate(content string) error {
// use the same parsing approach as email creation but without executing
_, err := template.New("validation").
Funcs(TemplateFuncs()).
Parse(content)
@@ -139,7 +135,6 @@ func (t *Template) ValidateEmailTemplate(content string) error {
// ValidateDomainTemplate validates that a domain template can be parsed and executed without errors
func (t *Template) ValidateDomainTemplate(content string) error {
// use the same parsing approach as domain content but without executing
_, err := template.New("validation").
Funcs(TemplateFuncs()).
Parse(content)
@@ -222,7 +217,6 @@ func (t *Template) CreateMailBody(
email,
apiSender,
)
// parse and execute the mail content
mailContentTemplate := template.New("mailContent")
mailContentTemplate = mailContentTemplate.Funcs(TemplateFuncs())
content, err := email.Content.Get()
@@ -293,14 +287,14 @@ func (t *Template) CreatePhishingPage(
return w, nil
}
// newTemplateDataMap creates a new data map for the templates
// newTemplateDataMap creates a new data map for templates
func (t *Template) newTemplateDataMap(
id string,
baseURL string,
url string,
recipient *model.Recipient,
trackingPixelPath string,
trackingPixelMarkup template.HTML,
trackingPixelMarkup string,
email *model.Email,
apiSender *model.APISender,
) *map[string]any {
@@ -386,6 +380,38 @@ func (t *Template) newTemplateDataMap(
return &m
}
// TemplateFuncs returns template functions for templates
func TemplateFuncs() template.FuncMap {
return template.FuncMap{
"urlEscape": func(s string) string {
return template.URLQueryEscaper(s)
},
"htmlEscape": func(s string) string {
return html.EscapeString(s)
},
"randInt": func(n1, n2 int) (int, error) {
if n1 > n2 {
return 0, fmt.Errorf("first number must be less than or equal to second number")
}
return rand.Intn(n2-n1+1) + n1, nil
},
"randAlpha": RandAlpha,
"qr": GenerateQRCode,
"date": func(format string, offsetSeconds ...int) string {
offset := 0
if len(offsetSeconds) > 0 {
offset = offsetSeconds[0]
}
targetTime := time.Now().Add(time.Duration(offset) * time.Second)
goFormat := convertDateFormat(format)
return targetTime.Format(goFormat)
},
"base64": func(s string) string {
return base64.StdEncoding.EncodeToString([]byte(s))
},
}
}
func (t *Template) AddTrackingPixel(content string) string {
if strings.Contains(content, trackingPixelTemplate) {
return content
@@ -505,39 +531,7 @@ func (t *Template) RemoveTrackingPixelFromContent(content string) string {
return strings.ReplaceAll(content, trackingPixelTemplate, "")
}
func TemplateFuncs() template.FuncMap {
return template.FuncMap{
"urlEscape": func(s string) string {
return template.URLQueryEscaper(s)
},
"htmlEscape": func(s string) string {
return html.EscapeString(s)
},
"randInt": func(n1, n2 int) (int, error) {
if n1 > n2 {
return 0, fmt.Errorf("first number must be less than or equal to second number")
}
// #nosec
return rand.Intn(n2-n1+1) + n1, nil
},
"randAlpha": RandAlpha,
"qr": GenerateQRCode,
"date": func(format string, offsetSeconds ...int) string {
offset := 0
if len(offsetSeconds) > 0 {
offset = offsetSeconds[0]
}
targetTime := time.Now().Add(time.Duration(offset) * time.Second)
goFormat := convertDateFormat(format)
return targetTime.Format(goFormat)
},
"base64": func(s string) string {
return base64.StdEncoding.EncodeToString([]byte(s))
},
}
}
func GenerateQRCode(args ...any) (template.HTML, error) {
func GenerateQRCode(args ...any) (string, error) {
if len(args) == 0 {
return "", errors.New("URL is required")
}
@@ -564,8 +558,7 @@ func GenerateQRCode(args ...any) (template.HTML, error) {
if err := qr.Save(writer); err != nil {
return "", err
}
// #nosec
return template.HTML(buf.String()), nil
return buf.String(), nil
}
const alphaChar = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"