[libgda] Initial LDAP write support, with dedicated API
- From: Vivien Malerba <vivien src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libgda] Initial LDAP write support, with dedicated API
- Date: Sat, 28 Apr 2012 17:28:25 +0000 (UTC)
commit 6fd47674f41cfe0a3e6f78c510ef9261d5b785fe
Author: Vivien Malerba <malerba gnome-db org>
Date: Sat Apr 28 18:18:47 2012 +0200
Initial LDAP write support, with dedicated API
doc/C/libgda-sections.txt | 9 +
libgda/gda-data-model-ldap.c | 50 ++++++
libgda/gda-data-model-ldap.h | 2 +-
libgda/libgda.symbols | 6 +
libgda/sqlite/virtual/gda-ldap-connection.c | 202 +++++++++++++++++++++++
libgda/sqlite/virtual/gda-ldap-connection.h | 35 ++++-
providers/ldap/gda-ldap-util.c | 86 ++++++++++-
providers/ldap/gda-ldap-util.h | 5 +
providers/ldap/gdaprov-data-model-ldap.c | 237 ++++++++++++++++++++++++++-
9 files changed, 627 insertions(+), 5 deletions(-)
---
diff --git a/doc/C/libgda-sections.txt b/doc/C/libgda-sections.txt
index 6bbce14..74351f1 100644
--- a/doc/C/libgda-sections.txt
+++ b/doc/C/libgda-sections.txt
@@ -258,10 +258,19 @@ gda_ldap_dn_split
gda_ldap_describe_entry
gda_ldap_entry_free
gda_ldap_get_entry_children
+<SUBSECTION>
+gda_ldap_entry_add_attribute
+gda_ldap_entry_new
GdaLdapAttributeDefinition
gda_ldap_entry_get_attributes_list
gda_ldap_attributes_list_free
<SUBSECTION>
+GdaLdapModificationType
+gda_ldap_add_entry
+gda_ldap_remove_entry
+gda_ldap_rename_entry
+gda_ldap_modify_entry
+<SUBSECTION>
GdaLdapClassKind
GdaLdapClass
gda_ldap_get_class_info
diff --git a/libgda/gda-data-model-ldap.c b/libgda/gda-data-model-ldap.c
index cc22a60..b87c954 100644
--- a/libgda/gda-data-model-ldap.c
+++ b/libgda/gda-data-model-ldap.c
@@ -486,3 +486,53 @@ _gda_ldap_entry_get_attributes_list (GdaLdapConnection *cnc, GdaLdapEntry *entry
return func (cnc, object_class_attr);
}
+
+/*
+ * _gda_ldap_modify:
+ * proxy to gda_ldap_add_entry() and others
+ */
+gboolean
+_gda_ldap_modify (GdaLdapConnection *cnc, GdaLdapModificationType modtype,
+ GdaLdapEntry *entry, GdaLdapEntry *ref_entry, GError **error)
+{
+ g_return_val_if_fail (GDA_IS_LDAP_CONNECTION (cnc), FALSE);
+
+ typedef gboolean (*Func) (GdaLdapConnection *, GdaLdapModificationType, GdaLdapEntry*, GdaLdapEntry*,
+ GError **);
+ static Func func = NULL;
+
+ if (!func) {
+ load_ldap_module ();
+ if (!ldap_prov_module)
+ return FALSE;
+
+ if (!g_module_symbol (ldap_prov_module, "gdaprov_ldap_modify", (void **) &func))
+ return FALSE;
+ }
+
+ return func (cnc, modtype, entry, ref_entry, error);
+}
+
+/*
+ * _gda_ldap_rename_entry:
+ * proxy to gda_ldap_rename_entry()
+ */
+gboolean
+_gda_ldap_rename_entry (GdaLdapConnection *cnc, const gchar *current_dn, const gchar *new_dn, GError **error)
+{
+ g_return_val_if_fail (GDA_IS_LDAP_CONNECTION (cnc), FALSE);
+
+ typedef gboolean (*Func) (GdaLdapConnection *, const gchar*, const gchar*, GError **);
+ static Func func = NULL;
+
+ if (!func) {
+ load_ldap_module ();
+ if (!ldap_prov_module)
+ return FALSE;
+
+ if (!g_module_symbol (ldap_prov_module, "gdaprov_ldap_rename_entry", (void **) &func))
+ return FALSE;
+ }
+
+ return func (cnc, current_dn, new_dn, error);
+}
diff --git a/libgda/gda-data-model-ldap.h b/libgda/gda-data-model-ldap.h
index 702a9ef..6020cfa 100644
--- a/libgda/gda-data-model-ldap.h
+++ b/libgda/gda-data-model-ldap.h
@@ -85,7 +85,7 @@ GdaDataModelLdap *gda_data_model_ldap_new_with_config (GdaConnection *cnc,
const gchar *base_dn, const gchar *filter,
const gchar *attributes, GdaLdapSearchScope scope);
-GList *gda_data_model_ldap_compute_columns (GdaConnection *cnc, const gchar *attributes);
+GList *gda_data_model_ldap_compute_columns (GdaConnection *cnc, const gchar *attributes);
G_END_DECLS
diff --git a/libgda/libgda.symbols b/libgda/libgda.symbols
index e83074b..a10f481 100644
--- a/libgda/libgda.symbols
+++ b/libgda/libgda.symbols
@@ -417,6 +417,7 @@
gda_init
gda_lang_locale
#ifdef HAVE_LDAP
+ gda_ldap_add_entry
gda_ldap_attributes_list_free
gda_ldap_connection_get_type
gda_ldap_get_class_info
@@ -427,10 +428,15 @@
gda_ldap_connection_undeclare_table
gda_ldap_describe_entry
gda_ldap_dn_split
+ gda_ldap_entry_add_attribute
+ gda_ldap_entry_new
gda_ldap_entry_free
gda_ldap_entry_get_attributes_list
gda_ldap_get_entry_children
gda_ldap_is_dn
+ gda_ldap_modify_entry
+ gda_ldap_remove_entry
+ gda_ldap_rename_entry
#endif
gda_locale_changed
gda_lockable_get_type
diff --git a/libgda/sqlite/virtual/gda-ldap-connection.c b/libgda/sqlite/virtual/gda-ldap-connection.c
index 314b98e..84b4e1c 100644
--- a/libgda/sqlite/virtual/gda-ldap-connection.c
+++ b/libgda/sqlite/virtual/gda-ldap-connection.c
@@ -878,6 +878,104 @@ gda_ldap_entry_free (GdaLdapEntry *entry)
}
}
+/**
+ * gda_ldap_entry_new:
+ * @dn: (allow-none): a Distinguished name, or %NULL
+ *
+ * Creates a new #GdaLdapEntry. This function is useful when using gda_ldap_modify_entry()
+ *
+ * Returns: a new #GdaLdapEntry
+ *
+ * Since: 5.2.0
+ */
+GdaLdapEntry *
+gda_ldap_entry_new (const gchar *dn)
+{
+ GdaLdapEntry *entry;
+ entry = g_new0 (GdaLdapEntry, 1);
+ if (dn)
+ entry->dn = g_strdup (dn);
+ entry->attributes_hash = g_hash_table_new (g_str_hash, g_str_equal);
+ entry->nb_attributes = 0;
+ entry->attributes = g_new0 (GdaLdapAttribute, 1);
+ return entry;
+}
+
+/**
+ * gda_ldap_entry_add_attribute:
+ * @entry: a #GdaLdapEntry pointer
+ * @merge: set to %TRUE to merge the values in case of an existing attribute in @entry, and %FALSE to replace any existing attribute's values in @entry
+ * @attr_name: the name of the attribute to add
+ * @nb_values: number of values in @values
+ * @values: (array length=nb_values): an array of #GValue (as much values as specified by @nb_values)
+ *
+ * Add an attribute (ans its values) to @entry. If the attribute is already present in @entry,
+ * then the attribute's values are merged or replaced depending on the @merge argument.
+ *
+ * Since: 5.2.0
+ */
+void
+gda_ldap_entry_add_attribute (GdaLdapEntry *entry, gboolean merge, const gchar *attr_name,
+ guint nb_values, GValue **values)
+{
+ guint i;
+ g_return_if_fail (entry);
+ g_return_if_fail (nb_values > 0);
+ g_return_if_fail (values);
+ g_return_if_fail (attr_name && *attr_name);
+
+ GdaLdapAttribute *att = NULL;
+ GdaLdapAttribute *natt = NULL;
+ guint replace_pos = G_MAXUINT;
+
+ if (entry->attributes_hash)
+ att = g_hash_table_lookup (entry->attributes_hash, attr_name);
+ else
+ entry->attributes_hash = g_hash_table_new (g_str_hash, g_str_equal);
+
+ if (att) {
+ if (merge) {
+ TO_IMPLEMENT;
+ return;
+ }
+ else {
+ /* get rid of @attr */
+ g_hash_table_remove (entry->attributes_hash, att->attr_name);
+ for (i = 0; i < entry->nb_attributes; i++) {
+ if (entry->attributes [i] == att) {
+ replace_pos = i;
+ entry->attributes [i] = NULL;
+ break;
+ }
+ }
+ gda_ldap_attribute_free (att);
+ }
+ }
+
+ natt = g_new0 (GdaLdapAttribute, 1);
+ natt->attr_name = g_strdup (attr_name);
+ natt->nb_values = nb_values;
+ if (natt->nb_values > 0) {
+ natt->values = g_new0 (GValue *, natt->nb_values + 1);
+ for (i = 0; i < natt->nb_values; i++) {
+ if (values [i])
+ natt->values [i] = gda_value_copy (values [i]);
+ else
+ natt->values [i] = NULL;
+ }
+ }
+ g_hash_table_insert (entry->attributes_hash, natt->attr_name, natt);
+ if (replace_pos != G_MAXUINT)
+ entry->attributes [replace_pos] = natt;
+ else {
+ entry->nb_attributes++;
+ entry->attributes = g_renew (GdaLdapAttribute*, entry->attributes, entry->nb_attributes + 1);
+ entry->attributes [entry->nb_attributes - 1] = natt;
+ entry->attributes [entry->nb_attributes] = NULL;
+ }
+}
+
+
/* proxy declaration */
GdaLdapEntry *_gda_ldap_describe_entry (GdaLdapConnection *cnc, const gchar *dn, GError **error);
GdaLdapEntry **_gda_ldap_get_entry_children (GdaLdapConnection *cnc, const gchar *dn, gchar **attributes, GError **error);
@@ -1027,6 +1125,7 @@ gda_ldap_get_top_classes (GdaLdapConnection *cnc)
GSList *_gda_ldap_entry_get_attributes_list (GdaLdapConnection *cnc, GdaLdapEntry *entry, GdaLdapAttribute *object_class_attr);
/**
* gda_ldap_entry_get_attributes_list:
+ * @cnc: a #GdaLdapConnection
* @entry: a #GdaLdapEntry
*
* Get a list of all the possible attributes which @entry can have. Each possible attribute is represented
@@ -1068,3 +1167,106 @@ gda_ldap_attributes_list_free (GSList *list)
}
g_slist_free (list);
}
+
+
+gboolean
+_gda_ldap_modify (GdaLdapConnection *cnc, GdaLdapModificationType modtype,
+ GdaLdapEntry *entry, GdaLdapEntry *ref_entry, GError **error);
+
+/**
+ * gda_ldap_add_entry:
+ * @cnc: a #GdaLdapConnection
+ * @entry: a #GdaLDapEntry describing the LDAP entry to add
+ * @error: (allow-none): a place to store an error, or %NULL
+ *
+ * Creates a new LDAP entry.
+ *
+ * Returns: %TRUE if no error occurred
+ *
+ * Since: 5.2.0
+ */
+gboolean
+gda_ldap_add_entry (GdaLdapConnection *cnc, GdaLdapEntry *entry, GError **error)
+{
+ g_return_val_if_fail (GDA_IS_LDAP_CONNECTION (cnc), FALSE);
+ g_return_val_if_fail (entry, FALSE);
+ g_return_val_if_fail (entry->dn && *(entry->dn), FALSE);
+
+ return _gda_ldap_modify (cnc, GDA_LDAP_MODIFICATION_INSERT, entry, NULL, error);
+}
+
+/**
+ * gda_ldap_remove_entry:
+ * @cnc: a #GdaLdapConnection
+ * @entry: a #GdaLDapEntry describing the LDAP entry to remove
+ * @error: (allow-none): a place to store an error, or %NULL
+ *
+ * Delete an LDAP entry.
+ *
+ * Returns: %TRUE if no error occurred
+ *
+ * Since: 5.2.0
+ */
+gboolean
+gda_ldap_remove_entry (GdaLdapConnection *cnc, const gchar *dn, GError **error)
+{
+ g_return_val_if_fail (GDA_IS_LDAP_CONNECTION (cnc), FALSE);
+ g_return_val_if_fail (dn && *dn, FALSE);
+
+ GdaLdapEntry entry;
+ memset (&entry, 0, sizeof (GdaLdapEntry));
+ entry.dn = (gchar*) dn;
+
+ return _gda_ldap_modify (cnc, GDA_LDAP_MODIFICATION_DELETE, &entry, NULL, error);
+}
+
+gboolean
+_gda_ldap_rename_entry (GdaLdapConnection *cnc, const gchar *current_dn, const gchar *new_dn, GError **error);
+
+/**
+ * gda_ldap_rename_entry:
+ * @cnc: a #GdaLdapConnection
+ * @current_dn: the current DN of the entry
+ * @new_dn: the new DN of the entry
+ * @error: (allow-none): a place to store an error, or %NULL
+ *
+ * Renames an LDAP entry.
+ *
+ * Returns: %TRUE if no error occurred
+ *
+ * Since: 5.2.0
+ */
+gboolean
+gda_ldap_rename_entry (GdaLdapConnection *cnc, const gchar *current_dn, const gchar *new_dn, GError **error)
+{
+ g_return_val_if_fail (GDA_IS_LDAP_CONNECTION (cnc), FALSE);
+ g_return_val_if_fail (current_dn && *current_dn, FALSE);
+ g_return_val_if_fail (new_dn && *new_dn, FALSE);
+
+ return _gda_ldap_rename_entry (cnc, current_dn, new_dn, error);
+}
+
+/**
+ * gda_ldap_modify_entry:
+ * @cnc: a #GdaLdapConnection
+ * @modtype: the type of modification to perform
+ * @entry: a #GdaLDapEntry describing the LDAP entry to apply modifications, along with the attributes which will be modified
+ * @ref_entry: (allow-none): a #GdaLDapEntry describing the reference LDAP entry, if @modtype is %GDA_LDAP_MODIFICATION_ATTR_DIFF
+ * @error: (allow-none): a place to store an error, or %NULL
+ *
+ * Modifies an LDAP entry.
+ *
+ * Returns: %TRUE if no error occurred
+ *
+ * Since: 5.2.0
+ */
+gboolean
+gda_ldap_modify_entry (GdaLdapConnection *cnc, GdaLdapModificationType modtype,
+ GdaLdapEntry *entry, GdaLdapEntry *ref_entry, GError **error)
+{
+ g_return_val_if_fail (GDA_IS_LDAP_CONNECTION (cnc), FALSE);
+ g_return_val_if_fail (entry, FALSE);
+ g_return_val_if_fail (entry->dn && *(entry->dn), FALSE);
+
+ return _gda_ldap_modify (cnc, modtype, entry, ref_entry, error);
+}
diff --git a/libgda/sqlite/virtual/gda-ldap-connection.h b/libgda/sqlite/virtual/gda-ldap-connection.h
index 4269163..1816252 100644
--- a/libgda/sqlite/virtual/gda-ldap-connection.h
+++ b/libgda/sqlite/virtual/gda-ldap-connection.h
@@ -162,7 +162,11 @@ typedef struct {
GHashTable *attributes_hash;
} GdaLdapEntry;
+GdaLdapEntry *gda_ldap_entry_new (const gchar *dn);
+void gda_ldap_entry_add_attribute (GdaLdapEntry *entry, gboolean merge, const gchar *attr_name,
+ guint nb_values, GValue **values);
void gda_ldap_entry_free (GdaLdapEntry *entry);
+
GdaLdapEntry *gda_ldap_describe_entry (GdaLdapConnection *cnc, const gchar *dn, GError **error);
GdaLdapEntry **gda_ldap_get_entry_children (GdaLdapConnection *cnc, const gchar *dn,
gchar **attributes, GError **error);
@@ -225,13 +229,40 @@ typedef struct {
guint nb_opt_attributes;
gchar **opt_attributes;
- GSList *parents; /* list of #LdapClass */
- GSList *children; /* list of #LdapClass */
+ GSList *parents; /* list of #GdaLdapClass */
+ GSList *children; /* list of #GdaLdapClass */
} GdaLdapClass;
GdaLdapClass *gda_ldap_get_class_info (GdaLdapConnection *cnc, const gchar *classname);
const GSList *gda_ldap_get_top_classes (GdaLdapConnection *cnc);
+
+/**
+ * GdaLdapModificationType:
+ * @GDA_LDAP_MODIFICATION_INSERT: modification corresponds to a new LDAP entry
+ * @GDA_LDAP_MODIFICATION_DELETE: modification corresponds to removing an LDAP entry
+ * @GDA_LDAP_MODIFICATION_ATTR_ADD: modification correspond to adding attributes to an existing LDAP entry
+ * @GDA_LDAP_MODIFICATION_ATTR_DEL: modification correspond to removing attributes from an existing LDAP entry
+ * @GDA_LDAP_MODIFICATION_ATTR_REPL: modification correspond to replacing attributes of an existing LDAP entry
+ * @GDA_LDAP_MODIFICATION_ATTR_DIFF: modification correspond to modifying attributes to an existing LDAP entry
+ *
+ * Speficies the type of operation requested when writing to an LDAP directory.
+ */
+typedef enum {
+ GDA_LDAP_MODIFICATION_INSERT,
+ GDA_LDAP_MODIFICATION_DELETE,
+ GDA_LDAP_MODIFICATION_ATTR_ADD,
+ GDA_LDAP_MODIFICATION_ATTR_DEL,
+ GDA_LDAP_MODIFICATION_ATTR_REPL,
+ GDA_LDAP_MODIFICATION_ATTR_DIFF
+} GdaLdapModificationType;
+
+gboolean gda_ldap_add_entry (GdaLdapConnection *cnc, GdaLdapEntry *entry, GError **error);
+gboolean gda_ldap_remove_entry (GdaLdapConnection *cnc, const gchar *dn, GError **error);
+gboolean gda_ldap_rename_entry (GdaLdapConnection *cnc, const gchar *current_dn, const gchar *new_dn, GError **error);
+gboolean gda_ldap_modify_entry (GdaLdapConnection *cnc, GdaLdapModificationType modtype,
+ GdaLdapEntry *entry, GdaLdapEntry *ref_entry, GError **error);
+
G_END_DECLS
#endif
diff --git a/providers/ldap/gda-ldap-util.c b/providers/ldap/gda-ldap-util.c
index 489c17d..1fd722d 100644
--- a/providers/ldap/gda-ldap-util.c
+++ b/providers/ldap/gda-ldap-util.c
@@ -918,6 +918,90 @@ gda_ldap_attr_value_to_g_value (LdapConnectionData *cdata, GType type, BerValue
return value;
}
+BerValue *
+gda_ldap_attr_g_value_to_value (LdapConnectionData *cdata, const GValue *cvalue)
+{
+ BerValue *bv;
+
+ if (!cvalue)
+ return NULL;
+
+ bv = g_new (struct berval, 1);
+
+ if (G_VALUE_TYPE (cvalue) == G_TYPE_STRING) {
+ const gchar *cstr;
+ cstr = g_value_get_string (cvalue);
+ bv->bv_val = g_strdup (cstr);
+ bv->bv_len = strlen (cstr);
+ }
+ else if (G_VALUE_TYPE (cvalue) == GDA_TYPE_TIMESTAMP) {
+ const GdaTimestamp *ts;
+ gchar *str;
+ ts = gda_value_get_timestamp (cvalue);
+ if (ts->fraction == 0) {
+ if (ts->timezone == GDA_TIMEZONE_INVALID)
+ str = g_strdup_printf ("%04d-%02d-%02dT%02d:%02d:%02d", ts->year, ts->month,
+ ts->day, ts->hour, ts->minute, ts->second);
+ else {
+ str = g_strdup_printf ("%04d-%02d-%02dT%02d:%02d:%02d", ts->year, ts->month,
+ ts->day, ts->hour, ts->minute, ts->second);
+ TO_IMPLEMENT;
+ }
+ }
+ else {
+ if (ts->timezone == GDA_TIMEZONE_INVALID)
+ str = g_strdup_printf ("%04d-%02d-%02dT%02d:%02d:%02d,%lu", ts->year, ts->month,
+ ts->day, ts->hour, ts->minute, ts->second,
+ ts->fraction);
+ else {
+ str = g_strdup_printf ("%04d-%02d-%02dT%02d:%02d:%02d,%lu", ts->year, ts->month,
+ ts->day, ts->hour, ts->minute, ts->second,
+ ts->fraction);
+ TO_IMPLEMENT;
+ }
+ }
+ bv->bv_val = str;
+ bv->bv_len = strlen (str);
+ }
+ else if (G_VALUE_TYPE (cvalue) == G_TYPE_DATE) {
+ GDate *date;
+ gchar *str;
+ date = (GDate*) g_value_get_boxed (cvalue);
+ str = g_strdup_printf ("%04d-%02d-%02d", g_date_get_year (date), g_date_get_month (date),
+ g_date_get_day (date));
+ bv->bv_val = str;
+ bv->bv_len = strlen (str);
+ }
+ else if (G_VALUE_TYPE (cvalue) == GDA_TYPE_NULL) {
+ bv->bv_val = NULL;
+ bv->bv_len = 0;
+ }
+ else if (G_VALUE_TYPE (cvalue) == GDA_TYPE_BINARY) {
+ TO_IMPLEMENT;
+ }
+ else if (G_VALUE_TYPE (cvalue) == GDA_TYPE_BLOB) {
+ TO_IMPLEMENT;
+ }
+ else {
+ gchar *str;
+ str = gda_value_stringify (cvalue);
+ bv->bv_val = str;
+ bv->bv_len = strlen (str);
+ }
+ return bv;
+}
+
+/*
+ * Frees @bvalue, which MUST have been created using gda_ldap_attr_g_value_to_value()
+ */
+void
+gda_ldap_attr_value_free (LdapConnectionData *cdata, BerValue *bvalue)
+{
+ g_free (bvalue->bv_val);
+ g_free (bvalue);
+}
+
+
/*
* make sure we respect http://www.faqs.org/rfcs/rfc2253.html
*/
@@ -1526,7 +1610,7 @@ gdaprov_ldap_get_attributes_list (GdaLdapConnection *cnc, GdaLdapAttribute *obje
GdaLdapClass *kl;
kl = gdaprov_ldap_get_class_info (cnc, tmp);
if (!kl) {
- g_warning (_("Can't get information about '%s' class"), tmp);
+ /*g_warning (_("Can't get information about '%s' class"), tmp);*/
continue;
}
retlist = handle_ldap_class (cdata, kl, retlist, hash);
diff --git a/providers/ldap/gda-ldap-util.h b/providers/ldap/gda-ldap-util.h
index f9800e7..0766831 100644
--- a/providers/ldap/gda-ldap-util.h
+++ b/providers/ldap/gda-ldap-util.h
@@ -50,6 +50,11 @@ GType gda_ldap_get_g_type (LdapConnectionData *cdata, const gchar *a
* Misc.
*/
GValue *gda_ldap_attr_value_to_g_value (LdapConnectionData *cdata, GType type, BerValue *bv);
+BerValue *gda_ldap_attr_g_value_to_value (LdapConnectionData *cdata, const GValue *cvalue);
+void gda_ldap_attr_value_free (LdapConnectionData *cdata, BerValue *bvalue);
+
gboolean gda_ldap_parse_dn (const char *attr, gchar **out_userdn);
+gboolean gdaprov_ldap_is_dn (const gchar *dn);
+
#endif
diff --git a/providers/ldap/gdaprov-data-model-ldap.c b/providers/ldap/gdaprov-data-model-ldap.c
index 8c33aff..acaca76 100644
--- a/providers/ldap/gdaprov-data-model-ldap.c
+++ b/providers/ldap/gdaprov-data-model-ldap.c
@@ -1055,7 +1055,7 @@ execute_ldap_search (GdaDataModelLdap *model)
int ldap_errno;
ldap_get_option (cdata->handle, LDAP_OPT_ERROR_NUMBER, &ldap_errno);
g_set_error (&e, GDA_DATA_MODEL_ERROR, GDA_DATA_MODEL_OTHER_ERROR,
- "%s", ldap_err2string(ldap_errno));
+ "%s", ldap_err2string (ldap_errno));
add_exception (model, e);
return;
}
@@ -1501,3 +1501,238 @@ row_multiplier_index_next (RowMultiplier *rm)
}
}
}
+
+/*
+ * Writing support
+ */
+
+typedef struct {
+ LdapConnectionData *cdata;
+ GArray *mods_array;
+} FHData;
+static void removed_attrs_func (const gchar *attr_name, GdaLdapAttribute *attr, FHData *data);
+
+gboolean
+gdaprov_ldap_modify (GdaLdapConnection *cnc, GdaLdapModificationType modtype,
+ GdaLdapEntry *entry, GdaLdapEntry *ref_entry, GError **error)
+{
+ LdapConnectionData *cdata;
+ int res;
+
+ g_return_val_if_fail (GDA_IS_LDAP_CONNECTION (cnc), FALSE);
+ g_return_val_if_fail (entry, FALSE);
+ if (entry)
+ g_return_val_if_fail (gdaprov_ldap_is_dn (entry->dn), FALSE);
+ if (ref_entry)
+ g_return_val_if_fail (gdaprov_ldap_is_dn (ref_entry->dn), FALSE);
+
+ cdata = (LdapConnectionData*) gda_virtual_connection_internal_get_provider_data (GDA_VIRTUAL_CONNECTION (cnc));
+ g_return_val_if_fail (cdata, FALSE);
+
+ /* checks */
+ if ((modtype != GDA_LDAP_MODIFICATION_INSERT) &&
+ (modtype != GDA_LDAP_MODIFICATION_ATTR_ADD) &&
+ (modtype != GDA_LDAP_MODIFICATION_ATTR_DEL) &&
+ (modtype != GDA_LDAP_MODIFICATION_ATTR_REPL) &&
+ (modtype != GDA_LDAP_MODIFICATION_ATTR_DIFF)) {
+ g_warning (_("Unknown GdaLdapModificationType %d"), modtype);
+ return FALSE;
+ }
+
+ if (((modtype == GDA_LDAP_MODIFICATION_DELETE) || (modtype == GDA_LDAP_MODIFICATION_INSERT)) &&
+ !entry) {
+ g_warning ("%s", _("No GdaLdapEntry specified"));
+ return FALSE;
+ }
+
+ if ((modtype == GDA_LDAP_MODIFICATION_ATTR_ADD) && !entry) {
+ g_warning ("%s", _("No GdaLdapEntry specified to define attributes to add"));
+ return FALSE;
+ }
+
+ if ((modtype == GDA_LDAP_MODIFICATION_ATTR_DEL) && !entry) {
+ g_warning ("%s", _("No GdaLdapEntry specified to define attributes to remove"));
+ return FALSE;
+ }
+
+ if ((modtype == GDA_LDAP_MODIFICATION_ATTR_REPL) && !entry) {
+ g_warning ("%s", _("No GdaLdapEntry specified to define attributes to replace"));
+ return FALSE;
+ }
+
+ if ((modtype == GDA_LDAP_MODIFICATION_ATTR_DIFF) && (!entry || !ref_entry)) {
+ g_warning ("%s", _("No GdaLdapEntry specified to compare attributes"));
+ return FALSE;
+ }
+ if ((modtype == GDA_LDAP_MODIFICATION_ATTR_DIFF) && strcmp (entry->dn, ref_entry->dn)) {
+ g_warning ("%s", _("GdaLdapEntry specified to compare have different DN"));
+ return FALSE;
+ }
+
+ /* handle DELETE operation */
+ if (modtype == GDA_LDAP_MODIFICATION_DELETE) {
+ res = ldap_delete_ext_s (cdata->handle, entry->dn, NULL, NULL);
+ if (res != LDAP_SUCCESS) {
+ g_set_error (error, GDA_DATA_MODEL_ERROR, GDA_DATA_MODEL_OTHER_ERROR,
+ "%s", ldap_err2string (res));
+ return FALSE;
+ }
+ else
+ return TRUE;
+ }
+
+ /* build array of modifications to perform */
+ GArray *mods_array;
+ mods_array = g_array_new (TRUE, FALSE, sizeof (LDAPMod*));
+ if (modtype == GDA_LDAP_MODIFICATION_ATTR_DIFF) {
+ /* index ref_entry's attributes */
+ GHashTable *hash;
+ guint i;
+ hash = g_hash_table_new (g_str_hash, g_str_equal);
+ for (i = 0; i < ref_entry->nb_attributes; i++) {
+ GdaLdapAttribute *attr;
+ attr = ref_entry->attributes [i];
+ g_hash_table_insert (hash, attr->attr_name, attr);
+ }
+
+ for (i = 0; i < entry->nb_attributes; i++) {
+ LDAPMod *mod;
+ GdaLdapAttribute *attr, *ref_attr;
+ guint j;
+
+ attr = entry->attributes [i];
+ ref_attr = g_hash_table_lookup (hash, attr->attr_name);
+
+ mod = g_new0 (LDAPMod, 1);
+ mod->mod_type = attr->attr_name; /* no duplication */
+ if (ref_attr) {
+ mod->mod_op = LDAP_MOD_BVALUES | LDAP_MOD_REPLACE;
+ g_hash_table_remove (hash, attr->attr_name);
+ }
+ else
+ mod->mod_op = LDAP_MOD_BVALUES | LDAP_MOD_ADD;
+
+ mod->mod_bvalues = g_new0 (struct berval *, attr->nb_values + 1); /* last is NULL */
+ for (j = 0; j < attr->nb_values; j++)
+ mod->mod_bvalues[j] = gda_ldap_attr_g_value_to_value (cdata, attr->values [j]);
+ g_array_append_val (mods_array, mod);
+ }
+
+ FHData fhdata;
+ fhdata.cdata = cdata;
+ fhdata.mods_array = mods_array;
+ g_hash_table_foreach (hash, (GHFunc) removed_attrs_func, &fhdata);
+ g_hash_table_destroy (hash);
+ }
+ else {
+ guint i;
+ for (i = 0; i < entry->nb_attributes; i++) {
+ LDAPMod *mod;
+ GdaLdapAttribute *attr;
+ guint j;
+
+ attr = entry->attributes [i];
+ mod = g_new0 (LDAPMod, 1);
+ mod->mod_op = LDAP_MOD_BVALUES;
+ if ((modtype == GDA_LDAP_MODIFICATION_INSERT) ||
+ (modtype == GDA_LDAP_MODIFICATION_ATTR_ADD))
+ mod->mod_op |= LDAP_MOD_ADD;
+ else if (modtype == GDA_LDAP_MODIFICATION_ATTR_DEL)
+ mod->mod_op |= LDAP_MOD_DELETE;
+ else
+ mod->mod_op |= LDAP_MOD_REPLACE;
+ mod->mod_type = attr->attr_name; /* no duplication */
+ mod->mod_bvalues = g_new0 (struct berval *, attr->nb_values + 1); /* last is NULL */
+ for (j = 0; j < attr->nb_values; j++)
+ mod->mod_bvalues[j] = gda_ldap_attr_g_value_to_value (cdata, attr->values [j]);
+ g_array_append_val (mods_array, mod);
+ }
+ }
+
+ gboolean retval = TRUE;
+ if (mods_array->len > 0) {
+ /* apply modifications */
+ if (modtype == GDA_LDAP_MODIFICATION_INSERT)
+ res = ldap_add_ext_s (cdata->handle, entry->dn, (LDAPMod **) mods_array->data, NULL, NULL);
+ else
+ res = ldap_modify_ext_s (cdata->handle, entry->dn, (LDAPMod **) mods_array->data, NULL, NULL);
+
+ if (res != LDAP_SUCCESS) {
+ g_set_error (error, GDA_DATA_MODEL_ERROR, GDA_DATA_MODEL_OTHER_ERROR,
+ "%s", ldap_err2string (res));
+ retval = FALSE;
+ }
+ }
+
+ /* clear tmp data */
+ guint i;
+ for (i = 0; i < mods_array->len; i++) {
+ LDAPMod *mod;
+ mod = g_array_index (mods_array, LDAPMod*, i);
+ if (mod->mod_values) {
+ guint j;
+ for (j = 0; mod->mod_values [j]; j++)
+ gda_ldap_attr_value_free (cdata, mod->mod_bvalues [j]);
+ g_free (mod->mod_values);
+ }
+ g_free (mod);
+ }
+ g_array_free (mods_array, TRUE);
+
+ return retval;
+}
+
+static void
+removed_attrs_func (const gchar *attr_name, GdaLdapAttribute *attr, FHData *data)
+{
+ LDAPMod *mod;
+ guint j;
+
+ mod = g_new0 (LDAPMod, 1);
+ mod->mod_op = LDAP_MOD_BVALUES | LDAP_MOD_DELETE;
+ mod->mod_type = attr->attr_name; /* no duplication */
+ mod->mod_bvalues = g_new0 (struct berval *, attr->nb_values + 1); /* last is NULL */
+ for (j = 0; j < attr->nb_values; j++)
+ mod->mod_bvalues[j] = gda_ldap_attr_g_value_to_value (data->cdata, attr->values [j]);
+ g_array_append_val (data->mods_array, mod);
+}
+
+gboolean
+gdaprov_ldap_rename_entry (GdaLdapConnection *cnc, const gchar *current_dn, const gchar *new_dn,
+ GError **error)
+{
+ g_return_val_if_fail (GDA_IS_LDAP_CONNECTION (cnc), FALSE);
+ g_return_val_if_fail (current_dn && *current_dn, FALSE);
+ g_return_val_if_fail (gdaprov_ldap_is_dn (current_dn), FALSE);
+ g_return_val_if_fail (new_dn && *new_dn, FALSE);
+ g_return_val_if_fail (gdaprov_ldap_is_dn (new_dn), FALSE);
+
+ LdapConnectionData *cdata;
+ cdata = (LdapConnectionData*) gda_virtual_connection_internal_get_provider_data (GDA_VIRTUAL_CONNECTION (cnc));
+ g_return_val_if_fail (cdata, FALSE);
+
+ gchar **carray, **narray;
+ int res;
+ gboolean retval = TRUE;
+ gchar *parent = NULL;
+
+ carray = gda_ldap_dn_split (current_dn, FALSE);
+ narray = gda_ldap_dn_split (new_dn, FALSE);
+
+ if (carray[1] && narray[1] && strcmp (carray[1], narray[1]))
+ parent = narray [1];
+ else if (! carray[1] && narray[1])
+ parent = narray [1];
+
+ res = ldap_rename_s (cdata->handle, current_dn, narray[0], parent, 1, NULL, NULL);
+ g_strfreev (carray);
+ g_strfreev (narray);
+
+ if (res != LDAP_SUCCESS) {
+ g_set_error (error, GDA_DATA_MODEL_ERROR, GDA_DATA_MODEL_OTHER_ERROR,
+ "%s", ldap_err2string (res));
+ retval = FALSE;
+ }
+
+ return retval;
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]