~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source3/lib/ldb/common/ldb_ldif.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
   ldb database library
 
3
 
 
4
   Copyright (C) Andrew Tridgell  2004
 
5
 
 
6
     ** NOTE! The following LGPL license applies to the ldb
 
7
     ** library. This does NOT imply that all of Samba is released
 
8
     ** under the LGPL
 
9
   
 
10
   This library is free software; you can redistribute it and/or
 
11
   modify it under the terms of the GNU Lesser General Public
 
12
   License as published by the Free Software Foundation; either
 
13
   version 3 of the License, or (at your option) any later version.
 
14
 
 
15
   This library is distributed in the hope that it will be useful,
 
16
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
18
   Lesser General Public License for more details.
 
19
 
 
20
   You should have received a copy of the GNU Lesser General Public
 
21
   License along with this library; if not, see <http://www.gnu.org/licenses/>.
 
22
*/
 
23
 
 
24
/*
 
25
 *  Name: ldb
 
26
 *
 
27
 *  Component: ldif routines
 
28
 *
 
29
 *  Description: ldif pack/unpack routines
 
30
 *
 
31
 *  Author: Andrew Tridgell
 
32
 */
 
33
 
 
34
/*
 
35
  see RFC2849 for the LDIF format definition
 
36
*/
 
37
 
 
38
#include "includes.h"
 
39
#include "ldb/include/includes.h"
 
40
#include "system/locale.h"
 
41
 
 
42
/*
 
43
  
 
44
*/
 
45
static int ldb_read_data_file(void *mem_ctx, struct ldb_val *value)
 
46
{
 
47
        struct stat statbuf;
 
48
        char *buf;
 
49
        int count, size, bytes;
 
50
        int ret;
 
51
        int f;
 
52
        const char *fname = (const char *)value->data;
 
53
 
 
54
        if (strncmp(fname, "file://", 7) != 0) {
 
55
                return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
 
56
        }
 
57
        fname += 7;
 
58
 
 
59
        f = open(fname, O_RDONLY);
 
60
        if (f == -1) {
 
61
                return -1;
 
62
        }
 
63
 
 
64
        if (fstat(f, &statbuf) != 0) {
 
65
                ret = -1;
 
66
                goto done;
 
67
        }
 
68
 
 
69
        if (statbuf.st_size == 0) {
 
70
                ret = -1;
 
71
                goto done;
 
72
        }
 
73
 
 
74
        value->data = (uint8_t *)talloc_size(mem_ctx, statbuf.st_size + 1);
 
75
        if (value->data == NULL) {
 
76
                ret = -1;
 
77
                goto done;
 
78
        }
 
79
        value->data[statbuf.st_size] = 0;
 
80
 
 
81
        count = 0;
 
82
        size = statbuf.st_size;
 
83
        buf = (char *)value->data;
 
84
        while (count < statbuf.st_size) {
 
85
                bytes = read(f, buf, size);
 
86
                if (bytes == -1) {
 
87
                        talloc_free(value->data);
 
88
                        ret = -1;
 
89
                        goto done;
 
90
                }
 
91
                count += bytes;
 
92
                buf += bytes;
 
93
                size -= bytes;
 
94
        }
 
95
 
 
96
        value->length = statbuf.st_size;
 
97
        ret = statbuf.st_size;
 
98
 
 
99
done:
 
100
        close(f);
 
101
        return ret;
 
102
}
 
103
 
 
104
/*
 
105
  this base64 decoder was taken from jitterbug (written by tridge).
 
106
  we might need to replace it with a new version
 
107
*/
 
108
int ldb_base64_decode(char *s)
 
