Esempio n. 1
0
static void
vxp_quote(const struct vxp *vxp, const char *b, const char *e, int tokoff)
{
	const char *p;
	char c;

	assert(b <= e);
	assert(b >= vxp->b);
	assert(e <= vxp->e);
	for (p = vxp->b; p < vxp->e; p++) {
		if (isspace(*p))
			VSB_bcat(vxp->sb, " ", 1);
		else
			VSB_bcat(vxp->sb, p, 1);
	}
	VSB_putc(vxp->sb, '\n');
	for (p = vxp->b; p < vxp->e; p++) {
		if (p >= b && p < e) {
			if (p - b == tokoff)
				c = '^';
			else
				c = '#';
		} else
			c = '-';
		VSB_putc(vxp->sb, c);
	}
	VSB_putc(vxp->sb, '\n');
}
Esempio n. 2
0
int
vtc_send_proxy(int fd, int version, const struct suckaddr *sac,
    const struct suckaddr *sas)
{
	struct vsb *vsb;
	char hc[VTCP_ADDRBUFSIZE];
	char pc[VTCP_PORTBUFSIZE];
	char hs[VTCP_ADDRBUFSIZE];
	char ps[VTCP_PORTBUFSIZE];
	int i, len;
	int proto;

	AN(sac);
	AN(sas);

	assert(version == 1 || version == 2);
	vsb = VSB_new_auto();
	AN(vsb);

	proto = VSA_Get_Proto(sas);
	assert(proto == PF_INET6 || proto == PF_INET);

	if (version == 1) {
		VSB_bcat(vsb, vpx1_sig, sizeof(vpx1_sig));
		if (proto == PF_INET6)
			VSB_printf(vsb, " TCP6 ");
		else if (proto == PF_INET)
			VSB_printf(vsb, " TCP4 ");
		VTCP_name(sac, hc, sizeof(hc), pc, sizeof(pc));
		VTCP_name(sas, hs, sizeof(hs), ps, sizeof(ps));
		VSB_printf(vsb, "%s %s %s %s\r\n", hc, hs, pc, ps);
	} else if (version == 2) {
		VSB_bcat(vsb, vpx2_sig, sizeof(vpx2_sig));
		VSB_putc(vsb, 0x21);
		if (proto == PF_INET6) {
			VSB_putc(vsb, 0x21);
			VSB_putc(vsb, 0x00);
			VSB_putc(vsb, 0x24);
		} else if (proto == PF_INET) {
			VSB_putc(vsb, 0x11);
			VSB_putc(vsb, 0x00);
			VSB_putc(vsb, 0x0c);
		}
		vpx_enc_addr(vsb, proto, sac);
		vpx_enc_addr(vsb, proto, sas);
		vpx_enc_port(vsb, sac);
		vpx_enc_port(vsb, sas);
	} else
		WRONG("Wrong proxy version");

	AZ(VSB_finish(vsb));
	len = VSB_len(vsb);
	i = write(fd, VSB_data(vsb), len);
	VSB_delete(vsb);
	return (i != len);
}
Esempio n. 3
0
static void
ban_add_lump(const struct ban_proto *bp, const void *p, uint32_t len)
{
	uint8_t buf[sizeof len];

	buf[0] = 0xff;
	while (VSB_len(bp->vsb) & PALGN)
		VSB_putc(bp->vsb, buf[0]);
	vbe32enc(buf, len);
	VSB_bcat(bp->vsb, buf, sizeof buf);
	VSB_bcat(bp->vsb, p, len);
}
Esempio n. 4
0
static void
cmd_http_chunkedlen(CMD_ARGS)
{
	unsigned len;
	unsigned u, v;
	char buf[16384];
	struct http *hp;

	(void)cmd;
	(void)vl;
	CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
	AN(av[1]);
	AZ(av[2]);
	VSB_clear(hp->vsb);

	len = atoi(av[1]);

	if (len == 0) {
		VSB_printf(hp->vsb, "0%s%s", nl, nl);
	} else {
		for (u = 0; u < sizeof buf; u++)
			buf[u] = (u & 7) + '0';

		VSB_printf(hp->vsb, "%x%s", len, nl);
		for (u = 0; u < len; u += v) {
			v = len - u;
			if (v > sizeof buf)
				v = sizeof buf;
			VSB_bcat(hp->vsb, buf, v);
		}
		VSB_printf(hp->vsb, "%s", nl);
	}
	http_write(hp, 4, "chunked");
}
Esempio n. 5
0
void *
vtc_record(struct vtclog *vl, int fd, struct vsb *vsb)
{
	char buf[65536];
	struct pollfd fds[1];
	int i;

	(void)VTCP_nonblocking(fd);
	while (1) {
		memset(fds, 0, sizeof fds);
		fds->fd = fd;
		fds->events = POLLIN;
		i = poll(fds, 1, 10000);
		if (i == 0)
			continue;
		if (fds->revents & POLLIN) {
			i = read(fd, buf, sizeof buf - 1);
			if (i > 0) {
				if (vsb != NULL)
					VSB_bcat(vsb, buf, i);
				buf[i] = '\0';
				vtc_dump(vl, 3, "debug", buf, -2);
			}
		}
		if (fds->revents & (POLLERR|POLLHUP)) {
			vtc_log(vl, 4, "STDOUT poll 0x%x", fds->revents);
			break;
		}
	}
	return (NULL);
}
Esempio n. 6
0
static void
vpx_enc_port(struct vsb *vsb, const struct suckaddr *s)
{
	uint8_t b[2];

	vbe16enc(b, (uint16_t)VSA_Port(s));
	VSB_bcat(vsb, b, sizeof(b));
}
Esempio n. 7
0
static int
vsf_iter_req_body(void *priv, int flush, const void *ptr, ssize_t len)
{
	(void)flush;

	VSB_bcat(priv, ptr, len);
	return (0);
}
Esempio n. 8
0
File: vmod_vsf.c Progetto: aaam/VSF
static int
vsf_iter_req_body(struct req *req, void *priv, void *ptr, size_t len)
{
	(void)req;

	VSB_bcat(priv, ptr, len);
	return (0);
}
Esempio n. 9
0
File: vsb.c Progetto: weongyo/eel
/*
 * Copy a byte string into an vsb.
 */
