示例#1
0
static nserror mimesniff__compute_text_or_binary(const uint8_t *data, 
		size_t len, lwc_string **effective_type)
{
	if (data == NULL)
		return NSERROR_NEED_DATA;

	len = min(len, 512);

	if (len >= 3 && ((data[0] == 0xfe && data[1] == 0xff) ||
			(data[0] == 0xff && data[1] == 0xfe) ||
			(data[0] == 0xef && data[1] == 0xbb && 
				data[2] == 0xbf))) {
		/* Found a BOM => text/plain */
		*effective_type = lwc_string_ref(text_plain);
		return NSERROR_OK;
	}

	if (mimesniff__has_binary_octets(data, len) == false) {
		/* No binary octets => text/plain */
		*effective_type = lwc_string_ref(text_plain);
		return NSERROR_OK;
	}

	if (mimesniff__match_unknown(data, len, false, 
			effective_type) == NSERROR_OK)
		return NSERROR_OK;

	*effective_type = lwc_string_ref(application_octet_stream);

	return NSERROR_OK;
}
示例#2
0
static nserror mimesniff__compute_image(lwc_string *official_type,
		const uint8_t *data, size_t len, lwc_string **effective_type)
{
#define SIG(t, s) { (const uint8_t *) s, SLEN(s), t }
	static const struct it_s {
		const uint8_t *sig;
		size_t len;
		lwc_string **type;
	} image_types[] = {
		SIG(&image_gif,                "GIF87a"),
		SIG(&image_gif,                "GIF89a"),
		SIG(&image_png,                "\x89PNG\r\n\x1a\n"),
		SIG(&image_jpeg,               "\xff\xd8\xff"),
		SIG(&image_bmp,                "BM"),
		SIG(&image_vnd_microsoft_icon, "\x00\x00\x01\x00"),
		{ NULL, 0, NULL }
	};
#undef SIG

	const struct it_s *it;

	if (data == NULL) {
		lwc_string_unref(official_type);
		return NSERROR_NEED_DATA;
	}

	for (it = image_types; it->sig != NULL; it++) {
		if (it->len <= len && memcmp(data, it->sig, it->len) == 0) {
			lwc_string_unref(official_type);
			*effective_type = lwc_string_ref(*it->type);
			return NSERROR_OK;
		}
	}

	/* WebP has a signature that doesn't fit into the above table */
	if (SLEN("RIFF????WEBPVP") <= len && 
			memcmp(data, "RIFF", SLEN("RIFF")) == 0 && 
			memcmp(data + SLEN("RIFF????"), 
					"WEBPVP", SLEN("WEBPVP")) == 0 ) {
		lwc_string_unref(official_type);
		*effective_type = lwc_string_ref(image_webp);
		return NSERROR_OK;
	}

	*effective_type = official_type;

	return NSERROR_OK;
}
示例#3
0
/**
 * Make the dom_string be interned
 *
 * \param str     The dom_string to be interned
 * \param lwcstr  The result lwc_string	
 * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
 */
dom_exception dom_string_intern(dom_string *str, 
		struct lwc_string_s **lwcstr)
{
	dom_string_internal *istr = (dom_string_internal *) str;
	/* If this string is already interned, do nothing */
	if (istr->type != DOM_STRING_INTERNED) {
		lwc_string *ret;
		lwc_error lerr;

		lerr = lwc_intern_string((const char *) istr->data.cdata.ptr, 
				istr->data.cdata.len, &ret);
		if (lerr != lwc_error_ok) {
			return _dom_exception_from_lwc_error(lerr);
		}

		free(istr->data.cdata.ptr);

		istr->data.intern = ret;

		istr->type = DOM_STRING_INTERNED;
	}

	*lwcstr = lwc_string_ref(istr->data.intern);

	return DOM_NO_ERR;
}
示例#4
0
static nserror mimesniff__match_unknown_exact(const uint8_t *data, size_t len,
		bool allow_unsafe, lwc_string **effective_type)
{
#define SIG(t, s, x) { (const uint8_t *) s, SLEN(s), x, t }
	static const struct map_s exact_match_types[] = {
		SIG(&image_gif,                    "GIF87a",            true),
		SIG(&image_gif,                    "GIF89a",            true),
		SIG(&image_png,                    "\x89PNG\r\n\x1a\n", true),
		SIG(&image_jpeg,                   "\xff\xd8\xff",      true),
		SIG(&image_bmp,                    "BM",                true),
		SIG(&image_vnd_microsoft_icon,     "\x00\x00\x01\x00",  true),
		SIG(&application_ogg,              "OggS\x00",          true),
		SIG(&video_webm,                   "\x1a\x45\xdf\xa3",  true),
		SIG(&application_x_rar_compressed, "Rar \x1a\x07\x00",  true),
		SIG(&application_zip,              "PK\x03\x04",        true),
		SIG(&application_x_gzip,           "\x1f\x8b\x08",      true),
		SIG(&application_postscript,       "%!PS-Adobe-",       true),
		SIG(&application_pdf,              "%PDF-",             false),
		{ NULL, 0, false, NULL }
	};
#undef SIG
	const struct map_s *it;

	for (it = exact_match_types; it->sig != NULL; it++) {
		if (it->len <= len && memcmp(data, it->sig, it->len) == 0 &&
				(allow_unsafe || it->safe)) {
			*effective_type = lwc_string_ref(*it->type);
			return NSERROR_OK;
		}
	}

	return NSERROR_NOT_FOUND;
}
示例#5
0
END_TEST

START_TEST (test_lwc_string_ref_unref_ok)
{
    lwc_string_ref(intern_one);
    lwc_string_unref(intern_one);
}
示例#6
0
END_TEST

