From 1b71b791e56100f731d23aeec7a47c9d9ca2d7e0 Mon Sep 17 00:00:00 2001 From: Art Cancro Date: Tue, 16 May 2017 15:44:09 -0400 Subject: [PATCH] New data format for internet addresses, convert old vcard format to new for version 912 --- citadel/citadel.h | 3 +- citadel/configure.ac | 2 +- citadel/internet_addressing.c | 6 +- citadel/internet_addressing.h | 21 +---- citadel/modules/upgrade/serv_upgrade.c | 106 +++++++++++++++++++++++-- citadel/modules/vcard/serv_vcard.c | 101 +---------------------- citadel/user_ops.c | 32 +++----- 7 files changed, 120 insertions(+), 151 deletions(-) diff --git a/citadel/citadel.h b/citadel/citadel.h index b2c0f0868..811d0f195 100644 --- a/citadel/citadel.h +++ b/citadel/citadel.h @@ -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 }; diff --git a/citadel/configure.ac b/citadel/configure.ac index c67c79223..32c7974d9 100644 --- a/citadel/configure.ac +++ b/citadel/configure.ac @@ -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) diff --git a/citadel/internet_addressing.c b/citadel/internet_addressing.c index 355656ab5..4bf5e0fe0 100644 --- a/citadel/internet_addressing.c +++ b/citadel/internet_addressing.c @@ -46,7 +46,7 @@ #include #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); } diff --git a/citadel/internet_addressing.h b/citadel/internet_addressing.h index 62508d3fa..344a62929 100644 --- a/citadel/internet_addressing.h +++ b/citadel/internet_addressing.h @@ -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; - diff --git a/citadel/modules/upgrade/serv_upgrade.c b/citadel/modules/upgrade/serv_upgrade.c index 6ffe09773..7cf4d869a 100644 --- a/citadel/modules/upgrade/serv_upgrade.c +++ b/citadel/modules/upgrade/serv_upgrade.c @@ -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 = <%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); /* diff --git a/citadel/modules/vcard/serv_vcard.c b/citadel/modules/vcard/serv_vcard.c index 89692e34e..1a30a86ba 100644 --- a/citadel/modules/vcard/serv_vcard.c +++ b/citadel/modules/vcard/serv_vcard.c @@ -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"); diff --git a/citadel/user_ops.c b/citadel/user_ops.c index 5c3379b13..e19f238b0 100644 --- a/citadel/user_ops.c +++ b/citadel/user_ops.c @@ -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) { -- 2.30.2