Adaptive Framework  0.9.0
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
afw_ldap_metadata.c
Go to the documentation of this file.
1 // See the 'COPYING' file in the project root for licensing information.
2 /*
3  * Internal LDAP Adaptive Framework Adaptor functions
4  *
5  * Copyright (c) 2010-2023 Clemson University
6  *
7  */
8 
9 
15 #include "afw.h"
16 #include "afw_ldap_metadata.h"
17 
18 typedef struct impl_lexical_s {
19  const afw_pool_t *p;
20  afw_xctx_t *xctx;
21  const afw_utf8_octet_t *start;
22  const afw_utf8_octet_t *c;
23  const afw_utf8_octet_t *end;
24  const afw_utf8_z_t *tkn;
25  afw_utf8_t token;
27 
28 static const afw_object_t *
29 impl_get_rootdse(
31  const afw_pool_t *p, afw_xctx_t *xctx);
32 
33 static const afw_object_t *
34 impl_get_schema(
36  const afw_utf8_t *subschema_subentry,
37  const afw_pool_t *p, afw_xctx_t *xctx);
38 
39 
40 static const afw_object_t *
41 impl_parse_schema_entry(
42  const afw_utf8_t *name,
43  const afw_utf8_t *string,
44  const afw_pool_t *p, afw_xctx_t *xctx);
45 
46 
47 static apr_hash_t *
48 impl_parse_definition(
49  const afw_utf8_t *adaptor_id,
50  const afw_utf8_t *object_type_id,
51  const afw_utf8_t *name_in_schema,
52  afw_ldap_metadata_t *metadata,
53  afw_xctx_t *xctx);
54 
55 
56 static void
57 impl_retrieve_objects(
59  apr_hash_t *ht,
60  const afw_query_criteria_t * criteria,
61  void * context,
62  afw_object_cb_t callback,
63  afw_xctx_t *xctx);
64 
65 
66 static void
67 impl_make_property_type_and_handler_hash_tables(
68  const afw_utf8_t *adaptor_id,
69  afw_ldap_metadata_t *metadata,
70  afw_xctx_t *xctx);
71 
72 
73 static void
74 impl_make_object_types(
75  const afw_utf8_t *adaptor_id,
76  afw_ldap_metadata_t *metadata,
77  afw_xctx_t *xctx);
78 
79 
80 
81 const afw_object_t *
82 impl_get(
83  apr_hash_t *ht, const afw_utf8_t *id)
84 {
85  return apr_hash_get(ht, id->s, id->len);
86 }
87 
88 
89 
90 const afw_object_t *
91 impl_get_rootdse(
93  const afw_pool_t *p, afw_xctx_t *xctx)
94 {
95  LDAPMessage *res;
96  LDAPMessage *e;
97 
98  res = afw_ldap_internal_search_s(session, "", LDAP_SCOPE_BASE,
99  "(objectclass=*)", xctx);
100 
101  /* Get entry and return it as an adaptive object. */
102  e = ldap_first_entry(session->ld, res);
103  if (!e) {
104  AFW_THROW_ERROR_Z(general,
105  "ldap_first_entry() failed.", xctx);
106  }
107 
108  return afw_ldap_internal_create_object_from_entry(session,
109  &afw_ldap_s__AdaptiveLdapRootDse_, &afw_s_current,
110  e, p, xctx);
111 
112 }
113 
114 const afw_object_t *
115 impl_get_schema(
117  const afw_utf8_t *subschema_subentry,
118  const afw_pool_t *p, afw_xctx_t *xctx)
119 {
120  LDAPMessage *res;
121  LDAPMessage *e;
122  const afw_utf8_z_t *s;
123 
125  s = afw_utf8_z_create(subschema_subentry->s, subschema_subentry->len, p, xctx);
126 
127 
128  res = afw_ldap_internal_search_s(session, s,
129  LDAP_SCOPE_BASE, "(objectclass=*)", xctx);
130 
131  /* Get entry and return it as an adaptive object. */
132  e = ldap_first_entry(session->ld, res);
133  if (!e) {
134  AFW_THROW_ERROR_Z(general,
135  "ldap_first_entry() failed.", xctx);
136  }
137 
138  return afw_ldap_internal_create_object_from_entry(session,
139  &afw_ldap_s__AdaptiveLdapSchema_, &afw_s_current,
140  e, p, xctx);
141 }
142 
143 
144 static impl_lexical_t *
145 impl_create_lexical_analyzer(const afw_utf8_t *s,
146  const afw_pool_t *p, afw_xctx_t *xctx)
147 {
148  impl_lexical_t *self;
149 
150  self = afw_xctx_calloc_type(impl_lexical_t, xctx);
151 
152  self->start = s->s;
153  self->c = s->s;
154  self->end = s->s + s->len;
155  self->p = p;
156  self->xctx = xctx;
157 
158  return self;
159 }
160 
161 
162 static const afw_utf8_z_t *
163 impl_get_token(impl_lexical_t *self)
164 {
165  const afw_utf8_octet_t *c;
166 
167  /* Skip whitespace. */
168  for (c = self->c; c < self->end; ++c) {
169  if (*c != ' ' /*&& *c != '\t' && *c != '\n' && *c != '\r'*/) break;
170  }
171  self->c = c;
172 
173  /* Return NULL if at end of input. */
174  if (self->c >= self->end) {
175  return NULL;
176  }
177 
178  /* If it starts with an apostrophe, token is chars up to next apostrophe. */
179  if (*c == '\'') {
180  for (c = ++(self->c); c < self->end && *c != '\''; ++c);
181  if (c >= self->end) {
182  AFW_THROW_ERROR_Z(general, "Error parsing schema.", self->xctx);
183  }
184  self->token.s = self->c;
185  self->token.len = c - self->c;
186  self->tkn = afw_utf8_z_create(self->c, c - self->c,
187  self->p, self->xctx);
188  c++; /* Skip apostrophe */
189  }
190 
191  /* Else token is special characters or characters up to space or end. */
192  else {
193  if (*c == '(' || *c == ')' || *c == '$') {
194  c++;
195  } else {
196  for (c = self->c; c < self->end && *c != ' '; ++c);
197  }
198  self->token.s = self->c;
199  self->token.len = c - self->c;
200  self->tkn = afw_utf8_z_create(self->c, c - self->c,
201  self->p, self->xctx);
202  }
203 
204  self->c = c;
205  return self->tkn;
206 }
207 
208 
209 static void
210 impl_set_string(impl_lexical_t *self, afw_utf8_t *string)
211 {
212  /* If starts with single quote, parse as quoted string. */
213  if (*(self->tkn) == '\'') {
215  string->len = strlen(self->tkn);
216  if (string->len < 2) {
217  AFW_THROW_ERROR_Z(general, "Error parsing schema.", self->xctx);
218  }
219  string->len -= 2;
220  string->s = self->tkn + 1;
221  }
222 
223  /* If does not start with single quote, use value asis. */
224  else {
225  string->s = self->tkn;
226  string->len = strlen(self->tkn);
227  }
228 }
229 
230 
231 static const afw_value_t *
232 impl_get_value(impl_lexical_t *self)
233 {
234  const afw_utf8_z_t *tkn;
235  const afw_value_t *val;
236  afw_size_t count;
237  const afw_utf8_octet_t *save_c;
238  const afw_list_t *list;
239  afw_utf8_t *s;
240  afw_utf8_t string;
241 
242  tkn = impl_get_token(self);
243  if (!tkn) {
244  AFW_THROW_ERROR_Z(general, "Error parsing schema.", self->xctx);
245  }
246 
247  /* If '(', build list of single values. */
248  else if (afw_utf8_z_equal(tkn, "(")) {
249 
250  /* Determine number of strings. */
251  save_c = self->c;
252  for (count = 0; ;) {
253  tkn = impl_get_token(self);
254 
255  /* Expect token. */
256  if (!tkn) {
257  AFW_THROW_ERROR_Z(general,
258  "Error parsing schema",
259  self->xctx);
260  }
261 
262  /* If ')' it's end of list. */
263  if (afw_utf8_z_equal(tkn, ")")) break;
264 
265  /* If '$', skip. */
266  if (afw_utf8_z_equal(tkn, "$")) continue;
267 
268  /* Increment string count. */
269  count++;
270  }
271  self->c = save_c;
272 
273  /* Allocate list to hold strings and populate it. */
274  s = afw_pool_malloc(self->p, count * sizeof(afw_utf8_t), self->xctx);
275  list = afw_list_create_wrapper_for_array(s, false,
276  afw_data_type_string, count, self->p, self->xctx);
277  val = afw_value_create_list(list, self->p, self->xctx);
278  for (;;) {
279  tkn = impl_get_token(self);
280  if (afw_utf8_z_equal(tkn, ")")) break;
281  if (afw_utf8_z_equal(tkn, "$")) continue;
282  impl_set_string(self, s++);
283  }
284  }
285 
286  /* If not list, just return single value. */
287  else {
288  impl_set_string(self, &string);
289  val = afw_value_create_string(&string, self->p, self->xctx);
290  }
291 
292  /* Return single value or list. */
293  return val;
294 
295 }
296 
297 
298 
299 /* Convert LDAP schema value to an object. */
300 const afw_object_t *
301 impl_parse_schema_entry(
302  const afw_utf8_t *name,
303  const afw_utf8_t *string,
304  const afw_pool_t *p,
305  afw_xctx_t *xctx)
306 {
307  const afw_utf8_z_t *tkn;
308  impl_lexical_t *self;
309  const afw_object_t *obj;
310  const afw_utf8_z_t *kwd;
311  const afw_value_t *val;
312 
313  self = impl_create_lexical_analyzer(string, p, xctx);
314  obj = afw_object_create(p, xctx);
315 
316  /* Starts with '(' */
317  tkn = impl_get_token(self);
318  if (!tkn || !afw_utf8_z_equal(tkn, "(")) {
319  AFW_THROW_ERROR_Z(general, "Error parsing schema.", self->xctx);
320  }
321 
322  /* Get value and set property with this value and passed name. */
323  val = impl_get_value(self);
324  afw_object_set_property(obj, name, val, xctx);
325 
326  /* Loop processing keywords. */
327  while ((kwd = impl_get_token(self))) {
328 
329  /* If to closing ')', make an object value and return. */
330  if (afw_utf8_z_equal(kwd, ")")) {
331  tkn = impl_get_token(self);
332  if (tkn) {
333  AFW_THROW_ERROR_Z(general, "Error parsing schema.",
334  self->xctx);
335  }
336  return obj;
337  }
338 
339  /* If one of the reserved boolean keywords, set it. */
340  if (
341  afw_utf8_z_equal(kwd, "SINGLE-VALUE") ||
342  afw_utf8_z_equal(kwd, "COLLECTIVE") ||
343  afw_utf8_z_equal(kwd, "OBSOLETE") ||
344  afw_utf8_z_equal(kwd, "ABSTRACT") ||
345  afw_utf8_z_equal(kwd, "STRUCTURAL") ||
346  afw_utf8_z_equal(kwd, "AUXILIARY") ||
347  afw_utf8_z_equal(kwd, "COLLECTIVE") ||
348  afw_utf8_z_equal(kwd, "NO-USER-MODIFICATION")
349  )
350  {
351  val = afw_value_true;
352  }
353 
354  /* If any other keyword, get following value and set. */
355  else {
356  val = impl_get_value(self);
357  }
358 
359  /* Set property. */
361  afw_utf8_create(kwd, AFW_UTF8_Z_LEN, p, xctx),
362  val, xctx);
363  }
364 
365  /* Error if it did not end with a ')'. */
366  AFW_THROW_ERROR_Z(general, "Error parsing schema.",
367  self->xctx);
368 }
369 
370 static void
371 impl_parse_definition_add(
372  apr_hash_t *ht,
373  const afw_object_t *obj,
374  const afw_utf8_t *adaptor_id,
375  const afw_utf8_t *object_type,
376  const afw_utf8_t *id,
377  afw_ldap_metadata_t *metadata,
378  afw_xctx_t *xctx)
379 {
380  const afw_utf8_t *object_id;
381 
382  /* Set ids in object. */
383  object_id = afw_utf8_clone(id, metadata->p, xctx);
384  afw_object_meta_set_ids(obj, adaptor_id, object_type, object_id, xctx);
385 
386  /* Add object to hash table. */
387  apr_hash_set(ht, object_id->s, object_id->len, obj);
388 };
389 
390 apr_hash_t *
391 impl_parse_definition(
392  const afw_utf8_t *adaptor_id,
393  const afw_utf8_t *object_type_id,
394  const afw_utf8_t *name_in_schema,
395  afw_ldap_metadata_t *metadata,
396  afw_xctx_t *xctx)
397 {
398  const afw_pool_t *p;
399  const afw_object_t *obj;
400  const afw_value_t *value;
401  const afw_value_t *name_value;
402  apr_hash_t *ht;
403  const afw_utf8_t *id;
404  const afw_utf8_t *e;
405  const afw_utf8_t *name;
406  const afw_list_t *list;
407  const afw_iterator_t *iterator;
408  const afw_iterator_t *iterator2;
409 
410  /* Use metadata p. */
411  p = metadata->p;
412 
413  value = afw_object_get_property(metadata->schema_object, name_in_schema, xctx);
414  if (!value) return NULL;
415  if (!afw_value_is_list_of_string(value)) {
416  AFW_THROW_ERROR_Z(general, "Expecting list of strings", xctx);
417  }
418  list = ((const afw_value_list_t *)value)->internal;
419 
420  /* Create hash table. */
421  ht = apr_hash_make(afw_pool_get_apr_pool(p));
422 
423  /* Process each definition in list. */
424  for (iterator = NULL;;) {
425  afw_list_get_next_internal(list, &iterator, NULL, (const void **)&e, xctx);
426  if (!e) {
427  break;
428  }
429  obj = impl_parse_schema_entry(&afw_ldap_s_numericoid, e,
430  metadata->p, xctx);
431 
432  name_value = afw_object_get_property(obj,
433  &afw_ldap_s_NAME, xctx);
434 
435  if (!name_value) {
436  name_value = afw_object_get_property(obj,
437  &afw_ldap_s_numericoid, xctx);
438  if (!name_value) {
439  AFW_THROW_ERROR_Z(general, "Error parsing schema", xctx);
440  }
441  }
442  if (afw_value_is_list_of_string(name_value)) {
443  for (iterator2 = NULL;;)
444  {
446  ((const afw_value_list_t *)name_value)->internal,
447  &iterator2, NULL, (const void **)&name, xctx);
448  if (!name) {
449  break;
450  }
451  impl_parse_definition_add(ht, obj, adaptor_id, object_type_id,
452  name, metadata, xctx);
453  }
454  }
455  else {
456  id = afw_value_as_utf8(name_value, p, xctx);
457  if (!id) {
458  AFW_THROW_ERROR_Z(general, "Error parsing schema", xctx);
459  }
460  impl_parse_definition_add(ht, obj, adaptor_id, object_type_id, id,
461  metadata, xctx);
462  }
463  }
464 
465  return ht;
466 }
467 
468 
469 void
470 impl_make_property_type_and_handler_hash_tables(
471  const afw_utf8_t *adaptor_id,
472  afw_ldap_metadata_t *metadata,
473  afw_xctx_t *xctx)
474 {
475  apr_hash_t *ht;
476 
477  const afw_value_t *value;
478  apr_hash_index_t *hi;
479  const afw_object_t *attribute_type_object;
480  const afw_utf8_t *id;
481  afw_utf8_t syntax_oid;
482  apr_hash_t *ht_attribute_types;
483  const afw_utf8_t *syntax;
484  const afw_utf8_t *error_id;
485  const afw_utf8_t *string;
486  afw_size_t len;
487  const afw_utf8_octet_t *s;
488  afw_utf8_t temp;
489  afw_ldap_metadata_attribute_type_t *attribute_type;
490  const void *key;
491  apr_ssize_t klen;
492  afw_boolean_t found;
493  const afw_pool_t *p;
494 
495  /* Use metadata p. */
496  p = metadata->p;
497 
498  /* Make value meta hash table. */
499  ht = apr_hash_make(afw_pool_get_apr_pool(p));
500  metadata->value_meta_objects = ht;
501 
502  /* Make attribute types hash table. */
503  ht_attribute_types = apr_hash_make(afw_pool_get_apr_pool(p));
504  metadata->attribute_types = ht_attribute_types;
505 
506  /* Create property type and object for each attribute type. */
507  for (hi = apr_hash_first(afw_pool_get_apr_pool(p),
508  metadata->attribute_type_objects);
509  hi; hi = apr_hash_next(hi))
510  {
511  apr_hash_this(hi, &key, &klen, (void **)&attribute_type_object);
512  attribute_type = afw_pool_calloc_type(p,
514  attribute_type->attribute_type_object = attribute_type_object;
515 
516  /*
517  * Use syntax to determine datatype and handler. Add handler to
518  * ht_attribute_types.
519  */
520  syntax = afw_object_old_get_property_as_string(attribute_type_object,
521  &afw_ldap_s_SYNTAX, xctx);
522  if (syntax) {
523 
524  /* Get oid part of syntax. */
525  error_id = &afw_ldap_s_SYNTAX;
526  for (len = syntax->len, s = syntax->s;
527  len > 0 && *s != '{';
528  len--, s++);
529  syntax_oid.s = syntax->s;
530  syntax_oid.len = s - syntax->s;
531  attribute_type->syntax_oid = afw_utf8_clone(
532  &syntax_oid, p, xctx);
533 
534  /* If there is a "{length}", set constraint. */
535  if (len > 0) {
536  temp.s = syntax->s + syntax_oid.len + 1;
537  if (len < 3) goto error;
538  temp.len = len - 2;
539  if (temp.s[temp.len] != '}') goto error;
540  attribute_type->upper_bound =
542  metadata->p, xctx);
543  attribute_type->upper_bound_present = true;
544  }
545 
546  /* Determine if single. */
547  attribute_type->is_single =
549  attribute_type_object, &afw_ldap_s_a_single_dash_value,
550  &found, xctx);
551 
552  /* X-NDS_LOWER_BOUND. */
553  attribute_type->lower_bound =
555  attribute_type_object, &afw_ldap_s_a_X_NDS_LOWER_BOUND,
556  &attribute_type->lower_bound_present, xctx);
557 
558  /* X-NDS_UPPER_BOUND if already be obtained by {} in syntax. */
559  if (!attribute_type->upper_bound_present) {
560  attribute_type->upper_bound =
562  attribute_type_object, &afw_ldap_s_a_X_NDS_UPPER_BOUND,
563  &attribute_type->upper_bound_present, xctx);
564  }
565 
566  /* NO-USER-MODIFICATION - Never allow write. */
567  if (afw_object_old_get_property_as_boolean_deprecated(attribute_type_object,
568  &afw_ldap_s_a_NO_USER_MODIFICATION, xctx))
569  {
570  attribute_type->never_allow_write = true;
571  }
572 
573  /* X-NDS_HIDDEN - Never allow read or write. */
574  if (afw_object_old_get_property_as_boolean_deprecated(attribute_type_object,
575  &afw_ldap_s_a_X_NDS_HIDDEN, xctx))
576  {
577  attribute_type->never_allow_read = true;
578  attribute_type->never_allow_write = true;
579  }
580 
581  /* X-NDS_NONREMOVABLE - Never remove. */
582  if (afw_object_old_get_property_as_boolean_deprecated(attribute_type_object,
583  &afw_ldap_s_a_X_NDS_NONREMOVABLE, xctx))
584  {
585  attribute_type->never_allow_write = true;
586  }
587 
588  /* X-NDS_READ_FILTERED - Operational. */
589  if (afw_object_old_get_property_as_boolean_deprecated(attribute_type_object,
590  &afw_ldap_s_a_X_NDS_READ_FILTERED, xctx))
591  {
592  attribute_type->operational = true;
593  attribute_type->never_allow_write = true;
594  }
595 
596  /*
597  * Assign syntax handler related values in attribute type. This
598  * must happen after other values in attribute type have been
599  * set.
600  */
602  metadata, attribute_type, xctx);
603 
604  /* If attribute can be read, make a property type object. */
605  if (!attribute_type->never_allow_read) {
606 
607  /* Create property type object and set ids. */
608  attribute_type->property_type_object =
609  afw_object_create(metadata->p, xctx);
610  id = afw_object_meta_get_object_id(attribute_type_object, xctx);
612  attribute_type->property_type_object,
613  adaptor_id, &afw_s__AdaptiveValueMeta_, id, xctx);
614  attribute_type->property_name = id;
615 
616  /* Set data type and data type parameter. */
617  if (attribute_type->is_single) {
618  if (attribute_type->data_type_id_value) {
620  attribute_type->property_type_object,
621  &afw_s_dataType, attribute_type->data_type_id_value,
622  xctx);
623  }
624  }
625  else {
627  attribute_type->property_type_object,
628  &afw_s_dataType, afw_data_type_list_id_value,
629  xctx);
630  if (attribute_type->data_type_id_value) {
632  attribute_type->property_type_object,
633  &afw_s_dataTypeParameter,
634  attribute_type->data_type_id_value,
635  xctx);
636  }
637  }
638 
639  /* If lower bound present, set in property type object. */
640  if (attribute_type->lower_bound_present) {
642  attribute_type->lower_bound, p, xctx);
644  attribute_type->property_type_object,
645  &afw_s_minValue, string, xctx);
646 
647  }
648 
649  /* If upper bound present, set in property type object. */
650  if (attribute_type->upper_bound_present) {
652  attribute_type->upper_bound, p, xctx);
654  attribute_type->property_type_object,
655  &afw_s_maxValue, string, xctx);
656  }
657 
658  /* allowWrite=false if applicable. */
659  if (attribute_type->never_allow_write) {
661  attribute_type->property_type_object,
662  &afw_s_allowWrite,
664  xctx);
665  }
666 
667  /* If you can read it, you can query it. */
669  attribute_type->property_type_object,
670  &afw_s_allowQuery, afw_value_true, xctx);
671 
672  /* Description. */
673  value = afw_object_get_property(attribute_type_object, &afw_ldap_s_DESC,
674  xctx);
675  if (value) {
677  attribute_type->property_type_object,
678  &afw_s_description, value, xctx);
679  }
680 
681  /* Add property type object to propertyType hash table. */
682  apr_hash_set(ht, id->s, id->len,
683  attribute_type->property_type_object);
684 
685  }
686 
687 
688  /* Add attribute type to ht. */
689  apr_hash_set(ht_attribute_types, key, klen, attribute_type);
690  }
691 
692  }
693 
694  return;
695 
696 error:
697  AFW_THROW_ERROR_FZ(general, xctx, "Internal %" AFW_UTF8_FMT,
698  AFW_UTF8_FMT_ARG(error_id));
699 }
700 
701 static void
702 impl_a_property_to_object_type(
703  afw_boolean_t required,
704  const afw_utf8_t *name,
705  const afw_object_t *properties,
706  afw_ldap_metadata_t *metadata,
707  afw_xctx_t *xctx)
708 {
709  const afw_object_t *prop;
710  const afw_object_t *parent;
711  afw_value_list_t *parent_paths;
712  const afw_utf8_t *s;
713  afw_ldap_metadata_attribute_type_t *attribute_type;
714 
715  /* If property is a never read, don't add to object type. */
716  attribute_type = apr_hash_get(metadata->attribute_types,
717  name->s, name->len);
718  if (!attribute_type || attribute_type->never_allow_read) {
719  return;
720  }
721 
722  /* Create object for property. */
723  prop = afw_object_create_embedded(properties,
724  name, xctx);
725 
726  /* Set parent to corresponding value meta. */
727  parent = apr_hash_get(metadata->value_meta_objects,
728  name->s, name->len);
729  if (parent) {
730  s = afw_object_meta_get_path(parent, xctx);
731  parent_paths = afw_value_allocate_list(prop->p, xctx);
732  parent_paths->internal = afw_list_create_wrapper_for_array(
733  (const void *)s, false, afw_data_type_anyURI, 1, prop->p, xctx);
734  afw_object_meta_set_parent_paths(prop, parent_paths, xctx);
735  }
736 
737  /* If required, add required property. */
738  if (required) {
739  afw_object_set_property(prop, &afw_s_required,
740  afw_value_true, xctx);
741  }
742 }
743 
744 static void
745 impl_properties_to_object_type(
746  afw_boolean_t required,
747  const afw_object_t *object_class_object,
748  const afw_object_t *properties,
749  afw_ldap_metadata_t *metadata,
750  afw_xctx_t *xctx)
751 {
752  const afw_value_t *value;
753  const afw_list_t *list;
754  const afw_utf8_t *s;
755  const afw_iterator_t *iterator;
756  afw_utf8_t req_pn;
757 
758  req_pn.s = (required) ? "MUST" : "MAY";
759  req_pn.len = strlen(req_pn.s);
760  value = afw_object_get_property(object_class_object, &req_pn, xctx);
761  if (!value) return;
762  if (afw_value_is_list_of_string(value)) {
763  list = ((const afw_value_list_t *)value)->internal;
764  for (iterator = NULL;;)
765  {
767  &iterator, NULL, (const void **)&s, xctx);
768  if (!s) {
769  break;
770  }
771  impl_a_property_to_object_type(required, s, properties, metadata,
772  xctx);
773  }
774  }
775  else if (afw_value_is_defined_and_evaluated(value)) {
776  impl_a_property_to_object_type(required,
777  afw_value_one_and_only_as_utf8(value, metadata->p, xctx),
778  properties,
779  metadata, xctx);
780  }
781  else {
782  AFW_THROW_ERROR_Z(general, "Valuetype error.", xctx);
783  }
784 }
785 
786 static void
787 impl_set_synthetic_object_type(apr_hash_t *ht,
788  const afw_utf8_t *object_type_id,
789  afw_xctx_t *xctx)
790 {
791  const afw_object_t *object_type;
792 
793  object_type = afw_runtime_get_object(
794  &afw_s__AdaptiveObjectType_, object_type_id, xctx);
795  if (!object_type) {
796  AFW_THROW_ERROR_FZ(general, xctx,
797  "Missing object /afw/_AdaptiveObjectType_/%" AFW_UTF8_FMT,
798  AFW_UTF8_FMT_ARG(object_type_id));
799  }
800  apr_hash_set(ht, object_type_id->s, object_type_id->len,
801  object_type);
802 }
803 
804 
805 /* Return afw_ldap_object_type_attribute_t * for name. */
809  const afw_utf8_t *name)
810 {
812 
813  for (result = first;
814  result &&
815  (!result->attribute_type ||
816  !afw_utf8_equal(name, result->attribute_type->property_name)
817  );
818  result = result->next);
819 
820  return result;
821 }
822 
823 
824 
825 /*
826  * Set parents and property types. Return first
827  * afw_ldap_object_type_attribute_t or NULL.
828  */
830 impl_add_parents_and_property_types(
831  afw_ldap_metadata_t *metadata,
832  const afw_object_t *object_class_object,
833  afw_xctx_t *xctx)
834 {
835  const afw_pool_t *p;
836  const afw_value_t *value;
837  const afw_object_t *object_type_object;
838  const afw_object_t *property_types_object;
839  const afw_object_t *property_type_object;
840  const afw_object_t *parent;
841  const afw_object_t *parent_object_class_object;
843  afw_ldap_object_type_attribute_t *object_type_attribute;
844  afw_ldap_object_type_attribute_t *parent_object_type_attribute;
845  afw_ldap_metadata_attribute_type_t *attribute_type;
846  afw_value_list_t *parent_paths;
847  const afw_utf8_t *property_name;
848  const afw_utf8_t *object_type_id;
849  const afw_utf8_t *s;
850  afw_utf8_t *ids;
851  const afw_utf8_t *parent_id;
852  const afw_utf8_t *parent_id2;
853  const afw_iterator_t *iterator;
854  const afw_list_t *list;
855  afw_size_t count;
856  afw_size_t count2;
857  afw_size_t i;
858 
859  /* Use metadata p. */
860  p = metadata->p;
861 
862  /* Get object type object. Return if there is not one. */
863  object_type_id = afw_object_meta_get_object_id(object_class_object, xctx);
864  object_type_object = impl_get(metadata->object_type_objects,
865  object_type_id);
866  if (!object_type_object) {
867  return NULL;
868  }
869 
870  /* If object_type_attribute already set for this object type id, return. */
871  result = apr_hash_get(metadata->object_type_attributes,
872  object_type_id->s, object_type_id->len);
873  if (result) {
874  return result;
875  }
876 
877  /* Make and set initial object_type_attribute. */
878  object_type_attribute = afw_pool_calloc_type(p,
880  apr_hash_set(metadata->object_type_attributes,
881  object_type_id->s, object_type_id->len,
882  object_type_attribute);
883  result = object_type_attribute;
884 
885  /* Make list of property types for this object type. */
886  property_types_object = afw_object_old_get_property_as_object(
887  object_type_object, &afw_s_propertyTypes, xctx);
888  if (property_types_object) {
889  iterator = NULL;
890  while ((property_type_object =
892  property_types_object, &iterator, &property_name, xctx))
893  )
894  {
895  attribute_type = apr_hash_get(metadata->attribute_types,
896  property_name->s, property_name->len);
897  if (object_type_attribute->attribute_type) {
898  object_type_attribute->next =
901  xctx);
902  object_type_attribute = object_type_attribute->next;
903  }
904  object_type_attribute->attribute_type = attribute_type;
905  object_type_attribute->property_type_object =
906  property_types_object;
907  object_type_attribute->is_required =
909  &afw_s_required, xctx);
910  }
911  }
912 
913  /* Determine max parent count and pointer to first parent id. */
914  count = 0;
915  parent_id = NULL;
916  value = afw_object_get_property(object_class_object,
917  &afw_ldap_s_SUP, xctx);
918  if (value) {
919  if (afw_value_is_string(value)) {
920  count = 1;
921  parent_id = &((const afw_value_string_t *)value)->
922  internal;
923  }
924 
925  /* Note: All of this can be improve. Was retrofitting a change. */
926  else if (afw_value_is_list_of_string(value)) {
927  list = ((afw_value_list_t *)value)->internal;
928  count = afw_list_get_count(list, xctx);
929  ids = afw_pool_calloc(p, count * sizeof(afw_utf8_t), xctx);
930  parent_id = ids;
931  for (iterator = NULL;;) {
932  afw_list_get_next_internal(list, &iterator, NULL,
933  (const void **)&s, xctx);
934  if (!s) {
935  break;
936  }
937  afw_memory_copy(ids, s);
938  ids++;
939  }
940  }
941  }
942 
943  /* Some parents don't exist such as internal ones. */
944  for (parent_id2 = parent_id, count2 = count, i = 0;
945  i < count;
946  i++, parent_id2++)
947  {
948  parent = impl_get(metadata->object_type_objects, parent_id2);
949  if (!parent) {
950  count2--;
951  }
952  }
953 
954  /* If there are parents, add parent paths and add attributes to list. */
955  if (count2 > 0) {
956  parent_paths = afw_value_allocate_list(p, xctx);
957  parent_paths->internal = afw_list_of_create(
958  afw_data_type_anyURI, p, xctx);
959  for (i = 0; i < count; i++, parent_id++) {
960  parent = impl_get(metadata->object_type_objects,
961  parent_id);
962 
963  /* If this doesn't exist, skip. */
964  if (!parent) {
965  continue;
966  }
967 
968  /* Set parent path. */
969  s = afw_object_meta_get_path(parent, xctx);
970  afw_list_of_anyURI_add(parent_paths->internal, s, xctx);
971 
972  /* Make sure parent is processed first. */
973  parent_object_class_object =
974  impl_get(metadata->object_class_objects, parent_id);
975  if (!parent_object_class_object) {
976  continue;
977  }
978  parent_object_type_attribute =
979  impl_add_parents_and_property_types(metadata,
980  parent_object_class_object, xctx);
981 
982  /* Add any unique parent property types. */
983  for (;
984  parent_object_type_attribute;
985  parent_object_type_attribute =
986  parent_object_type_attribute->next
987  )
988  {
989  if (parent_object_type_attribute->attribute_type &&
991  parent_object_type_attribute->attribute_type->
992  property_name))
993  {
994  if (object_type_attribute->attribute_type) {
995  object_type_attribute->next =
998  xctx);
999  object_type_attribute = object_type_attribute->next;
1000  }
1001  object_type_attribute->attribute_type =
1002  parent_object_type_attribute->attribute_type;
1003  object_type_attribute->property_type_object =
1004  parent_object_type_attribute->property_type_object;
1005  object_type_attribute->is_required =
1006  parent_object_type_attribute->is_required;
1007  }
1008  }
1009 
1010  object_type_attribute->next =
1013  xctx);
1014  object_type_attribute = object_type_attribute->next;
1015  object_type_attribute->next = apr_hash_get(
1016  metadata->object_type_attributes,
1017  parent_id->s, parent_id->len);
1018 
1019  }
1020  afw_object_meta_set_parent_paths(object_type_object,
1021  parent_paths, xctx);
1022  }
1023 
1024  return result;
1025 }
1026 
1027 
1028 /* impl_make_property_type_and_handler_hash_tables() must be called first. */
1029 static void
1030 impl_make_object_types(
1031  const afw_utf8_t *adaptor_id,
1032  afw_ldap_metadata_t *metadata,
1033  afw_xctx_t *xctx)
1034 {
1035  const afw_value_t *value;
1036  apr_hash_index_t *hi;
1037  const afw_object_t *object_class_object;
1038  const afw_object_t *object_type_object;
1039  const afw_utf8_t *id;
1040  const afw_object_t *property_types_object;
1041  const afw_utf8_t *default_description;
1042  const afw_object_t *other_properties;
1043  const afw_pool_t *p;
1044 
1045  /* Use metadata p. */
1046  p = metadata->p;
1047 
1048  /* Make hash tables. */
1049  metadata->object_type_objects = apr_hash_make(afw_pool_get_apr_pool(p));
1050  metadata->object_type_attributes = apr_hash_make(afw_pool_get_apr_pool(p));
1051 
1052  /* Loop though all ldap object classes. */
1053  for (hi = apr_hash_first(afw_pool_get_apr_pool(p),
1054  metadata->object_class_objects);
1055  hi; hi = apr_hash_next(hi))
1056  {
1057  apr_hash_this(hi, NULL, NULL, (void **)&object_class_object);
1058 
1059  /* Create _AdaptiveObjectType_ and initialize. */
1060  object_type_object = afw_object_create(p, xctx);
1061  id = afw_object_meta_get_object_id(object_class_object, xctx);
1062  afw_object_meta_set_ids(object_type_object, adaptor_id,
1063  &afw_ldap_s__AdaptiveObjectType_, id, xctx);
1064  afw_object_set_property_as_string(object_type_object, &afw_s_objectType,
1065  id, xctx);
1066  afw_object_set_property(object_type_object, &afw_s_allowEntity,
1068  &afw_ldap_s_STRUCTURAL, xctx))
1069  ? afw_value_true
1070  : afw_value_false,
1071  xctx);
1072 
1073  afw_object_set_property(object_type_object, &afw_s_allowAdd,
1074  afw_value_true, xctx);
1075  afw_object_set_property(object_type_object, &afw_s_allowChange,
1076  afw_value_true, xctx);
1077  afw_object_set_property(object_type_object, &afw_s_allowDelete,
1078  afw_value_true, xctx);
1079 
1080  /*
1081  * Set otherProperties to cover all operational properties. These
1082  * are all allowWrite=false.
1083  */
1084  other_properties = afw_object_create_embedded(
1085  object_type_object, &afw_s_otherProperties, xctx);
1086  afw_object_set_property(other_properties,
1087  &afw_s_allowWrite, afw_value_false, xctx);
1088 
1089  /* Add object type to object_type_objects ht. */
1090  apr_hash_set(metadata->object_type_objects, id->s, id->len,
1091  object_type_object);
1092 
1093  /* If object class has a description, use it otherwise, make up one. */
1094  value = afw_object_get_property(object_class_object, &afw_ldap_s_DESC,
1095  xctx);
1096  if (!value) {
1097  default_description = afw_utf8_printf(metadata->p, xctx,
1098  "_AdaptiveObjectType representation of LDAP object"
1099  "class %" AFW_UTF8_FMT ".",
1100  AFW_UTF8_FMT_ARG(id));
1102  default_description->s, default_description->len,
1103  p, xctx);
1104  }
1105  afw_object_set_property(object_type_object, &afw_s_description, value,
1106  xctx);
1107 
1108  /* Create properties object. */
1109  property_types_object = afw_object_create_embedded(
1110  object_type_object,
1111  &afw_s_propertyTypes, xctx);
1112 
1113  /* Add MUST and MAY properties. */
1114  impl_properties_to_object_type(AFW_TRUE,
1115  object_class_object, property_types_object, metadata, xctx);
1116  impl_properties_to_object_type(AFW_FALSE,
1117  object_class_object, property_types_object, metadata, xctx);
1118 
1121  }
1122 
1123  /* Run back though setting parents and making composite property types. */
1124  for (hi = apr_hash_first(afw_pool_get_apr_pool(p),
1125  metadata->object_class_objects);
1126  hi; hi = apr_hash_next(hi))
1127  {
1128  apr_hash_this(hi, NULL, NULL, (void **)&object_class_object);
1129  impl_add_parents_and_property_types(
1130  metadata, object_class_object, xctx);
1131  }
1132 
1133  /* Add synthetic object types. */
1134  impl_set_synthetic_object_type(metadata->object_type_objects,
1135  &afw_s__AdaptiveObjectType_, xctx);
1136  impl_set_synthetic_object_type(metadata->object_type_objects,
1137  &afw_s__AdaptiveValueMeta_, xctx);
1138  impl_set_synthetic_object_type(metadata->object_type_objects,
1139  &afw_ldap_s__AdaptiveLdapAttributeType_, xctx);
1140  impl_set_synthetic_object_type(metadata->object_type_objects,
1141  &afw_ldap_s__AdaptiveLdapMatchingRuleUse_, xctx);
1142  impl_set_synthetic_object_type(metadata->object_type_objects,
1143  &afw_ldap_s__AdaptiveLdapMatchingRuleUse_, xctx);
1144  impl_set_synthetic_object_type(metadata->object_type_objects,
1145  &afw_ldap_s__AdaptiveLdapMatchingRule_, xctx);
1146  impl_set_synthetic_object_type(metadata->object_type_objects,
1147  &afw_ldap_s__AdaptiveLdapObjectClass_, xctx);
1148  impl_set_synthetic_object_type(metadata->object_type_objects,
1149  &afw_ldap_s__AdaptiveLdapRootDse_, xctx);
1150  impl_set_synthetic_object_type(metadata->object_type_objects,
1151  &afw_ldap_s__AdaptiveLdapSchema_, xctx);
1152  impl_set_synthetic_object_type(metadata->object_type_objects,
1153  &afw_ldap_s__AdaptiveLdapSyntax_, xctx);
1154 }
1155 
1156 
1157 void
1159  afw_ldap_internal_adaptor_t *adaptor,
1160  afw_xctx_t *xctx)
1161 {
1163  afw_ldap_metadata_t *new_metadata;
1164  afw_ldap_metadata_t *old_metadata;
1165  const afw_value_t *value;
1166  const afw_pool_t *p;
1167 
1168  /* Use adaptor's pool. */
1169  p = adaptor->pub.p;
1170 
1171  /* Allocate new afw_ldap_metadata_t in subpool. */
1172  new_metadata = afw_pool_calloc_type(p, afw_ldap_metadata_t, xctx);
1173  new_metadata->p = p;
1174 
1175  /* Begin a temporary session with ldap adaptor. */
1176  session = afw_ldap_internal_adaptor_session_create(adaptor, xctx);
1177 
1178  /* Get rootDSE. */
1179  new_metadata->rootdse_object =
1180  impl_get_rootdse(session, p, xctx);
1181 
1182  /* Get subschemaSubentry property of rootDSE. */
1183  value = afw_object_get_property(new_metadata->rootdse_object,
1184  &afw_ldap_s_subschemaSubentry,
1185  xctx);
1186  if (!value) {
1187  AFW_THROW_ERROR_Z(general, "subschemaSubentry not found.", xctx);
1188  }
1189  new_metadata->subschema_subentry =
1190  afw_value_one_and_only_as_utf8(value, p, xctx);
1191 
1192  /* Get schema and parse definitions. */
1193  new_metadata->schema_object =
1194  impl_get_schema(session,
1195  new_metadata->subschema_subentry, p, xctx);
1196 
1197  new_metadata->attribute_type_objects =
1198  impl_parse_definition(
1199  &adaptor->pub.adaptor_id,
1200  &afw_ldap_s__AdaptiveLdapAttributeType_,
1201  &afw_ldap_s_attributeTypes,
1202  new_metadata, xctx);
1203 
1204  new_metadata->ldap_syntax_objects =
1205  impl_parse_definition(
1206  &adaptor->pub.adaptor_id,
1207  &afw_ldap_s__AdaptiveLdapSyntax_,
1208  &afw_ldap_s_ldapSyntaxes,
1209  new_metadata, xctx);
1210 
1211  new_metadata->matching_rule_objects =
1212  impl_parse_definition(
1213  &adaptor->pub.adaptor_id,
1214  &afw_ldap_s__AdaptiveLdapMatchingRule_,
1215  &afw_ldap_s_matchingRules,
1216  new_metadata, xctx);
1217 
1218  new_metadata->matching_rule_use_objects =
1219  impl_parse_definition(
1220  &adaptor->pub.adaptor_id,
1221  &afw_ldap_s__AdaptiveLdapMatchingRuleUse_,
1222  &afw_ldap_s_matchingRuleUse,
1223  new_metadata, xctx);
1224 
1225  new_metadata->object_class_objects =
1226  impl_parse_definition(
1227  &adaptor->pub.adaptor_id,
1228  &afw_ldap_s__AdaptiveLdapObjectClass_,
1229  &afw_ldap_s_objectClasses,
1230  new_metadata, xctx);
1231 
1232  impl_make_property_type_and_handler_hash_tables(
1233  &adaptor->pub.adaptor_id,
1234  new_metadata, xctx);
1235 
1236  impl_make_object_types(
1237  &adaptor->pub.adaptor_id,
1238  new_metadata, xctx);
1239 
1242  /* Start using new metadata. */
1244  old_metadata = adaptor->metadata;
1245  adaptor->metadata = new_metadata;
1246  if (old_metadata) {
1247  afw_pool_release(old_metadata->p, xctx);
1248  }
1249 
1250  /* Release temporary session. */
1251  afw_adaptor_session_release((const afw_adaptor_session_t *)session, xctx);
1252 
1253  return;
1254 }
1255 
1256 void
1257 impl_retrieve_objects(
1259  apr_hash_t *ht,
1260  const afw_query_criteria_t * criteria,
1261  void * context,
1262  afw_object_cb_t callback,
1263  afw_xctx_t *xctx)
1264 {
1265  apr_hash_index_t *hi;
1266  afw_object_t *obj;
1267 
1268  for (hi = apr_hash_first(afw_pool_get_apr_pool(xctx->p), ht);
1269  hi;
1270  hi = apr_hash_next(hi))
1271  {
1272  apr_hash_this(hi, NULL, NULL, (void **)&obj);
1273  if (afw_query_criteria_test_object(obj, criteria,
1274  xctx->p, xctx))
1275  {
1276  callback(obj, context, xctx);
1277  }
1278  }
1279 }
1280 
1281 
1282 /* Used by afw_ldap_adaptor_session() to retrieve metadata objects. */
1283 void
1286  const afw_utf8_t * object_type_id,
1287  const afw_query_criteria_t * criteria,
1288  void * context,
1289  afw_object_cb_t callback,
1290  afw_xctx_t *xctx)
1291 {
1292  apr_hash_t *ht;
1293  const afw_object_t *obj;
1294 
1295  ht = NULL;
1296 
1297  /* ObjectType. */
1298  if (afw_utf8_equal(object_type_id,
1300  {
1301  ht = self->adaptor->metadata->object_type_objects;
1302  }
1303 
1304  /* ValueMeta. */
1305  else if (afw_utf8_equal(object_type_id,
1307  {
1308  ht = self->adaptor->metadata->value_meta_objects;
1309  }
1310 
1311  /* Object Class. */
1312  else if (afw_utf8_equal(object_type_id,
1313  &afw_ldap_s__AdaptiveLdapObjectClass_))
1314  {
1315  ht = self->adaptor->metadata->object_class_objects;
1316  }
1317 
1318  /* Attribute Type */
1319  else if (afw_utf8_equal(object_type_id,
1320  &afw_ldap_s__AdaptiveLdapAttributeType_))
1321  {
1322  ht = self->adaptor->metadata->attribute_type_objects;
1323  }
1324 
1325  /* Syntax */
1326  else if (afw_utf8_equal(object_type_id,
1327  &afw_ldap_s__AdaptiveLdapSyntax_))
1328  {
1329  ht = self->adaptor->metadata->ldap_syntax_objects;
1330  }
1331 
1332  /* Matching Rule */
1333  else if (afw_utf8_equal(object_type_id,
1334  &afw_ldap_s__AdaptiveLdapMatchingRule_))
1335  {
1336  ht = self->adaptor->metadata->matching_rule_objects;
1337  }
1338 
1339  /* Matching Rule Use */
1340  else if (afw_utf8_equal(object_type_id,
1341  &afw_ldap_s__AdaptiveLdapMatchingRuleUse_))
1342  {
1343  ht = self->adaptor->metadata->matching_rule_use_objects;
1344  }
1345 
1346  /* If one of the multi entry pseudo object types, call retrieve them. */
1347  if (ht) {
1348  impl_retrieve_objects(self, ht, criteria, context, callback, xctx);
1349  }
1350 
1351  /* If one of the single entry object types, return it. */
1352  else {
1353 
1354  /* LDAP Root DSE */
1355  if (afw_utf8_equal(object_type_id,
1356  &afw_ldap_s__AdaptiveLdapRootDse_))
1357  {
1358  obj = self->adaptor->metadata->rootdse_object;
1359  if (afw_query_criteria_test_object(obj, criteria,
1360  xctx->p, xctx))
1361  {
1362  callback(obj, context, xctx);
1363  }
1364  }
1365 
1366  /* LDAP Schema */
1367  if (afw_utf8_equal(object_type_id,
1368  &afw_ldap_s__AdaptiveLdapSchema_))
1369  {
1370  obj = self->adaptor->metadata->schema_object;
1371  if (afw_query_criteria_test_object(obj, criteria,
1372  xctx->p, xctx))
1373  {
1374  callback(obj, context, xctx);
1375  }
1376  }
1377 
1378  }
1379 
1380  /* Callback one last time with NULL object pointer. */
1381  callback(NULL, context, xctx);
1382 }
1383 
1384 
1385 AFW_DEFINE_STATIC_INLINE(const afw_object_t *)
1386 impl_get_object(
1388  apr_hash_t *ht,
1389  const afw_utf8_t * object_id,
1390  afw_xctx_t *xctx)
1391 {
1392  return apr_hash_get(ht, object_id->s, object_id->len);
1393 }
1394 
1395 
1396 /* Called by afw_ldap_adaptor_session() to get a metadata object. */
1397 void
1400  const afw_utf8_t * object_type_id,
1401  const afw_utf8_t * object_id,
1402  void * context,
1403  afw_object_cb_t callback,
1404  afw_xctx_t *xctx)
1405 {
1406  const afw_object_t *obj;
1407 
1408  /* Assume no object will be found. */
1409  obj = NULL;
1410 
1411  /* RootDSE */
1412  if (afw_utf8_equal(object_type_id, &afw_ldap_s__AdaptiveLdapRootDse_))
1413  {
1414  if (afw_utf8_equal(object_id, &afw_s_current)) {
1415  obj = self->adaptor->metadata->rootdse_object;
1416  }
1417  }
1418 
1419  /* Schema */
1420  else if (afw_utf8_equal(object_type_id,
1421  &afw_ldap_s__AdaptiveLdapSchema_))
1422  {
1423  if (afw_utf8_equal(object_id, &afw_s_current)) {
1424  obj = self->adaptor->metadata->schema_object;
1425  }
1426  }
1427 
1428  /* ObjectType. */
1429  else if (afw_utf8_equal(object_type_id, &afw_s__AdaptiveObjectType_))
1430  {
1431  obj = impl_get_object(self,
1432  self->adaptor->metadata->object_type_objects,
1433  object_id, xctx);
1434  }
1435 
1436  /* ValueMeta. */
1437  else if (afw_utf8_equal(object_type_id, &afw_s__AdaptiveValueMeta_))
1438  {
1439  obj = impl_get_object(self,
1440  self->adaptor->metadata->value_meta_objects,
1441  object_id, xctx);
1442  }
1443 
1444  /* Object Class. */
1445  else if (afw_utf8_equal(object_type_id,
1446  &afw_ldap_s__AdaptiveLdapObjectClass_))
1447  {
1448  obj = impl_get_object(self,
1449  self->adaptor->metadata->object_class_objects,
1450  object_id, xctx);
1451  }
1452 
1453  /* Attribute Type */
1454  else if (afw_utf8_equal(object_type_id,
1455  &afw_ldap_s__AdaptiveLdapAttributeType_))
1456  {
1457  obj = impl_get_object(self,
1458  self->adaptor->metadata->attribute_type_objects,
1459  object_id, xctx);
1460  }
1461 
1462  /* Syntax */
1463  else if (afw_utf8_equal(object_type_id,
1464  &afw_ldap_s__AdaptiveLdapSyntax_))
1465  {
1466  obj = impl_get_object(self,
1467  self->adaptor->metadata->ldap_syntax_objects,
1468  object_id, xctx);
1469  }
1470 
1471  /* Matching Rule */
1472  else if (afw_utf8_equal(object_type_id,
1473  &afw_ldap_s__AdaptiveLdapMatchingRule_))
1474  {
1475  obj = impl_get_object(self,
1476  self->adaptor->metadata->matching_rule_objects,
1477  object_id, xctx);
1478  }
1479 
1480  /* Matching Rule Use */
1481  else if (afw_utf8_equal(object_type_id,
1482  &afw_ldap_s__AdaptiveLdapMatchingRuleUse_))
1483  {
1484  obj = impl_get_object(self,
1485  self->adaptor->metadata->matching_rule_use_objects,
1486  object_id, xctx);
1487  }
1488 
1489  /* Callback with object or NULL. */
1490  callback(obj, context, xctx);
1491 }
1492 
1493 /* Determine if afw_ldap_metadata.c handles an ObjectType. */
1495 afw_ldap_metadata_handles(const afw_utf8_t *object_type)
1496 {
1497  if (object_type && afw_utf8_starts_with(object_type, &afw_s__Adaptive))
1498  {
1499  return AFW_TRUE;
1500  }
1501 
1502  return AFW_FALSE;
1503 }
1504 
1505 
1506 const afw_value_t *
1507 afw_ldap_metadata_bv_to_value(
1510  const afw_utf8_t *attribute_name,
1511  struct berval * *bv,
1512  const afw_pool_t *p,
1513  afw_xctx_t *xctx)
1514 {
1515  const afw_value_t *result;
1516 
1517  if (attribute && attribute->attribute_type)
1518  {
1519  result = attribute->attribute_type->syntax_handler->to_value(
1520  attribute->attribute_type,
1521  attribute->attribute_type->syntax_handler->data,
1522  bv,
1523  p, xctx);
1524  }
1525  else {
1526  result = afw_ldap_internal_syntax_handler_unknown_to_value(
1527  bv, p, xctx);
1528  }
1529  return result;
1530 }
1531 
1532 struct berval **
1533 afw_ldap_metadata_value_to_bv(afw_ldap_internal_adaptor_session_t *session,
1534  const afw_utf8_t *attribute_name, const afw_value_t *value,
1535  afw_xctx_t *xctx)
1536 {
1537  const afw_ldap_metadata_attribute_type_t *attribute_type;
1538 
1539  attribute_type = apr_hash_get(
1540  session->adaptor->metadata->attribute_types,
1541  attribute_name->s, attribute_name->len);
1542  if (!attribute_type) {
1543  AFW_THROW_ERROR_FZ(general, xctx,
1544  "Unknown attribute type %" AFW_UTF8_FMT,
1545  AFW_UTF8_FMT_ARG(attribute_name));
1546  }
1547  if (!value) {
1548  AFW_THROW_ERROR_Z(general,
1549  "Missing value calling afw_ldap_metadata_value_to_bv()",
1550  xctx);
1551  }
1552  return attribute_type->syntax_handler->to_ber(
1553  attribute_type, attribute_type->syntax_handler->data, value,
1554  session->pub.p, xctx);
1555 }
Adaptive Framework Core API.
afw_ldap_internal_adaptor_session_t * afw_ldap_internal_adaptor_session_create(afw_ldap_internal_adaptor_t *adaptor, afw_xctx_t *xctx)
Internal create an LDAP adaptor session.
void afw_ldap_internal_syntax_handler_assign(afw_ldap_metadata_t *metadata, afw_ldap_metadata_attribute_type_t *attribute_type, afw_xctx_t *xctx)
void afw_ldap_metadata_retrieve_objects(afw_ldap_internal_adaptor_session_t *self, const afw_utf8_t *object_type_id, const afw_query_criteria_t *criteria, void *context, afw_object_cb_t callback, afw_xctx_t *xctx)
Called by afw_ldap_adaptor_session() to retrieve metadata objects.
void afw_ldap_metadata_get_object(afw_ldap_internal_adaptor_session_t *self, const afw_utf8_t *object_type_id, const afw_utf8_t *object_id, void *context, afw_object_cb_t callback, afw_xctx_t *xctx)
Called by afw_ldap_adaptor_session() to get a metadata object.
afw_ldap_object_type_attribute_t * afw_ldap_metadata_get_object_type_attribute(afw_ldap_object_type_attribute_t *first, const afw_utf8_t *name)
Return afw_ldap_object_type_attribute_t * for name.
void afw_ldap_metadata_load(afw_ldap_internal_adaptor_t *adaptor, afw_xctx_t *xctx)
Load LDAP adaptors Metadata .
Adaptive Framework LDAP Metadata Header.
afw_adaptor_session_release(const afw_adaptor_session_t *session, afw_xctx_t *xctx)
Release an adaptor session created by afw_adaptor_session_create().
Definition: afw_adaptor.c:282
afw_data_type_anyURI
Data type struct for anyURI.
afw_list_of_anyURI_add(const afw_list_t *instance, const afw_utf8_t *value, afw_xctx_t *xctx)
Add value from list of anyURI.
afw_object_set_property_as_boolean(const afw_object_t *object, const afw_utf8_t *property_name, afw_boolean_t internal, afw_xctx_t *xctx)
Set property function for data type boolean values.
#define afw_object_old_get_property_as_boolean(object, property_name, found, xctx)
Get property function for data type boolean value.
afw_value_create_list(const afw_list_t *internal, const afw_pool_t *p, afw_xctx_t *xctx)
Create function for unmanaged data type list value.
afw_value_allocate_list(const afw_pool_t *p, afw_xctx_t *xctx)
Allocate function for unmanaged data type list value.
afw_data_type_list_id_value
Adaptive string value for "list".
#define afw_object_old_get_property_as_object(object, property_name, xctx)
Get property function for data type object value.
#define afw_object_old_get_next_property_as_object(object, iterator, property_name, xctx)
Get next property function for data type object value.
afw_value_create_string(const afw_utf8_t *internal, const afw_pool_t *p, afw_xctx_t *xctx)
Create function for unmanaged data type string value.
#define afw_object_old_get_property_as_string(object, property_name, xctx)
Get property function for data type string value.
afw_data_type_string
Data type struct for string.
#define afw_value_is_string(A_VALUE)
Macro to determine if value is evaluated string.
afw_object_set_property_as_string(const afw_object_t *object, const afw_utf8_t *property_name, const afw_utf8_t *internal, afw_xctx_t *xctx)
Set property function for data type string values.
#define afw_value_is_list_of_string(A_VALUE)
Macro to determine if value is evaluated list of string.
#define AFW_UTF8_FMT_ARG(A_STRING)
Convenience Macro for use with AFW_UTF8_FMT to specify arg.
Definition: afw_common.h:605
#define AFW_FALSE
Definition: afw_common.h:392
#define AFW_UTF8_Z_LEN
String is NUL (0) terminate.
Definition: afw_common.h:266
afw_boolean_t(* afw_object_cb_t)(const afw_object_t *object, void *context, afw_xctx_t *xctx)
Typedef for afw_adaptor_session_object callback.
Definition: afw_common.h:1176
struct afw_iterator_s afw_iterator_t
#define AFW_TRUE
Definition: afw_common.h:383
_Bool afw_boolean_t
Definition: afw_common.h:373
#define AFW_UTF8_FMT
Format string specifier used for afw_utf8_t.
Definition: afw_common.h:588
afw_utf8_octet_t afw_utf8_z_t
NFC normalized UTF-8 null terminated string.
Definition: afw_common.h:523
char afw_utf8_octet_t
8 bits of utf-8 codepoint.
Definition: afw_common.h:236
apr_size_t afw_size_t
size_t.
Definition: afw_common.h:151
#define AFW_THROW_ERROR_FZ(code, xctx, format_z,...)
Macro used to set error and 0 rv in xctx and throw it.
Definition: afw_error.h:319
#define AFW_THROW_ERROR_Z(code, message_z, xctx)
Macro used to set error and 0 rv in xctx and throw it.
Definition: afw_error.h:283
#define afw_list_get_next_internal(instance, iterator, data_type, internal, xctx)
Call method get_next_internal of interface afw_list.
#define afw_list_get_count(instance, xctx)
Call method get_count of interface afw_list.
afw_list_create_wrapper_for_array(const void *array, afw_boolean_t indirect, const afw_data_type_t *data_type, afw_size_t count, const afw_pool_t *p, afw_xctx_t *xctx)
Create a immutable list wrapper for an array.
#define afw_list_of_create(data_type, p, xctx)
Create an list of a specific data type in memory.
Definition: afw_list.h:64
#define afw_memory_copy(to, from)
Copy to preallocated memory of same type.
Definition: afw_memory.h:39
afw_integer_t afw_number_utf8_to_integer(const afw_utf8_t *s, const afw_pool_t *p, afw_xctx_t *xctx)
Convert a utf8 string to integer in specified pool.
Definition: afw_number.h:221
afw_number_integer_to_utf8(afw_integer_t i, const afw_pool_t *p, afw_xctx_t *xctx)
Convert an integer to utf8 in specified pool.
Definition: afw_number.c:168
#define afw_object_get_property(instance, property_name, xctx)
Call method get_property of interface afw_object.
afw_object_meta_set_parent_paths(const afw_object_t *instance, const afw_value_list_t *parent_paths, afw_xctx_t *xctx)
Set meta parentPaths property.
afw_object_meta_get_path(const afw_object_t *instance, afw_xctx_t *xctx)
Get an object's path.
afw_object_meta_set_ids(const afw_object_t *instance, const afw_utf8_t *adaptor_id, const afw_utf8_t *object_type_id, const afw_utf8_t *object_id, afw_xctx_t *xctx)
Set object's ids.
afw_object_meta_get_object_id(const afw_object_t *instance, afw_xctx_t *xctx)
Get entity object's object id.
afw_object_old_get_property_as_integer_deprecated(const afw_object_t *instance, const afw_utf8_t *property_name, afw_boolean_t *found, afw_xctx_t *xctx)
Get an object's property value as an integer.
Definition: afw_object.c:495
#define AFW_OBJECT_S_OBJECT_TYPE_ID_VALUE_META
String object type id for Property Type object.
Definition: afw_object.h:51
#define afw_object_create(p, xctx)
Create an empty unmanaged object in memory.
Definition: afw_object.h:948
#define AFW_OBJECT_S_OBJECT_TYPE_ID_OBJECT_TYPE
String object type id for Object Type object.
Definition: afw_object.h:45
afw_object_old_get_property_as_boolean_deprecated(const afw_object_t *instance, const afw_utf8_t *property_name, afw_xctx_t *xctx)
Get an object's property value as a boolean.
Definition: afw_object.c:436
afw_object_set_property(const afw_object_t *instance, const afw_utf8_t *property_name, const afw_value_t *value, afw_xctx_t *xctx)
Set the value of an object's property.
Definition: afw_object.c:46
const afw_object_t * afw_object_create_embedded(const afw_object_t *embedding_object, const afw_utf8_t *property_name, afw_xctx_t *xctx)
Create an empty embedded object in a memory object.
#define afw_pool_malloc(instance, size, xctx)
Call method malloc of interface afw_pool.
#define afw_pool_calloc(instance, size, xctx)
Call method calloc of interface afw_pool.
#define afw_pool_get_apr_pool(instance)
Call method get_apr_pool of interface afw_pool.
#define afw_pool_release(instance, xctx)
Call method release of interface afw_pool.
#define afw_pool_calloc_type(instance, type, xctx)
Macro to allocate cleared memory to hold type in pool.
Definition: afw_pool.h:167
afw_query_criteria_test_object(const afw_object_t *obj, const afw_query_criteria_t *criteria, const afw_pool_t *p, afw_xctx_t *xctx)
Test object against query criteria.
afw_runtime_get_object(const afw_utf8_t *object_type_id, const afw_utf8_t *object_id, afw_xctx_t *xctx)
Get a runtime object.
Definition: afw_runtime.c:853
afw_boolean_t afw_utf8_equal(const afw_utf8_t *s1, const afw_utf8_t *s2)
Check to see if a string equals another string.
afw_utf8_z_create(const afw_utf8_octet_t *s, afw_size_t len, const afw_pool_t *p, afw_xctx_t *xctx)
Create a NFC Normalized zero terminated UTF-8 string in specified pool.
Definition: afw_utf8.c:366
const afw_utf8_t * afw_utf8_clone(const afw_utf8_t *string, const afw_pool_t *p, afw_xctx_t *xctx)
Clone a utf-8 string into a specific pool.
Definition: afw_utf8.h:347
afw_utf8_printf(const afw_pool_t *p, afw_xctx_t *xctx, const afw_utf8_z_t *format,...)
Create a utf-8 string using a c format string in specified pool.
Definition: afw_utf8.c:459
afw_boolean_t afw_utf8_z_equal(const afw_utf8_z_t *s1, const afw_utf8_z_t *s2)
Definition: afw_utf8.h:799
afw_boolean_t afw_utf8_starts_with(const afw_utf8_t *string, const afw_utf8_t *starts_with)
Check to see if a string starts with another string.
#define afw_utf8_create(s, len, p, xctx)
Create utf-8 string without copy unless necessary in pool specified.
Definition: afw_utf8.h:239
afw_value_as_utf8(const afw_value_t *value, const afw_pool_t *p, afw_xctx_t *xctx)
Definition: afw_value.c:456
afw_value_false
Adaptive value false.
Definition: afw_value.h:354
afw_value_one_and_only_as_utf8(const afw_value_t *value, const afw_pool_t *p, afw_xctx_t *xctx)
Return result of afw_value_one_and_only() as utf8.
Definition: afw_value.c:441
#define afw_value_is_defined_and_evaluated(A_VALUE)
Macro to determine if value is defined and evaluated.
Definition: afw_value.h:481
afw_value_make_single_string(const afw_utf8_octet_t *s, afw_size_t len, const afw_pool_t *p, afw_xctx_t *xctx)
Definition: afw_value.c:478
afw_value_true
Adaptive value true.
Definition: afw_value.h:348
#define afw_xctx_calloc_type(type, xctx)
Macro to allocate cleared memory to hold type in xctx's pool.
Definition: afw_xctx.h:199
Interface afw_adaptor_session public struct.
Interface afw_list public struct.
Interface afw_object public struct.
Interface afw_pool public struct.
Parsed query criteria.
NFC normalized UTF-8 string.
Definition: afw_common.h:545
struct for data type list values.
Interface afw_value public struct.
struct for data type string values.
Interface afw_xctx public struct.