START_TEST (test_lwc_string_ref_ok)
{
    fail_unless(lwc_string_ref(intern_one) == intern_one,
                "Oddly, reffing a string didn't return it");
}
示例#7
0
css_error node_classes(void *pw, void *n,
		lwc_string ***classes, uint32_t *n_classes)
{
	node *node = n;
	uint32_t i;
	line_ctx *lc = pw;

	for (i = 0; i < node->n_attrs; i++) {
		bool amatch = false;
		assert(lwc_string_caseless_isequal(
				node->attrs[i].name, lc->attr_class, &amatch) ==
				lwc_error_ok);
		if (amatch == true)
			break;
	}

	if (i != node->n_attrs) {
		*classes = realloc(NULL, sizeof(lwc_string **));
		if (*classes == NULL)
			return CSS_NOMEM;

		*(classes[0]) = 
			lwc_string_ref(node->attrs[i].value);
		*n_classes = 1;
	} else {
		*classes = NULL;
		*n_classes = 0;
	}

	return CSS_OK;

}
示例#8
0
/* exported interface documented in content/content_protected.h */
lwc_string *content__get_mime_type(struct content *c)
{
	if (c == NULL)
		return NULL;

	return lwc_string_ref(c->mime_type);
}
示例#9
0
bool content__add_rfc5988_link(struct content *c, 
		const struct content_rfc5988_link *link)
{
	struct content_rfc5988_link *newlink;	
	union content_msg_data msg_data;

	/* a link relation must be present for it to be a link */
	if (link->rel == NULL) {
		return false;
	}

	/* a link href must be present for it to be a link */
	if (link->href == NULL) {
		return false;
	}

	newlink = calloc(1, sizeof(struct content_rfc5988_link));
	if (newlink == NULL) {
		return false; 
	}

	/* copy values */
	newlink->rel = lwc_string_ref(link->rel);
	newlink->href = nsurl_ref(link->href);
	if (link->hreflang != NULL) {
		newlink->hreflang = lwc_string_ref(link->hreflang);
	}
	if (link->type != NULL) {
		newlink->type = lwc_string_ref(link->type);
	}
	if (link->media != NULL) {
		newlink->media = lwc_string_ref(link->media);
	}
	if (link->sizes != NULL) {
		newlink->sizes = lwc_string_ref(link->sizes);
	}

	/* add to metadata link to list */
	newlink->next = c->links;
	c->links = newlink;

	/* broadcast the data */
	msg_data.rfc5988_link = newlink;
	content_broadcast(c, CONTENT_MSG_LINK, msg_data);

	return true;
}
示例#10
0
文件: content.c 项目: ysei/NetSurf
nserror content__init(struct content *c, const content_handler *handler,
		lwc_string *imime_type, const http_parameter *params,
		llcache_handle *llcache, const char *fallback_charset, 
		bool quirks)
{
	struct content_user *user_sentinel;
	nserror error;
	
	LOG(("url "URL_FMT_SPC" -> %p", 
	     nsurl_access(llcache_handle_get_url(llcache)), c));

	user_sentinel = calloc(1, sizeof(struct content_user));
	if (user_sentinel == NULL) {
		return NSERROR_NOMEM;
	}

	if (fallback_charset != NULL) {
		c->fallback_charset = strdup(fallback_charset);
		if (c->fallback_charset == NULL) {
			free(user_sentinel);
			return NSERROR_NOMEM;
		}
	}

	c->llcache = llcache;
	c->mime_type = lwc_string_ref(imime_type);
	c->handler = handler;
	c->status = CONTENT_STATUS_LOADING;
	c->width = 0;
	c->height = 0;
	c->available_width = 0;
	c->quirks = quirks;
	c->refresh = 0;
	c->time = wallclock();
	c->size = 0;
	c->title = NULL;
	c->active = 0;
	user_sentinel->callback = NULL;
	user_sentinel->pw = NULL;
	user_sentinel->next = NULL;
	c->user_list = user_sentinel;
	c->sub_status[0] = 0;
	c->locked = false;
	c->total_size = 0;
	c->http_code = 0;
	c->error_count = 0;

	content_set_status(c, messages_get("Loading"));

	/* Finally, claim low-level cache events */
	error = llcache_handle_change_callback(llcache, 
			content_llcache_callback, c);
	if (error != NSERROR_OK) {
		lwc_string_unref(c->mime_type);
		return error;
	}

	return NSERROR_OK;
}
示例#11
0
/**
 * Cache a CURL handle for the provided host (if wanted)
 */
static void fetch_curl_cache_handle(CURL *handle, lwc_string *host)
{
#if LIBCURL_VERSION_NUM >= 0x071e00
	/* 7.30.0 or later has its own connection caching; suppress ours */
	curl_easy_cleanup(handle);
	return;
#else
	struct cache_handle *h = 0;
	int c;
	RING_FINDBYLWCHOST(curl_handle_ring, h, host);
	if (h) {
		/* Already have a handle cached for this hostname */
		curl_easy_cleanup(handle);
		return;
	}
	/* We do not have a handle cached, first up determine if the cache is full */
	RING_GETSIZE(struct cache_handle, curl_handle_ring, c);
	if (c >= nsoption_int(max_cached_fetch_handles)) {
		/* Cache is full, so, we rotate the ring by one and
		 * replace the oldest handle with this one. We do this
		 * without freeing/allocating memory (except the
		 * hostname) and without removing the entry from the
		 * ring and then re-inserting it, in order to be as
		 * efficient as we can.
		 */
		if (curl_handle_ring != NULL) {
			h = curl_handle_ring;
			curl_handle_ring = h->r_next;
			curl_easy_cleanup(h->handle);
			h->handle = handle;
			lwc_string_unref(h->host);
			h->host = lwc_string_ref(host);
		} else {
			/* Actually, we don't want to cache any handles */
			curl_easy_cleanup(handle);
		}

		return;
	}
	/* The table isn't full yet, so make a shiny new handle to add to the ring */
	h = (struct cache_handle*)malloc(sizeof(struct cache_handle));
	h->handle = handle;
	h->host = lwc_string_ref(host);
	RING_INSERT(curl_handle_ring, h);
#endif
}
示例#12
0
css_error node_name(void *pw, void *n, css_qname *qname)
{
	node *node = n;

	UNUSED(pw);
	
	qname->name = lwc_string_ref(node->name);
	
	return CSS_OK;
}
示例#13
0
static css_error resolve_url(void *pw,
		const char *base, lwc_string *rel, lwc_string **abs)
{
	UNUSED(pw);
	UNUSED(base);

	/* About as useless as possible */
	*abs = lwc_string_ref(rel);

	return CSS_OK;
}
示例#14
0
static nserror mimesniff__compute_unknown(const uint8_t *data, size_t len,
		lwc_string **effective_type)
{
	if (data == NULL)
		return NSERROR_NEED_DATA;

	len = min(len, 512);

	if (mimesniff__match_unknown(data, len, true, 
			effective_type) == NSERROR_OK)
		return NSERROR_OK;

	if (mimesniff__has_binary_octets(data, len) == false) {
		/* No binary octets => text/plain */
		*effective_type = lwc_string_ref(text_plain);
		return NSERROR_OK;
	}

	*effective_type = lwc_string_ref(application_octet_stream);

	return NSERROR_OK;
}
示例#15
0
/**
 * Set a font-face's font-family name
 *
 * \param font_face    The font-face
 * \param font_family  Font-family name
 * \param result       Pointer to location to receive result
 * \return CSS_OK on success,
 *         CSS_BADPARM on bad parameters.
 */
