示例#1
0
/* Before we render a mail message, let's make sure it looks like email.
 * This is similar to htmlTest() in html.c. */
bool emailTest(void)
{
	int i, j, k, n;

/* This is a very simple test - hopefully not too simple.
 * The first 20 non-indented lines have to look like mail header lines,
 * with at least half the keywords recognized. */
	for (i = 1, j = k = 0; i <= cw->dol && j < 20; ++i) {
		char *q;
		char *p = (char *)fetchLine(i, -1);
		char first = *p;
		if (first == '\n' || first == '\r' && p[1] == '\n')
			break;
		if (first == ' ' || first == '\t')
			continue;
		++j;		/* nonindented line */
		for (q = p; isalnumByte(*q) || *q == '_' || *q == '-'; ++q) ;
		if (q == p)
			continue;
		if (*q++ != ':')
			continue;
/* X-Whatever is a mail header word */
		if (q - p >= 8 && p[1] == '-' && toupper(p[0]) == 'X') {
			++k;
		} else {
			for (n = 0; mhwords[n]; ++n)
				if (memEqualCI(mhwords[n], p, q - p))
					break;
			if (mhwords[n])
				++k;
		}
		if (k >= 4 && k * 2 >= j)
			return true;
	}			/* loop over lines */

	return false;
}				/* emailTest */
示例#2
0
/* set document.cookie to the cookies relevant to this url */
static void docCookie(jsobjtype d)
{
	int cook_l;
	char *cook = initString(&cook_l);
	const char *url = cw->fileName;
	bool secure = false;
	const char *proto;
	char *s;

	if (url) {
		proto = getProtURL(url);
		if (proto && stringEqualCI(proto, "https"))
			secure = true;
		sendCookies(&cook, &cook_l, url, secure);
		if (memEqualCI(cook, "cookie: ", 8)) {	/* should often happen */
			strmove(cook, cook + 8);
		}
		if (s = strstr(cook, "\r\n"))
			*s = 0;
	}

	set_property_string(d, "cookie", cook);
	nzFree(cook);
}				/* docCookie */
示例#3
0
/* Read a file into memory, mime encode it,
 * and return the type of encoding and the encoded data.
 * Last three parameters are result parameters.
 * If ismail is nonzero, the file is the mail, not an attachment.
 * In fact ismail indicates the line that holds the subject.
 * If ismail is negative, then -ismail indicates the subject line,
 * and the string file is not the filename, but rather, the mail to send. */
