Example #1
0
int main(int argc, char **argv)
{
	line_ctx ctx;
	
	if (argc != 2) {
		printf("Usage: %s <filename>\n", argv[0]);
		return 1;
	}

	memset(&ctx, 0, sizeof(ctx));


	lwc_intern_string("class", SLEN("class"), &ctx.attr_class);
	lwc_intern_string("id", SLEN("id"), &ctx.attr_id);
	
	assert(css__parse_testfile(argv[1], handle_line, &ctx) == true);
	
	/* and run final test */
	if (ctx.tree != NULL)
		run_test(&ctx, ctx.exp, ctx.expused);

	free(ctx.exp);
	
	lwc_string_unref(ctx.attr_class);
	lwc_string_unref(ctx.attr_id);
	
	lwc_iterate_strings(printing_lwc_iterator, NULL);
	
	assert(fail_because_lwc_leaked == false);
	
	printf("PASS\n");
	return 0;
}
Example #2
0
struct content_rfc5988_link *
content__free_rfc5988_link(struct content_rfc5988_link *link) 
{
	struct content_rfc5988_link *next;

	next = link->next;

	lwc_string_unref(link->rel);
	nsurl_unref(link->href);
	if (link->hreflang != NULL) {
		lwc_string_unref(link->hreflang);
	}
	if (link->type != NULL) {
		lwc_string_unref(link->type);
	}
	if (link->media != NULL) {
		lwc_string_unref(link->media);
	}
	if (link->sizes != NULL) {
		lwc_string_unref(link->sizes);
	}
	free(link);

	return next;
}
Example #3
0
void destroy_tree(node *root)
{
	node *n, *p;
	uint32_t i;

	for (n = root->children; n != NULL; n = p) {
		p = n->next;

		destroy_tree(n);
	}
	
	for (i = 0; i < root->n_attrs; ++i) {
		lwc_string_unref(root->attrs[i].name);
		lwc_string_unref(root->attrs[i].value);
	}
	free(root->attrs);

	if (root->classes != NULL) {
		for (i = 0; i < root->n_classes; ++i) {
			lwc_string_unref(root->classes[i]);
		}
		free(root->classes);
	}

	if (root->libcss_node_data != NULL) {
		css_libcss_node_data_handler(&select_handler, CSS_NODE_DELETED,
				NULL, root, NULL, root->libcss_node_data);
	}

	lwc_string_unref(root->name);
	free(root);
}
Example #4
0
/** callback to initialise the resource fetcher. */
static bool fetch_resource_initialise(lwc_string *scheme)
{
	struct fetch_resource_map_entry *e;
	uint32_t i;

	fetch_resource_path_count = 0;

	for (i = 0; i < NOF_ELEMENTS(fetch_resource_paths); i++) {
		e = &fetch_resource_map[fetch_resource_path_count];

		if (lwc_intern_string(fetch_resource_paths[i],
				strlen(fetch_resource_paths[i]),
				&e->path) != lwc_error_ok) {
			while (i > 0) {
				i--;
				lwc_string_unref(fetch_resource_map[i].path);
				nsurl_unref(fetch_resource_map[i].url);
			}
		}

		e->url = gui_get_resource_url(fetch_resource_paths[i]);
		LOG(("URL is %s " ,lwc_string_data(e->path)));
		if (e->url == NULL) {
			lwc_string_unref(e->path);
		} else {
			fetch_resource_path_count++;
		}
	}

	return true;
}
Example #5
0
/**
 * Initialise a CSS content
 *
 * \param c       Content to initialise
 * \param params  Content-Type parameters
 * \return true on success, false on failure
 */