css_error css__font_face_set_font_family(css_font_face *font_face,
		lwc_string *font_family)
{
	if (font_face == NULL || font_family == NULL)
		return CSS_BADPARM;
	
	if (font_face->font_family != NULL)
		lwc_string_unref(font_face->font_family);
		
	font_face->font_family = lwc_string_ref(font_family);

	return CSS_OK;
}
示例#16
0
void fetch_data_register(void)
{
	lwc_string *scheme = lwc_string_ref(corestring_lwc_data);

	fetch_add_fetcher(scheme,
		fetch_data_initialise,
		fetch_data_can_fetch,
		fetch_data_setup,
		fetch_data_start,
		fetch_data_abort,
		fetch_data_free,
		fetch_data_poll,
		fetch_data_finalise);
}
示例#17
0
static css_error node_classes(void *pw, void *n,
		lwc_string ***classes, uint32_t *n_classes)
{
	unsigned int i;
	node *node = n;
	UNUSED(pw);

	*classes = node->classes;
	*n_classes = node->n_classes;

	for (i = 0; i < *n_classes; i++)
		(*classes)[i] = lwc_string_ref(node->classes[i]);

	return CSS_OK;

}
示例#18
0
/**
 * Register javascript scheme fetcher with fetcher factory.
 *
 * \return NSERROR_OK on success or appropriate error code on faliure.
*/
nserror fetch_javascript_register(void)
{
	lwc_string *scheme = lwc_string_ref(corestring_lwc_javascript);
	const struct fetcher_operation_table fetcher_ops = {
		.initialise = fetch_javascript_initialise,
		.acceptable = fetch_javascript_can_fetch,
		.setup = fetch_javascript_setup,
		.start = fetch_javascript_start,
		.abort = fetch_javascript_abort,
		.free = fetch_javascript_free,
		.poll = fetch_javascript_poll,
		.finalise = fetch_javascript_finalise
	};

	return fetcher_add(scheme, &fetcher_ops);
}
示例#19
0
static nserror mimesniff__match_unknown_bom(const uint8_t *data, size_t len,
		lwc_string **effective_type)
{
#define SIG(t, s, x) { (const uint8_t *) s, SLEN(s), x, t }
	static const struct map_s bom_match_types[] = {
		SIG(&text_plain, "\xfe\xff",     false),
		SIG(&text_plain, "\xff\xfe",     false),
		SIG(&text_plain, "\xef\xbb\xbf", false),
		{ NULL, 0, false, NULL }
	};
#undef SIG
	const struct map_s *it;

	for (it = bom_match_types; it->sig != NULL; it++) {
		if (it->len <= len && memcmp(data, it->sig, it->len) == 0) {
			*effective_type = lwc_string_ref(*it->type);
			return NSERROR_OK;
		}
	}

	return NSERROR_NOT_FOUND;
}
示例#20
0
/**
 * Create a string from a list of IDENT/S tokens if the next token is IDENT
 * or references the next token's string if it is a STRING
 *
 * \param c          Parsing context
 * \param vector     Vector containing tokens
 * \param ctx        Vector iteration context
 * \param reserved   Callback to determine if an identifier is reserved
 * \param result     Pointer to location to receive resulting string
 * \return CSS_OK on success, appropriate error otherwise.
 *
 * Post condition: \a *ctx is updated with the next token to process
 *                 If the input is invalid, then \a *ctx remains unchanged.
 *
 *                 The resulting string's reference is passed to the caller
 */
css_error css__ident_list_or_string_to_string(css_language *c,
		const parserutils_vector *vector, int *ctx,
		bool (*reserved)(css_language *c, const css_token *ident),
		lwc_string **result)
{
	const css_token *token;
	
	token = parserutils_vector_peek(vector, *ctx);
	if (token == NULL)
		return CSS_INVALID;
	
	if (token->type == CSS_TOKEN_STRING) {
		token = parserutils_vector_iterate(vector, ctx);
		*result = lwc_string_ref(token->idata);
		return CSS_OK;
	} else 	if(token->type == CSS_TOKEN_IDENT) {
		return css__ident_list_to_string(c, vector, ctx, reserved,
				result);
	}
	
	return CSS_INVALID;
}
示例#21
0
css_error node_id(void *pw, void *n,
		lwc_string **id)
{
	node *node = n;
	uint32_t i;
	line_ctx *lc = pw;

	for (i = 0; i < node->n_attrs; i++) {
		bool amatch = false;
		assert(lwc_string_caseless_isequal(
				node->attrs[i].name, lc->attr_id, &amatch) == 
				lwc_error_ok);
		if (amatch == true)
			break;
	}

	if (i != node->n_attrs)
		*id = lwc_string_ref(node->attrs[i].value);
	else
		*id = NULL;

	return CSS_OK;
}
示例#22
0
static nserror mimesniff__match_unknown_riff(const uint8_t *data, size_t len,
		lwc_string **effective_type)
{
#define SIG(t, s, x) { (const uint8_t *) s, SLEN(s), x, t }
	static const struct map_s riff_match_types[] = {
		SIG(&image_webp, "WEBPVP", true),
		SIG(&audio_wave, "WAVE",   true),
		{ NULL, 0, false, NULL }
	};
#undef SIG
	const struct map_s *it;

	for (it = riff_match_types; it->sig != NULL; it++) {
		if (it->len + SLEN("RIFF????") <= len && 
				memcmp(data, "RIFF", SLEN("RIFF")) == 0 &&
				memcmp(data + SLEN("RIFF????"), 
						it->sig, it->len) == 0) {
			*effective_type = lwc_string_ref(*it->type);
			return NSERROR_OK;
		}
	}

	return NSERROR_NOT_FOUND;
}
示例#23
0
/**
 * Parse content
 *
 * \param c	  Parsing context
 * \param vector  Vector of tokens to process
 * \param ctx	  Pointer to vector iteration context
 * \param result  Pointer to location to receive resulting style
 * \return CSS_OK on success,
 *	   CSS_NOMEM on memory exhaustion,
 *	   CSS_INVALID if the input is not valid
 *
 * Post condition: \a *ctx is updated with the next token to process
 *		   If the input is invalid, then \a *ctx remains unchanged.
 */
