]> git.deb.at Git - pkg/abook.git/commitdiff
ldif: support parsing from stdin
authorRaphaël Droz <raphael.droz+floss@gmail.com>
Thu, 13 Dec 2012 15:47:00 +0000 (16:47 +0100)
committerRaphaël Droz <raphael.droz+floss@gmail.com>
Thu, 13 Dec 2012 16:05:15 +0000 (17:05 +0100)
ldif parser used to seek in the file handler to grab multi-line
 strings, thus creating buggy records when input was stdin.
It now reads-ahead the next line in order to work consistently with
 unseekable streams like stdin.

filter.c

index 520d4ceddd5b1f248505667274dec44503145c28..e928492e596ffeddc69d0c8c380a73d8978e97b9 100644 (file)
--- a/filter.c
+++ b/filter.c
@@ -547,35 +547,42 @@ static int ldif_conv_table[LDIF_ITEM_FIELDS] = {
        -1,             /* "objectclass" */ /* this must be the last entry */
 };
 
-
+/*
+  Handles multi-line strings.
+  If a string starts with a space, it's the continuation
+  of the previous line. Thus we need to always read ahead.
+  But for this to work with stdin, we need to stores the next
+  line for later use in case it's not a continuation of the
+  first line.
+ */
 static char *
-ldif_read_line(FILE *in)
+ldif_read_line(FILE *in, char **next_line)
 {
        char *buf = NULL;
        char *ptr, *tmp;
-       long pos;
-       int i;
+       char *line;
 
-       for(i = 1;;i++) {
-               char *line;
+       // buf filled with the first line
+       if(!*next_line)
+               buf = getaline(in);
+       else {
+               buf = xstrdup(*next_line);
+               xfree(*next_line);
+       }
 
-               pos = ftell(in);
+       while(!feof(in)) {
+               // if no line already read-ahead.
                line = getaline(in);
+               if(!line) break;
 
-               if(feof(in) || !line)
-                       break;
-
-               if(i == 1) {
-                       buf = line;
-                       continue;
-               }
-
+               // this is not a continuation of what is already in buf
+               // store it for the next round
                if(*line != ' ') {
-                       fseek(in, pos, SEEK_SET); /* fixme ! */
-                       free(line);
+                       *next_line = line;
                        break;
                }
 
+               // starts with ' ': this is the continuation of buf
                ptr = line;
                while( *ptr == ' ')
                        ptr++;
@@ -642,6 +649,7 @@ static int
 ldif_parse_file(FILE *handle)
 {
        char *line = NULL;
+       char *next_line = NULL;
        char *type, *value;
        int vlen;
        ldif_item item;
@@ -649,8 +657,10 @@ ldif_parse_file(FILE *handle)
        memset(item, 0, sizeof(item));
 
        do {
-               if( !(line = ldif_read_line(handle)) )
-                       continue;
+               line = ldif_read_line(handle, &next_line);
+
+               // EOF or empty lines: continue;
+               if(!line || *line == '\0') continue;
 
                if(-1 == (str_parse_line(line, &type, &value, &vlen))) {
                        xfree(line);