Big change to the ldap code to break its dependancy on serv_vcard.c and
authorDave West <davew@uncensored.citadel.org>
Fri, 5 Oct 2007 02:19:17 +0000 (02:19 +0000)
committerDave West <davew@uncensored.citadel.org>
Fri, 5 Oct 2007 02:19:17 +0000 (02:19 +0000)
vice-versa.
This is also the beginings of a universal directory services interface.
Also added the missing pager module source code.

citadel/include/ctdl_module.h
citadel/modules/ldap/serv_ldap.c
citadel/modules/pager/serv_pager.c [new file with mode: 0644]
citadel/modules/vcard/serv_vcard.c
citadel/serv_extensions.c
citadel/serv_ldap.h
citadel/serv_vcard.h

index ce1b148f87d161820de09c0f2c29ef53e2626de9..5d8764db436878461b570a806d6f343bd41570a1 100644 (file)
@@ -66,6 +66,21 @@ void CtdlRegisterMaintenanceThread(char *name, void *(*thread_proc) (void *arg))
 
 void CtdlRegisterSearchFuncHook(void (*fcn_ptr)(int *, long **, char *), char *name);
 
+
+/*
+ * Directory services hooks for LDAP etc
+ */
+
+#define DIRECTORY_USER_DEL 1   // Delete a user entry
+#define DIRECTORY_CREATE_HOST 2        // Create a host entry if not already there.
+#define DIRECTORY_CREATE_OBJECT 3      // Create a new object for directory entry
+#define DIRECTORY_ATTRIB_ADD 4 // Add an attribute to the directory entry object
+#define DIRECTORY_SAVE_OBJECT 5        // Save the object to the directory service
+#define DIRECTORY_FREE_OBJECT 6        // Free the object and its attributes
+
+int CtdlRegisterDirectoryServiceFunc(int (*func)(char *cn, char *ou, void **object), int cmd, char *module);
+int CtdlDoDirectoryServiceFunc(char *cn, char *ou, void **object, char *module, int cmd);
+
 /* TODODRW: This needs to be changed into a hook type interface
  * for now we have this horrible hack
  */
index ac2ef9f43955978038907653456de0c8c8fa2be8..018a1f845f8ecd7ec9be5cfdb4a5c0ab767420c4 100644 (file)
@@ -39,7 +39,6 @@
 #include "database.h"
 #include "msgbase.h"
 #include "serv_ldap.h"
-#include "vcard.h"
 #include "tools.h"
 
 
