/**
 * cra_plugin_process_filename:
 */
static gboolean
cra_plugin_process_filename (CraPlugin *plugin,
			     CraPackage *pkg,
			     const gchar *filename,
			     GList **apps,
			     const gchar *tmpdir,
			     GError **error)
{
	GNode *root = NULL;
	GString *valid_xml;
	const gchar *tmp;
	const GNode *n;
	gboolean found_header = FALSE;
	gboolean ret;
	guint i;
	_cleanup_free_ gchar *basename = NULL;
	_cleanup_free_ gchar *data = NULL;
	_cleanup_free_ gchar *filename_tmp;
	_cleanup_object_unref_ CraApp *app = NULL;
	_cleanup_strv_free_ gchar **languages = NULL;
	_cleanup_strv_free_ gchar **lines = NULL;

	/* open file */
	filename_tmp = g_build_filename (tmpdir, filename, NULL);
	ret = g_file_get_contents (filename_tmp, &data, NULL, error);
	if (!ret)
		goto out;

	/* some components start with a comment (invalid XML) and some
	 * don't even have '<?xml' -- try to fix up best we can */
	valid_xml = g_string_new ("");
	lines = g_strsplit (data, "\n", -1);
	for (i = 0; lines[i] != NULL; i++) {
		if (g_str_has_prefix (lines[i], "<?xml") ||
		    g_str_has_prefix (lines[i], "<component>"))
			found_header = TRUE;
		if (found_header)
			g_string_append_printf (valid_xml, "%s\n", lines[i]);
	}

	/* parse contents */
	root = as_node_from_xml (valid_xml->str, -1,
				 AS_NODE_FROM_XML_FLAG_NONE,
				 error);
	if (!ret)
		goto out;

	/* create new app */
	basename = g_path_get_basename (filename);
	app = cra_app_new (pkg, basename);
	as_app_set_id_kind (AS_APP (app), AS_ID_KIND_INPUT_METHOD);
	as_app_add_category (AS_APP (app), "Addons", -1);
	as_app_add_category (AS_APP (app), "InputSources", -1);
	as_app_set_icon (AS_APP (app), "system-run-symbolic", -1);
	as_app_set_icon_kind (AS_APP (app), AS_ICON_KIND_STOCK);
	cra_app_set_requires_appdata (app, TRUE);

	/* read the component header which all input methods have */
	n = as_node_find (root, "component/description");
	if (n != NULL) {
		as_app_set_name (AS_APP (app), "C", as_node_get_data (n), -1);
		as_app_set_comment (AS_APP (app), "C", as_node_get_data (n), -1);
	}
	n = as_node_find (root, "component/homepage");
	if (n != NULL) {
		as_app_add_url (AS_APP (app),
				AS_URL_KIND_HOMEPAGE,
				as_node_get_data (n), -1);
	}

	/* do we have a engine section we can use? */
	n = as_node_find (root, "component/engines/engine/longname");
	if (n != NULL)
		as_app_set_name (AS_APP (app), "C", as_node_get_data (n), -1);
	n = as_node_find (root, "component/engines/engine/description");
	if (n != NULL)
		as_app_set_comment (AS_APP (app), "C", as_node_get_data (n), -1);
	n = as_node_find (root, "component/engines/engine/symbol");
	if (n != NULL) {
		tmp = as_node_get_data (n);
		if (tmp != NULL && tmp[0] != '\0') {
			as_app_add_metadata (AS_APP (app),
					     "X-IBus-Symbol",
					     tmp, -1);
		}
	}
	n = as_node_find (root, "component/engines/engine/language");
	if (n != NULL) {
		tmp = as_node_get_data (n);
		if (tmp != NULL) {
			languages = g_strsplit (tmp, ",", -1);
			for (i = 0; languages[i] != NULL; i++) {
				if (g_strcmp0 (languages[i], "other") == 0)
					continue;
				as_app_add_language (AS_APP (app),
						     100, languages[i], -1);
			}
		}
	}

	/* add */
	cra_plugin_add_app (apps, app);
out:
	if (root != NULL)
		as_node_unref (root);
	return ret;
}
static gboolean
as_app_validate_description (const gchar *xml,
			     AsAppValidateHelper *helper,
			     guint number_para_min,
			     guint number_para_max,
			     gboolean allow_short_para,
			     GError **error)
{
	GNode *l;
	GNode *l2;
	g_autoptr(AsNode) node = NULL;

	/* parse xml */
	node = as_node_from_xml (xml, AS_NODE_FROM_XML_FLAG_NONE, error);
	if (node == NULL)
		return FALSE;
	helper->number_paragraphs = 0;
	helper->previous_para_was_short = FALSE;
	for (l = node->children; l != NULL; l = l->next) {
		if (g_strcmp0 (as_node_get_name (l), "p") == 0) {
			if (as_node_get_attribute (l, "xml:lang") != NULL)
				continue;
			as_app_validate_description_para (as_node_get_data (l),
							  helper);
		} else if (g_strcmp0 (as_node_get_name (l), "ul") == 0 ||
			   g_strcmp0 (as_node_get_name (l), "ol") == 0) {
			as_app_validate_description_list (as_node_get_data (l),
							  allow_short_para,
							  helper);
			for (l2 = l->children; l2 != NULL; l2 = l2->next) {
				if (g_strcmp0 (as_node_get_name (l2), "li") == 0) {
					if (as_node_get_attribute (l2, "xml:lang") != NULL)
						continue;
					as_app_validate_description_li (as_node_get_data (l2),
									helper);
				} else {
					/* only <li> supported */
					g_set_error (error,
						     AS_APP_ERROR,
						     AS_APP_ERROR_FAILED,
						     "invalid markup: <%s> follows <%s>",
						     as_node_get_name (l2),
						     as_node_get_name (l));
					return FALSE;
				}
			}
		} else {
			/* only <p>, <ol> and <ul> supported */
			g_set_error (error,
				     AS_APP_ERROR,
				     AS_APP_ERROR_FAILED,
				     "invalid markup: tag <%s> invalid here",
				     as_node_get_name (l));
			return FALSE;
		}
	}

	/* previous paragraph wasn't long enough */
	if (helper->previous_para_was_short) {
		ai_app_validate_add (helper,
				     AS_PROBLEM_KIND_STYLE_INCORRECT,
				     "<p> is too short [%s]",
				     helper->previous_para_was_short_str);
	}
	if (helper->number_paragraphs < number_para_min) {
		ai_app_validate_add (helper,
				     AS_PROBLEM_KIND_STYLE_INCORRECT,
				     "Not enough <p> tags for a good description [%u/%u]",
				     helper->number_paragraphs,
				     number_para_min);
	}
	if (helper->number_paragraphs > number_para_max) {
		ai_app_validate_add (helper,
				     AS_PROBLEM_KIND_STYLE_INCORRECT,
				     "Too many <p> tags for a good description [%u/%u]",
				     helper->number_paragraphs,
				     number_para_max);
	}
	return TRUE;
}
Beispiel #3
0
/**
 * as_markup_convert_full:
 * @markup: the text to copy.
 * @format: the #AsMarkupConvertFormat, e.g. %AS_MARKUP_CONVERT_FORMAT_MARKDOWN
 * @flags: the #AsMarkupConvertFlag, e.g. %AS_MARKUP_CONVERT_FLAG_IGNORE_ERRORS
 * @error: A #GError or %NULL
 *
 * Converts an XML description into a printable form.
 *
 * Returns: (transfer full): a newly allocated %NULL terminated string
 *
 * Since: 0.3.5
 **/
