+/*
+ * Determine whether a given Internet address belongs to the current user
+ */
+int CtdlIsMe(char *addr, int addr_buf_len)
+{
+ 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; i<recp->num_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);
+}
+
+
+/* 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;
+}
+
+
+
+
+
+/*
+ * 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)
+{
+ unsigned 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 */
+ 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; 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 Global Address Book */
+ 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);
+ }
+
+ /* Otherwise we look in the IGnet maps for a valid Citadel node.
+ * Try directly-connected nodes first...
+ */
+ ignetcfg = CtdlGetSysConfig(IGNETCFG);
+ for (i=0; i<num_tokens(ignetcfg, '\n'); ++i) {
+ extract_token(buf, ignetcfg, i, '\n', sizeof buf);
+ extract_token(testnode, buf, 0, '|', sizeof testnode);
+ if (!strcasecmp(node, testnode)) {
+ free(ignetcfg);
+ return(MES_IGNET);
+ }
+ }
+ free(ignetcfg);
+
+ /*
+ * Then try nodes that are two or more hops away.
+ */
+ ignetmap = CtdlGetSysConfig(IGNETMAP);
+ for (i=0; i<num_tokens(ignetmap, '\n'); ++i) {
+ extract_token(buf, ignetmap, i, '\n', sizeof buf);
+ extract_token(testnode, buf, 0, '|', sizeof testnode);
+ if (!strcasecmp(node, testnode)) {
+ free(ignetmap);
+ return(MES_IGNET);
+ }
+ }
+ free(ignetmap);