Bug Summary

File:ctk/ctkrecentfilter.c
Warning:line 401, column 29
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name ctkrecentfilter.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/ctk -resource-dir /usr/lib/llvm-16/lib/clang/16 -D HAVE_CONFIG_H -I . -I .. -D G_LOG_DOMAIN="Ctk" -D G_LOG_USE_STRUCTURED=1 -D CTK_VERSION="3.25.5" -D CTK_BINARY_VERSION="3.0.0" -D CTK_COMPILATION -D CTK_PRINT_BACKEND_ENABLE_UNSUPPORTED -D CTK_LIBDIR="/usr/lib" -D CTK_LOCALEDIR="/usr/share/locale" -D CTK_DATADIR="/usr/share" -D CTK_DATA_PREFIX="/usr" -D CTK_SYSCONFDIR="/usr/etc" -D CTK_HOST="x86_64-pc-linux-gnu" -D CTK_PRINT_BACKENDS="file,cups" -D X11_DATA_PREFIX="/usr" -D ISO_CODES_PREFIX="" -I .. -I ../ctk -I .. -I ../cdk -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -D G_ENABLE_DEBUG -D G_ENABLE_CONSISTENCY_CHECKS -D GLIB_MIN_REQUIRED_VERSION=GLIB_VERSION_2_66 -D GLIB_MAX_ALLOWED_VERSION=GLIB_VERSION_2_66 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/atk-1.0 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/pango-1.0 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -D PIC -internal-isystem /usr/lib/llvm-16/lib/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir=/rootdir/ctk -ferror-limit 19 -fvisibility=hidden -fgnuc-version=4.2.1 -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2024-09-19-173409-43638-1 -x c ctkrecentfilter.c
1/* CTK - The GIMP Toolkit
2 * ctkrecentfilter.h - Filter object for recently used resources
3 * Copyright (C) 2006, Emmanuele Bassi
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19/**
20 * SECTION:ctkrecentfilter
21 * @Short_Description: A filter for selecting a subset of recently used files
22 * @Title: CtkRecentFilter
23 *
24 * A #CtkRecentFilter can be used to restrict the files being shown
25 * in a #CtkRecentChooser. Files can be filtered based on their name
26 * (with ctk_recent_filter_add_pattern()), on their mime type (with
27 * ctk_file_filter_add_mime_type()), on the application that has
28 * registered them (with ctk_recent_filter_add_application()), or by
29 * a custom filter function (with ctk_recent_filter_add_custom()).
30 *
31 * Filtering by mime type handles aliasing and subclassing of mime
32 * types; e.g. a filter for text/plain also matches a file with mime
33 * type application/rtf, since application/rtf is a subclass of text/plain.
34 * Note that #CtkRecentFilter allows wildcards for the subtype of a
35 * mime type, so you can e.g. filter for image/\*.
36 *
37 * Normally, filters are used by adding them to a #CtkRecentChooser,
38 * see ctk_recent_chooser_add_filter(), but it is also possible to
39 * manually use a filter on a file with ctk_recent_filter_filter().
40 *
41 * Recently used files are supported since CTK+ 2.10.
42 *
43 * ## CtkRecentFilter as CtkBuildable
44 *
45 * The CtkRecentFilter implementation of the CtkBuildable interface
46 * supports adding rules using the <mime-types>, <patterns> and
47 * <applications> elements and listing the rules within. Specifying
48 * a <mime-type>, <pattern> or <application> has the same effect as
49 * calling ctk_recent_filter_add_mime_type(),
50 * ctk_recent_filter_add_pattern() or ctk_recent_filter_add_application().
51 *
52 * An example of a UI definition fragment specifying CtkRecentFilter rules:
53 * |[
54 * <object class="CtkRecentFilter">
55 * <mime-types>
56 * <mime-type>text/plain</mime-type>
57 * <mime-type>image/png</mime-type>
58 * </mime-types>
59 * <patterns>
60 * <pattern>*.txt</pattern>
61 * <pattern>*.png</pattern>
62 * </patterns>
63 * <applications>
64 * <application>gimp</application>
65 * <application>gedit</application>
66 * <application>glade</application>
67 * </applications>
68 * </object>
69 * ]|
70 */
71
72#include "config.h"
73#include <string.h>
74
75#include <gdk-pixbuf/gdk-pixbuf.h>
76
77#include "ctkrecentfilter.h"
78#include "ctkbuildable.h"
79#include "ctkbuilderprivate.h"
80#include "ctkintl.h"
81#include "ctkprivate.h"
82
83static void ctk_recent_filter_buildable_init (CtkBuildableIface *iface);
84static gboolean ctk_recent_filter_buildable_custom_tag_start (CtkBuildable *buildable,
85 CtkBuilder *builder,
86 GObject *child,
87 const gchar *tagname,
88 GMarkupParser *parser,
89 gpointer *data);
90static void ctk_recent_filter_buildable_custom_tag_end (CtkBuildable *buildable,
91 CtkBuilder *builder,
92 GObject *child,
93 const gchar *tagname,
94 gpointer *data);
95
96typedef struct _CtkRecentFilterClass CtkRecentFilterClass;
97typedef struct _FilterRule FilterRule;
98
99typedef enum {
100 FILTER_RULE_URI,
101 FILTER_RULE_DISPLAY_NAME,
102 FILTER_RULE_MIME_TYPE,
103 FILTER_RULE_PIXBUF_FORMATS,
104 FILTER_RULE_APPLICATION,
105 FILTER_RULE_AGE,
106 FILTER_RULE_GROUP,
107 FILTER_RULE_CUSTOM
108} FilterRuleType;
109
110struct _CtkRecentFilter
111{
112 GInitiallyUnowned parent_instance;
113
114 gchar *name;
115 GSList *rules;
116
117 CtkRecentFilterFlags needed;
118};
119
120struct _CtkRecentFilterClass
121{
122 GInitiallyUnownedClass parent_class;
123};
124
125struct _FilterRule
126{
127 FilterRuleType type;
128 CtkRecentFilterFlags needed;
129
130 union {
131 gchar *uri;
132 gchar *pattern;
133 gchar *mime_type;
134 GSList *pixbuf_formats;
135 gchar *application;
136 gchar *group;
137 gint age;
138 struct {
139 CtkRecentFilterFunc func;
140 gpointer data;
141 GDestroyNotify data_destroy;
142 } custom;
143 } u;
144};
145
146G_DEFINE_TYPE_WITH_CODE (CtkRecentFilter, ctk_recent_filter, G_TYPE_INITIALLY_UNOWNED,static void ctk_recent_filter_init (CtkRecentFilter *self); static
void ctk_recent_filter_class_init (CtkRecentFilterClass *klass
); static GType ctk_recent_filter_get_type_once (void); static
gpointer ctk_recent_filter_parent_class = ((void*)0); static
gint CtkRecentFilter_private_offset; static void ctk_recent_filter_class_intern_init
(gpointer klass) { ctk_recent_filter_parent_class = g_type_class_peek_parent
(klass); if (CtkRecentFilter_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CtkRecentFilter_private_offset); ctk_recent_filter_class_init
((CtkRecentFilterClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer ctk_recent_filter_get_instance_private
(CtkRecentFilter *self) { return (((gpointer) ((guint8*) (self
) + (glong) (CtkRecentFilter_private_offset)))); } GType ctk_recent_filter_get_type
(void) { static GType static_g_define_type_id = 0; if ((__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); (void) (
0 ? (gpointer) * (&static_g_define_type_id) : ((void*)0))
; (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= ctk_recent_filter_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType ctk_recent_filter_get_type_once (
void) { GType g_define_type_id = g_type_register_static_simple
((g_initially_unowned_get_type()), g_intern_static_string ("CtkRecentFilter"
), sizeof (CtkRecentFilterClass), (GClassInitFunc)(void (*)(void
)) ctk_recent_filter_class_intern_init, sizeof (CtkRecentFilter
), (GInstanceInitFunc)(void (*)(void)) ctk_recent_filter_init
, (GTypeFlags) 0); { {{ const GInterfaceInfo g_implement_interface_info
= { (GInterfaceInitFunc)(void (*)(void)) ctk_recent_filter_buildable_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_buildable_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
147 G_IMPLEMENT_INTERFACE (CTK_TYPE_BUILDABLE,static void ctk_recent_filter_init (CtkRecentFilter *self); static
void ctk_recent_filter_class_init (CtkRecentFilterClass *klass
); static GType ctk_recent_filter_get_type_once (void); static
gpointer ctk_recent_filter_parent_class = ((void*)0); static
gint CtkRecentFilter_private_offset; static void ctk_recent_filter_class_intern_init
(gpointer klass) { ctk_recent_filter_parent_class = g_type_class_peek_parent
(klass); if (CtkRecentFilter_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CtkRecentFilter_private_offset); ctk_recent_filter_class_init
((CtkRecentFilterClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer ctk_recent_filter_get_instance_private
(CtkRecentFilter *self) { return (((gpointer) ((guint8*) (self
) + (glong) (CtkRecentFilter_private_offset)))); } GType ctk_recent_filter_get_type
(void) { static GType static_g_define_type_id = 0; if ((__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); (void) (
0 ? (gpointer) * (&static_g_define_type_id) : ((void*)0))
; (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= ctk_recent_filter_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType ctk_recent_filter_get_type_once (
void) { GType g_define_type_id = g_type_register_static_simple
((g_initially_unowned_get_type()), g_intern_static_string ("CtkRecentFilter"
), sizeof (CtkRecentFilterClass), (GClassInitFunc)(void (*)(void
)) ctk_recent_filter_class_intern_init, sizeof (CtkRecentFilter
), (GInstanceInitFunc)(void (*)(void)) ctk_recent_filter_init
, (GTypeFlags) 0); { {{ const GInterfaceInfo g_implement_interface_info
= { (GInterfaceInitFunc)(void (*)(void)) ctk_recent_filter_buildable_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_buildable_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
148 ctk_recent_filter_buildable_init))static void ctk_recent_filter_init (CtkRecentFilter *self); static
void ctk_recent_filter_class_init (CtkRecentFilterClass *klass
); static GType ctk_recent_filter_get_type_once (void); static
gpointer ctk_recent_filter_parent_class = ((void*)0); static
gint CtkRecentFilter_private_offset; static void ctk_recent_filter_class_intern_init
(gpointer klass) { ctk_recent_filter_parent_class = g_type_class_peek_parent
(klass); if (CtkRecentFilter_private_offset != 0) g_type_class_adjust_private_offset
(klass, &CtkRecentFilter_private_offset); ctk_recent_filter_class_init
((CtkRecentFilterClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer ctk_recent_filter_get_instance_private
(CtkRecentFilter *self) { return (((gpointer) ((guint8*) (self
) + (glong) (CtkRecentFilter_private_offset)))); } GType ctk_recent_filter_get_type
(void) { static GType static_g_define_type_id = 0; if ((__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); (void) (
0 ? (gpointer) * (&static_g_define_type_id) : ((void*)0))
; (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= ctk_recent_filter_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType ctk_recent_filter_get_type_once (
void) { GType g_define_type_id = g_type_register_static_simple
((g_initially_unowned_get_type()), g_intern_static_string ("CtkRecentFilter"
), sizeof (CtkRecentFilterClass), (GClassInitFunc)(void (*)(void
)) ctk_recent_filter_class_intern_init, sizeof (CtkRecentFilter
), (GInstanceInitFunc)(void (*)(void)) ctk_recent_filter_init
, (GTypeFlags) 0); { {{ const GInterfaceInfo g_implement_interface_info
= { (GInterfaceInitFunc)(void (*)(void)) ctk_recent_filter_buildable_init
, ((void*)0), ((void*)0) }; g_type_add_interface_static (g_define_type_id
, (ctk_buildable_get_type ()), &g_implement_interface_info
); };} } return g_define_type_id; }
149
150
151static void
152filter_rule_free (FilterRule *rule)
153{
154 switch (rule->type)
155 {
156 case FILTER_RULE_MIME_TYPE:
157 g_free (rule->u.mime_type);
158 break;
159 case FILTER_RULE_URI:
160 g_free (rule->u.uri);
161 break;
162 case FILTER_RULE_DISPLAY_NAME:
163 g_free (rule->u.pattern);
164 break;
165 case FILTER_RULE_PIXBUF_FORMATS:
166 g_slist_free (rule->u.pixbuf_formats);
167 break;
168 case FILTER_RULE_AGE:
169 break;
170 case FILTER_RULE_APPLICATION:
171 g_free (rule->u.application);
172 break;
173 case FILTER_RULE_GROUP:
174 g_free (rule->u.group);
175 break;
176 case FILTER_RULE_CUSTOM:
177 if (rule->u.custom.data_destroy)
178 rule->u.custom.data_destroy (rule->u.custom.data);
179 break;
180 default:
181 g_assert_not_reached ()do { g_assertion_message_expr ("Ctk", "ctkrecentfilter.c", 181
, ((const char*) (__func__)), ((void*)0)); } while (0)
;
182 break;
183 }
184
185 g_free (rule);
186}
187
188static void
189ctk_recent_filter_finalize (GObject *object)
190{
191 CtkRecentFilter *filter = CTK_RECENT_FILTER (object)((((CtkRecentFilter*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((ctk_recent_filter_get_type ()))))))
;
192
193 g_free (filter->name);
194 g_slist_free_full (filter->rules, (GDestroyNotify) filter_rule_free);
195
196 G_OBJECT_CLASS (ctk_recent_filter_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((ctk_recent_filter_parent_class)), (((GType) ((20) <<
(2))))))))
->finalize (object);
197}
198
199static void
200ctk_recent_filter_class_init (CtkRecentFilterClass *klass)
201{
202 GObjectClass *gobject_class = G_OBJECT_CLASS (klass)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((klass)), (((GType) ((20) << (2))))))))
;
203
204 gobject_class->finalize = ctk_recent_filter_finalize;
205}
206
207static void
208ctk_recent_filter_init (CtkRecentFilter *filter G_GNUC_UNUSED__attribute__ ((__unused__)))
209{
210
211}
212
213
214/*
215 * CtkBuildable implementation
216 */
217static void
218ctk_recent_filter_buildable_init (CtkBuildableIface *iface)
219{
220 iface->custom_tag_start = ctk_recent_filter_buildable_custom_tag_start;
221 iface->custom_tag_end = ctk_recent_filter_buildable_custom_tag_end;
222}
223
224
225typedef enum {
226 PARSE_MIME_TYPES,
227 PARSE_PATTERNS,
228 PARSE_APPLICATIONS
229} ParserType;
230
231typedef struct {
232 CtkRecentFilter *filter;
233 CtkBuilder *builder;
234 ParserType type;
235 GString *string;
236 gboolean parsing;
237} SubParserData;
238
239static void
240parser_start_element (GMarkupParseContext *context,
241 const gchar *element_name,
242 const gchar **names,
243 const gchar **values,
244 gpointer user_data,
245 GError **error)
246{
247 SubParserData *data = (SubParserData*)user_data;
248
249 if (!g_markup_collect_attributes (element_name, names, values, error,
250 G_MARKUP_COLLECT_INVALID, NULL((void*)0), NULL((void*)0),
251 G_MARKUP_COLLECT_INVALID))
252 {
253 _ctk_builder_prefix_error (data->builder, context, error);
254 return;
255 }
256
257 if (strcmp (element_name, "mime-types") == 0 ||
258 strcmp (element_name, "patterns") == 0 ||
259 strcmp (element_name, "applications") == 0)
260 {
261 if (!_ctk_builder_check_parent (data->builder, context, "object", error))
262 return;
263 }
264 else if (strcmp (element_name, "mime-type") == 0)
265 {
266 if (!_ctk_builder_check_parent (data->builder, context, "mime-types", error))
267 return;
268
269 data->parsing = TRUE(!(0));
270 }
271 else if (strcmp (element_name, "pattern") == 0)
272 {
273 if (!_ctk_builder_check_parent (data->builder, context, "patterns", error))
274 return;
275
276 data->parsing = TRUE(!(0));
277 }
278 else if (strcmp (element_name, "application") == 0)
279 {
280 if (!_ctk_builder_check_parent (data->builder, context, "applications", error))
281 return;
282
283 data->parsing = TRUE(!(0));
284 }
285 else
286 {
287 _ctk_builder_error_unhandled_tag (data->builder, context,
288 "CtkRecentFilter", element_name,
289 error);
290 }
291}
292
293static void
294parser_text_element (GMarkupParseContext *context G_GNUC_UNUSED__attribute__ ((__unused__)),
295 const gchar *text,
296 gsize text_len,
297 gpointer user_data,
298 GError **error G_GNUC_UNUSED__attribute__ ((__unused__)))
299{
300 SubParserData *data = (SubParserData*)user_data;
301
302 if (data->parsing)
303 g_string_append_len (data->string, text, text_len)g_string_append_len_inline (data->string, text, text_len);
304}
305
306static void
307parser_end_element (GMarkupParseContext *context G_GNUC_UNUSED__attribute__ ((__unused__)),
308 const gchar *element_name G_GNUC_UNUSED__attribute__ ((__unused__)),
309 gpointer user_data,
310 GError **error G_GNUC_UNUSED__attribute__ ((__unused__)))
311{
312 SubParserData *data = (SubParserData*)user_data;
313
314 if (data->string)
315 {
316 switch (data->type)
317 {
318 case PARSE_MIME_TYPES:
319 ctk_recent_filter_add_mime_type (data->filter, data->string->str);
320 break;
321 case PARSE_PATTERNS:
322 ctk_recent_filter_add_pattern (data->filter, data->string->str);
323 break;
324 case PARSE_APPLICATIONS:
325 ctk_recent_filter_add_application (data->filter, data->string->str);
326 break;
327 default:
328 break;
329 }
330 }
331
332 g_string_set_size (data->string, 0);
333 data->parsing = FALSE(0);
334}
335
336static const GMarkupParser sub_parser =
337 {
338 .start_element = parser_start_element,
339 .end_element = parser_end_element,
340 .text = parser_text_element,
341 };
342
343static gboolean
344ctk_recent_filter_buildable_custom_tag_start (CtkBuildable *buildable,
345 CtkBuilder *builder,
346 GObject *child G_GNUC_UNUSED__attribute__ ((__unused__)),
347 const gchar *tagname,
348 GMarkupParser *parser,
349 gpointer *parser_data)
350{
351 SubParserData *data = NULL((void*)0);
352
353 if (strcmp (tagname, "mime-types") == 0)
354 {
355 data = g_slice_new0 (SubParserData)((SubParserData*) g_slice_alloc0 (sizeof (SubParserData)));
356 data->string = g_string_new ("");
357 data->type = PARSE_MIME_TYPES;
358 data->filter = CTK_RECENT_FILTER (buildable)((((CtkRecentFilter*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((buildable)), ((ctk_recent_filter_get_type ()))))))
;
359 data->builder = builder;
360
361 *parser = sub_parser;
362 *parser_data = data;
363 }
364 else if (strcmp (tagname, "patterns") == 0)
365 {
366 data = g_slice_new0 (SubParserData)((SubParserData*) g_slice_alloc0 (sizeof (SubParserData)));
367 data->string = g_string_new ("");
368 data->type = PARSE_PATTERNS;
369 data->filter = CTK_RECENT_FILTER (buildable)((((CtkRecentFilter*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((buildable)), ((ctk_recent_filter_get_type ()))))))
;
370 data->builder = builder;
371
372 *parser = sub_parser;
373 *parser_data = data;
374 }
375 else if (strcmp (tagname, "applications") == 0)
376 {
377 data = g_slice_new0 (SubParserData)((SubParserData*) g_slice_alloc0 (sizeof (SubParserData)));
378 data->string = g_string_new ("");
379 data->type = PARSE_APPLICATIONS;
380 data->filter = CTK_RECENT_FILTER (buildable)((((CtkRecentFilter*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((buildable)), ((ctk_recent_filter_get_type ()))))))
;
381 data->builder = builder;
382
383 *parser = sub_parser;
384 *parser_data = data;
385 }
386
387 return data != NULL((void*)0);
388}
389
390static void
391ctk_recent_filter_buildable_custom_tag_end (CtkBuildable *buildable G_GNUC_UNUSED__attribute__ ((__unused__)),
392 CtkBuilder *builder G_GNUC_UNUSED__attribute__ ((__unused__)),
393 GObject *child G_GNUC_UNUSED__attribute__ ((__unused__)),
394 const gchar *tagname,
395 gpointer *parser_data)
396{
397 if (strcmp (tagname, "mime-types") == 0 ||
398 strcmp (tagname, "patterns") == 0 ||
399 strcmp (tagname, "applications") == 0)
400 {
401 SubParserData *data = (SubParserData*)parser_data;
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption
402
403 g_string_free (data->string, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(data->string), ((!(0)))) : g_string_free_and_steal (data->
string)) : (g_string_free) ((data->string), ((!(0)))))
;
404 g_slice_free (SubParserData, data)do { if (1) g_slice_free1 (sizeof (SubParserData), (data)); else
(void) ((SubParserData*) 0 == (data)); } while (0)
;
405 }
406}
407
408/*
409 * Public API
410 */
411
412/**
413 * ctk_recent_filter_new:
414 *
415 * Creates a new #CtkRecentFilter with no rules added to it.
416 * Such filter does not accept any recently used resources, so is not
417 * particularly useful until you add rules with
418 * ctk_recent_filter_add_pattern(), ctk_recent_filter_add_mime_type(),
419 * ctk_recent_filter_add_application(), ctk_recent_filter_add_age().
420 * To create a filter that accepts any recently used resource, use:
421 * |[<!-- language="C" -->
422 * CtkRecentFilter *filter = ctk_recent_filter_new ();
423 * ctk_recent_filter_add_pattern (filter, "*");
424 * ]|
425 *
426 * Returns: a new #CtkRecentFilter
427 *
428 * Since: 2.10
429 */
430CtkRecentFilter *
431ctk_recent_filter_new (void)
432{
433 return g_object_new (CTK_TYPE_RECENT_FILTER(ctk_recent_filter_get_type ()), NULL((void*)0));
434}
435
436/**
437 * ctk_recent_filter_set_name:
438 * @filter: a #CtkRecentFilter
439 * @name: then human readable name of @filter
440 *
441 * Sets the human-readable name of the filter; this is the string
442 * that will be displayed in the recently used resources selector
443 * user interface if there is a selectable list of filters.
444 *
445 * Since: 2.10
446 */
447void
448ctk_recent_filter_set_name (CtkRecentFilter *filter,
449 const gchar *name)
450{
451 g_return_if_fail (CTK_IS_RECENT_FILTER (filter))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((filter)); GType __t = ((ctk_recent_filter_get_type ()));
gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class
&& __inst->g_class->g_type == __t) __r = (!(0)
); else __r = g_type_check_instance_is_a (__inst, __t); __r; }
)))))) { } else { g_return_if_fail_warning ("Ctk", ((const char
*) (__func__)), "CTK_IS_RECENT_FILTER (filter)"); return; } }
while (0)
;
452
453 g_free (filter->name);
454
455 if (name)
456 filter->name = g_strdup (name)g_strdup_inline (name);
457}
458
459/**
460 * ctk_recent_filter_get_name:
461 * @filter: a #CtkRecentFilter
462 *
463 * Gets the human-readable name for the filter.
464 * See ctk_recent_filter_set_name().
465 *
466 * Returns: (nullable): the name of the filter, or %NULL. The returned string
467 * is owned by the filter object and should not be freed.
468 *
469 * Since: 2.10
470 */
471const gchar *
472ctk_recent_filter_get_name (CtkRecentFilter *filter)
473{
474 g_return_val_if_fail (CTK_IS_RECENT_FILTER (filter), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((filter)); GType __t = ((ctk_recent_filter_get_type ()));
gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class
&& __inst->g_class->g_type == __t) __r = (!(0)
); else __r = g_type_check_instance_is_a (__inst, __t); __r; }
)))))) { } else { g_return_if_fail_warning ("Ctk", ((const char
*) (__func__)), "CTK_IS_RECENT_FILTER (filter)"); return (((void
*)0)); } } while (0)
;
475
476 return filter->name;
477}
478
479/**
480 * ctk_recent_filter_get_needed:
481 * @filter: a #CtkRecentFilter
482 *
483 * Gets the fields that need to be filled in for the #CtkRecentFilterInfo
484 * passed to ctk_recent_filter_filter()
485 *
486 * This function will not typically be used by applications; it
487 * is intended principally for use in the implementation of
488 * #CtkRecentChooser.
489 *
490 * Returns: bitfield of flags indicating needed fields when
491 * calling ctk_recent_filter_filter()
492 *
493 * Since: 2.10
494 */
495CtkRecentFilterFlags
496ctk_recent_filter_get_needed (CtkRecentFilter *filter)
497{
498 return filter->needed;
499}
500
501static void
502recent_filter_add_rule (CtkRecentFilter *filter,
503 FilterRule *rule)
504{
505 filter->needed |= rule->needed;
506 filter->rules = g_slist_append (filter->rules, rule);
507}
508
509/**
510 * ctk_recent_filter_add_mime_type:
511 * @filter: a #CtkRecentFilter
512 * @mime_type: a MIME type
513 *
514 * Adds a rule that allows resources based on their registered MIME type.
515 *
516 * Since: 2.10
517 */
518void
519ctk_recent_filter_add_mime_type (CtkRecentFilter *filter,
520 const gchar *mime_type)
521{
522 FilterRule *rule;
523
524 g_return_if_fail (CTK_IS_RECENT_FILTER (filter))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((filter)); GType __t = ((ctk_recent_filter_get_type ()));
gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class
&& __inst->g_class->g_type == __t) __r = (!(0)
); else __r = g_type_check_instance_is_a (__inst, __t); __r; }
)))))) { } else { g_return_if_fail_warning ("Ctk", ((const char
*) (__func__)), "CTK_IS_RECENT_FILTER (filter)"); return; } }
while (0)
;
525 g_return_if_fail (mime_type != NULL)do { if ((mime_type != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "mime_type != NULL"); return
; } } while (0)
;
526
527 rule = g_new0 (FilterRule, 1)((FilterRule *) g_malloc0_n ((1), sizeof (FilterRule)));
528 rule->type = FILTER_RULE_MIME_TYPE;
529 rule->needed = CTK_RECENT_FILTER_MIME_TYPE;
530 rule->u.mime_type = g_strdup (mime_type)g_strdup_inline (mime_type);
531
532 recent_filter_add_rule (filter, rule);
533}
534
535/**
536 * ctk_recent_filter_add_pattern:
537 * @filter: a #CtkRecentFilter
538 * @pattern: a file pattern
539 *
540 * Adds a rule that allows resources based on a pattern matching their
541 * display name.
542 *
543 * Since: 2.10
544 */
545void
546ctk_recent_filter_add_pattern (CtkRecentFilter *filter,
547 const gchar *pattern)
548{
549 FilterRule *rule;
550
551 g_return_if_fail (CTK_IS_RECENT_FILTER (filter))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((filter)); GType __t = ((ctk_recent_filter_get_type ()));
gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class
&& __inst->g_class->g_type == __t) __r = (!(0)
); else __r = g_type_check_instance_is_a (__inst, __t); __r; }
)))))) { } else { g_return_if_fail_warning ("Ctk", ((const char
*) (__func__)), "CTK_IS_RECENT_FILTER (filter)"); return; } }
while (0)
;
552 g_return_if_fail (pattern != NULL)do { if ((pattern != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "pattern != NULL"); return
; } } while (0)
;
553
554 rule = g_new0 (FilterRule, 1)((FilterRule *) g_malloc0_n ((1), sizeof (FilterRule)));
555 rule->type = FILTER_RULE_DISPLAY_NAME;
556 rule->needed = CTK_RECENT_FILTER_DISPLAY_NAME;
557 rule->u.pattern = g_strdup (pattern)g_strdup_inline (pattern);
558
559 recent_filter_add_rule (filter, rule);
560}
561
562/**
563 * ctk_recent_filter_add_pixbuf_formats:
564 * @filter: a #CtkRecentFilter
565 *
566 * Adds a rule allowing image files in the formats supported
567 * by GdkPixbuf.
568 *
569 * Since: 2.10
570 */
571void
572ctk_recent_filter_add_pixbuf_formats (CtkRecentFilter *filter)
573{
574 FilterRule *rule;
575
576 g_return_if_fail (CTK_IS_RECENT_FILTER (filter))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((filter)); GType __t = ((ctk_recent_filter_get_type ()));
gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class
&& __inst->g_class->g_type == __t) __r = (!(0)
); else __r = g_type_check_instance_is_a (__inst, __t); __r; }
)))))) { } else { g_return_if_fail_warning ("Ctk", ((const char
*) (__func__)), "CTK_IS_RECENT_FILTER (filter)"); return; } }
while (0)
;
577
578 rule = g_new0 (FilterRule, 1)((FilterRule *) g_malloc0_n ((1), sizeof (FilterRule)));
579 rule->type = FILTER_RULE_PIXBUF_FORMATS;
580 rule->needed = CTK_RECENT_FILTER_MIME_TYPE;
581 rule->u.pixbuf_formats = gdk_pixbuf_get_formats ();
582
583 recent_filter_add_rule (filter, rule);
584}
585
586/**
587 * ctk_recent_filter_add_application:
588 * @filter: a #CtkRecentFilter
589 * @application: an application name
590 *
591 * Adds a rule that allows resources based on the name of the application
592 * that has registered them.
593 *
594 * Since: 2.10
595 */
596void
597ctk_recent_filter_add_application (CtkRecentFilter *filter,
598 const gchar *application)
599{
600 FilterRule *rule;
601
602 g_return_if_fail (CTK_IS_RECENT_FILTER (filter))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((filter)); GType __t = ((ctk_recent_filter_get_type ()));
gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class
&& __inst->g_class->g_type == __t) __r = (!(0)
); else __r = g_type_check_instance_is_a (__inst, __t); __r; }
)))))) { } else { g_return_if_fail_warning ("Ctk", ((const char
*) (__func__)), "CTK_IS_RECENT_FILTER (filter)"); return; } }
while (0)
;
603 g_return_if_fail (application != NULL)do { if ((application != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "application != NULL"); return
; } } while (0)
;
604
605 rule = g_new0 (FilterRule, 1)((FilterRule *) g_malloc0_n ((1), sizeof (FilterRule)));
606 rule->type = FILTER_RULE_APPLICATION;
607 rule->needed = CTK_RECENT_FILTER_APPLICATION;
608 rule->u.application = g_strdup (application)g_strdup_inline (application);
609
610 recent_filter_add_rule (filter, rule);
611}
612
613/**
614 * ctk_recent_filter_add_group:
615 * @filter: a #CtkRecentFilter
616 * @group: a group name
617 *
618 * Adds a rule that allows resources based on the name of the group
619 * to which they belong
620 *
621 * Since: 2.10
622 */
623void
624ctk_recent_filter_add_group (CtkRecentFilter *filter,
625 const gchar *group)
626{
627 FilterRule *rule;
628
629 g_return_if_fail (CTK_IS_RECENT_FILTER (filter))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((filter)); GType __t = ((ctk_recent_filter_get_type ()));
gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class
&& __inst->g_class->g_type == __t) __r = (!(0)
); else __r = g_type_check_instance_is_a (__inst, __t); __r; }
)))))) { } else { g_return_if_fail_warning ("Ctk", ((const char
*) (__func__)), "CTK_IS_RECENT_FILTER (filter)"); return; } }
while (0)
;
630 g_return_if_fail (group != NULL)do { if ((group != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "group != NULL"); return
; } } while (0)
;
631
632 rule = g_new0 (FilterRule, 1)((FilterRule *) g_malloc0_n ((1), sizeof (FilterRule)));
633 rule->type = FILTER_RULE_GROUP;
634 rule->needed = CTK_RECENT_FILTER_GROUP;
635 rule->u.group = g_strdup (group)g_strdup_inline (group);
636
637 recent_filter_add_rule (filter, rule);
638}
639
640/**
641 * ctk_recent_filter_add_age:
642 * @filter: a #CtkRecentFilter
643 * @days: number of days
644 *
645 * Adds a rule that allows resources based on their age - that is, the number
646 * of days elapsed since they were last modified.
647 *
648 * Since: 2.10
649 */
650void
651ctk_recent_filter_add_age (CtkRecentFilter *filter,
652 gint days)
653{
654 FilterRule *rule;
655
656 g_return_if_fail (CTK_IS_RECENT_FILTER (filter))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((filter)); GType __t = ((ctk_recent_filter_get_type ()));
gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class
&& __inst->g_class->g_type == __t) __r = (!(0)
); else __r = g_type_check_instance_is_a (__inst, __t); __r; }
)))))) { } else { g_return_if_fail_warning ("Ctk", ((const char
*) (__func__)), "CTK_IS_RECENT_FILTER (filter)"); return; } }
while (0)
;
657
658 rule = g_new0 (FilterRule, 1)((FilterRule *) g_malloc0_n ((1), sizeof (FilterRule)));
659 rule->type = FILTER_RULE_AGE;
660 rule->needed = CTK_RECENT_FILTER_AGE;
661 rule->u.age = days;
662
663 recent_filter_add_rule (filter, rule);
664}
665
666/**
667 * ctk_recent_filter_add_custom:
668 * @filter: a #CtkRecentFilter
669 * @needed: bitfield of flags indicating the information that the custom
670 * filter function needs.
671 * @func: callback function; if the function returns %TRUE, then
672 * the file will be displayed.
673 * @data: data to pass to @func
674 * @data_destroy: function to call to free @data when it is no longer needed.
675 *
676 * Adds a rule to a filter that allows resources based on a custom callback
677 * function. The bitfield @needed which is passed in provides information
678 * about what sorts of information that the filter function needs;
679 * this allows CTK+ to avoid retrieving expensive information when
680 * it isn’t needed by the filter.
681 *
682 * Since: 2.10
683 **/
684void
685ctk_recent_filter_add_custom (CtkRecentFilter *filter,
686 CtkRecentFilterFlags needed,
687 CtkRecentFilterFunc func,
688 gpointer data,
689 GDestroyNotify data_destroy)
690{
691 FilterRule *rule;
692
693 g_return_if_fail (CTK_IS_RECENT_FILTER (filter))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((filter)); GType __t = ((ctk_recent_filter_get_type ()));
gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class
&& __inst->g_class->g_type == __t) __r = (!(0)
); else __r = g_type_check_instance_is_a (__inst, __t); __r; }
)))))) { } else { g_return_if_fail_warning ("Ctk", ((const char
*) (__func__)), "CTK_IS_RECENT_FILTER (filter)"); return; } }
while (0)
;
694 g_return_if_fail (func != NULL)do { if ((func != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "func != NULL"); return;
} } while (0)
;
695
696 rule = g_new0 (FilterRule, 1)((FilterRule *) g_malloc0_n ((1), sizeof (FilterRule)));
697 rule->type = FILTER_RULE_CUSTOM;
698 rule->needed = needed;
699 rule->u.custom.func = func;
700 rule->u.custom.data = data;
701 rule->u.custom.data_destroy = data_destroy;
702
703 recent_filter_add_rule (filter, rule);
704}
705
706
707/**
708 * ctk_recent_filter_filter:
709 * @filter: a #CtkRecentFilter
710 * @filter_info: a #CtkRecentFilterInfo containing information
711 * about a recently used resource
712 *
713 * Tests whether a file should be displayed according to @filter.
714 * The #CtkRecentFilterInfo @filter_info should include
715 * the fields returned from ctk_recent_filter_get_needed(), and
716 * must set the #CtkRecentFilterInfo.contains field of @filter_info
717 * to indicate which fields have been set.
718 *
719 * This function will not typically be used by applications; it
720 * is intended principally for use in the implementation of
721 * #CtkRecentChooser.
722 *
723 * Returns: %TRUE if the file should be displayed
724 *
725 * Since: 2.10
726 */
727gboolean
728ctk_recent_filter_filter (CtkRecentFilter *filter,
729 const CtkRecentFilterInfo *filter_info)
730{
731 GSList *l;
732
733 g_return_val_if_fail (CTK_IS_RECENT_FILTER (filter), FALSE)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((filter)); GType __t = ((ctk_recent_filter_get_type ()));
gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class
&& __inst->g_class->g_type == __t) __r = (!(0)
); else __r = g_type_check_instance_is_a (__inst, __t); __r; }
)))))) { } else { g_return_if_fail_warning ("Ctk", ((const char
*) (__func__)), "CTK_IS_RECENT_FILTER (filter)"); return ((0)
); } } while (0)
;
734 g_return_val_if_fail (filter_info != NULL, FALSE)do { if ((filter_info != ((void*)0))) { } else { g_return_if_fail_warning
("Ctk", ((const char*) (__func__)), "filter_info != NULL"); return
((0)); } } while (0)
;
735
736 for (l = filter->rules; l != NULL((void*)0); l = l->next)
737 {
738 FilterRule *rule = (FilterRule *) l->data;
739
740 if ((filter_info->contains & rule->needed) != rule->needed)
741 continue;
742
743 switch (rule->type)
744 {
745 case FILTER_RULE_MIME_TYPE:
746 if (filter_info->mime_type != NULL((void*)0))
747 {
748 gchar *filter_content_type, *rule_content_type;
749 gboolean match = FALSE(0);
750
751 filter_content_type = g_content_type_from_mime_type (filter_info->mime_type);
752 rule_content_type = g_content_type_from_mime_type (rule->u.mime_type);
753 if (filter_content_type != NULL((void*)0) && rule_content_type != NULL((void*)0))
754 match = g_content_type_is_a (filter_content_type, rule_content_type);
755 g_free (filter_content_type);
756 g_free (rule_content_type);
757
758 if (match)
759 return TRUE(!(0));
760 }
761 break;
762 case FILTER_RULE_APPLICATION:
763 if (filter_info->applications)
764 {
765 gint i;
766
767 for (i = 0; filter_info->applications[i] != NULL((void*)0); i++)
768 {
769 if (strcmp (filter_info->applications[i], rule->u.application) == 0)
770 return TRUE(!(0));
771 }
772 }
773 break;
774 case FILTER_RULE_GROUP:
775 if (filter_info->groups)
776 {
777 gint i;
778
779 for (i = 0; filter_info->groups[i] != NULL((void*)0); i++)
780 {
781 if (strcmp (filter_info->groups[i], rule->u.group) == 0)
782 return TRUE(!(0));
783 }
784 }
785 break;
786 case FILTER_RULE_PIXBUF_FORMATS:
787 {
788 GSList *list;
789 if (!filter_info->mime_type)
790 break;
791
792 for (list = rule->u.pixbuf_formats; list; list = list->next)
793 {
794 gint i;
795 gchar **mime_types;
796
797 mime_types = gdk_pixbuf_format_get_mime_types (list->data);
798
799 for (i = 0; mime_types[i] != NULL((void*)0); i++)
800 {
801 if (strcmp (mime_types[i], filter_info->mime_type) == 0)
802 {
803 g_strfreev (mime_types);
804 return TRUE(!(0));
805 }
806 }
807
808 g_strfreev (mime_types);
809 }
810 break;
811 }
812 case FILTER_RULE_URI:
813 if ((filter_info->uri != NULL((void*)0)) &&
814 _ctk_fnmatch (rule->u.uri, filter_info->uri, FALSE(0)))
815 return TRUE(!(0));
816 break;
817 case FILTER_RULE_DISPLAY_NAME:
818 if ((filter_info->display_name != NULL((void*)0)) &&
819 _ctk_fnmatch (rule->u.pattern, filter_info->display_name, FALSE(0)))
820 return TRUE(!(0));
821 break;
822 case FILTER_RULE_AGE:
823 if ((filter_info->age != -1) &&
824 (filter_info->age < rule->u.age))
825 return TRUE(!(0));
826 break;
827 case FILTER_RULE_CUSTOM:
828 if (rule->u.custom.func (filter_info, rule->u.custom.data))
829 return TRUE(!(0));
830 break;
831 }
832 }
833
834 return FALSE(0);
835}