1 /*
2 * The contents of this file are subject to the Netscape Public
3 * License Version 1.1 (the "License"); you may not use this file
4 * except in compliance with the License. You may obtain a copy of
5 * the License at http://www.mozilla.org/NPL/
6 *
7 * Software distributed under the License is distributed on an "AS
8 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
9 * implied. See the License for the specific language governing
10 * rights and limitations under the License.
11 *
12 * The Original Code is Mozilla Communicator client code, released
13 * March 31, 1998.
14 *
15 * The Initial Developer of the Original Code is Netscape
16 * Communications Corporation. Portions created by Netscape are
17 * Copyright (C) 1998-1999 Netscape Communications Corporation. All
18 * Rights Reserved.
19 *
20 * Contributor(s):
21 */
22 /*
23 * Copyright (c) 1990 Regents of the University of Michigan.
24 * All rights reserved.
25 */
26 /*
27 * modify.c
28 */
29
30 #if 0
31 #ifndef lint
32 static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n";
33 #endif
34 #endif
35
36 #include "ldap-int.h"
37
38 /*
39 * ldap_modify - initiate an ldap modify operation. Parameters:
40 *
41 * ld LDAP descriptor
42 * dn DN of the object to modify
43 * mods List of modifications to make. This is null-terminated
44 * array of struct ldapmod's, specifying the modifications
45 * to perform.
46 *
47 * Example:
48 * LDAPMod *mods[] = {
49 * { LDAP_MOD_ADD, "cn", { "babs jensen", "babs", 0 } },
50 * { LDAP_MOD_REPLACE, "sn", { "jensen", 0 } },
51 * 0
52 * }
53 * msgid = ldap_modify( ld, dn, mods );
54 */
55 int
56 LDAP_CALL
ldap_modify(LDAP * ld,const char * dn,LDAPMod ** mods)57 ldap_modify( LDAP *ld, const char *dn, LDAPMod **mods )
58 {
59 int msgid;
60
61 LDAPDebug( LDAP_DEBUG_TRACE, "ldap_modify\n", 0, 0, 0 );
62
63 if ( ldap_modify_ext( ld, dn, mods, NULL, NULL, &msgid )
64 == LDAP_SUCCESS ) {
65 return( msgid );
66 } else {
67 return( -1 ); /* error is in ld handle */
68 }
69 }
70
71 int
72 LDAP_CALL
ldap_modify_ext(LDAP * ld,const char * dn,LDAPMod ** mods,LDAPControl ** serverctrls,LDAPControl ** clientctrls,int * msgidp)73 ldap_modify_ext( LDAP *ld, const char *dn, LDAPMod **mods,
74 LDAPControl **serverctrls, LDAPControl **clientctrls, int *msgidp )
75 {
76 BerElement *ber;
77 int i, rc, lderr;
78
79 /*
80 * A modify request looks like this:
81 * ModifyRequet ::= SEQUENCE {
82 * object DistinguishedName,
83 * modifications SEQUENCE OF SEQUENCE {
84 * operation ENUMERATED {
85 * add (0),
86 * delete (1),
87 * replace (2)
88 * },
89 * modification SEQUENCE {
90 * type AttributeType,
91 * values SET OF AttributeValue
92 * }
93 * }
94 * }
95 */
96
97 LDAPDebug( LDAP_DEBUG_TRACE, "ldap_modify_ext\n", 0, 0, 0 );
98
99 if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) {
100 return( LDAP_PARAM_ERROR );
101 }
102 if ( !NSLDAPI_VALID_LDAPMESSAGE_POINTER( msgidp ))
103 {
104 LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL );
105 return( LDAP_PARAM_ERROR );
106 }
107
108 if ( !NSLDAPI_VALID_NONEMPTY_LDAPMOD_ARRAY( mods )) {
109 lderr = LDAP_PARAM_ERROR;
110 LDAP_SET_LDERRNO( ld, lderr, NULL, NULL );
111 return( lderr );
112 }
113 if ( dn == NULL ) {
114 dn = "";
115 }
116
117 LDAP_MUTEX_LOCK( ld, LDAP_MSGID_LOCK );
118 *msgidp = ++ld->ld_msgid;
119 LDAP_MUTEX_UNLOCK( ld, LDAP_MSGID_LOCK );
120
121 /* see if we should add to the cache */
122 if ( ld->ld_cache_on && ld->ld_cache_modify != NULL ) {
123 LDAP_MUTEX_LOCK( ld, LDAP_CACHE_LOCK );
124 if ( (rc = (ld->ld_cache_modify)( ld, *msgidp, LDAP_REQ_MODIFY,
125 dn, mods )) != 0 ) {
126 *msgidp = rc;
127 LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK );
128 return( LDAP_SUCCESS );
129 }
130 LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK );
131 }
132
133 /* create a message to send */
134 if (( lderr = nsldapi_alloc_ber_with_options( ld, &ber ))
135 != LDAP_SUCCESS ) {
136 return( lderr );
137 }
138
139 if ( ber_printf( ber, "{it{s{", *msgidp, LDAP_REQ_MODIFY, dn )
140 == -1 ) {
141 lderr = LDAP_ENCODING_ERROR;
142 LDAP_SET_LDERRNO( ld, lderr, NULL, NULL );
143 ber_free( ber, 1 );
144 return( lderr );
145 }
146
147 /* for each modification to be performed... */
148 for ( i = 0; mods[i] != NULL; i++ ) {
149 if (( mods[i]->mod_op & LDAP_MOD_BVALUES) != 0 ) {
150 rc = ber_printf( ber, "{e{s[V]}}",
151 mods[i]->mod_op & ~LDAP_MOD_BVALUES,
152 mods[i]->mod_type, mods[i]->mod_bvalues );
153 } else {
154 rc = ber_printf( ber, "{e{s[v]}}", mods[i]->mod_op,
155 mods[i]->mod_type, mods[i]->mod_values );
156 }
157
158 if ( rc == -1 ) {
159 lderr = LDAP_ENCODING_ERROR;
160 LDAP_SET_LDERRNO( ld, lderr, NULL, NULL );
161 ber_free( ber, 1 );
162 return( lderr );
163 }
164 }
165
166 if ( ber_printf( ber, "}}" ) == -1 ) {
167 lderr = LDAP_ENCODING_ERROR;
168 LDAP_SET_LDERRNO( ld, lderr, NULL, NULL );
169 ber_free( ber, 1 );
170 return( lderr );
171 }
172
173 if (( lderr = nsldapi_put_controls( ld, serverctrls, 1, ber ))
174 != LDAP_SUCCESS ) {
175 ber_free( ber, 1 );
176 return( lderr );
177 }
178
179 /* send the message */
180 rc = nsldapi_send_initial_request( ld, *msgidp, LDAP_REQ_MODIFY,
181 (char *)dn, ber );
182 *msgidp = rc;
183 return( rc < 0 ? LDAP_GET_LDERRNO( ld, NULL, NULL ) : LDAP_SUCCESS );
184 }
185
186 int
187 LDAP_CALL
ldap_modify_s(LDAP * ld,const char * dn,LDAPMod ** mods)188 ldap_modify_s( LDAP *ld, const char *dn, LDAPMod **mods )
189 {
190 return( ldap_modify_ext_s( ld, dn, mods, NULL, NULL ));
191 }
192
193 int
194 LDAP_CALL
ldap_modify_ext_s(LDAP * ld,const char * dn,LDAPMod ** mods,LDAPControl ** serverctrls,LDAPControl ** clientctrls)195 ldap_modify_ext_s( LDAP *ld, const char *dn, LDAPMod **mods,
196 LDAPControl **serverctrls, LDAPControl **clientctrls )
197 {
198 int msgid, err;
199 LDAPMessage *res;
200
201 if (( err = ldap_modify_ext( ld, dn, mods, serverctrls, clientctrls,
202 &msgid )) != LDAP_SUCCESS ) {
203 return( err );
204 }
205
206 if ( ldap_result( ld, msgid, 1, (struct timeval *)NULL, &res ) == -1 ) {
207 return( LDAP_GET_LDERRNO( ld, NULL, NULL ) );
208 }
209
210 return( ldap_result2error( ld, res, 1 ) );
211 }
212