css_error css__parse_content(css_language *c,
		const parserutils_vector *vector, int *ctx,
		css_style *result)
{
	int orig_ctx = *ctx;
	css_error error;
	const css_token *token;
	bool match;

	/* IDENT(normal, none, inherit) | [ ... ]+ */
	token = parserutils_vector_iterate(vector, ctx);
	if (token == NULL) {
		*ctx = orig_ctx;
		return CSS_INVALID;
	}


	if ((token->type == CSS_TOKEN_IDENT) &&
	    (lwc_string_caseless_isequal(token->idata,
					 c->strings[INHERIT],
					 &match) == lwc_error_ok && match)) {
		error = css_stylesheet_style_inherit(result, CSS_PROP_CONTENT);
	} else if ((token->type == CSS_TOKEN_IDENT) &&
		   (lwc_string_caseless_isequal(token->idata,
						c->strings[NORMAL],
						&match) == lwc_error_ok && match)) {
		error = css__stylesheet_style_appendOPV(result, CSS_PROP_CONTENT, 0, CONTENT_NORMAL);
	} else if ((token->type == CSS_TOKEN_IDENT) &&
		   (lwc_string_caseless_isequal(token->idata,
						c->strings[NONE],
						&match) == lwc_error_ok && match)) {
		error = css__stylesheet_style_appendOPV(result, CSS_PROP_CONTENT, 0, CONTENT_NONE);
	} else {

/* Macro to output the value marker, awkward because we need to check
 * first to determine how the value is constructed.
 */
#define CSS_APPEND(CSSVAL) css__stylesheet_style_append(result, first?buildOPV(CSS_PROP_CONTENT, 0, CSSVAL):CSSVAL)

		bool first = true;
		int prev_ctx = orig_ctx;

		/* [
		 *   IDENT(open-quote, close-quote, no-open-quote,
		 *         no-close-quote) |
		 *   STRING |
		 *   URI |
		 *   FUNCTION(attr) IDENT ')' |
		 *   FUNCTION(counter) IDENT IDENT? ')' |
		 *   FUNCTION(counters) IDENT STRING IDENT? ')'
		 * ]+
		 */

		while (token != NULL) {
			if ((token->type == CSS_TOKEN_IDENT) &&
			    (lwc_string_caseless_isequal(
				    token->idata, c->strings[OPEN_QUOTE],
				    &match) == lwc_error_ok && match)) {

				error = CSS_APPEND(CONTENT_OPEN_QUOTE);

			} else if (token->type == CSS_TOKEN_IDENT &&
				   (lwc_string_caseless_isequal(
					   token->idata, c->strings[CLOSE_QUOTE],
					   &match) == lwc_error_ok && match)) {

				error = CSS_APPEND(CONTENT_CLOSE_QUOTE);
			} else if (token->type == CSS_TOKEN_IDENT &&
				   (lwc_string_caseless_isequal(
					   token->idata, c->strings[NO_OPEN_QUOTE],
					   &match) == lwc_error_ok && match)) {
				error = CSS_APPEND(CONTENT_NO_OPEN_QUOTE);
			} else if (token->type == CSS_TOKEN_IDENT &&
				   (lwc_string_caseless_isequal(
					   token->idata, c->strings[NO_CLOSE_QUOTE],
					   &match) == lwc_error_ok && match)) {
				error = CSS_APPEND(CONTENT_NO_CLOSE_QUOTE);
			} else if (token->type == CSS_TOKEN_STRING) {
				uint32_t snumber;

				error = css__stylesheet_string_add(c->sheet, lwc_string_ref(token->idata), &snumber);
				if (error != CSS_OK) {
					*ctx = orig_ctx;
					return error;
				}

				error = CSS_APPEND(CONTENT_STRING);
				if (error != CSS_OK) {
					*ctx = orig_ctx;
					return error;
				}

				error = css__stylesheet_style_append(result, snumber);
			} else if (token->type == CSS_TOKEN_URI) {
				lwc_string *uri;
				uint32_t uri_snumber;

				error = c->sheet->resolve(c->sheet->resolve_pw,
							  c->sheet->url,
							  token->idata, 
							  &uri);
				if (error != CSS_OK) {
					*ctx = orig_ctx;
					return error;
				}

				error = css__stylesheet_string_add(c->sheet, 
								  uri, 
								  &uri_snumber);
				if (error != CSS_OK) {
					*ctx = orig_ctx;
					return error;
				}

				error = CSS_APPEND(CONTENT_URI);
				if (error != CSS_OK) {
					*ctx = orig_ctx;
					return error;
				}

				error = css__stylesheet_style_append(result, uri_snumber);
			} else if (token->type == CSS_TOKEN_FUNCTION &&
				   (lwc_string_caseless_isequal(
					   token->idata, c->strings[ATTR],
					   &match) == lwc_error_ok && match)) {
				uint32_t snumber;

				consumeWhitespace(vector, ctx);

				/* Expect IDENT */
				token = parserutils_vector_iterate(vector, ctx);
				if (token == NULL || token->type != CSS_TOKEN_IDENT) {
					*ctx = orig_ctx;
					return CSS_INVALID;
				}

				error = css__stylesheet_string_add(c->sheet, lwc_string_ref(token->idata), &snumber);
				if (error != CSS_OK) {
					*ctx = orig_ctx;
					return error;
				}

				error = CSS_APPEND(CONTENT_ATTR);
				if (error != CSS_OK) {
					*ctx = orig_ctx;
					return error;
				}

				error = css__stylesheet_style_append(result, snumber);

				consumeWhitespace(vector, ctx);

				/* Expect ')' */
				token = parserutils_vector_iterate(vector, ctx);
				if (token == NULL || tokenIsChar(token, ')') == false) {
					*ctx = orig_ctx;
					return CSS_INVALID;
				}
			} else if (token->type == CSS_TOKEN_FUNCTION &&
				   (lwc_string_caseless_isequal(
					   token->idata, c->strings[COUNTER],
					   &match) == lwc_error_ok && match)) {
				lwc_string *name;
				uint32_t snumber;
				uint32_t opv;

				opv = CONTENT_COUNTER;

				consumeWhitespace(vector, ctx);

				/* Expect IDENT */
				token = parserutils_vector_iterate(vector, ctx);
				if (token == NULL || token->type != CSS_TOKEN_IDENT) {
					*ctx = orig_ctx;
					return CSS_INVALID;
				}

				name = token->idata;

				consumeWhitespace(vector, ctx);

				/* Possible ',' */
				token = parserutils_vector_peek(vector, *ctx);
				if (token == NULL ||
				    (tokenIsChar(token, ',') == false &&
				     tokenIsChar(token, ')') == false)) {
					*ctx = orig_ctx;
					return CSS_INVALID;
				}

				if (tokenIsChar(token, ',')) {
					uint16_t v;

					parserutils_vector_iterate(vector, ctx);

					consumeWhitespace(vector, ctx);

					/* Expect IDENT */
					token = parserutils_vector_peek(vector, *ctx);
					if (token == NULL || token->type !=
					    CSS_TOKEN_IDENT) {
						*ctx = orig_ctx;
						return CSS_INVALID;
					}

					error = css__parse_list_style_type_value(c, token, &v);
					if (error != CSS_OK) {
						*ctx = orig_ctx;
						return error;
					}

					opv |= v << CONTENT_COUNTER_STYLE_SHIFT;

					parserutils_vector_iterate(vector, ctx);

					consumeWhitespace(vector, ctx);
				} else {
					opv |= LIST_STYLE_TYPE_DECIMAL <<
						CONTENT_COUNTER_STYLE_SHIFT;
				}

				/* Expect ')' */
				token = parserutils_vector_iterate(vector, ctx);
				if (token == NULL || tokenIsChar(token,	')') == false) {
					*ctx = orig_ctx;
					return CSS_INVALID;
				}


				error = css__stylesheet_string_add(c->sheet, lwc_string_ref(name), &snumber);
				if (error != CSS_OK) {
					*ctx = orig_ctx;
					return error;
				}

				error = CSS_APPEND(opv);
				if (error != CSS_OK) {
					*ctx = orig_ctx;
					return error;
				}

				error = css__stylesheet_style_append(result, snumber);
			} else if (token->type == CSS_TOKEN_FUNCTION &&
				   (lwc_string_caseless_isequal(
					   token->idata, c->strings[COUNTERS],
					   &match) == lwc_error_ok && match)) {
				lwc_string *name;
				lwc_string *sep;
				uint32_t name_snumber;
				uint32_t sep_snumber;
				uint32_t opv;

				opv = CONTENT_COUNTERS;

				consumeWhitespace(vector, ctx);

				/* Expect IDENT */
				token = parserutils_vector_iterate(vector, ctx);
				if (token == NULL || token->type != CSS_TOKEN_IDENT) {
					*ctx = orig_ctx;
					return CSS_INVALID;
				}

				name = token->idata;

				consumeWhitespace(vector, ctx);

				/* Expect ',' */
				token = parserutils_vector_iterate(vector, ctx);
				if (token == NULL || tokenIsChar(token, ',') == false) {
					*ctx = orig_ctx;
					return CSS_INVALID;
				}

				consumeWhitespace(vector, ctx);

				/* Expect STRING */
				token = parserutils_vector_iterate(vector, ctx);
				if (token == NULL || token->type != CSS_TOKEN_STRING) {
					*ctx = orig_ctx;
					return CSS_INVALID;
				}

				sep = token->idata;

				consumeWhitespace(vector, ctx);

				/* Possible ',' */
				token = parserutils_vector_peek(vector, *ctx);
				if (token == NULL ||
				    (tokenIsChar(token, ',') == false &&
				     tokenIsChar(token, ')') == false)) {
					*ctx = orig_ctx;
					return CSS_INVALID;
				}

				if (tokenIsChar(token, ',')) {
					uint16_t v;

					parserutils_vector_iterate(vector, ctx);

					consumeWhitespace(vector, ctx);

					/* Expect IDENT */
					token = parserutils_vector_peek(vector, *ctx);
					if (token == NULL || token->type !=
					    CSS_TOKEN_IDENT) {
						*ctx = orig_ctx;
						return CSS_INVALID;
					}

					error = css__parse_list_style_type_value(c,
									    token, &v);
					if (error != CSS_OK) {
						*ctx = orig_ctx;
						return error;
					}

					opv |= v << CONTENT_COUNTERS_STYLE_SHIFT;

					parserutils_vector_iterate(vector, ctx);

					consumeWhitespace(vector, ctx);
				} else {
					opv |= LIST_STYLE_TYPE_DECIMAL <<
						CONTENT_COUNTERS_STYLE_SHIFT;
				}

				/* Expect ')' */
				token = parserutils_vector_iterate(vector, ctx);
				if (token == NULL || tokenIsChar(token, ')') == false) {
					*ctx = orig_ctx;
					return CSS_INVALID;
				}


				error = css__stylesheet_string_add(c->sheet, lwc_string_ref(name), &name_snumber);
				if (error != CSS_OK) {
					*ctx = orig_ctx;
					return error;
				}

				error = css__stylesheet_string_add(c->sheet, lwc_string_ref(sep), &sep_snumber);
				if (error != CSS_OK) {
					*ctx = orig_ctx;
					return error;
				}

				error = CSS_APPEND(opv);
				if (error != CSS_OK) {
					*ctx = orig_ctx;
					return error;
				}

				error = css__stylesheet_style_append(result, name_snumber);
				if (error != CSS_OK) {
					*ctx = orig_ctx;
					return error;
				}

				error = css__stylesheet_style_append(result, sep_snumber);
			} else if (first) {
				/* Invalid if this is the first iteration */
				error = CSS_INVALID;
			} else {
				/* Give up, ensuring current token is reprocessed */
				*ctx = prev_ctx;
				error = CSS_OK;
				break;
			}

			/* if there was an error bail */
			if (error != CSS_OK) {
				*ctx = orig_ctx;
				return error;
			}

			first = false;

			consumeWhitespace(vector, ctx);

			prev_ctx = *ctx;
			token = parserutils_vector_iterate(vector, ctx);
		} /* while */

		/* Write list terminator */
		css__stylesheet_style_append(result, CONTENT_NORMAL);
	}

	if (error != CSS_OK)
		*ctx = orig_ctx;

	return error;
}
示例#24
0
void css__parse_tree_data(line_ctx *ctx, const char *data, size_t len)
{
	const char *p = data;
	const char *end = data + len;
	const char *name = NULL;
	const char *value = NULL;
	size_t namelen = 0;
	size_t valuelen = 0;
	uint32_t depth = 0;
	bool target = false;

	/* ' '{depth+1} [ <element> '*'? | <attr> ]
	 * 
	 * <element> ::= [^=*[:space:]]+
	 * <attr>    ::= [^=*[:space:]]+ '=' [^[:space:]]*
	 */

	while (p < end && isspace(*p)) {
		depth++;
		p++;
	}
	depth--;

	/* Get element/attribute name */
	name = p;
	while (p < end && *p != '=' && *p != '*' && isspace(*p) == false) {
		namelen++;
		p++;
	}

	/* Skip whitespace */
	while (p < end && isspace(*p))
		p++;

	if (p < end && *p == '=') {
		/* Attribute value */
		p++;

		value = p;

		while (p < end && isspace(*p) == false) {
			valuelen++;
			p++;
		}
	} else if (p < end && *p == '*') {
		/* Element is target node */
		target = true;
	}

	if (value == NULL) {
		/* We have an element, so create it */
		node *n = malloc(sizeof(node));
		assert(n != NULL);

		memset(n, 0, sizeof(node));
		
		lwc_intern_string(name, namelen, &n->name);

		/* Insert it into tree */
		if (ctx->tree == NULL) {
			ctx->tree = n;
		} else {
			assert(depth > 0);
			assert(depth <= ctx->depth + 1);

			/* Find node to insert into */
			while (depth <= ctx->depth) {
				ctx->depth--;
				ctx->current = ctx->current->parent;
			}

			/* Insert into current node */
			if (ctx->current->children == NULL) {
				ctx->current->children = n;
				ctx->current->last_child = n;
			} else {
				ctx->current->last_child->next = n;
				n->prev = ctx->current->last_child;

				ctx->current->last_child = n;
			}
			n->parent = ctx->current;
		}

		ctx->current = n;
		ctx->depth = depth;

		/* Mark the target, if it's us */
		if (target)
			ctx->target = n;
	} else {
		/* New attribute */
		bool amatch = false;
		attribute *attr;
		node *n = ctx->current;

		attribute *temp = realloc(n->attrs,
				(n->n_attrs + 1) * sizeof(attribute));
		assert(temp != NULL);

		n->attrs = temp;

		attr = &n->attrs[n->n_attrs];
		
		lwc_intern_string(name, namelen, &attr->name);
		lwc_intern_string(value, valuelen, &attr->value);

		assert(lwc_string_caseless_isequal(
				n->attrs[n->n_attrs].name,
				ctx->attr_class, &amatch) == lwc_error_ok);
		if (amatch == true) {
			n->classes = realloc(NULL, sizeof(lwc_string **));
			assert(n->classes != NULL);

			n->classes[0] = lwc_string_ref(
					n->attrs[n->n_attrs].
					value);
			n->n_classes = 1;
		}

		n->n_attrs++;
	}
}
extern void rust_lwc_string_ref(lwc_string *str) {
  lwc_string_ref(str);
}
示例#26
0
/**
 * Clone a history entry
 *
 * \param history opaque history structure, as returned by history_create()
 * \param entry   entry to clone
 * \return A cloned history entry or NULL on error
 */
