Esempio n. 1
0
char *
has_ident(const char *name,
	  char *first,
	  char *last)
{
    char *base;
    char *s, *t, *d, c;

    name = leaf_of(name);

    s = first;
    while ((t = base = strchr(s, '$')) != 0 && (t < last)) {
	t++;
	if ((s = exact(skip_camel(t), "Id")) != 0
	    || (s = exact(t, "Header")) != 0) {
	    if (*s == '$') {
		return base;
	    } else if ((*s == ':')
		       && is_inline(t, '$')) {
		/* RCS identifier can have pathname prepended */
		s = skip_white(s + 1);
		d = skip_text(s);
		c = *d;
		*d = EOS;
		while (is_inline(s, '/'))
		    s++;
		*d = c;
		if ((s = same_name(s, name)) != 0
		    && (s = exact(s, ",v")) != 0
		    && isspace(*s))
		    return base;
	    }
	}
	s = t;
    }

    s = first;
    while ((t = base = strchr(s, '@')) != 0 && (t < last)) {
	t++;
	if ((s = exact(t, "(#)")) != NULL) {
	    t = s;
	    /* some versions of SCCS don't do module-name */
	    if ((s = same_name(t, name)) != NULL)
		return base;

	    t = skip_text(t);	/* module-name, if any */
	    t = skip_white(t);
	    if ((s = same_name(t, name)) != NULL)
		return base;
	}
	s = t;
    }
    return 0;
}
Esempio n. 2
0
static int get_real_size(struct sk_buff *skb, struct net_device *dev,
			 int *lso_header_size)
{
	struct mlx4_en_priv *priv = netdev_priv(dev);
	int real_size;

	if (skb_is_gso(skb)) {
		*lso_header_size = skb_transport_offset(skb) + tcp_hdrlen(skb);
		real_size = CTRL_SIZE + skb_shinfo(skb)->nr_frags * DS_SIZE +
			ALIGN(*lso_header_size + 4, DS_SIZE);
		if (unlikely(*lso_header_size != skb_headlen(skb))) {
			/* We add a segment for the skb linear buffer only if
			 * it contains data */
			if (*lso_header_size < skb_headlen(skb))
				real_size += DS_SIZE;
			else {
				if (netif_msg_tx_err(priv))
					en_warn(priv, "Non-linear headers\n");
				return 0;
			}
		}
	} else {
		*lso_header_size = 0;
		if (!is_inline(skb, NULL))
			real_size = CTRL_SIZE + (skb_shinfo(skb)->nr_frags + 1) * DS_SIZE;
		else
			real_size = inline_size(skb);
	}

	return real_size;
}
Esempio n. 3
0
int CNetCacheBlobFetchApp::ProcessRequest(CCgiContext& ctx)
{
    const CCgiRequest& request = ctx.GetRequest();
    CCgiResponse&      reply   = ctx.GetResponse();

    bool is_found;

    string key = request.GetEntry("key", &is_found);
    if (key.empty() || !is_found) {
        NCBI_THROW(CArgException, eNoArg, "CGI entry 'key' is missing");
    }

    string fmt = request.GetEntry("fmt", &is_found);
    if (fmt.empty() || !is_found)
        fmt = "image/png";

    string filename(request.GetEntry("filename", &is_found));
    if (is_found && !filename.empty()) {
        string is_inline(request.GetEntry("inline", &is_found));

        reply.SetHeaderValue("Content-Disposition",
                (is_found && NStr::StringToBool(is_inline) ?
                        "inline; filename=" : "attachment; filename=") +
                filename);
    }

    reply.SetContentType(fmt);

    reply.WriteHeader();

    CNetStorageObject netstorage_object(m_NetStorage.Open(key));

    char buffer[NETSTORAGE_IO_BUFFER_SIZE];

    size_t total_bytes_written = 0;

    while (!netstorage_object.Eof()) {
        size_t bytes_read = netstorage_object.Read(buffer, sizeof(buffer));

        reply.out().write(buffer, bytes_read);
        total_bytes_written += bytes_read;

        if (bytes_read < sizeof(buffer))
            break;
    }

    netstorage_object.Close();

    LOG_POST(Info << "retrieved data: " << total_bytes_written << " bytes");

    return 0;
}
Esempio n. 4
0
 void visit_app(expr const & e) {
     if (should_visit(e)) {
         buffer<expr> args;
         expr const & fn = get_app_args(e, args);
         if (is_constant(fn) && is_inline(m_tc.env(), const_name(fn))) {
             if (auto new_e = unfold_app(m_tc.env(), e)) {
                 visit(*new_e);
                 return;
             }
         }
         visit(fn);
         for (expr const & arg : args)
             visit(arg);
     }
 }