@@ -126,8 +125,10 @@ void CtdlCreateLdapRoot(void) {
 
 /*
  * Create an OU node representing a Citadel host.
+ * parameter cn is not used, its just there to keep the hook interface consistant
+ * parameter object not used here, present for interface compatability
  */
-void CtdlCreateHostOU(char *host) {
+int CtdlCreateLdapHostOU(char *cn, char *host, void **object) {
        char *dc_values[2];
        char *objectClass_values[3];
        LDAPMod dc, objectClass;
@@ -166,7 +167,9 @@ void CtdlCreateHostOU(char *host) {
        else if (i != LDAP_SUCCESS) {
                lprintf(CTDL_CRIT, "ldap_add_s() failed: %s (%d)\n",
                        ldap_err2string(i), i);
+               return -1;
        }
+       return 0;
 }
 
 
@@ -210,346 +213,107 @@ void CtdlConnectToLdap(void) {
 }
 
 
-/* 
- * vCard-to-LDAP conversions.
- *
- * If 'op' is set to V2L_WRITE, then write
- * (add, or change if already exists) a directory entry to the
- * LDAP server, based on the information supplied in a vCard.
- *
- * If 'op' is set to V2L_DELETE, then delete the entry from LDAP.
- */
-void ctdl_vcard_to_ldap(struct CtdlMessage *msg, int op) {
-       struct vCard *v = NULL;
-       int i, j;
-       char this_dn[SIZ];
-       LDAPMod **attrs = NULL;
-       int num_attrs = 0;
-       int num_emails = 0;
-       int alias_attr = (-1);
-       int num_phones = 0;
-       int phone_attr = (-1);
-       int have_addr = 0;
-       int have_cn = 0;
-
-       char givenname[128];
-       char sn[128];
-       char uid[256];
-       char street[256];
-       char city[128];
-       char state[3];
-       char zipcode[10];
-       char calFBURL[256];
-
-       if (dirserver == NULL) return;
-       if (msg == NULL) return;
-       if (msg->cm_fields['M'] == NULL) return;
-       if (msg->cm_fields['A'] == NULL) return;
-       if (msg->cm_fields['N'] == NULL) return;
-
-       /* Initialize variables */
-       strcpy(givenname, "");
-       strcpy(sn, "");
-       strcpy(calFBURL, "");
-
-       sprintf(this_dn, "cn=%s,ou=%s,%s",
-               msg->cm_fields['A'],
-               msg->cm_fields['N'],
-               config.c_ldap_base_dn
-       );
-               
-       sprintf(uid, "%s@%s",
-               msg->cm_fields['A'],
-               msg->cm_fields['N']
-       );
-
-       /* Are we just deleting?  If so, it's simple... */
-       if (op == V2L_DELETE) {
-               lprintf(CTDL_DEBUG, "Calling ldap_delete_s()\n");
-               begin_critical_section(S_LDAP);
-               i = ldap_delete_s(dirserver, this_dn);
-               end_critical_section(S_LDAP);
-               if (i != LDAP_SUCCESS) {
-                       lprintf(CTDL_ERR, "ldap_delete_s() failed: %s (%d)\n",
-                               ldap_err2string(i), i);
-               }
-               return;
-       }
-
-       /*
-        * If we get to this point then it must be a V2L_WRITE operation.
-        */
-
-       /* First make sure the OU for the user's home Citadel host is created */
-       CtdlCreateHostOU(msg->cm_fields['N']);
-
-       /* The first LDAP attribute will be an 'objectclass' list.  Citadel
-        * doesn't do anything with this.  It's just there for compatibility
-        * with Kolab.
-        */
-       num_attrs = 1;
-       attrs = malloc( (sizeof(LDAPMod *) * num_attrs) );
-       attrs[0] = malloc(sizeof(LDAPMod));
-       memset(attrs[0], 0, sizeof(LDAPMod));
-       attrs[0]->mod_op        = LDAP_MOD_ADD;
-       attrs[0]->mod_type      = "objectclass";
-       attrs[0]->mod_values    = malloc(3 * sizeof(char *));
-       attrs[0]->mod_values[0] = strdup("citadelInetOrgPerson");
-       attrs[0]->mod_values[1] = NULL;
-
-       /* Convert the vCard fields to LDAP properties */
-       v = vcard_load(msg->cm_fields['M']);
-       if (v->numprops) for (i=0; i<(v->numprops); ++i) if (striplt(v->prop[i].value), strlen(v->prop[i].value) > 0) {
-
-               if (!strcasecmp(v->prop[i].name, "n")) {
-                       extract_token(sn,               v->prop[i].value, 0, ';', sizeof sn);
-                       extract_token(givenname,        v->prop[i].value, 1, ';', sizeof givenname);
-               }
-
-               if (!strcasecmp(v->prop[i].name, "fn")) {
-                       attrs = realloc(attrs, (sizeof(LDAPMod *) * ++num_attrs) );
-                       attrs[num_attrs-1] = malloc(sizeof(LDAPMod));
-                       memset(attrs[num_attrs-1], 0, sizeof(LDAPMod));
-                       attrs[num_attrs-1]->mod_op              = LDAP_MOD_ADD;
-                       attrs[num_attrs-1]->mod_type            = "cn";
-                       attrs[num_attrs-1]->mod_values          = malloc(2 * sizeof(char *));
-                       attrs[num_attrs-1]->mod_values[0]       = strdup(v->prop[i].value);
-                       attrs[num_attrs-1]->mod_values[1]       = NULL;
-                       have_cn = 1;
-               }
-
-               if (!strcasecmp(v->prop[i].name, "title")) {
-                       attrs = realloc(attrs, (sizeof(LDAPMod *) * ++num_attrs) );
-                       attrs[num_attrs-1] = malloc(sizeof(LDAPMod));
-                       memset(attrs[num_attrs-1], 0, sizeof(LDAPMod));
-                       attrs[num_attrs-1]->mod_op              = LDAP_MOD_ADD;
-                       attrs[num_attrs-1]->mod_type            = "title";
-                       attrs[num_attrs-1]->mod_values          = malloc(2 * sizeof(char *));
-                       attrs[num_attrs-1]->mod_values[0]       = strdup(v->prop[i].value);
-                       attrs[num_attrs-1]->mod_values[1]       = NULL;
-               }
-
-               if (!strcasecmp(v->prop[i].name, "org")) {
-                       attrs = realloc(attrs, (sizeof(LDAPMod *) * ++num_attrs) );
-                       attrs[num_attrs-1] = malloc(sizeof(LDAPMod));
-                       memset(attrs[num_attrs-1], 0, sizeof(LDAPMod));
-                       attrs[num_attrs-1]->mod_op              = LDAP_MOD_ADD;
-                       attrs[num_attrs-1]->mod_type            = "o";
-                       attrs[num_attrs-1]->mod_values          = malloc(2 * sizeof(char *));
-                       attrs[num_attrs-1]->mod_values[0]       = strdup(v->prop[i].value);
-                       attrs[num_attrs-1]->mod_values[1]       = NULL;
-               }
-
-               if ( (!strcasecmp(v->prop[i].name, "adr"))
-                  ||(!strncasecmp(v->prop[i].name, "adr;", 4)) ) {
-                       /* Unfortunately, we can only do a single address */
-                       if (!have_addr) {
-                               have_addr = 1;
-                               strcpy(street, "");
-                               extract_token(&street[strlen(street)],
-                                       v->prop[i].value, 0, ';', (sizeof street - strlen(street))); /* po box */
-                               strcat(street, " ");
-                               extract_token(&street[strlen(street)],
-                                       v->prop[i].value, 1, ';', (sizeof street - strlen(street))); /* extend addr */
-                               strcat(street, " ");
-                               extract_token(&street[strlen(street)],
-                                       v->prop[i].value, 2, ';', (sizeof street - strlen(street))); /* street */
-                               striplt(street);
-                               extract_token(city, v->prop[i].value, 3, ';', sizeof city);
-                               extract_token(state, v->prop[i].value, 4, ';', sizeof state);
-                               extract_token(zipcode, v->prop[i].value, 5, ';', sizeof zipcode);
-
-                               attrs = realloc(attrs, (sizeof(LDAPMod *) * ++num_attrs) );
-                               attrs[num_attrs-1] = malloc(sizeof(LDAPMod));
-                               memset(attrs[num_attrs-1], 0, sizeof(LDAPMod));
-                               attrs[num_attrs-1]->mod_op              = LDAP_MOD_ADD;
-                               attrs[num_attrs-1]->mod_type            = "street";
-                               attrs[num_attrs-1]->mod_values          = malloc(2 * sizeof(char *));
-                               attrs[num_attrs-1]->mod_values[0]       = strdup(street);
-                               attrs[num_attrs-1]->mod_values[1]       = NULL;
-
-                               attrs = realloc(attrs, (sizeof(LDAPMod *) * ++num_attrs) );
-                               attrs[num_attrs-1] = malloc(sizeof(LDAPMod));
-                               memset(attrs[num_attrs-1], 0, sizeof(LDAPMod));
-                               attrs[num_attrs-1]->mod_op              = LDAP_MOD_ADD;
-                               attrs[num_attrs-1]->mod_type            = "l";
-                               attrs[num_attrs-1]->mod_values          = malloc(2 * sizeof(char *));
-                               attrs[num_attrs-1]->mod_values[0]       = strdup(city);
-                               attrs[num_attrs-1]->mod_values[1]       = NULL;
-
-                               attrs = realloc(attrs, (sizeof(LDAPMod *) * ++num_attrs) );
-                               attrs[num_attrs-1] = malloc(sizeof(LDAPMod));
-                               memset(attrs[num_attrs-1], 0, sizeof(LDAPMod));
-                               attrs[num_attrs-1]->mod_op              = LDAP_MOD_ADD;
-                               attrs[num_attrs-1]->mod_type            = "st";
-                               attrs[num_attrs-1]->mod_values          = malloc(2 * sizeof(char *));
-                               attrs[num_attrs-1]->mod_values[0]       = strdup(state);
-                               attrs[num_attrs-1]->mod_values[1]       = NULL;
-
-                               attrs = realloc(attrs, (sizeof(LDAPMod *) * ++num_attrs) );
-                               attrs[num_attrs-1] = malloc(sizeof(LDAPMod));
-                               memset(attrs[num_attrs-1], 0, sizeof(LDAPMod));
-                               attrs[num_attrs-1]->mod_op              = LDAP_MOD_ADD;
-                               attrs[num_attrs-1]->mod_type            = "postalcode";
-                               attrs[num_attrs-1]->mod_values          = malloc(2 * sizeof(char *));
-                               attrs[num_attrs-1]->mod_values[0]       = strdup(zipcode);
-                               attrs[num_attrs-1]->mod_values[1]       = NULL;
-                       }
-               }
 
-               if ( (!strcasecmp(v->prop[i].name, "tel"))
-                  ||(!strncasecmp(v->prop[i].name, "tel;", 4)) ) {
-                       ++num_phones;
-                       /* The first 'tel' property creates the 'telephoneNumber' attribute */
-                       if (num_phones == 1) {
-                               attrs = realloc(attrs, (sizeof(LDAPMod *) * ++num_attrs) );
-                               phone_attr = num_attrs-1;
-                               attrs[phone_attr] = malloc(sizeof(LDAPMod));
-                               memset(attrs[phone_attr], 0, sizeof(LDAPMod));
-                               attrs[phone_attr]->mod_op               = LDAP_MOD_ADD;
-                               attrs[phone_attr]->mod_type             = "telephoneNumber";
-                               attrs[phone_attr]->mod_values           = malloc(2 * sizeof(char *));
-                               attrs[phone_attr]->mod_values[0]        = strdup(v->prop[i].value);
-                               attrs[phone_attr]->mod_values[1]        = NULL;
-                       }
-                       /* Subsequent 'tel' properties *add to* the 'telephoneNumber' attribute */
-                       else {
-                               attrs[phone_attr]->mod_values = realloc(attrs[phone_attr]->mod_values,
-                                                                    num_phones * sizeof(char *));
-                               attrs[phone_attr]->mod_values[num_phones-1]
-                                                                       = strdup(v->prop[i].value);
-                               attrs[phone_attr]->mod_values[num_phones]
-                                                                       = NULL;
-                       }
-               }
+/*
+ * Create a base LDAP object for the interface
+ */
+int CtdlCreateLdapObject(char *cn, char *ou, void **object)
+{
+       // We do nothing here, this just gets the base structure created by the interface.
+       lprintf (CTDL_DEBUG, "Created ldap object\n");
+       return 0;
+}
 
 
-               if ( (!strcasecmp(v->prop[i].name, "email"))
-                  ||(!strcasecmp(v->prop[i].name, "email;internet")) ) {
+/*
+ * Add an attribute to the ldap object
+ */
+int CtdlAddLdapAttr(char *cn, char *ou, void **object)
+{
+       LDAPMod **attrs ;
+       int num_attrs = 0;
+       int num_values = 0;
+       int cur_attr;
        
-                       ++num_emails;
-                       lprintf(CTDL_DEBUG, "email addr %d\n", num_emails);
-
-                       /* The first email address creates the 'mail' attribute */
-                       if (num_emails == 1) {
-                               attrs = realloc(attrs, (sizeof(LDAPMod *) * ++num_attrs) );
-                               attrs[num_attrs-1] = malloc(sizeof(LDAPMod));
-                               memset(attrs[num_attrs-1], 0, sizeof(LDAPMod));
-                               attrs[num_attrs-1]->mod_op              = LDAP_MOD_ADD;
-                               attrs[num_attrs-1]->mod_type            = "mail";
-                               attrs[num_attrs-1]->mod_values          = malloc(2 * sizeof(char *));
-                               attrs[num_attrs-1]->mod_values[0]       = strdup(v->prop[i].value);
-                               attrs[num_attrs-1]->mod_values[1]       = NULL;
-                       }
-                       /* The second email address creates the 'alias' attribute */
-                       else if (num_emails == 2) {
-                               attrs = realloc(attrs, (sizeof(LDAPMod *) * ++num_attrs) );
-                               alias_attr = num_attrs-1;
-                               attrs[alias_attr] = malloc(sizeof(LDAPMod));
-                               memset(attrs[alias_attr], 0, sizeof(LDAPMod));
-                               attrs[alias_attr]->mod_op               = LDAP_MOD_ADD;
-                               attrs[alias_attr]->mod_type             = "alias";
-                               attrs[alias_attr]->mod_values           = malloc(2 * sizeof(char *));
-                               attrs[alias_attr]->mod_values[0]        = strdup(v->prop[i].value);
-                               attrs[alias_attr]->mod_values[1]        = NULL;
-                       }
-                       /* Subsequent email addresses *add to* the 'alias' attribute */
-                       else if (num_emails > 2) {
-                               attrs[alias_attr]->mod_values = realloc(attrs[alias_attr]->mod_values,
-                                                                    num_emails * sizeof(char *));
-                               attrs[alias_attr]->mod_values[num_emails-2]
-                                                                       = strdup(v->prop[i].value);
-                               attrs[alias_attr]->mod_values[num_emails-1]
-                                                                       = NULL;
-                       }
-
-
-               }
-
-               /* Calendar free/busy URL (take the first one we find, but if a subsequent
-                * one contains the "pref" designation then we go with that instead.)
-                */
-               if ( (!strcasecmp(v->prop[i].name, "fburl"))
-                  ||(!strncasecmp(v->prop[i].name, "fburl;", 6)) ) {
-                       if ( (IsEmptyStr(calFBURL))
-                          || (!strncasecmp(v->prop[i].name, "fburl;pref", 10)) ) {
-                               safestrncpy(calFBURL, v->prop[i].value, sizeof calFBURL);
+       
+       lprintf (CTDL_DEBUG, "Adding ldap attribute\n");
+       
+       attrs = *object;
+       if (attrs)
+       {
+               while (attrs[num_attrs])
+                       num_attrs++;
+       }
+       
+       for (cur_attr = 0; cur_attr < num_attrs ; cur_attr++)
+       {
+               if (!strcmp(attrs[cur_attr]->mod_type, cn))
+               {       // Adding a value to the attribute
+                       if (attrs[cur_attr]->mod_values)
+                       {
+                               while (attrs[cur_attr]->mod_values[num_values])
+                                       num_values++;
                        }
+                       attrs[cur_attr]->mod_values = realloc(attrs[cur_attr]->mod_values, (num_values + 2) * (sizeof(char *)));
+                       attrs[cur_attr]->mod_values[num_values] = strdup(ou);
+                       attrs[cur_attr]->mod_values[num_values+1] = NULL;
+                       return 0;
                }
-
-       }
-       vcard_free(v);  /* Don't need this anymore. */
-
-       /* "sn" (surname) based on info in vCard */
-       attrs = realloc(attrs, (sizeof(LDAPMod *) * ++num_attrs) );
-       attrs[num_attrs-1] = malloc(sizeof(LDAPMod));
-       memset(attrs[num_attrs-1], 0, sizeof(LDAPMod));
-       attrs[num_attrs-1]->mod_op              = LDAP_MOD_ADD;
-       attrs[num_attrs-1]->mod_type            = "sn";
-       attrs[num_attrs-1]->mod_values          = malloc(2 * sizeof(char *));
-       attrs[num_attrs-1]->mod_values[0]       = strdup(sn);
-       attrs[num_attrs-1]->mod_values[1]       = NULL;
-
-       /* "givenname" (first name) based on info in vCard */
-       if (IsEmptyStr(givenname)) strcpy(givenname, "_");
-       if (IsEmptyStr(sn)) strcpy(sn, "_");
-       attrs = realloc(attrs, (sizeof(LDAPMod *) * ++num_attrs) );
-       attrs[num_attrs-1] = malloc(sizeof(LDAPMod));
-       memset(attrs[num_attrs-1], 0, sizeof(LDAPMod));
-       attrs[num_attrs-1]->mod_op              = LDAP_MOD_ADD;
-       attrs[num_attrs-1]->mod_type            = "givenname";
-       attrs[num_attrs-1]->mod_values          = malloc(2 * sizeof(char *));
-       attrs[num_attrs-1]->mod_values[0]       = strdup(givenname);
-       attrs[num_attrs-1]->mod_values[1]       = NULL;
-
-       /* "uid" is a Kolab compatibility thing.  We just do cituser@citnode */
-       attrs = realloc(attrs, (sizeof(LDAPMod *) * ++num_attrs) );
-       attrs[num_attrs-1] = malloc(sizeof(LDAPMod));
-       memset(attrs[num_attrs-1], 0, sizeof(LDAPMod));
-       attrs[num_attrs-1]->mod_op              = LDAP_MOD_ADD;
-       attrs[num_attrs-1]->mod_type            = "uid";
-       attrs[num_attrs-1]->mod_values          = malloc(2 * sizeof(char *));
-       attrs[num_attrs-1]->mod_values[0]       = strdup(uid);
-       attrs[num_attrs-1]->mod_values[1]       = NULL;
-
-       /* Add a "cn" (Common Name) attribute based on the user's screen name,
-        * but only there was no 'fn' (full name) property in the vCard 
-        */
-       if (!have_cn) {
-               attrs = realloc(attrs, (sizeof(LDAPMod *) * ++num_attrs) );
-               attrs[num_attrs-1] = malloc(sizeof(LDAPMod));
-               memset(attrs[num_attrs-1], 0, sizeof(LDAPMod));
-               attrs[num_attrs-1]->mod_op              = LDAP_MOD_ADD;
-               attrs[num_attrs-1]->mod_type            = "cn";
-               attrs[num_attrs-1]->mod_values          = malloc(2 * sizeof(char *));
-               attrs[num_attrs-1]->mod_values[0]       = strdup(msg->cm_fields['A']);
-               attrs[num_attrs-1]->mod_values[1]       = NULL;
        }
+       if (num_attrs)
+               attrs = realloc(attrs, (sizeof(LDAPMod *)) * (num_attrs + 2));
+       else
+               attrs = malloc((sizeof(LDAPMod *)) * (num_attrs + 2));
+       attrs[num_attrs] = malloc(sizeof(LDAPMod));
+       memset(attrs[num_attrs], 0, sizeof(LDAPMod));
+       attrs[num_attrs+1] = NULL;
+       attrs[num_attrs]->mod_op        = LDAP_MOD_ADD;
+       attrs[num_attrs]->mod_type      = strdup(cn);
+       attrs[num_attrs]->mod_values    = malloc(2 * sizeof(char *));
+       attrs[num_attrs]->mod_values[0] = strdup(ou);
+       attrs[num_attrs]->mod_values[1] = NULL;
+       *object = attrs;
+       return 0;
+}
 
-       /* Add a "calFBURL" attribute if a calendar free/busy URL exists */
-       if (!IsEmptyStr(calFBURL)) {
-               attrs = realloc(attrs, (sizeof(LDAPMod *) * ++num_attrs) );
-               attrs[num_attrs-1] = malloc(sizeof(LDAPMod));
-               memset(attrs[num_attrs-1], 0, sizeof(LDAPMod));
-               attrs[num_attrs-1]->mod_op              = LDAP_MOD_ADD;
-               attrs[num_attrs-1]->mod_type            = "calFBURL";
-               attrs[num_attrs-1]->mod_values          = malloc(2 * sizeof(char *));
-               attrs[num_attrs-1]->mod_values[0]       = strdup(calFBURL);
-               attrs[num_attrs-1]->mod_values[1]       = NULL;
-       }
+
+/*
+ * SAve the object to the LDAP server
+ */
+int CtdlSaveLdapObject(char *cn, char *ou, void **object)
+{
+       int i, j;
+       
+       char this_dn[SIZ];
+       LDAPMod **attrs ;
+       int num_attrs = 0;
+       int count = 0;
+       
+       if (dirserver == NULL) return -1;
+       if (ou == NULL) return -1;
+       if (cn == NULL) return -1;
        
+       sprintf(this_dn, "cn=%s,ou=%s,%s", cn, ou, config.c_ldap_base_dn);
+
        /* The last attribute must be a NULL one. */
-       attrs = realloc(attrs, (sizeof(LDAPMod *) * ++num_attrs) );
-       attrs[num_attrs - 1] = NULL;
+       attrs = (LDAPMod **)*object;
+       if (attrs)
+       {
+               while (attrs[num_attrs])
+                       num_attrs++;
+       }
        
        lprintf(CTDL_DEBUG, "Calling ldap_add_s() for '%s'\n", this_dn);
+       
        begin_critical_section(S_LDAP);
        i = ldap_add_s(dirserver, this_dn, attrs);
        end_critical_section(S_LDAP);
 
        /* If the entry already exists, repopulate it instead */
        if (i == LDAP_ALREADY_EXISTS) {
-               for (j=0; j<(num_attrs-1); ++j) {
+               for (j=0; j<(num_attrs); ++j) {
                        attrs[j]->mod_op = LDAP_MOD_REPLACE;
                }
                lprintf(CTDL_DEBUG, "Calling ldap_modify_s() for '%s'\n", this_dn);
@@ -561,6 +325,27 @@ void ctdl_vcard_to_ldap(struct CtdlMessage *msg, int op) {
        if (i != LDAP_SUCCESS) {
                lprintf(CTDL_ERR, "ldap_add_s() failed: %s (%d)\n",
                        ldap_err2string(i), i);
+               return -1;
+       }
+       return 0;
+}
+
+
+/*
+ * Free the object
+ */
+int CtdlFreeLdapObject(char *cn, char *ou, void **object)
+{
+       int i, j;
+       
+       LDAPMod **attrs ;
+       int num_attrs = 0;
+
+       attrs = (LDAPMod **)*object;
+       if (attrs)
+       {
+               while (attrs[num_attrs])
+                       num_attrs++;
        }
 
        lprintf(CTDL_DEBUG, "Freeing attributes\n");
@@ -584,8 +369,42 @@ void ctdl_vcard_to_ldap(struct CtdlMessage *msg, int op) {
                        free(attrs[i]);
                }
        }
+       free(attrs[i]);
        free(attrs);
-       lprintf(CTDL_DEBUG, "LDAP write operation complete.\n");
+       *object = NULL;
+       return 0;
+}
+
+
+/*
+ * Delete a record from the LDAP
+ *
+ * parameter object not used here, present for hook interface compatability
+ */
+int CtdlDeleteFromLdap(char *cn, char *ou, void **object)
+{
+       int i;
+       
+       char this_dn[SIZ];
+       
+       if (dirserver == NULL) return -1;
+       if (ou == NULL) return -1;
+       if (cn == NULL) return -1;
+       
+       sprintf(this_dn, "cn=%s,ou=%s,%s", cn, ou, config.c_ldap_base_dn);
+       
+       lprintf(CTDL_DEBUG, "Calling ldap_delete_s()\n");
+       
+       begin_critical_section(S_LDAP);
+       i = ldap_delete_s(dirserver, this_dn);
+       end_critical_section(S_LDAP);
+       
+       if (i != LDAP_SUCCESS) {
+               lprintf(CTDL_ERR, "ldap_delete_s() failed: %s (%d)\n",
+                       ldap_err2string(i), i);
+               return -1;
+       }
+       return 0;
 }
 
 
@@ -599,6 +418,13 @@ CTDL_MODULE_INIT(ldap)
 {
 #ifdef HAVE_LDAP
        CtdlRegisterCleanupHook(serv_ldap_cleanup);
+       CtdlRegisterDirectoryServiceFunc(CtdlDeleteFromLdap, DIRECTORY_USER_DEL, "ldap");
+       CtdlRegisterDirectoryServiceFunc(CtdlCreateLdapHostOU, DIRECTORY_CREATE_HOST, "ldap");
+       CtdlRegisterDirectoryServiceFunc(CtdlCreateLdapObject, DIRECTORY_CREATE_OBJECT, "ldap");
+       CtdlRegisterDirectoryServiceFunc(CtdlAddLdapAttr, DIRECTORY_ATTRIB_ADD, "ldap");
+       CtdlRegisterDirectoryServiceFunc(CtdlSaveLdapObject, DIRECTORY_SAVE_OBJECT, "ldap");
+       CtdlRegisterDirectoryServiceFunc(CtdlFreeLdapObject, DIRECTORY_FREE_OBJECT, "ldap");
+       
 
        if (!IsEmptyStr(config.c_ldap_host)) {
                CtdlConnectToLdap();
diff --git a/citadel/modules/pager/serv_pager.c b/citadel/modules/pager/serv_pager.c
new file mode 100644 (file)
index 0000000..01d1540
--- /dev/null
@@ -0,0 +1,222 @@
+/*
+ * This module implements an external pager hook for when notifcation
+ * of a new email is wanted.
+ * Based on bits of serv_funambol
+ */
+
+#include "sysdep.h"
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <pwd.h>
+#include <errno.h>
+#include <sys/types.h>
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+#  include <sys/time.h>
+# else
+#  include <time.h>
+# endif
+#endif
+
+#include <sys/wait.h>
+#include <string.h>
+#include <limits.h>
+#include <sys/socket.h>
+#include "citadel.h"
+#include "server.h"
+#include "citserver.h"
+#include "support.h"
+#include "config.h"
+#include "control.h"
+#include "room_ops.h"
+#include "user_ops.h"
+#include "policy.h"
+#include "database.h"
+#include "msgbase.h"
+#include "tools.h"
+#include "internet_addressing.h"
+#include "domain.h"
+#include "clientsocket.h"
+#include "serv_pager.h"
+
+#include "ctdl_module.h"
+
+#define PAGER_CONFIG_MESSAGE "__ Push email settings __"
+#define PAGER_CONFIG_TEXT  "textmessage"
+
+/*
+ * Create the notify message queue. We use the exact same room 
+ */
+void create_pager_queue(void) {
+       struct ctdlroom qrbuf;
+
+       create_room(FNBL_QUEUE_ROOM, 3, "", 0, 1, 0, VIEW_MAILBOX);
+
+       /*
+        * Make sure it's set to be a "system room" so it doesn't show up
+        * in the <K>nown rooms list for Aides.
+        */
+       if (lgetroom(&qrbuf, FNBL_QUEUE_ROOM) == 0) {
+               qrbuf.QRflags2 |= QR2_SYSTEM;
+               lputroom(&qrbuf);
+       }
+}
+void do_pager_queue(void) {
+       static int doing_queue = 0;
+
+       /*
+        * This is a simple concurrency check to make sure only one queue run
+        * is done at a time.  We could do this with a mutex, but since we
+        * don't really require extremely fine granularity here, we'll do it
+        * with a static variable instead.
+        */
+       if (doing_queue) return;
+       doing_queue = 1;
+
+       /* 
+        * Go ahead and run the queue
+        */
+       lprintf(CTDL_DEBUG, "serv_pager: processing notify queue\n");
+
+       if (getroom(&CC->room, FNBL_QUEUE_ROOM) != 0) {
+               lprintf(CTDL_ERR, "Cannot find room <%s>\n", FNBL_QUEUE_ROOM);
+               return;
+       }
+       CtdlForEachMessage(MSGS_ALL, 0L, NULL,
+               SPOOLMIME, NULL, notify_pager, NULL);
+
+       lprintf(CTDL_DEBUG, "serv_pager: queue run completed\n");
+       doing_queue = 0;
+}
+
+/*
+ * Call the external tool
+ */
+void notify_pager(long msgnum, void *userdata) {
+       struct CtdlMessage *msg;
+       struct ctdlroom qrbuf;
+       
+       /* W means 'wireless', which contains the unix name */
+       msg = CtdlFetchMessage(msgnum, 1);
+       if ( msg->cm_fields['W'] == NULL) {
+               goto nuke;
+       }
+       /* Are we allowed to push? */
+       if (IsEmptyStr(config.c_pager_program)) {
+               return;
+       } else if (IsEmptyStr(config.c_pager_program) && IsEmptyStr(config.c_funambol_host)) {
+               goto nuke;
+       } else {
+               lprintf(CTDL_INFO, "Pager alerter enabled\n");  
+       }
+
+       /* Get the configuration. We might be allowed system wide but the user
+               may have configured otherwise */
+       long configMsgNum = pager_getConfigMessage(msg->cm_fields['W']);
+       int allowed = pager_isPagerAllowedByPrefs(configMsgNum);
+       if (allowed != 0 && pager_doesUserWant(configMsgNum) == 0) {
+               goto nuke;
+       } else if (allowed != 0) {
+               return;
+       }
+       char *num = pager_getUserPhoneNumber(configMsgNum);
+       char command[SIZ];
+       snprintf(command, sizeof command, "%s %s -u %s", config.c_pager_program, num, &msg->cm_fields['W']);
+       system(command);
+       
+       nuke:
+       CtdlFreeMessage(msg);
+       long todelete[1];
+       todelete[0] = msgnum;
+       CtdlDeleteMessages(FNBL_QUEUE_ROOM, todelete, 1, "");
+}
+
+long pager_getConfigMessage(char *username) {
+       struct ctdlroom qrbuf; // scratch for room
+       struct ctdluser user; // ctdl user instance
+       char configRoomName[ROOMNAMELEN];
+       struct CtdlMessage *template;
+       struct CtdlMessage *msg;
+       struct cdbdata *cdbfr;
+       long *msglist = NULL;
+       int num_msgs = 0;
+       long confMsgNum = -1;
+       // Get the user
+       getuser(&user, username);
+       
+       MailboxName(configRoomName, sizeof configRoomName, &user, USERCONFIGROOM);
+       int prefroom = getroom(&qrbuf, configRoomName);
+       
+       /* Do something really, really stoopid here. Raid the room on ourselves,
+               loop through the messages manually and find it. I don't want 
+               to use a CtdlForEachMessage callback here, as we would be 
+               already in one */
+       cdbfr = cdb_fetch(CDB_MSGLISTS, &qrbuf.QRnumber, sizeof(long));
+       if (cdbfr != NULL) {
+               msglist = (long *) cdbfr->ptr;
+               cdbfr->ptr = NULL;      /* CtdlForEachMessage() now owns this memory */
+               num_msgs = cdbfr->len / sizeof(long);
+               cdb_free(cdbfr);
+       } else {
+               return -1;      /* No messages at all?  No further action. */
+       }
+       int a;
+       for (a = 0; a < num_msgs; ++a) {
+                               msg = CtdlFetchMessage(msglist[a], 1);
+                               if (msg != NULL) {
+                                       if (msg->cm_fields['U'] != NULL && strncasecmp(msg->cm_fields['U'], PAGER_CONFIG_MESSAGE, 
+                                               strlen(PAGER_CONFIG_MESSAGE)) == 0) {
+                                               confMsgNum = msglist[a];
+                                       }
+                                       CtdlFreeMessage(msg);
+                               }
+       }
+       return confMsgNum;
+
+}
+int pager_isPagerAllowedByPrefs(long configMsgNum) {
+       // Do a simple string search to see if 'textmessage' is selected as the 
+       // type. This string would be at the very top of the message contents.
+       if (configMsgNum == -1) {
+               return -1;
+       }
+       struct CtdlMessage *prefMsg;
+       prefMsg = CtdlFetchMessage(configMsgNum, 1);
+       char *msgContents = prefMsg->cm_fields['M'];
+       return strncasecmp(msgContents, PAGER_CONFIG_TEXT, strlen(PAGER_CONFIG_TEXT));
+}
+int pager_doesUserWant(long configMsgNum) {
+       if (configMsgNum == -1) {
+               return -1;
+       }
+       struct CtdlMessage *prefMsg;
+       prefMsg = CtdlFetchMessage(configMsgNum, 1);
+       char *msgContents = prefMsg->cm_fields['M'];
+       return strncasecmp(msgContents, "none", 4);
+}
+       /* warning: fetching twice gravely inefficient, will fix some time */
+char *pager_getUserPhoneNumber(long configMsgNum) {
+       if (configMsgNum == -1) {
+               return;
+       }
+       struct CtdlMessage *prefMsg;
+       prefMsg = CtdlFetchMessage(configMsgNum, 1);
+       char *msgContents = prefMsg->cm_fields['M'];
+       char *lines = strtok(msgContents, "textmessage\n");
+       return lines;
+}
+CTDL_MODULE_INIT(pager)
+{
+       create_pager_queue();
+       CtdlRegisterSessionHook(do_pager_queue, EVT_TIMER);
+
+       /* return our Subversion id for the Log */
+        return "$Id: serv_pager.c $";
+}
index 54d3c39cb5f39c87de3a3045675ea5dd16fd3a39..016de159c9694e0818f3f5a38fcf24cac49224f5 100644 (file)
@@ -63,7 +63,6 @@
 #include "mime_parser.h"
 #include "vcard.h"
 #include "serv_vcard.h"
-#include "serv_ldap.h"
 
 #include "ctdl_module.h"
 
@@ -128,6 +127,195 @@ void vcard_extract_internet_addresses(struct CtdlMessage *msg,
 }
 
 
+/* 
+ * vCard-to-LDAP conversions.
+ *
+ * If 'op' is set to V2L_WRITE, then write
+ * (add, or change if already exists) a directory entry to the
+ * LDAP server, based on the information supplied in a vCard.
+ *
+ * If 'op' is set to V2L_DELETE, then delete the entry from LDAP.
+ */
+void ctdl_vcard_to_ldap(struct CtdlMessage *msg, int op) {
+       struct vCard *v = NULL;
+       int i;
+       int num_emails = 0;
+       int num_phones = 0;
+       int have_addr = 0;
+       int have_cn = 0;
+       
+       void *objectlist = NULL;
+
+       char givenname[128];
+       char sn[128];
+       char uid[256];
+       char street[256];
+       char city[128];
+       char state[3];
+       char zipcode[10];
+       char calFBURL[256];
+
+       if (msg == NULL) return;
+       if (msg->cm_fields['M'] == NULL) return;
+       if (msg->cm_fields['A'] == NULL) return;
+       if (msg->cm_fields['N'] == NULL) return;
+
+       /* Initialize variables */
+       strcpy(givenname, "");
+       strcpy(sn, "");
+       strcpy(calFBURL, "");
+
+       sprintf(uid, "%s@%s",
+               msg->cm_fields['A'],
+               msg->cm_fields['N']
+       );
+
+       /* Are we just deleting?  If so, it's simple... */
+       if (op == V2L_DELETE) {
+               (void) CtdlDoDirectoryServiceFunc (msg->cm_fields['A'], msg->cm_fields['N'], NULL, "ldap", DIRECTORY_USER_DEL);
+               return;
+       }
+
+       /*
+        * If we get to this point then it must be a V2L_WRITE operation.
+        */
+
+       /* First make sure the OU for the user's home Citadel host is created */
+       (void) CtdlDoDirectoryServiceFunc (NULL, msg->cm_fields['N'], NULL, "ldap", DIRECTORY_CREATE_HOST);
+       
+       /* Next create the directory service object */
+       (void) CtdlDoDirectoryServiceFunc(NULL, NULL, &objectlist, "ldap", DIRECTORY_CREATE_OBJECT);
+
+       /* The first LDAP attribute will be an 'objectclass' list.  Citadel
+        * doesn't do anything with this.  It's just there for compatibility
+        * with Kolab.
+        */
+       (void) CtdlDoDirectoryServiceFunc("objectclass", "citadelInetOrgPerson", &objectlist, "ldap", DIRECTORY_ATTRIB_ADD);
+
+       /* Convert the vCard fields to LDAP properties */
+       v = vcard_load(msg->cm_fields['M']);
+       if (v->numprops) for (i=0; i<(v->numprops); ++i) if (striplt(v->prop[i].value), strlen(v->prop[i].value) > 0) {
+
+               if (!strcasecmp(v->prop[i].name, "n")) {
+                       extract_token(sn,               v->prop[i].value, 0, ';', sizeof sn);
+                       extract_token(givenname,        v->prop[i].value, 1, ';', sizeof givenname);
+               }
+
+               if (!strcasecmp(v->prop[i].name, "fn")) {
+                       (void) CtdlDoDirectoryServiceFunc("cn", v->prop[i].value, &objectlist, "ldap", DIRECTORY_ATTRIB_ADD);
+                       have_cn = 1;
+               }
+
+               if (!strcasecmp(v->prop[i].name, "title")) {
+                       (void) CtdlDoDirectoryServiceFunc("title", v->prop[i].value, &objectlist, "ldap", DIRECTORY_ATTRIB_ADD);
+               }
+
+               if (!strcasecmp(v->prop[i].name, "org")) {
+                       (void) CtdlDoDirectoryServiceFunc("o", v->prop[i].value, &objectlist, "ldap", DIRECTORY_ATTRIB_ADD);
+               }
+
+               if ( (!strcasecmp(v->prop[i].name, "adr"))
+                  ||(!strncasecmp(v->prop[i].name, "adr;", 4)) ) {
+                       /* Unfortunately, we can only do a single address */
+                       if (!have_addr) {
+                               have_addr = 1;
+                               strcpy(street, "");
+                               extract_token(&street[strlen(street)],
+                                       v->prop[i].value, 0, ';', (sizeof street - strlen(street))); /* po box */
+                               strcat(street, " ");
+                               extract_token(&street[strlen(street)],
+                                       v->prop[i].value, 1, ';', (sizeof street - strlen(street))); /* extend addr */
+                               strcat(street, " ");
+                               extract_token(&street[strlen(street)],
+                                       v->prop[i].value, 2, ';', (sizeof street - strlen(street))); /* street */
+                               striplt(street);
+                               extract_token(city, v->prop[i].value, 3, ';', sizeof city);
+                               extract_token(state, v->prop[i].value, 4, ';', sizeof state);
+                               extract_token(zipcode, v->prop[i].value, 5, ';', sizeof zipcode);
+
+                               (void) CtdlDoDirectoryServiceFunc("street", street, &objectlist, "ldap", DIRECTORY_ATTRIB_ADD);
+                               (void) CtdlDoDirectoryServiceFunc("l", city, &objectlist, "ldap", DIRECTORY_ATTRIB_ADD);
+                               (void) CtdlDoDirectoryServiceFunc("st", state, &objectlist, "ldap", DIRECTORY_ATTRIB_ADD);
+                               (void) CtdlDoDirectoryServiceFunc("postalcode", zipcode, &objectlist, "ldap", DIRECTORY_ATTRIB_ADD);
+                       }
+               }
+
+               if ( (!strcasecmp(v->prop[i].name, "tel"))
+                  ||(!strncasecmp(v->prop[i].name, "tel;", 4)) ) {
+                       ++num_phones;
+                       /* The first 'tel' property creates the 'telephoneNumber' attribute */
+                       if (num_phones == 1) {
+                               (void) CtdlDoDirectoryServiceFunc("telephoneNumber", v->prop[i].value, &objectlist, "ldap", DIRECTORY_ATTRIB_ADD);
+                       }
+                       /* Subsequent 'tel' properties *add to* the 'telephoneNumber' attribute */
+                       else {
+                               (void) CtdlDoDirectoryServiceFunc("telephoneNumber", v->prop[i].value, &objectlist, "ldap", DIRECTORY_ATTRIB_ADD);
+                       }
+               }
+
+
+               if ( (!strcasecmp(v->prop[i].name, "email"))
+                  ||(!strcasecmp(v->prop[i].name, "email;internet")) ) {
+       
+                       ++num_emails;
+                       lprintf(CTDL_DEBUG, "email addr %d\n", num_emails);
+
+                       /* The first email address creates the 'mail' attribute */
+                       if (num_emails == 1) {
+                               (void) CtdlDoDirectoryServiceFunc("mail", v->prop[i].value, &objectlist, "ldap", DIRECTORY_ATTRIB_ADD);
+                       }
+                       /* The second and subsequent email address creates the 'alias' attribute */
+                       else if (num_emails >= 2) {
+                               (void) CtdlDoDirectoryServiceFunc("alias", v->prop[i].value, &objectlist, "ldap", DIRECTORY_ATTRIB_ADD);
+                       }
+               }
+
+               /* Calendar free/busy URL (take the first one we find, but if a subsequent
+                * one contains the "pref" designation then we go with that instead.)
+                */
+               if ( (!strcasecmp(v->prop[i].name, "fburl"))
+                  ||(!strncasecmp(v->prop[i].name, "fburl;", 6)) ) {
+                       if ( (IsEmptyStr(calFBURL))
+                          || (!strncasecmp(v->prop[i].name, "fburl;pref", 10)) ) {
+                               safestrncpy(calFBURL, v->prop[i].value, sizeof calFBURL);
+                       }
+               }
+
+       }
+       vcard_free(v);  /* Don't need this anymore. */
+
+       /* "sn" (surname) based on info in vCard */
+       (void) CtdlDoDirectoryServiceFunc("sn", sn, &objectlist, "ldap", DIRECTORY_ATTRIB_ADD);
+
+       /* "givenname" (first name) based on info in vCard */
+       if (IsEmptyStr(givenname)) strcpy(givenname, "_");
+       if (IsEmptyStr(sn)) strcpy(sn, "_");
+       (void) CtdlDoDirectoryServiceFunc("givenname", givenname, &objectlist, "ldap", DIRECTORY_ATTRIB_ADD);
+
+       /* "uid" is a Kolab compatibility thing.  We just do cituser@citnode */
+       (void) CtdlDoDirectoryServiceFunc("uid", uid, &objectlist, "ldap", DIRECTORY_ATTRIB_ADD);
+
+       /* Add a "cn" (Common Name) attribute based on the user's screen name,
+        * but only there was no 'fn' (full name) property in the vCard 
+        */
+       if (!have_cn) {
+               (void) CtdlDoDirectoryServiceFunc("cn", msg->cm_fields['A'], &objectlist, "ldap", DIRECTORY_ATTRIB_ADD);
+       }
+
+       /* Add a "calFBURL" attribute if a calendar free/busy URL exists */
+       if (!IsEmptyStr(calFBURL)) {
+               (void) CtdlDoDirectoryServiceFunc("calFBURL", calFBURL, &objectlist, "ldap", DIRECTORY_ATTRIB_ADD);
+       }
+       
+       (void) CtdlDoDirectoryServiceFunc(msg->cm_fields['A'], msg->cm_fields['N'], &objectlist, "ldap", DIRECTORY_SAVE_OBJECT);
+
+       (void) CtdlDoDirectoryServiceFunc(NULL, NULL, &objectlist, "ldap", DIRECTORY_FREE_OBJECT);
+       lprintf(CTDL_DEBUG, "LDAP write operation complete.\n");
+}
+
+
 
 /*
  * Callback for vcard_add_to_directory()
index 7af3da5341b055b6593346ea6ca8f2fd8d189337..9cc062c6c3dcfc1e1d54e8ae8a437cc51ed2f6c8 100644 (file)
@@ -25,6 +25,8 @@
 
 #include "modules/crypto/serv_crypto.h"        /* Needed until a universal crypto startup hook is implimented for CtdlStartTLS */
 
+#include "ctdl_module.h"
+
 #ifndef HAVE_SNPRINTF
 #include <stdarg.h>
 #include "snprintf.h"
@@ -51,6 +53,19 @@ struct ProtoFunctionHook {
 } *ProtoHookList = NULL;
 
 
+struct DirectoryServiceHook {
+       int (*handler) (char *cn, char *ou, void **object);
+       int cmd;
+       char *module;
+       struct DirectoryServiceHook *next;
+} *DirectoryServiceHookList = NULL;
+
+struct DirectoryObject {
+       char *module;
+       void *object;
+       struct DirectoryObject *next;
+};
+
 #define ERR_PORT (1 << 1)
 
 
@@ -1043,6 +1058,118 @@ void CtdlRegisterMaintenanceThread(char *name, void *(*thread_proc)(void *arg))
 }
 
 
+
+int CtdlRegisterDirectoryServiceFunc(int (*func)(char *cn, char *ou, void **object), int cmd, char *module)
+{
+       struct DirectoryServiceHook *newfcn;
+       
+       newfcn = DirectoryServiceHookList;
+       while (newfcn)
+       {
+               if (newfcn->cmd == cmd && !strcmp(newfcn->module, module))
+               {
+                       lprintf(CTDL_ERR, "Directory service function already handled by module %s\n", module);
+                       return -1;
+               }
+               newfcn = newfcn->next;
+       }
+       
+       newfcn = (struct DirectoryServiceHook *) malloc (sizeof(struct DirectoryServiceHook));
+       newfcn->handler = func;
+       newfcn->cmd = cmd;
+       newfcn->module = module;
+       newfcn->next = DirectoryServiceHookList;
+       DirectoryServiceHookList = newfcn;
+       
+       lprintf(CTDL_INFO, "Registered a new directory service function from module %s\n", module);
+       return 0;
+}
+
+int CtdlDoDirectoryServiceFunc(char *cn, char *ou, void **object, char *module, int cmd)
+{
+       struct DirectoryServiceHook *curfcn;
+       struct DirectoryObject *our_object_list = NULL;
+       struct DirectoryObject *newobject = NULL;
+       struct DirectoryObject *oldobject = NULL;
+       
+       
+       curfcn = DirectoryServiceHookList;
+       if (object)
+               our_object_list = (struct DirectoryObject *) *object;
+       
+       while (curfcn)
+       {
+               if (curfcn->cmd == cmd)
+               {
+                       if (!module)
+                       {
+                               if (cmd == DIRECTORY_CREATE_OBJECT)
+                               {
+                                       newobject = (struct DirectoryObject*) malloc (sizeof(struct DirectoryObject));
+                                       newobject->module = curfcn->module;
+                                       newobject->object = NULL;
+                                       newobject->next = our_object_list;
+                                       our_object_list = newobject;
+                               }
+                               if (our_object_list)
+                               {
+                                       for(newobject = our_object_list; newobject; newobject=newobject->next)
+                                       {
+                                               if (!strcmp(newobject->module, curfcn->module))
+                                                       (void) curfcn->handler(cn, ou, &newobject->object);
+                                       }
+                               }
+                               else
+                                       (void) curfcn->handler(cn, ou, NULL);
+
+                               continue;
+                       }
+                       else 
+                       {
+                               if(!strcmp(curfcn->module, module))
+                               {
+                                       if (cmd == DIRECTORY_CREATE_OBJECT)
+                                       {
+                                               newobject = (struct DirectoryObject*) malloc (sizeof(struct DirectoryObject));
+                                               newobject->module = module;
+                                               newobject->object = NULL;
+                                               newobject->next = our_object_list;
+                                               our_object_list = newobject;
+                                       }
+                                       if (our_object_list)
+                                       {
+                                               for(newobject = our_object_list; newobject; newobject=newobject->next)
+                                               {
+                                                       if (!strcmp(newobject->module, curfcn->module))
+                                                               (void) curfcn->handler(cn, ou, &newobject->object);
+                                               }
+                                       }
+                                       else
+                                               (void) (curfcn->handler(cn, ou, NULL));
+
+                                       break;
+                               }
+                       }
+               }
+               curfcn=curfcn->next;
+       }
+       if (our_object_list)
+       {
+               *object = our_object_list;
+               if (cmd == DIRECTORY_FREE_OBJECT)
+               {       // The objects pointed to by the list should have been freed by the module that created it
+                       for(newobject = our_object_list; newobject; )
+                       {
+                               oldobject=newobject;
+                               newobject=newobject->next;
+                               free(oldobject);
+                       }
+                       *object=NULL;
+               }
+       }
+       return 0;
+}
+
 /*
  * Dirty hack until we impliment a hook mechanism for this
  */
index f2595dba9203b22dd82cd82bf3213175d3f23834..5f3130d631f965a867bea3815d3f5cd52c000555 100644 (file)
@@ -7,9 +7,4 @@
 
 void ctdl_vcard_to_ldap(struct CtdlMessage *msg, int op);
 
-enum {
-       V2L_WRITE,
-       V2L_DELETE
-};
-
 #endif /* HAVE_LDAP */
index 0533cc8ff9b36c16dc43c359639ec1d00dcd6e9c..003b8d3d7accbeca5b5aa27fc2cfc691caf19c8f 100644 (file)
@@ -1,5 +1,11 @@
 /*
- * $Id$
+ * $Id$
  */
 void extract_inet_email_addrs(char *, size_t, char *, size_t, struct vCard *v, int local_addrs_only);
 struct vCard *vcard_get_user(struct ctdluser *u);
+
+enum {
+       V2L_WRITE,
+       V2L_DELETE
+};
+