static struct history_entry *
browser_window_history__clone_entry(struct history *history,
				    struct history_entry *entry)
{
	struct history_entry *child;
	struct history_entry *new_child;
	struct history_entry *prev = NULL;
	struct history_entry *new_entry;

	assert(entry->page.url);
	assert(entry->page.title);

	/* clone the entry */
	new_entry = malloc(sizeof *entry);
	if (!new_entry)
		return NULL;

	memcpy(new_entry, entry, sizeof *entry);
	new_entry->page.url = nsurl_ref(entry->page.url);
	if (entry->page.frag_id)
		new_entry->page.frag_id = lwc_string_ref(entry->page.frag_id);

	new_entry->page.title = strdup(entry->page.title);
	if (!new_entry->page.url || !new_entry->page.title ||
			((entry->page.frag_id) && (!new_entry->page.frag_id))) {
		nsurl_unref(new_entry->page.url);
		if (new_entry->page.frag_id)
			lwc_string_unref(new_entry->page.frag_id);
		free(new_entry->page.title);
		free(new_entry);
		return NULL;
	}

	/* update references */
	if (history->current == entry)
		history->current = new_entry;

	/* recurse for all children */
	for (child = new_entry->forward; child; child = child->next) {
		new_child = browser_window_history__clone_entry(history, child);
		if (new_child) {
			new_child->back = new_entry;
		} else {
			nsurl_unref(new_entry->page.url);
			if (new_entry->page.frag_id)
				lwc_string_unref(new_entry->page.frag_id);
			free(new_entry->page.title);
			free(new_entry);
			return NULL;
		}
		if (prev)
			prev->next = new_child;
		if (new_entry->forward == child)
			new_entry->forward = new_child;
		if (new_entry->forward_pref == child)
			new_entry->forward_pref = new_child;
		if (new_entry->forward_last == child)
			new_entry->forward_last = new_child;
		prev = new_child;
	}
	return new_entry;
}
示例#27
0
/**
 * Recursively redraw a history_entry.
 *
 * \param history history containing the entry
 * \param entry entry to render
 * \param x0 area top left x coordinate
 * \param y0 area top left y coordinate
 * \param x1 area bottom right x coordinate
 * \param y1 area bottom right y coordinate
 * \param x window x offset
 * \param y window y offset
 * \param clip clip redraw
 * \param ctx     current redraw context
 */
