/** * as_provide_node_parse: * @provide: a #AsProvide instance. * @node: a #GNode. * @ctx: a #AsNodeContext. * @error: A #GError or %NULL. * * Populates the object from a DOM node. * * Returns: %TRUE for success * * Since: 0.1.6 **/ gboolean as_provide_node_parse (AsProvide *provide, GNode *node, AsNodeContext *ctx, GError **error) { AsProvidePrivate *priv = GET_PRIVATE (provide); const gchar *tmp; if (g_strcmp0 (as_node_get_name (node), "dbus") == 0) { tmp = as_node_get_attribute (node, "type"); if (g_strcmp0 (tmp, "system") == 0) priv->kind = AS_PROVIDE_KIND_DBUS_SYSTEM; else priv->kind = AS_PROVIDE_KIND_DBUS_SESSION; } else if (g_strcmp0 (as_node_get_name (node), "firmware") == 0) { tmp = as_node_get_attribute (node, "type"); if (g_strcmp0 (tmp, "flashed") == 0) priv->kind = AS_PROVIDE_KIND_FIRMWARE_FLASHED; else priv->kind = AS_PROVIDE_KIND_FIRMWARE_RUNTIME; } else { priv->kind = as_provide_kind_from_string (as_node_get_name (node)); } as_ref_string_assign (&priv->value, as_node_get_data_as_refstr (node)); return TRUE; }
/** * as_content_rating_node_parse: * @content_rating: a #AsContentRating instance. * @node: a #GNode. * @ctx: a #AsNodeContext. * @error: A #GError or %NULL. * * Populates the object from a DOM node. * * Returns: %TRUE for success * * Since: 0.5.12 **/ gboolean as_content_rating_node_parse (AsContentRating *content_rating, GNode *node, AsNodeContext *ctx, GError **error) { AsContentRatingPrivate *priv = GET_PRIVATE (content_rating); GNode *c; const gchar *tmp; g_autoptr(GHashTable) captions = NULL; /* get ID */ tmp = as_node_get_attribute (node, "type"); if (tmp != NULL) as_content_rating_set_kind (content_rating, tmp); /* get keys */ for (c = node->children; c != NULL; c = c->next) { AsContentRatingKey *key; g_autoptr(AsImage) image = NULL; if (as_node_get_tag (c) != AS_TAG_CONTENT_ATTRIBUTE) continue; key = g_slice_new0 (AsContentRatingKey); as_ref_string_assign (&key->id, as_node_get_attribute (c, "id")); key->value = as_content_rating_value_from_string (as_node_get_data (c)); g_ptr_array_add (priv->keys, key); } return TRUE; }
static AsNode * as_node_get_child_node (const AsNode *root, const gchar *name, const gchar *attr_key, const gchar *attr_value) { AsNodeData *data; AsNode *node; /* invalid */ if (root == NULL) return NULL; if (name == NULL || name[0] == '\0') return NULL; /* find a node called name */ for (node = root->children; node != NULL; node = node->next) { data = node->data; if (data == NULL) return NULL; if (g_strcmp0 (as_tag_data_get_name (data), name) == 0) { if (attr_key != NULL) { if (g_strcmp0 (as_node_get_attribute (node, attr_key), attr_value) != 0) { continue; } } return node; } } return NULL; }
/** * as_image_node_parse: * @image: a #AsImage instance. * @node: a #GNode. * @ctx: a #AsNodeContext. * @error: A #GError or %NULL. * * Populates the object from a DOM node. * * Returns: %TRUE for success * * Since: 0.1.0 **/ gboolean as_image_node_parse (AsImage *image, GNode *node, AsNodeContext *ctx, GError **error) { AsImagePrivate *priv = GET_PRIVATE (image); const gchar *tmp; gchar *taken; guint size; size = as_node_get_attribute_as_int (node, "width"); if (size != G_MAXINT) as_image_set_width (image, size); size = as_node_get_attribute_as_int (node, "height"); if (size != G_MAXINT) as_image_set_height (image, size); tmp = as_node_get_attribute (node, "type"); if (tmp == NULL) as_image_set_kind (image, AS_IMAGE_KIND_SOURCE); else as_image_set_kind (image, as_image_kind_from_string (tmp)); taken = as_node_take_data (node); if (taken != NULL) { g_free (priv->url); priv->url = taken; } return TRUE; }
/** * asb_plugin_process_gir: */ static gboolean asb_plugin_process_gir (AsbApp *app, const gchar *tmpdir, const gchar *filename, GError **error) { GNode *l; GNode *node = NULL; const gchar *name; const gchar *version; gboolean ret = TRUE; g_autofree gchar *filename_full = NULL; g_autoptr(GFile) file = NULL; /* load file */ filename_full = g_build_filename (tmpdir, filename, NULL); file = g_file_new_for_path (filename_full); node = as_node_from_file (file, AS_NODE_FROM_XML_FLAG_NONE, NULL, error); if (node == NULL) { ret = FALSE; goto out; } /* look for includes */ l = as_node_find (node, "repository"); if (l == NULL) goto out; for (l = l->children; l != NULL; l = l->next) { if (g_strcmp0 (as_node_get_name (l), "include") != 0) continue; name = as_node_get_attribute (l, "name"); version = as_node_get_attribute (l, "version"); if (g_strcmp0 (name, "Gtk") == 0 && g_strcmp0 (version, "3.0") == 0) { asb_package_log (asb_app_get_package (app), ASB_PACKAGE_LOG_LEVEL_DEBUG, "Auto-adding kudo ModernToolkit for %s", as_app_get_id (AS_APP (app))); as_app_add_kudo_kind (AS_APP (app), AS_KUDO_KIND_MODERN_TOOLKIT); } } out: if (node != NULL) as_node_unref (node); return ret; }
/** * as_icon_node_parse: * @icon: a #AsIcon instance. * @node: a #GNode. * @error: A #GError or %NULL. * * Populates the object from a DOM node. * * Returns: %TRUE for success * * Since: 0.3.1 **/ gboolean as_icon_node_parse (AsIcon *icon, GNode *node, GError **error) { AsIconPrivate *priv = GET_PRIVATE (icon); const gchar *tmp; gint size; gboolean prepend_size = TRUE; tmp = as_node_get_attribute (node, "type"); as_icon_set_kind (icon, as_icon_kind_from_string (tmp)); switch (priv->kind) { case AS_ICON_KIND_EMBEDDED: if (!as_icon_node_parse_embedded (icon, node, error)) return FALSE; break; default: /* store the name without any prefix */ tmp = as_node_get_data (node); if (g_strstr_len (tmp, -1, "/") == NULL) { as_icon_set_name (icon, tmp, -1); } else { _cleanup_free_ gchar *basename = NULL; basename = g_path_get_basename (tmp); as_icon_set_name (icon, basename, -1); } /* width is optional, assume 64px if missing */ size = as_node_get_attribute_as_int (node, "width"); if (size == G_MAXINT) { size = 64; prepend_size = FALSE; } priv->width = size; /* height is optional, assume 64px if missing */ size = as_node_get_attribute_as_int (node, "height"); if (size == G_MAXINT) { size = 64; prepend_size = FALSE; } priv->height = size; /* only use the size if the metadata has width and height */ if (prepend_size) { g_free (priv->prefix_private); priv->prefix_private = g_strdup_printf ("%s/%ix%i", priv->prefix, priv->width, priv->height); } break; } return TRUE; }
/** * as_image_node_parse: * @image: a #AsImage instance. * @node: a #GNode. * @ctx: a #AsNodeContext. * @error: A #GError or %NULL. * * Populates the object from a DOM node. * * Returns: %TRUE for success * * Since: 0.1.0 **/ gboolean as_image_node_parse (AsImage *image, GNode *node, AsNodeContext *ctx, GError **error) { AsImagePrivate *priv = GET_PRIVATE (image); const gchar *tmp; guint size; size = as_node_get_attribute_as_uint (node, "width"); if (size != G_MAXUINT) as_image_set_width (image, size); size = as_node_get_attribute_as_uint (node, "height"); if (size != G_MAXUINT) as_image_set_height (image, size); tmp = as_node_get_attribute (node, "type"); if (tmp == NULL) as_image_set_kind (image, AS_IMAGE_KIND_SOURCE); else as_image_set_kind (image, as_image_kind_from_string (tmp)); as_ref_string_assign (&priv->url, as_node_get_data (node)); as_ref_string_assign (&priv->locale, as_node_get_attribute (node, "xml:lang")); return TRUE; }
/** * as_require_node_parse: * @require: a #AsRequire instance. * @node: a #GNode. * @ctx: a #AsNodeContext. * @error: A #GError or %NULL. * * Populates the object from a DOM node. * * Returns: %TRUE for success * * Since: 0.6.7 **/ gboolean as_require_node_parse (AsRequire *require, GNode *node, AsNodeContext *ctx, GError **error) { AsRequirePrivate *priv = GET_PRIVATE (require); const gchar *tmp; tmp = as_node_get_name (node); if (tmp != NULL) as_require_set_kind (require, as_require_kind_from_string (tmp)); tmp = as_node_get_attribute (node, "compare"); if (tmp != NULL) as_require_set_compare (require, as_require_compare_from_string (tmp)); as_ref_string_assign (&priv->version, as_node_get_attribute_as_refstr (node, "version")); as_ref_string_assign (&priv->value, as_node_get_data_as_refstr (node)); return TRUE; }
static void as_node_passthrough_cb (GMarkupParseContext *context, const gchar *passthrough_text, gsize passthrough_len, gpointer user_data, GError **error) { AsNodeToXmlHelper *helper = (AsNodeToXmlHelper *) user_data; const gchar *existing; const gchar *tmp; gchar *found; g_autofree gchar *text = NULL; /* only keep comments when told to */ if ((helper->flags & AS_NODE_FROM_XML_FLAG_KEEP_COMMENTS) == 0) return; /* xml header */ if (g_strstr_len (passthrough_text, passthrough_len, "<?xml") != NULL) return; /* get stripped comment without '<!--' and '-->' */ text = g_strndup (passthrough_text, passthrough_len); if (!g_str_has_prefix (text, "<!--")) { g_warning ("Unexpected input: %s", text); return; } found = g_strrstr (text, "-->"); if (found != NULL) *found = '\0'; tmp = text + 4; if ((helper->flags & AS_NODE_FROM_XML_FLAG_LITERAL_TEXT) == 0) tmp = g_strstrip ((gchar *) tmp); if (tmp == NULL || tmp[0] == '\0') return; /* append together comments */ existing = as_node_get_attribute (helper->current, "@comment-tmp"); if (existing == NULL) { as_node_add_attribute (helper->current, "@comment-tmp", tmp); } else { g_autofree gchar *join = NULL; join = g_strdup_printf ("%s<&>%s", existing, tmp); as_node_add_attribute (helper->current, "@comment-tmp", join); } }
/** * as_node_get_attribute_as_int: * @node: a #AsNode * @key: the attribute key * * Gets a node attribute, e.g. 34 * * Return value: integer value, or %G_MAXINT for error * * Since: 0.1.0 **/ gint as_node_get_attribute_as_int (const AsNode *node, const gchar *key) { const gchar *tmp; gchar *endptr = NULL; gint64 value_tmp; tmp = as_node_get_attribute (node, key); if (tmp == NULL) return G_MAXINT; value_tmp = g_ascii_strtoll (tmp, &endptr, 10); if (value_tmp == 0 && tmp == endptr) return G_MAXINT; if (value_tmp > G_MAXINT || value_tmp < G_MININT) return G_MAXINT; return value_tmp; }
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; }
/** * as_screenshot_node_parse: * @screenshot: a #AsScreenshot instance. * @node: a #GNode. * @ctx: a #AsNodeContext. * @error: A #GError or %NULL. * * Populates the object from a DOM node. * * Returns: %TRUE for success * * Since: 0.1.0 **/ gboolean as_screenshot_node_parse (AsScreenshot *screenshot, GNode *node, AsNodeContext *ctx, GError **error) { AsScreenshotPrivate *priv = GET_PRIVATE (screenshot); GList *l; GNode *c; const gchar *tmp; guint size; gint priority; g_autoptr(GHashTable) captions = NULL; tmp = as_node_get_attribute (node, "type"); if (tmp != NULL) { as_screenshot_set_kind (screenshot, as_screenshot_kind_from_string (tmp)); } priority = as_node_get_attribute_as_int (node, "priority"); if (priority != G_MAXINT) as_screenshot_set_priority (screenshot, priority); /* add captions */ captions = as_node_get_localized (node, "caption"); if (captions != NULL) { g_autoptr(GList) keys = NULL; keys = g_hash_table_get_keys (captions); for (l = keys; l != NULL; l = l->next) { tmp = l->data; as_screenshot_set_caption (screenshot, tmp, g_hash_table_lookup (captions, tmp)); } } /* AppData files does not have <image> tags */ tmp = as_node_get_data (node); if (tmp != NULL) { AsImage *image; image = as_image_new (); as_image_set_kind (image, AS_IMAGE_KIND_SOURCE); size = as_node_get_attribute_as_uint (node, "width"); if (size != G_MAXINT) as_image_set_width (image, size); size = as_node_get_attribute_as_uint (node, "height"); if (size != G_MAXINT) as_image_set_height (image, size); as_image_set_url (image, tmp); g_ptr_array_add (priv->images, image); } /* add images */ for (c = node->children; c != NULL; c = c->next) { g_autoptr(AsImage) image = NULL; if (as_node_get_tag (c) != AS_TAG_IMAGE) continue; image = as_image_new (); if (!as_image_node_parse (image, c, ctx, error)) return FALSE; g_ptr_array_add (priv->images, g_object_ref (image)); } return TRUE; }
/** * as_icon_node_parse: * @icon: a #AsIcon instance. * @node: a #GNode. * @ctx: a #AsNodeContext. * @error: A #GError or %NULL. * * Populates the object from a DOM node. * * Returns: %TRUE for success * * Since: 0.3.1 **/ gboolean as_icon_node_parse (AsIcon *icon, GNode *node, AsNodeContext *ctx, GError **error) { AsIconPrivate *priv = GET_PRIVATE (icon); const gchar *tmp; guint size; gboolean prepend_size = TRUE; tmp = as_node_get_attribute (node, "type"); as_icon_set_kind (icon, as_icon_kind_from_string (tmp)); switch (priv->kind) { case AS_ICON_KIND_EMBEDDED: if (!as_icon_node_parse_embedded (icon, node, error)) return FALSE; break; default: /* preserve the URL for remote icons */ tmp = as_node_get_data (node); if (tmp == NULL) { g_set_error (error, AS_ICON_ERROR, AS_ICON_ERROR_FAILED, "no data for icon of type %s", as_icon_kind_to_string (priv->kind)); return FALSE; } if (priv->kind == AS_ICON_KIND_REMOTE) as_icon_set_url (icon, tmp); else if (priv->kind == AS_ICON_KIND_LOCAL) as_icon_set_filename (icon, tmp); /* store the name without any prefix */ if (g_strstr_len (tmp, -1, "/") == NULL) { as_icon_set_name (icon, tmp); } else { g_autofree gchar *basename = NULL; basename = g_path_get_basename (tmp); as_icon_set_name (icon, basename); } /* width is optional, assume 64px if missing */ size = as_node_get_attribute_as_uint (node, "width"); if (size == G_MAXUINT) { size = 64; prepend_size = FALSE; } priv->width = size; /* height is optional, assume 64px if missing */ size = as_node_get_attribute_as_uint (node, "height"); if (size == G_MAXUINT) { size = 64; prepend_size = FALSE; } priv->height = size; /* only use the size if the metadata has width and height */ if (prepend_size) { g_free (priv->prefix_private); priv->prefix_private = g_strdup_printf ("%s/%ux%u", priv->prefix, priv->width, priv->height); } break; } return TRUE; }
/** * as_node_get_comment: * @node: a #AsNode * * Gets the node data, e.g. "Copyright 2014 Richard Hughes" * * Return value: string value, or %NULL * * Since: 0.1.6 **/ const gchar * as_node_get_comment (const AsNode *node) { return as_node_get_attribute (node, "@comment"); }
/** * as_node_get_localized_unwrap: * @node: a #AsNode. * @error: A #GError or %NULL. * * Denormalize AppData data like this: * * |[ * <description> * <p>Hi</p> * <p xml:lang="pl">Czesc</p> * <ul> * <li>First</li> * <li xml:lang="pl">Pierwszy</li> * </ul> * </description> * ]| * * into a hash that contains: * * |[ * "C" -> "<p>Hi</p><ul><li>First</li></ul>" * "pl" -> "<p>Czesc</p><ul><li>Pierwszy</li></ul>" * ]| * * Returns: (transfer full): a hash table of data * * Since: 0.1.0 **/ GHashTable * as_node_get_localized_unwrap (const AsNode *node, GError **error) { AsNodeData *data; GHashTable *results; GList *l; AsNode *tmp; GString *str; const gchar *xml_lang; gboolean is_li_translated = TRUE; g_autoptr(GHashTable) hash = NULL; g_autoptr(GList) keys = NULL; g_return_val_if_fail (node != NULL, NULL); /* work out what kind of normalization this is */ xml_lang = as_node_get_attribute (node, "xml:lang"); if (xml_lang != NULL && node->children != NULL) { str = as_node_to_xml (node->children, AS_NODE_TO_XML_FLAG_NONE); results = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); g_hash_table_insert (results, g_strdup (xml_lang), g_strdup (str->str)); g_string_free (str, TRUE); return results; } for (tmp = node->children; tmp != NULL; tmp = tmp->next) { data = tmp->data; if (g_strcmp0 (data->name, "ul") == 0 || g_strcmp0 (data->name, "ol") == 0) { if (as_node_attr_lookup (data, "xml:lang") != NULL) { is_li_translated = FALSE; break; } } } /* unwrap it to a hash */ hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) as_node_string_free); if (is_li_translated) { if (!as_node_get_localized_unwrap_type_li (node, hash, error)) return NULL; } else { if (!as_node_get_localized_unwrap_type_ul (node, hash, error)) return NULL; } /* copy into a hash table of the correct size */ results = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); keys = g_hash_table_get_keys (hash); for (l = keys; l != NULL; l = l->next) { gchar *locale_fixed; xml_lang = l->data; locale_fixed = as_node_fix_locale (xml_lang); if (locale_fixed == NULL) continue; str = g_hash_table_lookup (hash, xml_lang); g_hash_table_insert (results, locale_fixed, g_strdup (str->str)); } return results; }
/** * as_review_node_parse: * @review: a #AsReview instance. * @node: a #GNode. * @ctx: a #AsNodeContext. * @error: A #GError or %NULL. * * Populates the object from a DOM node. * * Returns: %TRUE for success * * Since: 0.6.1 **/ gboolean as_review_node_parse (AsReview *review, GNode *node, AsNodeContext *ctx, GError **error) { AsReviewPrivate *priv = GET_PRIVATE (review); AsNode *c; const gchar *tmp; gint itmp; itmp = as_node_get_attribute_as_int (node, "rating"); if (itmp != G_MAXINT) as_review_set_rating (review, itmp); tmp = as_node_get_attribute (node, "date"); if (tmp != NULL) { g_autoptr(GDateTime) dt = as_utils_iso8601_to_datetime (tmp); if (dt != NULL) as_review_set_date (review, dt); } tmp = as_node_get_attribute (node, "id"); if (tmp != NULL) as_review_set_id (review, tmp); for (c = node->children; c != NULL; c = c->next) { if (as_node_get_tag (c) == AS_TAG_SUMMARY) { as_review_set_summary (review, as_node_get_data (c)); continue; } if (as_node_get_tag (c) == AS_TAG_PRIORITY) { gint64 prio = g_ascii_strtoll (as_node_get_data (c), NULL, 10); as_review_set_priority (review, (gint) prio); continue; } if (as_node_get_tag (c) == AS_TAG_DESCRIPTION) { g_autoptr(GString) xml = NULL; xml = as_node_to_xml (c->children, AS_NODE_TO_XML_FLAG_INCLUDE_SIBLINGS); as_review_set_description (review, xml->str); continue; } if (as_node_get_tag (c) == AS_TAG_VERSION) { as_review_set_version (review, as_node_get_data (c)); continue; } if (as_node_get_tag (c) == AS_TAG_REVIEWER_ID) { as_review_set_reviewer_id (review, as_node_get_data (c)); continue; } if (as_node_get_tag (c) == AS_TAG_REVIEWER_NAME) { as_review_set_reviewer_name (review, as_node_get_data (c)); continue; } if (as_node_get_tag (c) == AS_TAG_LANG) { as_review_set_locale (review, as_node_get_data (c)); continue; } if (as_node_get_tag (c) == AS_TAG_METADATA) { AsNode *c2; for (c2 = c->children; c2 != NULL; c2 = c2->next) { AsRefString *key; AsRefString *value; if (as_node_get_tag (c2) != AS_TAG_VALUE) continue; key = as_node_get_attribute (c2, "key"); value = as_node_get_data (c2); if (value == NULL) { g_hash_table_insert (priv->metadata, as_ref_string_ref (key), as_ref_string_new_static ("")); } else { g_hash_table_insert (priv->metadata, as_ref_string_ref (key), as_ref_string_ref (value)); } } continue; } } return TRUE; }