-
Notifications
You must be signed in to change notification settings - Fork 35
/
mod.c
359 lines (316 loc) · 8.26 KB
/
mod.c
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
/*
* mod.c
* $Id: mod.c,v 1.14 2005/03/07 22:57:34 ianmacd Exp $
*/
#include "ruby.h"
#include "rbldap.h"
VALUE rb_cLDAP_Mod;
void
rb_ldap_mod_free (RB_LDAPMOD_DATA * data)
{
if (data->mod)
{
struct berval **bvals;
char **svals;
int i;
xfree(data->mod->mod_type);
if (data->mod->mod_op & LDAP_MOD_BVALUES)
{
bvals = data->mod->mod_vals.modv_bvals;
for (i = 0; bvals[i] != NULL; i++)
{
xfree (bvals[i]);
}
xfree (bvals);
}
else
{
svals = data->mod->mod_vals.modv_strvals;
for (i = 0; svals[i] != NULL; i++)
{
xfree (svals[i]);
}
xfree (svals);
}
xfree (data->mod);
}
xfree (data);
}
static LDAPMod *
rb_ldap_new_mod (int mod_op, char *mod_type, char **modv_strvals)
{
LDAPMod *mod;
if (mod_op & LDAP_MOD_BVALUES)
{
rb_bug ("rb_ldap_mod_new: illegal mod_op");
}
mod = ALLOC_N (LDAPMod, 1);
mod->mod_op = mod_op;
mod->mod_type = ALLOC_N(char,strlen(mod_type) + 1);
strcpy(mod->mod_type, mod_type);
mod->mod_vals.modv_strvals = modv_strvals;
return mod;
}
VALUE
rb_ldap_mod_new (int mod_op, char *mod_type, char **modv_strvals)
{
VALUE obj;
RB_LDAPMOD_DATA *moddata;
obj = Data_Make_Struct (rb_cLDAP_Mod, RB_LDAPMOD_DATA,
0, rb_ldap_mod_free, moddata);
moddata->mod = rb_ldap_new_mod (mod_op, mod_type, modv_strvals);
return obj;
}
static LDAPMod *
rb_ldap_new_mod2 (int mod_op, char *mod_type, struct berval **modv_bvals)
{
LDAPMod *mod;
if (!(mod_op & LDAP_MOD_BVALUES))
{
rb_bug ("rb_ldap_mod_new: illegal mod_op");
}
mod = ALLOC_N (LDAPMod, 1);
mod->mod_op = mod_op;
mod->mod_type = ALLOC_N(char,strlen(mod_type) + 1);
strcpy(mod->mod_type, mod_type);
mod->mod_vals.modv_bvals = modv_bvals;
return mod;
}
VALUE
rb_ldap_mod_new2 (int mod_op, char *mod_type, struct berval ** modv_bvals)
{
VALUE obj;
RB_LDAPMOD_DATA *moddata;
obj = Data_Make_Struct (rb_cLDAP_Mod, RB_LDAPMOD_DATA,
0, rb_ldap_mod_free, moddata);
moddata->mod = rb_ldap_new_mod2 (mod_op, mod_type, modv_bvals);
return obj;
}
static VALUE
rb_ldap_mod_s_allocate (VALUE klass)
{
RB_LDAPMOD_DATA *moddata;
VALUE obj;
obj =
Data_Make_Struct (klass, RB_LDAPMOD_DATA, 0, rb_ldap_mod_free, moddata);
moddata->mod = NULL;
return obj;
}
/*
* call-seq:
* Mod.new(mod_type, attr, vals) => LDAP::Mod
*
* Create a new LDAP::Mod object of type +mod_type+. This is most commonly
* *LDAP_MOD_ADD*, *LDAP_MOD_REPLACE* or *LDAP_MOD_DELETE*, although some LDAP
* servers may offer extension types.
*
* +attr+ should be the name of the attribute on which to operate, whilst
* +vals+ is an array of values pertaining to +attr+. If +vals+ contains
* binary data, +mod_type+ should be logically OR'ed (|) with
* *LDAP_MOD_BVALUES*.
*
* LDAP::Mod objects can be passed to methods in the LDAP::Conn class, such as
* Conn#add, Conn#add_ext, Conn#modify and Conn#modify_ext.
*/
static VALUE
rb_ldap_mod_initialize (int argc, VALUE argv[], VALUE self)
{
struct berval **bvals;
char **strvals;
int mod_op;
char *mod_type;
int i;
VALUE op, type, vals;
RB_LDAPMOD_DATA *moddata;
rb_scan_args (argc, argv, "3", &op, &type, &vals);
Data_Get_Struct (self, RB_LDAPMOD_DATA, moddata);
if (moddata->mod)
return Qnil;
mod_op = NUM2INT (op);
mod_type = RSTRING_PTR(type);
Check_Type (vals, T_ARRAY);
if (mod_op & LDAP_MOD_BVALUES)
{
bvals = ALLOC_N (struct berval *, RARRAY_LEN (vals) + 1);
for (i = 0; i < RARRAY_LEN (vals); i++)
{
VALUE str;
struct berval *bval;
str = RARRAY_PTR (vals)[i];
Check_Type (str, T_STRING);
bval = ALLOC_N (struct berval, 1);
bval->bv_len = RSTRING_LEN (str);
RB_LDAP_SET_STR (bval->bv_val, str);
bvals[i] = bval;
}
bvals[i] = NULL;
moddata->mod = rb_ldap_new_mod2 (mod_op, mod_type, bvals);
}
else
{
strvals = ALLOC_N (char *, RARRAY_LEN (vals) + 1);
for (i = 0; i < RARRAY_LEN (vals); i++)
{
VALUE str;
char *sval;
str = RARRAY_PTR (vals)[i];
RB_LDAP_SET_STR (sval, str);
strvals[i] = sval;
}
strvals[i] = NULL;
moddata->mod = rb_ldap_new_mod (mod_op, mod_type, strvals);
}
return Qnil;
}
/*
* call-seq:
* mod.mod_op => Fixnum
*
* Return the type of modification associated with the LDAP::Mod object.
* Standard types are *LDAP_MOD_ADD*, *LDAP_MOD_REPLACE* and
* *LDAP_MOD_DELETE*, although any of these may be logically OR'ed with
* *LDAP_MOD_BVALUES* to indicate that the values of the Mod object contain
* binary data.
*/
VALUE
rb_ldap_mod_op (VALUE self)
{
RB_LDAPMOD_DATA *moddata;
GET_LDAPMOD_DATA (self, moddata);
return INT2NUM (moddata->mod->mod_op);
}
/*
* call-seq:
* mod.mod_type => String
*
* Return the name of the attribute associated with the LDAP::Mod object.
*/
VALUE
rb_ldap_mod_type (VALUE self)
{
RB_LDAPMOD_DATA *moddata;
GET_LDAPMOD_DATA (self, moddata);
return rb_tainted_str_new2 (moddata->mod->mod_type);
}
/*
* call-seq:
* mod.mod_vals => Array of String
*
* Return the values associated with the Mod object.
*/
VALUE
rb_ldap_mod_vals (VALUE self)
{
RB_LDAPMOD_DATA *moddata;
struct berval **bvals;
char **svals;
int i;
VALUE val;
GET_LDAPMOD_DATA (self, moddata);
if (moddata->mod->mod_op & LDAP_MOD_BVALUES)
{
bvals = moddata->mod->mod_vals.modv_bvals;
val = rb_ary_new ();
for (i = 0; bvals[i] != NULL; i++)
{
VALUE str;
str = rb_tainted_str_new (bvals[i]->bv_val, bvals[i]->bv_len);
rb_ary_push (val, str);
}
}
else
{
svals = moddata->mod->mod_vals.modv_strvals;
val = rb_ary_new ();
for (i = 0; svals[i] != NULL; i++)
{
VALUE str;
str = rb_tainted_str_new2 (svals[i]);
rb_ary_push (val, str);
}
}
return val;
}
/* call-seq:
* mod.inspect => String
*
* Produce a concise representation of the Mod object.
*/
VALUE
rb_ldap_mod_inspect (VALUE self)
{
VALUE str;
VALUE hash = rb_hash_new ();
const char *c;
c = rb_obj_classname (self);
str = rb_str_new (0, strlen (c) + 10 + 16 + 1); /* 10:tags 16:addr 1:nul */
sprintf (RSTRING_PTR (str), "#<%s:0x%lx ", c, self);
#if RUBY_VERSION_CODE < 190
RSTRING(str)->len = strlen (RSTRING_PTR (str));
#else
rb_str_set_len(str, strlen (RSTRING_PTR (str)));
#endif
switch (FIX2INT (rb_ldap_mod_op (self)) & ~LDAP_MOD_BVALUES)
{
case LDAP_MOD_ADD:
rb_str_cat2 (str, "LDAP_MOD_ADD");
break;
case LDAP_MOD_DELETE:
rb_str_cat2 (str, "LDAP_MOD_DELETE");
break;
case LDAP_MOD_REPLACE:
rb_str_cat2 (str, "LDAP_MOD_REPLACE");
break;
#ifdef LDAP_MOD_INCREMENT
case LDAP_MOD_INCREMENT:
rb_str_cat2 (str, "LDAP_MOD_INCREMENT");
break;
#endif
#ifdef LDAP_MOD_OP
case LDAP_MOD_OP:
rb_str_cat2 (str, "LDAP_MOD_OP");
break;
#endif
default:
/* We shouldn't end up here. */
rb_str_cat2 (str, "unknown");
break;
}
if (FIX2INT (rb_ldap_mod_op (self)) & LDAP_MOD_BVALUES)
rb_str_cat2 (str, "|LDAP_MOD_BVALUES");
rb_str_cat2 (str, "\n");
rb_hash_aset (hash, rb_ldap_mod_type (self), rb_ldap_mod_vals (self));
rb_str_concat (str, rb_inspect (hash));
rb_str_cat2 (str, ">");
return str;
}
/* Document-class: LDAP::Mod
*
* Create and manipulate LDAP::Mod objects, which can then be passed to methods
* in the LDAP::Conn class, such as Conn#add, Conn#add_ext, Conn#modify and
* Conn#modify_ext.
*/
void
Init_ldap_mod ()
{
rb_cLDAP_Mod = rb_define_class_under (rb_mLDAP, "Mod", rb_cObject);
#if RUBY_VERSION_CODE < 170
rb_define_singleton_method (rb_cLDAP_Mod, "new", rb_ldap_class_new, -1);
#endif
#if RUBY_VERSION_CODE >= 173
rb_define_alloc_func (rb_cLDAP_Mod, rb_ldap_mod_s_allocate);
#else
rb_define_singleton_method (rb_cLDAP_Mod, "allocate",
rb_ldap_mod_s_allocate, 0);
#endif
rb_ldap_mod_define_method ("initialize", rb_ldap_mod_initialize, -1);
rb_ldap_mod_define_method ("mod_op", rb_ldap_mod_op, 0);
rb_ldap_mod_define_method ("mod_type", rb_ldap_mod_type, 0);
rb_ldap_mod_define_method ("mod_vals", rb_ldap_mod_vals, 0);
rb_ldap_mod_define_method ("inspect", rb_ldap_mod_inspect, 0);
/*
rb_ldap_mod_define_method("mod_op=", rb_ldap_mod_set_op, 1);
rb_ldap_mod_define_method("mod_type=", rb_ldap_mod_set_type, 1);
rb_ldap_mod_define_method("mod_vals=", rb_ldap_mod_set_vals, 1);
*/
}