]> git.sur5r.net Git - openldap/commitdiff
Add VLV support
authorHoward Chu <hyc@openldap.org>
Mon, 13 Jul 2009 12:41:02 +0000 (12:41 +0000)
committerHoward Chu <hyc@openldap.org>
Mon, 13 Jul 2009 12:41:02 +0000 (12:41 +0000)
clients/tools/common.c
clients/tools/common.h
clients/tools/ldapsearch.c

index 0728b684949cf9aa17c3875ee22f7b5e723b45c2..5185a699dace9d778478c25c3b3e1d813030a078 100644 (file)
@@ -121,6 +121,9 @@ static int  chainingContinuation = -1;
 static int     sessionTracking = 0;
 struct berval  stValue;
 #endif /* LDAP_CONTROL_X_SESSION_TRACKING */
+ber_int_t vlvPos;
+ber_int_t vlvCount;
+struct berval *vlvContext;
 
 LDAPControl    *unknown_ctrls = NULL;
 int            unknown_ctrls_num = 0;
@@ -137,6 +140,7 @@ static int print_paged_results( LDAP *ld, LDAPControl *ctrl );
 static int print_ppolicy( LDAP *ld, LDAPControl *ctrl );
 #endif
 static int print_sss( LDAP *ld, LDAPControl *ctrl );
+static int print_vlv( LDAP *ld, LDAPControl *ctrl );
 #ifdef LDAP_CONTROL_X_DEREF
 static int print_deref( LDAP *ld, LDAPControl *ctrl );
 #endif
@@ -156,6 +160,7 @@ static struct tool_ctrls_t {
        { LDAP_CONTROL_PASSWORDPOLICYRESPONSE,          TOOL_ALL,       print_ppolicy },
 #endif
        { LDAP_CONTROL_SORTRESPONSE,    TOOL_SEARCH,    print_sss },
+       { LDAP_CONTROL_VLVRESPONSE,             TOOL_SEARCH,    print_vlv },
 #ifdef LDAP_CONTROL_X_DEREF
        { LDAP_CONTROL_X_DEREF,                         TOOL_SEARCH,    print_deref },
 #endif
@@ -1951,6 +1956,46 @@ print_sss( LDAP *ld, LDAPControl *ctrl )
        return rc;
 }
 
+static int
+print_vlv( LDAP *ld, LDAPControl *ctrl )
+{
+       int rc;
+       ber_int_t err;
+       struct berval bv;
+
+       rc = ldap_parse_vlvresponse_control( ld, ctrl, &vlvPos, &vlvCount,
+               &vlvContext, &err );
+       if ( rc == LDAP_SUCCESS ) {
+               char buf[ BUFSIZ ];
+
+               if ( vlvContext && vlvContext->bv_len > 0 ) {
+                       bv.bv_len = LUTIL_BASE64_ENCODE_LEN(
+                               vlvContext->bv_len ) + 1;
+                       bv.bv_val = ber_memalloc( bv.bv_len + 1 );
+
+                       bv.bv_len = lutil_b64_ntop(
+                               (unsigned char *) vlvContext->bv_val,
+                               vlvContext->bv_len,
+                               bv.bv_val, bv.bv_len );
+               } else {
+                       bv.bv_val = "";
+                       bv.bv_len = 0;
+               }
+
+               rc = snprintf( buf, sizeof(buf), "pos=%d count=%d context=%s (%d) %s",
+                       vlvPos, vlvCount, bv.bv_val,
+                       err, ldap_err2string(err));
+
+               if ( bv.bv_len )
+                       ber_memfree( bv.bv_val );
+
+               tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE,
+                       "vlvResult", buf, rc );
+       }
+
+       return rc;
+}
+
 #ifdef LDAP_CONTROL_X_DEREF
 static int
 print_deref( LDAP *ld, LDAPControl *ctrl )
index 2d3bf622782b802405511a17e2e65adcd9e6aad2..0ddeeed1ea385fdbd8e128420a4b69cae778a482 100644 (file)
@@ -93,6 +93,9 @@ extern struct berval  pr_cookie;
 #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
 extern int             chaining;
 #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
+extern ber_int_t       vlvPos;
+extern ber_int_t       vlvCount;
+extern struct berval   *vlvContext;
 
 /* options */
 extern struct timeval  nettimeout;