static bool
browser_window_history__redraw_entry(struct history *history,
		struct history_entry *entry,
		int x0, int y0, int x1, int y1,
		int x, int y, bool clip,
		const struct redraw_context *ctx)
{
	const struct plotter_table *plot = ctx->plot;
	size_t char_offset;
	int actual_x;
	struct history_entry *child;
	colour c = entry == history->current ?
			HISTORY_COLOUR_SELECTED : HISTORY_COLOUR_FOREGROUND;
	int tailsize = 5;
	int xoffset = x - x0;
	int yoffset = y - y0;
        plot_style_t pstyle_history_rect = { 
            .stroke_type = PLOT_OP_TYPE_SOLID,
            .stroke_colour = c,
            .stroke_width = entry == history->current ? 3 : 1,
        };
	plot_font_style_t fstyle = *plot_style_font;

	if (clip) {
		struct rect rect;
		rect.x0 = x0 + xoffset;
		rect.y0 = y0 + yoffset;
		rect.x1 = x1 + xoffset;
		rect.y1 = y1 + yoffset;
		if (!plot->clip(&rect)) {
			return false;
		}
	}

	/* Only attempt to plot bitmap if it is present */
	if (entry->bitmap != NULL) {
		plot->bitmap(entry->x + xoffset,
			     entry->y + yoffset,
			     WIDTH, HEIGHT,
			     entry->bitmap, 0xffffff, 0);
	}
	if (!plot->rectangle(entry->x - 1 + xoffset, 
                            entry->y - 1 + yoffset,
                            entry->x + xoffset + WIDTH, 
                            entry->y + yoffset + HEIGHT,
                            &pstyle_history_rect))
		return false;

	if (!nsfont.font_position_in_string(plot_style_font, entry->page.title,
			strlen(entry->page.title), WIDTH,
			&char_offset, &actual_x))
		return false;

	fstyle.background = HISTORY_COLOUR_BACKGROUND;
	fstyle.foreground = c;
	fstyle.weight = entry == history->current ? 900 : 400;

	if (!plot->text(entry->x + xoffset, entry->y + HEIGHT + 12 + yoffset,
			entry->page.title, char_offset, &fstyle))
		return false;

	for (child = entry->forward; child; child = child->next) {
		if (!plot->line(entry->x + WIDTH + xoffset,
				entry->y + HEIGHT / 2 + yoffset,
		      	entry->x + WIDTH + tailsize + xoffset,
				entry->y + HEIGHT / 2 + yoffset, 
			       plot_style_stroke_history))
			return false;
		if (!plot->line(entry->x + WIDTH + tailsize + xoffset,
			       entry->y + HEIGHT / 2 + yoffset,
			       child->x - tailsize +xoffset,
			       child->y + HEIGHT / 2 + yoffset,
			       plot_style_stroke_history))
			return false;
		if (!plot->line(child->x - tailsize + xoffset,
			       child->y + HEIGHT / 2 + yoffset,
			       child->x + xoffset, child->y +
			       			HEIGHT / 2 + yoffset,
			       plot_style_stroke_history))
			return false;
		if (!browser_window_history__redraw_entry(history, child,
				x0, y0, x1, y1, x, y, clip, ctx))
			return false;
	}

	return true;
}


/**
 * Find the history entry at a position.
 *
 * \param  entry  entry to search from
 * \param  x      coordinate
 * \param  y      coordinate
 * \return  an entry if found, 0 if none
 */

static struct history_entry *browser_window_history__find_position(
		struct history_entry *entry, int x, int y)
{
	struct history_entry *child;
	struct history_entry *found;

	if (!entry)
		return 0;

	if (entry->x <= x && x <= entry->x + WIDTH &&
			entry->y <= y && y <= entry->y + HEIGHT)
		return entry;

	for (child = entry->forward; child; child = child->next) {
		found = browser_window_history__find_position(child, x, y);
		if (found)
			return found;
	}

	return 0;
}

/**
 * Enumerate subentries in history
 * See also history_enumerate()
 *
 * \param	bw		The browser window to enumerate history of
 * \param	entry		entry to start enumeration at
 * \param	cb			callback function
 * \param	ud			context pointer passed to cb
 * \return	true to continue enumeration, false to cancel
 */
static bool browser_window_history__enumerate_entry(
		const struct browser_window *bw,
		const struct history_entry *entry,
		browser_window_history_enumerate_cb cb,
		void *ud)
{
	const struct history_entry *child;

	if (!cb(bw, entry->x, entry->y,
			entry->x + WIDTH, entry->y + HEIGHT,
			entry, ud))
		return false;

	for (child = entry->forward; child; child = child->next) {
		if (!browser_window_history__enumerate_entry(bw, child,
				cb, ud))
			return false;
	}

	return true;
}


/* -------------------------------------------------------------------------- */


/* exported interface documented in desktop/browser_history.h */
nserror browser_window_history_create(struct browser_window *bw)
{
	struct history *history;

	bw->history = NULL;

	history = calloc(1, sizeof *history);
	if (history == NULL) {
		return NSERROR_NOMEM;
	}

	history->width = RIGHT_MARGIN / 2;
	history->height = BOTTOM_MARGIN / 2;

	bw->history = history;
	return NSERROR_OK;
}


