Ejemplo n.º 1
0
/* I'm assuming I can read the cookie file, process it,
 * and if necessary, write it out again, with the expired cookies deleted,
 * all before another edbrowse process interferes.
 * I've given it some thought, and I think I can ignore the race conditions. */
void cookiesFromJar(void)
{
	char *cbuf, *s, *t;
	FILE *f;
	int n, cnt, expired, displaced;
	char *cbuf_end;
	time_t now;
	struct cookie *c;

	if (!cookieFile)
		return;
	if (!fileIntoMemory(cookieFile, &cbuf, &n))
		showErrorAbort();
	cbuf[n] = 0;
	cbuf_end = cbuf + n;
	time(&now);

	cnt = expired = displaced = 0;
	s = cbuf;

	while (s < cbuf_end) {
		t = s + strcspn(s, "\r\n");
/* t points to the first newline past s.  If there is no newline in s,
 * then it points to the NUL byte at end of s. */
		*t = '\0';
		c = cookie_from_netscape_line(s);

		if (c) {	/* Got a valid cookie line. */
			cnt++;
			if (c->expires < now) {
				freeCookie(c);
				nzFree(c);
				++expired;
			} else {
				acceptCookie(c);
				displaced += displacedCookie;
			}
		}

		s = t + 1;	/* Get ready to read more lines. */
/* Skip over blank lines, if necessary.  */
		while (s < cbuf_end && (*s == '\r' || *s == '\n'))
			s++;
	}

	debugPrint(3, "%d persistent cookies, %d expired, %d displaced",
		   cnt, expired, displaced);
	nzFree(cbuf);
	if (!(expired + displaced))
		return;

/* Pour the cookies back into the jar */
	f = fopen(cookieFile, "w");
	if (!f)
		i_printfExit(MSG_NoRebCookie, cookieFile);
	foreach(c, cookies) {
		char *cookLine = netscapeCookieLine(c);
		fputs(cookLine, f);
		nzFree(cookLine);
	}
Ejemplo n.º 2
0
static void freeCookie(struct cookie *c)
{
	nzFree(c->name);
	nzFree(c->value);
	nzFree(c->server);
	nzFree(c->path);
	nzFree(c->domain);
}				/* freeCookie */
Ejemplo n.º 3
0
static void freeMailInfo(struct MHINFO *w)
{
	struct MHINFO *v;
	while (!listIsEmpty(&w->components)) {
		v = w->components.next;
		delFromList(v);
		freeMailInfo(v);
	}
	nzFree(w->tolist);
	nzFree(w->cclist);
	nzFree(w);
}				/* freeMailInfo */
Ejemplo n.º 4
0
/* the entry point */
void html2nodes(const char *htmltext, bool startpage)
{
	char *htmlfix = 0;

	tdoc = tidyCreate();
	if (!startpage)
		tidyOptSetInt(tdoc, TidyBodyOnly, yes);
	tidySetReportFilter(tdoc, tidyErrorHandler);
//    tidySetReportFilter(tdoc, tidyReportFilter);

	tidySetCharEncoding(tdoc, (cons_utf8 ? "utf8" : "latin1"));

	htmlfix = tidyPreprocess(htmltext);
	if (htmlfix) {
		tidyParseString(tdoc, htmlfix);
		nzFree(htmlfix);
	} else
		tidyParseString(tdoc, htmltext);

	tidyCleanAndRepair(tdoc);

	if (debugLevel >= 5) {
		traverse_tidycall = printNode;
		traverseTidy();
	}

/* convert tidy nodes into edbrowse nodes */
	traverse_tidycall = convertNode;
	traverseTidy();

	tidyRelease(tdoc);
}				/* html2nodes */
Ejemplo n.º 5
0
/* run a function with no args that returns an object */
jsobjtype run_function_object(jsobjtype obj, const char *name)
{
	run_function(obj, name, 0, NULL);
	if (!propval)
		return NULL;
	if (head.proptype == EJ_PROP_OBJECT || head.proptype == EJ_PROP_ARRAY) {
		jsobjtype p;
		sscanf(propval, "%p", &p);
		nzFree(propval);
		propval = 0;
		return p;
	}
/* wrong type, just return NULL */
	nzFree(propval);
	propval = 0;
	return NULL;
}				/* run_function_object */
Ejemplo n.º 6
0
/* Tell libcurl about a new cookie.  Called when setting cookies from
 * JavaScript.
 * The function is pretty simple.  Construct a line of the form used by
 * the Netscape cookie file format, and pass that to libcurl. */
static CURLcode cookieForLibcurl(const struct cookie *c)
{
	CURLcode ret;
	char *cookLine = netscapeCookieLine(c);
	debugPrint(3, "cookie for libcurl");
	ret = curl_easy_setopt(http_curl_handle, CURLOPT_COOKIELIST, cookLine);
	nzFree(cookLine);
	return ret;
}				/* cookieForLibcurl */
Ejemplo n.º 7
0
char *prependString(char *s, const char *p)
{
	int slen = strlen(s);
	int plen = strlen(p);
	char *t = allocString(slen + plen + 1);
	strcpy(t, p);
	strcpy(t + plen, s);
	nzFree(s);
	return t;
}				/* prependstring */
Ejemplo n.º 8
0
/* run a stored procedure with no % formatting */
static bool
sql_procGo(const char *stmt)
{
    bool rowfound;
    char *s = allocMem(20 + strlen(stmt));
    strcpy(s, "execute procedure ");
    strcat(s, stmt);
    rowfound = execInternal(s, 3);
    /* if execInternal doesn't return, we have a memory leak */
    nzFree(s);
    return rowfound;
}				/* sql_procGo */
Ejemplo n.º 9
0
char *tidyPreprocess(const char *h)
{
	char *ns;		/* the new string */
	int l;
	char *inside, *expanded;
	const char *lg, *s = strstrCI(h, "<textarea");
/* most web pages don't have textareas */
	if (!s)
		return NULL;
	ns = initString(&l);
	stringAndBytes(&ns, &l, h, s - h);
	h = s;
	while (true) {
/* next textarea */
		s = strstrCI(h, "<textarea");
		if (!s)
			break;
		s = strchr(s, '>');
		if (!s)
			break;
		++s;
		stringAndBytes(&ns, &l, h, s - h);
		h = s;
		s = strstrCI(h, "</textarea");
		if (!s)
			break;
		lg = strpbrk(h, "<>");
/* lg is at most s */
		if (lg == s)
			continue;
		inside = pullString1(h, s);
		expanded = htmlEscapeTextarea(inside);
		stringAndString(&ns, &l, expanded);
		nzFree(inside);
		nzFree(expanded);
		h = s;
	}
	stringAndString(&ns, &l, h);
	return ns;
}				/* tidyPreprocess */
Ejemplo n.º 10
0
/* run a function with no args that returns a boolean */
bool run_function_bool(jsobjtype obj, const char *name)
{
	run_function(obj, name, 0, NULL);
	if (!propval)
		return true;
	if (head.proptype == EJ_PROP_BOOL) {
		bool rc = (propval[0] == '1');
		nzFree(propval);
		propval = 0;
		return rc;
	}
	if (head.proptype == EJ_PROP_INT) {
		int n = atoi(propval);
		nzFree(propval);
		propval = 0;
		return (n != 0);
	}
/* wrong type, but at least it's something, just return true */
	nzFree(propval);
	propval = 0;
	return true;
}				/* run_function_bool */
Ejemplo n.º 11
0
jsobjtype instantiate_array_element(jsobjtype array, int idx,
				    const char *classname)
{
	jsobjtype p = 0;
	if (whichproc == 'j')
		return instantiate_array_element_nat(array, idx, classname);
	set_array_element(array, idx, classname, EJ_PROP_INSTANCE);
	if (!propval)
		return p;
	sscanf(propval, "%p", &p);
	nzFree(propval);
	propval = 0;
	return p;
}				/* instantiate_array_element */
Ejemplo n.º 12
0
bool
showTables(void)
{
    char tabname[40];
    char tabtype[40];
    char tabowner[40];
    SQLLEN tabnameOut, tabtypeOut, tabownerOut;
    char *buf;
    int buflen, cx;
    int truevalue = SQL_TRUE;

/*
SQLSetConnectAttr(hdbc, SQL_ATTR_METADATA_ID,
&truevalue, SQL_IS_INTEGER);
*/

    newStatement();
    stmt_text = "get tables";
    debugStatement();
    rc = SQLTables(hstmt,
       NULL, SQL_NTS, NULL, SQL_NTS, NULL, SQL_NTS, NULL, SQL_NTS);
    if(rc)
	goto abort;

    SQLBindCol(hstmt, 2, SQL_CHAR, (SQLPOINTER) tabowner, sizeof (tabowner),
       &tabownerOut);
    SQLBindCol(hstmt, 3, SQL_CHAR, (SQLPOINTER) tabname, sizeof (tabname),
       &tabnameOut);
    SQLBindCol(hstmt, 4, SQL_CHAR, (SQLPOINTER) tabtype, sizeof (tabtype),
       &tabtypeOut);

    buf = initString(&buflen);
    while(SQLFetch(hstmt) == SQL_SUCCESS) {
	char tabline[140];
	sprintf(tabline, "%s.%s|%s\n", tabowner, tabname, tabtype);
	stringAndString(&buf, &buflen, tabline);
    }

    cx = sideBuffer(0, buf, buflen, 0, false);
    nzFree(buf);
    i_printf(MSG_ShowTables, cx);
    SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
    return true;

  abort:
    SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
    return false;
}				/* showTables */
Ejemplo n.º 13
0
static void acceptCookie(struct cookie *c)
{
	struct cookie *d;
	displacedCookie = false;
	foreach(d, cookies) {
		if (stringEqualCI(d->name, c->name) &&
		    stringEqualCI(d->domain, c->domain)) {
			displacedCookie = true;
			delFromList(d);
			freeCookie(d);
			nzFree(d);
			break;
		}
	}
	addToListBack(&cookies, c);
}				/* acceptCookie */
Ejemplo n.º 14
0
/* Javascript has changed an input field */
static void javaSetsTagVar(jsobjtype v, const char *newtext)
{
	struct inputChange *ic;
	struct htmlTag *t = tagFromJavaVar(v);
	if (!t)
		return;
	if (t->itype == INP_HIDDEN || t->itype == INP_RADIO
	    || t->itype == INP_FILE)
		return;
	if (t->itype == INP_TA) {
		debugPrint(3, "textarea.value is being updated");
		return;
	}
	nzFree(t->value);
	t->value = cloneString(newtext);
}				/* javaSetsTagVar */
Ejemplo n.º 15
0
void scanMail(void)
{
	int nmsgs, m;

	if (!isInteractive)
		i_printfExit(MSG_FetchNotBackgnd);
	if (!mailDir)
		i_printfExit(MSG_NoMailDir);
	if (chdir(mailDir))
		i_printfExit(MSG_NoDirChange, mailDir);

	if (!umf) {
		umf = allocMem(strlen(mailUnread) + 12);
		sprintf(umf, "%s/", mailUnread);
		umf_end = umf + strlen(umf);
	}

/* How many mail messages? */
	unreadBase = 0;
	unreadStats();
	nmsgs = unreadCount;
	if (!nmsgs) {
		i_puts(MSG_NoMail);
		exit(0);
	}
	i_printf(MSG_MessagesX, nmsgs);

	loadAddressBook();

	for (m = 1; m <= nmsgs; ++m) {
		nzFree(lastMailText);
		lastMailText = 0;
/* Now grab the entire message */
		unreadStats();
		sprintf(umf_end, "%d", unreadMin);
		if (!fileIntoMemory(umf, &mailstring, &mailstring_l))
			showErrorAbort();
		unreadBase = unreadMin;

		if (presentMail() == 1)
			unlink(umf);
	}			/* loop over mail messages */

	exit(0);
}				/* scanMail */
Ejemplo n.º 16
0
/* Pass the return value of the script back as a string. */
char *jsRunScriptResult(jsobjtype obj, const char *str, const char *filename,
			int lineno)
{
	int rc;
	char *s;

	if (!allowJS || !cw->winobj || !obj)
		return 0;

	if (!str || !str[0])
		return 0;

	debugPrint(5, "> script:");
	debugPrint(6, "%s", str);

	head.cmd = EJ_CMD_SCRIPT;
	head.obj = obj;		/* this, in js */
	head.proplength = strlen(str);
	head.lineno = lineno;
	if (writeHeader())
		return 0;
/* and send the script to execute */
	if (writeToJS(str, head.proplength))
		return 0;
	jsSourceFile = filename;
	rc = readMessage();
	jsSourceFile = 0;
	if (rc)
		return 0;
	ack5();

	s = propval;
	propval = 0;

	if (head.n) {		/* a real result */
		if (!s)
			s = emptyString;
	} else {
		nzFree(s);
		s = 0;
	}
	return s;
}				/* jsRunScriptResult */
Ejemplo n.º 17
0
/* call javascript function with arguments, but all args must be objects */
static int run_function(jsobjtype obj, const char *name, int argc,
			const jsobjtype * argv)
{
	int rc;
	propval = 0;		/* should already be 0 */
	if (!allowJS || !cw->winobj || !obj)
		return -1;

	debugPrint(5, "> call %s(%d)", name, argc);

	if (argc) {
		int i, l;
		char oval[20];
		propval = initString(&l);
		for (i = 0; i < argc; ++i) {
			sprintf(oval, "%p|", argv[i]);
			stringAndString(&propval, &l, oval);
		}
	}

	head.cmd = EJ_CMD_CALL;
	head.n = strlen(name);
	head.obj = obj;
	head.proplength = 0;
	if (propval)
		head.proplength = strlen(propval);
	if (writeHeader())
		return -1;
	if (writeToJS(name, head.n))
		return -1;
	if (propval) {
		rc = writeToJS(propval, head.proplength);
		nzFree(propval);
		propval = 0;
		if (rc)
			return -1;
	}
	if (readMessage())
		return -1;
	ack5();
	return 0;
}				/* run_function */
Ejemplo n.º 18
0
/* Return 0 if there was no need to encode */
static char *isoEncode(char *start, char *end)
{
	int nacount = 0, count = 0, len;
	char *s, *t;
	char c, code;

	for (s = start; s < end; ++s) {
		c = *s;
		if (c == 0)
			*s = ' ';
		if (isspaceByte(c))
			*s = ' ';
	}

	for (s = start; s < end; ++s) {
		c = *s;
		++count;
		if (!isprintByte(c) && c != ' ')
			++nacount;
	}

	if (!nacount)
		return 0;

	if (nacount * 4 >= count && count > 8) {
		code = 'B';
		s = base64Encode(start, end - start, false);
		goto package;
	}

	code = 'Q';
	s = qpEncode(start);

package:
	len = strlen(s);
	t = allocMem(len + 20);
	sprintf(t, "=?ISO-8859-1?%c?%s?=", code, s);
	nzFree(s);
	return t;
}				/* isoEncode */
Ejemplo n.º 19
0
/* If debug is at least 5, show a simple acknowledgement or error
 * from the js process. */
static void ack5(void)
{
	char *a;
	int a_l;
	char buf[32];
	if (debugLevel < 5)
		return;
	a = initString(&a_l);
	stringAndChar(&a, &a_l, '<');
	if (head.highstat) {
		sprintf(buf, " error %d|%d", head.highstat, head.lowstat);
		stringAndString(&a, &a_l, buf);
	}
	stringAndChar(&a, &a_l, ' ');
	if (propval)
		stringAndString(&a, &a_l, debugString(propval));
	else if (head.cmd == EJ_CMD_HASPROP)
		stringAndNum(&a, &a_l, head.proptype);
	else
		stringAndString(&a, &a_l, "ok");
	debugPrint(5, "%s", a);
	nzFree(a);
}				/* ack5 */
Ejemplo n.º 20
0
void run_function_objargs(jsobjtype obj, const char *name, int nargs, ...)
{
/* lazy, limit of 20 args */
	jsobjtype argv[20];
	int i;
	va_list p;

	if (nargs > 20) {
		puts("more than 20 args to a javascript function");
		return;
	}

	va_start(p, nargs);
	for (i = 0; i < nargs; ++i)
		argv[i] = va_arg(p, jsobjtype);
	va_end(p);

	run_function(obj, name, nargs, argv);

/* return is thrown away; this is a void function */
	nzFree(propval);
	propval = 0;
}				/* run_function_objargs */
Ejemplo n.º 21
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 */
Ejemplo n.º 22
0
/* like the above but throw away the result */
void jsRunScript(jsobjtype obj, const char *str, const char *filename,
		 int lineno)
{
	char *s = jsRunScriptResult(obj, str, filename, lineno);
	nzFree(s);
}				/* jsRunScript */
Ejemplo n.º 23
0
/* some compilers care whether it's void * or const void * */
void cnzFree(const void *v)
{
	nzFree((void *)v);
}				/* cnzFree */
Ejemplo n.º 24
0
/* Returns number of messages fetched */
int fetchMail(int account)
{
	const struct MACCOUNT *a = accounts + account - 1;
	const char *login = a->login;
	const char *pass = a->password;
	int nfetch = 0;		/* number of messages actually fetched */
	CURLcode res_curl = CURLE_OK;
	char *mailbox_url = get_mailbox_url(a);
	const char *url_for_error = mailbox_url;
	char *message_url = NULL;
	int message_count = 0, message_number;

	if (!mailDir)
		i_printfExit(MSG_NoMailDir);
	if (chdir(mailDir))
		i_printfExit(MSG_NoDirChange, mailDir);

	if (!umf) {
		umf = allocMem(strlen(mailUnread) + 12);
		sprintf(umf, "%s/", mailUnread);
		umf_end = umf + strlen(umf);
	}
	unreadBase = 0;
	unreadStats();

	mailstring = initString(&mailstring_l);
	CURL *mail_handle = newFetchmailHandle(mailbox_url, login, pass);
	res_curl = count_messages(mail_handle, mailbox_url, &message_count);
	if (res_curl != CURLE_OK)
		goto fetchmail_cleanup;

	for (message_number = 1; message_number <= message_count;
	     message_number++) {
		if (asprintf(&message_url, "%s%u", mailbox_url, message_number)
		    == -1) {
/* Again, the byte count in the error message is a bit of a fib. */
			i_printfExit(MSG_MemAllocError,
				     strlen(mailbox_url) + 11);
		}
		nzFree(mailstring);
		mailstring = initString(&mailstring_l);
		res_curl =
		    fetchOneMessage(mail_handle, message_url, message_number);
		if (res_curl != CURLE_OK)
			goto fetchmail_cleanup;
		nfetch++;
		res_curl = deleteOneMessage(mail_handle, message_url);
		if (res_curl != CURLE_OK)
			goto fetchmail_cleanup;
		nzFree(message_url);
		message_url = NULL;
	}

fetchmail_cleanup:
	if (message_url)
		url_for_error = message_url;
	if (res_curl != CURLE_OK) {
		ebcurl_setError(res_curl, url_for_error);
		showError();
	}
	curl_easy_cleanup(mail_handle);
	nzFree(message_url);
	nzFree(mailbox_url);
	nzFree(mailstring);
	mailstring = initString(&mailstring_l);
	return nfetch;
}				/* fetchMail */
Ejemplo n.º 25
0
/* Let's jump right into it - parse a cookie, as received from a website. */
bool receiveCookie(const char *url, const char *str)
{
	struct cookie *c;
	const char *p, *q, *server;
	char *date, *s;

	debugPrint(3, "cookie %s", str);

	server = getHostURL(url);
	if (server == 0 || !*server)
		return false;

/* Cookie starts with name=value.  If we can't get that, go home. */
	for (p = str; *p != ';' && *p; p++) ;
	for (q = str; *q != '='; q++)
		if (!*q || q >= p)
			return false;
	if (str == q)
		return false;

	c = allocZeroMem(sizeof(struct cookie));
	c->tail = false;
	c->name = pullString1(str, q);
	++q;
	if (p - q > 0)
		c->value = pullString1(q, p);
	else
		c->value = emptyString;

	c->server = cloneString(server);

	if (date = extractHeaderParam(str, "expires")) {
		c->expires = parseHeaderDate(date);
		nzFree(date);
	} else if (date = extractHeaderParam(str, "max-age")) {
		int n = stringIsNum(date);
		if (n >= 0) {
			time_t now = time(0);
			c->expires = now + n;
		}
		nzFree(date);
	}

	c->path = extractHeaderParam(str, "path");
	if (!c->path) {
/* The url indicates the path for this cookie, if a path is not explicitly given */
		const char *dir, *dirend;
		getDirURL(url, &dir, &dirend);
		c->path = pullString1(dir, dirend);
	} else {
		if (!c->path[0] || c->path[strlen(c->path) - 1] != '/')
			c->path = appendString(c->path, "/");
		if (c->path[0] != '/')
			c->path = prependString(c->path, "/");
	}

	if (!(c->domain = extractHeaderParam(str, "domain"))) {
		c->domain = cloneString(server);
	} else {
/* Is this safe for tail-matching? */
		const char *domtemp = c->domain;
		if (domtemp[0] == '.')
			domtemp++;
		if (!domainSecurityCheck(server, domtemp)) {
			nzFree(c->domain);
			c->domain = cloneString(server);
		} else {
/* It's safe to do tail-matching with this domain. */
			c->tail = true;
/* Guarantee that it does in fact start with dot, prepending if necessary.. */
			if (c->domain[0] != '.')
				c->domain = prependString(c->domain, ".");
		}
	}

	if (s = extractHeaderParam(str, "secure")) {
		c->secure = true;
		nzFree(s);
	}

	cookieForLibcurl(c);
	freeCookie(c);
	nzFree(c);
	return true;
}				/* receiveCookie */
Ejemplo n.º 26
0
static bool
sendMailSMTP(const struct MACCOUNT *account, const char *reply,
	     const char **recipients, const char *message)
{
	CURLcode res = CURLE_OK;
	bool smtp_success = false;
	char *smtp_url = buildSMTPURL(account);
	struct curl_slist *recipient_slist = buildRecipientSList(recipients);
	struct smtp_upload upload = {
		.data = message,.length = strlen(message),.pos = 0
	};
	CURL *handle =
	    newSendmailHandle(account, smtp_url, reply, recipient_slist);

	if (!handle)
		goto smtp_cleanup;

	curl_easy_setopt(handle, CURLOPT_READFUNCTION, smtp_upload_callback);
	curl_easy_setopt(handle, CURLOPT_READDATA, &upload);
	curl_easy_setopt(handle, CURLOPT_UPLOAD, 1L);

	res = curl_easy_perform(handle);
	if (res == CURLE_OK)
		smtp_success = true;

smtp_cleanup:
	if (res != CURLE_OK)
		ebcurl_setError(res, smtp_url);
	if (handle)
		curl_easy_cleanup(handle);
	curl_slist_free_all(recipient_slist);
	nzFree(smtp_url);
	return smtp_success;
}				/* sendMailSMTP */

/* Send mail to the smtp server. */
bool
sendMail(int account, const char **recipients, const char *body,
	 int subjat, const char **attachments, const char *refline,
	 int nalt, bool dosig)
{
	char *from, *fromiso, *reply, *login, *smlogin, *pass;
	const struct MACCOUNT *a, *ao, *localMail;
	const char *s, *boundary;
	char reccc[MAXRECAT];
	char *t;
	int nat, cx, i, j;
	char *out = 0;
	bool sendmail_success = false;
	bool mustmime = false;
	bool firstgreet = true;
	bool firstrec;
	const char *ct, *ce;
	char *encoded = 0;

	if (!validAccount(account))
		return false;
	mailAccount = account;
	localMail = accounts + localAccount - 1;

	a = accounts + account - 1;
	from = a->from;
	reply = a->reply;
	ao = a->outssl ? a : localMail;
	doSignature = dosig;

	nat = 0;		/* number of attachments */
	if (attachments) {
		while (attachments[nat])
			++nat;
	}
	if (nat)
		mustmime = true;
	if (nalt && nalt < nat) {
		setError(MSG_AttAlternate);
		return false;
	}

	if (!loadAddressBook())
		return false;

/* set copy flags */
	for (j = 0; s = recipients[j]; ++j) {
		char cc = 0;
		if (*s == '^' || *s == '?')
			cc = *s++;
		if (j == MAXRECAT) {
			setError(MSG_RecipMany, MAXRECAT);
			return false;
		}
		recipients[j] = s;
		reccc[j] = cc;
	}

/* Look up aliases in the address book */
	for (j = 0; s = recipients[j]; ++j) {
		if (strchr(s, '@'))
			continue;
		t = 0;
		for (i = 0; i < nads; ++i) {
			const char *a = addressList[i].name;
			if (*a == '-' || *a == '!')
				++a;
			if (!stringEqual(s, a))
				continue;
			t = addressList[i].email;
			debugPrint(3, " %s becomes %s", s, t);
			break;
		}
		if (t) {
			recipients[j] = t;
			continue;
		}
		if (!addressFile) {
			setError(MSG_ABMissing);
			return false;
		}
		setError(MSG_ABNoAlias2, s);
		return false;
	}			/* recipients */

	if (!j) {
		setError(MSG_RecipNone);
		return false;
	}

/* verify attachments are readable */
	for (j = 0; s = attachments[j]; ++j) {
		if (!ismc && (cx = stringIsNum(s)) >= 0) {
			if (!cxCompare(cx) || !cxActive(cx))
				return false;
			if (!sessionList[cx].lw->dol) {
				setError(MSG_AttSessionEmpty, cx);
				return false;
			}
		} else {
			char ftype = fileTypeByName(s, false);
			if (!ftype) {
				setError(MSG_AttAccess, s);
				return false;
			}
			if (ftype != 'f') {
				setError(MSG_AttRegular, s);
				return false;
			}
			if (!fileSizeByName(s)) {
				setError(MSG_AttEmpty2, s);
				return false;
			}
		}
	}			/* loop over attachments */

	if (!encodeAttachment(body, subjat, false, &ct, &ce, &encoded))
		return false;
	if (ce[0] == 'q')
		mustmime = true;

	boundary = makeBoundary();

/* Build the outgoing mail, as one string. */
	out = initString(&j);

	firstrec = true;
	for (i = 0; s = recipients[i]; ++i) {
		if (reccc[i])
			continue;
		stringAndString(&out, &j, firstrec ? "To:" : ",\r\n  ");
		stringAndString(&out, &j, s);
		firstrec = false;
	}
	if (!firstrec)
		stringAndString(&out, &j, eol);

	firstrec = true;
	for (i = 0; s = recipients[i]; ++i) {
		if (reccc[i] != '^')
			continue;
		stringAndString(&out, &j, firstrec ? "CC:" : ",\r\n  ");
		stringAndString(&out, &j, s);
		firstrec = false;
	}
	if (!firstrec)
		stringAndString(&out, &j, eol);

	firstrec = true;
	for (i = 0; s = recipients[i]; ++i) {
		if (reccc[i] != '?')
			continue;
		stringAndString(&out, &j, firstrec ? "BCC:" : ",\r\n  ");
		stringAndString(&out, &j, s);
		firstrec = false;
	}
	if (!firstrec)
		stringAndString(&out, &j, eol);

	fromiso = isoEncode(from, from + strlen(from));
	if (!fromiso)
		fromiso = from;
	sprintf(serverLine, "From: %s <%s>%s", fromiso, reply, eol);
	stringAndString(&out, &j, serverLine);
	sprintf(serverLine, "Reply-to: %s <%s>%s", fromiso, reply, eol);
	stringAndString(&out, &j, serverLine);
	if (fromiso != from)
		nzFree(fromiso);
	if (refline) {
		s = strchr(refline, '\n');
		if (!s)		/* should never happen */
			s = refline + strlen(refline);
		stringAndBytes(&out, &j, refline, s - refline);
		stringAndString(&out, &j, eol);
	}
	sprintf(serverLine, "User-Agent: %s%s", currentAgent, eol);
	stringAndString(&out, &j, serverLine);
	if (subjectLine[0]) {
		sprintf(serverLine, "Subject: %s%s", subjectLine, eol);
		stringAndString(&out, &j, serverLine);
	}
	sprintf(serverLine,
		"Date: %s%sMessage-ID: <%s.%s>%sMime-Version: 1.0%s",
		mailTimeString(), eol, messageTimeID(), reply, eol, eol);
	stringAndString(&out, &j, serverLine);

	if (!mustmime) {
/* no mime components required, we can just send the mail. */
		sprintf(serverLine,
			"Content-Type: %s%s%sContent-Transfer-Encoding: %s%s%s",
			ct, charsetString(ct, ce), eol, ce, eol, eol);
		stringAndString(&out, &j, serverLine);
	} else {
		sprintf(serverLine,
			"Content-Type: multipart/%s; boundary=%s%sContent-Transfer-Encoding: 7bit%s%s",
			nalt ? "alternative" : "mixed", boundary, eol, eol,
			eol);
		stringAndString(&out, &j, serverLine);
		stringAndString(&out, &j,
				"This message is in MIME format. Since your mail reader does not understand\r\n\
this format, some or all of this message may not be legible.\r\n\r\n--");
		stringAndString(&out, &j, boundary);
		sprintf(serverLine,
			"%sContent-Type: %s%s%sContent-Transfer-Encoding: %s%s%s",
			eol, ct, charsetString(ct, ce), eol, ce, eol, eol);
		stringAndString(&out, &j, serverLine);
	}

/* Now send the body, line by line. */
	appendAttachment(encoded, &out, &j);
	nzFree(encoded);
	encoded = 0;

	if (mustmime) {
		for (i = 0; s = attachments[i]; ++i) {
			if (!encodeAttachment
			    (s, 0, false, &ct, &ce, &encoded))
				return false;
			sprintf(serverLine, "%s--%s%sContent-Type: %s%s", eol,
				boundary, eol, ct, charsetString(ct, ce));
			stringAndString(&out, &j, serverLine);
/* If the filename has a quote in it, forget it. */
/* Also, suppress filename if this is an alternate presentation. */
			if (!nalt && !strchr(s, '"')
			    && (ismc || stringIsNum(s) < 0)) {
				sprintf(serverLine, "; name=\"%s\"", s);
				stringAndString(&out, &j, serverLine);
			}
			sprintf(serverLine,
				"%sContent-Transfer-Encoding: %s%s%s", eol, ce,
				eol, eol);
			stringAndString(&out, &j, serverLine);
			appendAttachment(encoded, &out, &j);
			nzFree(encoded);
			encoded = 0;
		}		/* loop over attachments */

/* The last boundary */
		sprintf(serverLine, "%s--%s--%s", eol, boundary, eol);
		stringAndString(&out, &j, serverLine);
	}

	/* mime format */

	sendmail_success = sendMailSMTP(ao, reply, recipients, out);
	nzFree(out);
	return sendmail_success;
}				/* sendMail */
Ejemplo n.º 27
0
/* read and/or refresh the address book */
bool loadAddressBook(void)
{
	char *buf, *bufend, *v, *last, *s, *t;
	bool cmt = false;
	char state = 0, c;
	int j, buflen, ln = 1;
	time_t mtime;

	if (!addressFile ||
	    (mtime = fileTimeByName(addressFile)) == -1 || mtime <= adbooktime)
		return true;

	debugPrint(3, "loading address book");
	nzFree(addressList);
	addressList = 0;
	nads = 0;
	if (!fileIntoMemory(addressFile, &buf, &buflen))
		return false;
	bufend = buf + buflen;

	for (s = t = last = buf; s < bufend; ++s) {
		c = *s;
		if (cmt) {
			if (c != '\n')
				continue;
			cmt = false;
		}
		if (c == ':') {	/* delimiter */
			if (state == 0) {
				setError(MSG_ABNoAlias, ln);
freefail:
				nzFree(buf);
				nads = 0;
				return false;
			}
			while (t[-1] == ' ' || t[-1] == '\t')
				--t;
			if (state == 1) {
				*t++ = c;
				state = 2;
				continue;
			}
			c = '#';	/* extra fields are ignored */
		}		/* : */
		if (c == '#') {
			cmt = true;
			continue;
		}
		if (c == '\n') {
			++ln;
			if (state == 0)
				continue;
			if (state == 1) {
				setError(MSG_ABNoColon, ln - 1);
				goto freefail;
			}
			if (state == 3) {
				++nads;
				while (isspaceByte(t[-1]))
					--t;
				*t = 0;
				v = strchr(last, ':');
				if (v - last >= 16) {
					setError(MSG_ABAliasLong, ln - 1);
					goto freefail;
				}
				++v;
				if (t - v >= 64) {
					setError(MSG_ABMailLong, ln - 1);
					goto freefail;
				}
				if (!strchr(v, '@')) {
					setError(MSG_ABNoAt, ln - 1);
					goto freefail;
				}
				if (strpbrk(v, " \t")) {
					setError(MSG_ABMailSpaces, ln - 1);
					goto freefail;
				}

				while (last < t) {
					if (!isprintByte(*last)) {
						setError(MSG_AbMailUnprintable,
							 ln - 1);
						goto freefail;
					}
					++last;
				}
				*t++ = c;
			} else
				t = last;	/* back it up */
			last = t;
			state = 0;
			continue;
		}
		/* nl */
		if ((c == ' ' || c == '\t') && (state == 0 || state == 2))
			continue;
		if (state == 0)
			state = 1;
		if (state == 2)
			state = 3;
		*t++ = c;
	}

	*t = 0;
	if (state) {
		setError(MSG_ABUnterminated);
		goto freefail;
	}

	if (nads) {
		addressList = allocMem(nads * sizeof(struct ALIAS));
		j = 0;
		for (s = buf; *s; s = t + 1, ++j) {
			t = strchr(s, ':');
			memcpy(addressList[j].name, s, t - s);
			addressList[j].name[t - s] = 0;
			s = t + 1;
			t = strchr(s, '\n');
			memcpy(addressList[j].email, s, t - s);
			addressList[j].email[t - s] = 0;
		}
	}
	/* aliases are present */
	nzFree(buf);
	adbooktime = mtime;
	return true;
}				/* loadAddressBook */
Ejemplo n.º 28
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 */
Ejemplo n.º 29
0
/* Return 0 for ok, 1 to delete the mail, -1 to stop.
 * stop is only meaningful for imap. */
static int presentMail(void)
{
	int j, k;
	const char *redirect = NULL;	/* send mail elsewhere */
	char key = 0;
	const char *atname = NULL;	/* name of file or attachment */
	bool delflag = false;	/* delete this mail */
	bool scanat = false;	/* scan for attachments */
	int displine;
	int stashNumber = -1;

/* clear things out from the last message */
	if (lastMailInfo)
		freeMailInfo(lastMailInfo);
	lastMailInfo = 0;

	if (sessionList[1].lw)
		cxQuit(1, 2);
	cs = 0;
	cxSwitch(1, false);

	iuReformat(mailstring, mailstring_l, &mailu8, &mailu8_l);
	if (mailu8) {
		if (!addTextToBuffer((pst) mailu8, mailu8_l, 0, false))
			showErrorAbort();
	} else {
		if (!addTextToBuffer((pst) mailstring, mailstring_l, 0, false))
			showErrorAbort();
	}

	browseCurrentBuffer();

	if (!passMail) {
		redirect = mailRedirect(lastMailInfo->to,
					lastMailInfo->from,
					lastMailInfo->reply,
					lastMailInfo->subject);
	}

	if (redirect) {
		if (!isimap) {
			delflag = true;
			key = 'w';
			if (*redirect == '-')
				++redirect, key = 'u';
			if (stringEqual(redirect, "x"))
				i_puts(MSG_Junk);
			else
				printf("> %s\n", redirect);
		} else {
			if (*redirect == '-')
				++redirect;
			if (stringEqual(redirect, "x"))
				redirect = NULL;
		}
	}

/* display the next page of mail and get a command from the keyboard */
	displine = 1;
paging:
	if (!delflag) {		/* show next page */
		if (displine <= cw->dol) {
			for (j = 0; j < 20 && displine <= cw->dol;
			     ++j, ++displine) {
				char *showline = (char *)fetchLine(displine, 1);
				k = pstLength((pst) showline);
				showline[--k] = 0;
				printf("%s\n", showline);
				nzFree(showline);
			}
		}
	}

/* get key command from user */
key_command:
	if (delflag)
		goto writeMail;

/* interactive prompt depends on whether there is more text or not */
	printf("%c ", displine > cw->dol ? '?' : '*');
	fflush(stdout);
	key = getLetter((isimap ? "q? nwWuUasd" : "q? nwud"));
	printf("\b\b\b");
	fflush(stdout);

	switch (key) {
	case 'q':
		i_puts(MSG_Quit);
		exit(0);

	case 'n':
		i_puts(MSG_Next);
		goto afterinput;

	case 's':
		i_puts(MSG_Stop);
		goto afterinput;

	case 'd':
		i_puts(MSG_Delete);
		delflag = true;
		goto afterinput;

	case ' ':
		if (displine > cw->dol)
			i_puts(MSG_EndMessage);
		goto paging;

	case '?':
		i_puts(isimap ? MSG_ImapReadHelp : MSG_MailHelp);
		goto key_command;

	case 'a':
		key = 'w';	/* this will scan attachments */
		scanat = true;

	case 'w':
	case 'W':
	case 'u':
	case 'U':
		break;

	default:
		i_puts(MSG_NYI);
		goto key_command;
	}			/* switch */

/* At this point we're saving the mail somewhere. */
writeMail:
	if (!isimap || isupper(key))
		delflag = true;
	atname = 0;
	if (!isimap)
		atname = redirect;

	if (scanat)
		goto attachOnly;

saveMail:
	if (!atname)
		atname = getFileName(MSG_FileName, redirect, false, false);
	if (stringEqual(atname, "x"))
		goto afterinput;

	char exists = fileTypeByName(atname, false);
	int fsize;		/* file size */
	int fh = open(atname, O_WRONLY | O_TEXT | O_CREAT | O_APPEND, 0666);
	if (fh < 0) {
		i_printf(MSG_NoCreate, atname);
		goto saveMail;
	}
	if (exists)
		write(fh,
		      "======================================================================\n",
		      71);
	if (key == 'u') {
		if (write(fh, mailstring, mailstring_l) < mailstring_l) {
badsave:
			i_printf(MSG_NoWrite, atname);
			close(fh);
			goto saveMail;
		}
		close(fh);
		fsize = mailstring_l;
	} else {

/* key = w, write the file - if pop then save the original unformatted */
		if (!isimap && mailStash) {
			char *rmf;	/* raw mail file */
			int rmfh;	/* file handle to same */
/* I want a fairly easy filename, in case I want to go look at the original.
* Not a 30 character message ID that I am forced to cut&paste.
* 4 or 5 digits would be nice.
* So the filename looks like /home/foo/.Trash/rawmail/36921
* I pick the digits randomly.
* Please don't accumulate 100,000 emails before you empty your trash.
* It's good to have a cron job empty the trash early Sunday morning.
*/

			k = strlen(mailStash);
			rmf = allocMem(k + 12);
/* Try 20 times, then give up. */
			for (j = 0; j < 20; ++j) {
				int rn = rand() % 100000;	/* random number */
				sprintf(rmf, "%s/%05d", mailStash, rn);
				if (fileTypeByName(rmf, false))
					continue;
/* dump the original mail into the file */
				rmfh =
				    open(rmf,
					 O_WRONLY | O_TEXT | O_CREAT | O_APPEND,
					 0666);
				if (rmfh < 0)
					break;
				if (write(rmfh, mailstring, mailstring_l) <
				    mailstring_l) {
					close(rmfh);
					unlink(rmf);
					break;
				}
				close(rmfh);
/* written successfully, remember the stash number */
				stashNumber = rn;
				break;
			}
		}

		fsize = 0;
		for (j = 1; j <= cw->dol; ++j) {
			char *showline = (char *)fetchLine(j,
							   1);
			int len = pstLength((pst)
					    showline);
			if (write(fh, showline, len) < len)
				goto badsave;
			nzFree(showline);
			fsize += len;
		}		/* loop over lines */

		if (stashNumber >= 0) {
			char addstash[60];
			sprintf(addstash, "\nUnformatted %05d\n", stashNumber);
			k = strlen(addstash);
			if (write(fh, addstash, k) < k)
				goto badsave;
			fsize += k;
		}

		close(fh);

attachOnly:

		if (nattach)
			writeAttachments(lastMailInfo);
		else if (scanat)
			i_puts(MSG_NoAttachments);
	}			/* unformat or format */

	if (scanat)
		goto afterinput;
/* print "mail saved" message */
	i_printf(MSG_MailSaved, fsize);
	if (exists)
		i_printf(MSG_Appended);
	nl();

afterinput:
	nzFree(mailstring);
	mailstring = 0;
	nzFree(mailu8);
	mailu8 = 0;

	if (delflag)
		return 1;
	if (key == 's')
		return -1;
	return 0;
}				/* presentMail */
Ejemplo n.º 30
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 */