nserror nscss_create(const content_handler *handler, 
		lwc_string *imime_type,	const http_parameter *params,
		llcache_handle *llcache, const char *fallback_charset,
		bool quirks, struct content **c)
{
	nscss_content *result;
	const char *charset = NULL;
	const char *xnsbase = NULL;
	lwc_string *charset_value = NULL;
	union content_msg_data msg_data;
	nserror error;

	result = calloc(1, sizeof(nscss_content));
	if (result == NULL)
		return NSERROR_NOMEM;

	error = content__init(&result->base, handler, imime_type,
			params, llcache, fallback_charset, quirks);
	if (error != NSERROR_OK) {
		free(result);
		return error;
	}

	/* Find charset specified on HTTP layer, if any */
	error = http_parameter_list_find_item(params, css_charset, 
			&charset_value);
	if (error != NSERROR_OK || lwc_string_length(charset_value) == 0) {
		/* No charset specified, use fallback, if any */
		/** \todo libcss will take this as gospel, which is wrong */
		charset = fallback_charset;
	} else {
		charset = lwc_string_data(charset_value);
	}

	/* Compute base URL for stylesheet */
	xnsbase = llcache_handle_get_header(llcache, "X-NS-Base");
	if (xnsbase == NULL) {
		xnsbase = nsurl_access(content_get_url(&result->base));
	}

	error = nscss_create_css_data(&result->data, 
			xnsbase, charset, result->base.quirks, 
			nscss_content_done, result);
	if (error != NSERROR_OK) {
		msg_data.error = messages_get("NoMemory");
		content_broadcast(&result->base, CONTENT_MSG_ERROR, msg_data);
		if (charset_value != NULL)
			lwc_string_unref(charset_value);
		free(result);
		return error;
	}

	if (charset_value != NULL)
		lwc_string_unref(charset_value);

	*c = (struct content *) result;

	return NSERROR_OK;
}
Example #6
0
static void
with_filled_context_teardown(void)
{
    lwc_string_unref(intern_one);
    lwc_string_unref(intern_two);
    lwc_string_unref(intern_three);
    lwc_string_unref(intern_YAY);
}
Example #7
0
/**
 * Create a path from a nsurl using amiga file handling.
 *
 * @param[in] url The url to encode.
 * @param[out] path_out A string containing the result path which should
 *                      be freed by the caller.
 * @return NSERROR_OK and the path is written to \a path or error code
 *         on faliure.
 */
static nserror amiga_nsurl_to_path(struct nsurl *url, char **path_out)
{
	lwc_string *urlpath;
	char *path;
	bool match;
	lwc_string *scheme;
	nserror res;
	char *colon;
	char *slash;

	if ((url == NULL) || (path_out == NULL)) {
		return NSERROR_BAD_PARAMETER;
	}

	scheme = nsurl_get_component(url, NSURL_SCHEME);

	if (lwc_string_caseless_isequal(scheme, corestring_lwc_file,
					&match) != lwc_error_ok)
	{
		return NSERROR_BAD_PARAMETER;
	}
	lwc_string_unref(scheme);
	if (match == false) {
		return NSERROR_BAD_PARAMETER;
	}

	urlpath = nsurl_get_component(url, NSURL_PATH);
	if (urlpath == NULL) {
		return NSERROR_BAD_PARAMETER;
	}

	res = url_unescape(lwc_string_data(urlpath) + 1, &path);
	lwc_string_unref(urlpath);
	if (res != NSERROR_OK) {
		return res;
	}

	colon = strchr(path, ':');
	if(colon == NULL)
	{
		slash = strchr(path, '/');
		if(slash)
		{
			*slash = ':';
		}
		else
		{
			int len = strlen(path);
			path[len] = ':';
			path[len + 1] = '\0';
		}
	}

	*path_out = path;

	return NSERROR_OK;
}
Example #8
0
/**
 * Destroy a computed style
 *
 * \param style  Style to destroy
 * \return CSS_OK on success, appropriate error otherwise
 */
css_error css_computed_style_destroy(css_computed_style *style)
{
	if (style == NULL)
		return CSS_BADPARM;

	css__computed_uncommon_destroy(style->i.uncommon);

	if (style->count > 1) {
		style->count--;
		return CSS_OK;

	} else if (style->count == 1) {
		css__arena_remove_style(style);
	}

	if (style->page != NULL) {
		free(style->page);
	}

	if (style->i.aural != NULL) {
		free(style->i.aural);
	}

	if (style->font_family != NULL) {
		lwc_string **s;

		for (s = style->font_family; *s != NULL; s++) {
			lwc_string_unref(*s);
		}

		free(style->font_family);
	}

	if (style->quotes != NULL) {
		lwc_string **s;

		for (s = style->quotes; *s != NULL; s++) {
			lwc_string_unref(*s);
		}

		free(style->quotes);
	}

	if (style->i.list_style_image != NULL)
		lwc_string_unref(style->i.list_style_image);

	if (style->i.background_image != NULL)
		lwc_string_unref(style->i.background_image);

	free(style);

	return CSS_OK;
}
Example #9
0
void fetch_quit(void)
{
	while (fetchers != NULL) {
		if (fetchers->refcount != 1) {
			LOG(("Fetcher for scheme %s still active?!",
					lwc_string_data(fetchers->scheme_name)));
			/* We shouldn't do this, but... */
			fetchers->refcount = 1;
		}
		fetch_unref_fetcher(fetchers);
	}

	lwc_string_unref(fetch_http_lwc);
	lwc_string_unref(fetch_https_lwc);
}
Example #10
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;
}
Example #11
0
void
lwc_string_unref(lwc_string *str)
{
        assert(str);
        
        if (--(str->refcnt) > 1)
                return;
        
        if ((str->refcnt == 1) && (str->insensitive != str))
                return;
        
        *(str->prevptr) = str->next;
        
        if (str->next != NULL)
                str->next->prevptr = str->prevptr;

        if (str->insensitive != NULL && str->refcnt == 0)
                lwc_string_unref(str->insensitive);

#ifndef NDEBUG
        memset(str, 0xA5, sizeof(*str) + str->len);
#endif
        
        LWC_FREE(str);
}
Example #12
0
static const ULONG ami_file_asl_mime_hook(struct Hook *mh,
		struct FileRequester *fr, struct AnchorPathOld *ap)
{
	char fname[1024];
	BOOL ret = FALSE;
	char *mt = NULL;
	lwc_string *lwc_mt = NULL;
	lwc_error lerror;
	content_type ct;

