Initial QSfera import

This commit is contained in:
Курнат Андрей
2026-06-07 10:20:04 +03:00
commit 2315f25754
16485 changed files with 4826827 additions and 0 deletions
+24
View File
@@ -0,0 +1,24 @@
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so
# Folders
_obj
_test
# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out
*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*
_testmain.go
*.exe
*.test
*.prof
+22
View File
@@ -0,0 +1,22 @@
language: go
go:
- 1.11
- 1.13
- 1.14
- tip
matrix:
fast_finish: true
allow_failures:
- go: tip
go_import_path: github.com/go-ldap/ldif
install:
- go get github.com/go-ldap/ldap/v3
- go get code.google.com/p/go.tools/cmd/cover || go get golang.org/x/tools/cmd/cover
- go get golang.org/x/lint/golint || true
- go install golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow
- go build -v ./...
script:
- make test
- make fmt
- make vet
- if [ "${TRAVIS_GO_VERSION}" != "1.6" ]; then make lint; fi
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2016 go-ldap Authors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+41
View File
@@ -0,0 +1,41 @@
.PHONY: default install build test quicktest fmt vet lint
default: fmt vet lint build quicktest
install:
go get -t -v ./...
build:
go build -v ./...
test:
go test -v -cover ./...
quicktest:
go test ./...
# Capture output and force failure when there is non-empty output
fmt:
@echo gofmt -l .
@OUTPUT=`gofmt -l . 2>&1`; \
if [ "$$OUTPUT" ]; then \
echo "gofmt must be run on the following files:"; \
echo "$$OUTPUT"; \
exit 1; \
fi
# Only run on go1.5+
vet:
go vet -vettool=$(which shadow) -atomic -bool -copylocks -nilfunc -printf -rangeloops -unreachable -unsafeptr -unusedresult .
# https://github.com/golang/lint
# go get github.com/golang/lint/golint
# Capture output and force failure when there is non-empty output
lint:
@echo golint ./...
@OUTPUT=`golint ./... 2>&1`; \
if [ "$$OUTPUT" ]; then \
echo "golint errors:"; \
echo "$$OUTPUT"; \
exit 1; \
fi
+20
View File
@@ -0,0 +1,20 @@
# ldif
Utilities for working with ldif data. This implements most of RFC 2849.
## Change Entries
Support for moddn / modrdn changes is missing (in Unmarshal and
Marshal) - github.com/go-ldap/ldap/v3 does not support it currently
## Controls
Only simple controls without control value are supported, currently
just
Manage DSA IT - oid: 2.16.840.1.113730.3.4.2
## URLs
URL schemes in an LDIF like
jpegPhoto;binary:< file:///usr/share/photos/someone.jpg
are only supported for the "file" scheme like in the example above
+57
View File
@@ -0,0 +1,57 @@
package ldif
import (
"fmt"
"log"
"github.com/go-ldap/ldap/v3"
)
// Apply sends the LDIF entries to the server and does the changes as
// given by the entries.
//
// All *ldap.Entry are converted to an *ldap.AddRequest.
//
// By default, it returns on the first error. To continue with applying the
// LDIF, set the continueOnErr argument to true - in this case the errors
// are logged with log.Printf()
func (l *LDIF) Apply(conn ldap.Client, continueOnErr bool) error {
for _, entry := range l.Entries {
switch {
case entry.Entry != nil:
add := ldap.NewAddRequest(entry.Entry.DN, entry.Add.Controls)
for _, attr := range entry.Entry.Attributes {
add.Attribute(attr.Name, attr.Values)
}
entry.Add = add
fallthrough
case entry.Add != nil:
if err := conn.Add(entry.Add); err != nil {
if continueOnErr {
log.Printf("ERROR: Failed to add %s: %s", entry.Add.DN, err)
continue
}
return fmt.Errorf("failed to add %s: %s", entry.Add.DN, err)
}
case entry.Del != nil:
if err := conn.Del(entry.Del); err != nil {
if continueOnErr {
log.Printf("ERROR: Failed to delete %s: %s", entry.Del.DN, err)
continue
}
return fmt.Errorf("failed to delete %s: %s", entry.Del.DN, err)
}
case entry.Modify != nil:
if err := conn.Modify(entry.Modify); err != nil {
if continueOnErr {
log.Printf("ERROR: Failed to modify %s: %s", entry.Modify.DN, err)
continue
}
return fmt.Errorf("failed to modify %s: %s", entry.Modify.DN, err)
}
}
}
return nil
}
+2
View File
@@ -0,0 +1,2 @@
// Package ldif contains utilities for working with ldif data
package ldif
+534
View File
@@ -0,0 +1,534 @@
// Package ldif contains an LDIF parser and marshaller (RFC 2849).
package ldif
import (
"bufio"
"bytes"
"encoding/base64"
"errors"
"fmt"
"io"
"io/ioutil"
"net/url"
"strconv"
"strings"
"github.com/go-ldap/ldap/v3"
)
// Entry is one entry in the LDIF
type Entry struct {
Entry *ldap.Entry
Add *ldap.AddRequest
Del *ldap.DelRequest
Modify *ldap.ModifyRequest
}
// The LDIF struct is used for parsing an LDIF. The Controls
// is used to tell the parser to ignore any controls found
// when parsing (default: false to ignore the controls).
// FoldWidth is used for the line lenght when marshalling.
type LDIF struct {
Entries []*Entry
Version int
changeType string
FoldWidth int
Controls bool
firstEntry bool
}
// The ParseError holds the error message and the line in the ldif
// where the error occurred.
type ParseError struct {
Line int
Message string
}
// Error implements the error interface
func (e *ParseError) Error() string {
return fmt.Sprintf("Error in line %d: %s", e.Line, e.Message)
}
var cr byte = '\x0D'
var lf byte = '\x0A'
var sep = string([]byte{cr, lf})
var comment byte = '#'
var space byte = ' '
var spaces = string(space)
// Parse wraps Unmarshal to parse an LDIF from a string
func Parse(str string) (l *LDIF, err error) {
buf := bytes.NewBuffer([]byte(str))
l = &LDIF{}
err = Unmarshal(buf, l)
return
}
// ParseWithControls wraps Unmarshal to parse an LDIF from
// a string, controls are added to change records
func ParseWithControls(str string) (l *LDIF, err error) {
buf := bytes.NewBuffer([]byte(str))
l = &LDIF{Controls: true}
err = Unmarshal(buf, l)
return
}
// Unmarshal parses the LDIF from the given io.Reader into the LDIF struct.
// The caller is responsible for closing the io.Reader if that is
// needed.
func Unmarshal(r io.Reader, l *LDIF) (err error) {
if r == nil {
return &ParseError{Line: 0, Message: "No reader present"}
}
curLine := 0
l.Version = 0
l.changeType = ""
isComment := false
reader := bufio.NewReader(r)
var lines []string
var line, nextLine string
l.firstEntry = true
for {
curLine++
nextLine, err = reader.ReadString(lf)
nextLine = strings.TrimRight(nextLine, sep)
switch err {
case nil, io.EOF:
switch len(nextLine) {
case 0:
if len(line) == 0 && err == io.EOF {
return nil
}
if len(line) == 0 && len(lines) == 0 {
continue
}
lines = append(lines, line)
entry, perr := l.parseEntry(lines)
if perr != nil {
return &ParseError{Line: curLine, Message: perr.Error()}
}
l.Entries = append(l.Entries, entry)
line = ""
lines = []string{}
if err == io.EOF {
return nil
}
default:
switch nextLine[0] {
case comment:
isComment = true
continue
case space:
if isComment {
continue
}
line += nextLine[1:]
continue
default:
isComment = false
if len(line) != 0 {
lines = append(lines, line)
}
line = nextLine
continue
}
}
default:
return &ParseError{Line: curLine, Message: err.Error()}
}
}
}
func (l *LDIF) parseEntry(lines []string) (entry *Entry, err error) {
if len(lines) == 0 {
return nil, errors.New("empty entry?")
}
if l.firstEntry && strings.HasPrefix(lines[0], "version:") {
l.firstEntry = false
line := strings.TrimLeft(lines[0][8:], spaces)
if l.Version, err = strconv.Atoi(line); err != nil {
return nil, err
}
if l.Version != 1 {
return nil, errors.New("Invalid version spec " + string(line))
}
l.Version = 1
if len(lines) == 1 {
return nil, nil
}
lines = lines[1:]
}
l.firstEntry = false
if len(lines) == 0 {
return nil, nil
}
if !strings.HasPrefix(lines[0], "dn:") {
return nil, errors.New("missing 'dn:'")
}
_, val, err := l.parseLine(lines[0])
if err != nil {
return nil, err
}
dn := val
if len(lines) == 1 {
return nil, errors.New("only a dn: line")
}
lines = lines[1:]
var controls []ldap.Control
controls, lines, err = l.parseControls(lines)
if err != nil {
return nil, err
}
if strings.HasPrefix(lines[0], "changetype:") {
_, val, err := l.parseLine(lines[0])
if err != nil {
return nil, err
}
l.changeType = val
if len(lines) > 1 {
lines = lines[1:]
}
}
switch l.changeType {
case "":
if len(controls) != 0 {
return nil, errors.New("controls found without changetype")
}
attrs, err := l.parseAttrs(lines)
if err != nil {
return nil, err
}
return &Entry{Entry: ldap.NewEntry(dn, attrs)}, nil
case "add":
attrs, err := l.parseAttrs(lines)
if err != nil {
return nil, err
}
// FIXME: controls for add - see https://github.com/go-ldap/ldap/issues/81
add := ldap.NewAddRequest(dn, controls)
for attr, vals := range attrs {
add.Attribute(attr, vals)
}
return &Entry{Add: add}, nil
case "delete":
if len(lines) > 1 {
return nil, errors.New("no attributes allowed for changetype delete")
}
return &Entry{Del: ldap.NewDelRequest(dn, controls)}, nil
case "modify":
// FIXME: controls for modify - see https://github.com/go-ldap/ldap/issues/81
mod := ldap.NewModifyRequest(dn, controls)
var op, attribute string
var values []string
if lines[len(lines)-1] != "-" {
return nil, errors.New("modify request does not close with a single dash")
}
for i := 0; i < len(lines); i++ {
if lines[i] == "-" {
switch op {
case "":
return nil, fmt.Errorf("empty operation")
case "add":
mod.Add(attribute, values)
op = ""
attribute = ""
values = nil
case "replace":
mod.Replace(attribute, values)
op = ""
attribute = ""
values = nil
case "delete":
mod.Delete(attribute, values)
op = ""
attribute = ""
values = nil
default:
return nil, fmt.Errorf("invalid operation %s in modify request", op)
}
continue
}
attr, val, err := l.parseLine(lines[i])
if err != nil {
return nil, err
}
if op == "" {
op = attr
attribute = val
} else {
if attr != attribute {
return nil, fmt.Errorf("invalid attribute %s in %s request for %s", attr, op, attribute)
}
values = append(values, val)
}
}
return &Entry{Modify: mod}, nil
case "moddn", "modrdn":
return nil, fmt.Errorf("unsupported changetype %s", l.changeType)
default:
return nil, fmt.Errorf("invalid changetype %s", l.changeType)
}
}
func (l *LDIF) parseAttrs(lines []string) (map[string][]string, error) {
attrs := make(map[string][]string)
for i := 0; i < len(lines); i++ {
attr, val, err := l.parseLine(lines[i])
if err != nil {
return nil, err
}
attrs[attr] = append(attrs[attr], val)
}
return attrs, nil
}
func (l *LDIF) parseLine(line string) (attr, val string, err error) {
off := 0
for len(line) > off && line[off] != ':' {
off++
if off >= len(line) {
err = fmt.Errorf("Missing : in line `%s`", line)
return
}
}
if off == len(line) {
err = fmt.Errorf("Missing : in the line `%s`", line)
return
}
if off > len(line)-2 {
err = errors.New("empty value")
// FIXME: this is allowed for some attributes, e.g. seeAlso
return
}
attr = line[0:off]
if err = validAttr(attr); err != nil {
attr = ""
val = ""
return
}
switch line[off+1] {
case ':':
val, err = decodeBase64(strings.TrimLeft(line[off+2:], spaces))
if err != nil {
return
}
case '<':
val, err = readURLValue(strings.TrimLeft(line[off+2:], spaces))
if err != nil {
return
}
default:
val = strings.TrimLeft(line[off+1:], spaces)
}
return
}
func (l *LDIF) parseControls(lines []string) ([]ldap.Control, []string, error) {
var controls []ldap.Control
for {
if !strings.HasPrefix(lines[0], "control:") {
break
}
if !l.Controls {
if len(lines) == 1 {
return nil, nil, errors.New("only controls found")
}
lines = lines[1:]
continue
}
_, val, err := l.parseLine(lines[0])
if err != nil {
return nil, nil, err
}
var oid, ctrlValue string
criticality := false
parts := strings.SplitN(val, " ", 3)
if err = validOID(parts[0]); err != nil {
return nil, nil, fmt.Errorf("%s is not a valid oid: %s", oid, err)
}
oid = parts[0]
if len(parts) > 1 {
switch parts[1] {
case "true":
criticality = true
if len(parts) > 2 {
parts[1] = parts[2]
parts = parts[0:2]
}
case "false":
criticality = false
if len(parts) > 2 {
parts[1] = parts[2]
parts = parts[0:2]
}
}
}
if len(parts) == 2 {
ctrlValue = parts[1]
}
if ctrlValue == "" {
switch oid {
case ldap.ControlTypeManageDsaIT:
controls = append(controls, &ldap.ControlManageDsaIT{Criticality: criticality})
default:
return nil, nil, fmt.Errorf("unsupported control found: %s", oid)
}
} else {
switch ctrlValue[0] { // where is this documented?
case ':':
if len(ctrlValue) == 1 {
return nil, nil, errors.New("missing value for base64 encoded control value")
}
ctrlValue, err = decodeBase64(strings.TrimLeft(ctrlValue[1:], spaces))
if err != nil {
return nil, nil, err
}
if ctrlValue == "" {
return nil, nil, errors.New("base64 decoded to empty value")
}
case '<':
if len(ctrlValue) == 1 {
return nil, nil, errors.New("missing value for url control value")
}
ctrlValue, err = readURLValue(strings.TrimLeft(ctrlValue[1:], spaces))
if err != nil {
return nil, nil, err
}
if ctrlValue == "" {
return nil, nil, errors.New("url resolved to an empty value")
}
}
// TODO:
// convert ctrlValue to *ber.Packet and decode with something like
// ctrl := ldap.DecodeControl()
// ... FIXME: the controls need a Decode() interface
// so we can just do a
// ctrl := ldap.ControlByOID(oid) // returns an empty &ControlSomething{}
// ctrl.Decode((*ber.Packet)(ctrlValue))
// ctrl.Criticality = criticality
// that should be usable in github.com/go-ldap/ldap/control.go also
// to decode the incoming control
// controls = append(controls, ctrl)
return nil, nil, fmt.Errorf("controls with values are not supported, oid: %s", oid)
}
if len(lines) == 1 {
return nil, nil, errors.New("only controls found")
}
lines = lines[1:]
}
return controls, lines, nil
}
func readURLValue(val string) (string, error) {
u, err := url.Parse(val)
if err != nil {
return "", fmt.Errorf("failed to parse URL: %s", err)
}
if u.Scheme != "file" {
return "", fmt.Errorf("unsupported URL scheme %s", u.Scheme)
}
data, err := ioutil.ReadFile(toPath(u))
if err != nil {
return "", fmt.Errorf("failed to read %s: %s", u.Path, err)
}
val = string(data) // FIXME: safe?
return val, nil
}
func decodeBase64(enc string) (string, error) {
dec := make([]byte, base64.StdEncoding.DecodedLen(len([]byte(enc))))
n, err := base64.StdEncoding.Decode(dec, []byte(enc))
if err != nil {
return "", err
}
return string(dec[:n]), nil
}
func validOID(oid string) error {
lastDot := true
for _, c := range oid {
switch {
case c == '.' && lastDot:
return errors.New("OID with at least 2 consecutive dots")
case c == '.':
lastDot = true
case c >= '0' && c <= '9':
lastDot = false
default:
return errors.New("Invalid character in OID")
}
}
return nil
}
func validAttr(attr string) error {
if len(attr) == 0 {
return errors.New("empty attribute name")
}
switch {
case attr[0] >= 'A' && attr[0] <= 'Z':
// A-Z
case attr[0] >= 'a' && attr[0] <= 'z':
// a-z
default:
if attr[0] >= '0' && attr[0] <= '9' {
return validOID(attr)
}
return errors.New("invalid first character in attribute")
}
for i := 1; i < len(attr); i++ {
c := attr[i]
switch {
case c >= '0' && c <= '9':
case c >= 'A' && c <= 'Z':
case c >= 'a' && c <= 'z':
case c == '-':
case c == ';':
default:
return errors.New("invalid character in attribute name")
}
}
return nil
}
// AllEntries returns all *ldap.Entries in the LDIF
func (l *LDIF) AllEntries() (entries []*ldap.Entry) {
for _, entry := range l.Entries {
if entry.Entry != nil {
entries = append(entries, entry.Entry)
}
}
return entries
}
+247
View File
@@ -0,0 +1,247 @@
package ldif
import (
"encoding/base64"
"errors"
"fmt"
"io"
"github.com/go-ldap/ldap/v3"
)
var foldWidth = 76
// ErrMixed is the error, that we cannot mix change records and content
// records in one LDIF
var ErrMixed = errors.New("cannot mix change records and content records")
// Marshal returns an LDIF string from the given LDIF.
//
// The default line lenght is 76 characters. This can be changed by setting
// the fw parameter to something else than 0.
// For a fold width < 0, no folding will be done, with 0, the default is used.
func Marshal(l *LDIF) (data string, err error) {
hasEntry := false
hasChange := false
if l.Version > 0 {
data = "version: 1\n"
}
fw := l.FoldWidth
if fw == 0 {
fw = foldWidth
}
for _, e := range l.Entries {
switch {
case e.Add != nil:
hasChange = true
if hasEntry {
return "", ErrMixed
}
data += foldLine("dn: "+e.Add.DN, fw) + "\n"
data += "changetype: add\n"
for _, add := range e.Add.Attributes {
if len(add.Vals) == 0 {
return "", errors.New("changetype 'add' requires non empty value list")
}
for _, v := range add.Vals {
ev, t := encodeValue(v)
col := ": "
if t {
col = ":: "
}
data += foldLine(add.Type+col+ev, fw) + "\n"
}
}
case e.Del != nil:
hasChange = true
if hasEntry {
return "", ErrMixed
}
data += foldLine("dn: "+e.Del.DN, fw) + "\n"
data += "changetype: delete\n"
case e.Modify != nil:
hasChange = true
if hasEntry {
return "", ErrMixed
}
data += foldLine("dn: "+e.Modify.DN, fw) + "\n"
data += "changetype: modify\n"
for _, mod := range e.Modify.Changes {
switch mod.Operation {
// add operation - https://tools.ietf.org/html/rfc4511#section-4.6
case 0:
if len(mod.Modification.Vals) == 0 {
return "", errors.New("changetype 'modify', op 'add' requires non empty value list")
}
data += "add: " + mod.Modification.Type + "\n"
for _, v := range mod.Modification.Vals {
ev, t := encodeValue(v)
col := ": "
if t {
col = ":: "
}
data += foldLine(mod.Modification.Type+col+ev, fw) + "\n"
}
data += "-\n"
// delete operation - https://tools.ietf.org/html/rfc4511#section-4.6
case 1:
data += "delete: " + mod.Modification.Type + "\n"
for _, v := range mod.Modification.Vals {
ev, t := encodeValue(v)
col := ": "
if t {
col = ":: "
}
data += foldLine(mod.Modification.Type+col+ev, fw) + "\n"
}
data += "-\n"
// replace operation - https://tools.ietf.org/html/rfc4511#section-4.6
case 2:
if len(mod.Modification.Vals) == 0 {
return "", errors.New("changetype 'modify', op 'replace' requires non empty value list")
}
data += "replace: " + mod.Modification.Type + "\n"
for _, v := range mod.Modification.Vals {
ev, t := encodeValue(v)
col := ": "
if t {
col = ":: "
}
data += foldLine(mod.Modification.Type+col+ev, fw) + "\n"
}
data += "-\n"
default:
return "", fmt.Errorf("invalid type %s in modify request", mod.Modification.Type)
}
}
default:
hasEntry = true
if hasChange {
return "", ErrMixed
}
data += foldLine("dn: "+e.Entry.DN, fw) + "\n"
for _, av := range e.Entry.Attributes {
for _, v := range av.Values {
ev, t := encodeValue(v)
col := ": "
if t {
col = ":: "
}
data += foldLine(av.Name+col+ev, fw) + "\n"
}
}
}
data += "\n"
}
return data, nil
}
func encodeValue(value string) (string, bool) {
required := false
for _, r := range value {
if r < ' ' || r > '~' { // ~ = 0x7E, <DEL> = 0x7F
required = true
break
}
}
if !required {
return value, false
}
return base64.StdEncoding.EncodeToString([]byte(value)), true
}
func foldLine(line string, fw int) (folded string) {
if fw < 0 {
return line
}
if len(line) <= fw {
return line
}
folded = line[:fw] + "\n"
line = line[fw:]
for len(line) > fw-1 {
folded += " " + line[:fw-1] + "\n"
line = line[fw-1:]
}
if len(line) > 0 {
folded += " " + line
}
return
}
// Dump writes the given entries to the io.Writer.
//
// The entries argument can be *ldap.Entry or a mix of *ldap.AddRequest,
// *ldap.DelRequest, *ldap.ModifyRequest and *ldap.ModifyDNRequest or slices
// of any of those.
//
// See Marshal() for the fw argument.
func Dump(fh io.Writer, fw int, entries ...interface{}) error {
l, err := ToLDIF(entries...)
if err != nil {
return err
}
l.FoldWidth = fw
str, err := Marshal(l)
if err != nil {
return err
}
_, err = fh.Write([]byte(str))
return err
}
// ToLDIF puts the given arguments in an LDIF struct and returns it.
//
// The entries argument can be *ldap.Entry or a mix of *ldap.AddRequest,
// *ldap.DelRequest, *ldap.ModifyRequest and *ldap.ModifyDNRequest or slices
// of any of those.
func ToLDIF(entries ...interface{}) (*LDIF, error) {
l := &LDIF{}
for _, e := range entries {
switch e.(type) {
case []*ldap.Entry:
for _, en := range e.([]*ldap.Entry) {
l.Entries = append(l.Entries, &Entry{Entry: en})
}
case *ldap.Entry:
l.Entries = append(l.Entries, &Entry{Entry: e.(*ldap.Entry)})
case []*ldap.AddRequest:
for _, en := range e.([]*ldap.AddRequest) {
l.Entries = append(l.Entries, &Entry{Add: en})
}
case *ldap.AddRequest:
l.Entries = append(l.Entries, &Entry{Add: e.(*ldap.AddRequest)})
case []*ldap.DelRequest:
for _, en := range e.([]*ldap.DelRequest) {
l.Entries = append(l.Entries, &Entry{Del: en})
}
case *ldap.DelRequest:
l.Entries = append(l.Entries, &Entry{Del: e.(*ldap.DelRequest)})
case []*ldap.ModifyRequest:
for _, en := range e.([]*ldap.ModifyRequest) {
l.Entries = append(l.Entries, &Entry{Modify: en})
}
case *ldap.ModifyRequest:
l.Entries = append(l.Entries, &Entry{Modify: e.(*ldap.ModifyRequest)})
default:
return nil, fmt.Errorf("unsupported type %T", e)
}
}
return l, nil
}
+9
View File
@@ -0,0 +1,9 @@
// +build !windows
package ldif
import "net/url"
func toPath(u *url.URL) string {
return u.Path
}
+12
View File
@@ -0,0 +1,12 @@
package ldif
import "net/url"
import "strings"
// toPath get the file path
// We use ioutil.ReadFile to read the content file.
// On windows,
// https://github.com/golang/go/blob/95a11c7381e01fdaaf34e25b82db0632081ab74e/src/net/url/url_test.go#L283-L292
func toPath(u *url.URL) string {
return strings.TrimPrefix(u.Path, "/")
}