1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
2  *
3  * Copyright (C) 2014-2015 Richard Hughes <richard@hughsie.com>
4  *
5  * SPDX-License-Identifier: LGPL-2.1+
6  */
7 
8 #include <config.h>
9 #include <string.h>
10 #include <fnmatch.h>
11 
12 #include <asb-plugin.h>
13 
14 #define __APPSTREAM_GLIB_PRIVATE_H
15 #include <as-utils-private.h>
16 #include <as-app-private.h>
17 
18 const gchar *
asb_plugin_get_name(void)19 asb_plugin_get_name (void)
20 {
21 	return "desktop";
22 }
23 
24 void
asb_plugin_add_globs(AsbPlugin * plugin,GPtrArray * globs)25 asb_plugin_add_globs (AsbPlugin *plugin, GPtrArray *globs)
26 {
27 	asb_plugin_add_glob (globs, "/usr/share/applications/*.desktop");
28 	asb_plugin_add_glob (globs, "/usr/share/applications/kde4/*.desktop");
29 }
30 
31 static gboolean
asb_plugin_desktop_refine(AsbPlugin * plugin,AsbPackage * pkg,const gchar * filename,AsbApp * app,const gchar * tmpdir,GError ** error)32 asb_plugin_desktop_refine (AsbPlugin *plugin,
33 			   AsbPackage *pkg,
34 			   const gchar *filename,
35 			   AsbApp *app,
36 			   const gchar *tmpdir,
37 			   GError **error)
38 {
39 	AsAppParseFlags parse_flags = AS_APP_PARSE_FLAG_USE_HEURISTICS |
40 				      AS_APP_PARSE_FLAG_ALLOW_VETO;
41 	g_autoptr(AsApp) desktop_app = NULL;
42 	g_autoptr(GdkPixbuf) pixbuf = NULL;
43 
44 	/* use GenericName fallback */
45 	if (asb_context_get_flag (plugin->ctx, ASB_CONTEXT_FLAG_USE_FALLBACKS))
46 		parse_flags |= AS_APP_PARSE_FLAG_USE_FALLBACKS;
47 
48 	/* create app */
49 	desktop_app = as_app_new ();
50 	if (!as_app_parse_file (desktop_app, filename, parse_flags, error))
51 		return FALSE;
52 
53 	/* copy all metadata */
54 	as_app_subsume_full (AS_APP (app), desktop_app,
55 			     AS_APP_SUBSUME_FLAG_NO_OVERWRITE |
56 			     AS_APP_SUBSUME_FLAG_MERGE);
57 
58 	return TRUE;
59 }
60 
61 gboolean
asb_plugin_process_app(AsbPlugin * plugin,AsbPackage * pkg,AsbApp * app,const gchar * tmpdir,GError ** error)62 asb_plugin_process_app (AsbPlugin *plugin,
63 			AsbPackage *pkg,
64 			AsbApp *app,
65 			const gchar *tmpdir,
66 			GError **error)
67 {
68 	AsLaunchable *launchable;
69 	gboolean found = FALSE;
70 	guint i;
71 	g_autoptr(GString) desktop_basename = NULL;
72 	const gchar *app_dirs[] = {
73 		"/usr/share/applications",
74 		"/usr/share/applications/kde4",
75 		NULL };
76 
77 	/* get the (optional) launchable to get the name of the desktop file */
78 	launchable = as_app_get_launchable_by_kind (AS_APP (app), AS_LAUNCHABLE_KIND_DESKTOP_ID);
79 	if (launchable != NULL) {
80 		desktop_basename = g_string_new (as_launchable_get_value (launchable));
81 	} else {
82 		desktop_basename = g_string_new (as_app_get_id (AS_APP (app)));
83 		if (!g_str_has_suffix (desktop_basename->str, ".desktop"))
84 			g_string_append (desktop_basename, ".desktop");
85 	}
86 
87 	/* use the .desktop file to refine the application */
88 	for (i = 0; app_dirs[i] != NULL; i++) {
89 		g_autofree gchar *fn = NULL;
90 		fn = g_build_filename (tmpdir,
91 				       app_dirs[i],
92 				       desktop_basename->str,
93 				       NULL);
94 		if (g_file_test (fn, G_FILE_TEST_EXISTS)) {
95 			if (!asb_plugin_desktop_refine (plugin, pkg, fn,
96 							app, tmpdir, error))
97 				return FALSE;
98 			found = TRUE;
99 		}
100 	}
101 
102 	/* required */
103 	if (!found && as_app_get_kind (AS_APP (app)) == AS_APP_KIND_DESKTOP) {
104 		g_set_error (error,
105 			     ASB_PLUGIN_ERROR,
106 			     ASB_PLUGIN_ERROR_FAILED,
107 			     "a desktop file is required for %s",
108 			     as_app_get_id (AS_APP (app)));
109 		return FALSE;
110 	}
111 
112 	return TRUE;
113 }
114