	if(ap->ap_Info.fib_DirEntryType > 0) return(TRUE);

	strcpy(fname,fr->fr_Drawer);
	AddPart(fname,ap->ap_Info.fib_FileName,1024);

  	mt = strdup(fetch_filetype(fname));
	lerror = lwc_intern_string(mt, strlen(mt), &lwc_mt);
	if (lerror != lwc_error_ok)
		return FALSE;

	ct = content_factory_type_from_mime_type(lwc_mt);
	lwc_string_unref(lwc_mt);

	if(ct != CONTENT_NONE) ret = TRUE;

	free(mt);
	return ret;
}
Example #13
0
/**
 * Free a fetch structure and associated resources.
 */
static void fetch_curl_free(void *vf)
{
	struct curl_fetch_info *f = (struct curl_fetch_info *)vf;
	int i;

	if (f->curl_handle) {
		curl_easy_cleanup(f->curl_handle);
	}
	nsurl_unref(f->url);
	lwc_string_unref(f->host);
	free(f->location);
	free(f->cookie_string);
	free(f->realm);
	if (f->headers) {
		curl_slist_free_all(f->headers);
	}
	free(f->post_urlenc);
	if (f->post_multipart) {
		curl_formfree(f->post_multipart);
	}

	for (i = 0; i < MAX_CERTS && f->cert_data[i].cert; i++) {
		f->cert_data[i].cert->references--;
		if (f->cert_data[i].cert->references == 0) {
			X509_free(f->cert_data[i].cert);
		}
	}

	free(f);
}
Example #14
0
/**
 * Finalise a cURL fetcher.
 *
 * \param scheme The scheme to finalise.
 */
static void fetch_curl_finalise(lwc_string *scheme)
{
	struct cache_handle *h;

	curl_fetchers_registered--;
	LOG("Finalise cURL fetcher %s", lwc_string_data(scheme));
	if (curl_fetchers_registered == 0) {
		CURLMcode codem;
		/* All the fetchers have been finalised. */
		LOG("All cURL fetchers finalised, closing down cURL");

		curl_easy_cleanup(fetch_blank_curl);

		codem = curl_multi_cleanup(fetch_curl_multi);
		if (codem != CURLM_OK)
			LOG("curl_multi_cleanup failed: ignoring");

		curl_global_cleanup();
	}

	/* Free anything remaining in the cached curl handle ring */
	while (curl_handle_ring != NULL) {
		h = curl_handle_ring;
		RING_REMOVE(curl_handle_ring, h);
		lwc_string_unref(h->host);
		curl_easy_cleanup(h->handle);
		free(h);
	}
}
Example #15
0
/**
 * Handle closing of login dialog
 */
void ro_gui_401login_close(wimp_w w)
{
	os_error *error;
	struct session_401 *session;

	session = (struct session_401 *)ro_gui_wimp_event_get_user_data(w);

	assert(session);

	/* If ok didn't happen, send failure response */
	if (session->cb != NULL)
		session->cb(false, session->cbpw);

	nsurl_unref(session->url);
	lwc_string_unref(session->host);
	free(session->realm);
	free(session);

	error = xwimp_delete_window(w);
	if (error) {
		LOG(("xwimp_delete_window: 0x%x:%s",
			error->errnum, error->errmess));
		warn_user("WimpError", error->errmess);
	}
	ro_gui_wimp_event_finalise(w);
}
Example #16
0
END_TEST