int
VSB_bcpy(struct vsb *s, const void *buf, size_t len)
{

	assert_VSB_integrity(s);
	assert_VSB_state(s, 0);

	VSB_clear(s);
	return (VSB_bcat(s, buf, len));
}
Esempio n. 10
0
static void
vpx_enc_addr(struct vsb *vsb, int proto, const struct suckaddr *s)
{
	const struct sockaddr_in *sin4;
	const struct sockaddr_in6 *sin6;
	socklen_t sl;

	if (proto == PF_INET6) {
		sin6 = VSA_Get_Sockaddr(s, &sl);	//lint !e826
		AN(sin6);
		assert(sl >= sizeof(*sin6));
		VSB_bcat(vsb, &sin6->sin6_addr, sizeof(sin6->sin6_addr));
	} else {
		sin4 = VSA_Get_Sockaddr(s, &sl);	//lint !e826
		AN(sin4);
		assert(sl >= sizeof(*sin4));
		VSB_bcat(vsb, &sin4->sin_addr, sizeof(sin4->sin_addr));
	}
}
Esempio n. 11
0
static void
vep_emit_verbatim(const struct vep_state *vep, ssize_t l, ssize_t l_crc)
{
	uint8_t buf[4];

	vep_emit_len(vep, l, VEC_V1, VEC_V2, VEC_V8);
	if (vep->dogzip) {
		vep_emit_len(vep, l_crc, VEC_C1, VEC_C2, VEC_C8);
		vbe32enc(buf, vep->crc);
		VSB_bcat(vep->vsb, buf, sizeof buf);
	}
}
Esempio n. 12
0
/*
 * Quote a string
 */
void
VSB_quote(struct vsb *s, const char *p, int len, int how)
{
	const char *q;
	int quote = 0;

	(void)how;	/* For future enhancements */
	if (len == -1)
		len = strlen(p);

	for (q = p; q < p + len; q++) {
		if (!isgraph(*q) || *q == '"' || *q == '\\') {
			quote++;
			break;
		}
	}
	if (!quote) {
		(void)VSB_bcat(s, p, len);
		return;
	}
	(void)VSB_putc(s, '"');
	for (q = p; q < p + len; q++) {
		switch (*q) {
		case ' ':
			(void)VSB_putc(s, *q);
			break;
		case '\\':
		case '"':
			(void)VSB_putc(s, '\\');
			(void)VSB_putc(s, *q);
			break;
		case '\n':
			if (how & VSB_QUOTE_NONL)
				(void)VSB_cat(s, "\n");
			else
				(void)VSB_cat(s, "\\n");
			break;
		case '\r':
			(void)VSB_cat(s, "\\r");
			break;
		case '\t':
			(void)VSB_cat(s, "\\t");
			break;
		default:
			if (isgraph(*q))
				(void)VSB_putc(s, *q);
			else
				(void)VSB_printf(s, "\\%o", *q & 0xff);
			break;
		}
	}
	(void)VSB_putc(s, '"');
}
Esempio n. 13
0
static void
vep_emit_len(const struct vep_state *vep, ssize_t l, int m8, int m16, int m64)
{
	uint8_t buf[9];

	assert(l > 0);
	if (l < 256) {
		buf[0] = (uint8_t)m8;
		buf[1] = (uint8_t)l;
		assert((ssize_t)buf[1] == l);
		VSB_bcat(vep->vsb, buf, 2);
	} else if (l < 65536) {
		buf[0] = (uint8_t)m16;
		vbe16enc(buf + 1, (uint16_t)l);
		assert((ssize_t)vbe16dec(buf + 1) == l);
		VSB_bcat(vep->vsb, buf, 3);
	} else {
		buf[0] = (uint8_t)m64;
		vbe64enc(buf + 1, l);
		assert((ssize_t)vbe64dec(buf + 1) == l);
		VSB_bcat(vep->vsb, buf, 9);
	}
}
static void
vep_emit_verbatim(const struct vep_state *vep, ssize_t l, ssize_t l_crc)
{
	uint8_t buf[4];

	if (params->esi_syntax & 0x20) {
		Debug("---> VERBATIM(%jd)\n", (intmax_t)l);
	}
	vep_emit_len(vep, l, VEC_V1, VEC_V2, VEC_V8);
	if (vep->dogzip) {
		vep_emit_len(vep, l_crc, VEC_C1, VEC_C2, VEC_C8);
		vbe32enc(buf, vep->crc);
		VSB_bcat(vep->vsb, buf, sizeof buf);
	}
}
Esempio n. 15
0
VCL_VOID
vmod_synth(const struct vrt_ctx *ctx, VCL_STRING name, VCL_INT len)
{
	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);

	assert(ctx->method == VCL_MET_SYNTH ||
	    ctx->method == VCL_MET_BACKEND_ERROR);

	if (name == NULL || len <= 0) {
		return;
	}

	CHECK_OBJ_NOTNULL((struct vsb*)ctx->specific, VSB_MAGIC);

	VSB_bcat((struct vsb*)ctx->specific, name, len);
}
Esempio n. 16
0
File: vsb.c Progetto: weongyo/eel
/*
 * Unquote a string
 */
