24#include <libcitadel.h>
46 end = strchr(bptr + 2,
'?');
47 if (end == NULL)
return NULL;
48 if (((*(end + 1) ==
'B') || (*(end + 1) ==
'Q')) &&
49 (*(end + 2) ==
'?')) {
51 end = strstr(end + 3,
"?=");
55 end = strstr(bptr,
"?=");
59#define FindNextEnd(bptr, end) { \
60 end = strchr(bptr + 2, '?'); \
62 if (((*(end + 1) == 'B') || (*(end + 1) == 'Q')) && (*(end + 2) == '?')) { \
63 end = strstr(end + 3, "?="); \
64 } else end = strstr(bptr, "?="); \
71 char *start, *end, *next, *nextend, *ptr;
76 iconv_t ic = (iconv_t)(-1) ;
85 int illegal_non_rfc2047_encoding = 0;
93 for (i=0; i<len; ++i) {
94 if ((buf[i] < 32) || (buf[i] > 126)) {
95 illegal_non_rfc2047_encoding = 1;
99 if (illegal_non_rfc2047_encoding) {
100 const char *default_header_charset =
"iso-8859-1";
101 if ( (strcasecmp(default_header_charset,
"UTF-8")) && (strcasecmp(default_header_charset,
"us-ascii")) ) {
102 ctdl_iconv_open(
"UTF-8", default_header_charset, &ic);
103 if (ic != (iconv_t)(-1) ) {
106 safestrncpy(ibuf, buf, 1024);
107 ibuflen = strlen(ibuf);
109 obuf = (
char *)
malloc(obuflen);
111 iconv(ic, &ibuf, &ibuflen, &obuf, &obuflen);
112 osav[1024-obuflen] = 0;
122 nextend = end = NULL;
124 start = strstr(buf,
"=?");
128 while ((start != NULL) && (end != NULL)) {
129 next = strstr(end,
"=?");
136 if ((next != NULL) && ((next - end) > 2)) {
138 while ((ptr < next) &&
146 memmove(end + 2, next, len - (next - start));
149 delta = (next - end) - 2;
164 start = strstr(buf,
"=?");
166 while (start != NULL && end != NULL && end > start) {
167 extract_token(charset, start, 1,
'?',
sizeof charset);
168 extract_token(encoding, start, 2,
'?',
sizeof encoding);
169 extract_token(istr, start, 3,
'?',
sizeof istr);
173 if (!strcasecmp(encoding,
"B")) {
174 ibuflen = CtdlDecodeBase64(ibuf, istr, strlen(istr));
176 else if (!strcasecmp(encoding,
"Q")) {
183 if (istr[pos] ==
'_') istr[pos] =
' ';
186 ibuflen = CtdlDecodeQuotedPrintable(ibuf, istr, len);
190 ibuflen = strlen(istr);
193 ctdl_iconv_open(
"UTF-8", charset, &ic);
194 if (ic != (iconv_t)(-1) ) {
196 obuf = (
char *)
malloc(obuflen);
198 iconv(ic, &ibuf, &ibuflen, &obuf, &obuflen);
199 osav[1024-obuflen] = 0;
204 remove_token(end, 0,
'?');
205 remove_token(end, 0,
'?');
206 remove_token(end, 0,
'?');
207 remove_token(end, 0,
'?');
208 strcpy(end, &end[1]);
210 snprintf(newbuf,
sizeof newbuf,
"%s%s%s", buf, osav, end);
219 remove_token(end, 0,
'?');
220 remove_token(end, 0,
'?');
221 remove_token(end, 0,
'?');
222 remove_token(end, 0,
'?');
223 strcpy(end, &end[1]);
225 snprintf(newbuf,
sizeof newbuf,
"%s(unreadable)%s", buf, end);
236 if (passes > 20)
return;
238 start = strstr(buf,
"=?");
256 char host[256], type[256];
266 config_lines = num_tokens(
inetcfg,
'\n');
267 for (i=0; i<config_lines; ++i) {
268 extract_token(buf,
inetcfg, i,
'\n',
sizeof buf);
269 extract_token(host, buf, 0,
'|',
sizeof host);
270 extract_token(type, buf, 1,
'|',
sizeof type);
277 if ( (!strcasecmp(type,
"masqdomain")) && (!strcasecmp(fqdn, host))) {
281 if ( (!strcasecmp(type,
"localhost")) && (!strcasecmp(fqdn, host))) {
286 if ( (!strcasecmp(type,
"directory")) && (!strcasecmp(fqdn, host))) {
290 if (found)
return(found);
302 if (recp == NULL)
return(0);
310 extract_token(addr, recp->
recp_local, i,
'|', addr_buf_len);
311 if (!strcasecmp(addr,
CC->user.fullname)) {
326 if (num_tokens(str,
',') < 2)
return;
328 int len = strlen(str);
329 if (len < 900)
return;
330 if (len > 998) str[998] = 0;
332 char *cptr = strrchr(str,
',');
335 char *lptr = strchr(cptr,
'<');
336 char *rptr = strchr(cptr,
'>');
338 if ( (lptr) && (rptr) && (rptr > lptr) )
return;
350 for (ptr=name; *ptr; ++ptr) {
351 while ( (isspace(*ptr)) && (*(ptr+1)==
'@') ) {
353 if (ptr > name) --ptr;
355 while ( (*ptr==
'@') && (*(ptr+1)!=0) && (isspace(*(ptr+1))) ) {
356 strcpy(ptr+1, ptr+2);
379 int num_aliases = num_tokens(aliases,
'\n');
380 for (a=0; a<num_aliases; ++a) {
381 extract_token(aaa, aliases, a,
'\n',
sizeof aaa);
382 char *bar = strchr(aaa,
'|');
388 if ( (!IsEmptyStr(aaa)) && (!strcasecmp(name, aaa)) ) {
389 syslog(LOG_DEBUG,
"internet_addressing: global alias <%s> to <%s>", name, bar);
394 if (strchr(name,
',')) {
399 char original_name[256];
400 safestrncpy(original_name, name,
sizeof original_name);
405 stripallbut(name,
'<',
'>');
412 if (strcasecmp(original_name, name)) {
413 syslog(LOG_INFO,
"internet_addressing: directory alias <%s> to <%s>", original_name, name);
417 for (a=0; name[a] !=
'\0'; ++a) {
418 if (name[a] ==
'@') {
421 syslog(LOG_DEBUG,
"internet_addressing: host is local, recipient is <%s>", name);
428 at = haschar(name,
'@');
445 if (IsEmptyStr(addresses)) {
450 char *a = strdup(addresses);
452 syslog(LOG_ERR,
"internet_addressing: malloc() failed: %m");
461 r = strrchr(a,
'\"');
469 for (t=a; t[0]; ++t) {
470 if ((t[0]==
';') || (t[0]==
'|')) {
476 Array *recipients_array = NULL;
478 recipients_array = append_to;
481 recipients_array = array_new(256);
484 int num_addresses = num_tokens(a,
',');
486 for (i=0; i<num_addresses; ++i) {
487 char this_address[256];
488 extract_token(this_address, a, i,
',',
sizeof this_address);
489 striplt(this_address);
490 stripout(this_address,
'(',
')');
491 stripallbut(this_address,
'<',
'>');
492 if (!IsEmptyStr(this_address)) {
493 array_append(recipients_array, this_address);
498 return(recipients_array);
511 char *recipients = NULL;
524 if (ret == NULL)
return(NULL);
525 memset(ret, 0,
sizeof(
struct recptypes));
527 if (supplied_recipients == NULL) {
528 recipients = strdup(
"");
531 recipients = strdup(supplied_recipients);
534 len = strlen(recipients) + 1024;
550 Array *recp_array =
split_recps(supplied_recipients, NULL);
555 for (r=0; (recp_array && r<array_len(recp_array)); ++r) {
556 org_recp = (
char *)array_get_element_at(recp_array, r);
557 strncpy(this_recp, org_recp,
sizeof this_recp);
560 for (i=0; i<3; ++i) {
572 for (j=0; j<r; ++j) {
573 if (!strcasecmp(this_recp, (
char *)array_get_element_at(recp_array, j) )) {
578 syslog(LOG_DEBUG,
"Recipient #%d of type %d is <%s>", r, mailtype, this_recp);
585 if (!strcasecmp(this_recp,
"sysop")) {
595 else if (!strncasecmp(this_recp,
"room_", 5)) {
596 original_room =
CC->room;
600 strncpy(mail_to_room, &this_recp[5],
sizeof mail_to_room);
601 for (m = mail_to_room; *m; ++m) {
602 if (m[0] ==
'_') m[0]=
' ';
636 CC->room = original_room;
682 if (IsEmptyStr(errmsg)) {
683 snprintf(append,
sizeof append,
"Invalid recipient: %s", this_recp);
686 snprintf(append,
sizeof append,
"%s", errmsg);
688 if ( (strlen(ret->
errormsg) + strlen(append) + 3) <
SIZ) {
697 strcpy(append, this_recp);
700 snprintf(append,
sizeof append,
", %s", this_recp);
708 if (aliases != NULL) {
714 strcpy(ret->
errormsg,
"No recipients specified.");
717 syslog(LOG_DEBUG,
"internet_addressing: validate_recipients() = %d local, %d room, %d SMTP, %d error",
723 array_free(recp_array);
738 syslog(LOG_ERR,
"internet_addressing: attempt to call free_recipients() on some other data type!");
756 char *user, *node, *name;
757 const char headerStr[] =
"=?UTF-8?Q?";
761 int need_to_encode = 0;
767 long nAddrPtrMax = 50;
772 if (source == NULL)
return source;
773 if (IsEmptyStr(source))
return source;
774 syslog(LOG_DEBUG,
"internet_addressing: qp_encode_email_addrs <%s>", source);
776 AddrPtr =
malloc (
sizeof (
long) * nAddrPtrMax);
777 AddrUtf8 =
malloc (
sizeof (
long) * nAddrPtrMax);
778 memset(AddrUtf8, 0,
sizeof (
long) * nAddrPtrMax);
781 while (!IsEmptyStr (&source[i])) {
782 if (nColons >= nAddrPtrMax){
785 ptr = (
long *)
malloc(
sizeof (
long) * nAddrPtrMax * 2);
786 memcpy (ptr, AddrPtr,
sizeof (
long) * nAddrPtrMax);
787 free (AddrPtr), AddrPtr = ptr;
789 ptr = (
long *)
malloc(
sizeof (
long) * nAddrPtrMax * 2);
790 memset(&ptr[nAddrPtrMax], 0,
sizeof (
long) * nAddrPtrMax);
792 memcpy (ptr, AddrUtf8,
sizeof (
long) * nAddrPtrMax);
793 free (AddrUtf8), AddrUtf8 = ptr;
796 if (((
unsigned char) source[i] < 32) || ((
unsigned char) source[i] > 126)) {
798 AddrUtf8[nColons] = 1;
800 if (source[i] ==
'"') {
801 InQuotes = !InQuotes;
803 if (!InQuotes && source[i] ==
',') {
804 AddrPtr[nColons] = i;
809 if (need_to_encode == 0) {
816 EncodedMaxLen = nColons * (
sizeof(headerStr) + 3) + SourceLen * 3;
817 Encoded = (
char*)
malloc (EncodedMaxLen);
819 for (i = 0; i < nColons; i++) {
820 source[AddrPtr[i]++] =
'\0';
823 user =
malloc(SourceLen + 1);
824 node =
malloc(SourceLen + 1);
825 name =
malloc(SourceLen + 1);
829 for (i = 0; i < nColons && nPtr != NULL; i++) {
830 nmax = EncodedMaxLen - (nPtr - Encoded);
834 if (IsEmptyStr(name)) {
835 n = snprintf(nPtr, nmax, (i==0)?
"%s@%s" :
",%s@%s", user, node);
838 EncodedName = rfc2047encode(name, strlen(name));
839 n = snprintf(nPtr, nmax, (i==0)?
"%s <%s@%s>" :
",%s <%s@%s>", EncodedName, user, node);
844 n = snprintf(nPtr, nmax, (i==0)?
"%s" :
",%s", &source[AddrPtr[i]]);
850 ptr = (
char*)
malloc(EncodedMaxLen * 2);
851 memcpy(ptr, Encoded, EncodedMaxLen);
852 nnPtr = ptr + (nPtr - Encoded), nPtr = nnPtr;
853 free(Encoded), Encoded = ptr;
858 for (i = 0; i < nColons; i++)
859 source[--AddrPtr[i]] =
',';
874 char *pField = *field;
876 char *pFieldEnd = *FieldEnd;
878 while (isspace(*pField))
883 while (isspace(*pFieldEnd))
886 *FieldEnd = pFieldEnd;
888 for (sField = *field = pField;
892 if ((*sField==
'\r') || (*sField==
'\n'))
895 while ( ( (*(sField + offset) ==
'\r') || (*(sField + offset) ==
'\n' )) && (sField + offset < pFieldEnd) ) {
902 if (*sField==
'\"') quote = 1 - quote;
904 if (isspace(*sField)) {
909 while ((sField < pFieldEnd) &&
914 else *pField = *sField;
916 else *pField = *sField;
920 *FieldEnd = pField - 1;
935 if (rfc822 == NULL)
return;
938 strcpy(name, rfc822);
939 stripout(name,
'<',
'>');
942 while ((!IsEmptyStr(name)) && (haschar(name,
'!') > 0))
943 strcpy(name, &name[1]);
946 for (a = 0; name[a] !=
'\0'; ++a) {
947 if (name[a] ==
'@') {
951 if (name[a] ==
'%') {
958 if ((haschar(rfc822,
'(') == 1) && (haschar(rfc822,
')') == 1)) {
959 strcpy(name, rfc822);
960 stripallbut(name,
'(',
')');
964 if (haschar(rfc822, 34) == 2) {
965 strcpy(name, rfc822);
966 while ((!IsEmptyStr(name)) && (name[0] != 34)) {
967 strcpy(&name[0], &name[1]);
969 strcpy(&name[0], &name[1]);
970 for (a = 0; name[a] !=
'\0'; ++a)
977 strcpy(user, rfc822);
980 stripout(user,
'(',
')');
983 if ((haschar(user,
'<') == 1) && (haschar(user,
'>') == 1)) {
984 stripallbut(user,
'<',
'>');
988 while ((!IsEmptyStr(user)) && (haschar(user,
'!') > 0))
989 strcpy(user, &user[1]);
992 for (a = 0; user[a] !=
'\0'; ++a) {
993 if (user[a] ==
'@') {
997 if (user[a] ==
'%') {
1005 strcpy(node, rfc822);
1008 stripout(node,
'(',
')');
1011 if ((haschar(node,
'<') == 1) && (haschar(node,
'>') == 1)) {
1012 stripallbut(node,
'<',
'>');
1017 (haschar(node,
'@')==0)
1018 && (haschar(node,
'%')==0)
1019 && (haschar(node,
'!')==0)
1026 while ((!IsEmptyStr(node)) && (haschar(node,
'@') > 0))
1027 strcpy(node, &node[1]);
1030 while ((!IsEmptyStr(node)) && (haschar(node,
'%') > 0))
1031 strcpy(node, &node[1]);
1034 while ((!IsEmptyStr(node)) && (haschar(node,
'!') > 1))
1035 strcpy(node, &node[1]);
1038 for (a = 0; node[a] !=
'\0'; ++a)
1039 if (node[a] ==
'!') {
1053 if ((IsEmptyStr(name)) && (!IsEmptyStr(user))) {
1067 char *key, *value, *valueend;
1071 const char *colonpos = NULL;
1080 for (pos = end; pos >= beg; pos--) {
1081 if (*pos ==
':') colonpos = pos;
1084 if (colonpos == NULL)
return(0);
1088 memcpy(key, beg, len + 1);
1090 valueend = key + len;
1091 * ( key + (colonpos - beg) ) =
'\0';
1092 value = &key[(colonpos - beg) + 1];
1095 valuelen = valueend - value + 1;
1102 if (!strcasecmp(key,
"Date")) {
1104 if (parsed_date < 0L) parsed_date = time(NULL);
1111 else if (!strcasecmp(key,
"From")) {
1113 syslog(LOG_DEBUG,
"internet_addressing: converted to <%s@%s> (%s)", user, node, name);
1114 snprintf(addr,
sizeof(addr),
"%s@%s", user, node);
1124 else if (!strcasecmp(key,
"Subject")) {
1130 else if (!strcasecmp(key,
"List-ID")) {
1136 else if (!strcasecmp(key,
"To")) {
1142 else if (!strcasecmp(key,
"CC")) {
1148 else if (!strcasecmp(key,
"Message-ID")) {
1150 syslog(LOG_WARNING,
"internet_addressing: duplicate message id");
1157 pValueLen = valuelen;
1159 while (haschar(pValue,
'<') > 0) {
1164 for (i = 0; i <= pValueLen; ++i)
1165 if (pValue[i] ==
'>') {
1176 else if (!strcasecmp(key,
"Return-Path")) {
1182 else if (!strcasecmp(key,
"Envelope-To")) {
1188 else if (!strcasecmp(key,
"References")) {
1193 else if (!strcasecmp(key,
"Reply-To")) {
1198 else if (!strcasecmp(key,
"In-reply-to")) {
1214 int bracket_nesting = 0;
1216 char *moveptr = NULL;
1223 if (bracket_nesting < 0) bracket_nesting = 0;
1225 if ((ch ==
'>') && (bracket_nesting == 0) && (*(ptr+1)) && (ptr>str) ) {
1229 else if (bracket_nesting > 0) {
1235 *moveptr = *(moveptr+1);
1239 if (ch ==
'<') ++bracket_nesting;
1251 StrBuf *RFCBuf = NewStrBufPlain(rfc822, -1);
1260 const char *pos, *beg, *end, *totalend;
1261 int done, alldone = 0;
1263 StrBuf *OtherHeaders;
1266 if (msg == NULL)
return msg;
1273 pos = ChrPtr(*rfc822);
1274 totalend = pos + StrLength(*rfc822);
1276 OtherHeaders = NewStrBufPlain(NULL, StrLength(*rfc822));
1285 while ((end < totalend) &&
1290 if ( (*pos==
'\n') && ((*(pos+1))!=0x20) && ((*(pos+1))!=0x09) )
1297 ( (*(pos+1)==
'\n') ||
1303 if (pos >= (totalend - 1) )
1318 StrBufAppendBufPlain(OtherHeaders, beg, end - beg, 0);
1319 StrBufAppendBufPlain(OtherHeaders, HKEY(
"\n"), 0);
1323 if (pos >= totalend)
1326 StrBufAppendBufPlain(OtherHeaders, HKEY(
"\n"), 0);
1328 StrBufAppendBufPlain(OtherHeaders, pos, totalend - pos, 0);
1359 char *fieldbuf = NULL;
1360 const char *end_of_headers;
1361 const char *field_start;
1367 if (rfc822 == NULL)
return(NULL);
1368 if (fieldname == NULL)
return(NULL);
1370 snprintf(fieldhdr,
sizeof fieldhdr,
"%s:", fieldname);
1373 end_of_headers = cbmstrcasestr(rfc822,
"\n\r\n");
1374 if (end_of_headers == NULL) {
1375 end_of_headers = cbmstrcasestr(rfc822,
"\n\n");
1377 if (end_of_headers == NULL)
return (NULL);
1379 field_start = cbmstrcasestr(rfc822, fieldhdr);
1380 if (field_start == NULL)
return(NULL);
1381 if (field_start > end_of_headers)
return(NULL);
1384 strcpy(fieldbuf,
"");
1387 ptr = cmemreadline(ptr, fieldbuf,
SIZ-strlen(fieldbuf) );
1388 while ( (isspace(ptr[0])) && (ptr < end_of_headers) ) {
1389 strcat(fieldbuf,
" ");
1390 cont = &fieldbuf[strlen(fieldbuf)];
1391 ptr = cmemreadline(ptr, cont,
SIZ-strlen(fieldbuf) );
1395 strcpy(fieldbuf, &fieldbuf[strlen(fieldhdr)]);
1414 for (i=0; !IsEmptyStr(&addr[i]); ++i) {
1415 if (!isspace(addr[i])) {
1416 key[keylen++] = tolower(addr[i]);
1421 syslog(LOG_DEBUG,
"internet_addressing: directory key is <%s>", key);
1432 extract_token(domain, addr, 1,
'@',
sizeof domain);
1458 syslog(LOG_DEBUG,
"internet_addressing: create directory entry: %s --> %s", internet_addr, citadel_addr);
1474 syslog(LOG_DEBUG,
"internet_addressing: delete directory entry: %s --> %s", internet_addr, citadel_addr);
1490 if (target != NULL) {
1491 safestrncpy(target, internet_addr, targbuflen);
1495 if (num_tokens(internet_addr,
'@') != 2)
return(-1);
1498 if (
IsDirectory(internet_addr, 0) == 0)
return(-1);
1502 if (cdbrec != NULL) {
1503 if (target != NULL) {
1504 safestrncpy(target, cdbrec->
ptr, targbuflen);
1521 char user[256], node[256], name[256];
1526 if (msg == NULL)
return(NULL);
1542 if (is_harvestable) {
1543 coll = strdup(addr);
1549 if (coll == NULL)
return(NULL);
1552 for (i = 0; i < 2; ++i) {
1557 for (j=0; j<num_tokens(msg->
cm_fields[field],
','); ++j) {
1558 extract_token(addr, msg->
cm_fields[field], j,
',',
sizeof addr);
1559 if (strstr(addr,
"=?") != NULL)
1564 coll = realloc(coll, strlen(coll) + strlen(addr) + 4);
1565 if (coll == NULL)
return(NULL);
1566 if (!IsEmptyStr(coll)) {
1576 if (IsEmptyStr(coll)) {
1598 char one_email[512];
1610 syslog(LOG_INFO,
"internet_addressing: rebuilding email address directory index");
1626 syslog(LOG_DEBUG,
"internet_addressing: setting email addresses for <%s> to <%s>",
usbuf.
fullname, new_emailaddrs);
1650 char synthetic_email_addr[1024];
1654 for (i=0; u==0; ++i) {
1658 for (j=0; ((synthetic_email_addr[j] !=
'\0')&&(synthetic_email_addr[j] !=
'@')); j++) {
1659 synthetic_email_addr[j] = tolower(synthetic_email_addr[j]);
1660 if (!isalnum(synthetic_email_addr[j])) {
1661 synthetic_email_addr[j] =
'_';
1667 snprintf(synthetic_email_addr,
sizeof synthetic_email_addr,
"ctdl%08lx@%s", user->
usernum,
CtdlGetConfigStr(
"c_fqdn"));
1671 snprintf(synthetic_email_addr,
sizeof synthetic_email_addr,
"ctdl%08x@%s", i,
CtdlGetConfigStr(
"c_fqdn"));
1674 syslog(LOG_DEBUG,
"user_ops: address <%s> lookup returned <%d>", synthetic_email_addr, u);
1678 strncpy(
CC->user.emailaddrs, synthetic_email_addr,
sizeof(user->
emailaddrs));
1679 syslog(LOG_DEBUG,
"user_ops: auto-generated email address <%s> for <%s>", synthetic_email_addr, user->
fullname);
1687 char *roomnetconfig;
1701 if (roomnetconfig == NULL) {
1707 if (bmstrcasestr(roomnetconfig, email)) {
1714 free(roomnetconfig);
char * CtdlGetConfigStr(char *key)
char * CtdlGetSysConfig(char *sysconfname)
int CtdlGetRoom(struct ctdlroom *qrbuf, const char *room_name)
char * LoadRoomNetConfigFile(long roomnum)
int CtdlGetUserLock(struct ctdluser *usbuf, char *name)
void CtdlPutUserLock(struct ctdluser *usbuf)
int CtdlGetUser(struct ctdluser *usbuf, char *name)
void cdb_free(struct cdbdata *cdb)
int cdb_store(int cdb, const void *ckey, int ckeylen, void *cdata, int cdatalen)
struct cdbdata * cdb_fetch(int cdb, const void *key, int keylen)
int cdb_delete(int cdb, void *key, int keylen)
struct CtdlMessage * convert_internet_message_buf(StrBuf **rfc822)
int CtdlDirectoryDelUser(char *internet_addr, char *citadel_addr)
int CtdlIsMe(char *addr, int addr_buf_len)
struct recptypes * validate_recipients(char *supplied_recipients, const char *RemoteIdentifier, int Flags)
void free_recipients(struct recptypes *valid)
int IsDirectory(char *addr, int allow_masq_domains)
void sanitize_truncated_recipient(char *str)
void CtdlRebuildDirectoryIndex(void)
void directory_key(char *key, char *addr)
struct CtdlMessage * convert_internet_message(char *rfc822)
int expand_aliases(char *name, char *aliases)
Array * split_recps(char *addresses, Array *append_to)
int CtdlHostAlias(char *fqdn)
void CtdlSetEmailAddressesForUser(char *requested_user, char *new_emailaddrs)
void CtdlRebuildDirectoryIndex_backend(char *username, void *data)
void process_rfc822_addr(const char *rfc822, char *user, char *node, char *name)
#define FindNextEnd(bptr, end)
char * harvest_collected_addresses(struct CtdlMessage *msg)
int CtdlDirectoryLookup(char *target, char *internet_addr, size_t targbuflen)
char * rfc822_fetch_field(const char *rfc822, const char *fieldname)
void unfold_rfc822_field(char **field, char **FieldEnd)
int convert_field(struct CtdlMessage *msg, const char *beg, const char *end)
void utf8ify_rfc822_string(char *buf)
char * qp_encode_email_addrs(char *source)
void convert_references_to_wefewences(char *str)
int is_email_subscribed_to_list(char *email, char *room_name)
void AutoGenerateEmailAddressForUser(struct ctdluser *user)
int CtdlDirectoryAddUser(char *internet_addr, char *citadel_addr)
void remove_any_whitespace_to_the_left_or_right_of_at_symbol(char *name)
int CM_IsEmpty(struct CtdlMessage *Msg, eMsgField which)
void CM_SetField(struct CtdlMessage *Msg, eMsgField which, const char *buf, long length)
void CM_SetFieldLONG(struct CtdlMessage *Msg, eMsgField which, long lvalue)
void CM_SetAsFieldSB(struct CtdlMessage *Msg, eMsgField which, StrBuf **buf)
time_t parsedate(const char *p)
int CtdlDoIHavePermissionToPostInThisRoom(char *errmsgbuf, size_t n, PostType PostPublic, int is_reply)
#define CTDLMESSAGE_MAGIC
void ForEachUser(void(*CallBack)(char *, void *out_data), void *in_data)