109
{
 
110
        const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 
111
        int bit_offset=0, byte_offset, idx, i, n;
 
112
        uint8_t *d = (uint8_t *)s;
 
113
        char *p=NULL;
 
114
 
 
115
        n=i=0;
 
116
 
 
117
        while (*s && (p=strchr(b64,*s))) {
 
118
                idx = (int)(p - b64);
 
119
                byte_offset = (i*6)/8;
 
120
                bit_offset = (i*6)%8;
 
121
                d[byte_offset] &= ~((1<<(8-bit_offset))-1);
 
122
                if (bit_offset < 3) {
 
123
                        d[byte_offset] |= (idx << (2-bit_offset));
 
124
                        n = byte_offset+1;
 
125
                } else {
 
126
                        d[byte_offset] |= (idx >> (bit_offset-2));
 
127
                        d[byte_offset+1] = 0;
 
128
                        d[byte_offset+1] |= (idx << (8-(bit_offset-2))) & 0xFF;
 
129
                        n = byte_offset+2;
 
130
                }
 
131
                s++; i++;
 
132
        }
 
133
        if (bit_offset >= 3) {
 
134
                n--;
 
135
        }
 
136
 
 
137
        if (*s && !p) {
 
138
                /* the only termination allowed */
 
139
                if (*s != '=') {
 
140
                        return -1;
 
141
                }
 
142
        }
 
143
 
 
144
        /* null terminate */
 
145
        d[n] = 0;
 
146
        return n;
 
147
}
 
148
 
 
149
 
 
150
/*
 
151
  encode as base64
 
152
  caller frees
 
153
*/
 
154
char *ldb_base64_encode(void *mem_ctx, const char *buf, int len)
 
155
{
 
156
        const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 
157
        int bit_offset, byte_offset, idx, i;
 
158
        const uint8_t *d = (const uint8_t *)buf;
 
159
        int bytes = (len*8 + 5)/6, pad_bytes = (bytes % 4) ? 4 - (bytes % 4) : 0;
 
160
        char *out;
 
161
 
 
162
        out = talloc_array(mem_ctx, char, bytes+pad_bytes+1);
 
163
        if (!out) return NULL;
 
164
 
 
165
        for (i=0;i<bytes;i++) {
 
166
                byte_offset = (i*6)/8;
 
167
                bit_offset = (i*6)%8;
 
168
                if (bit_offset < 3) {
 
169
                        idx = (d[byte_offset] >> (2-bit_offset)) & 0x3F;
 
170
                } else {
 
171
                        idx = (d[byte_offset] << (bit_offset-2)) & 0x3F;
 
172
                        if (byte_offset+1 < len) {
 
173
                                idx |= (d[byte_offset+1] >> (8-(bit_offset-2)));
 
174
                        }
 
175
                }
 
176
                out[i] = b64[idx];
 
177
        }
 
178
 
 
179
        for (;i<bytes+pad_bytes;i++)
 
180
                out[i] = '=';
 
181
        out[i] = 0;
 
182
 
 
183
        return out;
 
184
}
 
185
 
 
186
/*
 
187
  see if a buffer should be base64 encoded
 
188
*/
 
189
int ldb_should_b64_encode(const struct ldb_val *val)
 
190
{
 
191
        unsigned int i;
 
192
        uint8_t *p = val->data;
 
193
 
 
194
        if (val->length == 0) {
 
195
                return 0;
 
196
        }
 
197
 
 
198
        if (p[0] == ' ' || p[0] == ':') {
 
199
                return 1;
 
200
        }
 
201
 
 
202
        for (i=0; i<val->length; i++) {
 
203
                if (!isprint(p[i]) || p[i] == '\n') {
 
204
                        return 1;
 
205
                }
 
206
        }
 
207
        return 0;
 
208
}
 
209
 
 
210
/* this macro is used to handle the return checking on fprintf_fn() */
 
211
#define CHECK_RET do { if (ret < 0) return ret; total += ret; } while (0)
 
212
 
 
213
/*
 
214
  write a line folded string onto a file
 
215
*/
 
216
static int fold_string(int (*fprintf_fn)(void *, const char *, ...), void *private_data,
 
217
                        const char *buf, size_t length, int start_pos)
 
218
{
 
219
        unsigned int i;
 
220
        int total=0, ret;
 
221
 
 
222
        for (i=0;i<length;i++) {
 
223
                ret = fprintf_fn(private_data, "%c", buf[i]);
 
224
                CHECK_RET;
 
225
                if (i != (length-1) && (i + start_pos) % 77 == 0) {
 
226
                        ret = fprintf_fn(private_data, "\n ");
 
227
                        CHECK_RET;
 
228
                }
 
229
        }
 
230
 
 
231
        return total;
 
232
}
 