const char *
VSB_unquote(struct vsb *s, const char *p, int len, int how)
{
	const char *q;
	char *r;
	unsigned long u;
	char c;

	(void)how;	/* For future enhancements */

	if (len == -1)
		len = strlen(p);

	for (q = p; q < p + len; q++) {
		if (*q != '\\') {
			(void)VSB_bcat(s, q, 1);
			continue;
		}
		if (++q >= p + len)
			return ("Incomplete '\\'-sequence at end of string");

		switch(*q) {
		case 'n':
			(void)VSB_bcat(s, "\n", 1);
			continue;
		case 'r':
			(void)VSB_bcat(s, "\r", 1);
			continue;
		case 't':
			(void)VSB_bcat(s, "\t", 1);
			continue;
		case '0':
		case '1':
		case '2':
		case '3':
		case '4':
		case '5':
		case '6':
		case '7':
			errno = 0;
			u = strtoul(q, &r, 8);
			if (errno != 0 || (u & ~0xff))
				return ("\\ooo sequence out of range");
			c = (char)u;
			(void)VSB_bcat(s, &c, 1);
			q = r - 1;
			continue;
		default:
			(void)VSB_bcat(s, q, 1);
		}
	}
	return (NULL);
}
Esempio n. 17
0
struct vsb *
macro_expand(struct vtclog *vl, const char *text)
{
	struct vsb *vsb;
	const char *p, *q;
	char *m;

	vsb = VSB_new_auto();
	AN(vsb);
	while (*text != '\0') {
		p = strstr(text, "${");
		if (p == NULL) {
			VSB_cat(vsb, text);
			break;
		}
		VSB_bcat(vsb, text, p - text);
		q = strchr(p, '}');
		if (q == NULL) {
			VSB_cat(vsb, text);
			break;
		}
		assert(p[0] == '$');
		assert(p[1] == '{');
		assert(q[0] == '}');
		p += 2;
		m = macro_get(p, q);
		if (m == NULL) {
			VSB_delete(vsb);
			vtc_log(vl, 0, "Macro ${%.*s} not found", (int)(q - p),
			    p);
			return (NULL);
		}
		VSB_printf(vsb, "%s", m);
		free(m);
		text = q + 1;
	}
	AZ(VSB_finish(vsb));
	return (vsb);
}
Esempio n. 18
0
pan_ic(const char *func, const char *file, int line, const char *cond,
    enum vas_e kind)
{
	const char *q;
	struct req *req;
	struct busyobj *bo;
	struct sigaction sa;
	int err = errno;

	AZ(pthread_mutex_lock(&panicstr_mtx)); /* Won't be released,
						  we're going to die
						  anyway */

	/*
	 * should we trigger a SIGSEGV while handling a panic, our sigsegv
	 * handler would hide the panic, so we need to reset the handler to
	 * default
	 */
	memset(&sa, 0, sizeof sa);
	sa.sa_handler = SIG_DFL;
	(void)sigaction(SIGSEGV, &sa, NULL);
	/* Set SIGABRT back to default so the final abort() has the
	   desired effect */
	(void)sigaction(SIGABRT, &sa, NULL);

	switch(kind) {
	case VAS_WRONG:
		VSB_printf(pan_vsb,
		    "Wrong turn at %s:%d:\n%s\n", file, line, cond);
		break;
	case VAS_VCL:
		VSB_printf(pan_vsb,
		    "Panic from VCL:\n  %s\n", cond);
		break;
	case VAS_MISSING:
		VSB_printf(pan_vsb,
		    "Missing errorhandling code in %s(), %s line %d:\n"
		    "  Condition(%s) not true.",
		    func, file, line, cond);
		break;
	case VAS_INCOMPLETE:
		VSB_printf(pan_vsb,
		    "Incomplete code in %s(), %s line %d:\n",
		    func, file, line);
		break;
	default:
	case VAS_ASSERT:
		VSB_printf(pan_vsb,
		    "Assert error in %s(), %s line %d:\n"
		    "  Condition(%s) not true.\n",
		    func, file, line, cond);
		break;
	}
	if (err)
		VSB_printf(pan_vsb, "errno = %d (%s)\n", err, strerror(err));

	q = THR_GetName();
	if (q != NULL)
		VSB_printf(pan_vsb, "thread = (%s)\n", q);

	VSB_printf(pan_vsb, "version = %s\n", VCS_version);
	VSB_printf(pan_vsb, "ident = %s,%s\n",
	    VSB_data(vident) + 1, Waiter_GetName());

	pan_backtrace(pan_vsb);

	if (!FEATURE(FEATURE_SHORT_PANIC)) {
		req = THR_GetRequest();
		if (req != NULL) {
			pan_req(pan_vsb, req);
			VSL_Flush(req->vsl, 0);
		}
		bo = THR_GetBusyobj();
		if (bo != NULL) {
			pan_busyobj(pan_vsb, bo);
			VSL_Flush(bo->vsl, 0);
		}
	}
	VSB_printf(pan_vsb, "\n");
	VSB_bcat(pan_vsb, "", 1);	/* NUL termination */