bool
encodeAttachment(const char *file, int ismail, bool webform,
		 const char **type_p, const char **enc_p, char **data_p)
{
	char *buf;
	char c;
	bool longline;
	char *s, *t, *v;
	char *ct, *ce;		/* content type, content encoding */
	int buflen, i, cx;
	int nacount, nullcount, nlcount;

	if (ismail < 0) {
		buf = cloneString(file);
		buflen = strlen(buf);
		ismail = -ismail;
		file = EMPTYSTRING;
	} else {

		if (!ismc && (cx = stringIsNum(file)) >= 0) {
			static char newfilename[16];
			if (!unfoldBuffer(cx, false, &buf, &buflen))
				return false;
			if (!buflen) {
				if (webform) {
empty:
					buf = EMPTYSTRING;
					ct = "text/plain";
					ce = "7bit";
					goto success;
				}
				setError(MSG_BufferXEmpty, cx);
				goto freefail;
			}
			sprintf(newfilename, "<buffer %d>", cx);
			file = newfilename;
			if (sessionList[cx].lw->fileName)
				file = sessionList[cx].lw->fileName;
		} else {
			if (!fileIntoMemory(file, &buf, &buflen))
				return false;
			if (!buflen) {
				if (webform)
					goto empty;
				setError(MSG_FileXEmpty, file);
				goto freefail;
			}
		}
	}			/* ismail negative or normal */

	if (ismail) {
/* Put newline at the end.  Yes, the buffer is allocated
 * with space for newline and null. */
		if (buf[buflen - 1] != '\n')
			buf[buflen++] = '\n';
/* check for subject: line */
		s = buf;
		i = ismail;
		while (--i) {
			while (*s != '\n')
				++s;
			++s;
		}
		while (*s == ' ' || *s == '\t')
			++s;
		if (!memEqualCI(s, "subject:", 8)) {
			setError(MSG_SubjectStart);
			goto freefail;
		}
		s += 8;
		while (*s == ' ' || *s == '\t')
			++s;
		t = s;
		while (*s != '\n')
			++s;
		v = s;
		while (s > t && isspaceByte(s[-1]))
			--s;
		if (s - t >= sizeof(subjectLine)) {
			setError(MSG_SubjectLong, sizeof(subjectLine) - 1);
			goto freefail;
		}
		if (s > t)
			memcpy(subjectLine, t, s - t);
		subjectLine[s - t] = 0;
		if (subjectLine[0]) {
			char *subjiso = isoEncode(subjectLine,
						  subjectLine +
						  strlen(subjectLine));
			if (subjiso) {
				if (strlen(subjiso) >= sizeof(subjectLine)) {
					nzFree(subjiso);
					setError(MSG_SubjectLong,
						 sizeof(subjectLine) - 1);
					goto freefail;
				}
				strcpy(subjectLine, subjiso);
				nzFree(subjiso);
			}
		}
		debugPrint(6, "subject = %s", subjectLine);
/* Blank lines after subject are optional, and ignored. */
		for (t = buf + buflen; v < t; ++v)
			if (*v != '\r' && *v != '\n')
				break;
		buflen -= (v - buf);
		if (buflen)
			memmove(buf, v, buflen);
		buf[buflen] = 0;

		if (doSignature) {	/* Append .signature file. */
/* Try account specific .signature file, then fall back to .signature */
			sprintf(sigFileEnd, "%d", mailAccount);
			c = fileTypeByName(sigFile, false);
			if (!c) {
				*sigFileEnd = 0;
				c = fileTypeByName(sigFile, false);
			}
			if (c != 0) {
				int fd, n;
				if (c != 'f') {
					setError(MSG_SigRegular);
					goto freefail;
				}
				n = fileSizeByName(sigFile);
				if (n > 0) {
					buf = reallocMem(buf, buflen + n + 1);
					fd = open(sigFile, O_RDONLY);
					if (fd < 0) {
						setError(MSG_SigAccess);
						goto freefail;
					}
					read(fd, buf + buflen, n);
					close(fd);
					buflen += n;
					buf[buflen] = 0;
				}
			}
		}		/* .signature */
	}

	/* Infer content type from the filename */
	ct = 0;
	s = strrchr(file, '.');
	if (s && s[1]) {
		++s;
		if (stringEqualCI(s, "ps"))
			ct = "application/PostScript";
		if (stringEqualCI(s, "jpeg"))
			ct = "image/jpeg";
		if (stringEqualCI(s, "gif"))
			ct = "image/gif";
		if (stringEqualCI(s, "wav"))
			ct = "audio/basic";
		if (stringEqualCI(s, "mpeg"))
			ct = "video/mpeg";
		if (stringEqualCI(s, "rtf"))
			ct = "text/richtext";
		if (stringEqualCI(s, "htm") ||
		    stringEqualCI(s, "html") ||
		    stringEqualCI(s, "shtm") ||
		    stringEqualCI(s, "shtml") || stringEqualCI(s, "asp"))
			ct = "text/html";
	}

/* Count the nonascii characters */
	nacount = nullcount = nlcount = 0;
	longline = false;
	s = 0;
	for (i = 0; i < buflen; ++i) {
		c = buf[i];
		if (c == '\0')
			++nullcount;
		if (c < 0)
			++nacount;
		if (c != '\n')
			continue;
		++nlcount;
		t = buf + i;
		if (s && t - s > 120)
			longline = true;
		if (!s && i > 120)
			longline = true;
		s = t;
	}
	t = buf + i;
	if (s && t - s > 120)
		longline = true;
	if (!s && i > 120)
		longline = true;
	debugPrint(6, "attaching %s length %d nonascii %d nulls %d longline %d",
		   file, buflen, nacount, nullcount, longline);
	nacount += nullcount;

/* Set the type of attachment */
	if (buflen > 20 && nacount * 5 > buflen) {
		if (!ct)
			ct = "application/octet-stream";	/* default type for binary */
	}
	if (!ct)
		ct = "text/plain";

/* Criteria for base64 encode.
 * files uploaded from a web form need not be encoded, unless they contain
 * nulls, which is a quirk of my slapped together software. */

	if (!webform && (buflen > 20 && nacount * 5 > buflen) ||
	    webform && nullcount) {
		if (ismail) {
			setError(MSG_MailBinary, file);
			goto freefail;
		}
		s = base64Encode(buf, buflen, true);
		nzFree(buf);
		buf = s;
		ce = "base64";
		goto success;
	}

	if (!webform) {
/* Switch to unix newlines - we'll switch back to dos later. */
		v = buf + buflen;
		for (s = t = buf; s < v; ++s) {
			c = *s;
			if (c == '\r' && s < v - 1 && s[1] == '\n')
				continue;
			*t++ = c;
		}
		buflen = t - buf;

/* Do we need to use quoted-printable? */
/* Perhaps this hshould read (nacount > 0) */
		if (nacount * 20 > buflen || nullcount || longline) {
			char *newbuf;
			int l, colno = 0, space = 0;

			newbuf = initString(&l);
			v = buf + buflen;
			for (s = buf; s < v; ++s) {
				c = *s;
/* do we have to =expand this character? */
				if (c < '\n' && c != '\t' ||
				    c == '=' ||
				    c == '\xff' ||
				    (c == ' ' || c == '\t') && s < v - 1
				    && s[1] == '\n') {
					char expand[4];
					sprintf(expand, "=%02X", (uchar) c);
					stringAndString(&newbuf, &l, expand);
					colno += 3;
				} else {
					stringAndChar(&newbuf, &l, c);
					++colno;
				}
				if (c == '\n') {
					colno = space = 0;
					continue;
				}
				if (c == ' ' || c == '\t')
					space = l;
				if (colno < 72)
					continue;
				if (s == v - 1)
					continue;
/* If newline's coming up anyways, don't force another one. */
				if (s[1] == '\n')
					continue;
				i = l;
				if (!space || space == i) {
					stringAndString(&newbuf, &l, "=\n");
					colno = space = 0;
					continue;
				}
				colno = i - space;
				stringAndString(&newbuf, &l, "**");	/* make room */
				while (i > space) {
					newbuf[i + 1] = newbuf[i - 1];
					--i;
				}
				newbuf[space] = '=';
				newbuf[space + 1] = '\n';
				space = 0;
			}	/* loop over characters */

			nzFree(buf);
			buf = newbuf;
			ce = "quoted-printable";
			goto success;
		}
	}

	buf[buflen] = 0;
	ce = (nacount ? "8bit" : "7bit");

success:
	debugPrint(6, "encoded %s %s length %d", ct, ce, strlen(buf));
	*enc_p = ce;
	*type_p = ct;
	*data_p = buf;
	return true;

freefail:
	nzFree(buf);
	return false;
}				/* encodeAttachment */
示例#4
0
bool sendMailCurrent(int sm_account, bool dosig)
{
	const char *reclist[MAXRECAT + 1];
	char *recmem;
	const char *atlist[MAXRECAT + 1];
	char *atmem;
	char *s, *t;
	char cxbuf[4];
	int lr, la, ln;
	char *refline = 0;
	int nrec = 0, nat = 0, nalt = 0;
	int account = localAccount;
	int j;
	bool rc = false;
	bool subj = false;

	if (cw->browseMode) {
		setError(MSG_MailBrowse);
		return false;
	}
	if (cw->sqlMode) {
		setError(MSG_MailDB);
		return false;
	}
	if (cw->dirMode) {
		setError(MSG_MailDir);
		return false;
	}
	if (cw->binMode) {
		setError(MSG_MailBinary2);
		return false;
	}
	if (!cw->dol) {
		setError(MSG_MailEmpty);
		return false;
	}

	if (!validAccount(account))
		return false;

	recmem = initString(&lr);
	atmem = initString(&la);

/* Gather recipients and attachments, until we reach subject: */
	for (ln = 1; ln <= cw->dol; ++ln) {
		char *line = (char *)fetchLine(ln, -1);

		if (memEqualCI(line, "to:", 3) ||
		    memEqualCI(line, "mailto:", 7) ||
		    memEqualCI(line, "cc:", 3) ||
		    memEqualCI(line, "bcc:", 4) ||
		    memEqualCI(line, "reply to:", 9) ||
		    memEqualCI(line, "reply to ", 9)) {
			char cc = 0;
			if (toupper(line[0]) == 'C')
				cc = '^';
			if (toupper(line[0]) == 'B')
				cc = '?';
			if (toupper(line[0]) == 'R')
				line += 9;
			else
				line = strchr(line, ':') + 1;
			while (*line == ' ' || *line == '\t')
				++line;
			if (*line == '\n') {
				setError(MSG_RecipNone2, ln);
				goto done;
			}
			if (nrec == MAXRECAT) {
				setError(MSG_RecipMany, MAXRECAT);
				goto done;
			}
			++nrec;
			for (t = line; *t != '\n'; ++t) ;
			if (cc) {
				if (!lr) {
					setError(MSG_MailFirstCC);
					goto done;
				}
				stringAndChar(&recmem, &lr, cc);
			}
			stringAndBytes(&recmem, &lr, line, t + 1 - line);
			continue;
		}

		if (memEqualCI(line, "attach:", 7)
		    || memEqualCI(line, "alt:", 4)) {
			if (toupper(line[1]) == 'T')
				line += 7;
			else
				line += 4, ++nalt;
			while (*line == ' ' || *line == '\t')
				++line;
			if (*line == '\n') {
				setError(MSG_AttLineX, ln);
				goto done;
			}
			if (nat == MAXRECAT) {
				setError(MSG_RecipMany, MAXRECAT);
				goto done;
			}
			++nat;
			for (t = line; *t != '\n'; ++t) ;
			stringAndBytes(&atmem, &la, line, t + 1 - line);
			continue;
		}

		if (memEqualCI(line, "account:", 8)) {
			line += 8;
			while (*line == ' ' || *line == '\t')
				++line;
			if (!isdigitByte(*line) ||
			    (account = strtol(line, &line, 10)) == 0 ||
			    account > maxAccount || *line != '\n') {
				setError(MSG_MailAccountBadLineX, ln);
				goto done;
			}
			continue;
		}

		if (memEqualCI(line, "references:", 11)) {
			if (!refline)
				refline = line;
			continue;
		}

		if (memEqualCI(line, "subject:", 8)) {
			while (*line == ' ' || *line == '\t')
				++line;
			subj = true;
		}

		break;
	}			/* loop over lines */

	if (sm_account)
		account = sm_account;
	if (!subj) {
		setError(((ln > cw->dol) + MSG_MailFirstLine), ln);
		goto done;
	}

	if (nrec == 0) {
		setError(MSG_RecipNone3);
		goto done;
	}

	for (s = recmem, j = 0; *s; s = t + 1, ++j) {
		t = strchr(s, '\n');
		*t = 0;
		reclist[j] = s;
	}
	reclist[j] = 0;
	for (s = atmem, j = 0; *s; s = t + 1, ++j) {
		t = strchr(s, '\n');
		*t = 0;
		atlist[j] = s;
	}
	atlist[j] = 0;

	sprintf(cxbuf, "%d", context);
	rc = sendMail(account, reclist, cxbuf, ln, atlist, refline, nalt,
		      dosig);

done:
	nzFree(recmem);
	nzFree(atmem);
	if (!rc && intFlag)
		setError(MSG_Interrupted);
	if (rc)
		i_puts(MSG_OK);
	return rc;
}				/* sendMailCurrent */
示例#5
0
static void isoDecode(char *vl, char **vrp)
{
	char *vr = *vrp;
	char *start, *end;	/* section being decoded */
	char *s, *t, c, d, code;
	int len;
	uchar val, leftover, mod;

	start = vl;
restart:
	start = strstr(start, "=?");
	if (!start || start >= vr)
		goto finish;
	start += 2;
	if (!memEqualCI(start, "iso-", 4) &&
	    !memEqualCI(start, "us-ascii", 8) &&
	    !memEqualCI(start, "utf-", 4) &&
	    !memEqualCI(start, "cp1252", 6) &&
	    !memEqualCI(start, "gb", 2) && !memEqualCI(start, "windows-", 8))
		goto restart;
	s = strchr(start, '?');
	if (!s || s > vr - 5 || s[2] != '?')
		goto restart;
	code = s[1];
	code = toupper(code);
	if (code != 'Q' && code != 'B')
		goto restart;
	s += 3;
	end = strstr(s, "?=");
	if (!end || end > vr - 2)
		goto restart;

	t = start - 2;

	if (code == 'Q') {
		while (s < end) {
			c = *s++;
			if (c == '=') {
				c = *s;
				d = s[1];
				if (isxdigit(c) && isxdigit(d)) {
					d = fromHex(c, d);
					*t++ = d;
					s += 2;
					continue;
				}
				c = '=';
			}
			*t++ = c;
		}
		goto copy;
	}

/* base64 */
	mod = 0;
	for (; s < end; ++s) {
		c = *s;
		if (isspaceByte(c))
			continue;
		if (c == '=')
			continue;
		val = base64Bits(c);
		if (val & 64)
			val = 0;	/* ignore errors here */
		if (mod == 0) {
			leftover = val << 2;
		} else if (mod == 1) {
			*t++ = (leftover | (val >> 4));
			leftover = val << 4;
		} else if (mod == 2) {
示例#6
0
/* Look for the name of the attachment and boundary */
static void ctExtras(struct MHINFO *w, const char *s, const char *t)
{
	char quote;
	const char *q, *al, *ar;

	if (w->ct < CT_MULTI) {
		quote = 0;
		for (q = s + 1; q < t; ++q) {
			if (isalnumByte(q[-1]))
				continue;
/* could be name= or filename= */
			if (memEqualCI(q, "file", 4))
				q += 4;
			if (!memEqualCI(q, "name=", 5))
				continue;
			q += 5;
			if (*q == '"') {
				quote = *q;
				++q;
			}
			for (al = q; q < t; ++q) {
				if (*q == '"')
					break;
				if (quote)
					continue;
				if (strchr(",; \t", *q))
					break;
			}
			ar = q;
			if (ar - al >= MHLINE)
				ar = al + MHLINE - 1;
			strncpy(w->cfn, al, ar - al);
			break;
		}
	}
	/* regular file */
	if (w->ct >= CT_MULTI) {
		quote = 0;
		for (q = s + 1; q < t; ++q) {
			if (isalnumByte(q[-1]))
				continue;
			if (!memEqualCI(q, "boundary=", 9))
				continue;
			q += 9;
			if (*q == '"') {
				quote = *q;
				++q;
			}
			for (al = q; q < t; ++q) {
				if (*q == '"')
					break;
				if (quote)
					continue;
				if (strchr(",; \t", *q))
					break;
			}
			ar = q;
			w->boundlen = ar - al;
			strncpy(w->boundary, al, ar - al);
			break;
		}
	}			/* multi or alt */
}				/* ctExtras */