+ char original_name[256];
+ safestrncpy(original_name, name, sizeof original_name);
+
+ striplt(name);
+ remove_any_whitespace_to_the_left_or_right_of_at_symbol(name);
+ stripallbut(name, '<', '>');
+
+ fp = fopen(file_mail_aliases, "r"); // when are we going to get rid of this?
+ if (fp == NULL) {
+ fp = fopen("/dev/null", "r");
+ }
+ if (fp == NULL) {
+ return (MES_ERROR);
+ }
+ strcpy(aaa, "");
+ strcpy(bbb, "");
+ while (fgets(aaa, sizeof aaa, fp) != NULL) {
+ while (isspace(name[0]))
+ strcpy(name, &name[1]);
+ aaa[strlen(aaa) - 1] = 0;
+ strcpy(bbb, "");
+ for (a = 0; aaa[a] != '\0'; ++a) {
+ if (aaa[a] == ',') {
+ strcpy(bbb, &aaa[a + 1]);
+ aaa[a] = 0;
+ break;
+ }
+ }
+ if (!strcasecmp(name, aaa))
+ strcpy(name, bbb);
+ }
+ fclose(fp);
+
+ /* Hit the email address directory */
+ if (CtdlDirectoryLookup(aaa, name, sizeof aaa) == 0) {
+ strcpy(name, aaa);
+ }
+
+ if (strcasecmp(original_name, name)) {
+ syslog(LOG_INFO, "internet_addressing: %s is being forwarded to %s", original_name, name);
+ }
+
+ /* Change "user @ xxx" to "user" if xxx is an alias for this host */
+ for (a=0; name[a] != '\0'; ++a) {
+ if (name[a] == '@') {
+ if (CtdlHostAlias(&name[a+1]) == hostalias_localhost) {
+ name[a] = 0;
+ syslog(LOG_DEBUG, "internet_addressing: changed to <%s>", name);
+ break;
+ }
+ }
+ }
+
+ /* determine local or remote type, see citadel.h */
+ at = haschar(name, '@');
+ if (at == 0) return(MES_LOCAL); /* no @'s - local address */
+ if (at > 1) return(MES_ERROR); /* >1 @'s - invalid address */
+ remove_any_whitespace_to_the_left_or_right_of_at_symbol(name);
+
+ /* figure out the delivery mode */
+ extract_token(node, name, 1, '@', sizeof node);
+
+ /* If there are one or more dots in the nodename, we assume that it
+ * is an FQDN and will attempt SMTP delivery to the Internet.
+ */
+ if (haschar(node, '.') > 0) {
+ return(MES_INTERNET);
+ }
+
+ /* If we get to this point it's an invalid node name */
+ return (MES_ERROR);
+}
+
+
+/*
+ * Validate recipients, count delivery types and errors, and handle aliasing
+ * FIXME check for dupes!!!!!
+ *
+ * Returns 0 if all addresses are ok, ret->num_error = -1 if no addresses
+ * were specified, or the number of addresses found invalid.
+ *
+ * Caller needs to free the result using free_recipients()
+ */
+recptypes *validate_recipients(const char *supplied_recipients, const char *RemoteIdentifier, int Flags)
+{
+ struct CitContext *CCC = CC;
+ recptypes *ret;
+ char *recipients = NULL;
+ char *org_recp;
+ char this_recp[256];
+ char this_recp_cooked[256];
+ char append[SIZ];
+ long len;
+ int num_recps = 0;
+ int i, j;
+ int mailtype;
+ int invalid;
+ struct ctdluser tempUS;
+ struct ctdlroom tempQR;
+ struct ctdlroom tempQR2;
+ int err = 0;
+ char errmsg[SIZ];
+ int in_quotes = 0;
+
+ /* Initialize */
+ ret = (recptypes *) malloc(sizeof(recptypes));
+ if (ret == NULL) return(NULL);
+
+ /* Set all strings to null and numeric values to zero */
+ memset(ret, 0, sizeof(recptypes));
+
+ if (supplied_recipients == NULL) {
+ recipients = strdup("");
+ }
+ else {
+ recipients = strdup(supplied_recipients);
+ }
+
+ /* Allocate some memory. Yes, this allocates 500% more memory than we will
+ * actually need, but it's healthier for the heap than doing lots of tiny
+ * realloc() calls instead.
+ */
+ len = strlen(recipients) + 1024;
+ ret->errormsg = malloc(len);
+ ret->recp_local = malloc(len);
+ ret->recp_internet = malloc(len);
+ ret->recp_room = malloc(len);
+ ret->display_recp = malloc(len);
+ ret->recp_orgroom = malloc(len);
+ org_recp = malloc(len);
+
+ ret->errormsg[0] = 0;
+ ret->recp_local[0] = 0;
+ ret->recp_internet[0] = 0;
+ ret->recp_room[0] = 0;
+ ret->recp_orgroom[0] = 0;
+ ret->display_recp[0] = 0;
+
+ ret->recptypes_magic = RECPTYPES_MAGIC;
+
+ /* Change all valid separator characters to commas */
+ for (i=0; !IsEmptyStr(&recipients[i]); ++i) {
+ if ((recipients[i] == ';') || (recipients[i] == '|')) {
+ recipients[i] = ',';
+ }
+ }
+
+ /* Now start extracting recipients... */
+
+ while (!IsEmptyStr(recipients)) {
+ for (i=0; i<=strlen(recipients); ++i) {
+ if (recipients[i] == '\"') in_quotes = 1 - in_quotes;
+ if ( ( (recipients[i] == ',') && (!in_quotes) ) || (recipients[i] == 0) ) {
+ safestrncpy(this_recp, recipients, i+1);
+ this_recp[i] = 0;
+ if (recipients[i] == ',') {
+ strcpy(recipients, &recipients[i+1]);
+ }
+ else {
+ strcpy(recipients, "");
+ }
+ break;
+ }
+ }
+
+ striplt(this_recp);
+ if (IsEmptyStr(this_recp))
+ break;
+ syslog(LOG_DEBUG, "internet_addressing: evaluating recipient #%d: %s", num_recps, this_recp);
+ ++num_recps;
+
+ strcpy(org_recp, this_recp);
+ alias(this_recp);
+ alias(this_recp);
+ mailtype = alias(this_recp);
+
+ for (j = 0; !IsEmptyStr(&this_recp[j]); ++j) {
+ if (this_recp[j]=='_') {
+ this_recp_cooked[j] = ' ';
+ }
+ else {
+ this_recp_cooked[j] = this_recp[j];
+ }
+ }
+ this_recp_cooked[j] = '\0';
+ invalid = 0;
+ errmsg[0] = 0;
+ switch(mailtype) {
+ case MES_LOCAL:
+ if (!strcasecmp(this_recp, "sysop")) {
+ ++ret->num_room;
+ strcpy(this_recp, CtdlGetConfigStr("c_aideroom"));
+ if (!IsEmptyStr(ret->recp_room)) {
+ strcat(ret->recp_room, "|");
+ }
+ strcat(ret->recp_room, this_recp);
+ }
+ else if ( (!strncasecmp(this_recp, "room_", 5))
+ && (!CtdlGetRoom(&tempQR, &this_recp_cooked[5])) ) {
+
+ /* Save room so we can restore it later */
+ tempQR2 = CCC->room;
+ CCC->room = tempQR;
+
+ /* Check permissions to send mail to this room */
+ err = CtdlDoIHavePermissionToPostInThisRoom(
+ errmsg,
+ sizeof errmsg,
+ RemoteIdentifier,
+ Flags,
+ 0 /* 0 = not a reply */
+ );
+ if (err)
+ {
+ ++ret->num_error;
+ invalid = 1;
+ }
+ else {
+ ++ret->num_room;
+ if (!IsEmptyStr(ret->recp_room)) {
+ strcat(ret->recp_room, "|");
+ }
+ strcat(ret->recp_room, &this_recp_cooked[5]);
+
+ if (!IsEmptyStr(ret->recp_orgroom)) {
+ strcat(ret->recp_orgroom, "|");
+ }
+ strcat(ret->recp_orgroom, org_recp);
+
+ }
+
+ /* Restore room in case something needs it */
+ CCC->room = tempQR2;
+
+ }
+ else if (CtdlGetUser(&tempUS, this_recp) == 0) {
+ ++ret->num_local;
+ strcpy(this_recp, tempUS.fullname);
+ if (!IsEmptyStr(ret->recp_local)) {
+ strcat(ret->recp_local, "|");
+ }
+ strcat(ret->recp_local, this_recp);
+ }
+ else if (CtdlGetUser(&tempUS, this_recp_cooked) == 0) {
+ ++ret->num_local;
+ strcpy(this_recp, tempUS.fullname);
+ if (!IsEmptyStr(ret->recp_local)) {
+ strcat(ret->recp_local, "|");
+ }
+ strcat(ret->recp_local, this_recp);
+ }
+ else {
+ ++ret->num_error;
+ invalid = 1;
+ }
+ break;
+ case MES_INTERNET:
+ /* Yes, you're reading this correctly: if the target
+ * domain points back to the local system,
+ * the address is invalid. That's
+ * because if the address were valid, we would have
+ * already translated it to a local address by now.
+ */
+ if (IsDirectory(this_recp, 0)) {
+ ++ret->num_error;
+ invalid = 1;
+ }
+ else {
+ ++ret->num_internet;
+ if (!IsEmptyStr(ret->recp_internet)) {
+ strcat(ret->recp_internet, "|");
+ }
+ strcat(ret->recp_internet, this_recp);
+ }
+ break;
+ case MES_ERROR:
+ ++ret->num_error;
+ invalid = 1;
+ break;
+ }
+ if (invalid) {
+ if (IsEmptyStr(errmsg)) {
+ snprintf(append, sizeof append, "Invalid recipient: %s", this_recp);
+ }
+ else {
+ snprintf(append, sizeof append, "%s", errmsg);
+ }
+ if ( (strlen(ret->errormsg) + strlen(append) + 3) < SIZ) {
+ if (!IsEmptyStr(ret->errormsg)) {
+ strcat(ret->errormsg, "; ");
+ }
+ strcat(ret->errormsg, append);
+ }
+ }
+ else {
+ if (IsEmptyStr(ret->display_recp)) {
+ strcpy(append, this_recp);
+ }
+ else {
+ snprintf(append, sizeof append, ", %s", this_recp);
+ }
+ if ( (strlen(ret->display_recp)+strlen(append)) < SIZ) {
+ strcat(ret->display_recp, append);
+ }
+ }
+ }
+ free(org_recp);
+
+ if ( (ret->num_local + ret->num_internet + ret->num_room + ret->num_error) == 0)
+ {
+ ret->num_error = (-1);
+ strcpy(ret->errormsg, "No recipients specified.");