	if (FEATURE(FEATURE_NO_COREDUMP))
		exit(4);
	else
		abort();
}
Esempio n. 19
0
struct vsb *
VRY_Create(const struct sess *sp, const struct http *hp)
{
	char *v, *p, *q, *h, *e;
	struct vsb *sb, *sbh;
	unsigned l;

	/* No Vary: header, no worries */
	if (!http_GetHdr(hp, H_Vary, &v))
		return (NULL);

	/* For vary matching string */
	sb = VSB_new_auto();
	AN(sb);

	/* For header matching strings */
	sbh = VSB_new_auto();
	AN(sbh);

	if (*v == ':') {
		WSP(sp, SLT_Error, "Vary header had extra ':', fix backend");
		v++;
	}
	for (p = v; *p; p++) {

		/* Find next header-name */
		if (vct_issp(*p))
			continue;
		for (q = p; *q && !vct_issp(*q) && *q != ','; q++)
			continue;

		/* Build a header-matching string out of it */
		VSB_clear(sbh);
		VSB_printf(sbh, "%c%.*s:%c",
		    (char)(1 + (q - p)), (int)(q - p), p, 0);
		AZ(VSB_finish(sbh));

		if (http_GetHdr(sp->http, VSB_data(sbh), &h)) {
			AZ(vct_issp(*h));
			/* Trim trailing space */
			e = strchr(h, '\0');
			while (e > h && vct_issp(e[-1]))
				e--;
			/* Encode two byte length and contents */
			l = e - h;
			assert(!(l & ~0xffff));
		} else {
			e = h;
			l = 0xffff;
		}
		VSB_printf(sb, "%c%c", (int)(l >> 8), (int)(l & 0xff));
		/* Append to vary matching string */
		VSB_bcat(sb, VSB_data(sbh), VSB_len(sbh));
		if (e != h)
			VSB_bcat(sb, h, e - h);

		while (vct_issp(*q))
			q++;
		if (*q == '\0')
			break;
		xxxassert(*q == ',');
		p = q;
	}
	/* Terminate vary matching string */
	VSB_printf(sb, "%c%c%c", 0xff, 0xff, 0);

	VSB_delete(sbh);
	AZ(VSB_finish(sb));
	return(sb);
}
Esempio n. 20
0
pan_ic(const char *func, const char *file, int line, const char *cond,
    int err, enum vas_e kind)
{
	const char *q;
	struct req *req;
	struct busyobj *bo;

	AZ(pthread_mutex_lock(&panicstr_mtx)); /* Won't be released,
						  we're going to die
						  anyway */
	switch(kind) {
	case VAS_WRONG:
		VSB_printf(pan_vsp,
		    "Wrong turn at %s:%d:\n%s\n", file, line, cond);
		break;
	case VAS_VCL:
		VSB_printf(pan_vsp,
		    "Panic from VCL:\n  %s\n", cond);
		break;
	case VAS_MISSING:
		VSB_printf(pan_vsp,
		    "Missing errorhandling code in %s(), %s line %d:\n"
		    "  Condition(%s) not true.",
		    func, file, line, cond);
		break;
	case VAS_INCOMPLETE:
		VSB_printf(pan_vsp,
		    "Incomplete code in %s(), %s line %d:\n",
		    func, file, line);
		break;
	default:
	case VAS_ASSERT:
		VSB_printf(pan_vsp,
		    "Assert error in %s(), %s line %d:\n"
		    "  Condition(%s) not true.\n",
		    func, file, line, cond);
		break;
	}
	if (err)
		VSB_printf(pan_vsp, "errno = %d (%s)\n", err, strerror(err));

	q = THR_GetName();
	if (q != NULL)
		VSB_printf(pan_vsp, "thread = (%s)\n", q);

	VSB_printf(pan_vsp, "ident = %s,%s\n",
	    VSB_data(vident) + 1, WAIT_GetName());

	pan_backtrace();

	if (!FEATURE(FEATURE_SHORT_PANIC)) {
		req = THR_GetRequest();
		if (req != NULL) {
			pan_req(req);
			VSL_Flush(req->vsl, 0);
		}
		bo = THR_GetBusyobj();
		if (bo != NULL) {
			pan_busyobj(bo);
			VSL_Flush(bo->vsl, 0);
		}
	}
	VSB_printf(pan_vsp, "\n");
	VSB_bcat(pan_vsp, "", 1);	/* NUL termination */

	if (FEATURE(FEATURE_NO_COREDUMP))
		exit(4);
	else
		abort();
}
Esempio n. 21
0
void
VEP_Parse(struct vep_state *vep, const char *p, size_t l)
{
	const char *e;
	struct vep_match *vm;
	int i;

	CHECK_OBJ_NOTNULL(vep, VEP_MAGIC);
	assert(l > 0);

	if (vep->startup) {
		/*
		 * We must force the GZIP header out as a SKIP string,
		 * otherwise an object starting with <esi:include would
		 * have its GZIP header appear after the included object
		 * (e000026.vtc)
		 */
		vep->ver_p = "";
		vep->last_mark = SKIP;
		vep_mark_common(vep, vep->ver_p, VERBATIM);
		vep->startup = 0;
		AZ(vep->hack_p);
		vep->hack_p = p;
	}

	vep->ver_p = p;

	e = p + l;

	while (p < e) {
		AN(vep->state);
		i = e - p;
		if (i > 10)
			i = 10;
		Debug("EP %s %d (%.*s) [%.*s]\n",
		    vep->state,
		    vep->remove,
		    vep->tag_i, vep->tag,
		    i, p);
		assert(p >= vep->ver_p);

		/******************************************************
		 * SECTION A
		 */

		if (vep->state == VEP_START) {
			if (FEATURE(FEATURE_ESI_REMOVE_BOM) && *p == '\xeb') {
				vep->match = vep_match_bom;
				vep->state = VEP_MATCH;
			} else
				vep->state = VEP_BOM;
		} else if (vep->state == VEP_BOM) {
			vep_mark_skip(vep, p);
			if (FEATURE(FEATURE_ESI_DISABLE_XML_CHECK))
				vep->state = VEP_NEXTTAG;
			else
				vep->state = VEP_TESTXML;
		} else if (vep->state == VEP_TESTXML) {
			/*
			 * If the first non-whitespace char is different
			 * from '<' we assume this is not XML.
			 */
			while (p < e && vct_islws(*p))
				p++;
			vep_mark_verbatim(vep, p);
			if (p < e && *p == '<') {
				p++;
				vep->state = VEP_STARTTAG;
			} else if (p < e && *p == '\xeb') {
				VSLb(vep->vc->wrk->vsl, SLT_ESI_xmlerror,
				    "No ESI processing, "
				    "first char not '<' but BOM."
				    " (See feature esi_remove_bom)"
				);
				vep->state = VEP_NOTXML;
			} else if (p < e) {
				VSLb(vep->vc->wrk->vsl, SLT_ESI_xmlerror,
				    "No ESI processing, "
				    "first char not '<'."
				    " (See feature esi_disable_xml_check)"
				);
				vep->state = VEP_NOTXML;
			}
		} else if (vep->state == VEP_NOTXML) {
			/*
			 * This is not recognized as XML, just skip thru
			 * vfp_esi_end() will handle the rest
			 */
			p = e;
			vep_mark_verbatim(vep, p);

		/******************************************************
		 * SECTION B
		 */

		} else if (vep->state == VEP_NOTMYTAG) {
			if (FEATURE(FEATURE_ESI_IGNORE_OTHER_ELEMENTS)) {
				p++;
				vep->state = VEP_NEXTTAG;
			} else {
				vep->tag_i = 0;
				while (p < e) {
					if (*p++ == '>') {
						vep->state = VEP_NEXTTAG;
						break;
					}
				}
			}
			if (p == e && !vep->remove)
				vep_mark_verbatim(vep, p);
		} else if (vep->state == VEP_NEXTTAG) {
			/*
			 * Hunt for start of next tag and keep an eye
			 * out for end of EsiCmt if armed.
			 */
			vep->emptytag = 0;
			vep->endtag = 0;
			vep->attr = NULL;
			vep->dostuff = NULL;
			while (p < e && *p != '<') {
				if (vep->esicmt_p == NULL) {
					p++;
					continue;
				}
				if (*p != *vep->esicmt_p) {
					p++;
					vep->esicmt_p = vep->esicmt;
					continue;
				}
				if (!vep->remove &&
				    vep->esicmt_p == vep->esicmt)
					vep_mark_verbatim(vep, p);
				p++;
				if (*++vep->esicmt_p == '\0') {
					vep->esi_found = 1;
					vep->esicmt = NULL;
					vep->esicmt_p = NULL;
					/*
					 * The end of the esicmt
					 * should not be emitted.
					 * But the stuff before should
					 */
					vep_mark_skip(vep, p);
				}
			}
			if (p < e) {
				if (!vep->remove)
					vep_mark_verbatim(vep, p);
				assert(*p == '<');
				p++;
				vep->state = VEP_STARTTAG;
			} else if (vep->esicmt_p == vep->esicmt && !vep->remove)
				vep_mark_verbatim(vep, p);

		/******************************************************
		 * SECTION C
		 */

		} else if (vep->state == VEP_STARTTAG) {
			/*
			 * Start of tag, set up match table
			 */
			if (p < e) {
				if (*p == '/') {
					vep->endtag = 1;
					p++;
				}
				vep->match = vep_match_starttag;
				vep->state = VEP_MATCH;
			}
		} else if (vep->state == VEP_COMMENT) {
			/*
			 * We are in a comment, find out if it is an
			 * ESI comment or a regular comment
			 */
			if (vep->esicmt == NULL)
				vep->esicmt_p = vep->esicmt = "esi";
			while (p < e) {
				if (*p != *vep->esicmt_p) {
					vep->esicmt_p = vep->esicmt = NULL;
					vep->until_p = vep->until = "-->";
					vep->until_s = VEP_NEXTTAG;
					vep->state = VEP_UNTIL;
					break;
				}
				p++;
				if (*++vep->esicmt_p != '\0')
					continue;
				if (vep->remove)
					vep_error(vep,
					    "ESI 1.0 Nested <!--esi"
					    " element in <esi:remove>");
				vep->esicmt_p = vep->esicmt = "-->";
				vep->state = VEP_NEXTTAG;
				vep_mark_skip(vep, p);
				break;
			}
		} else if (vep->state == VEP_CDATA) {
			/*
			 * Easy: just look for the end of CDATA
			 */
			vep->until_p = vep->until = "]]>";
			vep->until_s = VEP_NEXTTAG;
			vep->state = VEP_UNTIL;
		} else if (vep->state == VEP_ESITAG) {
			vep->in_esi_tag = 1;
			vep->esi_found = 1;
			vep_mark_skip(vep, p);
			vep->match = vep_match_esi;
			vep->state = VEP_MATCH;
		} else if (vep->state == VEP_ESIINCLUDE) {
			if (vep->remove) {
				vep_error(vep,
				    "ESI 1.0 <esi:include> element"
				    " nested in <esi:remove>");
				vep->state = VEP_TAGERROR;
			} else if (vep->endtag) {
				vep_error(vep,
				    "ESI 1.0 </esi:include> illegal end-tag");
				vep->state = VEP_TAGERROR;
			} else {
				vep->dostuff = vep_do_include;
				vep->state = VEP_INTAG;
				vep->attr = vep_match_attr_include;
			}
		} else if (vep->state == VEP_ESIREMOVE) {
			vep->dostuff = vep_do_remove;
			vep->state = VEP_INTAG;
		} else if (vep->state == VEP_ESICOMMENT) {
			if (vep->remove) {
				vep_error(vep,
				    "ESI 1.0 <esi:comment> element"
				    " nested in <esi:remove>");
				vep->state = VEP_TAGERROR;
			} else if (vep->endtag) {
				vep_error(vep,
				    "ESI 1.0 </esi:comment> illegal end-tag");
				vep->state = VEP_TAGERROR;
			} else {
				vep->dostuff = vep_do_comment;
				vep->state = VEP_INTAG;
			}
		} else if (vep->state == VEP_ESIBOGON) {
			vep_error(vep,
			    "ESI 1.0 <esi:bogus> element");
			vep->state = VEP_TAGERROR;

		/******************************************************
		 * SECTION D
		 */

		} else if (vep->state == VEP_INTAG) {
			vep->tag_i = 0;
			while (p < e && vct_islws(*p) && !vep->emptytag) {
				p++;
				vep->canattr = 1;
			}
			if (p < e && *p == '/' && !vep->emptytag) {
				p++;
				vep->emptytag = 1;
				vep->canattr = 0;
			}
			if (p < e && *p == '>') {
				p++;
				AN(vep->dostuff);
				vep_mark_skip(vep, p);
				vep->dostuff(vep, DO_TAG);
				vep->in_esi_tag = 0;
				vep->state = VEP_NEXTTAG;
			} else if (p < e && vep->emptytag) {
				vep_error(vep,
				    "XML 1.0 '>' does not follow '/' in tag");
				vep->state = VEP_TAGERROR;
			} else if (p < e && vep->canattr &&
			    vct_isxmlnamestart(*p)) {
				vep->state = VEP_ATTR;
			} else if (p < e) {
				vep_error(vep,
				    "XML 1.0 Illegal attribute start char");
				vep->state = VEP_TAGERROR;
			}
		} else if (vep->state == VEP_TAGERROR) {
			while (p < e && *p != '>')
				p++;
			if (p < e) {
				p++;
				vep_mark_skip(vep, p);
				vep->in_esi_tag = 0;
				vep->state = VEP_NEXTTAG;
			}

		/******************************************************
		 * SECTION E
		 */

		} else if (vep->state == VEP_ATTR) {
			AZ(vep->attr_delim);
			if (vep->attr == NULL) {
				p++;
				AZ(vep->attr_vsb);
				vep->state = VEP_SKIPATTR;
			} else {
				vep->match = vep->attr;
				vep->state = VEP_MATCH;
			}
		} else if (vep->state == VEP_SKIPATTR) {
			while (p < e && vct_isxmlname(*p))
				p++;
			if (p < e && *p == '=') {
				p++;
				vep->state = VEP_ATTRDELIM;
			} else if (p < e && *p == '>') {
				vep->state = VEP_INTAG;
			} else if (p < e && *p == '/') {
				vep->state = VEP_INTAG;
			} else if (p < e && vct_issp(*p)) {
				vep->state = VEP_INTAG;
			} else if (p < e) {
				vep_error(vep,
				    "XML 1.0 Illegal attr char");
				vep->state = VEP_TAGERROR;
			}
		} else if (vep->state == VEP_ATTRGETVAL) {
			vep->attr_vsb = VSB_new_auto();
			vep->state = VEP_ATTRDELIM;
		} else if (vep->state == VEP_ATTRDELIM) {
			AZ(vep->attr_delim);
			if (*p == '"' || *p == '\'') {
				vep->attr_delim = *p++;
				vep->state = VEP_ATTRVAL;
			} else if (!vct_issp(*p)) {
				vep->attr_delim = ' ';
				vep->state = VEP_ATTRVAL;
			} else {
				vep_error(vep,
				    "XML 1.0 Illegal attribute delimiter");
				vep->state = VEP_TAGERROR;
			}

		} else if (vep->state == VEP_ATTRVAL) {
			while (p < e && *p != '>' && *p != vep->attr_delim &&
			   (vep->attr_delim != ' ' || !vct_issp(*p))) {
				if (vep->attr_vsb != NULL)
					VSB_bcat(vep->attr_vsb, p, 1);
				p++;
			}
			if (p < e && *p == '>') {
				vep_error(vep,
				    "XML 1.0 Missing end attribute delimiter");
				vep->state = VEP_TAGERROR;
				vep->attr_delim = 0;
				if (vep->attr_vsb != NULL) {
					AZ(VSB_finish(vep->attr_vsb));
					VSB_delete(vep->attr_vsb);
					vep->attr_vsb = NULL;
				}
			} else if (p < e) {
				vep->attr_delim = 0;
				p++;
				vep->state = VEP_INTAG;
				if (vep->attr_vsb != NULL) {
					AZ(VSB_finish(vep->attr_vsb));
					AN(vep->dostuff);
					vep->dostuff(vep, DO_ATTR);
					vep->attr_vsb = NULL;
				}
			}

		/******************************************************
		 * Utility Section
		 */

		} else if (vep->state == VEP_MATCH) {
			/*
			 * Match against a table
			 */
			vm = vep_match(vep, p, e);
			vep->match_hit = vm;
			if (vm != NULL) {
				if (vm->match != NULL)
					p += strlen(vm->match);
				vep->state = *vm->state;
				vep->match = NULL;
				vep->tag_i = 0;
			} else {
				memcpy(vep->tag, p, e - p);
				vep->tag_i = e - p;
				vep->state = VEP_MATCHBUF;
				p = e;
			}
		} else if (vep->state == VEP_MATCHBUF) {
			/*
			 * Match against a table while split over input
			 * sections.
			 */
			AN(vep->match);
			do {
				if (*p == '>') {
					for (vm = vep->match;
					    vm->match != NULL; vm++)
						continue;
					AZ(vm->match);
				} else {
					vep->tag[vep->tag_i++] = *p++;
					vm = vep_match(vep,
					    vep->tag, vep->tag + vep->tag_i);
					if (vm && vm->match == NULL) {
						vep->tag_i--;
						p--;
					}
				}
			} while (vm == NULL && p < e);
			vep->match_hit = vm;
			if (vm == NULL) {
				assert(p == e);
			} else {
				vep->state = *vm->state;
				vep->match = NULL;
			}
		} else if (vep->state == VEP_UNTIL) {
			/*
			 * Skip until we see magic string
			 */
			while (p < e) {
				if (*p++ != *vep->until_p++) {
					vep->until_p = vep->until;
				} else if (*vep->until_p == '\0') {
					vep->state = vep->until_s;
					break;
				}
			}
			if (p == e && !vep->remove)
				vep_mark_verbatim(vep, p);
		} else {
			Debug("*** Unknown state %s\n", vep->state);
			INCOMPL();
		}
	}
	/*
	 * We must always mark up the storage we got, try to do so
	 * in the most efficient way, in particular with respect to
	 * minimizing and limiting use of pending.
	 */
	if (p == vep->ver_p)
		;
	else if (vep->in_esi_tag)
		vep_mark_skip(vep, p);
	else if (vep->remove)
		vep_mark_skip(vep, p);
	else
		vep_mark_pending(vep, p);
}
Esempio n. 22
0
static void
pan_ic(const char *func, const char *file, int line, const char *cond,
    int err, int xxx)
{
	const char *q;
	const struct sess *sp;

	AZ(pthread_mutex_lock(&panicstr_mtx)); /* Won't be released,
						  we're going to die
						  anyway */
	switch(xxx) {
	case 3:
		VSB_printf(vsp,
		    "Wrong turn at %s:%d:\n%s\n", file, line, cond);
		break;
	case 2:
		VSB_printf(vsp,
		    "Panic from VCL:\n  %s\n", cond);
		break;
	case 1:
		VSB_printf(vsp,
		    "Missing errorhandling code in %s(), %s line %d:\n"
		    "  Condition(%s) not true.",
		    func, file, line, cond);
		break;
	default:
	case 0:
		VSB_printf(vsp,
		    "Assert error in %s(), %s line %d:\n"
		    "  Condition(%s) not true.\n",
		    func, file, line, cond);
		break;
	}
	if (err)
		VSB_printf(vsp, "errno = %d (%s)\n", err, strerror(err));

	q = THR_GetName();
	if (q != NULL)
		VSB_printf(vsp, "thread = (%s)\n", q);

	VSB_printf(vsp, "ident = %s,%s\n",
	    VSB_data(vident) + 1, WAIT_GetName());

	pan_backtrace();

	if (!(cache_param->diag_bitmap & 0x2000)) {
		sp = THR_GetSession();
		if (sp != NULL)
			pan_sess(sp);
	}
	VSB_printf(vsp, "\n");
	VSB_bcat(vsp, "", 1);	/* NUL termination */

	if (cache_param->diag_bitmap & 0x4000)
		(void)fputs(VSM_head->panicstr, stderr);

#ifdef HAVE_ABORT2
	if (cache_param->diag_bitmap & 0x8000) {
		void *arg[1];
		char *p;

		for (p = VSM_head->panicstr; *p; p++)
			if (*p == '\n')
				*p = ' ';
		arg[0] = VSM_head->panicstr;
		abort2(VSM_head->panicstr, 1, arg);
	}
#endif
	if (cache_param->diag_bitmap & 0x1000)
		exit(4);
	else
		abort();
}
Esempio n. 23
0
/*
 * Quote a string
 */
