| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647 |
- package common
- import (
- "errors"
- "net/url"
- "strings"
- )
- // EnsureURLScheme prepends https:// to a URL that carries no scheme, so
- // subscription apps and browsers don't resolve it relative to the panel's own
- // domain (e.g. "t.me/support" turning into "https://panel.example/t.me/support").
- // Values with an explicit scheme (https://, tg://, mailto:, tel:) and empty
- // strings pass through untouched.
- func EnsureURLScheme(raw string) string {
- trimmed := strings.TrimSpace(raw)
- if trimmed == "" {
- return ""
- }
- if strings.Contains(trimmed, "://") ||
- strings.HasPrefix(trimmed, "mailto:") ||
- strings.HasPrefix(trimmed, "tel:") {
- return trimmed
- }
- return "https://" + trimmed
- }
- // ParseRemoteRoutingURL classifies a routing settings value: one single-line
- // absolute HTTPS URL is a remote source (canonicalized); anything else is inline.
- func ParseRemoteRoutingURL(raw string) (string, bool, error) {
- trimmed := strings.TrimSpace(raw)
- if trimmed == "" || strings.ContainsAny(trimmed, "\r\n") {
- return "", false, nil
- }
- if !strings.HasPrefix(strings.ToLower(trimmed), "https://") {
- return "", false, nil
- }
- u, err := url.Parse(trimmed)
- if err != nil || u.Host == "" || u.Hostname() == "" {
- return "", true, errors.New("must be an absolute HTTPS URL")
- }
- if u.User != nil {
- return "", true, errors.New("must not contain URL credentials")
- }
- u.Scheme = "https"
- u.Fragment = ""
- return u.String(), true, nil
- }
|