示例#1
0
/* start a document.write */
void dwStart(void)
{
	if (cw->dw)
		return;
	cw->dw = initString(&cw->dw_l);
	stringAndString(&cw->dw, &cw->dw_l, "<!DOCTYPE public><body>");
}				/* dwStart */
示例#2
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 */
示例#3
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 */
示例#4
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 */
示例#5
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 */
示例#6
0
static char *qpEncode(const char *line)
{
	char *newbuf;
	int l;
	const char *s;
	char c;

	newbuf = initString(&l);
	for (s = line; (c = *s); ++s) {
		if (c < '\n' && c != '\t' || c == '=') {
			char expand[4];
			sprintf(expand, "=%02X", (uchar) c);
			stringAndString(&newbuf, &l, expand);
		} else {
			stringAndChar(&newbuf, &l, c);
		}
	}

	return newbuf;
}				/* qpEncode */
示例#7
0
static void appendAttachment(const char *s, char **out, int *l)
{
	const char *t;
	int n;
	while (*s) {		/* another line */
		t = strchr(s, '\n');
		if (!t)
			t = s + strlen(s);
		n = t - s;
		if (t[-1] == '\r')
			--n;
		if (n)
			memcpy(serverLine, s, n);
		serverLine[n] = 0;
		strcat(serverLine, eol);
		stringAndString(out, l, serverLine);
		if (*t)
			++t;
		s = t;
	}
/* Small bug here - an attachment that is not base64 encoded,
 * and had no newline at the end, now has one. */
}				/* appendAttachment */
示例#8
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 */
示例#9
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 */
示例#10
0
static void processEffects(void)
{
	char *s, *t, *v;
	char c;
	jsobjtype p;
	int n;
	struct inputChange *ic;

	if (!effects)
		return;

	s = effects;
	while (c = *s) {	/* another effect */
		s += 2;
		v = strstr(s, "`~@}");	/* end marker */
/* There should always be an end marker -
 * unless there is a spurious null in the string. */
		if (!v)
			break;
		*v = 0;

		switch (c) {
		case 'w':	/* document.write */
			dwStart();
			stringAndString(&cw->dw, &cw->dw_l, s);
			break;

		case 'n':	/* new window */
/* url on one line, name of window on next line */
			t = strchr(s, '\n');
			*t = 0;
			javaOpensWindow(s, t + 1);
			break;

		case 'v':	/* value = "foo" */
			t = strchr(s, '=');
			*t++ = 0;
			sscanf(s, "%p", &p);
			prepareForField(t);
			javaSetsTagVar(p, t);
			break;

		case 't':	/* js timer */
			n = strtol(s, &t, 10);
			s = t + 1;
			t = strchr(s, '|');
			*t++ = 0;
			v[-2] = 0;
			sscanf(t, "%p", &p);
			ic = allocMem(sizeof(struct inputChange) + strlen(s));
// Yeah I know, this isn't a pointer to htmlTag.
			ic->t = p;
			ic->tagno = n;
			ic->major = 't';
			ic->minor = v[-1];
			strcpy(ic->value, s);
			addToListBack(&inputChangesPending, ic);
			break;

		case 'c':	/* cookie */
/* Javascript does some modest syntax checking on the cookie before
 * passing it back to us, so I'm just going to assume it works. */
			receiveCookie(cw->fileName, s);
			break;

		case 'f':
			c = *s++;
			sscanf(s, "%p", &p);
			javaSubmitsForm(p, (c == 'r'));
			break;

		case 'i':
			c = *s++;
/* h = inner html, t = inner text */
			t = strchr(s, '|');
			*t++ = 0;
			sscanf(s, "%p", &p);
			javaSetsInner(p, t, c);
			break;

		case 'l':
			c = *s;
			s += 2;
			sscanf(s, "%p", &p);
			s = strchr(s, ',') + 1;
			javaSetsLinkage(false, c, p, s);
			break;

		}		/* switch */

/* skip past end marker + newline */
		s = v + 5;
	}			/* loop over effects */

	free(effects);
	effects = 0;
}				/* processEffects */