233
 
 
234
#undef CHECK_RET
 
235
 
 
236
/*
 
237
  encode as base64 to a file
 
238
*/
 
239
static int base64_encode_f(struct ldb_context *ldb,
 
240
                           int (*fprintf_fn)(void *, const char *, ...), 
 
241
                           void *private_data,
 
242
                           const char *buf, int len, int start_pos)
 
243
{
 
244
        char *b = ldb_base64_encode(ldb, buf, len);
 
245
        int ret;
 
246
 
 
247
        if (!b) {
 
248
                return -1;
 
249
        }
 
250
 
 
251
        ret = fold_string(fprintf_fn, private_data, b, strlen(b), start_pos);
 
252
 
 
253
        talloc_free(b);
 
254
        return ret;
 
255
}
 
256
 
 
257
 
 
258
static const struct {
 
259
        const char *name;
 
260
        enum ldb_changetype changetype;
 
261
} ldb_changetypes[] = {
 
262
        {"add",    LDB_CHANGETYPE_ADD},
 
263
        {"delete", LDB_CHANGETYPE_DELETE},
 
264
        {"modify", LDB_CHANGETYPE_MODIFY},
 
265
        {NULL, 0}
 
266
};
 
267
 
 
268
/* this macro is used to handle the return checking on fprintf_fn() */
 
269
#define CHECK_RET do { if (ret < 0) { talloc_free(mem_ctx); return ret; } total += ret; } while (0)
 
270
 
 
271
/*
 
272
  write to ldif, using a caller supplied write method
 
273
*/
 
274
int ldb_ldif_write(struct ldb_context *ldb,
 
275
                   int (*fprintf_fn)(void *, const char *, ...), 
 
276
                   void *private_data,
 
277
                   const struct ldb_ldif *ldif)
 
278
{
 
279
        TALLOC_CTX *mem_ctx;
 
280
        unsigned int i, j;
 
281
        int total=0, ret;
 
282
        const struct ldb_message *msg;
 
283
 
 
284
        mem_ctx = talloc_named_const(NULL, 0, "ldb_ldif_write");
 
285
 
 
286
        msg = ldif->msg;
 
287
 
 
288
        ret = fprintf_fn(private_data, "dn: %s\n", ldb_dn_linearize(msg->dn, msg->dn));
 
289
        CHECK_RET;
 
290
 
 
291
        if (ldif->changetype != LDB_CHANGETYPE_NONE) {
 
292
                for (i=0;ldb_changetypes[i].name;i++) {
 
293
                        if (ldb_changetypes[i].changetype == ldif->changetype) {
 
294
                                break;
 
295
                        }
 
296
                }
 
297
                if (!ldb_changetypes[i].name) {
 
298
                        ldb_debug(ldb, LDB_DEBUG_ERROR, "Error: Invalid ldif changetype %d\n",
 
299
                                  ldif->changetype);
 
300
                        talloc_free(mem_ctx);
 
301
                        return -1;
 
302
                }
 
303
                ret = fprintf_fn(private_data, "changetype: %s\n", ldb_changetypes[i].name);
 
304
                CHECK_RET;
 
305
        }
 
306
 
 
307
        for (i=0;i<msg->num_elements;i++) {
 
308
                const struct ldb_attrib_handler *h;
 
309
 
 
310
                h = ldb_attrib_handler(ldb, msg->elements[i].name);
 
311
 
 
312
                if (ldif->changetype == LDB_CHANGETYPE_MODIFY) {
 
313
                        switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) {
 
314
                        case LDB_FLAG_MOD_ADD:
 
315
                                fprintf_fn(private_data, "add: %s\n", 
 
316
                                           msg->elements[i].name);
 
317
                                break;
 
318
                        case LDB_FLAG_MOD_DELETE:
 
319
                                fprintf_fn(private_data, "delete: %s\n", 
 
320
                                           msg->elements[i].name);
 
321
                                break;
 
322
                        case LDB_FLAG_MOD_REPLACE:
 
323
                                fprintf_fn(private_data, "replace: %s\n", 
 
324
                                           msg->elements[i].name);
 
325
                                break;
 
326
                        }
 
327
                }
 
328
 
 
329
                for (j=0;j<msg->elements[i].num_values;j++) {
 
330
                        struct ldb_val v;
 
331
                        ret = h->ldif_write_fn(ldb, mem_ctx, &msg->elements[i].values[j], &v);
 
332
                        CHECK_RET;
 
333
                        if (ldb_should_b64_encode(&v)) {
 
334
                                ret = fprintf_fn(private_data, "%s:: ", 
 
335
                                                 msg->elements[i].name);
 
336
                                CHECK_RET;
 
337
                                ret = base64_encode_f(ldb, fprintf_fn, private_data, 
 
338
                                                      (char *)v.data, v.length,
 
339
                                                      strlen(msg->elements[i].name)+3);
 
340
                                CHECK_RET;
 
341
                                ret = fprintf_fn(private_data, "\n");
 
342
                                CHECK_RET;
 
343
                        } else {
 
344
                                ret = fprintf_fn(private_data, "%s: ", msg->elements[i].name);
 
345
                                CHECK_RET;
 
346
                                ret = fold_string(fprintf_fn, private_data,
 
347
                                                  (char *)v.data, v.length,
 
348
                                                  strlen(msg->elements[i].name)+2);
 
349
                                CHECK_RET;
 
350
                                ret = fprintf_fn(private_data, "\n");
 
351
                                CHECK_RET;
 
352
                        }
 
353
                        if (v.data != msg->elements[i].values[j].data) {
 
354
                                talloc_free(v.data);
 
355
                        }
 
356
                }
 
357
                if (ldif->changetype == LDB_CHANGETYPE_MODIFY) {
 
358
                        fprintf_fn(private_data, "-\n");
 
359
                }
 
360
        }
 