Esempio n. 5
0
File: en_tx.c Progetto: avagin/linux
static int get_real_size(const struct sk_buff *skb,
			 const struct skb_shared_info *shinfo,
			 struct net_device *dev,
			 int *lso_header_size,
			 bool *inline_ok,
			 void **pfrag)
{
	struct mlx4_en_priv *priv = netdev_priv(dev);
	int real_size;

	if (shinfo->gso_size) {
		*inline_ok = false;
		if (skb->encapsulation)
			*lso_header_size = (skb_inner_transport_header(skb) - skb->data) + inner_tcp_hdrlen(skb);
		else
			*lso_header_size = skb_transport_offset(skb) + tcp_hdrlen(skb);
		real_size = CTRL_SIZE + shinfo->nr_frags * DS_SIZE +
			ALIGN(*lso_header_size + 4, DS_SIZE);
		if (unlikely(*lso_header_size != skb_headlen(skb))) {
			/* We add a segment for the skb linear buffer only if
			 * it contains data */
			if (*lso_header_size < skb_headlen(skb))
				real_size += DS_SIZE;
			else {
				if (netif_msg_tx_err(priv))
					en_warn(priv, "Non-linear headers\n");
				return 0;
			}
		}
	} else {
		*lso_header_size = 0;
		*inline_ok = is_inline(priv->prof->inline_thold, skb,
				       shinfo, pfrag);

		if (*inline_ok)
			real_size = inline_size(skb);
		else
			real_size = CTRL_SIZE +
				    (shinfo->nr_frags + 1) * DS_SIZE;
	}

	return real_size;
}
Esempio n. 6
0
    virtual expr visit_app(expr const & e) override {
        expr const & fn = get_app_fn(e);
        if (!is_constant(fn))
            return default_visit_app(e);
        name const & n  = const_name(fn);
        if (is_vm_builtin_function(n))
            return default_visit_app(e);
        if (is_cases_on_recursor(env(), n) || is_nonrecursive_recursor(n))
            return visit_cases_on_app(e);
        unsigned nargs  = get_app_num_args(e);
        declaration d   = env().get(n);
        if (!d.is_definition() || d.is_theorem())
            return default_visit_app(e);
        expr v = d.get_value();
        unsigned arity = 0;
        while (is_lambda(v)) {
            arity++;
            v = binding_body(v);
        }

        if (arity > nargs) {
            // not fully applied
            return default_visit_app(e);
        }

        if (is_inline(env(), n) || is_simple_application(v)) {
            if (auto r = unfold_term(env(), e))
                return visit(*r);
        }

        /*
          TODO(Leo): this is not safe here.
          Reason: we may put recursors have have been eliminated in previous steps.
          We need to move this code to a different place, or make sure
          that we can recursors will be eliminated later
        if (auto r = ctx().reduce_projection(e)) {
            return visit(*r);
        }
        */

        return default_visit_app(e);
    }
