1 /*
2 * Copyright (C) 2011 Vivien Malerba <malerba@gnome-db.org>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20 #include <glib/gi18n-lib.h>
21 #include <libgda/libgda.h>
22 #include "gda-tree-mgr-ldap.h"
23 #include "gda-tree-node.h"
24 #include <sqlite/virtual/gda-ldap-connection.h>
25
26 struct _GdaTreeMgrLdapPriv {
27 GdaLdapConnection *cnc;
28 gchar *dn;
29 };
30
31 static void gda_tree_mgr_ldap_class_init (GdaTreeMgrLdapClass *klass);
32 static void gda_tree_mgr_ldap_init (GdaTreeMgrLdap *tmgr1, GdaTreeMgrLdapClass *klass);
33 static void gda_tree_mgr_ldap_dispose (GObject *object);
34 static void gda_tree_mgr_ldap_set_property (GObject *object,
35 guint param_id,
36 const GValue *value,
37 GParamSpec *pspec);
38 static void gda_tree_mgr_ldap_get_property (GObject *object,
39 guint param_id,
40 GValue *value,
41 GParamSpec *pspec);
42
43 /* virtual methods */
44 static GSList *gda_tree_mgr_ldap_update_children (GdaTreeManager *manager, GdaTreeNode *node, const GSList *children_nodes,
45 gboolean *out_error, GError **error);
46
47 static GObjectClass *parent_class = NULL;
48
49 /* properties */
50 enum {
51 PROP_0,
52 PROP_CNC,
53 PROP_DN,
54 };
55
56 /*
57 * GdaTreeMgrLdap class implementation
58 * @klass:
59 */
60 static void
gda_tree_mgr_ldap_class_init(GdaTreeMgrLdapClass * klass)61 gda_tree_mgr_ldap_class_init (GdaTreeMgrLdapClass *klass)
62 {
63 GObjectClass *object_class = G_OBJECT_CLASS (klass);
64
65 parent_class = g_type_class_peek_parent (klass);
66
67 /* virtual methods */
68 ((GdaTreeManagerClass*) klass)->update_children = gda_tree_mgr_ldap_update_children;
69
70 /* Properties */
71 object_class->set_property = gda_tree_mgr_ldap_set_property;
72 object_class->get_property = gda_tree_mgr_ldap_get_property;
73
74 /**
75 * GdaTreeMgrLdap:connection:
76 *
77 * Defines the #GdaLdapConnection to get information from.
78 */
79 g_object_class_install_property (object_class, PROP_CNC,
80 g_param_spec_object ("connection", NULL, "Connection to use",
81 GDA_TYPE_LDAP_CONNECTION,
82 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
83
84 /**
85 * GdaTreeMgrLdap:dn:
86 *
87 * Defines the Distinguised Name of the LDAP entry to list children from
88 */
89 g_object_class_install_property (object_class, PROP_DN,
90 g_param_spec_string ("dn", NULL, "Distinguised Name",
91 NULL,
92 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
93 object_class->dispose = gda_tree_mgr_ldap_dispose;
94 }
95
96 static void
gda_tree_mgr_ldap_init(GdaTreeMgrLdap * mgr,G_GNUC_UNUSED GdaTreeMgrLdapClass * klass)97 gda_tree_mgr_ldap_init (GdaTreeMgrLdap *mgr, G_GNUC_UNUSED GdaTreeMgrLdapClass *klass)
98 {
99 g_return_if_fail (GDA_IS_TREE_MGR_LDAP (mgr));
100 mgr->priv = g_new0 (GdaTreeMgrLdapPriv, 1);
101 }
102
103 static void
gda_tree_mgr_ldap_dispose(GObject * object)104 gda_tree_mgr_ldap_dispose (GObject *object)
105 {
106 GdaTreeMgrLdap *mgr = (GdaTreeMgrLdap *) object;
107
108 g_return_if_fail (GDA_IS_TREE_MGR_LDAP (mgr));
109
110 if (mgr->priv) {
111 if (mgr->priv->cnc)
112 g_object_unref (mgr->priv->cnc);
113 g_free (mgr->priv->dn);
114 g_free (mgr->priv);
115 mgr->priv = NULL;
116 }
117
118 /* chain to parent class */
119 parent_class->dispose (object);
120 }
121
122 /**
123 * gda_tree_mgr_ldap_get_type:
124 *
125 * Returns: the GType
126 *
127 * Since: 4.2.8
128 */
129 GType
gda_tree_mgr_ldap_get_type(void)130 gda_tree_mgr_ldap_get_type (void)
131 {
132 static GType type = 0;
133
134 if (G_UNLIKELY (type == 0)) {
135 static GMutex registering;
136 static const GTypeInfo info = {
137 sizeof (GdaTreeMgrLdapClass),
138 (GBaseInitFunc) NULL,
139 (GBaseFinalizeFunc) NULL,
140 (GClassInitFunc) gda_tree_mgr_ldap_class_init,
141 NULL,
142 NULL,
143 sizeof (GdaTreeMgrLdap),
144 0,
145 (GInstanceInitFunc) gda_tree_mgr_ldap_init,
146 0
147 };
148
149 g_mutex_lock (®istering);
150 if (type == 0)
151 type = g_type_register_static (GDA_TYPE_TREE_MANAGER, "GdaTreeMgrLdap", &info, 0);
152 g_mutex_unlock (®istering);
153 }
154 return type;
155 }
156
157 static void
gda_tree_mgr_ldap_set_property(GObject * object,guint param_id,const GValue * value,GParamSpec * pspec)158 gda_tree_mgr_ldap_set_property (GObject *object,
159 guint param_id,
160 const GValue *value,
161 GParamSpec *pspec)
162 {
163 GdaTreeMgrLdap *mgr;
164
165 mgr = GDA_TREE_MGR_LDAP (object);
166 if (mgr->priv) {
167 switch (param_id) {
168 case PROP_CNC:
169 mgr->priv->cnc = (GdaLdapConnection*) g_value_get_object (value);
170 if (mgr->priv->cnc)
171 g_object_ref (mgr->priv->cnc);
172 break;
173 case PROP_DN:
174 mgr->priv->dn = g_value_dup_string (value);
175 break;
176 default:
177 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
178 break;
179 }
180 }
181 }
182
183 static void
gda_tree_mgr_ldap_get_property(GObject * object,guint param_id,GValue * value,GParamSpec * pspec)184 gda_tree_mgr_ldap_get_property (GObject *object,
185 guint param_id,
186 GValue *value,
187 GParamSpec *pspec)
188 {
189 GdaTreeMgrLdap *mgr;
190
191 mgr = GDA_TREE_MGR_LDAP (object);
192 if (mgr->priv) {
193 switch (param_id) {
194 case PROP_CNC:
195 g_value_set_object (value, mgr->priv->cnc);
196 break;
197 case PROP_DN:
198 g_value_set_string (value, mgr->priv->dn);
199 break;
200 default:
201 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
202 break;
203 }
204 }
205 }
206
207 /**
208 * gda_tree_mgr_ldap_new:
209 * @cnc: a #GdaConnection object
210 * @dn: (allow-none): an LDAP Distinguished Name or %NULL
211 *
212 * Creates a new #GdaTreeManager object which will list the children of the LDAP entry which Distinguished name
213 * is @dn. If @dn is %NULL, then the tree manager will look in the tree itself for an attribute named "dn" and
214 * use it.
215 *
216 * Returns: (transfer full): a new #GdaTreeManager object
217 *
218 * Since: 4.2.8
219 */
220 GdaTreeManager*
gda_tree_mgr_ldap_new(GdaConnection * cnc,const gchar * dn)221 gda_tree_mgr_ldap_new (GdaConnection *cnc, const gchar *dn)
222 {
223 GdaTreeMgrLdap *mgr;
224 g_return_val_if_fail (GDA_IS_LDAP_CONNECTION (cnc), NULL);
225
226 mgr = (GdaTreeMgrLdap*) g_object_new (GDA_TYPE_TREE_MGR_LDAP,
227 "connection", cnc,
228 "dn", dn, NULL);
229 return (GdaTreeManager*) mgr;
230 }
231
232 static GSList *
gda_tree_mgr_ldap_update_children(GdaTreeManager * manager,GdaTreeNode * node,G_GNUC_UNUSED const GSList * children_nodes,gboolean * out_error,GError ** error)233 gda_tree_mgr_ldap_update_children (GdaTreeManager *manager, GdaTreeNode *node,
234 G_GNUC_UNUSED const GSList *children_nodes, gboolean *out_error,
235 GError **error)
236 {
237 GdaTreeMgrLdap *mgr = GDA_TREE_MGR_LDAP (manager);
238 gchar *real_dn = NULL;
239
240 if (!mgr->priv->cnc) {
241 g_set_error (error, GDA_TREE_MANAGER_ERROR, GDA_TREE_MANAGER_UNKNOWN_ERROR,
242 _("No LDAP connection specified"));
243 if (out_error)
244 *out_error = TRUE;
245 return NULL;
246 }
247
248 if (mgr->priv->dn)
249 real_dn = g_strdup (mgr->priv->dn);
250 else if (node) {
251 /* looking for a dn in @node's attributes */
252 const GValue *cvalue;
253 cvalue = gda_tree_node_fetch_attribute (node, "dn");
254 if (cvalue && (G_VALUE_TYPE (cvalue) == G_TYPE_STRING))
255 real_dn = g_value_dup_string (cvalue);
256 }
257
258 GdaLdapEntry **entries;
259 entries = gda_ldap_get_entry_children (mgr->priv->cnc, real_dn, NULL, error);
260 g_free (real_dn);
261 if (entries) {
262 gint i;
263 GSList *list = NULL;
264 for (i = 0; entries [i]; i++) {
265 GdaTreeNode* snode;
266 GValue *dnv;
267 GdaLdapEntry *lentry;
268 lentry = entries [i];
269 snode = gda_tree_manager_create_node (manager, node, lentry->dn);
270
271 /* full DN */
272 g_value_set_string ((dnv = gda_value_new (G_TYPE_STRING)), lentry->dn);
273 gda_tree_node_set_node_attribute (snode, "dn", dnv, NULL);
274 gda_value_free (dnv);
275
276 /* RDN */
277 gchar **array;
278 array = gda_ldap_dn_split (lentry->dn, FALSE);
279 if (array) {
280 g_value_set_string ((dnv = gda_value_new (G_TYPE_STRING)), array [0]);
281 gda_tree_node_set_node_attribute (snode, "rdn", dnv, NULL);
282 gda_value_free (dnv);
283 g_strfreev (array);
284 }
285
286 if (gda_tree_manager_get_managers (manager)) {
287 g_value_set_boolean ((dnv = gda_value_new (G_TYPE_BOOLEAN)), TRUE);
288 gda_tree_node_set_node_attribute (snode,
289 GDA_ATTRIBUTE_TREE_NODE_UNKNOWN_CHILDREN,
290 dnv, NULL);
291 gda_value_free (dnv);
292 }
293
294 list = g_slist_prepend (list, snode);
295 gda_ldap_entry_free (lentry);
296 }
297 g_free (entries);
298
299 if (node)
300 gda_tree_node_set_node_attribute (node,
301 GDA_ATTRIBUTE_TREE_NODE_UNKNOWN_CHILDREN,
302 NULL, NULL);
303 return list;
304 }
305 else {
306 if (out_error)
307 *out_error = TRUE;
308 return NULL;
309 }
310 }
311