/* exported interface documented in desktop/browser_history.h */
nserror browser_window_history_clone(const struct browser_window *existing,
		struct browser_window *clone)
{
	struct history *new_history;

	clone->history = NULL;

	if (existing == NULL || existing->history == NULL ||
			existing->history->start == NULL)
		/* Nothing to clone, create new history for clone window */
		return browser_window_history_create(clone);

	/* Make cloned history */
	new_history = malloc(sizeof *new_history);
	if (!new_history)
		return NSERROR_NOMEM;

	clone->history = new_history;
	memcpy(new_history, existing->history, sizeof *new_history);

	new_history->start = browser_window_history__clone_entry(new_history,
			new_history->start);
	if (!new_history->start) {
		LOG("Insufficient memory to clone history");
		browser_window_history_destroy(clone);
		clone->history = NULL;
		return NSERROR_NOMEM;
	}

	return NSERROR_OK;
}


/* exported interface documented in desktop/browser_history.h */
nserror browser_window_history_add(struct browser_window *bw,
		struct hlcache_handle *content, lwc_string *frag_id)
{
	struct history *history;
	struct history_entry *entry;
	nsurl *nsurl = hlcache_handle_get_url(content);
	char *title;
	struct bitmap *bitmap;
	nserror ret;

	assert(bw);
	assert(bw->history);
	assert(content);

	history = bw->history;

	/* allocate space */
	entry = malloc(sizeof *entry);
	if (entry == NULL) {
		return NSERROR_NOMEM;
	}

	title = strdup(content_get_title(content));
	if (title == NULL) {
		free(entry);
		return NSERROR_NOMEM;
	}

	entry->page.url = nsurl_ref(nsurl);
	entry->page.frag_id = frag_id ? lwc_string_ref(frag_id) : 0;

	entry->page.title = title;
	entry->back = history->current;
	entry->next = 0;
	entry->forward = entry->forward_pref = entry->forward_last = 0;
	entry->children = 0;
	entry->bitmap = 0;
	if (history->current) {
		if (history->current->forward_last)
			history->current->forward_last->next = entry;
		else
			history->current->forward = entry;
		history->current->forward_pref = entry;
		history->current->forward_last = entry;
		history->current->children++;
	} else {
		history->start = entry;
	}
	history->current = entry;

	/* if we have a thumbnail, don't update until the page has finished
	 * loading */
	bitmap = urldb_get_thumbnail(nsurl);
	if (bitmap == NULL) {
		LOG("Creating thumbnail for %s", nsurl_access(nsurl));
		bitmap = guit->bitmap->create(WIDTH, HEIGHT,
					      BITMAP_NEW | BITMAP_CLEAR_MEMORY |
					      BITMAP_OPAQUE);
		if (bitmap != NULL) {
			ret = guit->bitmap->render(bitmap, content);
			if (ret == NSERROR_OK) {
				/* Successful thumbnail so register it
				 * with the url.
				 */
				urldb_set_thumbnail(nsurl, bitmap);
			} else {
				/* Thumbnailing failed. Ignore it
				 * silently but clean up bitmap.
				 */
				LOG("Thumbnail renderfailed");
				guit->bitmap->destroy(bitmap);
				bitmap = NULL;
			}
		}
	}
	entry->bitmap = bitmap;

	browser_window_history__layout(history);

	return NSERROR_OK;
}


/* exported interface documented in desktop/browser_history.h */
nserror browser_window_history_update(struct browser_window *bw,
		struct hlcache_handle *content)
{
	struct history *history;
	char *title;

	assert(bw != NULL);

	history = bw->history;

	if (!history || !history->current || !history->current->bitmap) {
		return NSERROR_INVALID;
	}

	assert(history->current->page.url);
	assert(history->current->page.title);

	title = strdup(content_get_title(content));
	if (title == NULL) {
		return NSERROR_NOMEM;
	}

	free(history->current->page.title);
	history->current->page.title = title;

	guit->bitmap->render(history->current->bitmap, content);

	return NSERROR_OK;
}



/* exported interface documented in desktop/browser_history.h */
void browser_window_history_destroy(struct browser_window *bw)
{
	assert(bw != NULL);

	if (bw->history == NULL)
		return;

	browser_window_history__free_entry(bw->history->start);
	free(bw->history);

	bw->history = NULL;
}
示例#28
0
/**
 * Parse a comma separated list, converting to bytecode
 *
 * \param c          Parsing context
 * \param vector     Vector of tokens to process
 * \param ctx        Pointer to vector iteration context
 * \param reserved   Callback to determine if an identifier is reserved
 * \param get_value  Callback to retrieve bytecode value for a token
 * \param style      Pointer to output style
 * \return CSS_OK      on success,
 *         CSS_INVALID if the input is invalid
 *
 * Post condition: \a *ctx is updated with the next token to process
 *                 If the input is invalid, then \a *ctx remains unchanged.
 */