void CL_CSSUsedValues::set_width(const CL_CSSBoxProperties &properties)
{
	margin.left = get_margin_width(properties.margin_width_left);
	margin.right = get_margin_width(properties.margin_width_right);
	border.left = properties.border_width_left.length.value;
	border.right = properties.border_width_right.length.value;
	padding.left = get_padding_width(properties.padding_width_left);
	padding.right = get_padding_width(properties.padding_width_right);

	width = 0;
	undetermined_width = false;

	if (replaced)
	{
		if (properties.width.type == CL_CSSBoxWidth::type_auto && properties.height.type == CL_CSSBoxHeight::type_auto && intrinsic.has_width)
		{
			width = intrinsic.width;
		}
		else if (properties.width.type == CL_CSSBoxWidth::type_auto && properties.height.type == CL_CSSBoxHeight::type_auto && intrinsic.has_height && intrinsic.has_ratio)
		{
			width = intrinsic.height / intrinsic.ratio;
		}
		else if (properties.width.type == CL_CSSBoxWidth::type_auto && properties.height.type == CL_CSSBoxHeight::type_auto && intrinsic.has_ratio)
		{
			if (containing.undetermined_width)
			{
				width = 0;
				undetermined_width = true;
			}
			else
			{
				width = containing.width - margin.left - margin.right - border.left - border.right - padding.left - padding.right;
			}
		}
		else if (properties.width.type == CL_CSSBoxWidth::type_auto && intrinsic.has_width)
		{
			width = intrinsic.width;
		}
		else if (properties.width.type == CL_CSSBoxWidth::type_auto)
		{
			width = 300; // bug: Should be 300px (css physical length)
			/*if (width > device.width)
			{
				width = largest_2_1_ratio_rect();
			}*/
		}
	}
	else if (is_inline(properties))
	{
		// width property does not apply.
		width = 0;
		undetermined_width = true;
	}
	else if (is_absolute(properties))
	{
		if (properties.width.type == CL_CSSBoxWidth::type_length)
		{
			width = properties.width.length.value;
		}
		else if (properties.width.type == CL_CSSBoxWidth::type_percentage)
		{
			if (containing.undetermined_width)
			{
				width = 0;
				undetermined_width = true;
			}
			else
			{
				width = properties.width.percentage * containing.width / 100.0f;
			}
		}
		else if (properties.width.type == CL_CSSBoxWidth::type_auto && properties.left.type != CL_CSSBoxLeft::type_auto && properties.right.type != CL_CSSBoxRight::type_auto)
		{
			if (containing.undetermined_width)
			{
				width = 0;
				undetermined_width = true;
			}
			else
			{
				// To do: Handle the cases where the length property is a percentage. Also determine what the containing box is (the viewport/page-area?)
				width = containing.width - properties.left.length.value - properties.right.length.value - margin.left - margin.right - border.left - border.right - padding.left - padding.right;
			}
		}
		else if (properties.width.type == CL_CSSBoxWidth::type_auto)
		{
			width = 0.0f;
			undetermined_width = true; // shrink-to-fit
		}
	}
	else if (is_floating(properties) || is_inline_block(properties))
	{
		if (properties.width.type == CL_CSSBoxWidth::type_length)
		{
			width = properties.width.length.value;
		}
		else if (properties.width.type == CL_CSSBoxWidth::type_percentage)
		{
			if (containing.undetermined_width)
			{
				width = 0;
				undetermined_width = true;
			}
			else
			{
				width = properties.width.percentage * containing.width / 100.0f;
			}
		}
		else if (properties.width.type == CL_CSSBoxWidth::type_auto)
		{
			width = 0.0f;
			undetermined_width = true; // shrink-to-fit
		}
	}
	else if (is_block(properties))
	{
		if (properties.width.type == CL_CSSBoxWidth::type_length)
		{
			width = properties.width.length.value;
		}
		else if (properties.width.type == CL_CSSBoxWidth::type_percentage)
		{
			if (containing.undetermined_width)
			{
				width = 0;
				undetermined_width = true;
			}
			else
			{
				width = properties.width.percentage * containing.width / 100.0f;
			}
		}
		else if (properties.width.type == CL_CSSBoxWidth::type_auto)
		{
			if (containing.undetermined_width)
			{
				width = 0;
				undetermined_width = true;
			}
			else
			{
				width = cl_max(0.0f, containing.width - margin.left - margin.right - border.left - border.right - padding.left - padding.right);
			}
		}
	}

	if (!undetermined_width)
	{
		if (properties.max_width.type == CL_CSSBoxMaxWidth::type_length)
		{
			width = cl_min(width, properties.max_width.length.value);
		}
		else if (properties.max_width.type == CL_CSSBoxMaxWidth::type_percentage && !containing.undetermined_width)
		{
			width = cl_min(width, properties.max_width.percentage * containing.width / 100.0f);
		}

		if (properties.min_width.type == CL_CSSBoxMinWidth::type_length)
		{
			width = cl_max(width, properties.min_width.length.value);
		}
		else if (properties.min_width.type == CL_CSSBoxMinWidth::type_percentage && !containing.undetermined_width)
		{
			width = cl_max(width, properties.min_width.percentage * containing.width / 100.0f);
		}
	}

	calc_noncontent_width(properties);
}
void CL_CSSUsedValues::set_height(const CL_CSSBoxProperties &properties)
{
	height = 0;
	undetermined_height = false;

	if (replaced)
	{
		if (!is_absolute(properties))
		{
			if (properties.height.type == CL_CSSBoxHeight::type_length)
			{
				height = properties.height.length.value;
			}
			else if (properties.height.type == CL_CSSBoxHeight::type_percentage)
			{
				if (containing.undetermined_height)
				{
					height = 0;
					undetermined_height = true;
				}
				else
				{
					height = containing.height * properties.height.percentage / 100.0f;
				}
			}
			else if (properties.height.type == CL_CSSBoxHeight::type_auto)
			{
				height = 0;
				undetermined_height = true;
			}
		}
		else
		{
			height = 0;
			undetermined_height = true;

			// 'top' + 'margin-top' + 'border-top-width' + 'padding-top' + 'height' + 'padding-bottom' + 'border-bottom-width' + 'margin-bottom' + 'bottom' = height of containing block
		}
	}
	else if (is_inline(properties))
	{
		// Height does not apply.
		height = 0;
		undetermined_height = true;
	}
	else if (is_block(properties))
	{
		if (properties.height.type == CL_CSSBoxHeight::type_length)
		{
			height = properties.height.length.value;
		}
		else if (properties.height.type == CL_CSSBoxHeight::type_percentage)
		{
			if (containing.undetermined_height)
			{
				height = 0;
				undetermined_height = true;
			}
			else
			{
				height = containing.height * properties.height.percentage / 100.0f;
			}
		}
		else if (properties.height.type == CL_CSSBoxHeight::type_auto)
		{
			height = 0;
			undetermined_height = true;
		}
	}
	else if (is_absolute(properties))
	{
		height = 0;
		undetermined_height = true;

		// 'top' + 'margin-top' + 'border-top-width' + 'padding-top' + 'height' + 'padding-bottom' + 'border-bottom-width' + 'margin-bottom' + 'bottom' = height of containing block
	}

	if (!undetermined_height)
	{
		if (properties.max_height.type == CL_CSSBoxMaxHeight::type_length)
		{
			height = cl_min(height, properties.max_height.length.value);
		}
		else if (properties.max_height.type == CL_CSSBoxMaxHeight::type_percentage && !containing.undetermined_height)
		{
			height = cl_min(height, properties.max_height.percentage * containing.height / 100.0f);
		}

		if (properties.min_height.type == CL_CSSBoxMinHeight::type_length)
		{
			height = cl_max(height, properties.min_height.length.value);
		}
		else if (properties.min_height.type == CL_CSSBoxMinHeight::type_percentage && !containing.undetermined_height)
		{
			height = cl_max(height, properties.min_height.percentage * containing.height / 100.0f);
		}
	}

	calc_noncontent_height(properties);
}
void CL_CSSUsedValues::calc_noncontent_width(const CL_CSSBoxProperties &properties)
{
	margin.left = get_margin_width(properties.margin_width_left);
	margin.right = get_margin_width(properties.margin_width_right);
	border.left = properties.border_width_left.length.value;
	border.right = properties.border_width_right.length.value;
	padding.left = get_padding_width(properties.padding_width_left);
	padding.right = get_padding_width(properties.padding_width_right);

	if (is_inline(properties) || is_inline_block(properties) || is_floating(properties))
	{
		// Do nothing. Correct values already set by get_margin_width.
	}
	else if (is_block(properties))
	{
		if (properties.margin_width_left.type == CL_CSSBoxMarginWidth::type_auto && properties.margin_width_right.type == CL_CSSBoxMarginWidth::type_auto)
		{
			margin.left = cl_max(0.0f, (containing.width-border.left-border.right-padding.left-padding.right-width)/2.0f);
			margin.right = cl_max(0.0f, containing.width-border.left-border.right-padding.left-padding.right-width-margin.left);
		}
		else if (properties.margin_width_left.type == CL_CSSBoxMarginWidth::type_auto)
		{
			margin.left = cl_max(0.0f, containing.width-margin.right-border.left-border.right-padding.left-padding.right-width);
		}
		else if (properties.margin_width_right.type == CL_CSSBoxMarginWidth::type_auto)
		{
			margin.right = cl_max(0.0f, containing.width-margin.left-border.left-border.right-padding.left-padding.right-width);
		}

		if (margin.left + border.left + width + border.right + padding.right + margin.right > containing.width)
		{
			if (properties.direction.type == CL_CSSBoxDirection::type_ltr)
				margin.right = cl_max(0.0f, containing.width-margin.left-border.left-border.right-padding.left-padding.right-width);
			else
				margin.left = cl_max(0.0f, containing.width-margin.right-border.left-border.right-padding.left-padding.right-width);
		}
	}
	else if (is_absolute(properties) && !replaced)
	{
		// Lots of annoying calculations here using 'left', 'right', 'width', 'direction' and the margin+border+padding+width=containing.width constraint
	}
	else if (is_absolute(properties) && replaced)
	{
		if (properties.margin_width_left.type == CL_CSSBoxMarginWidth::type_auto)
		{
			if (properties.left.type == CL_CSSBoxLeft::type_auto || properties.right.type == CL_CSSBoxRight::type_auto)
			{
				margin.left = 0;
			}
			else
			{
				// solve using margin+border+padding+width=containing.width constraint
			}
		}

		if (properties.margin_width_right.type == CL_CSSBoxMarginWidth::type_auto)
		{
			if (properties.left.type == CL_CSSBoxLeft::type_auto || properties.right.type == CL_CSSBoxRight::type_auto)
			{
				margin.right = 0;
			}
			else
			{
				// solve using margin+border+padding+width=containing.width constraint
			}
		}
	}
}
Esempio n. 10
0
VarOrRVar LoopLevel::var() const {
    internal_assert(defined());
    internal_assert(!is_inline() && !is_root());
    return VarOrRVar(contents->var_name, contents->is_rvar);
}
Esempio n. 11
0
File: html.c Progetto: aabc/blists
int html_message(const char *list, unsigned int y, unsigned int m, unsigned int d, unsigned int n)
{
	unsigned int aday, n0, n2;
	char *list_file;
	off_t idx_offset;
	int fd, error, got, trunc, prev, next;
	idx_msgnum_t m0, m1, m1r;
	struct idx_message idx_msg[3];
	idx_off_t offset;
	idx_size_t size;
	struct buffer src, dst;
	struct mime_ctx mime;
	char *p, *q, *date, *from, *to, *cc, *subject, *body, *bend;

	if (y < MIN_YEAR || y > MAX_YEAR ||
	    m < 1 || m > 12 ||
	    d < 1 || d > 31 ||
	    n < 1 || n > 999999)
		return html_error("Invalid date or message number");
	aday = YMD2ADAY(y - MIN_YEAR, m, d);

	list_file = concat(MAIL_SPOOL_PATH "/", list, NULL);
	if (!list_file)
		return html_error(NULL);

	fd = idx_open(list);
	if (fd < 0) {
		error = errno;
		free(list_file);
		return html_error(error == ENOENT ?
		    "No such mailing list" : (error == ESRCH ?
		    "Index needs rebuild" : NULL));
	}

	error = !idx_read_aday_ok(fd, aday, &m1, sizeof(m1));
	if (error || m1 < 1 || m1 >= MAX_MAILBOX_MESSAGES) {
		idx_close(fd);
		free(list_file);
		return html_error((error || m1 > 0) ? NULL : "No such message");
	}
	m1r = m1 + n - (1 + 1); /* both m1 and n are 1-based; m1r is 0-based */
	idx_offset = IDX2MSG(m1r);
	prev = next = 1;
	if (m1r >= 1) {
		idx_offset -= sizeof(idx_msg[0]);
		got = idx_read(fd, idx_offset, &idx_msg, sizeof(idx_msg));
		if (got != sizeof(idx_msg)) {
			error = got != sizeof(idx_msg[0]) * 2;
			idx_msg[2] = idx_msg[1];
			next = 0;
		}
	} else {
		prev = 0;
		got = idx_read(fd, idx_offset, &idx_msg[1], sizeof(idx_msg[1]) * 2);
		if (got != sizeof(idx_msg[1]) * 2) {
			error = got != sizeof(idx_msg[1]);
			idx_msg[2] = idx_msg[1];
			next = 0;
		}
		idx_msg[0] = idx_msg[1];
	}

	n0 = n - 1;
	if (!n0 && prev && !error) {
		aday = YMD2ADAY(idx_msg[0].y, idx_msg[0].m, idx_msg[0].d);
		error = !idx_read_aday_ok(fd, aday, &m0, sizeof(m0));
		if (m1 > m0)
			n0 = m1 - m0;
		else
			error = 1;
	}

	if (idx_close(fd) || error) {
		free(list_file);
		return html_error(got ? NULL : "No such message");
	}

	n2 = n + 1;
	if (idx_msg[2].y != idx_msg[1].y ||
	    idx_msg[2].m != m || idx_msg[2].d != d)
		n2 = 1;

	if (y - MIN_YEAR != idx_msg[1].y ||
	    m != idx_msg[1].m || d != idx_msg[1].d) {
		free(list_file);
		return html_error("No such message");
	}

	offset = idx_msg[1].offset;
	size = idx_msg[1].size;

	trunc = size > MAX_MESSAGE_SIZE;
	if (trunc)
		size = MAX_MESSAGE_SIZE;
	if (buffer_init(&src, size)) {
		free(list_file);
		return html_error(NULL);
	}
	fd = open(list_file, O_RDONLY);
	free(list_file);
	if (fd < 0) {
		buffer_free(&src);
		return html_error("mbox open error");
	}
	error =
	    lseek(fd, offset, SEEK_SET) != offset ||
	    read_loop(fd, src.start, size) != size;
	if (close(fd) || error || mime_init(&mime, &src)) {
		buffer_free(&src);
		return html_error("mbox read error");
	}
	if (buffer_init(&dst, size)) {
		buffer_free(&src);
		mime_free(&mime);
		return html_error(NULL);
	}

	date = from = to = cc = subject = body = NULL;
	while (src.end - src.ptr > 9 && *src.ptr != '\n') {
		switch (*src.ptr) {
		case 'D':
		case 'd':
			if (!strncasecmp(src.ptr, "Date:", 5)) {
				date = mime_decode_header(&mime);
				continue;
			}
			break;
		case 'F':
		case 'f':
			if (!strncasecmp(src.ptr, "From:", 5)) {
				from = mime_decode_header(&mime);
				continue;
			}
			break;
		case 'T':
		case 't':
			if (!strncasecmp(src.ptr, "To:", 3)) {
				to = mime_decode_header(&mime);
				continue;
			}
			break;
		case 'S':
		case 's':
			if (!strncasecmp(src.ptr, "Subject:", 8)) {
				subject = mime_decode_header(&mime);
				continue;
			}
			break;
		case 'C':
		case 'c':
			if (!strncasecmp(src.ptr, "CC:", 3))
				cc = mime_decode_header(&mime);
			else
				mime_decode_header(&mime);
			continue;
		}
		mime_skip_header(&mime);
	}
	if (src.ptr >= src.end) {
		buffer_free(&src);
		buffer_free(&dst);
		mime_free(&mime);
		return html_error(NULL);
	}
	if (*src.ptr == '\n')
		body = ++src.ptr;

	if ((p = subject)) {
		while ((p = strchr(p, '['))) {
			if (strncasecmp(++p, list, strlen(list)))
				continue;
			q = p + strlen(list);
			if (*q != ']')
				continue;
			if (*++q == ' ') q++;
			memmove(--p, q, strlen(q) + 1);
		}
	}

	buffer_appends(&dst, "\n");

	if (html_flags & HTML_HEADER) {
		buffer_appends(&dst, "<title>");
		buffer_appends_html(&dst, list);
		if (subject && strlen(subject) > 9) {
			buffer_appends(&dst, " - ");
			buffer_appends_html(&dst, subject + 9);
		}
		buffer_appends(&dst, "</title>\n");
		if (html_flags & HTML_CENSOR)
			buffer_appends(&dst, "<meta name=\"robots\" content=\"noindex\">\n");
	}

	if (html_flags & HTML_BODY) {
		unsigned int attachment_count = 0;

		if (prev) {
			buffer_appends(&dst, "<a href=\"");
			if (n == 1)
				buffer_appendf(&dst, "../../../%u/%02u/%02u/",
				    MIN_YEAR + idx_msg[0].y, idx_msg[0].m, idx_msg[0].d);
			buffer_appendf(&dst, "%u\">[&lt;prev]</a> ", n0);
		}
		if (next) {
			buffer_appends(&dst, "<a href=\"");
			if (n2 == 1)
				buffer_appendf(&dst, "../../../%u/%02u/%02u/",
				    MIN_YEAR + idx_msg[2].y, idx_msg[2].m, idx_msg[2].d);
			buffer_appendf(&dst, "%u\">[next&gt;]</a> ", n2);
		}
		if (idx_msg[1].t.pn) {
			buffer_appends(&dst, "<a href=\"");
			if (idx_msg[1].t.py != idx_msg[1].y ||
			    idx_msg[1].t.pm != idx_msg[1].m ||
			    idx_msg[1].t.pd != idx_msg[1].d)
				buffer_appendf(&dst, "../../../%u/%02u/%02u/",
				    MIN_YEAR + idx_msg[1].t.py, idx_msg[1].t.pm, idx_msg[1].t.pd);
			buffer_appendf(&dst, "%u\">[&lt;thread-prev]</a> ", idx_msg[1].t.pn);
		}
		if (idx_msg[1].t.nn) {
			buffer_appends(&dst, "<a href=\"");
			if (idx_msg[1].t.ny != idx_msg[1].y ||
			    idx_msg[1].t.nm != idx_msg[1].m ||
			    idx_msg[1].t.nd != idx_msg[1].d)
				buffer_appendf(&dst, "../../../%u/%02u/%02u/",
				    MIN_YEAR + idx_msg[1].t.ny, idx_msg[1].t.nm, idx_msg[1].t.nd);
			buffer_appendf(&dst, "%u\">[thread-next&gt;]</a> ", idx_msg[1].t.nn);
		}
		buffer_appends(&dst,
		    "<a href=\".\">[day]</a>"
		    " <a href=\"..\">[month]</a>"
		    " <a href=\"../..\">[year]</a>"
		    " <a href=\"../../..\">[list]</a>\n");

		buffer_appends(&dst, "<pre style=\"white-space: pre-wrap\">\n");
		if (date)
			buffer_append_header(&dst, date);
		if (from)
			buffer_append_header(&dst, from);
		if (to)
			buffer_append_header(&dst, to);
		if (cc)
			buffer_append_header(&dst, cc);
		if (subject)
			buffer_append_header(&dst, subject);

		if (!(html_flags & HTML_CENSOR))
		do {
			if (mime.entities->boundary) {
				body = mime_next_body_part(&mime);
				if (!body || body >= src.end)
					break;
				body = mime_next_body(&mime);
			}
			if (mime.entities->boundary)
				body = NULL;
			if (!body) {
				bend = mime_skip_body(&mime);
				if (!bend)
					break;
				continue;
			}

			/* mime_decode_body() will break mime vars, so,
			 * remember them now */
			char *filename = mime.entities->filename;
			char *type = mime.entities->type;
			const int isattachment = is_attachment(&mime);
			const int isinline = is_inline(&mime);
			int skip = 0;

			body = mime_decode_body(&mime, isattachment ? RECODE_NO : RECODE_YES, &bend);
			if (!body)
				break;
			if (bend >= src.end)
				skip = trunc;
			bend = src.ptr;
			if (!skip && isattachment) {
				int text = !strncasecmp(type, "text/", 5);
				attachment_count++;
				buffer_appendf(&dst, "\n<span style=\"font-family: times;\"><strong>"
				    "%s attachment \"</strong><a href=\"%u/%u\"%s>",
				    text ? "View" : "Download", n, attachment_count,
				    text ? "" :  " rel=\"nofollow\" download");
				if (filename)
					buffer_appends_html(&dst, filename);
				buffer_appends(&dst, "</a><strong>\" of type \"</strong>");
				buffer_appends_html(&dst, type);
				buffer_appends(&dst, "<strong>\"");
				if (body)
					buffer_appendf(&dst, " (%llu bytes)", (unsigned long long)(mime.dst.ptr - body));
				buffer_appends(&dst, "</strong></span>\n");
				continue;
			} else if (!isinline) {
				skip = 1;
			} else {
				skip = 0; /* do not skip non-attachments */
			}
			if (skip) {
				buffer_appends(&dst, "\n<span style=\"font-family: times;\"><strong>"
				    "Content of type \"</strong>");
				buffer_appends_html(&dst, type);
				buffer_appends(&dst, "<strong>\" skipped</strong></span>\n");
				continue;
			}
			/* inline */
			buffer_appendc(&dst, '\n');
			buffer_append_html_generic(&dst, body, mime.dst.ptr - body, 0, 1);
			mime.dst.ptr = body;
		} while (bend < src.end && mime.entities);

		if ((html_flags & HTML_CENSOR) || trunc)
			buffer_appendf(&dst, "\n<span style=\"font-family: times;\"><strong>"
			    "Content %s</strong></span>\n", (html_flags & HTML_CENSOR) ? "removed" : "truncated");

		buffer_appends(&dst, "</pre>\n");
	}

	buffer_free(&src);

	if (mime.dst.error || dst.error) {
		mime_free(&mime);
		buffer_free(&dst);
		return html_error(NULL);
	}

	mime_free(&mime);

	return html_send(&dst);
}