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.
18 \brief XML vCard's to/from LDAP objects translation functions.
27 #include "../util/util.h"
30 #define log_warn log_debug
31 #define log_error log_debug
34 #include <v2l_vcard.h>
36 #define LOG_ERROR_MEM log_error (ZONE, "Unable to allocate memory")
38 /*! \brief vCard template item.
39 SLL. All of relations tag<->LDAP attr read from template
41 typedef struct v2l_vCardItem
43 char *vcard
; /*!< tag name */
44 char *ldap
; /*!< LDAP attribute */
45 char *group
; /*!< XML parent of the tag */
46 struct v2l_vCardItem
*next
;
49 /*! \brief Gets the translation map.
50 If it is not initilized yet, the function reads the template from disk
52 \param self Module config, if map is initialized can be NULL.
53 \return The map, NULL if error.
55 static v2l_vCardItem
*_v2l_vcard_map (v2l_Config
*self
);
57 /*! \brief Creates the FN tag
58 Creates FN tag from GIVEN and FAMILY tags.
59 \param vcard The vCard.
60 \return 1 if no error, otherwise 0.
62 static int _v2l_create_fn (xmlnode vcard
);
64 /*! \brief Sets sn1 and sn2 from sn
65 Hack. IrisPerson has two surnames: first surname and mother's maiden name.
66 This function splits sn in two. Should be called when the list of request
67 are complete and before program excutes them.
68 \param req The SLL of LDAP requests.
70 static v2l_LdapRequest
*_v2l_set_sn12 (v2l_LdapRequest
*req
);
72 /*! \brief Map function from LDAP to XML vCard
73 \param item Info about the tag (name, parent group and attribute associated)
74 \param vals array of values for the attribe.
75 \param[in,out] res The vCard, output is appended here.
76 \return res + new tag or res if error.
78 static xmlnode
_v2l_ldap2vcard_generic (v2l_vCardItem
*item
, const char **vals
,
81 /*! \brief Function for maps PHOTO tag.
82 Hack. InetOrgPerson has a jpegphoto attribute so PHOTO/MIMETYPE tag can be
84 \warning The module doesn't support storing avatars in another format (png)
86 static xmlnode
_v2l_ldap2vcard_photo (v2l_vCardItem
*item
, const char **vals
,
89 /*! \brief Map function from XML Vcard to LDAP
90 \param item Info about the tag (name, parent group and attribute associated)
91 \param data Thhe vCard.
92 \param[in,out] req List of requests, the new request is appended here.
93 \return req + new request or req if error.
95 static v2l_LdapRequest
*_v2l_vcard2ldap_generic (v2l_vCardItem
*item
,
96 xmlnode data
, v2l_LdapRequest
*req
);
98 /*! \brief Finds tag linked to attr
99 Parses the translation map since 'item' node.
100 \param item Where the search starts.
101 \param attr The attribute;
102 \return node with tag<->attr association or NULL if error or not found.
104 static v2l_vCardItem
*_v2l_vcard_find_attr (v2l_vCardItem
*item
,
107 /*! \brief Is LDAP object attribute linked to any tag?
109 \param attr The attribute.
110 \param[out] shrdata Contents the address of any map's node. NULL if no match
111 \return true if attr is linked to any tag, otherwise false
113 static int _v2l_vcard_attr_match (const char *attr
, void **shrdata
);
115 /*! \brief Function applied to all attrs.
116 Utility function, walker function.
117 \param attr The attribute.
118 \param vals Values of attribute.
119 \param pointer Deferenced pointer to vCard.
120 \param shrdata Data shared with the match function.
122 static void _v2l_vcard_attr_value (const char *attr
, const char **vals
,
123 void *pointer
, void *shrdata
);
126 static v2l_vCardItem
*
127 _v2l_vcard_find_tag (v2l_vCardItem
*item
, char *tag
);
130 /*! List of all XML vCard tags supported */
131 static const char *_V2L_MAP_VCARD
[] = {
185 v2l_vcard_get (v2l_Config
*self
, v2l_LdapConn
*curr_conn
)
188 v2l_LdapEvt
*evt_res
;
190 if (_v2l_vcard_map (self
) == NULL
)
192 log_error (ZONE
, "Unreadable/malformed vCard template!");
196 /* get user info from LDAP */
197 evt_res
= v2l_ldap_get_entry (self
, curr_conn
);
204 /* prepare the XML result */
205 vcard
= xmlnode_new_tag ("vCard");
206 xmlnode_put_attrib (vcard
, "xmlns", "vcard-temp");
208 v2l_ldap_for_all_attrs (_v2l_vcard_attr_value
, _v2l_vcard_attr_match
, vcard
,
212 _v2l_create_fn (vcard
);
218 v2l_vcard_set (v2l_Config
*self
, v2l_LdapConn
*curr_conn
, xmlnode data
)
221 v2l_LdapRequest
*ldap_req
= NULL
;
226 log_warn (ZONE
, "vCard data is NULL?");
230 item
= _v2l_vcard_map (self
);
234 log_error (ZONE
, "Unreadable/Malformed vCard template!");
240 if (strcmp (item
->vcard
, "FN") == 0) /* FIXME: ugly */
245 if (item
->group
!= NULL
)
249 sprintf (tag
, "%s/%s", item
->group
, item
->vcard
);
250 node
= xmlnode_get_tag (data
, tag
);
254 node
= xmlnode_get_tag (data
, item
->vcard
);
259 ldap_req
= _v2l_vcard2ldap_generic (item
, node
, ldap_req
);
263 } while (item
!= NULL
);
265 ldap_req
= _v2l_set_sn12 (ldap_req
);
267 return v2l_request_record (self
, curr_conn
, ldap_req
);
270 /* public api ends here */
272 static v2l_vCardItem
*
273 _v2l_vcard_map (v2l_Config
*self
)
275 static v2l_vCardItem
*_V2L_TPL
= NULL
;
277 char **stag
, *tmp
, group
[10];
280 if (_V2L_TPL
== NULL
&& self
!= NULL
&& self
->confpath
!= NULL
)
282 tpl
= xmlnode_file (self
->confpath
);
289 for (stag
= (char **) _V2L_MAP_VCARD
; *stag
!= NULL
; stag
++)
291 tmp
= strchr (*stag
, '/');
300 sprintf (group
, "%.*s", tmp
- *stag
, *stag
);
304 tag
= xmlnode_get_tag (tpl
, *stag
);
306 if (xmlnode_get_data (tag
) != NULL
)
315 ptr
= (v2l_vCardItem
*) pmalloc (self
->poolref
,
316 sizeof (v2l_vCardItem
));
319 ptr
->ldap
= pstrdup (self
->poolref
, xmlnode_get_data (tag
));
321 ptr
->group
= group
[0] == 0 ? NULL
:
322 pstrdup (self
->poolref
, group
);
324 if (_V2L_TPL
== NULL
)
335 sprintf (find_attr
, "%s?v2ln=%d", *stag
, ++ntags
);
336 tag
= xmlnode_get_tag (tpl
, find_attr
);
337 } while (tag
&& xmlnode_get_data (tag
) != NULL
&& ntags
< 10);
338 }/* xmlnode_get_data (tag) != NULL */
339 } /* for loop, all tags in template */
348 static v2l_vCardItem
*
349 _v2l_vcard_find_tag (v2l_vCardItem
*item
, char *tag
)
351 v2l_vCardItem
*res
= NULL
;
355 if (strcmp (item
->vcard
, tag
) == 0)
368 static v2l_vCardItem
*
369 _v2l_vcard_find_attr (v2l_vCardItem
*item
, const char *attr
)
371 v2l_vCardItem
*res
= NULL
;
375 if (strcmp (item
->ldap
, attr
) == 0)
388 _v2l_vcard_attr_match (const char *attr
, void **shrdata
)
390 *shrdata
= _v2l_vcard_find_attr (_v2l_vcard_map (NULL
), attr
);
392 return *shrdata
!= NULL
;
396 _v2l_vcard_attr_value (const char *attr
, const char **vals
, void *pointer
,
400 v2l_vCardItem
*match
;
402 vcard
= (xmlnode
) pointer
;
403 match
= (v2l_vCardItem
*) shrdata
;
408 if (match
->group
!= NULL
&& (strcmp (match
->group
, "PHOTO") == 0))
410 _v2l_ldap2vcard_photo (match
, vals
, vcard
);
414 _v2l_ldap2vcard_generic (match
, vals
, vcard
);
420 _v2l_create_fn (xmlnode vcard
)
423 char *family
, *given
, *fn_str
;
426 fn
= xmlnode_insert_tag (vcard
, "FN");
427 n
= xmlnode_get_tag (vcard
, "N");
428 family
= xmlnode_get_tag_data (n
, "FAMILY");
429 given
= xmlnode_get_tag_data (n
, "GIVEN");
432 len
+= (family
!= NULL
) ? strlen (family
) : 0;
433 len
+= (given
!= NULL
) ? strlen (given
) : 0;
437 log_debug (ZONE
, "<fn><n>...</n></fn> is empty, returning");
441 fn_str
= (char *) malloc (sizeof (char) * (len
+ 2));
453 sprintf (fn_str
, "%s ", family
);
458 strcat (fn_str
, given
);
461 xmlnode_insert_cdata (fn
, fn_str
, len
+ 1);
470 _v2l_ldap2vcard_generic (v2l_vCardItem
*item
, const char **vals
, xmlnode res
)
474 if (item
->group
!= NULL
)
476 node
= xmlnode_get_tag (res
, item
->group
);
480 node
= xmlnode_insert_tag (res
, item
->group
);
488 node
= xmlnode_insert_tag (node
, item
->vcard
);
489 xmlnode_insert_cdata (node
, vals
[0], strlen (vals
[0]));
495 _v2l_ldap2vcard_photo (v2l_vCardItem
*item
, const char **vals
, xmlnode res
)
497 xmlnode mimetype
, photo
;
499 res
= _v2l_ldap2vcard_generic (item
, vals
, res
);
501 /* FIXME: mimetype is hardcoded */
502 photo
= xmlnode_get_tag (res
, "PHOTO");
503 mimetype
= xmlnode_insert_tag (photo
, "TYPE");
504 xmlnode_insert_cdata (mimetype
, "image/jpeg", sizeof ("image/jpeg"));
511 static v2l_LdapRequest
*
512 _v2l_vcard2ldap_generic (v2l_vCardItem
*item
, xmlnode data
,
513 v2l_LdapRequest
*req
)
517 str
= xmlnode_get_data (data
);
519 return str
== NULL
? req
: v2l_add_attr_str (req
, item
->ldap
, str
);
522 static v2l_LdapRequest
*
523 _v2l_set_sn12 (v2l_LdapRequest
*req
)
527 v2l_LdapRequest
*ptr
;
530 for (ptr
= req
, sn
= NULL
; ptr
!= NULL
; ptr
= ptr
->next
)
532 if (strcmp (ptr
->attr
->mod_type
, "sn") == 0)
534 sn
= ptr
->attr
->mod_values
[0];
541 char *sit
, *sn1
, *sn2
;
543 for (sit
= sn
; *sit
!= ' ' && *sit
!= 0; sit
++);
545 sn1
= (char *) malloc (sizeof (char) * (sit
- sn
+ 1));
552 strncpy (sn1
, sn
, sizeof (char) * (sit
- sn
));
554 ptr
= v2l_add_attr_str (req
, "sn1", sn1
);
564 if (sit
- sn
!= strlen (sn
))
566 sn2
= (char *) malloc (strlen (sit
) + 1);
575 ptr
= v2l_add_attr_str (req
, "sn2", sn2
);