r12833: complete ldbsearch support for controls
authorSimo Sorce <idra@samba.org>
Tue, 10 Jan 2006 17:19:32 +0000 (17:19 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:50:04 +0000 (13:50 -0500)
now the three supported controls (paged_results,
server_sort, extended_dn) are fully functional
and the infrastructure to add more is in place.

valgrind is happy too :)

Simo.
(This used to be commit bd8e2629378700198e16287823970f52d1150a86)

source4/lib/ldb/tools/cmdline.c
source4/lib/ldb/tools/ldbsearch.c

index 9b24b83239cb7f21660538b9a6588ad4a97081e5..ee9e5f5e47b37ab144ca2059abc6d798a3105ed5 100644 (file)
@@ -141,10 +141,10 @@ struct ldb_cmdline *ldb_cmdline_process(struct ldb_context *ldb, int argc, const
 
                case 'c': {
                        const char *cs = poptGetOptArg(pc);
-                       const char *p;
+                       const char *p, *q;
                        int cc;
 
-                       for (p = cs, cc = 1; (p = strchr(p, ',')); cc++) ;
+                       for (p = cs, cc = 1; (q = strchr(p, ',')); cc++, p = q + 1) ;
 
                        options.controls = talloc_array(ret, char *, cc + 1);
                        if (options.controls == NULL) {
@@ -163,7 +163,7 @@ struct ldb_cmdline *ldb_cmdline_process(struct ldb_context *ldb, int argc, const
                                        p = t + 1;
                                }
                        }
-                       options.controls[cc + 1] = NULL;
+                       options.controls[cc] = NULL;
 
                        break;    
                }
index 4ce974c6fa4acf382f2b6d3c8caa2692bf9cd2ce..46a67ad324812f6f2ab9432e7612fa09828f40f4 100644 (file)
@@ -125,6 +125,8 @@ static struct ldb_control **parse_controls(void *mem_ctx, char **control_strings
                        char rule[128];
                        int crit, rev, ret;
 
+                       attr[0] = '\0';
+                       rule[0] = '\0';
                        p = &(control_strings[i][12]);
                        ret = sscanf(p, "%d:%d:%255[^:]:%127[^:]", &crit, &rev, attr, rule);
                        if ((ret < 3) || (crit < 0) || (crit > 1) || (rev < 0 ) || (rev > 1) ||attr[0] == '\0') {
@@ -137,7 +139,10 @@ static struct ldb_control **parse_controls(void *mem_ctx, char **control_strings
                        control = talloc_array(ctrl[i], struct ldb_server_sort_control *, 2);
                        control[0] = talloc(control, struct ldb_server_sort_control);
                        control[0]->attributeName = talloc_strdup(control, attr);
-                       control[0]->orderingRule = talloc_strdup(control, rule);
+                       if (rule[0])
+                               control[0]->orderingRule = talloc_strdup(control, rule);
+                       else
+                               control[0]->orderingRule = NULL;
                        control[0]->reverse = rev;
                        control[1] = NULL;
                        ctrl[i]->data = control;
@@ -150,11 +155,90 @@ static struct ldb_control **parse_controls(void *mem_ctx, char **control_strings
                return NULL;
        }
 
-       ctrl[i + 1] = NULL;
+       ctrl[i] = NULL;
 
        return ctrl;
 }
 
+/* this function check controls reply and determines if more
+ * processing is needed setting up the request controls correctly
+ *
+ * returns:
+ *     -1 error
+ *     0 all ok
+ *     1 all ok, more processing required
+ */
+static int handle_controls_reply(struct ldb_control **reply, struct ldb_control **request)
+{
+       int i, j;
+               int ret = 0;
+
+       if (reply == NULL || request == NULL) return -1;
+       
+       for (i = 0; reply[i]; i++) {
+               if (strcmp(LDB_CONTROL_PAGED_RESULTS_OID, reply[i]->oid) == 0) {
+                       struct ldb_paged_control *rep_control, *req_control;
+
+                       rep_control = talloc_get_type(reply[i]->data, struct ldb_paged_control);
+                       if (rep_control->cookie_len == 0) /* we are done */
+                               break;
+
+                       /* more processing required */
+                       /* let's fill in the request control with the new cookie */
+
+                       for (j = 0; request[j]; j++) {
+                               if (strcmp(LDB_CONTROL_PAGED_RESULTS_OID, request[j]->oid) == 0)
+                                       break;
+                       }
+                       /* if there's a reply control we must find a request
+                        * control matching it */
+                       if (! request[j]) return -1;
+
+                       req_control = talloc_get_type(request[j]->data, struct ldb_paged_control);
+
+                       if (req_control->cookie)
+                               talloc_free(req_control->cookie);
+                       req_control->cookie = talloc_memdup(req_control,
+                                                           rep_control->cookie,
+                                                           rep_control->cookie_len);
+                       req_control->cookie_len = rep_control->cookie_len;
+
+                       ret = 1;
+
+                       continue;
+               }
+
+               if (strcmp(LDB_CONTROL_SORT_RESP_OID, reply[i]->oid) == 0) {
+                       struct ldb_sort_resp_control *rep_control;
+
+                       rep_control = talloc_get_type(reply[i]->data, struct ldb_sort_resp_control);
+
+                       /* check we have a matching control in the request */
+                       for (j = 0; request[j]; j++) {
+                               if (strcmp(LDB_CONTROL_SERVER_SORT_OID, request[j]->oid) == 0)
+                                       break;
+                       }
+                       if (! request[j]) {
+                               fprintf(stderr, "Warning Server Sort reply received but no request found\n");
+                               continue;
+                       }
+
+                       /* check the result */
+                       if (rep_control->result != 0) {
+                               fprintf(stderr, "Warning: Sorting not performed with error: %d\n", rep_control->result);
+                       }
+
+                       continue;
+               }
+
+               /* no controls matched, throw a warning */
+               fprintf(stderr, "Unknown reply control oid: %s\n", reply[i]->oid);
+       }
+
+       return ret;
+}
+
+
 static int do_search(struct ldb_context *ldb,
                     const struct ldb_dn *basedn,
                     struct ldb_cmdline *options,
@@ -162,6 +246,8 @@ static int do_search(struct ldb_context *ldb,
                     const char * const *attrs)
 {
        int ret, i;
+       int loop = 0;
+       int total = 0;
        struct ldb_request req;
        struct ldb_result *result = NULL;
 
@@ -175,46 +261,58 @@ static int do_search(struct ldb_context *ldb,
        if (options->controls != NULL && req.controls == NULL) return -1;
        req.creds = NULL;
 
-       ret = ldb_request(ldb, &req);
-       if (ret != LDB_SUCCESS) {
-               printf("search failed - %s\n", ldb_errstring(ldb));
-               return -1;
-       }
+       do {
+               loop = 0;
+
+               ret = ldb_request(ldb, &req);
+               if (ret != LDB_SUCCESS) {
+                       printf("search failed - %s\n", ldb_errstring(ldb));
+                       return -1;
+               }
 
-       result = req.op.search.res;
-       printf("# returned %d records\n", ret);
+               result = req.op.search.res;
+               printf("# returned %d records\n", result->count);
 
-       if (options->sorted) {
-               ldb_qsort(result->msgs, ret, sizeof(struct ldb_message *),
-                         ldb, (ldb_qsort_cmp_fn_t)do_compare_msg);
-       }
+               if (options->sorted) {
+                       ldb_qsort(result->msgs, ret, sizeof(struct ldb_message *),
+                                 ldb, (ldb_qsort_cmp_fn_t)do_compare_msg);
+               }
 
-       for (i = 0; i < result->count; i++) {
-               struct ldb_ldif ldif;
-               printf("# record %d\n", i+1);
-
-               ldif.changetype = LDB_CHANGETYPE_NONE;
-               ldif.msg = result->msgs[i];
-
-                if (options->sorted) {
-                        /*
-                         * Ensure attributes are always returned in the same
-                         * order.  For testing, this makes comparison of old
-                         * vs. new much easier.
-                         */
-                        ldb_msg_sort_elements(ldif.msg);
-                }
-                
-               ldb_ldif_write_file(ldb, stdout, &ldif);
-       }
+               for (i = 0; i < result->count; i++, total++) {
+                       struct ldb_ldif ldif;
+                       printf("# record %d\n", total + 1);
+
+                       ldif.changetype = LDB_CHANGETYPE_NONE;
+                       ldif.msg = result->msgs[i];
+
+                       if (options->sorted) {
+                               /*
+                                * Ensure attributes are always returned in the same
+                                * order.  For testing, this makes comparison of old
+                                * vs. new much easier.
+                                */
+                               ldb_msg_sort_elements(ldif.msg);
+                       }
+       
+                       ldb_ldif_write_file(ldb, stdout, &ldif);
+               }
 
-       if (result) {
-               ret = talloc_free(result);
-               if (ret == -1) {
-                       fprintf(stderr, "talloc_free failed\n");
-                       exit(1);
+               if (result->controls) {
+                       if (handle_controls_reply(result->controls, req.controls) == 1)
+                               loop = 1;
                }
-       }
+
+               if (result) {
+                       ret = talloc_free(result);
+                       if (ret == -1) {
+                               fprintf(stderr, "talloc_free failed\n");
+                               exit(1);
+                       }
+               }
+
+               req.op.search.res = NULL;
+               
+       } while(loop);
 
        return 0;
 }