361
        ret = fprintf_fn(private_data,"\n");
 
362
        CHECK_RET;
 
363
 
 
364
        return total;
 
365
}
 
366
 
 
367
#undef CHECK_RET
 
368
 
 
369
 
 
370
/*
 
371
  pull a ldif chunk, which is defined as a piece of data ending in \n\n or EOF
 
372
  this routine removes any RFC2849 continuations and comments
 
373
 
 
374
  caller frees
 
375
*/
 
376
static char *next_chunk(struct ldb_context *ldb, 
 
377
                        int (*fgetc_fn)(void *), void *private_data)
 
378
{
 
379
        size_t alloc_size=0, chunk_size = 0;
 
380
        char *chunk = NULL;
 
381
        int c;
 
382
        int in_comment = 0;
 
383
 
 
384
        while ((c = fgetc_fn(private_data)) != EOF) {
 
385
                if (chunk_size+1 >= alloc_size) {
 
386
                        char *c2;
 
387
                        alloc_size += 1024;
 
388
                        c2 = talloc_realloc(ldb, chunk, char, alloc_size);
 
389
                        if (!c2) {
 
390
                                talloc_free(chunk);
 
391
                                errno = ENOMEM;
 
392
                                return NULL;
 
393
                        }
 
394
                        chunk = c2;
 
395
                }
 
396
 
 
397
                if (in_comment) {
 
398
                        if (c == '\n') {
 
399
                                in_comment = 0;
 
400
                        }
 
401
                        continue;                       
 
402
                }
 
403
                
 
404
                /* handle continuation lines - see RFC2849 */
 
405
                if (c == ' ' && chunk_size > 1 && chunk[chunk_size-1] == '\n') {
 
406
                        chunk_size--;
 
407
                        continue;
 
408
                }
 
409
                
 
410
                /* chunks are terminated by a double line-feed */
 
411
                if (c == '\n' && chunk_size > 0 && chunk[chunk_size-1] == '\n') {
 
412
                        chunk[chunk_size-1] = 0;
 
413
                        return chunk;
 
414
                }
 
415
 
 
416
                if (c == '#' && (chunk_size == 0 || chunk[chunk_size-1] == '\n')) {
 
417
                        in_comment = 1;
 
418
                        continue;
 
419
                }
 
420
 
 
421
                /* ignore leading blank lines */
 
422
                if (chunk_size == 0 && c == '\n') {
 
423
                        continue;
 
424
                }
 
425
 
 
426
                chunk[chunk_size++] = c;
 
427
        }
 
428
 
 
429
        if (chunk) {
 
430
                chunk[chunk_size] = 0;
 
431
        }
 
432
 
 
433
        return chunk;
 
434
}
 
