Files
QSfera/Server/vendor/github.com/go-ldap/ldap/v3/postaladdress.go
T
Курнат Андрей 2315f25754 Initial QSfera import
2026-06-07 10:20:04 +03:00

131 lines
3.2 KiB
Go

package ldap
import (
"errors"
"fmt"
"strings"
)
var ErrEmptyPostalAddress = errors.New("ldap: postal address cannot be empty")
// PostalAddress represents an RFC 4517 Postal Address
// A postal address is a sequence of strings of one or more arbitrary UCS
// characters, which form the lines of the address.
type PostalAddress struct {
lines []string
}
// NewPostalAddress creates a new PostalAddress by copying non-empty lines from the provided slice of strings.
func NewPostalAddress(lines []string) (*PostalAddress, error) {
copiedLines := make([]string, 0, len(lines))
for _, line := range lines {
if line == "" {
continue
}
copiedLines = append(copiedLines, line)
}
if len(copiedLines) == 0 {
return nil, ErrEmptyPostalAddress
}
return &PostalAddress{lines: copiedLines}, nil
}
// Lines returns a copy of the address lines as a slice of strings.
func (p *PostalAddress) Lines() []string {
copiedLines := make([]string, len(p.lines))
copy(copiedLines, p.lines)
return copiedLines
}
// String returns the postal address as a single string, with lines joined by newline characters.
func (p *PostalAddress) String() string {
return strings.Join(p.lines, "\n")
}
// Escape encodes special characters in the PostalAddress lines as per RFC 4517 and appends a `$` at the end of each line.
func (p *PostalAddress) Escape() string {
builder := &strings.Builder{}
for _, line := range p.lines {
for _, char := range line {
switch char {
case '\\':
builder.WriteString("\\5C")
case '$':
builder.WriteString("\\24")
default:
builder.WriteRune(char)
}
}
builder.WriteRune('$')
}
return builder.String()
}
// ParsePostalAddress parses an RFC 4517 escaped postal address string into a PostalAddress object or returns an error.
func ParsePostalAddress(escaped string) (*PostalAddress, error) {
lines := strings.Split(escaped, "$")
parsedLines := make([]string, 0, len(lines))
const totalEscapeLen = 3
for _, line := range lines {
if line == "" {
// Skip empty lines
continue
}
builder := &strings.Builder{}
for i := 0; i < len(line); i++ {
char := line[i]
if char == '\\' && i+totalEscapeLen <= len(line) {
escapeSeq := line[i+1 : i+totalEscapeLen]
switch escapeSeq {
case "5C", "5c":
builder.WriteRune('\\')
i += 2
case "24":
builder.WriteRune('$')
i += 2
default:
return nil, fmt.Errorf("invalid escape sequence: \\%s at position %d", escapeSeq, i)
}
} else if char == '\\' {
return nil, fmt.Errorf("incomplete escape sequence at position %d", i)
} else {
builder.WriteByte(char)
}
}
parsedLines = append(parsedLines, builder.String())
}
if len(parsedLines) == 0 {
return nil, ErrEmptyPostalAddress
}
return &PostalAddress{lines: parsedLines}, nil
}
// Equal compares the current PostalAddress with another PostalAddress and returns true if they are identical.
func (p *PostalAddress) Equal(other *PostalAddress) bool {
if p == other {
return true
}
if p == nil || other == nil {
return false
}
if len(p.lines) != len(other.lines) {
return false
}
for i := range p.lines {
if p.lines[i] != other.lines[i] {
return false
}
}
return true
}