{
int a;
+ strcpy(user, "");
+ strcpy(node, config.c_fqdn);
+ strcpy(name, "");
+
/* extract full name - first, it's From minus <userid> */
strcpy(name, rfc822);
for (a = 0; a < strlen(name); ++a) {
}
+
/*
* Convert an Internet email address to a Citadel user/host combination
*/
* FIX ... make this work for non-local systems
*/
if (strcasecmp(node, config.c_nodename)) {
- return(1);
+ return(rfc822_address_invalid);
}
/* Now try to resolve the name
strcpy(CC->buffer1, user);
strcpy(CC->buffer2, "");
ForEachUser(try_name);
- if (strlen(CC->buffer2) == 0) return(2);
+ if (strlen(CC->buffer2) == 0) return(rfc822_no_such_user);
strcpy(destuser, CC->buffer2);
- return(0);
+ return(rfc822_address_locally_validated);
+ }
+
+ return(rfc822_address_invalid); /* unknown error */
+}
+
+
+
+
+
+/*
+ * Convert an RFC822 message (headers + body) to a CtdlMessage structure.
+ */
+struct CtdlMessage *convert_internet_message(char *rfc822) {
+
+ struct CtdlMessage *msg;
+ char *buf;
+
+ msg = mallok(sizeof(struct CtdlMessage));
+ if (msg == NULL) return msg;
+
+ memset(msg, 0, sizeof(struct CtdlMessage));
+ msg->cm_magic = CTDLMESSAGE_MAGIC; /* self check */
+ msg->cm_anon_type = 0; /* never anonymous */
+ msg->cm_format_type = 4; /* always MIME */
+ msg->cm_fields['M'] = rfc822;
+
+ /* FIX there's plenty to do here. */
+
+
+ /* Follow-up sanity check. */
+
+ /* If there's no timestamp on this message, set it to now. */
+ if (msg->cm_fields['T'] == NULL) {
+ sprintf(buf, "%ld", time(NULL));
+ msg->cm_fields['T'] = strdoop(buf);
}
- return(3); /* unknown error */
+ return msg;
}
int fuzzy_match(struct usersupp *us, char *matchstring);
void process_rfc822_addr(char *rfc822, char *user, char *node, char *name);
int convert_internet_address(char *destuser, char *desthost, char *source);
+
+
+enum {
+ rfc822_address_locally_validated,
+ rfc822_no_such_user,
+ rfc822_address_on_citadel_network,
+ rfc822_address_invalid
+};
+
}
+
+/*
+ * Back end function used by make_message() and similar functions
+ */
+char *CtdlReadMessageBody(char *terminator, size_t maxlen) {
+ char buf[256];
+ size_t message_len = 0;
+ size_t buffer_len = 0;
+ char *ptr, *append;
+ char *m;
+
+ m = mallok(4096);
+ if (m == NULL) {
+ while ( (client_gets(buf)>0) && strcmp(buf, terminator) ) ;;
+ return(NULL);
+ } else {
+ buffer_len = 4096;
+ m[0] = 0;
+ message_len = 0;
+ }
+ /* read in the lines of message text one by one */
+ append = NULL;
+ while ( (client_gets(buf)>0) && strcmp(buf, terminator) ) {
+
+ /* augment the buffer if we have to */
+ if ((message_len + strlen(buf) + 2) > buffer_len) {
+ lprintf(9, "realloking\n");
+ ptr = reallok(m, (buffer_len * 2) );
+ if (ptr == NULL) { /* flush if can't allocate */
+ while ( (client_gets(buf)>0) &&
+ strcmp(buf, terminator)) ;;
+ return(m);
+ } else {
+ buffer_len = (buffer_len * 2);
+ m = ptr;
+ append = NULL;
+ lprintf(9, "buffer_len is %d\n", buffer_len);
+ }
+ }
+
+ if (append == NULL) append = m;
+ while (strlen(append) > 0) ++append;
+ strcpy(append, buf);
+ strcat(append, "\n");
+ message_len = message_len + strlen(buf) + 1;
+
+ /* if we've hit the max msg length, flush the rest */
+ if (message_len >= maxlen) {
+ while ( (client_gets(buf)>0) && strcmp(buf, terminator)) ;;
+ return(m);
+ }
+ }
+ return(m);
+}
+
+
+
+
/*
* Build a binary message to be saved on disk.
*/
int a;
char dest_node[32];
char buf[256];
- size_t message_len = 0;
- size_t buffer_len = 0;
- char *ptr, *append;
struct CtdlMessage *msg;
msg = mallok(sizeof(struct CtdlMessage));
if (dest_node[0] != 0)
msg->cm_fields['D'] = strdoop(dest_node);
- msg->cm_fields['M'] = mallok(4096);
- if (msg->cm_fields['M'] == NULL) {
- while (client_gets(buf), strcmp(buf, "000")) ;; /* flush */
- return(msg);
- } else {
- buffer_len = 4096;
- msg->cm_fields['M'][0] = 0;
- message_len = 0;
- }
- /* read in the lines of message text one by one */
- append = NULL;
- while (client_gets(buf), strcmp(buf, "000")) {
+ msg->cm_fields['M'] = CtdlReadMessageBody("000", config.c_maxmsglen);
- /* augment the buffer if we have to */
- if ((message_len + strlen(buf) + 2) > buffer_len) {
- lprintf(9, "realloking\n");
- ptr = reallok(msg->cm_fields['M'], (buffer_len * 2) );
- if (ptr == NULL) { /* flush if can't allocate */
- while (client_gets(buf), strcmp(buf, "000")) ;;
- return(msg);
- } else {
- buffer_len = (buffer_len * 2);
- msg->cm_fields['M'] = ptr;
- append = NULL;
- lprintf(9, "buffer_len is %d\n", buffer_len);
- }
- }
-
- if (append == NULL) append = msg->cm_fields['M'];
- while (strlen(append) > 0) ++append;
- strcpy(append, buf);
- strcat(append, "\n");
- message_len = message_len + strlen(buf) + 1;
-
- /* if we've hit the max msg length, flush the rest */
- if (message_len >= config.c_maxmsglen) {
- while (client_gets(buf), strcmp(buf, "000")) ;;
- return(msg);
- }
- }
return(msg);
}
int is_valid_message(struct CtdlMessage *);
int ReplicationChecks(struct CtdlMessage *);
int CtdlSaveMsgPointerInRoom(char *roomname, long msgid, int flags);
+char *CtdlReadMessageBody(char *terminator, size_t maxlen);
** <rsalz@osf.org> and Jim Berets <jberets@bbn.com> in August, 1990.
** Further revised (removed obsolete constructs and cleaned up timezone
** names) in August, 1991, by Rich. Paul Eggert <eggert@twinsun.com>
-** helped in September, 1992.
+** helped in September, 1992. Art Cancro <ajc@uncnsrd.mt-kisco.ny.us> cleaned
+** it up for ANSI C in December, 1999.
**
** This grammar has six shift/reduce conflicts.
**
#include <ctype.h>
#include <time.h>
-int date_lex();
+int date_lex(void);
#define yyparse date_parse
#define yylex date_lex
static time_t yyRelSeconds;
-extern struct tm *localtime();
-
-static void date_error();
-#line 100 "parsedate.y"
+static void date_error(char *);
+#line 99 "parsedate.y"
typedef union {
time_t Number;
enum _MERIDIAN Meridian;
} YYSTYPE;
-#line 114 "y.tab.c"
+#line 113 "y.tab.c"
#define tDAY 257
#define tDAYZONE 258
#define tMERIDIAN 259
short yyss[YYSTACKSIZE];
YYSTYPE yyvs[YYSTACKSIZE];
#define yystacksize YYSTACKSIZE
-#line 287 "parsedate.y"
+#line 286 "parsedate.y"
/* Month and day table. */
static TABLE MonthDayTable[] = {
static time_t
-ToSeconds(Hours, Minutes, Seconds, Meridian)
- time_t Hours;
- time_t Minutes;
- time_t Seconds;
- MERIDIAN Meridian;
+ToSeconds(time_t Hours, time_t Minutes, time_t Seconds, MERIDIAN Meridian)
{
if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 61)
return -1;
static time_t
-Convert(Month, Day, Year, Hours, Minutes, Seconds, Meridian, dst)
- time_t Month;
- time_t Day;
- time_t Year;
- time_t Hours;
- time_t Minutes;
- time_t Seconds;
- MERIDIAN Meridian;
- DSTMODE dst;
+Convert(time_t Month, time_t Day, time_t Year,
+ time_t Hours, time_t Minutes, time_t Seconds,
+ MERIDIAN Meridian, DSTMODE dst)
{
static int DaysNormal[13] = {
0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
static time_t
-DSTcorrect(Start, Future)
- time_t Start;
- time_t Future;
+DSTcorrect(time_t Start, time_t Future)
{
time_t StartDay;
time_t FutureDay;
static time_t
-RelativeMonth(Start, RelMonth)
- time_t Start;
- time_t RelMonth;
+RelativeMonth(time_t Start, time_t RelMonth)
{
struct tm *tm;
time_t Month;
static int
-LookupWord(buff, length)
- char *buff;
- register int length;
+LookupWord(char *buff, register int length)
{
register char *p;
register char *q;
int
-date_lex()
+date_lex(void)
{
register char c;
register char *p;
time_t
-parsedate(p)
- char *p;
+parsedate(char *p)
{
- extern int date_parse();
+ extern int date_parse(void);
time_t Start;
yyInput = p;
/* ARGSUSED */
int
-main(ac, av)
- int ac;
- char *av[];
+main(int ac, char *av[])
{
char buff[128];
time_t d;
/* NOTREACHED */
}
#endif /* TEST */
-#line 825 "y.tab.c"
+#line 805 "y.tab.c"
#define YYABORT goto yyabort
#define YYREJECT goto yyabort
#define YYACCEPT goto yyaccept
switch (yyn)
{
case 3:
-#line 118 "parsedate.y"
+#line 117 "parsedate.y"
{
yyHaveTime++;
#ifdef lint
}
break;
case 4:
-#line 127 "parsedate.y"
+#line 126 "parsedate.y"
{
yyHaveTime++;
yyTimezone = yyvsp[0].Number;
}
break;
case 5:
-#line 131 "parsedate.y"
+#line 130 "parsedate.y"
{
yyHaveDate++;
}
break;
case 6:
-#line 134 "parsedate.y"
+#line 133 "parsedate.y"
{
yyHaveRel = 1;
}
break;
case 7:
-#line 139 "parsedate.y"
+#line 138 "parsedate.y"
{
if (yyvsp[-1].Number < 100) {
yyHour = yyvsp[-1].Number;
}
break;
case 8:
-#line 151 "parsedate.y"
+#line 150 "parsedate.y"
{
yyHour = yyvsp[-3].Number;
yyMinutes = yyvsp[-1].Number;
}
break;
case 9:
-#line 157 "parsedate.y"
+#line 156 "parsedate.y"
{
yyHour = yyvsp[-3].Number;
yyMinutes = yyvsp[-1].Number;
}
break;
case 10:
-#line 164 "parsedate.y"
+#line 163 "parsedate.y"
{
yyHour = yyvsp[-5].Number;
yyMinutes = yyvsp[-3].Number;
}
break;
case 11:
-#line 170 "parsedate.y"
+#line 169 "parsedate.y"
{
yyHour = yyvsp[-5].Number;
yyMinutes = yyvsp[-3].Number;
}
break;
case 12:
-#line 180 "parsedate.y"
+#line 179 "parsedate.y"
{
yyval.Number = yyvsp[0].Number;
yyDSTmode = DSToff;
}
break;
case 13:
-#line 184 "parsedate.y"
+#line 183 "parsedate.y"
{
yyval.Number = yyvsp[0].Number;
yyDSTmode = DSTon;
}
break;
case 14:
-#line 188 "parsedate.y"
+#line 187 "parsedate.y"
{
/* Only allow "GMT+300" and "GMT-0800" */
if (yyvsp[-1].Number != 0) {
}
break;
case 15:
-#line 196 "parsedate.y"
+#line 195 "parsedate.y"
{
yyval.Number = yyvsp[0].Number;
yyDSTmode = DSToff;
}
break;
case 16:
-#line 202 "parsedate.y"
+#line 201 "parsedate.y"
{
int i;
}
break;
case 17:
-#line 223 "parsedate.y"
+#line 222 "parsedate.y"
{
yyMonth = yyvsp[-2].Number;
yyDay = yyvsp[0].Number;
}
break;
case 18:
-#line 227 "parsedate.y"
+#line 226 "parsedate.y"
{
if (yyvsp[-4].Number > 100) {
yyYear = yyvsp[-4].Number;
}
break;
case 19:
-#line 239 "parsedate.y"
+#line 238 "parsedate.y"
{
yyMonth = yyvsp[-1].Number;
yyDay = yyvsp[0].Number;
}
break;
case 20:
-#line 243 "parsedate.y"
+#line 242 "parsedate.y"
{
yyMonth = yyvsp[-3].Number;
yyDay = yyvsp[-2].Number;
}
break;
case 21:
-#line 248 "parsedate.y"
+#line 247 "parsedate.y"
{
yyDay = yyvsp[-1].Number;
yyMonth = yyvsp[0].Number;
}
break;
case 22:
-#line 252 "parsedate.y"
+#line 251 "parsedate.y"
{
yyDay = yyvsp[-2].Number;
yyMonth = yyvsp[-1].Number;
}
break;
case 23:
-#line 257 "parsedate.y"
+#line 256 "parsedate.y"
{
yyDay = yyvsp[-2].Number;
yyMonth = yyvsp[-1].Number;
}
break;
case 24:
-#line 264 "parsedate.y"
+#line 263 "parsedate.y"
{
yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number;
}
break;
case 25:
-#line 267 "parsedate.y"
+#line 266 "parsedate.y"
{
yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number;
}
break;
case 26:
-#line 270 "parsedate.y"
+#line 269 "parsedate.y"
{
yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number;
}
break;
case 27:
-#line 273 "parsedate.y"
+#line 272 "parsedate.y"
{
yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number;
}
break;
case 28:
-#line 278 "parsedate.y"
+#line 277 "parsedate.y"
{
yyval.Meridian = MER24;
}
break;
case 29:
-#line 281 "parsedate.y"
+#line 280 "parsedate.y"
{
yyval.Meridian = yyvsp[0].Meridian;
}
break;
-#line 1201 "y.tab.c"
+#line 1181 "y.tab.c"
}
yyssp -= yym;
yystate = *yyssp;
** <rsalz@osf.org> and Jim Berets <jberets@bbn.com> in August, 1990.
** Further revised (removed obsolete constructs and cleaned up timezone
** names) in August, 1991, by Rich. Paul Eggert <eggert@twinsun.com>
-** helped in September, 1992.
+** helped in September, 1992. Art Cancro <ajc@uncnsrd.mt-kisco.ny.us> cleaned
+** it up for ANSI C in December, 1999.
**
** This grammar has six shift/reduce conflicts.
**
#include <ctype.h>
#include <time.h>
-int date_lex();
+int date_lex(void);
#define yyparse date_parse
#define yylex date_lex
static time_t yyRelSeconds;
-extern struct tm *localtime();
-
-static void date_error();
+static void date_error(char *);
%}
%union {
static time_t
-ToSeconds(Hours, Minutes, Seconds, Meridian)
- time_t Hours;
- time_t Minutes;
- time_t Seconds;
- MERIDIAN Meridian;
+ToSeconds(time_t Hours, time_t Minutes, time_t Seconds, MERIDIAN Meridian)
{
if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 61)
return -1;
static time_t
-Convert(Month, Day, Year, Hours, Minutes, Seconds, Meridian, dst)
- time_t Month;
- time_t Day;
- time_t Year;
- time_t Hours;
- time_t Minutes;
- time_t Seconds;
- MERIDIAN Meridian;
- DSTMODE dst;
+Convert(time_t Month, time_t Day, time_t Year,
+ time_t Hours, time_t Minutes, time_t Seconds,
+ MERIDIAN Meridian, DSTMODE dst)
{
static int DaysNormal[13] = {
0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
static time_t
-DSTcorrect(Start, Future)
- time_t Start;
- time_t Future;
+DSTcorrect(time_t Start, time_t Future)
{
time_t StartDay;
time_t FutureDay;
static time_t
-RelativeMonth(Start, RelMonth)
- time_t Start;
- time_t RelMonth;
+RelativeMonth(time_t Start, time_t RelMonth)
{
struct tm *tm;
time_t Month;
static int
-LookupWord(buff, length)
- char *buff;
- register int length;
+LookupWord(char *buff, register int length)
{
register char *p;
register char *q;
int
-date_lex()
+date_lex(void)
{
register char c;
register char *p;
time_t
-parsedate(p)
- char *p;
+parsedate(char *p)
{
- extern int date_parse();
+ extern int date_parse(void);
time_t Start;
yyInput = p;
/* ARGSUSED */
int
-main(ac, av)
- int ac;
- char *av[];
+main(int ac, char *av[])
{
char buff[128];
time_t d;
#include "tools.h"
#include "internet_addressing.h"
-struct citsmtp {
+
+struct citsmtp { /* Information about the current session */
int command_state;
struct usersupp vrfy_buffer;
int vrfy_count;
char vrfy_match[256];
char from[256];
+ char recipient[256];
+ int number_of_recipients;
};
-enum {
+enum { /* Command states for login authentication */
smtp_command,
smtp_user,
smtp_password
*/
void smtp_help(void) {
cprintf("214-Here's the frequency, Kenneth:\n");
+ cprintf("214- DATA\n");
cprintf("214- EHLO\n");
cprintf("214- EXPN\n");
cprintf("214- HELO\n");
if (!strcasecmp(node, config.c_nodename)) { /* FIX use fcn */
cprintf("550 You must log in to send mail from %s\n",
config.c_fqdn);
+ strcpy(SMTP->from, "");
return;
}
}
* Implements the "RCPT To:" command
*/
void smtp_rcpt(char *argbuf) {
+ int cvt;
+ char user[256];
+ char node[256];
if (strlen(SMTP->from) == 0) {
cprintf("503 MAIL first, then RCPT. Duh.\n");
return;
}
+ if (strlen(SMTP->recipient) > 0) {
+ cprintf("550 Only one recipient allowed (FIX)\n");
+ return;
+ }
+
if (strncasecmp(argbuf, "To:", 3)) {
cprintf("501 Syntax error\n");
return;
}
- cprintf("599 this is unfinished\n");
+ strcpy(SMTP->recipient, &argbuf[3]);
+ striplt(SMTP->recipient);
+
+ cvt = convert_internet_address(user, node, SMTP->recipient);
+ switch(cvt) {
+ case rfc822_address_locally_validated:
+ cprintf("250 %s is a valid recipient.\n", user);
+ return;
+ case rfc822_no_such_user:
+ cprintf("550 %s: no such user\n", SMTP->recipient);
+ strcpy(SMTP->recipient, "");
+ return;
+ }
+
+ strcpy(SMTP->recipient, "");
+ cprintf("599 Unknown error (FIX)\n");
+}
+
+
+
+
+/*
+ * Implements the DATA command
+ */
+void smtp_data(void) {
+ char *body;
+
+ if (strlen(SMTP->from) == 0) {
+ cprintf("503 Need MAIL command first.\n");
+ return;
+ }
+
+ if (SMTP->number_of_recipients < 1) {
+ cprintf("503 Need RCPT command first.\n");
+ return;
+ }
+
+ cprintf("354 Transmit message now; terminate with '.' by itself\n");
+ body = CtdlReadMessageBody(".", config.c_maxmsglen);
+ if (body == NULL) {
+ cprintf("550 Unable to save message text: internal error.\n");
+ return;
+ }
+
+ phree(body);
+ cprintf("599 command unfinished\n");
}
smtp_auth(&cmdbuf[5]);
}
+ else if (!strncasecmp(cmdbuf, "DATA", 4)) {
+ smtp_data();
+ }
+
else if (!strncasecmp(cmdbuf, "EHLO", 4)) {
smtp_hello(&cmdbuf[5], 1);
}
c2 = strdup(s2);
for (i=0; i<strlen(c1); ++i) {
- if (isupper(c1[i])) c1[i]=tolower(c1[i]);
while (!isalnum(c1[i])) strcpy(&c1[i], &c1[i+1]);
+ if (isupper(c1[i])) c1[i]=tolower(c1[i]);
}
for (i=0; i<strlen(c2); ++i) {
- if (isupper(c2[i])) c2[i]=tolower(c2[i]);
while (!isalnum(c2[i])) strcpy(&c2[i], &c2[i+1]);
+ if (isupper(c2[i])) c2[i]=tolower(c2[i]);
}
ret = strcmp(c1, c2);