435
 
 
436
 
 
437
/* simple ldif attribute parser */
 
438
static int next_attr(void *mem_ctx, char **s, const char **attr, struct ldb_val *value)
 
439
{
 
440
        char *p;
 
441
        int base64_encoded = 0;
 
442
        int binary_file = 0;
 
443
 
 
444
        if (strncmp(*s, "-\n", 2) == 0) {
 
445
                value->length = 0;
 
446
                *attr = "-";
 
447
                *s += 2;
 
448
                return 0;
 
449
        }
 
450
 
 
451
        p = strchr(*s, ':');
 
452
        if (!p) {
 
453
                return -1;
 
454
        }
 
455
 
 
456
        *p++ = 0;
 
457
 
 
458
        if (*p == ':') {
 
459
                base64_encoded = 1;
 
460
                p++;
 
461
        }
 
462
 
 
463
        if (*p == '<') {
 
464
                binary_file = 1;
 
465
                p++;
 
466
        }
 
467
 
 
468
        *attr = *s;
 
469
 
 
470
        while (*p == ' ' || *p == '\t') {
 
471
                p++;
 
472
        }
 
473
 
 
474
        value->data = (uint8_t *)p;
 
475
 
 
476
        p = strchr(p, '\n');
 
477
 
 
478
        if (!p) {
 
479
                value->length = strlen((char *)value->data);
 
480
                *s = ((char *)value->data) + value->length;
 
481
        } else {
 
482
                value->length = p - (char *)value->data;
 
483
                *s = p+1;
 
484
                *p = 0;
 
485
        }
 
486
 
 
487
        if (base64_encoded) {
 
488
                int len = ldb_base64_decode((char *)value->data);
 
489
                if (len == -1) {
 
490
                        /* it wasn't valid base64 data */
 
491
                        return -1;
 
492
                }
 
493
                value->length = len;
 
494
        }
 
495
 
 
496
        if (binary_file) {
 
497
                int len = ldb_read_data_file(mem_ctx, value);
 
498
                if (len == -1) {
 
499
                        /* an error occured hile trying to retrieve the file */
 
500
                        return -1;
 
501
                }
 
502
        }
 
503
 
 
504
        return 0;
 
505
}
 
506
 
 
507
 
 
508
/*
 
509
  free a message from a ldif_read
 
510
*/
 
511
void ldb_ldif_read_free(struct ldb_context *ldb, struct ldb_ldif *ldif)
 
512
{
 
513
        talloc_free(ldif);
 
514
}
 
515
 
 
516
/*
 
517
 read from a LDIF source, creating a ldb_message
 
518
*/
 
519
struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb,
 
520
                               int (*fgetc_fn)(void *), void *private_data)
 
