/* * smtp_queue_thread() * * Run through the queue sending out messages. */ void smtp_do_queue(void) { int num_processed = 0; int num_activated = 0; pthread_setspecific(MyConKey, (void *)&smtp_queue_CC); SMTPCM_syslog(LOG_DEBUG, "processing outbound queue"); if (CtdlGetRoom(&CC->room, SMTP_SPOOLOUT_ROOM) != 0) { SMTPC_syslog(LOG_ERR, "Cannot find room <%s>", SMTP_SPOOLOUT_ROOM); } else { num_processed = CtdlForEachMessage(MSGS_ALL, 0L, NULL, SPOOLMIME, NULL, smtp_do_procmsg, &num_activated); } if (num_activated > 0) { SMTPC_syslog(LOG_INFO, "queue run completed; %d messages processed %d activated", num_processed, num_activated); } }
/* * get room parameters (admin or room admin command) */ void cmd_getr(char *cmdbuf) { if (CtdlAccessCheck(ac_room_aide)) return; CtdlGetRoom(&CC->room, CC->room.QRname); cprintf("%d%c%s|%s|%s|%d|%d|%d|%d|%d|\n", CIT_OK, CtdlCheckExpress(), ((CC->room.QRflags & QR_MAILBOX) ? &CC->room.QRname[11] : CC->room.QRname), ((CC->room.QRflags & QR_PASSWORDED) ? CC->room.QRpasswd : ""), ((CC->room.QRflags & QR_DIRECTORY) ? CC->room.QRdirname : ""), CC->room.QRflags, (int) CC->room.QRfloor, (int) CC->room.QRorder, CC->room.QRdefaultview, CC->room.QRflags2 ); }
/* * Scan a room for messages to index. */ void ft_index_room(struct ctdlroom *qrbuf, void *data) { if (server_shutting_down) return; CtdlGetRoom(&CC->room, qrbuf->QRname); CtdlForEachMessage(MSGS_ALL, 0L, NULL, NULL, NULL, ft_index_msg, NULL); }
/* * Fetch the "mortuary" - a list of dead buddies which we keep around forever * so we can remove them from any client's roster that still has them listed */ HashList *xmpp_fetch_mortuary(void) { HashList *mortuary = NewHash(1, NULL); if (!mortuary) { syslog(LOG_ALERT, "NewHash() failed!\n"); return(NULL); } if (CtdlGetRoom(&CC->room, USERCONFIGROOM) != 0) { /* no config room exists - no further processing is required. */ return(mortuary); } CtdlForEachMessage(MSGS_LAST, 1, NULL, XMPPMORTUARY, NULL, xmpp_fetch_mortuary_backend, (void *)mortuary ); return(mortuary); }
int PurgeRooms(void) { struct PurgeList *pptr; int num_rooms_purged = 0; struct ctdlroom qrbuf; struct ValidUser *vuptr; char *transcript = NULL; syslog(LOG_DEBUG, "PurgeRooms() called"); /* Load up a table full of valid user numbers so we can delete * user-owned rooms for users who no longer exist */ ForEachUser(AddValidUser, NULL); /* Then cycle through the room file */ CtdlForEachRoom(DoPurgeRooms, NULL); /* Free the valid user list */ while (ValidUserList != NULL) { vuptr = ValidUserList->next; free(ValidUserList); ValidUserList = vuptr; } transcript = malloc(SIZ); strcpy(transcript, "The following rooms have been auto-purged:\n"); while (RoomPurgeList != NULL) { if (CtdlGetRoom(&qrbuf, RoomPurgeList->name) == 0) { transcript=realloc(transcript, strlen(transcript)+SIZ); snprintf(&transcript[strlen(transcript)], SIZ, " %s\n", qrbuf.QRname); CtdlDeleteRoom(&qrbuf); } pptr = RoomPurgeList->next; free(RoomPurgeList); RoomPurgeList = pptr; ++num_rooms_purged; } if (num_rooms_purged > 0) CtdlAideMessage(transcript, "Room Autopurger Message"); free(transcript); syslog(LOG_DEBUG, "Purged %d rooms.", num_rooms_purged); return(num_rooms_purged); }
/* * callback to get highest room number when rebuilding control file */ void control_find_highest(struct ctdlroom *qrbuf, void *data) { struct ctdlroom room; struct cdbdata *cdbfr; long *msglist; int num_msgs=0; int c; int room_fixed = 0; int message_fixed = 0; if (qrbuf->QRnumber > CitControl.MMnextroom) { CitControl.MMnextroom = qrbuf->QRnumber; room_fixed = 1; } CtdlGetRoom (&room, qrbuf->QRname); /* Load the message list */ cdbfr = cdb_fetch(CDB_MSGLISTS, &room.QRnumber, sizeof(long)); if (cdbfr != NULL) { msglist = (long *) cdbfr->ptr; num_msgs = cdbfr->len / sizeof(long); } else { return; /* No messages at all? No further action. */ } if (num_msgs>0) { for (c=0; c<num_msgs; c++) { if (msglist[c] > CitControl.MMhighest) { CitControl.MMhighest = msglist[c]; message_fixed = 1; } } } cdb_free(cdbfr); if (room_fixed) syslog(LOG_INFO, "Control record checking....Fixed room counter\n"); if (message_fixed) syslog(LOG_INFO, "Control record checking....Fixed message count\n"); return; }
/* * set room parameters (admin or room admin command) */ void cmd_setr(char *args) { char buf[256]; int new_order = 0; int r; int new_floor; char new_name[ROOMNAMELEN]; if (CtdlAccessCheck(ac_logged_in)) return; if (num_parms(args) >= 6) { new_floor = extract_int(args, 5); } else { new_floor = (-1); /* don't change the floor */ } /* When is a new name more than just a new name? When the old name * has a namespace prefix. */ if (CC->room.QRflags & QR_MAILBOX) { sprintf(new_name, "%010ld.", atol(CC->room.QRname) ); } else { safestrncpy(new_name, "", sizeof new_name); } extract_token(&new_name[strlen(new_name)], args, 0, '|', (sizeof new_name - strlen(new_name))); r = CtdlRenameRoom(CC->room.QRname, new_name, new_floor); if (r == crr_room_not_found) { cprintf("%d Internal error - room not found?\n", ERROR + INTERNAL_ERROR); } else if (r == crr_already_exists) { cprintf("%d '%s' already exists.\n", ERROR + ALREADY_EXISTS, new_name); } else if (r == crr_noneditable) { cprintf("%d Cannot edit this room.\n", ERROR + NOT_HERE); } else if (r == crr_invalid_floor) { cprintf("%d Target floor does not exist.\n", ERROR + INVALID_FLOOR_OPERATION); } else if (r == crr_access_denied) { cprintf("%d You do not have permission to edit '%s'\n", ERROR + HIGHER_ACCESS_REQUIRED, CC->room.QRname); } else if (r != crr_ok) { cprintf("%d Error: CtdlRenameRoom() returned %d\n", ERROR + INTERNAL_ERROR, r); } if (r != crr_ok) { return; } CtdlGetRoom(&CC->room, new_name); /* Now we have to do a bunch of other stuff */ if (num_parms(args) >= 7) { new_order = extract_int(args, 6); if (new_order < 1) new_order = 1; if (new_order > 127) new_order = 127; } CtdlGetRoomLock(&CC->room, CC->room.QRname); /* Directory room */ extract_token(buf, args, 2, '|', sizeof buf); buf[15] = 0; safestrncpy(CC->room.QRdirname, buf, sizeof CC->room.QRdirname); /* Default view */ if (num_parms(args) >= 8) { CC->room.QRdefaultview = extract_int(args, 7); } /* Second set of flags */ if (num_parms(args) >= 9) { CC->room.QRflags2 = extract_int(args, 8); } /* Misc. flags */ CC->room.QRflags = (extract_int(args, 3) | QR_INUSE); /* Clean up a client boo-boo: if the client set the room to * guess-name or passworded, ensure that the private flag is * also set. */ if ((CC->room.QRflags & QR_GUESSNAME) || (CC->room.QRflags & QR_PASSWORDED)) CC->room.QRflags |= QR_PRIVATE; /* Some changes can't apply to BASEROOM */ if (!strncasecmp(CC->room.QRname, CtdlGetConfigStr("c_baseroom"), ROOMNAMELEN)) { CC->room.QRorder = 0; CC->room.QRpasswd[0] = '\0'; CC->room.QRflags &= ~(QR_PRIVATE & QR_PASSWORDED & QR_GUESSNAME & QR_PREFONLY & QR_MAILBOX); CC->room.QRflags |= QR_PERMANENT; } else { /* March order (doesn't apply to AIDEROOM) */ if (num_parms(args) >= 7) CC->room.QRorder = (char) new_order; /* Room password */ extract_token(buf, args, 1, '|', sizeof buf); buf[10] = 0; safestrncpy(CC->room.QRpasswd, buf, sizeof CC->room.QRpasswd); /* Kick everyone out if the client requested it * (by changing the room's generation number) */ if (extract_int(args, 4)) { time(&CC->room.QRgen); } } /* Some changes can't apply to AIDEROOM */ if (!strncasecmp(CC->room.QRname, CtdlGetConfigStr("c_baseroom"), ROOMNAMELEN)) { CC->room.QRorder = 0; CC->room.QRflags &= ~QR_MAILBOX; CC->room.QRflags |= QR_PERMANENT; } /* Write the room record back to disk */ CtdlPutRoomLock(&CC->room); /* Create a room directory if necessary */ if (CC->room.QRflags & QR_DIRECTORY) { snprintf(buf, sizeof buf,"%s/%s", ctdl_file_dir, CC->room.QRdirname); mkdir(buf, 0755); } snprintf(buf, sizeof buf, "The room \"%s\" has been edited by %s.\n", CC->room.QRname, (CC->logged_in ? CC->curr_user : "******") ); CtdlAideMessage(buf, "Room modification Message"); cprintf("%d Ok\n", CIT_OK); }
/* * RDIR command for room directory */ void cmd_rdir(char *cmdbuf) { char buf[256]; char comment[256]; FILE *fd; struct stat statbuf; DIR *filedir = NULL; struct dirent *filedir_entry; int d_namelen; char buf2[SIZ]; char mimebuf[64]; long len; if (CtdlAccessCheck(ac_logged_in)) return; CtdlGetRoom(&CC->room, CC->room.QRname); CtdlGetUser(&CC->user, CC->curr_user); if ((CC->room.QRflags & QR_DIRECTORY) == 0) { cprintf("%d not here.\n", ERROR + NOT_HERE); return; } if (((CC->room.QRflags & QR_VISDIR) == 0) && (CC->user.axlevel < AxAideU) && (CC->user.usernum != CC->room.QRroomaide)) { cprintf("%d not here.\n", ERROR + HIGHER_ACCESS_REQUIRED); return; } snprintf(buf, sizeof buf, "%s/%s", ctdl_file_dir, CC->room.QRdirname); filedir = opendir (buf); if (filedir == NULL) { cprintf("%d not here.\n", ERROR + HIGHER_ACCESS_REQUIRED); return; } cprintf("%d %s|%s/%s\n", LISTING_FOLLOWS, CtdlGetConfigStr("c_fqdn"), ctdl_file_dir, CC->room.QRdirname); snprintf(buf, sizeof buf, "%s/%s/filedir", ctdl_file_dir, CC->room.QRdirname); fd = fopen(buf, "r"); if (fd == NULL) fd = fopen("/dev/null", "r"); while ((filedir_entry = readdir(filedir))) { if (strcasecmp(filedir_entry->d_name, "filedir") && filedir_entry->d_name[0] != '.') { #ifdef _DIRENT_HAVE_D_NAMELEN d_namelen = filedir_entry->d_namlen; #else d_namelen = strlen(filedir_entry->d_name); #endif snprintf(buf, sizeof buf, "%s/%s/%s", ctdl_file_dir, CC->room.QRdirname, filedir_entry->d_name); stat(buf, &statbuf); /* stat the file */ if (!(statbuf.st_mode & S_IFREG)) { snprintf(buf2, sizeof buf2, "\"%s\" appears in the file directory for room \"%s\" but is not a regular file. Directories, named pipes, sockets, etc. are not usable in Citadel room directories.\n", buf, CC->room.QRname ); CtdlAideMessage(buf2, "Unusable data found in room directory"); continue; /* not a useable file type so don't show it */ } safestrncpy(comment, "", sizeof comment); fseek(fd, 0L, 0); /* rewind descriptions file */ /* Get the description from the descriptions file */ while ((fgets(buf, sizeof buf, fd) != NULL) && (IsEmptyStr(comment))) { buf[strlen(buf) - 1] = 0; if ((!strncasecmp(buf, filedir_entry->d_name, d_namelen)) && (buf[d_namelen] == ' ')) safestrncpy(comment, &buf[d_namelen + 1], sizeof comment); } len = extract_token (mimebuf, comment, 0,' ', 64); if ((len <0) || strchr(mimebuf, '/') == NULL) { snprintf (mimebuf, 64, "application/octetstream"); len = 0; } cprintf("%s|%ld|%s|%s\n", filedir_entry->d_name, (long)statbuf.st_size, mimebuf, &comment[len]); } } fclose(fd); closedir(filedir); cprintf("000\n"); }
/* * cmd_goto() - goto a new room */ void cmd_goto(char *gargs) { struct ctdlroom QRscratch; int c; int ok = 0; int ra; char augmented_roomname[ROOMNAMELEN]; char towhere[ROOMNAMELEN]; char password[32]; int transiently = 0; if (CtdlAccessCheck(ac_logged_in_or_guest)) return; extract_token(towhere, gargs, 0, '|', sizeof towhere); extract_token(password, gargs, 1, '|', sizeof password); transiently = extract_int(gargs, 2); CtdlGetUser(&CC->user, CC->curr_user); /* * Handle some of the macro named rooms */ convert_room_name_macros(towhere, sizeof towhere); /* First try a regular match */ c = CtdlGetRoom(&QRscratch, towhere); /* Then try a mailbox name match */ if (c != 0) { CtdlMailboxName(augmented_roomname, sizeof augmented_roomname, &CC->user, towhere); c = CtdlGetRoom(&QRscratch, augmented_roomname); if (c == 0) safestrncpy(towhere, augmented_roomname, sizeof towhere); } /* And if the room was found... */ if (c == 0) { /* Let internal programs go directly to any room. */ if (CC->internal_pgm) { memcpy(&CC->room, &QRscratch, sizeof(struct ctdlroom)); CtdlUserGoto(NULL, 1, transiently, NULL, NULL, NULL, NULL); return; } /* See if there is an existing user/room relationship */ CtdlRoomAccess(&QRscratch, &CC->user, &ra, NULL); /* normal clients have to pass through security */ if (ra & UA_GOTOALLOWED) { ok = 1; } if (ok == 1) { if ((QRscratch.QRflags & QR_MAILBOX) && ((ra & UA_GOTOALLOWED))) { memcpy(&CC->room, &QRscratch, sizeof(struct ctdlroom)); CtdlUserGoto(NULL, 1, transiently, NULL, NULL, NULL, NULL); return; } else if ((QRscratch.QRflags & QR_PASSWORDED) && ((ra & UA_KNOWN) == 0) && (strcasecmp(QRscratch.QRpasswd, password)) && (CC->user.axlevel < AxAideU) ) { cprintf("%d wrong or missing passwd\n", ERROR + PASSWORD_REQUIRED); return; } else if ((QRscratch.QRflags & QR_PRIVATE) && ((QRscratch.QRflags & QR_PASSWORDED) == 0) && ((QRscratch.QRflags & QR_GUESSNAME) == 0) && ((ra & UA_KNOWN) == 0) && (CC->user.axlevel < AxAideU) ) { syslog(LOG_DEBUG, "Failed to acquire private room\n"); } else { memcpy(&CC->room, &QRscratch, sizeof(struct ctdlroom)); CtdlUserGoto(NULL, 1, transiently, NULL, NULL, NULL, NULL); return; } } } cprintf("%d room '%s' not found\n", ERROR + ROOM_NOT_FOUND, towhere); }
/* * cmd_stat() - return the modification time of the current room (maybe other things in the future) */ void cmd_stat(char *gargs) { if (CtdlAccessCheck(ac_logged_in_or_guest)) return; CtdlGetRoom(&CC->room, CC->room.QRname); cprintf("%d %s|%ld|\n", CIT_OK, CC->room.QRname, CC->room.QRmtime); }
// // Implements the GROUP and LISTGROUP commands // void nntp_group(const char *cmd) { if (CtdlAccessCheck(ac_logged_in_or_guest)) return; citnntp *nntpstate = (citnntp *) CC->session_specific_data; char verb[16]; char requested_group[1024]; char message_range[256]; char range_lo[256]; char range_hi[256]; char requested_room[ROOMNAMELEN]; char augmented_roomname[ROOMNAMELEN]; int c = 0; int ok = 0; int ra = 0; struct ctdlroom QRscratch; int msgs, new; long oldest,newest; struct listgroup_range lr; extract_token(verb, cmd, 0, ' ', sizeof verb); extract_token(requested_group, cmd, 1, ' ', sizeof requested_group); extract_token(message_range, cmd, 2, ' ', sizeof message_range); extract_token(range_lo, message_range, 0, '-', sizeof range_lo); extract_token(range_hi, message_range, 1, '-', sizeof range_hi); lr.lo = atoi(range_lo); lr.hi = atoi(range_hi); /* In LISTGROUP mode we can specify an empty name for 'currently selected' */ if ((!strcasecmp(verb, "LISTGROUP")) && (IsEmptyStr(requested_group))) { room_to_newsgroup(requested_group, CC->room.QRname, sizeof requested_group); } /* First try a regular match */ newsgroup_to_room(requested_room, requested_group, sizeof requested_room); c = CtdlGetRoom(&QRscratch, requested_room); /* Then try a mailbox name match */ if (c != 0) { CtdlMailboxName(augmented_roomname, sizeof augmented_roomname, &CC->user, requested_room); c = CtdlGetRoom(&QRscratch, augmented_roomname); if (c == 0) { safestrncpy(requested_room, augmented_roomname, sizeof(requested_room)); } } /* If the room exists, check security/access */ if (c == 0) { /* See if there is an existing user/room relationship */ CtdlRoomAccess(&QRscratch, &CC->user, &ra, NULL); /* normal clients have to pass through security */ if (ra & UA_KNOWN) { ok = 1; } } /* Fail here if no such room */ if (!ok) { cprintf("411 no such newsgroup\r\n"); return; } /* * CtdlUserGoto() formally takes us to the desired room, happily returning * the number of messages and number of new messages. */ memcpy(&CC->room, &QRscratch, sizeof(struct ctdlroom)); CtdlUserGoto(NULL, 0, 0, &msgs, &new, &oldest, &newest); cprintf("211 %d %ld %ld %s\r\n", msgs, oldest, newest, requested_group); // If this is a GROUP command, set the "current article number" to zero, and then stop here. if (!strcasecmp(verb, "GROUP")) { nntpstate->current_article_number = oldest; return; } // If we get to this point we are running a LISTGROUP command. Fetch those message numbers. CtdlForEachMessage(MSGS_ALL, 0L, NULL, NULL, NULL, nntp_listgroup_backend, &lr); cprintf(".\r\n"); }
void inetcfg_init(void) { if (CtdlGetRoom(&CC->room, SYSCONFIGROOM) != 0) return; CtdlForEachMessage(MSGS_LAST, 1, NULL, INTERNETCFG, NULL, inetcfg_init_backend, NULL); }
/* * Attempt to autocomplete an address based on a partial... */ void cmd_auto(char *argbuf) { char hold_rm[ROOMNAMELEN]; char search_string[256]; long *msglist = NULL; int num_msgs = 0; long *fts_msgs = NULL; int fts_num_msgs = 0; struct cdbdata *cdbfr; int r = 0; int i = 0; int j = 0; int search_match = 0; char *rooms_to_try[] = { USERCONTACTSROOM, ADDRESS_BOOK_ROOM }; if (CtdlAccessCheck(ac_logged_in)) return; extract_token(search_string, argbuf, 0, '|', sizeof search_string); if (IsEmptyStr(search_string)) { cprintf("%d You supplied an empty partial.\n", ERROR + ILLEGAL_VALUE); return; } strcpy(hold_rm, CC->room.QRname); /* save current room */ cprintf("%d try these:\n", LISTING_FOLLOWS); /* * Gather up message pointers in rooms containing vCards */ for (r=0; r < (sizeof(rooms_to_try) / sizeof(char *)); ++r) { if (CtdlGetRoom(&CC->room, rooms_to_try[r]) == 0) { cdbfr = cdb_fetch(CDB_MSGLISTS, &CC->room.QRnumber, sizeof(long)); if (cdbfr != NULL) { msglist = realloc(msglist, (num_msgs * sizeof(long)) + cdbfr->len + 1); memcpy(&msglist[num_msgs], cdbfr->ptr, cdbfr->len); num_msgs += (cdbfr->len / sizeof(long)); cdb_free(cdbfr); } } } /* * Search-reduce the results if we have the full text index available */ if (config.c_enable_fulltext) { CtdlModuleDoSearch(&fts_num_msgs, &fts_msgs, search_string, "fulltext"); if (fts_msgs) { for (i=0; i<num_msgs; ++i) { search_match = 0; for (j=0; j<fts_num_msgs; ++j) { if (msglist[i] == fts_msgs[j]) { search_match = 1; j = fts_num_msgs + 1; /* end the search */ } } if (!search_match) { msglist[i] = 0; /* invalidate this result */ } } free(fts_msgs); } else { /* If no results, invalidate the whole list */ free(msglist); msglist = NULL; num_msgs = 0; } } /* * Now output the ones that look interesting */ if (num_msgs > 0) for (i=0; i<num_msgs; ++i) { if (msglist[i] != 0) { hunt_for_autocomplete(msglist[i], search_string); } } cprintf("000\n"); if (strcmp(CC->room.QRname, hold_rm)) { CtdlGetRoom(&CC->room, hold_rm); /* return to saved room */ } if (msglist) { free(msglist); } }
/* * 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_ignet = 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_ignet[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; MSG_syslog(LOG_DEBUG, "Evaluating recipient #%d: %s\n", 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 or an attached * Citadel directory, 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_IGNET: ++ret->num_ignet; if (!IsEmptyStr(ret->recp_ignet)) { strcat(ret->recp_ignet, "|"); } strcat(ret->recp_ignet, 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_ignet + ret->num_room + ret->num_error) == 0) { ret->num_error = (-1); strcpy(ret->errormsg, "No recipients specified."); } MSGM_syslog(LOG_DEBUG, "validate_recipients()\n"); MSG_syslog(LOG_DEBUG, " local: %d <%s>\n", ret->num_local, ret->recp_local); MSG_syslog(LOG_DEBUG, " room: %d <%s>\n", ret->num_room, ret->recp_room); MSG_syslog(LOG_DEBUG, " inet: %d <%s>\n", ret->num_internet, ret->recp_internet); MSG_syslog(LOG_DEBUG, " ignet: %d <%s>\n", ret->num_ignet, ret->recp_ignet); MSG_syslog(LOG_DEBUG, " error: %d <%s>\n", ret->num_error, ret->errormsg); free(recipients); return(ret); }