START_TEST (test_lwc_string_ref_unref_ok)
{
    lwc_string_ref(intern_one);
    lwc_string_unref(intern_one);
}
Example #17
0
/**
 * Register a handler with the content factory
 *
 * \param mime_type  MIME type to handle
 * \param handler    Content handler for MIME type
 * \return NSERROR_OK on success, appropriate error otherwise
 *
 * \note Latest registration for a MIME type wins
 */
nserror content_factory_register_handler(const char *mime_type,
		const content_handler *handler)
{
	lwc_string *imime_type;
	lwc_error lerror;
	content_handler_entry *entry;
	bool match;

	lerror = lwc_intern_string(mime_type, strlen(mime_type), &imime_type);
	if (lerror != lwc_error_ok)
		return NSERROR_NOMEM;

	for (entry = content_handlers; entry != NULL; entry = entry->next) {
		if (lwc_string_caseless_isequal(imime_type, entry->mime_type,
				&match) == lwc_error_ok && match)
			break;
	}

	if (entry == NULL) {
		entry = malloc(sizeof(content_handler_entry));
		if (entry == NULL)
			return NSERROR_NOMEM;

		entry->next = content_handlers;
		content_handlers = entry;

		entry->mime_type = imime_type;
	} else {
		lwc_string_unref(imime_type);
	}

	entry->handler = handler;

	return NSERROR_OK;
}
Example #18
0
/** callback to finalise the about fetcher. */
static void fetch_about_finalise(lwc_string *scheme)
{
	unsigned int abt_loop = 0;
	for (abt_loop = 0; abt_loop < about_handler_list_len; abt_loop++) {
		lwc_string_unref(about_handler_list[abt_loop].lname);
	}
}
Example #19
0
/* Exported interface, documented in cookie_manager.h */
nserror cookie_manager_fini(void)
{
	int i;
	nserror err;

	LOG(("Finalising cookie manager"));

	cm_ctx.built = false;

	/* Destroy the cookie manager treeview */
	err = treeview_destroy(cm_ctx.tree);

	/* Free cookie manager treeview entry fields */
	for (i = 0; i < COOKIE_M_N_FIELDS; i++)
		if (cm_ctx.fields[i].field != NULL)
			lwc_string_unref(cm_ctx.fields[i].field);

	/* Free cookie manager treeview common entry values */
	for (i = 0; i < COOKIE_M_N_VALUES; i++)
		if (cm_ctx.values[i].value != NULL)
			free((void *) cm_ctx.values[i].value);

	LOG(("Finalised cookie manager"));

	return err;
}
Example #20
0
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;
}
Example #21
0
void gui_system_colour_finalize(void)
{
	unsigned int ccount;

	for (ccount = 0; ccount < colour_list_len; ccount++) {
		lwc_string_unref(colour_list[ccount].lwcstr);
	}
}
Example #22
0
static bool save_complete_save_html_document(save_complete_ctx *ctx,
		hlcache_handle *c, bool index)
{
	nserror ret;
	FILE *fp;
	char *fname = NULL;
	dom_document *doc;
	lwc_string *mime_type;
	char filename[32];

	if (index) {
		snprintf(filename, sizeof filename, "index");
	} else {
		snprintf(filename, sizeof filename, "%p", c);
	}

	ret = netsurf_mkpath(&fname, NULL, 2, ctx->path, filename);
	if (ret != NSERROR_OK) {
		guit->misc->warning(messages_get_errorcode(ret), NULL);
		return false;
	}

	fp = fopen(fname, "wb");
	if (fp == NULL) {
		free(fname);
		LOG("fopen(): errno = %i", errno);
		guit->misc->warning("SaveError", strerror(errno));
		return false;
	}

	ctx->base = html_get_base_url(c);
	ctx->fp = fp;
	ctx->iter_state = STATE_NORMAL;

	doc = html_get_document(c);

	if (save_complete_libdom_treewalk((dom_node *) doc,
			save_complete_node_handler, ctx) == false) {
		free(fname);
		guit->misc->warning("NoMemory", 0);
		fclose(fp);
		return false;
	}

	fclose(fp);

	mime_type = content_get_mime_type(c);
	if (mime_type != NULL) {
		if (ctx->set_type != NULL)
			ctx->set_type(fname, mime_type);

		lwc_string_unref(mime_type);
	}
	free(fname);

	return true;
}
Example #23
0
/** callback to finalise the resource fetcher. */
static void fetch_resource_finalise(lwc_string *scheme)
{
	uint32_t i;

	for (i = 0; i < fetch_resource_path_count; i++) {
		lwc_string_unref(fetch_resource_map[i].path);
		nsurl_unref(fetch_resource_map[i].url);
	}
}
Example #24
0
/**
 * Open the login dialog
 */
