/* * Amsterdam Web Communities System * Copyright (c) 2025 Erbosoft Metaverse Design Solutions, All Rights Reserved * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. * * SPDX-License-Identifier: MPL-2.0 */ // The htmlcheck package contains the HTML Checker. package htmlcheck import ( "context" "net/url" "regexp" "strings" ) // urlElement is a basic element type urlElement struct { re *regexp.Regexp prefix string } // eval matches the argument against our regular expression and adds an optional prefix. func (e *urlElement) eval(s string) string { if e.re.FindString(s) == "" { return "" } return e.prefix + s } // urlSetupData contains the data needed to set up the URL rewriter elements. var urlSetupData = [...]string{ `^(?i:http)://[A-Za-z0-9_-]+(\.[A-Za-z0-9_-]+)+.*$`, "", `^(?i:https)://[A-Za-z0-9_-]+(\.[A-Za-z0-9_-]+)+.*$`, "", `^(?i:ftp)://[A-Za-z0-9_-]+(\.[A-Za-z0-9_-]+)+.*$`, "", `^(?i:gopher)://[A-Za-z0-9_-]+(\.[A-Za-z0-9_-]+)+.*$`, "", "^(?i:mailto):[A-Za-z0-9!#$%*+-/=?^_`{|}~.]+@[A-Za-z0-9_-]+(\\.[A-Za-z0-9_-]+)+$", "", `^(?i:news):[A-Za-z0-9_-]+(\.[A-Za-z0-9_-]+)+$`, "", `^(?i:nntp)://[A-Za-z0-9_-]+(\.[A-Za-z0-9_-]+)+.*$`, "", `^(?i:telnet)://[A-Za-z0-9_-]+(\.[A-Za-z0-9_-]+)+.*$`, "", `^(?i:tn3270)://[A-Za-z0-9_-]+(\.[A-Za-z0-9_-]+)+.*$`, "", `^(?i:www)\.[A-Za-z0-9_-]+(\.[A-Za-z0-9_-]+)*.*$`, "http://", `^(?i:ftp)\.[A-Za-z0-9_-]+(\.[A-Za-z0-9_-]+)*.*$`, "ftp://", `^(?i:gopher)\.[A-Za-z0-9_-]+(\.[A-Za-z0-9_-]+)*.*$`, "gopher://", } // The URL elements we can match against. var urlElements []urlElement // init builds the URL elements and registers the rewriter. func init() { urlElements = make([]urlElement, len(urlSetupData)/2) i, j := 0, 0 for i < len(urlSetupData) { urlElements[j].re = regexp.MustCompile(urlSetupData[i]) urlElements[j].prefix = urlSetupData[i+1] i += 2 j++ } r := urlRewriter{} rewriterRegistry[r.Name()] = &r } // urlRewriter is an implementation of Rewriter that recognizes URLs. type urlRewriter struct{} // Name returns the rewriter's name. func (rw *urlRewriter) Name() string { return "url" } /* Rewrite rewrites the given string data and adds markup before and after if needed. * Parameters: * ctx - Standard Go context value. * data - The data to be rewritten. * svc - Services interface we can use. * Returns: * Pointer to markup data, or nil. */ func (rw *urlRewriter) Rewrite(ctx context.Context, data string, svc rewriterServices) *markupData { for _, ue := range urlElements { s := ue.eval(data) if s != "" { ls := strings.ToLower(s) if strings.HasPrefix(ls, "http:") || strings.HasPrefix(ls, "https:") { url, err := url.Parse(s) if err == nil { svc.addExternalRef(url) } } var openA strings.Builder openA.WriteString("") return &markupData{ beginMarkup: openA.String(), text: data, endMarkup: "", rescan: false, } } } return nil }