-
Notifications
You must be signed in to change notification settings - Fork 4
/
entry.go
116 lines (103 loc) · 3.46 KB
/
entry.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
// Copyright (c) Jim Lambert
// SPDX-License-Identifier: MIT
package gldap
import (
"fmt"
"os"
"sort"
"strings"
ber "github.com/go-asn1-ber/asn1-ber"
)
// Entry represents an ldap entry
type Entry struct {
// DN is the distinguished name of the entry
DN string
// Attributes are the returned attributes for the entry
Attributes []*EntryAttribute
}
// GetAttributeValues returns the values for the named attribute, or an empty list
func (e *Entry) GetAttributeValues(attribute string) []string {
for _, attr := range e.Attributes {
if attr.Name == attribute {
return attr.Values
}
}
return []string{}
}
// NewEntry returns an Entry object with the specified distinguished name and attribute key-value pairs.
// The map of attributes is accessed in alphabetical order of the keys in order to ensure that, for the
// same input map of attributes, the output entry will contain the same order of attributes
func NewEntry(dn string, attributes map[string][]string) *Entry {
var attributeNames []string
for attributeName := range attributes {
attributeNames = append(attributeNames, attributeName)
}
sort.Strings(attributeNames)
var encodedAttributes []*EntryAttribute
for _, attributeName := range attributeNames {
encodedAttributes = append(encodedAttributes, NewEntryAttribute(attributeName, attributes[attributeName]))
}
return &Entry{
DN: dn,
Attributes: encodedAttributes,
}
}
// PrettyPrint outputs a human-readable description indenting. Supported
// options: WithWriter
func (e *Entry) PrettyPrint(indent int, opt ...Option) {
opts := getGeneralOpts(opt...)
if opts.withWriter == nil {
opts.withWriter = os.Stdout
}
fmt.Fprintf(opts.withWriter, "%sDN: %s\n", strings.Repeat(" ", indent), e.DN)
for _, attr := range e.Attributes {
attr.PrettyPrint(indent+2, opt...)
}
}
// PrettyPrint outputs a human-readable description with indenting. Supported
// options: WithWriter
func (e *EntryAttribute) PrettyPrint(indent int, opt ...Option) {
opts := getGeneralOpts(opt...)
if opts.withWriter == nil {
opts.withWriter = os.Stdout
}
fmt.Fprintf(opts.withWriter, "%s%s: %s\n", strings.Repeat(" ", indent), e.Name, e.Values)
}
// EntryAttribute holds a single attribute
type EntryAttribute struct {
// Name is the name of the attribute
Name string
// Values contain the string values of the attribute
Values []string
// ByteValues contain the raw values of the attribute
ByteValues [][]byte
}
// NewEntryAttribute returns a new EntryAttribute with the desired key-value pair
func NewEntryAttribute(name string, values []string) *EntryAttribute {
var bytes [][]byte
for _, value := range values {
bytes = append(bytes, []byte(value))
}
return &EntryAttribute{
Name: name,
Values: values,
ByteValues: bytes,
}
}
// AddValue to an existing EntryAttribute
func (e *EntryAttribute) AddValue(value ...string) {
for _, v := range value {
e.ByteValues = append(e.ByteValues, []byte(v))
e.Values = append(e.Values, v)
}
}
func (e *EntryAttribute) encode() *ber.Packet {
seq := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Attribute")
seq.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, e.Name, "Type"))
set := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSet, nil, "AttributeValue")
for _, value := range e.Values {
set.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, value, "Vals"))
}
seq.AppendChild(set)
return seq
}