File: | src/eoc-util.c |
Warning: | line 302, column 11 Out of bound memory access (access exceeds upper limit of memory block) |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* Eye Of Cafe - General Utilities | |||
2 | * | |||
3 | * Copyright (C) 2006 The Free Software Foundation | |||
4 | * | |||
5 | * Author: Lucas Rocha <lucasr@gnome.org> | |||
6 | * | |||
7 | * Based on code by: | |||
8 | * - Jens Finke <jens@gnome.org> | |||
9 | * | |||
10 | * This program is free software; you can redistribute it and/or modify | |||
11 | * it under the terms of the GNU General Public License as published by | |||
12 | * the Free Software Foundation; either version 2 of the License, or | |||
13 | * (at your option) any later version. | |||
14 | * | |||
15 | * This program is distributed in the hope that it will be useful, | |||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
18 | * GNU General Public License for more details. | |||
19 | * | |||
20 | * You should have received a copy of the GNU General Public License | |||
21 | * along with this program; if not, write to the Free Software | |||
22 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. | |||
23 | */ | |||
24 | ||||
25 | #ifdef HAVE_CONFIG_H1 | |||
26 | #include "config.h" | |||
27 | #endif | |||
28 | ||||
29 | #include <sys/time.h> | |||
30 | #ifdef HAVE_STRPTIME1 | |||
31 | #define _XOPEN_SOURCE | |||
32 | #endif /* HAVE_STRPTIME */ | |||
33 | ||||
34 | #include <time.h> | |||
35 | ||||
36 | #include "eoc-util.h" | |||
37 | ||||
38 | #include <errno(*__errno_location ()).h> | |||
39 | #include <string.h> | |||
40 | #include <glib.h> | |||
41 | #include <glib/gprintf.h> | |||
42 | #include <glib/gstdio.h> | |||
43 | #include <ctk/ctk.h> | |||
44 | #include <gio/gio.h> | |||
45 | #include <glib/gi18n.h> | |||
46 | ||||
47 | void | |||
48 | eoc_util_show_help (const gchar *section, CtkWindow *parent) | |||
49 | { | |||
50 | GError *error = NULL((void*)0); | |||
51 | gchar *uri = NULL((void*)0); | |||
52 | ||||
53 | if (section) | |||
54 | uri = g_strdup_printf ("help:eoc/%s", section); | |||
55 | ||||
56 | ctk_show_uri_on_window (parent, ((uri != NULL((void*)0)) ? uri : "help:eoc"), | |||
57 | ctk_get_current_event_time (), &error); | |||
58 | ||||
59 | g_free (uri); | |||
60 | ||||
61 | if (error) { | |||
62 | CtkWidget *dialog; | |||
63 | ||||
64 | dialog = ctk_message_dialog_new (parent, | |||
65 | 0, | |||
66 | CTK_MESSAGE_ERROR, | |||
67 | CTK_BUTTONS_OK, | |||
68 | _("Could not display help for Eye of CAFE")gettext ("Could not display help for Eye of CAFE")); | |||
69 | ||||
70 | ctk_message_dialog_format_secondary_text (CTK_MESSAGE_DIALOG (dialog)((((CtkMessageDialog*) (void *) g_type_check_instance_cast (( GTypeInstance*) ((dialog)), ((ctk_message_dialog_get_type ()) ))))), | |||
71 | "%s", error->message); | |||
72 | ||||
73 | g_signal_connect_swapped (dialog, "response",g_signal_connect_data ((dialog), ("response"), (((GCallback) ( ctk_widget_destroy))), (dialog), ((void*)0), G_CONNECT_SWAPPED ) | |||
74 | G_CALLBACK (ctk_widget_destroy),g_signal_connect_data ((dialog), ("response"), (((GCallback) ( ctk_widget_destroy))), (dialog), ((void*)0), G_CONNECT_SWAPPED ) | |||
75 | dialog)g_signal_connect_data ((dialog), ("response"), (((GCallback) ( ctk_widget_destroy))), (dialog), ((void*)0), G_CONNECT_SWAPPED ); | |||
76 | ctk_widget_show (dialog); | |||
77 | ||||
78 | g_error_free (error); | |||
79 | } | |||
80 | } | |||
81 | ||||
82 | gchar * | |||
83 | eoc_util_make_valid_utf8 (const gchar *str) | |||
84 | { | |||
85 | GString *string; | |||
86 | const char *remainder, *invalid; | |||
87 | int remaining_bytes, valid_bytes; | |||
88 | ||||
89 | string = NULL((void*)0); | |||
90 | remainder = str; | |||
91 | remaining_bytes = strlen (str); | |||
92 | ||||
93 | while (remaining_bytes != 0) { | |||
94 | if (g_utf8_validate (remainder, remaining_bytes, &invalid)) { | |||
95 | break; | |||
96 | } | |||
97 | ||||
98 | valid_bytes = invalid - remainder; | |||
99 | ||||
100 | if (string == NULL((void*)0)) { | |||
101 | string = g_string_sized_new (remaining_bytes); | |||
102 | } | |||
103 | ||||
104 | g_string_append_len (string, remainder, valid_bytes)g_string_append_len_inline (string, remainder, valid_bytes); | |||
105 | g_string_append_c (string, '?')g_string_append_c_inline (string, '?'); | |||
106 | ||||
107 | remaining_bytes -= valid_bytes + 1; | |||
108 | remainder = invalid + 1; | |||
109 | } | |||
110 | ||||
111 | if (string == NULL((void*)0)) { | |||
112 | return g_strdup (str)g_strdup_inline (str); | |||
113 | } | |||
114 | ||||
115 | g_string_append (string, remainder)(__builtin_constant_p (remainder) ? __extension__ ({ const char * const __val = (remainder); g_string_append_len_inline (string , __val, (__val != ((void*)0)) ? (gssize) strlen (((__val) + ! (__val))) : (gssize) -1); }) : g_string_append_len_inline (string , remainder, (gssize) -1)); | |||
116 | g_string_append (string, _(" (invalid Unicode)"))(__builtin_constant_p (gettext (" (invalid Unicode)")) ? __extension__ ({ const char * const __val = (gettext (" (invalid Unicode)" )); g_string_append_len_inline (string, __val, (__val != ((void *)0)) ? (gssize) strlen (((__val) + !(__val))) : (gssize) -1) ; }) : g_string_append_len_inline (string, gettext (" (invalid Unicode)" ), (gssize) -1)); | |||
117 | ||||
118 | g_assert (g_utf8_validate (string->str, -1, NULL))do { if (g_utf8_validate (string->str, -1, ((void*)0))) ; else g_assertion_message_expr ("EOC", "eoc-util.c", 118, ((const char *) (__func__)), "g_utf8_validate (string->str, -1, NULL)") ; } while (0); | |||
119 | ||||
120 | return g_string_free (string, FALSE)(__builtin_constant_p ((0)) ? (((0)) ? (g_string_free) ((string ), ((0))) : g_string_free_and_steal (string)) : (g_string_free ) ((string), ((0)))); | |||
121 | } | |||
122 | ||||
123 | GSList* | |||
124 | eoc_util_parse_uri_string_list_to_file_list (const gchar *uri_list) | |||
125 | { | |||
126 | GSList* file_list = NULL((void*)0); | |||
127 | gsize i = 0; | |||
128 | gchar **uris; | |||
129 | ||||
130 | uris = g_uri_list_extract_uris (uri_list); | |||
131 | ||||
132 | while (uris[i] != NULL((void*)0)) { | |||
133 | file_list = g_slist_append (file_list, g_file_new_for_uri (uris[i])); | |||
134 | i++; | |||
135 | } | |||
136 | ||||
137 | g_strfreev (uris); | |||
138 | ||||
139 | return file_list; | |||
140 | } | |||
141 | ||||
142 | GSList* | |||
143 | eoc_util_string_list_to_file_list (GSList *string_list) | |||
144 | { | |||
145 | GSList *it = NULL((void*)0); | |||
146 | GSList *file_list = NULL((void*)0); | |||
147 | ||||
148 | for (it = string_list; it != NULL((void*)0); it = it->next) { | |||
149 | char *uri_str; | |||
150 | ||||
151 | uri_str = (gchar *) it->data; | |||
152 | ||||
153 | file_list = g_slist_prepend (file_list, | |||
154 | g_file_new_for_uri (uri_str)); | |||
155 | } | |||
156 | ||||
157 | return g_slist_reverse (file_list); | |||
158 | } | |||
159 | ||||
160 | GSList* | |||
161 | eoc_util_strings_to_file_list (gchar **strings) | |||
162 | { | |||
163 | int i; | |||
164 | GSList *file_list = NULL((void*)0); | |||
165 | ||||
166 | for (i = 0; strings[i]; i++) { | |||
167 | file_list = g_slist_prepend (file_list, | |||
168 | g_file_new_for_uri (strings[i])); | |||
169 | } | |||
170 | ||||
171 | return g_slist_reverse (file_list); | |||
172 | } | |||
173 | ||||
174 | GSList* | |||
175 | eoc_util_string_array_to_list (const gchar **files, gboolean create_uri) | |||
176 | { | |||
177 | gint i; | |||
178 | GSList *list = NULL((void*)0); | |||
179 | ||||
180 | if (files == NULL((void*)0)) return list; | |||
181 | ||||
182 | for (i = 0; files[i]; i++) { | |||
183 | char *str; | |||
184 | ||||
185 | if (create_uri) { | |||
186 | GFile *file; | |||
187 | ||||
188 | file = g_file_new_for_commandline_arg (files[i]); | |||
189 | str = g_file_get_uri (file); | |||
190 | ||||
191 | g_object_unref (file); | |||
192 | } else { | |||
193 | str = g_strdup (files[i])g_strdup_inline (files[i]); | |||
194 | } | |||
195 | ||||
196 | if (str) { | |||
197 | list = g_slist_prepend (list, g_strdup (str)g_strdup_inline (str)); | |||
198 | g_free (str); | |||
199 | } | |||
200 | } | |||
201 | ||||
202 | return g_slist_reverse (list); | |||
203 | } | |||
204 | ||||
205 | gchar ** | |||
206 | eoc_util_string_array_make_absolute (gchar **files) | |||
207 | { | |||
208 | int i; | |||
209 | int size; | |||
210 | gchar **abs_files; | |||
211 | GFile *file; | |||
212 | ||||
213 | if (files == NULL((void*)0)) | |||
214 | return NULL((void*)0); | |||
215 | ||||
216 | size = g_strv_length (files); | |||
217 | ||||
218 | /* Ensure new list is NULL-terminated */ | |||
219 | abs_files = g_new0 (gchar *, size+1)((gchar * *) g_malloc0_n ((size+1), sizeof (gchar *))); | |||
220 | ||||
221 | for (i = 0; i < size; i++) { | |||
222 | file = g_file_new_for_commandline_arg (files[i]); | |||
223 | abs_files[i] = g_file_get_uri (file); | |||
224 | ||||
225 | g_object_unref (file); | |||
226 | } | |||
227 | ||||
228 | return abs_files; | |||
229 | } | |||
230 | ||||
231 | static gchar *dot_dir = NULL((void*)0); | |||
232 | ||||
233 | static gboolean | |||
234 | ensure_dir_exists (const char *dir) | |||
235 | { | |||
236 | if (g_file_test (dir, G_FILE_TEST_IS_DIR)) | |||
237 | return TRUE(!(0)); | |||
238 | ||||
239 | if (g_mkdir_with_parents (dir, 0700) == 0) | |||
240 | return TRUE(!(0)); | |||
241 | ||||
242 | if (errno(*__errno_location ()) == EEXIST17) | |||
243 | return g_file_test (dir, G_FILE_TEST_IS_DIR); | |||
244 | ||||
245 | g_warning ("Failed to create directory %s: %s", dir, strerror (errno(*__errno_location ()))); | |||
246 | return FALSE(0); | |||
247 | } | |||
248 | ||||
249 | const gchar * | |||
250 | eoc_util_dot_dir (void) | |||
251 | { | |||
252 | if (dot_dir == NULL((void*)0)) { | |||
253 | gboolean exists; | |||
254 | ||||
255 | dot_dir = g_build_filename(g_get_user_config_dir(), "cafe", "eoc", NULL((void*)0)); | |||
256 | ||||
257 | exists = ensure_dir_exists (dot_dir); | |||
258 | ||||
259 | if (G_UNLIKELY (!exists)(!exists)) { | |||
260 | static gboolean printed_warning = FALSE(0); | |||
261 | ||||
262 | if (!printed_warning) { | |||
263 | g_warning ("EOC could not save some of your preferences in its settings directory due to a file with the same name (%s) blocking its creation. Please remove that file, or move it away.", dot_dir); | |||
264 | printed_warning = TRUE(!(0)); | |||
265 | } | |||
266 | dot_dir = NULL((void*)0); | |||
267 | return NULL((void*)0); | |||
268 | } | |||
269 | } | |||
270 | ||||
271 | return dot_dir; | |||
272 | } | |||
273 | ||||
274 | /* Based on eel_filename_strip_extension() */ | |||
275 | ||||
276 | /** | |||
277 | * eoc_util_filename_get_extension: | |||
278 | * @filename: a filename | |||
279 | * | |||
280 | * Returns a reasonably good guess of the file extension of @filename. | |||
281 | * | |||
282 | * Returns: a newly allocated string with the file extension of @filename. | |||
283 | **/ | |||
284 | char * | |||
285 | eoc_util_filename_get_extension (const char * filename) | |||
286 | { | |||
287 | char *begin, *begin2; | |||
288 | ||||
289 | if (filename == NULL((void*)0)) { | |||
| ||||
290 | return NULL((void*)0); | |||
291 | } | |||
292 | ||||
293 | begin = strrchr (filename, '.'); | |||
294 | ||||
295 | if (begin && begin != filename) { | |||
296 | if (strcmp (begin, ".gz") == 0 || | |||
297 | strcmp (begin, ".bz2") == 0 || | |||
298 | strcmp (begin, ".sit") == 0 || | |||
299 | strcmp (begin, ".Z") == 0) { | |||
300 | begin2 = begin - 1; | |||
301 | while (begin2 > filename && | |||
302 | *begin2 != '.') { | |||
| ||||
303 | begin2--; | |||
304 | } | |||
305 | if (begin2 != filename) { | |||
306 | begin = begin2; | |||
307 | } | |||
308 | } | |||
309 | begin ++; | |||
310 | } else { | |||
311 | return NULL((void*)0); | |||
312 | } | |||
313 | ||||
314 | return g_strdup (begin)g_strdup_inline (begin); | |||
315 | } | |||
316 | ||||
317 | ||||
318 | /** | |||
319 | * eoc_util_file_is_persistent: | |||
320 | * @file: a #GFile | |||
321 | * | |||
322 | * Checks whether @file is a non-removable local mount. | |||
323 | * | |||
324 | * Returns: %TRUE if @file is in a non-removable mount, | |||
325 | * %FALSE otherwise or when it is remote. | |||
326 | **/ | |||
327 | gboolean | |||
328 | eoc_util_file_is_persistent (GFile *file) | |||
329 | { | |||
330 | GMount *mount; | |||
331 | ||||
332 | if (!g_file_is_native (file)) | |||
333 | return FALSE(0); | |||
334 | ||||
335 | mount = g_file_find_enclosing_mount (file, NULL((void*)0), NULL((void*)0)); | |||
336 | if (mount) { | |||
337 | if (g_mount_can_unmount (mount)) { | |||
338 | return FALSE(0); | |||
339 | } | |||
340 | } | |||
341 | ||||
342 | return TRUE(!(0)); | |||
343 | } | |||
344 | ||||
345 | static void | |||
346 | _eoc_util_show_file_in_filemanager_fallback (GFile *file, CtkWindow *toplevel) | |||
347 | { | |||
348 | gchar *uri = NULL((void*)0); | |||
349 | GError *error = NULL((void*)0); | |||
350 | guint32 timestamp = ctk_get_current_event_time (); | |||
351 | ||||
352 | if (g_file_query_file_type (file, 0, NULL((void*)0)) == G_FILE_TYPE_DIRECTORY) { | |||
353 | uri = g_file_get_uri (file); | |||
354 | } else { | |||
355 | /* If input file is not a directory we must open it's | |||
356 | folder/parent to avoid opening the file itself */ | |||
357 | GFile *parent_file; | |||
358 | ||||
359 | parent_file = g_file_get_parent (file); | |||
360 | if (G_LIKELY (parent_file)(parent_file)) | |||
361 | uri = g_file_get_uri (parent_file); | |||
362 | g_object_unref (parent_file); | |||
363 | } | |||
364 | ||||
365 | if (uri && !ctk_show_uri_on_window (toplevel, uri, timestamp, &error)) { | |||
366 | g_warning ("Couldn't show containing folder \"%s\": %s", uri, | |||
367 | error->message); | |||
368 | g_error_free (error); | |||
369 | } | |||
370 | ||||
371 | g_free (uri); | |||
372 | } | |||
373 | ||||
374 | void | |||
375 | eoc_util_show_file_in_filemanager (GFile *file, CtkWindow *toplevel) | |||
376 | { | |||
377 | GDBusProxy *proxy; | |||
378 | gboolean done = FALSE(0); | |||
379 | ||||
380 | g_return_if_fail (file != NULL)do { if ((file != ((void*)0))) { } else { g_return_if_fail_warning ("EOC", ((const char*) (__func__)), "file != NULL"); return; } } while (0); | |||
381 | ||||
382 | proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, | |||
383 | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS | | |||
384 | G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, | |||
385 | NULL((void*)0), "org.freedesktop.FileManager1", | |||
386 | "/org/freedesktop/FileManager1", | |||
387 | "org.freedesktop.FileManager1", | |||
388 | NULL((void*)0), NULL((void*)0)); | |||
389 | ||||
390 | if (proxy) { | |||
391 | gchar *uri = g_file_get_uri (file); | |||
392 | gchar *startup_id; | |||
393 | GVariant *params, *result; | |||
394 | GVariantBuilder builder; | |||
395 | ||||
396 | g_variant_builder_init (&builder, | |||
397 | G_VARIANT_TYPE ("as")(g_variant_type_checked_ (("as")))); | |||
398 | g_variant_builder_add (&builder, "s", uri); | |||
399 | ||||
400 | /* This seems to be the expected format, as other values | |||
401 | cause the filemanager window not to get focus. */ | |||
402 | startup_id = g_strdup_printf("_TIME%u", | |||
403 | ctk_get_current_event_time()); | |||
404 | ||||
405 | /* params is floating! */ | |||
406 | params = g_variant_new ("(ass)", &builder, startup_id); | |||
407 | ||||
408 | g_free (startup_id); | |||
409 | g_variant_builder_clear (&builder); | |||
410 | ||||
411 | /* Floating params-GVariant is consumed here */ | |||
412 | result = g_dbus_proxy_call_sync (proxy, "ShowItems", | |||
413 | params, G_DBUS_CALL_FLAGS_NONE, | |||
414 | -1, NULL((void*)0), NULL((void*)0)); | |||
415 | ||||
416 | /* Receiving a non-NULL result counts as a successful call. */ | |||
417 | if (G_LIKELY (result != NULL)(result != ((void*)0))) { | |||
418 | done = TRUE(!(0)); | |||
419 | g_variant_unref (result); | |||
420 | } | |||
421 | ||||
422 | g_free (uri); | |||
423 | g_object_unref (proxy); | |||
424 | } | |||
425 | ||||
426 | /* Fallback to ctk_show_uri() if launch over DBus is not possible */ | |||
427 | if (!done) | |||
428 | _eoc_util_show_file_in_filemanager_fallback (file, toplevel); | |||
429 | } |