X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=citadel%2Fmsgbase.c;h=39c79d3d73326477ccca86b568fd8888203c51b8;hb=2735841869b264ba98805f1679731cf86942c90b;hp=052f06fcaf78ef88d830e5530cc742f020aaacda;hpb=192117806435453b6008edde07261fd41305e059;p=citadel.git diff --git a/citadel/msgbase.c b/citadel/msgbase.c index 052f06fca..39c79d3d7 100644 --- a/citadel/msgbase.c +++ b/citadel/msgbase.c @@ -65,7 +65,6 @@ #include "ctdl_module.h" -long config_msgnum; struct addresses_to_be_filed *atbf = NULL; /* This temp file holds the queue of operations for AdjRefCount() */ @@ -352,145 +351,6 @@ struct CtdlMessage * CM_Duplicate(struct CtdlMessage *OrgMsg) -/* - * This function is self explanatory. - * (What can I say, I'm in a weird mood today...) - */ -void remove_any_whitespace_to_the_left_or_right_of_at_symbol(char *name) -{ - int i; - - for (i = 0; i < strlen(name); ++i) { - if (name[i] == '@') { - while (isspace(name[i - 1]) && i > 0) { - strcpy(&name[i - 1], &name[i]); - --i; - } - while (isspace(name[i + 1])) { - strcpy(&name[i + 1], &name[i + 2]); - } - } - } -} - - -/* - * Aliasing for network mail. - * (Error messages have been commented out, because this is a server.) - */ -int alias(char *name) -{ /* process alias and routing info for mail */ - struct CitContext *CCC = CC; - FILE *fp; - int a, i; - char aaa[SIZ], bbb[SIZ]; - char *ignetcfg = NULL; - char *ignetmap = NULL; - int at = 0; - char node[64]; - char testnode[64]; - char buf[SIZ]; - - 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"); - 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; a < strlen(aaa); ++a) { - if (aaa[a] == ',') { - strcpy(bbb, &aaa[a + 1]); - aaa[a] = 0; - } - } - if (!strcasecmp(name, aaa)) - strcpy(name, bbb); - } - fclose(fp); - - /* Hit the Global Address Book */ - if (CtdlDirectoryLookup(aaa, name, sizeof aaa) == 0) { - strcpy(name, aaa); - } - - if (strcasecmp(original_name, name)) { - MSG_syslog(LOG_INFO, "%s is being forwarded to %s\n", original_name, name); - } - - /* Change "user @ xxx" to "user" if xxx is an alias for this host */ - for (a=0; a\n", name); - } - } - } - - /* 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); - } - - /* Otherwise we look in the IGnet maps for a valid Citadel node. - * Try directly-connected nodes first... - */ - ignetcfg = CtdlGetSysConfig(IGNETCFG); - for (i=0; i= nAddrPtrMax){ - long *ptr; - - ptr = (long *) malloc(sizeof (long) * nAddrPtrMax * 2); - memcpy (ptr, AddrPtr, sizeof (long) * nAddrPtrMax); - free (AddrPtr), AddrPtr = ptr; - - ptr = (long *) malloc(sizeof (long) * nAddrPtrMax * 2); - memset(&ptr[nAddrPtrMax], 0, - sizeof (long) * nAddrPtrMax); - - memcpy (ptr, AddrUtf8, sizeof (long) * nAddrPtrMax); - free (AddrUtf8), AddrUtf8 = ptr; - nAddrPtrMax *= 2; - } - if (((unsigned char) source[i] < 32) || - ((unsigned char) source[i] > 126)) { - need_to_encode = 1; - AddrUtf8[nColons] = 1; - } - if (source[i] == '"') - InQuotes = !InQuotes; - if (!InQuotes && source[i] == ',') { - AddrPtr[nColons] = i; - nColons++; - } - i++; - } - if (need_to_encode == 0) { - free(AddrPtr); - free(AddrUtf8); - return source; - } - - SourceLen = i; - EncodedMaxLen = nColons * (sizeof(headerStr) + 3) + SourceLen * 3; - Encoded = (char*) malloc (EncodedMaxLen); - - for (i = 0; i < nColons; i++) - source[AddrPtr[i]++] = '\0'; - /* TODO: if libidn, this might get larger*/ - user = malloc(SourceLen + 1); - node = malloc(SourceLen + 1); - name = malloc(SourceLen + 1); - - nPtr = Encoded; - *nPtr = '\0'; - for (i = 0; i < nColons && nPtr != NULL; i++) { - nmax = EncodedMaxLen - (nPtr - Encoded); - if (AddrUtf8[i]) { - process_rfc822_addr(&source[AddrPtr[i]], - user, - node, - name); - /* TODO: libIDN here ! */ - if (IsEmptyStr(name)) { - n = snprintf(nPtr, nmax, - (i==0)?"%s@%s" : ",%s@%s", - user, node); - } - else { - EncodedName = rfc2047encode(name, strlen(name)); - n = snprintf(nPtr, nmax, - (i==0)?"%s <%s@%s>" : ",%s <%s@%s>", - EncodedName, user, node); - free(EncodedName); - } - } - else { - n = snprintf(nPtr, nmax, - (i==0)?"%s" : ",%s", - &source[AddrPtr[i]]); - } - if (n > 0 ) - nPtr += n; - else { - char *ptr, *nnPtr; - ptr = (char*) malloc(EncodedMaxLen * 2); - memcpy(ptr, Encoded, EncodedMaxLen); - nnPtr = ptr + (nPtr - Encoded), nPtr = nnPtr; - free(Encoded), Encoded = ptr; - EncodedMaxLen *= 2; - i--; /* do it once more with properly lengthened buffer */ - } - } - for (i = 0; i < nColons; i++) - source[--AddrPtr[i]] = ','; - - free(user); - free(node); - free(name); - free(AddrUtf8); - free(AddrPtr); - return Encoded; -} - - -/* If the last item in a list of recipients was truncated to a partial address, - * remove it completely in order to avoid choking libSieve - */ -void sanitize_truncated_recipient(char *str) -{ - if (!str) return; - if (num_tokens(str, ',') < 2) return; - - int len = strlen(str); - if (len < 900) return; - if (len > 998) str[998] = 0; - - char *cptr = strrchr(str, ','); - if (!cptr) return; - - char *lptr = strchr(cptr, '<'); - char *rptr = strchr(cptr, '>'); - - if ( (lptr) && (rptr) && (rptr > lptr) ) return; - - *cptr = 0; -} - void OutputCtdlMsgHeaders( struct CtdlMessage *TheMessage, @@ -4170,298 +3880,6 @@ struct CtdlMessage *CtdlMakeMessage( -/* - * 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() - */ -struct recptypes *validate_recipients(const char *supplied_recipients, - const char *RemoteIdentifier, - int Flags) { - struct CitContext *CCC = CC; - struct 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 = (struct recptypes *) malloc(sizeof(struct recptypes)); - if (ret == NULL) return(NULL); - - /* Set all strings to null and numeric values to zero */ - memset(ret, 0, sizeof(struct 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, config.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); -} - - -/* - * Destructor for struct recptypes - */ -void free_recipients(struct recptypes *valid) { - - if (valid == NULL) { - return; - } - - if (valid->recptypes_magic != RECPTYPES_MAGIC) { - struct CitContext *CCC = CC; - MSGM_syslog(LOG_EMERG, "Attempt to call free_recipients() on some other data type!\n"); - abort(); - } - - if (valid->errormsg != NULL) free(valid->errormsg); - if (valid->recp_local != NULL) free(valid->recp_local); - if (valid->recp_internet != NULL) free(valid->recp_internet); - if (valid->recp_ignet != NULL) free(valid->recp_ignet); - if (valid->recp_room != NULL) free(valid->recp_room); - if (valid->recp_orgroom != NULL) free(valid->recp_orgroom); - if (valid->display_recp != NULL) free(valid->display_recp); - if (valid->bounce_to != NULL) free(valid->bounce_to); - if (valid->envelope_from != NULL) free(valid->envelope_from); - if (valid->sending_room != NULL) free(valid->sending_room); - free(valid); -} - - - /* * message entry - mode 0 (normal) */ @@ -5453,114 +4871,6 @@ void CtdlWriteObject(char *req_room, /* Room to stuff it in */ - - - -void CtdlGetSysConfigBackend(long msgnum, void *userdata) { - config_msgnum = msgnum; -} - - -char *CtdlGetSysConfig(char *sysconfname) { - char hold_rm[ROOMNAMELEN]; - long msgnum; - char *conf; - struct CtdlMessage *msg; - char buf[SIZ]; - - strcpy(hold_rm, CC->room.QRname); - if (CtdlGetRoom(&CC->room, SYSCONFIGROOM) != 0) { - CtdlGetRoom(&CC->room, hold_rm); - return NULL; - } - - - /* We want the last (and probably only) config in this room */ - begin_critical_section(S_CONFIG); - config_msgnum = (-1L); - CtdlForEachMessage(MSGS_LAST, 1, NULL, sysconfname, NULL, - CtdlGetSysConfigBackend, NULL); - msgnum = config_msgnum; - end_critical_section(S_CONFIG); - - if (msgnum < 0L) { - conf = NULL; - } - else { - msg = CtdlFetchMessage(msgnum, 1); - if (msg != NULL) { - conf = strdup(msg->cm_fields[eMesageText]); - CM_Free(msg); - } - else { - conf = NULL; - } - } - - CtdlGetRoom(&CC->room, hold_rm); - - if (conf != NULL) do { - extract_token(buf, conf, 0, '\n', sizeof buf); - strcpy(conf, &conf[strlen(buf)+1]); - } while ( (!IsEmptyStr(conf)) && (!IsEmptyStr(buf)) ); - - return(conf); -} - - -void CtdlPutSysConfig(char *sysconfname, char *sysconfdata) { - CtdlWriteObject(SYSCONFIGROOM, sysconfname, sysconfdata, (strlen(sysconfdata)+1), NULL, 0, 1, 0); -} - - -/* - * Determine whether a given Internet address belongs to the current user - */ -int CtdlIsMe(char *addr, int addr_buf_len) -{ - struct recptypes *recp; - int i; - - recp = validate_recipients(addr, NULL, 0); - if (recp == NULL) return(0); - - if (recp->num_local == 0) { - free_recipients(recp); - return(0); - } - - for (i=0; inum_local; ++i) { - extract_token(addr, recp->recp_local, i, '|', addr_buf_len); - if (!strcasecmp(addr, CC->user.fullname)) { - free_recipients(recp); - return(1); - } - } - - free_recipients(recp); - return(0); -} - - -/* - * Citadel protocol command to do the same - */ -void cmd_isme(char *argbuf) { - char addr[256]; - - if (CtdlAccessCheck(ac_logged_in)) return; - extract_token(addr, argbuf, 0, '|', sizeof addr); - - if (CtdlIsMe(addr, sizeof addr)) { - cprintf("%d %s\n", CIT_OK, addr); - } - else { - cprintf("%d Not you.\n", ERROR + ILLEGAL_VALUE); - } - -} - - /*****************************************************************************/ /* MODULE INITIALIZATION STUFF */ /*****************************************************************************/ @@ -5584,7 +4894,6 @@ CTDL_MODULE_INIT(msgbase) CtdlRegisterProtoHook(cmd_ent0, "ENT0", "Enter a message"); CtdlRegisterProtoHook(cmd_dele, "DELE", "Delete a message"); CtdlRegisterProtoHook(cmd_move, "MOVE", "Move or copy a message to another room"); - CtdlRegisterProtoHook(cmd_isme, "ISME", "Determine whether an email address belongs to a user"); } /* return our Subversion id for the Log */