index 36be9ee9e87fc9e908aaad9a68f88a7ad764be88..629f56afa53643d48414adf0dc5d76c706585e00 100644 (file)
@@ -133,6 +133,8 @@ usage( void )
        fprintf( stderr, _("             [!]subentries[=true|false]  (RFC 3672 subentries)\n"));
        fprintf( stderr, _("             [!]sync=ro[/<cookie>]       (RFC 4533 LDAP Sync refreshOnly)\n"));
        fprintf( stderr, _("                     rp[/<cookie>][/<slimit>] (refreshAndPersist)\n"));
+       fprintf( stderr, _("             [!]vlv=<before>/<after>(/<offset>/<count>|:<value>)\n"));
+       fprintf( stderr, _("                                         (ldapv3-vlv-09 virtual list views)\n"));
 #ifdef LDAP_CONTROL_X_DEREF
        fprintf( stderr, _("             [!]deref=derefAttr:attr[,...][;derefAttr:attr[,...][;...]]\n"));
 #endif
@@ -207,6 +209,10 @@ static int domainScope = 0;
 static int sss = 0;
 static LDAPSortKey **sss_keys = NULL;
 
+static int vlv = 0;
+static LDAPVLVInfo vlvInfo;
+static struct berval vlvValue;
+
 static int ldapsync = 0;
 static struct berval sync_cookie = { 0, NULL };
 static int sync_slimit = -1;
@@ -263,6 +269,47 @@ urlize(char *url)
        }
 }
 
+static int
+parse_vlv(char *cvalue)
+{
+       char *keyp, *key2;
+       int num1, num2;
+
+       keyp = cvalue;
+       if ( sscanf( keyp, "%d/%d", &num1, &num2 ) != 2 ) {
+               fprintf( stderr,
+                       _("VLV control value \"%s\" invalid\n"),
+                       cvalue );
+               return -1;
+       }
+       vlvInfo.ldvlv_before_count = num1;
+       vlvInfo.ldvlv_after_count = num2;
+       keyp = strchr( keyp, '/' ) + 1;
+       key2 = strchr( keyp, '/' );
+       if ( key2 ) {
+               keyp = key2 + 1;
+               if ( sscanf( keyp, "%d/%d", &num1, &num2 ) != 2 ) {
+                       fprintf( stderr,
+                               _("VLV control value \"%s\" invalid\n"),
+                               cvalue );
+                       return -1;
+               }
+               vlvInfo.ldvlv_offset = num1;
+               vlvInfo.ldvlv_count = num2;
+               vlvInfo.ldvlv_attrvalue = NULL;
+       } else {
+               key2 = strchr( keyp, ':' );
+               if ( !key2 ) {
+                       fprintf( stderr,
+                               _("VLV control value \"%s\" invalid\n"),
+                               cvalue );
+                       return -1;
+               }
+               ber_str2bv( key2+1, 0, 0, &vlvValue );
+               vlvInfo.ldvlv_attrvalue = &vlvValue;
+       }
+       return 0;
+}
 
 const char options[] = "a:Ab:cE:F:l:Ls:S:tT:uz:"
        "Cd:D:e:f:h:H:IMnNO:o:p:P:QR:U:vVw:WxX:y:Y:Z";
@@ -343,6 +390,11 @@ handle_private_option( int i )
                                        _("PagedResultsControl previously specified\n") );
                                exit( EXIT_FAILURE );
                        }
+                       if ( vlv != 0 ) {
+                               fprintf( stderr,
+                                       _("PagedResultsControl incompatible with VLV\n") );
+                               exit( EXIT_FAILURE );
+                       }
 
                        if( cvalue != NULL ) {
                                char *promptp;
@@ -500,6 +552,27 @@ handle_private_option( int i )
                        }
                        if ( crit ) ldapsync *= -1;
 
