harbor/vendor/github.com/mqu/openldap/add-modify-delete.go

231 lines
7.2 KiB
Go

/*
*
* Copyright (C) 2012 - Marc Quinton.
*
* Use of this source code is governed by the MIT Licence :
* http://opensource.org/licenses/mit-license.php
*
* 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 AUTHOR 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.
*/
package openldap
/* #include <stdlib.h>
#include <stdio.h>
#define LDAP_DEPRECATED 1
#include <ldap.h>
// goc can not use union on structs ; so create a new type with same attributes and size
// fixme : support binary mods (mod_bvalues)
typedef struct ldapmod_str {
int mod_op;
char *mod_type;
char **mod_vals;
} LDAPModStr;
int _ldap_add(LDAP *ld, char* dn, LDAPModStr **attrs){
//API: int ldap_add_ext_s(LDAP *ld, char *dn, LDAPMod **attrs, LDAPControl *sctrls, LDAPControl *cctrls );
// nota : cast (LDAPMod **) is possible because structs have same size
return ldap_add_ext_s(ld, dn, (LDAPMod **)attrs, NULL, NULL);
}
int _ldap_modify(LDAP *ld, char* dn, LDAPModStr **mods ){
// nota : cast (LDAPMod **) is possible because structs have same size
return ldap_modify_ext_s( ld, dn, (LDAPMod **)mods, NULL, NULL);
}
int _ldap_rename (LDAP *ld, char *dn, char *newrdn, char *newSuperior, int deleteoldrdn){
//API: int ldap_rename_s( ld, dn, newrdn, newparent, deleteoldrdn, sctrls[], cctrls[])
return ldap_rename_s(ld, dn, newrdn, newSuperior, deleteoldrdn, NULL, NULL);
}
void _ldap_mods_free (LDAPModStr **mods, int freemods){
//API: void ldap_mods_free(LDAPMod **mods, int freemods);
return ldap_mods_free((LDAPMod **)mods, freemods);
}
*/
// #cgo CFLAGS: -DLDAP_DEPRECATED=1
// #cgo linux CFLAGS: -DLINUX=1
// #cgo LDFLAGS: -lldap -llber
import "C"
import (
"errors"
"unsafe"
"fmt"
)
func (self *Ldap) doModify(dn string, attrs map[string][]string, changeType int, full_add bool) (int){
_dn := C.CString(dn)
defer C.free(unsafe.Pointer(_dn))
mods := make([]*C.LDAPModStr, len(attrs)+1)
// mods[len] = nil by default
count:= 0
for key, values := range attrs {
// transform []string to C.char** null terminated array (attributes argument)
_values := make([]*C.char, len(values)+1) // default set to nil (NULL in C)
for i, value := range values {
_values[i] = C.CString(value)
defer C.free(unsafe.Pointer(_values[i]))
}
var mod C.LDAPModStr
mod.mod_op = C.int(changeType)
mod.mod_type = C.CString(key)
mod.mod_vals = &_values[0]
defer C.free(unsafe.Pointer(mod.mod_type))
mods[count] = &mod
count++
}
var rv int
if full_add {
// API: int ldap_add (LDAP *ld, LDAP_CONST char *dn, LDAPMod **mods )
rv = int(C._ldap_add(self.conn, _dn, &mods[0]))
} else{
// API: int ldap_modify (LDAP *ld, LDAP_CONST char *dn, LDAPMod **mods )
rv = int(C._ldap_modify(self.conn, _dn, &mods[0]))
}
// FIXME: need to call ldap_mods_free(&mods) some where.
// C._ldap_mods_free(&mods[0], 1) // not OK.
return rv
}
func (self *Ldap) Modify(dn string, attrs map[string][]string) (error){
changeType := C.LDAP_MOD_REPLACE
full_add := false
rv := self.doModify(dn, attrs, changeType, full_add)
if rv != LDAP_OPT_SUCCESS {
return errors.New(fmt.Sprintf("LDAP::Modify() error : %d (%s)", rv, ErrorToString(rv)))
}
return nil
}
func (self *Ldap) ModifyDel(dn string, attrs map[string][]string) (error){
changeType := C.LDAP_MOD_DELETE
full_add := false
rv := self.doModify(dn, attrs, changeType, full_add)
if rv != LDAP_OPT_SUCCESS {
return errors.New(fmt.Sprintf("LDAP::ModifyDel() error : %d (%s)", rv, ErrorToString(rv)))
}
return nil
}
func (self *Ldap) ModifyAdd(dn string, attrs map[string][]string) (error){
changeType := C.LDAP_MOD_ADD
full_add := false
rv := self.doModify(dn, attrs, changeType, full_add)
if rv != LDAP_OPT_SUCCESS {
return errors.New(fmt.Sprintf("LDAP::ModifyAdd() error : %d (%s)", rv, ErrorToString(rv)))
}
return nil
}
func (self *Ldap) Add(dn string, attrs map[string][]string) (error){
changeType := C.LDAP_MOD_ADD
full_add := true
rv := self.doModify(dn, attrs, changeType, full_add)
if rv != LDAP_OPT_SUCCESS {
return errors.New(fmt.Sprintf("LDAP::Add() error : %d (%s)", rv, ErrorToString(rv)))
}
return nil
}
func (self *Ldap) Delete(dn string) (error){
_dn := C.CString(dn)
defer C.free(unsafe.Pointer(_dn))
// API: int ldap_delete (LDAP *ld, LDAP_CONST char *dn)
rv := C.ldap_delete_s(self.conn, _dn)
if rv != LDAP_OPT_SUCCESS {
return errors.New(fmt.Sprintf("LDAP::Delete() error : %d (%s)", rv, ErrorToString(int(rv))))
}
return nil
}
// Rename() to rename LDAP entries.
//
// These routines are used to perform a LDAP rename operation. The function changes the leaf compo-
// nent of an entry's distinguished name and optionally moves the entry to a new parent container.
// The ldap_rename_s performs a rename operation synchronously. The method takes dn, which points to
// the distinguished name of the entry whose attribute is being compared, newparent,the distinguished
// name of the entry's new parent. If this parameter is NULL, only the RDN is changed. The root DN is
// specified by passing a zero length string, "". deleteoldrdn specifies whether the old RDN should
// be retained or deleted. Zero indicates that the old RDN should be retained. If you choose this
// option, the attribute will contain both names (the old and the new). Non-zero indicates that the
// old RDN should be deleted. serverctrls points to an array of LDAPControl structures that list the
// client controls to use with this extended operation. Use NULL to specify no client controls.
// clientctrls points to an array of LDAPControl structures that list the client controls to use with
// the search.
// FIXME: support NULL and "" values for newSuperior parameter.
//
func (self *Ldap) Rename(dn string, newrdn string, newSuperior string, deleteOld bool) (error){
_dn := C.CString(dn)
defer C.free(unsafe.Pointer(_dn))
_newrdn := C.CString(newrdn)
defer C.free(unsafe.Pointer(_newrdn))
_newSuperior := C.CString(newSuperior)
defer C.free(unsafe.Pointer(_newSuperior))
var _delete C.int = 0
if deleteOld {
_delete = 1
}
// API: int ldap_rename (LDAP *ld, char *newrdn, char *newSuperior, int deleteoldrdn)
rv := C._ldap_rename(self.conn, _dn, _newrdn, _newSuperior, _delete)
if rv != LDAP_OPT_SUCCESS {
return errors.New(fmt.Sprintf("LDAP::Rename() error : %d (%s)", rv, ErrorToString(int(rv))))
}
return nil
}