File indexing completed on 2018-03-02 18:44:55 UTC
view on githubraw file Latest commit ec6cf3b0 on 2003-08-26 20:45:25 UTC
ec6cf3b09d Ed H*0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052 #include "macnapp.h"
0053
0054 #define SMTP_PORT 25
0055
0056 typedef struct {
0057 na_win w;
0058 void *context;
0059 short num, rcpt;
0060 na_smtpstat statf;
0061 na_tcp tcpid;
0062 short state;
0063 short count;
0064 short refnum;
0065 short crfound:1;
0066 short crlf:1;
0067 short crtrans:1;
0068 long headsize;
0069 long fsize, fdone;
0070 long bufsize;
0071 Ptr buf;
0072 char linebuf[1024];
0073 char data[1];
0074 } na_smtpwin;
0075
0076 #define sw ((na_smtpwin *) w)
0077
0078
0079 #define S_conn 0
0080 #define S_greet 1
0081 #define S_hello 2
0082 #define S_mailf 3
0083 #define S_rcpt 4
0084 #define S_data 5
0085 #define S_send 6
0086 #define S_done 7
0087 #define S_quit 8
0088 #define S_wait 9
0089 #define S_close 10
0090
0091
0092
0093
0094 static int SMTPsend(na_win *w, char *com, char *data)
0095 {
0096 char buf[512];
0097 char *dest = buf;
0098 int result = 0;
0099
0100 while ((*dest = *com) != '\0') ++dest, ++com;
0101 if (data) {
0102 while ((*dest = *data++) != '\0') ++dest;
0103 if (com[-1] == '<') *dest++ = '>';
0104 }
0105 *dest++ = '\r';
0106 *dest++ = '\n';
0107 result = NATCPwrite(sw->tcpid, buf, dest - buf, -1);
0108
0109 return (result);
0110 }
0111
0112
0113
0114 static void smtpclose(na_win *w, short code, short err, long size, char *data)
0115 {
0116 if (sw->state < S_wait) {
0117 NATCPclose(sw->tcpid);
0118 FSClose(sw->refnum);
0119 sw->state = S_wait;
0120 (*sw->statf)(sw->context, code, err, size, data);
0121 }
0122 }
0123
0124
0125
0126 static void readp(void *wh, na_tcp s, short status, long size, char *data)
0127 {
0128 na_win *w, **taskh;
0129 char *dest;
0130 short major, count, smtpcode;
0131
0132
0133 for (taskh = NAtask; taskh && taskh != wh; taskh = (*taskh)->task);
0134 if (!taskh) return;
0135
0136
0137 w = NAlockWindow((na_win **) wh);
0138 if (status == NATCP_connect) {
0139
0140 sw->state = S_greet;
0141 } else if (status < 0) {
0142
0143 smtpclose(w, NASMTP_tcpfail, status, size, NULL);
0144 if (status == NATCP_closed) sw->state = S_close;
0145 } else if (status & NATCP_closing) {
0146
0147 if (sw->state < S_wait) {
0148 smtpclose(w, NASMTP_conclosed, 0, 0, NULL);
0149 }
0150 } else if (status & NATCP_data) {
0151 do {
0152
0153 dest = sw->linebuf + sw->count;
0154 while (size && sw->count < sizeof (sw->linebuf)) {
0155 --size, ++sw->count;
0156 if (sw->crfound && *data == '\n') {
0157 *--dest = '\0';
0158 --sw->count;
0159 ++data;
0160 sw->crfound = 0;
0161 sw->crlf = 1;
0162 break;
0163 }
0164 sw->crfound = (*dest++ = *data++) == '\r';
0165 }
0166 if (!sw->crlf) {
0167 if (sw->count == sizeof (sw->linebuf)) {
0168 sw->linebuf[sw->count - 1] = '\0';
0169 smtpclose(w, NASMTP_badprot, 0, 0, sw->linebuf);
0170 }
0171 break;
0172 }
0173 sw->crlf = 0;
0174
0175 dest = sw->linebuf;
0176 if (sw->count < 3 || !isdigit(dest[0])
0177 || !isdigit(dest[1]) || !isdigit(dest[2])) {
0178 smtpclose(w, NASMTP_badprot, 0, 0, dest);
0179 break;
0180 }
0181 sw->count = 0;
0182 major = dest[0] - '0';
0183 smtpcode = major * 100 + (dest[1] - '0') * 10 + (dest[2] - '0');
0184
0185 if (dest[3] == '-') continue;
0186
0187 if (major > 3) {
0188 if (sw->state != S_rcpt) {
0189 smtpclose(w, major == 4 ? NASMTP_temperr : NASMTP_permerr,
0190 smtpcode, sw->state, dest + 3);
0191 break;
0192 }
0193 (*sw->statf)(sw->context, NASMTP_badaddr, smtpcode, 0, sw->linebuf + 3);
0194 }
0195 dest = sw->data + sw->headsize;
0196
0197 switch (sw->state) {
0198 case S_greet:
0199 if (sw->buf) {
0200 SMTPsend(w, "HELO ", sw->buf);
0201 if (sw->buf) DisposPtr(sw->buf);
0202 }
0203 sw->state = S_hello;
0204 break;
0205 case S_hello:
0206 SMTPsend(w, "MAIL FROM:<", dest);
0207 (*sw->statf)(sw->context, NASMTP_progress, 5, 0, 0);
0208 sw->state = S_mailf;
0209 break;
0210 case S_mailf:
0211 case S_rcpt:
0212 count = ++sw->rcpt;
0213 if (count < sw->num + 1) {
0214 while (count--) {
0215 while (*dest++);
0216 }
0217 SMTPsend(w, "RCPT TO:<", dest);
0218 (*sw->statf)(sw->context, NASMTP_progress, 5 + 10 * sw->rcpt / sw->num, 0, 0);
0219 } else {
0220 sw->state = S_data;
0221 SMTPsend(w, "DATA", 0);
0222 (*sw->statf)(sw->context, NASMTP_progress, 20, 0, 0);
0223 }
0224 break;
0225 case S_data:
0226 if (major != 3) {
0227 smtpclose(w, NASMTP_badprot, 0, 0, dest);
0228 break;
0229 }
0230 sw->state = S_send;
0231 if (sw->headsize) {
0232 sw->buf = NewPtr(sw->bufsize = sw->headsize);
0233 if (!sw->buf) {
0234 smtpclose(w, NASMTP_nomem, 0, 0, NULL);
0235 break;
0236 }
0237 memcpy(sw->buf, sw->data, sw->headsize);
0238 }
0239 case S_send:
0240
0241 break;
0242 case S_done:
0243 sw->state = S_quit;
0244 SMTPsend(w, "QUIT", NULL);
0245 (*sw->statf)(sw->context, NASMTP_progress, 95, 0, 0);
0246 break;
0247 case S_quit:
0248 smtpclose(w, NASMTP_completed, 0, 0, 0);
0249 break;
0250 }
0251 } while (size);
0252 }
0253 NAunlockWindowh((na_win **) wh, w)
0254 }
0255
0256
0257
0258 static void hostp(void *wh, na_tcp s, short status, long size, char *data)
0259 {
0260 na_win *w, **taskh;
0261
0262
0263 for (taskh = NAtask; taskh && taskh != wh; taskh = (*taskh)->task);
0264 if (!taskh) return;
0265
0266
0267 w = NAlockWindow((na_win **) wh);
0268 if (status == NATCP_connect) {
0269 if (sw->state == S_hello) {
0270 SMTPsend(w, "HELO ", data);
0271 } else {
0272 sw->buf = NewPtr(size + 1);
0273 if (sw->buf == NULL) {
0274 smtpclose(w, NASMTP_nomem, 0, 0, NULL);
0275 } else {
0276 memcpy(sw->buf, data, size + 1);
0277 }
0278 }
0279 } else {
0280 smtpclose(w, NASMTP_tcpfail, status, size, NULL);
0281 }
0282 NAunlockWindowh((na_win **) wh, w);
0283 }
0284
0285
0286
0287 static void crtocrlf(char *buf, long *size)
0288 {
0289 long crcount = 0;
0290 char *src, *dst, *end = buf + *size;
0291
0292 for (src = buf; src < end; ++src) {
0293 if (src[0] == '\r') ++crcount;
0294 }
0295 src = end - 1;
0296 for (dst = src + crcount; dst > src; *dst-- = *src--) {
0297 if (*src == '\r') *dst-- = '\n';
0298 }
0299 *size += crcount;
0300 }
0301
0302
0303
0304 static short taskp(na_win *w)
0305 {
0306 OSErr oserr;
0307
0308 if (sw->state == S_send || sw->state == S_done) {
0309
0310 if (!sw->bufsize) {
0311 if ((sw->buf = NewPtr(8192)) == NULL) {
0312 smtpclose(w, NASMTP_nomem, 0, 0, NULL);
0313 return (NA_NOTPROCESSED);
0314 }
0315 sw->bufsize = sw->crtrans ? 4096 : 8192;
0316 oserr = FSRead(sw->refnum, &sw->bufsize, sw->buf);
0317 if (oserr != noErr && oserr != eofErr) sw->bufsize = 0;
0318 if (!sw->bufsize) {
0319 if (oserr == eofErr && sw->state == S_send) {
0320 memcpy(sw->buf, "\r\n.\r\n", 5);
0321 sw->bufsize = 5;
0322 sw->state = S_done;
0323 } else {
0324 DisposPtr(sw->buf);
0325 }
0326 } else {
0327 if (sw->crtrans) {
0328 crtocrlf(sw->buf, &sw->bufsize);
0329 }
0330 (*sw->statf)(sw->context, NASMTP_progress, 20
0331 + 70 * (sw->fdone += sw->bufsize) / sw->fsize, 0, 0);
0332 }
0333 }
0334 if (sw->bufsize && NATCPwrite(sw->tcpid, sw->buf, sw->bufsize, 1) == NATCP_data) {
0335 sw->bufsize = 0;
0336 }
0337 }
0338
0339 return (sw->state == S_close ? NA_REQCLOSE : NA_NOTPROCESSED);
0340 }
0341
0342
0343
0344
0345
0346 static short closep(na_win *w)
0347 {
0348 if (sw->state < S_wait) {
0349
0350 if (sw->tcpid >= 0) NATCPclose(sw->tcpid);
0351 FSClose(sw->refnum);
0352 }
0353
0354 return (NA_CLOSED);
0355 }
0356
0357
0358
0359
0360
0361
0362 void NASMTPsubmit(na_smtpstat statf, char *server, FSSpec *fspec, Handle headers,
0363 Handle envelope, short flags, void *context)
0364 {
0365 long size;
0366 na_win **wh, *w;
0367 char *src, *dst;
0368 OSErr oserr;
0369
0370
0371 size = sizeof (na_smtpwin);
0372 if (headers) size += GetHandleSize(headers);
0373 size += GetHandleSize(envelope);
0374 wh = NAaddtask(taskp, size);
0375 if (!wh) {
0376 (*statf)(context, NASMTP_nomem, 0, 0, 0);
0377 return;
0378 }
0379
0380
0381 w = NAlockWindow(wh);
0382 w->type = NA_SMTPTYPE;
0383 w->closep = closep;
0384 sw->context = context;
0385 sw->statf = statf;
0386 if (headers && (sw->headsize = GetHandleSize(headers))) {
0387 memcpy(sw->data, (char *) *headers, sw->headsize);
0388 }
0389 size = GetHandleSize(envelope);
0390 sw->num = -1;
0391 dst = sw->data + sw->headsize;
0392 for (src = (char *) *envelope; size; --size) {
0393 if ((*dst++ = *src++) == '\0') ++sw->num;
0394 }
0395 if (flags & NASMTP_crtrans) sw->crtrans = 1;
0396
0397
0398 if ((oserr = HOpen(fspec->vRefNum, fspec->parID, fspec->name,
0399 fsRdPerm, &sw->refnum)) != noErr) {
0400 (*statf)(context, NASMTP_oserr, 0, oserr, 0);
0401 NAcloseWindow(w, NA_CLOSED);
0402 return;
0403 }
0404 GetEOF(sw->refnum, &sw->fsize);
0405
0406
0407 sw->tcpid = NATCPopen(readp, (void *) wh, server, SMTP_PORT, 0);
0408 if (sw->tcpid != -1) NATCPgethost(hostp, (void *) wh);
0409 NAunlockWindowh(wh, w);
0410 }