package app import ( "fmt" "html/template" "os" "path/filepath" "strings" ) // WebTemplateManager handles HTML template management for web honeypots type WebTemplateManager struct { templateDir string templates map[string]*template.Template } // NewWebTemplateManager creates a new template manager func NewWebTemplateManager(configPath string) *WebTemplateManager { templateDir := filepath.Join(filepath.Dir(configPath), "webtemplates") // Ensure template directory exists os.MkdirAll(templateDir, 0755) return &WebTemplateManager{ templateDir: templateDir, templates: make(map[string]*template.Template), } } // GetTemplateDir returns the template directory path func (wtm *WebTemplateManager) GetTemplateDir() string { return wtm.templateDir } // CreateDefaultTemplate creates a default login template if it doesn't exist func (wtm *WebTemplateManager) CreateDefaultTemplate(templateName string) error { templatePath := filepath.Join(wtm.templateDir, templateName) // Check if template already exists if _, err := os.Stat(templatePath); err == nil { return nil // Template already exists } defaultHTML := ` Login - {{ .ServiceName }}

{{ .ServiceName }}

Please sign in to continue

Invalid username or password
` return os.WriteFile(templatePath, []byte(defaultHTML), 0644) } // LoadTemplate loads and parses a template file func (wtm *WebTemplateManager) LoadTemplate(templateName string) (*template.Template, error) { // Check if template is already loaded if tmpl, exists := wtm.templates[templateName]; exists { return tmpl, nil } templatePath := filepath.Join(wtm.templateDir, templateName) // Create default template if it doesn't exist if _, err := os.Stat(templatePath); os.IsNotExist(err) { if err := wtm.CreateDefaultTemplate(templateName); err != nil { return nil, fmt.Errorf("failed to create default template: %w", err) } } // Parse template tmpl, err := template.ParseFiles(templatePath) if err != nil { return nil, fmt.Errorf("failed to parse template %s: %w", templateName, err) } // Cache template wtm.templates[templateName] = tmpl return tmpl, nil } // SaveTemplate saves template content to file func (wtm *WebTemplateManager) SaveTemplate(templateName, content string) error { templatePath := filepath.Join(wtm.templateDir, templateName) // Validate template by parsing it _, err := template.New("test").Parse(content) if err != nil { return fmt.Errorf("invalid template syntax: %w", err) } // Save to file if err := os.WriteFile(templatePath, []byte(content), 0644); err != nil { return fmt.Errorf("failed to save template: %w", err) } // Remove from cache to force reload delete(wtm.templates, templateName) return nil } // GetTemplate returns template content as string func (wtm *WebTemplateManager) GetTemplate(templateName string) (string, error) { templatePath := filepath.Join(wtm.templateDir, templateName) content, err := os.ReadFile(templatePath) if err != nil { // If template doesn't exist, create default and return it if os.IsNotExist(err) { if err := wtm.CreateDefaultTemplate(templateName); err != nil { return "", fmt.Errorf("failed to create default template: %w", err) } content, err = os.ReadFile(templatePath) if err != nil { return "", fmt.Errorf("failed to read created template: %w", err) } } else { return "", fmt.Errorf("failed to read template: %w", err) } } return string(content), nil } // ListTemplates returns a list of available templates func (wtm *WebTemplateManager) ListTemplates() ([]string, error) { files, err := os.ReadDir(wtm.templateDir) if err != nil { return nil, fmt.Errorf("failed to read template directory: %w", err) } var templates []string for _, file := range files { if !file.IsDir() && strings.HasSuffix(file.Name(), ".html") { templates = append(templates, file.Name()) } } return templates, nil } // DeleteTemplate removes a template file func (wtm *WebTemplateManager) DeleteTemplate(templateName string) error { templatePath := filepath.Join(wtm.templateDir, templateName) if err := os.Remove(templatePath); err != nil { return fmt.Errorf("failed to delete template: %w", err) } // Remove from cache delete(wtm.templates, templateName) return nil } // ValidateTemplate checks if template has required fields func (wtm *WebTemplateManager) ValidateTemplate(content string) error { // Check for required form fields requiredFields := []string{ `name="username"`, `name="password"`, `method="POST"` + ` ` + `action=`, // Split to avoid matching this comment } contentLower := strings.ToLower(content) for _, field := range requiredFields { if !strings.Contains(contentLower, strings.ToLower(field)) { return fmt.Errorf("template missing required field: %s", field) } } // Try to parse as template _, err := template.New("validation").Parse(content) if err != nil { return fmt.Errorf("invalid template syntax: %w", err) } return nil }