Script for populate rosters. Bug fixed (xmlfile works now in jabberd2)
[vcard2ldap.git] / src / v2l_vcard.c
blob6bb68a3d6af278979c4a0c9024b691f686aa7235
1 /*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 #include <stdlib.h>
18 #include <stdio.h>
19 #ifndef _V2L_JABBER2
20 #include <jabberd.h>
21 #else
22 #include "../util/util.h"
23 #include <xmlnode.h>
25 #define log_warn log_debug
26 #define log_error log_debug
28 #endif
29 #include <v2l_conn.h>
30 #include <v2l_config.h>
31 #include <v2l_vcard.h>
33 #define LOG_ERROR_MEM log_error(ZONE, "Unable to allocate memory")
35 typedef struct v2l_vCardItem
37 char *vcard;
38 char *ldap;
39 char *group;
40 struct v2l_vCardItem *next;
41 } v2l_vCardItem;
43 static int _v2l_vcard_maps_init (v2l_Config *self);
45 /* create the <FN> tag */
46 static int _v2l_create_fn (xmlnode vcard);
47 /* set sn1 and sn2 from sn */
48 static v2l_LdapRequest *_v2l_set_sn12 (v2l_LdapRequest *req);
50 /* mapping functions from LDAP to XML vCard */
51 static xmlnode _v2l_ldap2vcard_generic (v2l_vCardItem *item, char **vals,
52 xmlnode res);
54 static xmlnode _v2l_ldap2vcard_photo (v2l_vCardItem *item, char **vals,
55 xmlnode res);
57 /* mapping functions from XML Vcard to LDAP */
58 static v2l_LdapRequest *_v2l_vcard2ldap_generic (v2l_vCardItem *item,
59 xmlnode data, v2l_LdapRequest *req);
61 static v2l_vCardItem *_v2l_vcard_find_attr (v2l_vCardItem *item,
62 char *attr);
63 #if 0
64 static v2l_vCardItem *
65 _v2l_vcard_find_tag (v2l_vCardItem *item, char *tag);
66 #endif
68 static v2l_vCardItem *_V2L_TPL;
70 /******* Translation maps */
71 static const char *_V2L_MAP_VCARD [] = {
72 "FN",
73 "NICKNAME",
74 "URL",
75 "TEL/NUMBER",
76 "EMAIL/USERID",
77 "TITLE",
78 "ROLE",
79 "BDAY",
80 "DESC",
81 "N/FAMILY",
82 "N/GIVEN",
83 "N/MIDDLE",
84 "N/PREFIX",
85 "N/SUFFIX",
86 "ADR/STREET",
87 "ADR/POBOX",
88 "ADR/EXTADD",
89 "ADR/LOCALITY",
90 "ADR/REGION",
91 "ADR/PCODE",
92 "ADR/CTRY",
93 "ORG/ORGNAME",
94 "ORG/ORGUNIT",
96 "TZ",
97 "GEO/LAT",
98 "GEO/LON",
99 "AGENT/EXTVAL",
100 "NOTE",
101 "REV",
102 "SORT-STRING",
104 "KEY/TYPE",
105 "KEY/CRED",
107 "PHOTO/TYPE",
108 "PHOTO/BINVAL",
109 "PHOTO/EXTVAL",
111 "LOGO/TYPE",
112 "LOGO/BINVAL",
113 "LOGO/EXTVAL",
115 "SOUND/PHONETIC",
116 "SOUND/BINVAL",
117 "SOUND/EXTVAL",
119 NULL
122 /* public api */
124 xmlnode
125 v2l_vcard_get (v2l_Config *self, v2l_LdapConn *curr_conn)
127 LDAPMessage *current_result;
128 BerElement *ber;
129 xmlnode vcard;
130 char *current_attr;
131 int rc;
133 if (!_v2l_vcard_maps_init (self))
135 log_error (ZONE, "Unreadable/malformed vCard template!");
136 return NULL;
139 /* LDAP request is asynchronous */
140 v2l_LdapEvt *evt_res;
142 evt_res = (v2l_LdapEvt *) malloc (sizeof (v2l_LdapEvt));
144 if (evt_res == NULL)
146 LOG_ERROR_MEM;
147 return NULL;
150 evt_res->ld = curr_conn->ld;
152 /* get user info from LDAP */
153 rc = v2l_ldap_search (curr_conn->entry, self->suffix, NULL, 1, evt_res);
155 if (rc != LDAP_SUCCESS)
157 log_error (ZONE, "LDAP error attempting to retrieve user info: %s",
158 ldap_err2string (rc));
159 free (evt_res);
160 return NULL;
163 v2l_ldap_sync(evt_res);
165 if (ldap_count_entries (evt_res->ld, evt_res->result) != 1)
167 log_warn (ZONE,
168 "Multiple users with the same dn?, vCard is not retrieved");
169 free (evt_res);
170 return NULL;
173 /* prepare the XML result */
174 vcard = xmlnode_new_tag ("vCard");
175 xmlnode_put_attrib (vcard, "xmlns", "vcard-temp");
177 current_result = ldap_first_entry (evt_res->ld, evt_res->result);
179 /* step through each attribute in objectclass */
180 for (current_attr =
181 ldap_first_attribute (evt_res->ld, current_result, &ber);
182 current_attr != NULL;
183 current_attr = ldap_next_attribute (evt_res->ld, current_result, ber))
185 v2l_vCardItem *match;
187 match = _v2l_vcard_find_attr (_V2L_TPL, current_attr);
189 if (match != NULL)
191 char **vals;
192 vals = ldap_get_values (evt_res->ld, current_result, current_attr);
194 if (vals != NULL)
196 /* FIXME: ugly */
197 if (match->group != NULL && (strcmp (match->group, "PHOTO") == 0))
199 _v2l_ldap2vcard_photo (match, vals, vcard);
201 else
203 _v2l_ldap2vcard_generic (match, vals, vcard);
206 ldap_value_free (vals);
210 ldap_memfree (current_attr);
213 if (ber != NULL)
215 ber_free (ber, 0);
218 /* don't forget to free the next attribute */
219 ldap_memfree (current_attr);
220 ldap_msgfree (evt_res->result);
221 free (evt_res);
223 _v2l_create_fn (vcard);
225 return vcard;
229 v2l_vcard_set (v2l_Config *self, v2l_LdapConn *curr_conn, xmlnode data)
231 xmlnode node;
232 v2l_LdapRequest *ldap_req = NULL;
233 v2l_vCardItem *item;
235 if (data == NULL)
237 log_warn (ZONE, "vCard data is NULL?");
238 return 0;
241 if (!_v2l_vcard_maps_init (self))
243 log_error (ZONE, "Unreadable/Malformed vCard template!");
244 return 0;
247 item = _V2L_TPL;
251 if (strcmp (item->vcard, "FN") == 0) /* FIXME: ugly */
253 goto is_fn;
256 if (item->group != NULL)
258 char tag[30];
260 sprintf (tag, "%s/%s", item->group, item->vcard);
261 node = xmlnode_get_tag (data, tag);
263 else
265 node = xmlnode_get_tag (data, item->vcard);
268 if (node != NULL)
270 ldap_req = _v2l_vcard2ldap_generic (item, node, ldap_req);
272 is_fn:
273 item = item->next;
274 } while (item != NULL);
276 ldap_req = _v2l_set_sn12 (ldap_req);
278 return v2l_request_record (self, curr_conn, ldap_req);
281 /* public api ends here */
283 static int
284 _v2l_vcard_maps_init (v2l_Config *self)
286 xmlnode tpl, tag;
287 char **stag, *tmp, group[10];
288 v2l_vCardItem *item;
290 if (_V2L_TPL != NULL)
292 return 1;
295 tpl = xmlnode_file (self->confpath);
297 for (stag = (char **) _V2L_MAP_VCARD; *stag != NULL; stag++)
299 tmp = strchr(*stag, '/');
301 if (tmp == NULL)
303 group[0] = 0;
304 tmp = *stag;
306 else
308 sprintf(group, "%.*s", tmp - *stag, *stag);
309 tmp++;
312 tag = xmlnode_get_tag (tpl, *stag);
314 if (xmlnode_get_data(tag) != NULL)
316 int ntags = 0;
317 char find_attr[30];
321 v2l_vCardItem *ptr;
323 ptr = (v2l_vCardItem *) pmalloc (self->poolref,
324 sizeof(v2l_vCardItem));
326 ptr->vcard = tmp;
327 ptr->ldap = pstrdup (self->poolref, xmlnode_get_data(tag));
328 ptr->next = NULL;
329 ptr->group = group[0] == 0 ? NULL :
330 pstrdup (self->poolref, group);
332 if (_V2L_TPL == NULL)
334 _V2L_TPL = ptr;
335 item = ptr;
337 else
339 item->next = ptr;
340 item = item->next;
343 sprintf (find_attr, "%s?v2ln=%d", *stag, ++ntags);
344 tag = xmlnode_get_tag (tpl, find_attr);
345 } while (tag && xmlnode_get_data (tag) != NULL && ntags < 10);
349 xmlnode_free (tpl);
351 return 1;
354 #if 0
355 static v2l_vCardItem *
356 _v2l_vcard_find_tag (v2l_vCardItem *item, char *tag)
358 v2l_vCardItem *res = NULL;
360 while (item != NULL)
362 if (strcmp (item->vcard, tag) == 0)
364 res = item;
365 break;
368 item = item->next;
371 return res;
373 #endif
375 static v2l_vCardItem *
376 _v2l_vcard_find_attr (v2l_vCardItem *item, char *attr)
378 v2l_vCardItem *res = NULL;
380 while (item != NULL)
382 if (strcmp (item->ldap, attr) == 0)
384 res = item;
385 break;
388 item = item->next;
391 return res;
394 static int
395 _v2l_create_fn (xmlnode vcard)
397 xmlnode n, fn;
398 char *family, *given, *fn_str;
399 int len;
401 fn = xmlnode_insert_tag (vcard, "FN");
402 n = xmlnode_get_tag (vcard, "N");
403 family = xmlnode_get_tag_data (n, "FAMILY");
404 given = xmlnode_get_tag_data (n, "GIVEN");
406 len = 0;
407 len += (family != NULL) ? strlen (family) : 0;
408 len += (given != NULL) ? strlen (given) : 0;
410 if (len == 0)
412 log_debug (ZONE, "<fn><n>...</n></fn> is empty, returning");
413 return 1;
416 fn_str = (char *) malloc (sizeof (char) * (len + 2));
418 if (fn_str == NULL)
420 LOG_ERROR_MEM;
421 return 0;
424 fn_str[0] = 0;
426 if (family != NULL)
428 sprintf (fn_str, "%s ", family);
431 if (given != NULL)
433 strcat (fn_str, given);
436 xmlnode_insert_cdata (fn, fn_str, len + 1);
437 free (fn_str);
439 return 1;
442 /* LDAP -> vCard */
444 static xmlnode
445 _v2l_ldap2vcard_generic (v2l_vCardItem *item, char **vals, xmlnode res)
447 xmlnode node;
449 if (item->group != NULL)
451 node = xmlnode_get_tag (res, item->group);
453 if (node == NULL)
455 node = xmlnode_insert_tag(res, item->group);
458 else
460 node = res;
463 node = xmlnode_insert_tag (node, item->vcard);
464 xmlnode_insert_cdata (node, vals[0], strlen (vals[0]));
466 return res;
469 static xmlnode
470 _v2l_ldap2vcard_photo (v2l_vCardItem *item, char **vals, xmlnode res)
472 xmlnode mimetype, photo;
474 res = _v2l_ldap2vcard_generic (item, vals, res);
476 /* FIXME: mimetype is hardcoded */
477 photo = xmlnode_get_tag (res, "PHOTO");
478 mimetype = xmlnode_insert_tag (photo, "TYPE");
479 xmlnode_insert_cdata (mimetype, "image/jpeg", sizeof ("image/jpeg"));
481 return res;
484 /* vCard -> LDAP */
486 static v2l_LdapRequest *
487 _v2l_vcard2ldap_generic (v2l_vCardItem *item, xmlnode data,
488 v2l_LdapRequest *req)
490 const char *str;
492 str = xmlnode_get_data (data);
494 return str == NULL ? req : v2l_add_attr_str (req, item->ldap, str);
497 static v2l_LdapRequest *
498 _v2l_set_sn12 (v2l_LdapRequest *req)
500 if (req != NULL)
502 v2l_LdapRequest *ptr;
503 char *sn;
505 for (ptr = req, sn = NULL; ptr != NULL; ptr = ptr->next)
507 if (strcmp (ptr->attr->mod_type, "sn") == 0)
509 sn = ptr->attr->mod_values[0];
510 break;
514 if (sn != NULL)
516 char *sit, *sn1, *sn2;
518 for (sit = sn; *sit != ' ' && *sit != 0; sit++);
520 sn1 = (char *) malloc (sizeof (char) * (sit - sn + 1));
522 if (sn1 == NULL)
524 return req;
527 strncpy (sn1, sn, sizeof (char) * (sit - sn));
528 sn1[sit - sn] = 0;
529 ptr = v2l_add_attr_str (req, "sn1", sn1);
530 free (sn1);
532 if (ptr == NULL)
534 return req;
537 req = ptr;
539 if (sit - sn != strlen (sn))
541 sn2 = (char *) malloc (sizeof (char) * (strlen (sit) + 1));
543 if (sn2 == NULL)
545 LOG_ERROR_MEM;
546 return req;
549 strcpy (sn2, sit);
550 ptr = v2l_add_attr_str (req, "sn2", sn2);
551 free (sn2);
553 if (ptr == NULL)
555 return req;
558 req = ptr;
560 } /* sn != NULL */
561 } /* req != NULL */
563 return req;