521
{
 
522
        struct ldb_ldif *ldif;
 
523
        struct ldb_message *msg;
 
524
        const char *attr=NULL;
 
525
        char *chunk=NULL, *s;
 
526
        struct ldb_val value;
 
527
        unsigned flags = 0;
 
528
 
 
529
        value.data = NULL;
 
530
 
 
531
        ldif = talloc(ldb, struct ldb_ldif);
 
532
        if (!ldif) return NULL;
 
533
 
 
534
        ldif->msg = talloc(ldif, struct ldb_message);
 
535
        if (ldif->msg == NULL) {
 
536
                talloc_free(ldif);
 
537
                return NULL;
 
538
        }
 
539
 
 
540
        ldif->changetype = LDB_CHANGETYPE_NONE;
 
541
        msg = ldif->msg;
 
542
 
 
543
        msg->dn = NULL;
 
544
        msg->elements = NULL;
 
545
        msg->num_elements = 0;
 
546
        msg->private_data = NULL;
 
547
 
 
548
        chunk = next_chunk(ldb, fgetc_fn, private_data);
 
549
        if (!chunk) {
 
550
                goto failed;
 
551
        }
 
552
        talloc_steal(ldif, chunk);
 
553
 
 
554
        msg->private_data = chunk;
 
555
        s = chunk;
 
556
 
 
557
        if (next_attr(ldif, &s, &attr, &value) != 0) {
 
558
                goto failed;
 
559
        }
 
560
        
 
561
        /* first line must be a dn */
 
562
        if (ldb_attr_cmp(attr, "dn") != 0) {
 
563
                ldb_debug(ldb, LDB_DEBUG_ERROR, "Error: First line of ldif must be a dn not '%s'\n", 
 
564
                          attr);
 
565
                goto failed;
 
566
        }
 
567
 
 
568
        msg->dn = ldb_dn_explode(msg, (char *)value.data);
 
569
 
 
570
        if (msg->dn == NULL) {
 
571
                ldb_debug(ldb, LDB_DEBUG_ERROR, "Error: Unable to parse dn '%s'\n", 
 
572
                                  value.data);
 
573
                goto failed;
 
574
        }
 
575
 
 
576
        while (next_attr(ldif, &s, &attr, &value) == 0) {
 
577
                const struct ldb_attrib_handler *h;             
 
578
                struct ldb_message_element *el;
 
579
                int ret, empty = 0;
 
580
 
 
581
                if (ldb_attr_cmp(attr, "changetype") == 0) {
 
582
                        int i;
 
583
                        for (i=0;ldb_changetypes[i].name;i++) {
 
584
                                if (ldb_attr_cmp((char *)value.data, ldb_changetypes[i].name) == 0) {
 
585
                                        ldif->changetype = ldb_changetypes[i].changetype;
 
586
                                        break;
 
587
                                }
 
588
                        }
 
589
                        if (!ldb_changetypes[i].name) {
 
590
                                ldb_debug(ldb, LDB_DEBUG_ERROR, 
 
591
                                          "Error: Bad ldif changetype '%s'\n",(char *)value.data);
 
592
                        }
 
593
                        flags = 0;
 
594
                        continue;
 
595
                }
 
596
 
 
597
                if (ldb_attr_cmp(attr, "add") == 0) {
 
598
                        flags = LDB_FLAG_MOD_ADD;
 
599
                        empty = 1;
 
600
                }
 
601
                if (ldb_attr_cmp(attr, "delete") == 0) {
 
602
                        flags = LDB_FLAG_MOD_DELETE;
 
603
                        empty = 1;
 
604
                }
 
605
                if (ldb_attr_cmp(attr, "replace") == 0) {
 
606
                        flags = LDB_FLAG_MOD_REPLACE;
 
607
                        empty = 1;
 
608
                }
 
609
                if (ldb_attr_cmp(attr, "-") == 0) {
 
610
                        flags = 0;
 
611
                        continue;
 
612
                }
 
613
 
 
614
                if (empty) {
 
615
                        if (ldb_msg_add_empty(msg, (char *)value.data, flags, NULL) != 0) {
 
616
                                goto failed;
 
617
                        }
 
618
                        continue;
 
619
                }
 
620
                
 
621
                el = &msg->elements[msg->num_elements-1];
 
622
 
 
623
                h = ldb_attrib_handler(ldb, attr);
 
624
 
 
625
                if (msg->num_elements > 0 && ldb_attr_cmp(attr, el->name) == 0 &&
 
626
                    flags == el->flags) {
 
627
                        /* its a continuation */
 
628
                        el->values = 
 
629
                                talloc_realloc(msg->elements, el->values, 
 
630
                                                 struct ldb_val, el->num_values+1);
 
631
                        if (!el->values) {
 
632
                                goto failed;
 
633
                        }
 
634
                        ret = h->ldif_read_fn(ldb, ldif, &value, &el->values[el->num_values]);
 
635
                        if (ret != 0) {
 
636
                                goto failed;
 
637
                        }
 
638
                        if (value.length == 0) {
 
639
                                ldb_debug(ldb, LDB_DEBUG_ERROR,
 
640
                                          "Error: Attribute value cannot be empty for attribute '%s'\n", el->name);
 
641
                                goto failed;
 
642
                        }
 
643
                        if (value.data != el->values[el->num_values].data) {
 
644
                                talloc_steal(el->values, el->values[el->num_values].data);
 
645
                        }
 
646
                        el->num_values++;
 
647
                } else {
 
648
                        /* its a new attribute */
 
649
                        msg->elements = talloc_realloc(ldif, msg->elements, 
 
650
                                                         struct ldb_message_element, 
 
651
                                                         msg->num_elements+1);
 
652
                        if (!msg->elements) {
 
653
                                goto failed;
 
654
                        }
 
655
                        el = &msg->elements[msg->num_elements];
 
656
                        el->flags = flags;
 
657
                        el->name = talloc_strdup(msg->elements, attr);
 
658
                        el->values = talloc(msg->elements, struct ldb_val);
 
659
                        if (!el->values || !el->name) {
 
660
                                goto failed;
 
661
                        }
 
662
                        el->num_values = 1;
 
663
                        ret = h->ldif_read_fn(ldb, ldif, &value, &el->values[0]);
 
664
                        if (ret != 0) {
 
665
                                goto failed;
 
666
                        }
 
667
                        if (value.data != el->values[0].data) {
 
668
                                talloc_steal(el->values, el->values[0].data);
 
669
                        }
 
670
                        msg->num_elements++;
 
671
                }
 
672
        }
 
673
 
 
674
        return ldif;
 
675
 
 
676
failed:
 
677
        talloc_free(ldif);
 
678
        return NULL;
 
679
}
 
