📄 ldb_map_outbound.c
字号:
/* ldb database mapping module Copyright (C) Jelmer Vernooij 2005 Copyright (C) Martin Kuehl <mkhl@samba.org> 2006 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006 ** NOTE! The following LGPL license applies to the ldb ** library. This does NOT imply that all of Samba is released ** under the LGPL This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, see <http://www.gnu.org/licenses/>.*/#include "ldb_includes.h"#include "ldb_map.h"#include "ldb_map_private.h"/* Mapping attributes * ================== *//* Select attributes that stay in the local partition. */static const char **map_attrs_select_local(struct ldb_module *module, void *mem_ctx, const char * const *attrs){ const struct ldb_map_context *data = map_get_context(module); const char **result; int i, last; if (attrs == NULL) return NULL; last = 0; result = talloc_array(mem_ctx, const char *, 1); if (result == NULL) { goto failed; } result[0] = NULL; for (i = 0; attrs[i]; i++) { /* Wildcards and ignored attributes are kept locally */ if ((ldb_attr_cmp(attrs[i], "*") == 0) || (!map_attr_check_remote(data, attrs[i]))) { result = talloc_realloc(mem_ctx, result, const char *, last+2); if (result == NULL) { goto failed; } result[last] = talloc_strdup(result, attrs[i]); result[last+1] = NULL; last++; } } return result;failed: talloc_free(result); map_oom(module); return NULL;}/* Collect attributes that are mapped into the remote partition. */static const char **map_attrs_collect_remote(struct ldb_module *module, void *mem_ctx, const char * const *attrs){ const struct ldb_map_context *data = map_get_context(module); const char **result; const struct ldb_map_attribute *map; const char *name=NULL; int i, j, last; int ret; last = 0; result = talloc_array(mem_ctx, const char *, 1); if (result == NULL) { goto failed; } result[0] = NULL; for (i = 0; attrs[i]; i++) { /* Wildcards are kept remotely, too */ if (ldb_attr_cmp(attrs[i], "*") == 0) { const char **new_attrs = NULL; ret = map_attrs_merge(module, mem_ctx, &new_attrs, attrs); if (ret != LDB_SUCCESS) { goto failed; } ret = map_attrs_merge(module, mem_ctx, &new_attrs, data->wildcard_attributes); if (ret != LDB_SUCCESS) { goto failed; } attrs = new_attrs; break; } } for (i = 0; attrs[i]; i++) { /* Wildcards are kept remotely, too */ if (ldb_attr_cmp(attrs[i], "*") == 0) { /* Add all 'include in wildcard' attributes */ name = attrs[i]; goto named; } /* Add remote names of mapped attrs */ map = map_attr_find_local(data, attrs[i]); if (map == NULL) { continue; } switch (map->type) { case MAP_IGNORE: continue; case MAP_KEEP: name = attrs[i]; goto named; case MAP_RENAME: case MAP_CONVERT: name = map->u.rename.remote_name; goto named; case MAP_GENERATE: /* Add all remote names of "generate" attrs */ for (j = 0; map->u.generate.remote_names[j]; j++) { result = talloc_realloc(mem_ctx, result, const char *, last+2); if (result == NULL) { goto failed; } result[last] = talloc_strdup(result, map->u.generate.remote_names[j]); result[last+1] = NULL; last++; } continue; } named: /* We found a single remote name, add that */ result = talloc_realloc(mem_ctx, result, const char *, last+2); if (result == NULL) { goto failed; } result[last] = talloc_strdup(result, name); result[last+1] = NULL; last++; } return result;failed: talloc_free(result); map_oom(module); return NULL;}/* Split attributes that stay in the local partition from those that * are mapped into the remote partition. */static int map_attrs_partition(struct ldb_module *module, void *mem_ctx, const char ***local_attrs, const char ***remote_attrs, const char * const *attrs){ *local_attrs = map_attrs_select_local(module, mem_ctx, attrs); *remote_attrs = map_attrs_collect_remote(module, mem_ctx, attrs); return 0;}/* Mapping message elements * ======================== *//* Add an element to a message, overwriting any old identically named elements. */static int ldb_msg_replace(struct ldb_message *msg, const struct ldb_message_element *el){ struct ldb_message_element *old; old = ldb_msg_find_element(msg, el->name); /* no local result, add as new element */ if (old == NULL) { if (ldb_msg_add_empty(msg, el->name, 0, &old) != 0) { return -1; } talloc_free(old->name); } /* copy new element */ *old = *el; /* and make sure we reference the contents */ if (!talloc_reference(msg->elements, el->name)) { return -1; } if (!talloc_reference(msg->elements, el->values)) { return -1; } return 0;}/* Map a message element back into the local partition. */static struct ldb_message_element *ldb_msg_el_map_remote(struct ldb_module *module, void *mem_ctx, const struct ldb_map_attribute *map, const char *attr_name, const struct ldb_message_element *old){ struct ldb_message_element *el; int i; el = talloc_zero(mem_ctx, struct ldb_message_element); if (el == NULL) { map_oom(module); return NULL; } el->values = talloc_array(el, struct ldb_val, old->num_values); if (el->values == NULL) { talloc_free(el); map_oom(module); return NULL; } el->name = talloc_strdup(el, attr_name); if (el->name == NULL) { talloc_free(el); map_oom(module); return NULL; } for (i = 0; i < old->num_values; i++) { el->values[i] = ldb_val_map_remote(module, el->values, map, &old->values[i]); /* Conversions might fail, in which case bail */ if (!el->values[i].data) { talloc_free(el); return NULL; } el->num_values++; } return el;}/* Merge a remote message element into a local message. */static int ldb_msg_el_merge(struct ldb_module *module, struct ldb_message *local, struct ldb_message *remote, const char *attr_name){ const struct ldb_map_context *data = map_get_context(module); const struct ldb_map_attribute *map; struct ldb_message_element *old, *el=NULL; const char *remote_name = NULL; /* We handle wildcards in ldb_msg_el_merge_wildcard */ if (ldb_attr_cmp(attr_name, "*") == 0) { return LDB_SUCCESS; } map = map_attr_find_local(data, attr_name); /* Unknown attribute in remote message: * skip, attribute was probably auto-generated */ if (map == NULL) { return LDB_SUCCESS; } switch (map->type) { case MAP_IGNORE: break; case MAP_CONVERT: remote_name = map->u.convert.remote_name; break; case MAP_KEEP: remote_name = attr_name; break; case MAP_RENAME: remote_name = map->u.rename.remote_name; break; case MAP_GENERATE: break; } switch (map->type) { case MAP_IGNORE: return LDB_SUCCESS; case MAP_CONVERT: if (map->u.convert.convert_remote == NULL) { ldb_debug(module->ldb, LDB_DEBUG_ERROR, "ldb_map: " "Skipping attribute '%s': " "'convert_remote' not set\n", attr_name); return LDB_SUCCESS; } /* fall through */ case MAP_KEEP: case MAP_RENAME: old = ldb_msg_find_element(remote, remote_name); if (old) { el = ldb_msg_el_map_remote(module, local, map, attr_name, old); } else { return LDB_ERR_NO_SUCH_ATTRIBUTE; } break; case MAP_GENERATE: if (map->u.generate.generate_local == NULL) { ldb_debug(module->ldb, LDB_DEBUG_ERROR, "ldb_map: " "Skipping attribute '%s': " "'generate_local' not set\n", attr_name); return LDB_SUCCESS; } el = map->u.generate.generate_local(module, local, attr_name, remote); if (!el) { /* Generation failure is probably due to lack of source attributes */ return LDB_ERR_NO_SUCH_ATTRIBUTE; } break; } if (el == NULL) { return LDB_ERR_NO_SUCH_ATTRIBUTE; } return ldb_msg_replace(local, el);}/* Handle wildcard parts of merging a remote message element into a local message. */static int ldb_msg_el_merge_wildcard(struct ldb_module *module, struct ldb_message *local, struct ldb_message *remote){ const struct ldb_map_context *data = map_get_context(module); const struct ldb_map_attribute *map = map_attr_find_local(data, "*"); struct ldb_message_element *el=NULL; int i, ret; /* Perhaps we have a mapping for "*" */ if (map && map->type == MAP_KEEP) { /* We copy everything over, and hope that anything with a more specific rule is overwritten */ for (i = 0; i < remote->num_elements; i++) { el = ldb_msg_el_map_remote(module, local, map, remote->elements[i].name, &remote->elements[i]); if (el == NULL) { return LDB_ERR_OPERATIONS_ERROR; } ret = ldb_msg_replace(local, el); if (ret) { return ret; } } } /* Now walk the list of possible mappings, and apply each */ for (i = 0; data->attribute_maps[i].local_name; i++) { ret = ldb_msg_el_merge(module, local, remote, data->attribute_maps[i].local_name); if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) { continue; } else if (ret) { return ret; } else { continue; } } return LDB_SUCCESS;}/* Mapping messages * ================ *//* Merge two local messages into a single one. */static int ldb_msg_merge_local(struct ldb_module *module, struct ldb_message *msg1, struct ldb_message *msg2){ int i, ret; for (i = 0; i < msg2->num_elements; i++) { ret = ldb_msg_replace(msg1, &msg2->elements[i]); if (ret) { return ret; } } return LDB_SUCCESS;}/* Merge a local and a remote message into a single local one. */static int ldb_msg_merge_remote(struct map_context *ac, struct ldb_message *local, struct ldb_message *remote){ int i, ret; const char * const *attrs = ac->all_attrs; if (!attrs) { ret = ldb_msg_el_merge_wildcard(ac->module, local, remote); if (ret) { return ret; } } for (i = 0; attrs && attrs[i]; i++) { if (ldb_attr_cmp(attrs[i], "*") == 0) { ret = ldb_msg_el_merge_wildcard(ac->module, local, remote); if (ret) { return ret; } break; } } /* Try to map each attribute back; * Add to local message is possible, * Overwrite old local attribute if necessary */ for (i = 0; attrs && attrs[i]; i++) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -