#!/usr/bin/ruby -w
#
# $Id: pr_ctl,v 1.2 2005/02/19 17:13:50 ianmacd Exp $
#
# Program to demonstrate the use of the LDAPv3 PagedResults control. This
# control is interesting, because it requires the passing of controls in
# both directions between the client and the server.
#
# See RFC 2696 for more information.

require 'ldap'
require 'ldap/control'

# Find a PagedResults control in an Array of LDAP controls.
#
def paged_results_ctl( ctls )
  ctls.each do |ctl|
    return ctl if ctl.oid == LDAP::LDAP_CONTROL_PAGEDRESULTS
  end

  nil
end
 
unless ARGV[0]
  $stderr.puts "Please give a page size."
  exit
end
page_size = ARGV[0].to_i
cookie = ''
critical = true

conn = LDAP::Conn.new( 'localhost', 389 )
conn.set_option( LDAP::LDAP_OPT_PROTOCOL_VERSION, 3 )
conn.bind( '', '' )

search = 0
total = 0

loop do
  ber_string = LDAP::Control.encode( page_size, cookie )
  control = LDAP::Control.new( LDAP::LDAP_CONTROL_PAGEDRESULTS,
			       ber_string,
			       critical )
  conn.set_option( LDAP::LDAP_OPT_SERVER_CONTROLS, [control] )

  count = 0
  conn.search( 'dc=localhost,dc=localdomain',
               LDAP::LDAP_SCOPE_SUBTREE, '(objectclass=*)', ['cn']) do |x|
    count += 1
  end

  printf( "Page %d has %d entries.\n", search += 1, count )
  printf( "That's %d entries in total.\n", total += count )
  
  # Get the PagedResults control from the list of controls set by the
  # last search operation.
  control = paged_results_ctl( conn.controls )
  
  # How many entries does the server estimate are left?
  # Also, get the cookie returned by the last search.
  returned_size, cookie = control.decode
  puts "Returned size = #{returned_size}" if $DEBUG
  
  # According to RFC 2696, the server may not be able to estimate the number
  # of results outstanding. In that case, it will return zero, so we should
  # only use the new size if it is non-zero.
  page_size = returned_size if returned_size > 0
  
  puts "Returned cookie = #{cookie.inspect}" if $DEBUG

  break if cookie.empty?
  
  puts
end
