UNPKG

4.2 kBJavaScriptView Raw
1// Copyright 2011 Mark Cavage, Inc. All rights reserved.
2
3const assert = require('assert-plus')
4const util = require('util')
5
6const LDAPResult = require('./result')
7const SearchEntry = require('./search_entry')
8const SearchReference = require('./search_reference')
9
10const dtrace = require('../dtrace')
11const parseDN = require('../dn').parse
12const parseURL = require('../url').parse
13const Protocol = require('../protocol')
14
15/// --- API
16
17function SearchResponse (options) {
18 options = options || {}
19 assert.object(options)
20
21 options.protocolOp = Protocol.LDAP_REP_SEARCH
22 LDAPResult.call(this, options)
23
24 this.attributes = options.attributes ? options.attributes.slice() : []
25 this.notAttributes = []
26 this.sentEntries = 0
27}
28util.inherits(SearchResponse, LDAPResult)
29
30/**
31 * Allows you to send a SearchEntry back to the client.
32 *
33 * @param {Object} entry an instance of SearchEntry.
34 * @param {Boolean} nofiltering skip filtering notAttributes and '_' attributes.
35 * Defaults to 'false'.
36 */
37SearchResponse.prototype.send = function (entry, nofiltering) {
38 if (!entry || typeof (entry) !== 'object') { throw new TypeError('entry (SearchEntry) required') }
39 if (nofiltering === undefined) { nofiltering = false }
40 if (typeof (nofiltering) !== 'boolean') { throw new TypeError('noFiltering must be a boolean') }
41
42 const self = this
43
44 const savedAttrs = {}
45 let save = null
46 if (entry instanceof SearchEntry || entry instanceof SearchReference) {
47 if (!entry.messageID) { entry.messageID = this.messageID }
48 if (entry.messageID !== this.messageID) { throw new Error('SearchEntry messageID mismatch') }
49 } else {
50 if (!entry.attributes) { throw new Error('entry.attributes required') }
51
52 const all = (self.attributes.indexOf('*') !== -1)
53 Object.keys(entry.attributes).forEach(function (a) {
54 const _a = a.toLowerCase()
55 if (!nofiltering && _a.length && _a[0] === '_') {
56 savedAttrs[a] = entry.attributes[a]
57 delete entry.attributes[a]
58 } else if (!nofiltering && self.notAttributes.indexOf(_a) !== -1) {
59 savedAttrs[a] = entry.attributes[a]
60 delete entry.attributes[a]
61 } else if (all) {
62 // do nothing
63 } else if (self.attributes.length && self.attributes.indexOf(_a) === -1) {
64 savedAttrs[a] = entry.attributes[a]
65 delete entry.attributes[a]
66 }
67 })
68
69 save = entry
70 entry = new SearchEntry({
71 objectName: typeof (save.dn) === 'string' ? parseDN(save.dn) : save.dn,
72 messageID: self.messageID,
73 log: self.log
74 })
75 entry.fromObject(save)
76 }
77
78 try {
79 this.log.debug('%s: sending: %j', this.connection.ldap.id, entry.json)
80
81 this.connection.write(entry.toBer())
82 this.sentEntries++
83
84 if (self._dtraceOp && self._dtraceId) {
85 dtrace.fire('server-search-entry', function () {
86 const c = self.connection || { ldap: {} }
87 return [
88 self._dtraceId || 0,
89 (c.remoteAddress || ''),
90 c.ldap.bindDN ? c.ldap.bindDN.toString() : '',
91 (self.requestDN ? self.requestDN.toString() : ''),
92 entry.objectName.toString(),
93 entry.attributes.length
94 ]
95 })
96 }
97
98 // Restore attributes
99 Object.keys(savedAttrs).forEach(function (k) {
100 save.attributes[k] = savedAttrs[k]
101 })
102 } catch (e) {
103 this.log.warn(e, '%s failure to write message %j',
104 this.connection.ldap.id, this.json)
105 }
106}
107
108SearchResponse.prototype.createSearchEntry = function (object) {
109 assert.object(object)
110
111 const entry = new SearchEntry({
112 messageID: this.messageID,
113 log: this.log,
114 objectName: object.objectName || object.dn
115 })
116 entry.fromObject((object.attributes || object))
117 return entry
118}
119
120SearchResponse.prototype.createSearchReference = function (uris) {
121 if (!uris) { throw new TypeError('uris ([string]) required') }
122
123 if (!Array.isArray(uris)) { uris = [uris] }
124
125 for (let i = 0; i < uris.length; i++) {
126 if (typeof (uris[i]) === 'string') { uris[i] = parseURL(uris[i]) }
127 }
128
129 const self = this
130 return new SearchReference({
131 messageID: self.messageID,
132 log: self.log,
133 uris: uris
134 })
135}
136
137/// --- Exports
138
139module.exports = SearchResponse