* 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
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
};
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)
#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? */
};
char *inetcfg = NULL;
-struct spamstrings_t *spamstrings = NULL;
-
/*
* Return nonzero if the supplied name is an alias for this host.
/*
* Initialize the directory database (erasing anything already there)
*/
-void CtdlDirectoryInit(void) {
+void CtdlRebuildDirectoryIndex(void) {
cdb_trunc(CDB_DIRECTORY);
}
#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);
};
extern char *inetcfg;
-
-
-struct spamstrings_t {
- struct spamstrings_t *next;
- char *string;
-};
-
-extern struct spamstrings_t *spamstrings;
-
* 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.
#include "serv_upgrade.h"
#include "euidindex.h"
#include "ctdl_module.h"
+#include "serv_vcard.h"
+#include "internet_addressing.h"
/*
/*
* 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));
return;
}
+ /* this is the calling mode where we do the processing */
+
while (uplist != NULL) {
if (CtdlGetUserLock(&us, uplist->user) == 0) {
}
+/*
+ * 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,
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);
/*
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
/*
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
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");
*/
int CtdlGetUserLen(struct ctdluser *usbuf, const char *name, long len)
{
-
char usernamekey[USERNAME_SIZE];
struct cdbdata *cdbus;
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
*/
{
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);
}
-
/*
* rename_user() - this is tricky because the user's display name is the database key
*
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);
}
-
/*
* Index-generating function used by Ctdl[Get|Set]Relationship
*/
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.
*/
put_visit(newvisit);
}
+
/*
* Locate a relationship between a user and a room
*/
struct ctdluser *rel_user,
struct ctdlroom *rel_room)
{
-
char IndexBuf[32];
int IndexLen;
struct cdbdata *cdbvisit;
return(0);
}
+
/*
* Convenience function.
*/
{
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);
}
}
-
/*
* Is the user currently logged in an Admin?
*/
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) {
char buf[SIZ];
int retval;
uid_t uid = (-1);
-
safestrncpy(username, newusername, sizeof username);
strproc(username);
-
if (CtdlGetConfigInt("c_auth_mode") == AUTHMODE_HOST) {