css_error css__comma_list_to_style(css_language *c,
		const parserutils_vector *vector, int *ctx,
		bool (*reserved)(css_language *c, const css_token *ident),
		css_code_t (*get_value)(css_language *c, const css_token *token, bool first),
		css_style *result)
{
	int orig_ctx = *ctx;
	int prev_ctx = orig_ctx;
	const css_token *token;
	bool first = true;
	css_error error = CSS_OK;

	token = parserutils_vector_iterate(vector, ctx);
	if (token == NULL) {
		*ctx = orig_ctx;
		return CSS_INVALID;
	}

	while (token != NULL) {
		if (token->type == CSS_TOKEN_IDENT) {
			css_code_t value = get_value(c, token, first);

			if (reserved(c, token) == false) {
				lwc_string *str = NULL;
				uint32_t snumber;

				*ctx = prev_ctx;

				error = css__ident_list_to_string(c, vector, ctx,
						reserved, &str);
				if (error != CSS_OK)
					goto cleanup;

				error = css__stylesheet_string_add(c->sheet,
						str, &snumber);
				if (error != CSS_OK)
					goto cleanup;

				error = css__stylesheet_style_append(result, 
						value);
				if (error != CSS_OK)
					goto cleanup;

				error = css__stylesheet_style_append(result,
						snumber);
				if (error != CSS_OK)
					goto cleanup;
			} else {
				error = css__stylesheet_style_append(result,
						value);
				if (error != CSS_OK)
					goto cleanup;
			}
		} else if (token->type == CSS_TOKEN_STRING) {
			css_code_t value = get_value(c, token, first);
			uint32_t snumber;

			error = css__stylesheet_string_add(c->sheet, 
					lwc_string_ref(token->idata), &snumber);
			if (error != CSS_OK)
				goto cleanup;

			error = css__stylesheet_style_append(result, value);
			if (error != CSS_OK)
				goto cleanup;

			error = css__stylesheet_style_append(result, snumber);
			if (error != CSS_OK)
				goto cleanup;
		} else {
			error = CSS_INVALID;
			goto cleanup;
		}

		consumeWhitespace(vector, ctx);

		token = parserutils_vector_peek(vector, *ctx);
		if (token != NULL && tokenIsChar(token, ',')) {
			parserutils_vector_iterate(vector, ctx);

			consumeWhitespace(vector, ctx);

			token = parserutils_vector_peek(vector, *ctx);
			if (token == NULL || (token->type != CSS_TOKEN_IDENT &&
					token->type != CSS_TOKEN_STRING)) {
				error = CSS_INVALID;
				goto cleanup;
			}
		} else {
			break;
		}

		first = false;

		prev_ctx = *ctx;

		token = parserutils_vector_iterate(vector, ctx);
	}

cleanup:
	if (error != CSS_OK)
		*ctx = orig_ctx;

	return error;
}
示例#29
0
/* See mimesniff.h for documentation */
nserror mimesniff_compute_effective_type(llcache_handle *handle,
		const uint8_t *data, size_t len, bool sniff_allowed,
		bool image_only, lwc_string **effective_type)
{
#define S(s) { s, SLEN(s) }
	static const struct tt_s {
		const char *data;
		size_t len;
	} text_types[] = {
		S("text/plain"),
		S("text/plain; charset=ISO-8859-1"),
		S("text/plain; charset=iso-8859-1"),
		S("text/plain; charset=UTF-8"),
		{ NULL, 0 }
	};
#undef S

	const char *content_type_header;
	size_t content_type_header_len;
	http_content_type *ct;
	const struct tt_s *tt;
	bool match;
	nserror error;

	content_type_header = 
			llcache_handle_get_header(handle, "Content-Type");
	if (content_type_header == NULL) {
		if (sniff_allowed == false)
			return NSERROR_NOT_FOUND;

		/* No official type => unknown */
		return mimesniff__compute_unknown(data, len, effective_type);
	}

	error = http_parse_content_type(content_type_header, &ct);
	if (error != NSERROR_OK) {
		if (sniff_allowed == false)
			return NSERROR_NOT_FOUND;

		/* Unparseable => unknown */
		return mimesniff__compute_unknown(data, len, effective_type);
	}

	if (sniff_allowed == false) {
		*effective_type = lwc_string_ref(ct->media_type);
		http_content_type_destroy(ct);
		return NSERROR_OK;
	}

	if (image_only) {
		lwc_string *official_type;

		if (lwc_string_caseless_isequal(ct->media_type, image_svg, 
				&match) == lwc_error_ok && match) {
			*effective_type = lwc_string_ref(image_svg);
			http_content_type_destroy(ct);
			return NSERROR_OK;
		}

		official_type = lwc_string_ref(ct->media_type);
		http_content_type_destroy(ct);
		return mimesniff__compute_image(official_type,
				data, len, effective_type);
	}

	content_type_header_len = strlen(content_type_header);

	/* Look for text types */
	for (tt = text_types; tt->data != NULL; tt++) {
		if (tt->len == content_type_header_len &&
				memcmp(tt->data, content_type_header, 
					content_type_header_len) == 0) {
			http_content_type_destroy(ct);
			return mimesniff__compute_text_or_binary(data, len,
					effective_type);
		}
	}

	/* unknown/unknown, application/unknown, * / * */
	if ((lwc_string_caseless_isequal(ct->media_type, unknown_unknown, 
				&match) == lwc_error_ok && match) ||
			(lwc_string_caseless_isequal(ct->media_type, 
				application_unknown, &match) == lwc_error_ok && 
				match) ||
			(lwc_string_caseless_isequal(ct->media_type, any, 
				&match) == lwc_error_ok && match)) {
		http_content_type_destroy(ct);
		return mimesniff__compute_unknown(data, len, effective_type);
	}

	/* +xml */
	if (lwc_string_length(ct->media_type) > SLEN("+xml") &&
			strncasecmp(lwc_string_data(ct->media_type) + 
				lwc_string_length(ct->media_type) - 
				SLEN("+xml"), 
				"+xml", SLEN("+xml")) == 0) {
		/* Use official type */
		*effective_type = lwc_string_ref(ct->media_type);
		http_content_type_destroy(ct);
		return NSERROR_OK;
	}

	/* text/xml, application/xml */
	if ((lwc_string_caseless_isequal(ct->media_type, text_xml, 
				&match) == lwc_error_ok && match) ||
			(lwc_string_caseless_isequal(ct->media_type, 
				application_xml, &match) == lwc_error_ok && 
				match)) {
		/* Use official type */
		*effective_type = lwc_string_ref(ct->media_type);
		http_content_type_destroy(ct);
		return NSERROR_OK;
	}
	
	/* Image types */
	if (content_factory_type_from_mime_type(ct->media_type) == 
			CONTENT_IMAGE) {
		lwc_string *official_type = lwc_string_ref(ct->media_type);
		http_content_type_destroy(ct);
		return mimesniff__compute_image(official_type,
				data, len, effective_type);
	}

	/* text/html */
	if ((lwc_string_caseless_isequal(ct->media_type, text_html, 
			&match) == lwc_error_ok && match)) {
		http_content_type_destroy(ct);
		return mimesniff__compute_feed_or_html(data, len,
				effective_type);
	}

	/* Use official type */
	*effective_type = lwc_string_ref(ct->media_type);

	http_content_type_destroy(ct);

	return NSERROR_OK;
}
示例#30
0
/**
 * Clone a content's data members
 *
 * \param c   Content to clone
 * \param nc  Content to populate
 * \return NSERROR_OK on success, appropriate error otherwise
 */
nserror content__clone(const struct content *c, struct content *nc)
{
	nserror error;

	error = llcache_handle_clone(c->llcache, &(nc->llcache));
	if (error != NSERROR_OK) {
		return error;
	}

	llcache_handle_change_callback(nc->llcache,
				       content_llcache_callback, nc);

	nc->mime_type = lwc_string_ref(c->mime_type);
	nc->handler = c->handler;

	nc->status = c->status;

	nc->width = c->width;
	nc->height = c->height;
	nc->available_width = c->available_width;
	nc->quirks = c->quirks;

	if (c->fallback_charset != NULL) {
		nc->fallback_charset = strdup(c->fallback_charset);
		if (nc->fallback_charset == NULL) {
			return NSERROR_NOMEM;
		}
	}

	if (c->refresh != NULL) {
		nc->refresh = nsurl_ref(c->refresh);
		if (nc->refresh == NULL) {
			return NSERROR_NOMEM;
		}
	}

	nc->time = c->time;
	nc->reformat_time = c->reformat_time;
	nc->size = c->size;

	if (c->title != NULL) {
		nc->title = strdup(c->title);
		if (nc->title == NULL) {
			return NSERROR_NOMEM;
		}
	}

	nc->active = c->active;

	nc->user_list = calloc(1, sizeof(struct content_user));
	if (nc->user_list == NULL) {
		return NSERROR_NOMEM;
	}

	memcpy(&(nc->status_message), &(c->status_message), 120);
	memcpy(&(nc->sub_status), &(c->sub_status), 80);

	nc->locked = c->locked;
	nc->total_size = c->total_size;
	nc->http_code = c->http_code;
	
	return NSERROR_OK;
}