static void gs_editor_refine_app_pixbuf (GsApp *app) { GPtrArray *icons; if (gs_app_get_pixbuf (app) != NULL) return; icons = gs_app_get_icons (app); for (guint i = 0; i < icons->len; i++) { AsIcon *ic = g_ptr_array_index (icons, i); g_autoptr(GError) error = NULL; if (as_icon_get_kind (ic) == AS_ICON_KIND_STOCK) { g_autoptr(GdkPixbuf) pb = NULL; pb = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (), as_icon_get_name (ic), 64, GTK_ICON_LOOKUP_FORCE_SIZE, &error); if (pb == NULL) { g_warning ("failed to load icon: %s", error->message); continue; } gs_app_set_pixbuf (app, pb); } else { if (!as_icon_load (ic, AS_ICON_LOAD_FLAG_SEARCH_SIZE, &error)) { g_warning ("failed to load icon: %s", error->message); continue; } gs_app_set_pixbuf (app, as_icon_get_pixbuf (ic)); } break; } }
static AsApp * load_desktop (const gchar *prefix, const gchar *icons_dir, guint min_icon_size, const gchar *app_name, const gchar *appdata_id, GError **error) { AsIcon *icon; g_autofree gchar *desktop_basename = NULL; g_autofree gchar *desktop_path = NULL; g_autoptr(AsApp) app = NULL; if (appdata_id != NULL) desktop_basename = g_strdup (appdata_id); else desktop_basename = g_strconcat (app_name, ".desktop", NULL); desktop_path = g_build_filename (prefix, "share/applications", desktop_basename, NULL); app = as_app_new (); if (!as_app_parse_file (app, desktop_path, AS_APP_PARSE_FLAG_USE_HEURISTICS | AS_APP_PARSE_FLAG_ALLOW_VETO, error)) return NULL; if (as_app_get_kind (app) == AS_APP_KIND_UNKNOWN) { g_set_error (error, AS_APP_ERROR, AS_APP_ERROR_FAILED, "%s has no recognised type", as_app_get_id (AS_APP (app))); return NULL; } icon = as_app_get_icon_default (AS_APP (app)); if (icon != NULL) { g_autofree gchar *key = NULL; key = g_strdup (as_icon_get_name (icon)); if (as_icon_get_kind (icon) == AS_ICON_KIND_STOCK) { as_compose_app_log (app, "using stock icon %s", key); } else { g_autoptr(GError) error_local = NULL; gboolean ret; g_ptr_array_set_size (as_app_get_icons (AS_APP (app)), 0); ret = add_icons (app, icons_dir, min_icon_size, prefix, key, error); if (!ret) return NULL; } } return g_steal_pointer (&app); }
static gboolean asb_plugin_desktop_refine (AsbPlugin *plugin, AsbPackage *pkg, const gchar *filename, AsbApp *app, const gchar *tmpdir, GError **error) { AsIcon *icon; AsAppParseFlags parse_flags = AS_APP_PARSE_FLAG_USE_HEURISTICS | AS_APP_PARSE_FLAG_ALLOW_VETO; gboolean ret; g_autoptr(AsApp) desktop_app = NULL; g_autoptr(GdkPixbuf) pixbuf = NULL; /* use GenericName fallback */ if (asb_context_get_flag (plugin->ctx, ASB_CONTEXT_FLAG_USE_FALLBACKS)) parse_flags |= AS_APP_PARSE_FLAG_USE_FALLBACKS; /* create app */ desktop_app = as_app_new (); if (!as_app_parse_file (desktop_app, filename, parse_flags, error)) return FALSE; /* copy all metadata */ as_app_subsume_full (AS_APP (app), desktop_app, AS_APP_SUBSUME_FLAG_NO_OVERWRITE); /* is the icon a stock-icon-name? */ icon = as_app_get_icon_default (AS_APP (app)); if (icon != NULL) { g_autofree gchar *key = NULL; key = g_strdup (as_icon_get_name (icon)); if (as_icon_get_kind (icon) == AS_ICON_KIND_STOCK) { asb_package_log (pkg, ASB_PACKAGE_LOG_LEVEL_DEBUG, "using stock icon %s", key); } else { g_autoptr(GError) error_local = NULL; g_ptr_array_set_size (as_app_get_icons (AS_APP (app)), 0); ret = asb_plugin_desktop_add_icons (plugin, app, tmpdir, key, &error_local); if (!ret) { as_app_add_veto (AS_APP (app), "%s", error_local->message); } } } return TRUE; }
/** * gs_refine_item_pixbuf: */ static void gs_refine_item_pixbuf (GsPlugin *plugin, GsApp *app, AsApp *item) { AsIcon *icon; gboolean ret; g_autoptr(GError) error = NULL; g_autofree gchar *fn = NULL; g_autofree gchar *cachedir = NULL; icon = as_app_get_icon_default (item); switch (as_icon_get_kind (icon)) { case AS_ICON_KIND_REMOTE: gs_app_set_icon (app, icon); if (as_icon_get_filename (icon) == NULL) { cachedir = gs_utils_get_cachedir ("icons", NULL); fn = g_build_filename (cachedir, as_icon_get_name (icon), NULL); as_icon_set_filename (icon, fn); as_icon_set_prefix (icon, cachedir); } if (g_file_test (fn, G_FILE_TEST_EXISTS)) { as_icon_set_kind (icon, AS_ICON_KIND_LOCAL); ret = gs_app_load_icon (app, plugin->scale, &error); if (!ret) { g_warning ("failed to load icon %s: %s", as_icon_get_name (icon), error->message); return; } } break; case AS_ICON_KIND_STOCK: case AS_ICON_KIND_LOCAL: gs_app_set_icon (app, icon); /* does not exist, so try to find using the icon theme */ if (as_icon_get_kind (icon) == AS_ICON_KIND_LOCAL && as_icon_get_filename (icon) == NULL) as_icon_set_kind (icon, AS_ICON_KIND_STOCK); /* load */ ret = gs_app_load_icon (app, plugin->scale, &error); if (!ret) { g_warning ("failed to load %s icon %s: %s", as_icon_kind_to_string (as_icon_get_kind (icon)), as_icon_get_name (icon), error->message); return; } break; case AS_ICON_KIND_CACHED: if (plugin->scale == 2) icon = as_app_get_icon_for_size (item, 128, 128); if (icon == NULL) icon = as_app_get_icon_for_size (item, 64, 64); if (icon == NULL) { g_warning ("failed to find cached icon %s", as_icon_get_name (icon)); return; } if (!as_icon_load (icon, AS_ICON_LOAD_FLAG_SEARCH_SIZE, &error)) { g_warning ("failed to load cached icon %s: %s", as_icon_get_name (icon), error->message); return; } gs_app_set_pixbuf (app, as_icon_get_pixbuf (icon)); break; default: g_warning ("icon kind unknown for %s", as_app_get_id (item)); break; } }
static void as_app_validate_icons (AsApp *app, AsAppValidateHelper *helper) { AsIcon *icon; AsIconKind icon_kind; const gchar *icon_name; /* just check the default icon */ icon = as_app_get_icon_default (app); if (icon == NULL) { AsFormat *fmt = as_app_get_format_default (app); if (fmt != NULL && as_format_get_kind (fmt) == AS_FORMAT_KIND_APPSTREAM && as_app_get_kind (app) == AS_APP_KIND_DESKTOP) { ai_app_validate_add (helper, AS_PROBLEM_KIND_TAG_MISSING, "desktop application has no icon"); } return; } /* check the content is correct */ icon_kind = as_icon_get_kind (icon); switch (icon_kind) { case AS_ICON_KIND_STOCK: icon_name = as_icon_get_name (icon); if (!as_utils_is_stock_icon_name (icon_name)) { ai_app_validate_add (helper, AS_PROBLEM_KIND_TAG_INVALID, "stock icon is not valid [%s]", icon_name); } break; case AS_ICON_KIND_LOCAL: icon_name = as_icon_get_filename (icon); if (icon_name == NULL || !g_str_has_prefix (icon_name, "/")) { ai_app_validate_add (helper, AS_PROBLEM_KIND_TAG_INVALID, "local icon is not a filename [%s]", icon_name); } break; case AS_ICON_KIND_CACHED: icon_name = as_icon_get_name (icon); if (icon_name == NULL || g_str_has_prefix (icon_name, "/")) { ai_app_validate_add (helper, AS_PROBLEM_KIND_TAG_INVALID, "cached icon is a filename [%s]", icon_name); } break; case AS_ICON_KIND_REMOTE: icon_name = as_icon_get_url (icon); if (!g_str_has_prefix (icon_name, "http://") && !g_str_has_prefix (icon_name, "https://")) { ai_app_validate_add (helper, AS_PROBLEM_KIND_TAG_INVALID, "remote icon is not a url [%s]", icon_name); } break; default: break; } }
/** * as_app_validate: * @app: a #AsApp instance. * @flags: the #AsAppValidateFlags to use, e.g. %AS_APP_VALIDATE_FLAG_NONE * @error: A #GError or %NULL. * * Validates data in the instance for style and consistency. * * Returns: (transfer container) (element-type AsProblem): A list of problems, or %NULL * * Since: 0.1.4 **/ GPtrArray * as_app_validate (AsApp *app, guint32 flags, GError **error) { AsAppProblems problems; AsFormat *format; GError *error_local = NULL; GHashTable *urls; GList *l; const gchar *description; const gchar *key; const gchar *license; const gchar *name; const gchar *summary; const gchar *tmp; const gchar *update_contact; gboolean deprecated_failure = FALSE; gboolean require_appstream_spec_only = FALSE; gboolean require_contactdetails = FALSE; gboolean require_copyright = FALSE; gboolean require_description = FALSE; gboolean require_project_license = FALSE; gboolean require_sentence_case = FALSE; gboolean require_translations = FALSE; gboolean require_url = TRUE; gboolean require_content_license = TRUE; gboolean require_name = TRUE; gboolean require_translation = FALSE; gboolean require_content_rating = FALSE; gboolean require_name_shorter_than_summary = FALSE; gboolean validate_license = TRUE; gboolean ret; guint length_name_max = 60; guint length_name_min = 3; guint length_summary_max = 200; guint length_summary_min = 8; guint number_para_max = 10; guint number_para_min = 1; guint str_len; g_autoptr(GList) keys = NULL; g_autoptr(AsAppValidateHelper) helper = g_new0 (AsAppValidateHelper, 1); /* has to be set */ format = as_app_get_format_default (app); if (format == NULL) { g_set_error_literal (error, AS_APP_ERROR, AS_APP_ERROR_FAILED, "cannot validate without at least one format"); return NULL; } /* only for desktop and console apps */ if (as_app_get_kind (app) == AS_APP_KIND_DESKTOP || as_app_get_kind (app) == AS_APP_KIND_CONSOLE) { require_content_rating = TRUE; require_description = TRUE; } /* relax the requirements a bit */ if ((flags & AS_APP_VALIDATE_FLAG_RELAX) > 0) { length_name_max = 100; length_summary_max = 200; require_content_license = FALSE; validate_license = FALSE; require_url = FALSE; number_para_max = 20; number_para_min = 1; require_sentence_case = FALSE; require_content_rating = FALSE; switch (as_format_get_kind (format)) { case AS_FORMAT_KIND_METAINFO: case AS_FORMAT_KIND_APPDATA: require_name = FALSE; break; default: break; } } /* make the requirements more strict */ if ((flags & AS_APP_VALIDATE_FLAG_STRICT) > 0) { deprecated_failure = TRUE; require_copyright = TRUE; require_translations = TRUE; require_project_license = TRUE; require_content_license = TRUE; require_appstream_spec_only = TRUE; require_sentence_case = TRUE; require_name_shorter_than_summary = TRUE; require_contactdetails = TRUE; require_translation = TRUE; number_para_min = 2; number_para_max = 4; } /* addons don't need such a long description */ switch (as_format_get_kind (format)) { case AS_FORMAT_KIND_METAINFO: case AS_FORMAT_KIND_APPDATA: number_para_min = 1; break; default: break; } /* set up networking */ helper->app = app; helper->probs = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref); helper->screenshot_urls = g_ptr_array_new_with_free_func (g_free); helper->flags = flags; if (!as_app_validate_setup_networking (helper, error)) return NULL; /* invalid component type */ if (as_app_get_kind (app) == AS_APP_KIND_UNKNOWN) { ai_app_validate_add (helper, AS_PROBLEM_KIND_ATTRIBUTE_INVALID, "<component> has invalid type attribute"); } as_app_validate_check_id (helper, as_app_get_id (app)); /* metadata_license */ license = as_app_get_metadata_license (app); if (license != NULL) { if (require_content_license && !as_app_validate_is_content_license (license)) { ai_app_validate_add (helper, AS_PROBLEM_KIND_TAG_INVALID, "<metadata_license> is not valid [%s]", license); } else if (validate_license) { if (!as_app_validate_license (license, &error_local)) { g_prefix_error (&error_local, "<metadata_license> is not valid [%s]", license); ai_app_validate_add (helper, AS_PROBLEM_KIND_TAG_INVALID, "%s", error_local->message); g_clear_error (&error_local); } } } if (license == NULL) { switch (as_format_get_kind (format)) { case AS_FORMAT_KIND_APPDATA: case AS_FORMAT_KIND_METAINFO: ai_app_validate_add (helper, AS_PROBLEM_KIND_TAG_MISSING, "<metadata_license> is not present"); break; default: break; } } /* project_license */ license = as_app_get_project_license (app); if (license != NULL && validate_license) { if (!as_app_validate_license (license, &error_local)) { g_prefix_error (&error_local, "<project_license> is not valid [%s]", license); ai_app_validate_add (helper, AS_PROBLEM_KIND_TAG_INVALID, "%s", error_local->message); g_clear_error (&error_local); } } if (require_project_license && license == NULL) { switch (as_format_get_kind (format)) { case AS_FORMAT_KIND_APPDATA: case AS_FORMAT_KIND_METAINFO: ai_app_validate_add (helper, AS_PROBLEM_KIND_TAG_MISSING, "<project_license> is not present"); break; default: break; } } /* categories */ if (as_format_get_kind (format) == AS_FORMAT_KIND_APPSTREAM && as_app_get_kind (app) == AS_APP_KIND_DESKTOP) { GPtrArray *categories = as_app_get_categories (app); guint nr_toplevel_cats = 0; const gchar *cats[] = { "AudioVideo", "Development", "Education", "Game", "Graphics", "Network", "Office", "Science", "Settings", "System", "Utility", NULL }; for (guint i = 0; i < categories->len; i++) { const gchar *cat = g_ptr_array_index (categories, i); for (guint j = 0; cats[j] != NULL; j++) { if (g_strcmp0 (cats[j], cat) == 0) nr_toplevel_cats++; } } if (nr_toplevel_cats == 0) { ai_app_validate_add (helper, AS_PROBLEM_KIND_TAG_MISSING, "<category> must include main categories " "from the desktop entry spec"); } else if (nr_toplevel_cats > 3) { ai_app_validate_add (helper, AS_PROBLEM_KIND_TAG_MISSING, "too many main <category> types: %u", nr_toplevel_cats); } } /* translation */ if (require_translation && as_format_get_kind (format) == AS_FORMAT_KIND_APPDATA && as_app_get_translations (app)->len == 0) { ai_app_validate_add (helper, AS_PROBLEM_KIND_TAG_MISSING, "<translation> not specified"); } /* pkgname */ if (as_app_get_pkgname_default (app) != NULL && as_format_get_kind (format) == AS_FORMAT_KIND_METAINFO) { ai_app_validate_add (helper, AS_PROBLEM_KIND_TAG_INVALID, "<pkgname> not allowed in metainfo"); } /* appdata */ if (as_format_get_kind (format) == AS_FORMAT_KIND_APPDATA && as_app_get_kind (app) == AS_APP_KIND_DESKTOP) { AsIcon *icon = as_app_get_icon_default (app); if (icon != NULL && as_icon_get_kind (icon) != AS_ICON_KIND_REMOTE) { ai_app_validate_add (helper, AS_PROBLEM_KIND_TAG_INVALID, "<icon> not allowed in desktop appdata"); } } /* extends */ if (as_app_get_extends(app)->len == 0 && as_app_get_kind (app) == AS_APP_KIND_ADDON && as_format_get_kind (format) == AS_FORMAT_KIND_METAINFO) { ai_app_validate_add (helper, AS_PROBLEM_KIND_TAG_MISSING, "<extends> is not present"); } /* update_contact */ update_contact = as_app_get_update_contact (app); if (g_strcmp0 (update_contact, "someone_who_cares@upstream_project.org") == 0) { ai_app_validate_add (helper, AS_PROBLEM_KIND_TAG_INVALID, "<update_contact> is still set to a dummy value"); } if (update_contact != NULL && strlen (update_contact) < 6) { ai_app_validate_add (helper, AS_PROBLEM_KIND_STYLE_INCORRECT, "<update_contact> is too short [%s]", update_contact); } if (require_contactdetails && update_contact == NULL) { switch (as_format_get_kind (format)) { case AS_FORMAT_KIND_APPDATA: case AS_FORMAT_KIND_METAINFO: ai_app_validate_add (helper, AS_PROBLEM_KIND_TAG_MISSING, "<update_contact> is not present"); break; default: break; } } /* only found for files */ problems = as_app_get_problems (app); if (as_format_get_kind (format) == AS_FORMAT_KIND_APPDATA || as_format_get_kind (format) == AS_FORMAT_KIND_METAINFO) { if ((problems & AS_APP_PROBLEM_NO_XML_HEADER) > 0) { ai_app_validate_add (helper, AS_PROBLEM_KIND_MARKUP_INVALID, "<?xml> header not found"); } if (require_copyright && (problems & AS_APP_PROBLEM_NO_COPYRIGHT_INFO) > 0) { ai_app_validate_add (helper, AS_PROBLEM_KIND_VALUE_MISSING, "<!-- Copyright [year] [name] --> is not present"); } if (deprecated_failure && (problems & AS_APP_PROBLEM_UPDATECONTACT_FALLBACK) > 0) { ai_app_validate_add (helper, AS_PROBLEM_KIND_TAG_INVALID, "<updatecontact> should be <update_contact>"); } } /* check invalid values */ if ((problems & AS_APP_PROBLEM_INVALID_PROJECT_GROUP) > 0) { ai_app_validate_add (helper, AS_PROBLEM_KIND_TAG_INVALID, "<project_group> is not valid"); } /* only allow XML in the specification */ if (require_appstream_spec_only && (problems & AS_APP_PROBLEM_INVALID_XML_TAG) > 0) { ai_app_validate_add (helper, AS_PROBLEM_KIND_TAG_INVALID, "XML data contains unknown tag"); } /* only allow XML in the specification */ if (problems & AS_APP_PROBLEM_EXPECTED_CHILDREN) { ai_app_validate_add (helper, AS_PROBLEM_KIND_TAG_INVALID, "Expected children for tag"); } /* only allow XML in the specification */ if (problems & AS_APP_PROBLEM_INVALID_KEYWORDS) { ai_app_validate_add (helper, AS_PROBLEM_KIND_TAG_INVALID, "<keyword> invalid contents"); } /* releases all have to have unique versions */ if (problems & AS_APP_PROBLEM_DUPLICATE_RELEASE) { ai_app_validate_add (helper, AS_PROBLEM_KIND_TAG_INVALID, "<release> version was duplicated"); } if (problems & AS_APP_PROBLEM_DUPLICATE_SCREENSHOT) { ai_app_validate_add (helper, AS_PROBLEM_KIND_TAG_INVALID, "<screenshot> content was duplicated"); } if (problems & AS_APP_PROBLEM_DUPLICATE_CONTENT_RATING) { ai_app_validate_add (helper, AS_PROBLEM_KIND_TAG_INVALID, "<content_rating> was duplicated"); } /* check for things that have to exist */ if (as_app_get_id (app) == NULL) { ai_app_validate_add (helper, AS_PROBLEM_KIND_TAG_MISSING, "<id> is not present"); } /* games require a content rating */ if (require_content_rating) { GPtrArray *ratings = as_app_get_content_ratings (app); if (ratings->len == 0) { ai_app_validate_add (helper, AS_PROBLEM_KIND_TAG_MISSING, "<content_rating> required " "[use https://odrs.gnome.org/oars]"); } } /* url */ urls = as_app_get_urls (app); keys = g_hash_table_get_keys (urls); for (l = keys; l != NULL; l = l->next) { key = l->data; if (g_strcmp0 (key, "unknown") == 0) { ai_app_validate_add (helper, AS_PROBLEM_KIND_TAG_INVALID, "<url> type invalid [%s]", key); } tmp = g_hash_table_lookup (urls, key); if (tmp == NULL || tmp[0] == '\0') continue; if (!g_str_has_prefix (tmp, "http://") && !g_str_has_prefix (tmp, "https://")) { ai_app_validate_add (helper, AS_PROBLEM_KIND_TAG_INVALID, "<url> does not start with 'http://' [%s]", tmp); } } /* screenshots */ as_app_validate_screenshots (app, helper); /* icons */ as_app_validate_icons (app, helper); /* releases */ if (!as_app_validate_releases (app, helper, error)) return NULL; /* kudos */ if (!as_app_validate_kudos (app, helper, error)) return NULL; /* name */ name = as_app_get_name (app, "C"); if (name != NULL) { str_len = (guint) strlen (name); if (str_len < length_name_min) { ai_app_validate_add (helper, AS_PROBLEM_KIND_STYLE_INCORRECT, "<name> is too short [%s] minimum is %u chars", name, length_name_min); } if (str_len > length_name_max) { ai_app_validate_add (helper, AS_PROBLEM_KIND_STYLE_INCORRECT, "<name> is too long [%s] maximum is %u chars", name, length_name_max); } if (ai_app_validate_fullstop_ending (name)) { ai_app_validate_add (helper, AS_PROBLEM_KIND_STYLE_INCORRECT, "<name> cannot end in '.' [%s]", name); } if (as_app_validate_has_hyperlink (name)) { ai_app_validate_add (helper, AS_PROBLEM_KIND_STYLE_INCORRECT, "<name> cannot contain a hyperlink [%s]", name); } if (require_sentence_case && !as_app_validate_has_first_word_capital (helper, name)) { ai_app_validate_add (helper, AS_PROBLEM_KIND_STYLE_INCORRECT, "<name> requires sentence case [%s]", name); } } else if (require_name) { ai_app_validate_add (helper, AS_PROBLEM_KIND_TAG_MISSING, "<name> is not present"); } /* comment */ summary = as_app_get_comment (app, "C"); if (summary != NULL) { str_len = (guint) strlen (summary); if (str_len < length_summary_min) { ai_app_validate_add (helper, AS_PROBLEM_KIND_STYLE_INCORRECT, "<summary> is too short [%s] minimum is %u chars", summary, length_summary_min); } if (str_len > length_summary_max) { ai_app_validate_add (helper, AS_PROBLEM_KIND_STYLE_INCORRECT, "<summary> is too long [%s] maximum is %u chars", summary, length_summary_max); } if (require_sentence_case && ai_app_validate_fullstop_ending (summary)) { ai_app_validate_add (helper, AS_PROBLEM_KIND_STYLE_INCORRECT, "<summary> cannot end in '.' [%s]", summary); } if (as_app_validate_has_hyperlink (summary)) { ai_app_validate_add (helper, AS_PROBLEM_KIND_STYLE_INCORRECT, "<summary> cannot contain a hyperlink [%s]", summary); } if (require_sentence_case && !as_app_validate_has_first_word_capital (helper, summary)) { ai_app_validate_add (helper, AS_PROBLEM_KIND_STYLE_INCORRECT, "<summary> requires sentence case [%s]", summary); } } else if (require_name) { ai_app_validate_add (helper, AS_PROBLEM_KIND_TAG_MISSING, "<summary> is not present"); } if (require_name_shorter_than_summary && summary != NULL && name != NULL && strlen (summary) < strlen (name)) { ai_app_validate_add (helper, AS_PROBLEM_KIND_STYLE_INCORRECT, "<summary> is shorter than <name>"); } description = as_app_get_description (app, "C"); if (description == NULL) { if (require_description) { ai_app_validate_add (helper, AS_PROBLEM_KIND_TAG_MISSING, "<description> required"); } } else { ret = as_app_validate_description (description, helper, number_para_min, number_para_max, FALSE, &error_local); if (!ret) { ai_app_validate_add (helper, AS_PROBLEM_KIND_MARKUP_INVALID, "%s", error_local->message); g_error_free (error_local); } } if (require_translations) { if (name != NULL && as_app_get_name_size (app) == 1 && (problems & AS_APP_PROBLEM_INTLTOOL_NAME) == 0) { ai_app_validate_add (helper, AS_PROBLEM_KIND_TRANSLATIONS_REQUIRED, "<name> has no translations"); } if (summary != NULL && as_app_get_comment_size (app) == 1 && (problems & AS_APP_PROBLEM_INTLTOOL_SUMMARY) == 0) { ai_app_validate_add (helper, AS_PROBLEM_KIND_TRANSLATIONS_REQUIRED, "<summary> has no translations"); } if (description != NULL && as_app_get_description_size (app) == 1 && (problems & AS_APP_PROBLEM_INTLTOOL_DESCRIPTION) == 0) { ai_app_validate_add (helper, AS_PROBLEM_KIND_TRANSLATIONS_REQUIRED, "<description> has no translations"); } } /* developer_name */ name = as_app_get_developer_name (app, NULL); if (name != NULL) { str_len = (guint) strlen (name); if (str_len < length_name_min) { ai_app_validate_add (helper, AS_PROBLEM_KIND_STYLE_INCORRECT, "<developer_name> is too short [%s] minimum is %u chars", name, length_name_min); } if (str_len > length_name_max) { ai_app_validate_add (helper, AS_PROBLEM_KIND_STYLE_INCORRECT, "<developer_name> is too long [%s] maximum is %u chars", name, length_name_max); } if (as_app_validate_has_hyperlink (name)) { ai_app_validate_add (helper, AS_PROBLEM_KIND_STYLE_INCORRECT, "<developer_name> cannot contain a hyperlink [%s]", name); } if (as_app_validate_has_email (name)) { ai_app_validate_add (helper, AS_PROBLEM_KIND_STYLE_INCORRECT, "<developer_name> cannot contain an email address [%s]", name); } } /* using deprecated names */ if (deprecated_failure && (problems & AS_APP_PROBLEM_DEPRECATED_LICENCE) > 0) { ai_app_validate_add (helper, AS_PROBLEM_KIND_ATTRIBUTE_INVALID, "<licence> is deprecated, use " "<metadata_license> instead"); } if ((problems & AS_APP_PROBLEM_MULTIPLE_ENTRIES) > 0) { ai_app_validate_add (helper, AS_PROBLEM_KIND_MARKUP_INVALID, "<application> used more than once"); } /* require homepage */ if (require_url && as_app_get_url_item (app, AS_URL_KIND_HOMEPAGE) == NULL) { switch (as_format_get_kind (format)) { case AS_FORMAT_KIND_APPDATA: case AS_FORMAT_KIND_METAINFO: ai_app_validate_add (helper, AS_PROBLEM_KIND_TAG_MISSING, "<url> is not present"); break; default: break; } } return helper->probs; }
/** * asb_plugin_process_filename: */ static gboolean asb_plugin_process_filename (AsbPlugin *plugin, AsbPackage *pkg, const gchar *filename, GList **apps, const gchar *tmpdir, GError **error) { AsIcon *icon; AsAppParseFlags parse_flags = AS_APP_PARSE_FLAG_USE_HEURISTICS; gboolean ret; _cleanup_free_ gchar *app_id = NULL; _cleanup_free_ gchar *full_filename = NULL; _cleanup_object_unref_ AsbApp *app = NULL; _cleanup_object_unref_ GdkPixbuf *pixbuf = NULL; /* use GenericName fallback */ if (asb_context_get_flag (plugin->ctx, ASB_CONTEXT_FLAG_USE_FALLBACKS)) parse_flags |= AS_APP_PARSE_FLAG_USE_FALLBACKS; /* create app */ app_id = g_path_get_basename (filename); app = asb_app_new (pkg, app_id); asb_app_set_hidpi_enabled (app, asb_context_get_flag (plugin->ctx, ASB_CONTEXT_FLAG_HIDPI_ICONS)); full_filename = g_build_filename (tmpdir, filename, NULL); if (!as_app_parse_file (AS_APP (app), full_filename, parse_flags, error)) return FALSE; /* NoDisplay apps are never included */ if (as_app_get_metadata_item (AS_APP (app), "NoDisplay") != NULL) asb_app_add_requires_appdata (app, "NoDisplay=true"); /* Settings or DesktopSettings requires AppData */ if (!asb_context_get_flag (plugin->ctx, ASB_CONTEXT_FLAG_IGNORE_SETTINGS)) { if (as_app_has_category (AS_APP (app), "Settings")) asb_app_add_requires_appdata (app, "Category=Settings"); if (as_app_has_category (AS_APP (app), "DesktopSettings")) asb_app_add_requires_appdata (app, "Category=DesktopSettings"); } /* is the icon a stock-icon-name? */ icon = as_app_get_icon_default (AS_APP (app)); if (icon != NULL) { _cleanup_free_ gchar *key = NULL; key = g_strdup (as_icon_get_name (icon)); if (as_icon_get_kind (icon) == AS_ICON_KIND_STOCK) { asb_package_log (pkg, ASB_PACKAGE_LOG_LEVEL_DEBUG, "using stock icon %s", key); } else { _cleanup_error_free_ GError *error_local = NULL; g_ptr_array_set_size (as_app_get_icons (AS_APP (app)), 0); ret = asb_plugin_desktop_add_icons (plugin, app, tmpdir, key, &error_local); if (!ret) { as_app_add_veto (AS_APP (app), "%s", error_local->message); } } } /* add */ asb_plugin_add_app (apps, AS_APP (app)); return TRUE; }