+               } else if ( strcasecmp( control, "vlv" ) == 0 ) {
+                       if( vlv ) {
+                               fprintf( stderr,
+                                       _("virtual list view control previously specified\n"));
+                               exit( EXIT_FAILURE );
+                       }
+                       if ( pagedResults != 0 ) {
+                               fprintf( stderr,
+                                       _("PagedResultsControl incompatible with VLV\n") );
+                               exit( EXIT_FAILURE );
+                       }
+                       if( cvalue == NULL ) {
+                               fprintf( stderr,
+                                _("missing specification of vlv control\n") );
+                               exit( EXIT_FAILURE );
+                       }
+                       if ( parse_vlv( cvalue ))
+                               exit( EXIT_FAILURE );
+
+                       vlv = 1 + crit;
+
 #ifdef LDAP_CONTROL_X_DEREF
                } else if ( strcasecmp( control, "deref" ) == 0 ) {
                        int ispecs;
@@ -758,6 +831,12 @@ main( int argc, char **argv )
 
        tool_args( argc, argv );
 
+       if ( vlv && !sss ) {
+               fprintf( stderr,
+                       _("VLV control requires server side sort control\n" ));
+               return EXIT_FAILURE;
+       }
+
        if (( argc - optind < 1 ) ||
                ( *argv[optind] != '(' /*')'*/ &&
                ( strchr( argv[optind], '=' ) == NULL ) ) )
@@ -853,7 +932,8 @@ getNextPage:
                || ldapsync
                || sss
                || subentries
-               || valuesReturnFilter )
+               || valuesReturnFilter
+               || vlv )
        {
 
 #ifdef LDAP_CONTROL_DONTUSECOPY
@@ -1001,6 +1081,21 @@ getNextPage:
                        i++;
                }
 
+               if ( vlv ) {
+                       if ( ctrl_add() ) {
+                               return EXIT_FAILURE;
+                       }
+
+                       if ( ldap_create_vlv_control_value( ld,
+                               &vlvInfo, &c[i].ldctl_value ) )
+                       {
+                               return EXIT_FAILURE;
+                       }
+
+                       c[i].ldctl_oid = LDAP_CONTROL_VLVREQUEST;
+                       c[i].ldctl_iscritical = sss > 1;
+                       i++;
+               }
 #ifdef LDAP_CONTROL_X_DEREF
                if ( derefcrit ) {
                        if ( derefval.bv_val == NULL ) {
@@ -1116,6 +1211,15 @@ getNextPage:
                        printf(_("\n# with server side sorting %scontrol"),
                                sss > 1 ? _("critical ") : "" );
                }
+               if ( vlv ) {
+                       printf(_("\n# with virtual list view %scontrol: %d/%d"),
+                               vlv > 1 ? _("critical ") : "",
+                               vlvInfo.ldvlv_before_count, vlvInfo.ldvlv_after_count);
+                       if ( vlvInfo.ldvlv_attrvalue )
+                               printf(":%s", vlvInfo.ldvlv_attrvalue->bv_val );
+                       else
+                               printf("/%d/%d", vlvInfo.ldvlv_offset, vlvInfo.ldvlv_count );
+               }
 #ifdef LDAP_CONTROL_X_DEREF
                if ( derefcrit ) {
                        printf(_("\n# with dereference %scontrol"),
@@ -1159,7 +1263,7 @@ getNextPage:
        }
 
        if (( rc == LDAP_SUCCESS ) && pageSize && pr_morePagedResults ) {
-               char    buf[6];
+               char    buf[12];
                int     i, moreEntries, tmpSize;
 
                /* Loop to get the next pages when 
@@ -1197,6 +1301,41 @@ getNextPage:
                goto getNextPage;
        }
 
+       if (( rc == LDAP_SUCCESS ) && vlv ) {
+               char    buf[BUFSIZ];
+               int     i, moreEntries, tmpSize;
+
+               /* Loop to get the next window when 
+                * enter is pressed on the terminal.
+                */
+               printf( _("Press [before/after(/offset/count|:value)] Enter for the next window.\n"));
+               i = 0;
+               moreEntries = getchar();
+               while ( moreEntries != EOF && moreEntries != '\n' ) { 
+                       if ( i < (int)sizeof(buf) - 1 ) {
+                               buf[i] = moreEntries;
+                               i++;
+                       }
+                       moreEntries = getchar();
+               }
+               buf[i] = '\0';
+               if ( buf[0] ) {
+                       i = parse_vlv( strdup( buf ));
+                       if ( i )
+                               return EXIT_FAILURE;
+               } else {
+                       vlvInfo.ldvlv_attrvalue = NULL;
+                       vlvInfo.ldvlv_count = vlvCount;
+                       vlvInfo.ldvlv_offset += vlvInfo.ldvlv_after_count;
+               }
+
+               if ( vlvInfo.ldvlv_context )
+                       ber_bvfree( vlvInfo.ldvlv_context );
+               vlvInfo.ldvlv_context = vlvContext;
+
+               goto getNextPage;
+       }
+
        tool_unbind( ld );
        tool_destroy();
        if ( base != NULL ) {