void
VSB_quote_pfx(struct vsb *s, const char *pfx, const void *v, int len, int how)
{
	const char *p;
	const char *q;
	int quote = 0;
	int nl = 0;
	const unsigned char *u, *w;

	assert(v != NULL);
	if (len == -1)
		len = strlen(v);

	if (len == 0 && (how & VSB_QUOTE_CSTR)) {
		VSB_printf(s, "%s\"\"", pfx);
		return;
	} else if (len == 0)
		return;

	VSB_cat(s, pfx);

	if (how & VSB_QUOTE_HEX) {
		u = v;
		for (w = u; w < u + len; w++)
			if (*w != 0x00)
				break;
		VSB_printf(s, "0x");
		if (w == u + len && len > 4) {
			VSB_printf(s, "0...0");
		} else {
			for (w = u; w < u + len; w++)
				VSB_printf(s, "%02x", *w);
		}
		return;
	}
	p = v;

	for (q = p; q < p + len; q++) {
		if (!isgraph(*q) || *q == '"' || *q == '\\') {
			quote++;
			break;
		}
	}
	if (!quote && !(how & (VSB_QUOTE_JSON|VSB_QUOTE_CSTR))) {
		(void)VSB_bcat(s, p, len);
		if ((how & (VSB_QUOTE_UNSAFE|VSB_QUOTE_NONL)) &&
		    p[len-1] != '\n')
			(void)VSB_putc(s, '\n');
		return;
	}

	if (how & VSB_QUOTE_CSTR)
		(void)VSB_putc(s, '"');

	for (q = p; q < p + len; q++) {
		if (nl)
			VSB_cat(s, pfx);
		nl = 0;
		switch (*q) {
		case '?':
			if (how & VSB_QUOTE_CSTR)
				(void)VSB_putc(s, '\\');
			(void)VSB_putc(s, *q);
			break;
		case ' ':
			(void)VSB_putc(s, *q);
			break;
		case '\\':
		case '"':
			if (!(how & VSB_QUOTE_UNSAFE))
				(void)VSB_putc(s, '\\');
			(void)VSB_putc(s, *q);
			break;
		case '\n':
			if (how & VSB_QUOTE_CSTR) {
				(void)VSB_printf(s, "\\n\"\n%s\t\"", pfx);
			} else if (how & (VSB_QUOTE_NONL|VSB_QUOTE_UNSAFE)) {
				(void)VSB_printf(s, "\n");
				nl = 1;
			} else {
				(void)VSB_printf(s, "\\n");
			}
			break;
		case '\r':
			(void)VSB_cat(s, "\\r");
			break;
		case '\t':
			(void)VSB_cat(s, "\\t");
			break;
		case '\v':
			(void)VSB_cat(s, "\\v");
			break;
		default:
			/* XXX: Implement VSB_QUOTE_JSON */
			if (isgraph(*q))
				(void)VSB_putc(s, *q);
			else if (how & VSB_QUOTE_ESCHEX)
				(void)VSB_printf(s, "\\x%02x", *q & 0xff);
			else
				(void)VSB_printf(s, "\\%03o", *q & 0xff);
			break;
		}
	}
	if (how & VSB_QUOTE_CSTR)
		(void)VSB_putc(s, '"');
	if ((how & (VSB_QUOTE_NONL|VSB_QUOTE_UNSAFE)) && !nl)
		(void)VSB_putc(s, '\n');
}
Esempio n. 24
0
int
VRY_Create(struct busyobj *bo, struct vsb **psb)
{
	char *v, *p, *q, *h, *e;
	struct vsb *sb, *sbh;
	unsigned l;
	int error = 0;

	CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
	CHECK_OBJ_NOTNULL(bo->bereq, HTTP_MAGIC);
	CHECK_OBJ_NOTNULL(bo->beresp, HTTP_MAGIC);
	AN(psb);
	AZ(*psb);

	/* No Vary: header, no worries */
	if (!http_GetHdr(bo->beresp, H_Vary, &v))
		return (0);

	/* For vary matching string */
	sb = VSB_new_auto();
	AN(sb);

	/* For header matching strings */
	sbh = VSB_new_auto();
	AN(sbh);

	for (p = v; *p; p++) {

		/* Find next header-name */
		if (vct_issp(*p))
			continue;
		for (q = p; *q && !vct_issp(*q) && *q != ','; q++)
			continue;

		if (q - p > INT8_MAX) {
			VSLb(bo->vsl, SLT_Error,
			    "Vary header name length exceeded");
			error = 1;
			break;
		}

		/* Build a header-matching string out of it */
		VSB_clear(sbh);
		VSB_printf(sbh, "%c%.*s:%c",
		    (char)(1 + (q - p)), (int)(q - p), p, 0);
		AZ(VSB_finish(sbh));

		if (http_GetHdr(bo->bereq, VSB_data(sbh), &h)) {
			AZ(vct_issp(*h));
			/* Trim trailing space */
			e = strchr(h, '\0');
			while (e > h && vct_issp(e[-1]))
				e--;
			/* Encode two byte length and contents */
			l = e - h;
			if (l > 0xffff - 1) {
				VSLb(bo->vsl, SLT_Error,
				    "Vary header maximum length exceeded");
				error = 1;
				break;
			}
		} else {
			e = h;
			l = 0xffff;
		}
		VSB_printf(sb, "%c%c", (int)(l >> 8), (int)(l & 0xff));
		/* Append to vary matching string */
		VSB_bcat(sb, VSB_data(sbh), VSB_len(sbh));
		if (e != h)
			VSB_bcat(sb, h, e - h);

		while (vct_issp(*q))
			q++;
		if (*q == '\0')
			break;
		if (*q != ',') {
			VSLb(bo->vsl, SLT_Error, "Malformed Vary header");
			error = 1;
			break;
		}
		p = q;
	}

	if (error) {
		VSB_delete(sbh);
		VSB_delete(sb);
		return (-1);
	}

	/* Terminate vary matching string */
	VSB_printf(sb, "%c%c%c", 0xff, 0xff, 0);

	VSB_delete(sbh);
	AZ(VSB_finish(sb));
	*psb = sb;
	return (VSB_len(sb));
}
Esempio n. 25
0
static void
cmd_http_txresp(CMD_ARGS)
{
	struct http *hp;
	const char *proto = "HTTP/1.1";
	const char *status = "200";
	const char *msg = "Ok";
	int bodylen = 0;
	char *b, *c;
	char *body = NULL, *nullbody;
	int nolen = 0;


	(void)cmd;
	(void)vl;
	CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC);
	ONLY_SERVER(hp, av);
	assert(!strcmp(av[0], "txresp"));
	av++;

	VSB_clear(hp->vsb);

	/* send a "Content-Length: 0" header unless something else happens */
	REPLACE(body, "");
	nullbody = body;

	for(; *av != NULL; av++) {
		if (!strcmp(*av, "-proto")) {
			proto = av[1];
			av++;
		} else if (!strcmp(*av, "-status")) {
			status = av[1];
			av++;
		} else if (!strcmp(*av, "-msg")) {
			msg = av[1];
			av++;
			continue;
		} else
			break;
	}

	VSB_printf(hp->vsb, "%s %s %s%s", proto, status, msg, nl);

	for(; *av != NULL; av++) {
		if (!strcmp(*av, "-nolen")) {
			nolen = 1;
		} else if (!strcmp(*av, "-hdr")) {
			VSB_printf(hp->vsb, "%s%s", av[1], nl);
			av++;
		} else
			break;
	}
	for(; *av != NULL; av++) {
		if (!strcmp(*av, "-body")) {
			assert(body == nullbody);
			REPLACE(body, av[1]);

			AN(body);
			av++;
			bodylen = strlen(body);
			for (b = body; *b != '\0'; b++) {
				if(*b == '\\' && b[1] == '0') {
					*b = '\0';
					for(c = b+1; *c != '\0'; c++) {
						*c = c[1];
					}
					b++;
					bodylen--;
				}
			}
		} else if (!strcmp(*av, "-bodylen")) {
			assert(body == nullbody);
			body = synth_body(av[1], 0);
			bodylen = strlen(body);
			av++;
		} else if (!strcmp(*av, "-gzipresidual")) {
			hp->gzipresidual = strtoul(av[1], NULL, 0);
			av++;
		} else if (!strcmp(*av, "-gziplevel")) {
			hp->gziplevel = strtoul(av[1], NULL, 0);
			av++;
		} else if (!strcmp(*av, "-gziplen")) {
			assert(body == nullbody);
			b = synth_body(av[1], 1);
			gzip_body(hp, b, &body, &bodylen);
			VSB_printf(hp->vsb, "Content-Encoding: gzip%s", nl);
			// vtc_hexdump(hp->vl, 4, "gzip", (void*)body, bodylen);
			av++;
		} else if (!strcmp(*av, "-gzipbody")) {
			assert(body == nullbody);
			gzip_body(hp, av[1], &body, &bodylen);
			VSB_printf(hp->vsb, "Content-Encoding: gzip%s", nl);
			// vtc_hexdump(hp->vl, 4, "gzip", (void*)body, bodylen);
			av++;
		} else
			break;
	}
	if (*av != NULL)
		vtc_log(hp->vl, 0, "Unknown http txresp spec: %s\n", *av);
	if (body != NULL && !nolen)
		VSB_printf(hp->vsb, "Content-Length: %d%s", bodylen, nl);
	VSB_cat(hp->vsb, nl);
	if (body != NULL)
		VSB_bcat(hp->vsb, body, bodylen);
	http_write(hp, 4, "txresp");
}