gchar *
as_markup_convert_full (const gchar *markup,
			AsMarkupConvertFormat format,
			AsMarkupConvertFlag flags,
			GError **error)
{
	GNode *tmp;
	GNode *tmp_c;
	const gchar *tag;
	const gchar *tag_c;
	g_autoptr(AsNode) root = NULL;
	g_autoptr(GError) error_local = NULL;
	g_autoptr(GString) str = NULL;

	/* is this actually markup */
	if (g_strstr_len (markup, -1, "<") == NULL)
		return g_strdup (markup);

	/* load */
	root = as_node_from_xml (markup, AS_NODE_FROM_XML_FLAG_NONE, &error_local);
	if (root == NULL) {

		/* truncate to the last tag and try again */
		if (flags & AS_MARKUP_CONVERT_FLAG_IGNORE_ERRORS) {
			gchar *found;
			g_autofree gchar *markup_new = NULL;
			markup_new = g_strdup (markup);
			found = g_strrstr (markup_new, "<");
			g_assert (found != NULL);
			*found = '\0';
			return as_markup_convert_full (markup_new, format, flags, error);
		}

		/* just return error */
		g_propagate_error (error, error_local);
		error_local = NULL;
		return NULL;
	}

	/* format */
	str = g_string_new ("");
	for (tmp = root->children; tmp != NULL; tmp = tmp->next) {

		tag = as_node_get_name (tmp);
		if (g_strcmp0 (tag, "unknown") == 0)
			continue;
		if (g_strcmp0 (tag, "p") == 0) {
			as_markup_render_para (str, format, as_node_get_data (tmp));
			continue;
		}

		/* loop on the children */
		if (g_strcmp0 (tag, "ul") == 0 ||
		    g_strcmp0 (tag, "ol") == 0) {
			as_markup_render_ul_start (str, format);
			for (tmp_c = tmp->children; tmp_c != NULL; tmp_c = tmp_c->next) {
				tag_c = as_node_get_name (tmp_c);
				if (g_strcmp0 (tag_c, "unknown") == 0)
					continue;
				if (g_strcmp0 (tag_c, "li") == 0) {
					as_markup_render_li (str, format,
							     as_node_get_data (tmp_c));
					continue;
				}

				/* just abort the list */
				if (flags & AS_MARKUP_CONVERT_FLAG_IGNORE_ERRORS)
					break;

				/* only <li> is valid in lists */
				g_set_error (error,
					     AS_NODE_ERROR,
					     AS_NODE_ERROR_FAILED,
					     "Tag %s in %s invalid",
					     tag_c, tag);
				return NULL;
			}
			as_markup_render_ul_end (str, format);
			continue;
		}

		/* just try again */
		if (flags & AS_MARKUP_CONVERT_FLAG_IGNORE_ERRORS)
			continue;

		/* only <p>, <ul> and <ol> is valid here */
		g_set_error (error,
			     AS_NODE_ERROR,
			     AS_NODE_ERROR_FAILED,
			     "Unknown tag '%s'", tag);
		return NULL;
	}

	/* success */
	switch (format) {
	case AS_MARKUP_CONVERT_FORMAT_SIMPLE:
	case AS_MARKUP_CONVERT_FORMAT_MARKDOWN:
		if (str->len > 0)
			g_string_truncate (str, str->len - 1);
		break;
	default:
		break;
	}
	return g_strdup (str->str);
}