New data format for internet addresses, convert old vcard format to new for version 912
authorArt Cancro <ajc@citadel.org>
Tue, 16 May 2017 19:44:09 +0000 (15:44 -0400)
committerArt Cancro <ajc@citadel.org>
Tue, 16 May 2017 19:44:09 +0000 (15:44 -0400)
citadel/citadel.h
citadel/configure.ac
citadel/internet_addressing.c
citadel/internet_addressing.h
citadel/modules/upgrade/serv_upgrade.c
citadel/modules/vcard/serv_vcard.c
citadel/user_ops.c

index b2c0f08681d19f88e0419781540da2b6a84829fc..811d0f1951f7935cc50512ca1cba4354041df3b2 100644 (file)
@@ -45,7 +45,7 @@ extern "C" {
  * usually more strict because you're not really supposed to dump/load and
  * upgrade at the same time.
  */
-#define REV_LEVEL      911             // This version
+#define REV_LEVEL      912             // This version
 #define REV_MIN                591             // Oldest compatible database
 #define EXPORT_REV_MIN 760             // Oldest compatible export files
 #define LIBCITADEL_MIN 903             // Minimum required version of libcitadel
@@ -115,6 +115,7 @@ struct ctdluser {                   // User record
        char fullname[64];              // Display name (primary identifier)
        long msgnum_bio;                // msgnum of user's profile (bio)
        long msgnum_pic;                // msgnum of user's avatar (photo)
+       char emailaddrs[512];           // Internet email addresses
 };
 
 
index c67c792236c5c885e0bf89e340cc8044e3bb6689..32c7974d991620e2c26c7e3c079cf22a5d083f92 100644 (file)
@@ -1,6 +1,6 @@
 dnl Process this file with autoconf to produce a configure script.
 AC_PREREQ(2.52)
-AC_INIT([Citadel], [911], [http://www.citadel.org/])
+AC_INIT([Citadel], [912], [http://www.citadel.org/])
 AC_REVISION([$Revision: 5108 $])
 AC_CONFIG_SRCDIR([citserver.c])
 AC_CONFIG_HEADER(sysdep.h)
index 355656ab52d888ee93297c9771a7285ca730a6f7..4bf5e0fe0614da98eb663f2a0d774b92d583ba3c 100644 (file)
@@ -46,7 +46,7 @@
 #include <iconv.h>
 
 #if 0
-/* This is the non-define version in case of s.b. needing to debug */
+/* This is the non-define version in case it is needed for debugging */
 inline void FindNextEnd (char *bptr, char *end)
 {
        /* Find the next ?Q? */
@@ -275,8 +275,6 @@ struct trynamebuf {
 };
 
 char *inetcfg = NULL;
-struct spamstrings_t *spamstrings = NULL;
-
 
 /*
  * Return nonzero if the supplied name is an alias for this host.
@@ -1526,7 +1524,7 @@ int IsDirectory(char *addr, int allow_masq_domains) {
 /*
  * Initialize the directory database (erasing anything already there)
  */
-void CtdlDirectoryInit(void) {
+void CtdlRebuildDirectoryIndex(void) {
        cdb_trunc(CDB_DIRECTORY);
 }
 
index 62508d3fa2934c8eefa0b00e05b8612ca65c1233..344a62929fe79281153c4bf3f019c9d0ca04040a 100644 (file)
@@ -2,28 +2,20 @@
 #include "server.h"
 #include "ctdl_module.h"
 
-recptypes *validate_recipients(const char *recipients,
-                                     const char *RemoteIdentifier, 
-                                     int Flags);
-
+recptypes *validate_recipients(const char *recipients, const char *RemoteIdentifier, int Flags);
 void free_recipients(recptypes *);
-
-
 void process_rfc822_addr(const char *rfc822, char *user, char *node, char *name);
 char *rfc822_fetch_field(const char *rfc822, const char *fieldname);
 void sanitize_truncated_recipient(char *str);
 char *qp_encode_email_addrs(char *source);
 int alias (char *name);
-
-
 int IsDirectory(char *addr, int allow_masq_domains);
-void CtdlDirectoryInit(void);
+void CtdlRebuildDirectoryIndex(void);
 int CtdlDirectoryAddUser(char *internet_addr, char *citadel_addr);
 int CtdlDirectoryDelUser(char *internet_addr, char *citadel_addr);
 int CtdlDirectoryLookup(char *target, char *internet_addr, size_t targbuflen);
 struct CtdlMessage *convert_internet_message(char *rfc822);
 struct CtdlMessage *convert_internet_message_buf(StrBuf **rfc822);
-
 int CtdlIsMe(char *addr, int addr_buf_len);
 int CtdlHostAlias(char *fqdn);
 char *harvest_collected_addresses(struct CtdlMessage *msg);
@@ -40,12 +32,3 @@ enum {
 };
 
 extern char *inetcfg;
-
-
-struct spamstrings_t {
-       struct spamstrings_t *next;
-       char *string;
-};
-
-extern struct spamstrings_t *spamstrings;
-
index 6ffe097736d73437baa1468e9dde9c8f5f17f522..7cf4d869aa718f2d3c6e22f6b05615188865a10f 100644 (file)
@@ -4,7 +4,7 @@
  * guesses about what kind of data format changes need to be applied, and
  * we apply them transparently.
  *
- * Copyright (c) 1987-2016 by the citadel.org team
+ * Copyright (c) 1987-2017 by the citadel.org team
  *
  * This program is open source software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License version 3.
@@ -52,6 +52,8 @@
 #include "serv_upgrade.h"
 #include "euidindex.h"
 #include "ctdl_module.h"
+#include "serv_vcard.h"
+#include "internet_addressing.h"
 
 
 /*
@@ -99,16 +101,18 @@ void fix_sys_user_name(void)
 
 /* 
  * Back end processing function for convert_ctdluid_to_minusone()
+ * Call this function as a ForEachUser backend in order to queue up
+ * room names, or call it with a null user to make it do the processing.
+ * This allows us to maintain the list as a static instead of passing
+ * pointers around.
  */
 void cbtm_backend(struct ctdluser *usbuf, void *data) {
        static struct UserProcList *uplist = NULL;
        struct UserProcList *ptr;
        struct ctdluser us;
 
-       /* Lazy programming here.  Call this function as a ForEachUser backend
-        * in order to queue up the room names, or call it with a null user
-        * to make it do the processing.
-        */
+       /* this is the calling mode where we add a user */
+
        if (usbuf != NULL) {
                ptr = (struct UserProcList *)
                        malloc(sizeof (struct UserProcList));
@@ -120,6 +124,8 @@ void cbtm_backend(struct ctdluser *usbuf, void *data) {
                return;
        }
 
+       /* this is the calling mode where we do the processing */
+
        while (uplist != NULL) {
 
                if (CtdlGetUserLock(&us, uplist->user) == 0) {
@@ -419,6 +425,92 @@ void update_config(void) {
 }
 
 
+/*
+ * Helper function for move_inet_addrs_from_vcards_to_user_records()
+ *
+ * Call this function as a ForEachUser backend in order to queue up
+ * room names, or call it with a null user to make it do the processing.
+ * This allows us to maintain the list as a static instead of passing
+ * pointers around.
+ */
+void miafvtur_backend(struct ctdluser *usbuf, void *data) {
+
+       struct miafvtur {
+               char name[64];
+               char emails[512];
+       };
+
+       static struct miafvtur *m = NULL;
+       static int num_m = 0;
+       static int alloc_m = 0;
+
+       /* this is the calling mode where we add a user */
+
+       if (usbuf != NULL) {
+               char primary_inet_email[512] = { 0 };
+               char other_inet_emails[512] = { 0 };
+               struct vCard *v = vcard_get_user(usbuf);
+               if (!v) return;
+               extract_inet_email_addrs(primary_inet_email, sizeof primary_inet_email, other_inet_emails, sizeof other_inet_emails, v, 1);
+               vcard_free(v);
+       
+               if ( (IsEmptyStr(primary_inet_email)) && (IsEmptyStr(other_inet_emails)) ) {
+                       return;
+               }
+
+               if (num_m >= alloc_m) {
+                       if (alloc_m == 0) {
+                               alloc_m = 100;
+                               m = malloc(sizeof(struct miafvtur) * alloc_m);
+                       }
+                       else {
+                               alloc_m *= 2;
+                               m = realloc(m, (sizeof(struct miafvtur) * alloc_m));
+                       }
+               }
+
+               strcpy(m[num_m].name, usbuf->fullname);
+               snprintf(m[num_m].emails, 512, "%s%s%s",
+                       (!IsEmptyStr(primary_inet_email) ? primary_inet_email : ""),
+                       ((!IsEmptyStr(primary_inet_email)&&(!IsEmptyStr(other_inet_emails))) ? "|" : ""),
+                       (!IsEmptyStr(other_inet_emails) ? other_inet_emails : "")
+               );
+               ++num_m;
+               return;
+       }
+
+       /* this is the calling mode where we do the processing */
+
+       int i;
+       struct ctdluser u;
+
+       CtdlRebuildDirectoryIndex();
+
+       for (i=0; i<num_m; ++i) {
+               syslog(LOG_DEBUG, "<%s> = <%s>", m[i].name, m[i].emails);
+               if (CtdlGetUser(&u, m[i].name) == 0) {
+                       safestrncpy(u.emailaddrs, m[i].emails, sizeof u.emailaddrs);
+                       CtdlPutUser(&u);
+               }
+       }
+       free(m);
+       num_m = 0;
+       alloc_m = 0;
+       abort();
+       return;
+}
+
+
+/*
+ * Prior to version 912 we kept a user's various Internet email addresses in their vCards.
+ * This function moves them over to the user record, which is where we keep them now.
+ */
+void move_inet_addrs_from_vcards_to_user_records(void)
+{
+       ForEachUser(miafvtur_backend, NULL);
+       miafvtur_backend(NULL, NULL);
+}
+
 
 /*
  * Based on the server version number reported by the existing database,
@@ -472,6 +564,10 @@ void check_server_upgrades(void) {
                ingest_old_roominfo_and_roompic_files();
        }
 
+       if ((CtdlGetConfigInt("MM_hosted_upgrade_level") > 000) && (CtdlGetConfigInt("MM_hosted_upgrade_level") < 912)) {
+               move_inet_addrs_from_vcards_to_user_records();
+       }
+
        CtdlSetConfigInt("MM_hosted_upgrade_level", REV_LEVEL);
 
        /*
index 89692e34efd9cd247160500e2764d08f8737af86..1a30a86babdda0024aca345c35f82b4cc764aa47 100644 (file)
@@ -129,103 +129,10 @@ void vcard_extract_internet_addresses(struct CtdlMessage *msg, int (*callback)(c
 
        vcard_free(v);
 }
-///TODO: gettext!
-#define _(a) a
-/*
- * Callback for vcard_add_to_directory()
- * (Lotsa ugly nested callbacks.  Oh well.)
- */
-int vcard_directory_add_user(char *internet_addr, char *citadel_addr) {
-       struct CitContext *CCC = CC;
-       char buf[SIZ];
-
-       /* We have to validate that we're not stepping on someone else's
-        * email address ... but only if we're logged in.  Otherwise it's
-        * probably just the networker or something.
-        */
-       if (CCC->logged_in) {
-               syslog(LOG_DEBUG, "Checking for <%s>...", internet_addr);
-               if (CtdlDirectoryLookup(buf, internet_addr, sizeof buf) == 0) {
-                       if (strcasecmp(buf, citadel_addr)) {
-                               /* This address belongs to someone else.
-                                * Bail out silently without saving.
-                                */
-                               syslog(LOG_DEBUG, "DOOP!");
-                               
-                               StrBufAppendPrintf(CCC->StatusMessage, "\n%d|", ERROR+ALREADY_EXISTS);
-                               StrBufAppendBufPlain(CCC->StatusMessage, internet_addr, -1, 0);
-                               StrBufAppendBufPlain(CCC->StatusMessage, HKEY("|"), 0);
-                               StrBufAppendBufPlain(CCC->StatusMessage, _("Unable to add this email address again."), -1, 0);
-                               StrBufAppendBufPlain(CCC->StatusMessage, HKEY("\n"), 0);
-                               return 0;
-                       }
-               }
-       }
-       syslog(LOG_INFO, "Adding %s (%s) to directory", citadel_addr, internet_addr);
-       if (CtdlDirectoryAddUser(internet_addr, citadel_addr))
-       {
-               StrBufAppendPrintf(CCC->StatusMessage, "\n%d|", CIT_OK);
-               StrBufAppendBufPlain(CCC->StatusMessage, internet_addr, -1, 0);
-               StrBufAppendBufPlain(CCC->StatusMessage, HKEY("|"), 0);
-               StrBufAppendBufPlain(CCC->StatusMessage, _("Successfully added email address."), -1, 0);
-               return 1;
-       }
-       else
-       {
-               StrBufAppendPrintf(CCC->StatusMessage, "\n%d|", ERROR+ ILLEGAL_VALUE);
-               StrBufAppendBufPlain(CCC->StatusMessage, internet_addr, -1, 0);
-               StrBufAppendBufPlain(CCC->StatusMessage, HKEY("|"), 0);
-               StrBufAppendBufPlain(CCC->StatusMessage, _("Unable to add this email address. It does not match any local domain."), -1, 0);
-               return 0;
-       }
-}
-
-
-/*
- * Back end function for cmd_igab()
- */
-void vcard_add_to_directory(long msgnum, void *data) {
-       struct CtdlMessage *msg;
-
-       msg = CtdlFetchMessage(msgnum, 1, 1);
-       if (msg != NULL) {
-               vcard_extract_internet_addresses(msg, vcard_directory_add_user);
-       }
-
-       CM_Free(msg);
-}
-
-
-/*
- * Initialize Global Adress Book
- */
-void cmd_igab(char *argbuf) {
-       char hold_rm[ROOMNAMELEN];
-
-       if (CtdlAccessCheck(ac_aide)) return;
-
-       strcpy(hold_rm, CC->room.QRname);       /* save current room */
-
-       if (CtdlGetRoom(&CC->room, ADDRESS_BOOK_ROOM) != 0) {
-               CtdlGetRoom(&CC->room, hold_rm);
-               cprintf("%d cannot get address book room\n", ERROR + ROOM_NOT_FOUND);
-               return;
-       }
-
-       /* Empty the existing database first.
-        */
-       CtdlDirectoryInit();
-
-       /* We want *all* vCards in this room */
-       NewStrBufDupAppendFlush(&CC->StatusMessage, NULL, NULL, 0);
-       CtdlForEachMessage(MSGS_ALL, 0, NULL, "[Tt][Ee][Xx][Tt]/.*[Vv][Cc][Aa][Rr][Dd]$",
-               NULL, vcard_add_to_directory, NULL);
-
-       CtdlGetRoom(&CC->room, hold_rm);        /* return to saved room */
-       cprintf("%d Directory has been rebuilt.\n", CIT_OK);
-}
 
 
+///TODO: gettext!
+#define _(a) a
 
 
 /*
@@ -586,9 +493,6 @@ int vcard_upload_aftersave(struct CtdlMessage *msg, recptypes *recp) {
                                CtdlSaveMsgPointerInRoom(ADDRESS_BOOK_ROOM, I, 1, msg);
                        }
 
-                       /* ...and also in the directory database. */
-                       vcard_add_to_directory(I, NULL);
-
                        /* Some sites want an Aide to be notified when a
                         * user registers or re-registers
                         * But if the user was an Aide or was edited by an Aide then we can
@@ -1522,7 +1426,6 @@ CTDL_MODULE_INIT(vcard)
                CtdlRegisterDeleteHook(vcard_delete_remove);
                CtdlRegisterProtoHook(cmd_regi, "REGI", "Enter registration info");
                CtdlRegisterProtoHook(cmd_greg, "GREG", "Get registration info");
-               CtdlRegisterProtoHook(cmd_igab, "IGAB", "Initialize Global Address Book");
                CtdlRegisterProtoHook(cmd_qdir, "QDIR", "Query Directory");
                CtdlRegisterProtoHook(cmd_gvsn, "GVSN", "Get Valid Screen Names");
                CtdlRegisterProtoHook(cmd_gvea, "GVEA", "Get Valid Email Addresses");
index 5c3379b13c9a5b91c000a9c1fee30f73335d3cda..e19f238b0359fddac35def6586ae2dca5bd98cd1 100644 (file)
@@ -38,7 +38,6 @@ int chkpwd_read_pipe[2];
  */
 int CtdlGetUserLen(struct ctdluser *usbuf, const char *name, long len)
 {
-
        char usernamekey[USERNAME_SIZE];
        struct cdbdata *cdbus;
 
@@ -68,13 +67,14 @@ int CtdlGetUser(struct ctdluser *usbuf, char *name)
        return CtdlGetUserLen(usbuf, name, cutuserkey(name));
 }
 
+
 int CtdlLockGetCurrentUser(void)
 {
        CitContext *CCC = CC;
-
        return CtdlGetUserLen(&CCC->user, CCC->curr_user, cutuserkey(CCC->curr_user));
 }
 
+
 /*
  * CtdlGetUserLock()  -  same as getuser() but locks the record
  */
@@ -97,17 +97,12 @@ void CtdlPutUser(struct ctdluser *usbuf)
 {
        char usernamekey[USERNAME_SIZE];
 
-       makeuserkey(usernamekey, 
-                   usbuf->fullname, 
-                   cutuserkey(usbuf->fullname));
-
+       makeuserkey(usernamekey, usbuf->fullname, cutuserkey(usbuf->fullname));
        usbuf->version = REV_LEVEL;
-       cdb_store(CDB_USERS,
-                 usernamekey, strlen(usernamekey),
-                 usbuf, sizeof(struct ctdluser));
-
+       cdb_store(CDB_USERS, usernamekey, strlen(usernamekey), usbuf, sizeof(struct ctdluser));
 }
 
+
 void CtdlPutCurrentUserLock()
 {
        CtdlPutUser(&CC->user);
@@ -124,7 +119,6 @@ void CtdlPutUserLock(struct ctdluser *usbuf)
 }
 
 
-
 /*
  * rename_user()  -  this is tricky because the user's display name is the database key
  *
@@ -166,7 +160,7 @@ int rename_user(char *oldname, char *newname) {
                                syslog(LOG_DEBUG, "user_ops: can not rename user \"Citadel\".");
                                retcode = RENAMEUSER_NOT_FOUND;
                        } else {
-                               syslog(LOG_DEBUG, "user_ops: renaming <%s> to <%s>\n", oldname, newname);
+                               syslog(LOG_DEBUG, "user_ops: renaming <%s> to <%s>", oldname, newname);
                                cdb_delete(CDB_USERS, oldnamekey, strlen(oldnamekey));
                                safestrncpy(usbuf.fullname, newname, sizeof usbuf.fullname);
                                CtdlPutUser(&usbuf);
@@ -182,7 +176,6 @@ int rename_user(char *oldname, char *newname) {
 }
 
 
-
 /*
  * Index-generating function used by Ctdl[Get|Set]Relationship
  */
@@ -233,8 +226,6 @@ void CtdlSetRelationship(visit *newvisit,
                         struct ctdluser *rel_user,
                         struct ctdlroom *rel_room)
 {
-
-
        /* We don't use these in Citadel because they're implicit by the
         * index, but they must be present if the database is exported.
         */
@@ -245,6 +236,7 @@ void CtdlSetRelationship(visit *newvisit,
        put_visit(newvisit);
 }
 
+
 /*
  * Locate a relationship between a user and a room
  */
@@ -252,7 +244,6 @@ void CtdlGetRelationship(visit *vbuf,
                         struct ctdluser *rel_user,
                         struct ctdlroom *rel_room)
 {
-
        char IndexBuf[32];
        int IndexLen;
        struct cdbdata *cdbvisit;
@@ -321,6 +312,7 @@ int CtdlCheckInternetMailPermission(struct ctdluser *who) {
        return(0);
 }
 
+
 /*
  * Convenience function.
  */
@@ -328,8 +320,7 @@ int CtdlAccessCheck(int required_level)
 {
        if (CC->internal_pgm) return(0);
        if (required_level >= ac_internal) {
-               cprintf("%d This is not a user-level command.\n",
-                       ERROR + HIGHER_ACCESS_REQUIRED);
+               cprintf("%d This is not a user-level command.\n", ERROR + HIGHER_ACCESS_REQUIRED);
                return(-1);
        }
 
@@ -362,7 +353,6 @@ int CtdlAccessCheck(int required_level)
 }
 
 
-
 /*
  * Is the user currently logged in an Admin?
  */
@@ -809,7 +799,7 @@ void start_chkpwd_daemon(void) {
        syslog(LOG_DEBUG, "user_ops: starting chkpwd daemon for host authentication mode");
 
        if ((stat(file_chkpwd, &filestats)==-1) || (filestats.st_size==0)) {
-               printf("didn't find chkpwd daemon in %s: %s\n", file_chkpwd, strerror(errno));
+               syslog(LOG_ERR, "user_ops: %s: %s", file_chkpwd, strerror(errno));
                abort();
        }
        if (pipe(chkpwd_write_pipe) != 0) {
@@ -1044,11 +1034,9 @@ int create_user(const char *newusername, long len, int become_user)
        char buf[SIZ];
        int retval;
        uid_t uid = (-1);
-       
 
        safestrncpy(username, newusername, sizeof username);
        strproc(username);
-
        
        if (CtdlGetConfigInt("c_auth_mode") == AUTHMODE_HOST) {