void gui_401login_open(nsurl *url, const char *realm,
		nserror (*cb)(bool proceed, void *pw), void *cbpw)
{
	lwc_string *host = nsurl_get_component(url, NSURL_HOST);
	assert(host != NULL);

	ro_gui_401login_open(url, host, realm, cb, cbpw);

	lwc_string_unref(host);
}
/* See content-disposition.h for documentation */
nserror http_parse_content_disposition(const char *header_value,
		http_content_disposition **result)
{
	const char *pos = header_value;
	lwc_string *mtype;
	http_parameter *params = NULL;
	http_content_disposition *cd;
	nserror error;

	/* disposition-type *( ";" parameter ) */

	http__skip_LWS(&pos);

	error = http__parse_token(&pos, &mtype);
	if (error != NSERROR_OK)
		return error;

	http__skip_LWS(&pos);

	if (*pos == ';') {
		error = http__item_list_parse(&pos, 
				http__parse_parameter, NULL, &params);
		if (error != NSERROR_OK && error != NSERROR_NOT_FOUND) {
			lwc_string_unref(mtype);
			return error;
		}
	}

	cd = malloc(sizeof(*cd));
	if (cd == NULL) {
		http_parameter_list_destroy(params);
		lwc_string_unref(mtype);
		return NSERROR_NOMEM;
	}

	cd->disposition_type = mtype;
	cd->parameters = params;

	*result = cd;

	return NSERROR_OK;
}
Example #26
0
static bool save_complete_save_html_document(save_complete_ctx *ctx,
		hlcache_handle *c, bool index)
{
	bool error;
	FILE *fp;
	dom_document *doc;
	lwc_string *mime_type;
	char filename[32];
	char fullpath[PATH_MAX];

	strncpy(fullpath, ctx->path, sizeof fullpath);

	if (index)
		snprintf(filename, sizeof filename, "index");
	else 
		snprintf(filename, sizeof filename, "%p", c);

	error = path_add_part(fullpath, sizeof fullpath, filename);
	if (error == false) {
		warn_user("NoMemory", NULL);
		return false;
	}

	fp = fopen(fullpath, "wb");
	if (fp == NULL) {
		warn_user("NoMemory", NULL);
		return false;
	}

	ctx->base = html_get_base_url(c);
	ctx->fp = fp;
	ctx->iter_state = STATE_NORMAL;

	doc = html_get_document(c);

	if (save_complete_libdom_treewalk((dom_node *) doc,
			save_complete_node_handler, ctx) == false) {
		warn_user("NoMemory", 0);
		fclose(fp);
		return false;
	}

	fclose(fp);

	mime_type = content_get_mime_type(c);
	if (mime_type != NULL) {
		if (ctx->set_type != NULL)
			ctx->set_type(fullpath, mime_type);

		lwc_string_unref(mime_type);
	}

	return true;
}
Example #27
0
/**
 * Reduce reference count for propstring list by one.
 *
 * When count hits zero, the list is destroyed.
 */
void css__propstrings_unref(void)
{
	css__propstrings.count--;

	if (css__propstrings.count == 0) {
		int i;

		for (i = 0; i < LAST_KNOWN; i++)
			lwc_string_unref(css__propstrings.strings[i]);
	}
}
Example #28
0
static void browser_window_history__free_entry(struct history_entry *entry)
{
	if (!entry)
		return;
	browser_window_history__free_entry(entry->forward);
	browser_window_history__free_entry(entry->next);
	nsurl_unref(entry->page.url);
	if (entry->page.frag_id)
		lwc_string_unref(entry->page.frag_id);
	free(entry->page.title);
	free(entry);
}
Example #29
0
void destroy_tree(node *root)
{
	node *n, *p;
	uint32_t i;

	for (n = root->children; n != NULL; n = p) {
		p = n->next;

		destroy_tree(n);
	}
	
	for (i = 0; i < root->n_attrs; ++i) {
		lwc_string_unref(root->attrs[i].name);
		lwc_string_unref(root->attrs[i].value);
	}
	
	free(root->attrs);
	
	lwc_string_unref(root->name);
	free(root);
}
Example #30
0
/**
 * Clean up after the CSS content handler
 */
static void nscss_fini(void)
{
	if (css_charset != NULL) {
		lwc_string_unref(css_charset);
		css_charset = NULL;
	}

	if (blank_import != NULL) {
		css_stylesheet_destroy(blank_import);
		blank_import = NULL;
	}
}