680
 
 
681
 
 
682
 
 
683
/*
 
684
  a wrapper around ldif_read() for reading from FILE*
 
685
*/
 
686
struct ldif_read_file_state {
 
687
        FILE *f;
 
688
};
 
689
 
 
690
static int fgetc_file(void *private_data)
 
691
{
 
692
        struct ldif_read_file_state *state =
 
693
                (struct ldif_read_file_state *)private_data;
 
694
        return fgetc(state->f);
 
695
}
 
696
 
 
697
struct ldb_ldif *ldb_ldif_read_file(struct ldb_context *ldb, FILE *f)
 
698
{
 
699
        struct ldif_read_file_state state;
 
700
        state.f = f;
 
701
        return ldb_ldif_read(ldb, fgetc_file, &state);
 
702
}
 
703
 
 
704
 
 
705
/*
 
706
  a wrapper around ldif_read() for reading from const char*
 
707
*/
 
708
struct ldif_read_string_state {
 
709
        const char *s;
 
710
};
 
711
 
 
712
static int fgetc_string(void *private_data)
 
713
{
 
714
        struct ldif_read_string_state *state =
 
715
                (struct ldif_read_string_state *)private_data;
 
716
        if (state->s[0] != 0) {
 
717
                return *state->s++;
 
718
        }
 
719
        return EOF;
 
720
}
 
721
 
 
722
struct ldb_ldif *ldb_ldif_read_string(struct ldb_context *ldb, const char **s)
 
723
{
 
724
        struct ldif_read_string_state state;
 
725
        struct ldb_ldif *ldif;
 
726
        state.s = *s;
 
727
        ldif = ldb_ldif_read(ldb, fgetc_string, &state);
 
728
        *s = state.s;
 
729
        return ldif;
 
730
}
 
731
 
 
732
 
 
733
/*
 
734
  wrapper around ldif_write() for a file
 
735
*/
 
736
struct ldif_write_file_state {
 
737
        FILE *f;
 
738
};
 
739
 
 
740
static int fprintf_file(void *private_data, const char *fmt, ...) PRINTF_ATTRIBUTE(2, 3);
 
741
 
 
742
static int fprintf_file(void *private_data, const char *fmt, ...)
 
743
{
 
744
        struct ldif_write_file_state *state =
 
745
                (struct ldif_write_file_state *)private_data;
 
746
        int ret;
 
747
        va_list ap;
 
748
 
 
749
        va_start(ap, fmt);
 
750
        ret = vfprintf(state->f, fmt, ap);
 
751
        va_end(ap);
 
752
        return ret;
 
753
}
 
754
 
 
755
int ldb_ldif_write_file(struct ldb_context *ldb, FILE *f, const struct ldb_ldif *ldif)
 
756
{
 
757
        struct ldif_write_file_state state;
 
758
        state.f = f;
 
759
        return ldb_ldif_write(ldb, fprintf_file, &state, ldif);
 
760
}