Skip to content
This repository was archived by the owner on May 14, 2024. It is now read-only.

Commit eb4f665

Browse files
authored
Merge pull request #553 from Worteks/next-vls-controls
Added support for Virtual List View (vlv) control for browsing directory using paged search
2 parents dd2a722 + fa6ffb4 commit eb4f665

7 files changed

+587
-1
lines changed

lib/controls/index.js

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ var ServerSideSortingRequestControl =
1212
require('./server_side_sorting_request_control.js')
1313
var ServerSideSortingResponseControl =
1414
require('./server_side_sorting_response_control.js')
15+
var VirtualListViewRequestControl =
16+
require('./virtual_list_view_request_control.js')
17+
var VirtualListViewResponseControl =
18+
require('./virtual_list_view_response_control.js')
1519

1620
/// --- API
1721

@@ -56,6 +60,12 @@ module.exports = {
5660
case ServerSideSortingResponseControl.OID:
5761
control = new ServerSideSortingResponseControl(opts)
5862
break
63+
case VirtualListViewRequestControl.OID:
64+
control = new VirtualListViewRequestControl(opts)
65+
break
66+
case VirtualListViewResponseControl.OID:
67+
control = new VirtualListViewResponseControl(opts)
68+
break
5969
default:
6070
opts.type = type
6171
control = new Control(opts)
@@ -70,5 +80,7 @@ module.exports = {
7080
PagedResultsControl: PagedResultsControl,
7181
PersistentSearchControl: PersistentSearchControl,
7282
ServerSideSortingRequestControl: ServerSideSortingRequestControl,
73-
ServerSideSortingResponseControl: ServerSideSortingResponseControl
83+
ServerSideSortingResponseControl: ServerSideSortingResponseControl,
84+
VirtualListViewRequestControl: VirtualListViewRequestControl,
85+
VirtualListViewResponseControl: VirtualListViewResponseControl
7486
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
var assert = require('assert-plus')
2+
var util = require('util')
3+
4+
var asn1 = require('asn1')
5+
6+
var Control = require('./control')
7+
8+
/// --- Globals
9+
10+
var BerReader = asn1.BerReader
11+
var BerWriter = asn1.BerWriter
12+
13+
/// --- API
14+
15+
function VirtualListViewControl (options) {
16+
assert.optionalObject(options)
17+
options = options || {}
18+
options.type = VirtualListViewControl.OID
19+
if (options.value) {
20+
if (Buffer.isBuffer(options.value)) {
21+
this.parse(options.value)
22+
} else if (typeof (options.value) === 'object') {
23+
if (Object.prototype.hasOwnProperty.call(options.value, 'beforeCount') === false) {
24+
throw new Error('Missing required key: beforeCount')
25+
}
26+
if (Object.prototype.hasOwnProperty.call(options.value, 'afterCount') === false) {
27+
throw new Error('Missing required key: afterCount')
28+
}
29+
this._value = options.value
30+
} else {
31+
throw new TypeError('options.value must be a Buffer or Object')
32+
}
33+
options.value = null
34+
}
35+
Control.call(this, options)
36+
}
37+
util.inherits(VirtualListViewControl, Control)
38+
Object.defineProperties(VirtualListViewControl.prototype, {
39+
value: {
40+
get: function () { return this._value || [] },
41+
configurable: false
42+
}
43+
})
44+
45+
VirtualListViewControl.prototype.parse = function parse (buffer) {
46+
assert.ok(buffer)
47+
var ber = new BerReader(buffer)
48+
if (ber.readSequence()) {
49+
this._value = {}
50+
this._value.beforeCount = ber.readInt()
51+
this._value.afterCount = ber.readInt()
52+
if (ber.peek() === 0xa0) {
53+
if (ber.readSequence(0xa0)) {
54+
this._value.targetOffset = ber.readInt()
55+
this._value.contentCount = ber.readInt()
56+
}
57+
}
58+
if (ber.peek() === 0x81) {
59+
this._value.greaterThanOrEqual = ber.readString(0x81)
60+
}
61+
return true
62+
}
63+
return false
64+
}
65+
66+
VirtualListViewControl.prototype._toBer = function (ber) {
67+
assert.ok(ber)
68+
if (!this._value || this.value.length === 0) {
69+
return
70+
}
71+
var writer = new BerWriter()
72+
writer.startSequence(0x30)
73+
writer.writeInt(this.value.beforeCount)
74+
writer.writeInt(this.value.afterCount)
75+
if (this.value.targetOffset !== undefined) {
76+
writer.startSequence(0xa0)
77+
writer.writeInt(this.value.targetOffset)
78+
writer.writeInt(this.value.contentCount)
79+
writer.endSequence()
80+
} else if (this.value.greaterThanOrEqual !== undefined) {
81+
writer.writeString(this.value.greaterThanOrEqual, 0x81)
82+
}
83+
writer.endSequence()
84+
ber.writeBuffer(writer.buffer, 0x04)
85+
}
86+
VirtualListViewControl.prototype._json = function (obj) {
87+
obj.controlValue = this.value
88+
return obj
89+
}
90+
VirtualListViewControl.OID = '2.16.840.1.113730.3.4.9'
91+
92+
/// ---Exports
93+
94+
module.exports = VirtualListViewControl
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
var assert = require('assert-plus')
2+
var util = require('util')
3+
4+
var asn1 = require('asn1')
5+
6+
var Control = require('./control')
7+
var CODES = require('../errors/codes')
8+
9+
/// --- Globals
10+
11+
var BerReader = asn1.BerReader
12+
var BerWriter = asn1.BerWriter
13+
14+
var VALID_CODES = [
15+
CODES.LDAP_SUCCESS,
16+
CODES.LDAP_OPERATIONS_ERROR,
17+
CODES.LDAP_UNWILLING_TO_PERFORM,
18+
CODES.LDAP_INSUFFICIENT_ACCESS_RIGHTS,
19+
CODES.LDAP_BUSY,
20+
CODES.LDAP_TIME_LIMIT_EXCEEDED,
21+
CODES.LDAP_ADMIN_LIMIT_EXCEEDED,
22+
CODES.LDAP_SORT_CONTROL_MISSING,
23+
CODES.LDAP_INDEX_RANGE_ERROR,
24+
CODES.LDAP_CONTROL_ERROR,
25+
CODES.LDAP_OTHER
26+
]
27+
28+
function VirtualListViewResponseControl (options) {
29+
assert.optionalObject(options)
30+
options = options || {}
31+
options.type = VirtualListViewResponseControl.OID
32+
options.criticality = false
33+
34+
if (options.value) {
35+
if (Buffer.isBuffer(options.value)) {
36+
this.parse(options.value)
37+
} else if (typeof (options.value) === 'object') {
38+
if (VALID_CODES.indexOf(options.value.result) === -1) {
39+
throw new Error('Invalid result code')
40+
}
41+
this._value = options.value
42+
} else {
43+
throw new TypeError('options.value must be a Buffer or Object')
44+
}
45+
options.value = null
46+
}
47+
Control.call(this, options)
48+
}
49+
util.inherits(VirtualListViewResponseControl, Control)
50+
Object.defineProperties(VirtualListViewResponseControl.prototype, {
51+
value: {
52+
get: function () { return this._value || {} },
53+
configurable: false
54+
}
55+
})
56+
57+
VirtualListViewResponseControl.prototype.parse = function parse (buffer) {
58+
assert.ok(buffer)
59+
var ber = new BerReader(buffer)
60+
if (ber.readSequence()) {
61+
this._value = {}
62+
if (ber.peek(0x02)) {
63+
this._value.targetPosition = ber.readInt()
64+
}
65+
if (ber.peek(0x02)) {
66+
this._value.contentCount = ber.readInt()
67+
}
68+
this._value.result = ber.readEnumeration()
69+
this._value.cookie = ber.readString(asn1.Ber.OctetString, true)
70+
// readString returns '' instead of a zero-length buffer
71+
if (!this._value.cookie) {
72+
this._value.cookie = Buffer.alloc(0)
73+
}
74+
return true
75+
}
76+
return false
77+
}
78+
79+
VirtualListViewResponseControl.prototype._toBer = function (ber) {
80+
assert.ok(ber)
81+
82+
if (!this._value || this.value.length === 0) {
83+
return
84+
}
85+
86+
var writer = new BerWriter()
87+
writer.startSequence()
88+
if (this.value.targetPosition !== undefined) {
89+
writer.writeInt(this.value.targetPosition)
90+
}
91+
if (this.value.contentCount !== undefined) {
92+
writer.writeInt(this.value.contentCount)
93+
}
94+
writer.writeEnumeration(this.value.result)
95+
if (this.value.cookie && this.value.cookie.length > 0) {
96+
writer.writeBuffer(this.value.cookie, asn1.Ber.OctetString)
97+
} else {
98+
writer.writeString('') // writeBuffer rejects zero-length buffers
99+
}
100+
writer.endSequence()
101+
ber.writeBuffer(writer.buffer, 0x04)
102+
}
103+
104+
VirtualListViewResponseControl.prototype._json = function (obj) {
105+
obj.controlValue = this.value
106+
return obj
107+
}
108+
109+
VirtualListViewResponseControl.OID = '2.16.840.1.113730.3.4.10'
110+
111+
/// --- Exports
112+
module.exports = VirtualListViewResponseControl

lib/errors/codes.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,16 @@ module.exports = {
3232
LDAP_UNAVAILABLE: 52,
3333
LDAP_UNWILLING_TO_PERFORM: 53,
3434
LDAP_LOOP_DETECT: 54,
35+
LDAP_SORT_CONTROL_MISSING: 60,
36+
LDAP_INDEX_RANGE_ERROR: 61,
3537
LDAP_NAMING_VIOLATION: 64,
3638
LDAP_OBJECTCLASS_VIOLATION: 65,
3739
LDAP_NOT_ALLOWED_ON_NON_LEAF: 66,
3840
LDAP_NOT_ALLOWED_ON_RDN: 67,
3941
LDAP_ENTRY_ALREADY_EXISTS: 68,
4042
LDAP_OBJECTCLASS_MODS_PROHIBITED: 69,
4143
LDAP_AFFECTS_MULTIPLE_DSAS: 71,
44+
LDAP_CONTROL_ERROR: 76,
4245
LDAP_OTHER: 80,
4346
LDAP_PROXIED_AUTHORIZATION_DENIED: 123
4447
}

0 commit comments

Comments
 (0)