1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 
3 /*
4  *  GThumb
5  *
6  *  Copyright (C) 2001-2008 Free Software Foundation, Inc.
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 #include <config.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include <glib.h>
28 #include <glib/gi18n.h>
29 #include <glib/gprintf.h>
30 #include <gio/gio.h>
31 #include "glib-utils.h"
32 
33 #define MAX_PATTERNS 128
34 
35 
36 /* gobject utils*/
37 
38 
39 gpointer
_g_object_ref(gpointer object)40 _g_object_ref (gpointer object)
41 {
42 	if (object != NULL)
43 		return g_object_ref (object);
44 	else
45 		return NULL;
46 }
47 
48 
49 void
_g_object_unref(gpointer object)50 _g_object_unref (gpointer object)
51 {
52 	if (object != NULL)
53 		g_object_unref (object);
54 }
55 
56 
57 void
_g_object_clear(gpointer object)58 _g_object_clear (gpointer  object)
59 {
60 	gpointer *object_p = (gpointer *) object;
61 
62 	if ((object_p != NULL) && (*object_p != NULL)) {
63 		g_object_unref (*object_p);
64 		*object_p = NULL;
65 	}
66 }
67 
68 
69 GList *
_g_object_list_ref(GList * list)70 _g_object_list_ref (GList *list)
71 {
72 	GList *new_list;
73 
74 	if (list == NULL)
75 		return NULL;
76 
77 	new_list = g_list_copy (list);
78 	g_list_foreach (new_list, (GFunc) g_object_ref, NULL);
79 
80 	return new_list;
81 }
82 
83 
84 void
_g_object_list_unref(GList * list)85 _g_object_list_unref (GList *list)
86 {
87 	g_list_foreach (list, (GFunc) g_object_unref, NULL);
88 	g_list_free (list);
89 }
90 
91 
92 GType
g_object_list_get_type(void)93 g_object_list_get_type (void)
94 {
95 	static GType type = 0;
96 
97 	if (type == 0)
98 		type = g_boxed_type_register_static ("GObjectList",
99 						     (GBoxedCopyFunc) _g_object_list_ref,
100 						     (GBoxedFreeFunc) _g_object_list_unref);
101 
102 	return type;
103 }
104 
105 
106 GEnumValue *
_g_enum_type_get_value(GType enum_type,int value)107 _g_enum_type_get_value (GType enum_type,
108 			int   value)
109 {
110 	GEnumClass *class;
111 	GEnumValue *enum_value;
112 
113 	class = G_ENUM_CLASS (g_type_class_ref (enum_type));
114 	enum_value = g_enum_get_value (class, value);
115 	g_type_class_unref (class);
116 
117 	return enum_value;
118 }
119 
120 
121 GEnumValue *
_g_enum_type_get_value_by_nick(GType enum_type,const char * nick)122 _g_enum_type_get_value_by_nick (GType       enum_type,
123 				const char *nick)
124 {
125 	GEnumClass *class;
126 	GEnumValue *enum_value;
127 
128 	class = G_ENUM_CLASS (g_type_class_ref (enum_type));
129 	enum_value = g_enum_get_value_by_nick (class, nick);
130 	g_type_class_unref (class);
131 
132 	return enum_value;
133 }
134 
135 
136 /* idle callback */
137 
138 
139 IdleCall*
idle_call_new(DataFunc func,gpointer data)140 idle_call_new (DataFunc func,
141 	       gpointer data)
142 {
143 	IdleCall *call = g_new0 (IdleCall, 1);
144 	call->func = func;
145 	call->data = data;
146 	return call;
147 }
148 
149 
150 void
idle_call_free(IdleCall * call)151 idle_call_free (IdleCall *call)
152 {
153 	g_free (call);
154 }
155 
156 
157 static gboolean
idle_call_exec_cb(gpointer data)158 idle_call_exec_cb (gpointer data)
159 {
160 	IdleCall *call = data;
161 	(*call->func) (call->data);
162 	return FALSE;
163 }
164 
165 
166 guint
idle_call_exec(IdleCall * call,gboolean use_idle_cb)167 idle_call_exec (IdleCall *call,
168 		gboolean  use_idle_cb)
169 {
170 	if (use_idle_cb)
171 		return g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
172 					idle_call_exec_cb,
173 					call,
174 					(GDestroyNotify) idle_call_free);
175 	else {
176 		(*call->func) (call->data);
177 		idle_call_free (call);
178 		return 0;
179 	}
180 }
181 
182 
183 guint
call_when_idle(DataFunc func,gpointer data)184 call_when_idle (DataFunc  func,
185 		gpointer  data)
186 {
187 	return idle_call_exec (idle_call_new (func, data), TRUE);
188 }
189 
190 
191 typedef struct {
192 	gpointer       object;
193 	ReadyCallback  ready_func;
194 	gpointer       user_data;
195 	GError        *error;
196 	guint          id;
197 } ObjectReadyData;
198 
199 
200 static gboolean
exec_object_ready_func(gpointer user_data)201 exec_object_ready_func (gpointer user_data)
202 {
203 	ObjectReadyData *data = user_data;
204 
205 	g_source_remove (data->id);
206 	data->ready_func (G_OBJECT (data->object), data->error, data->user_data);
207 	g_free (data);
208 
209 	return FALSE;
210 }
211 
212 
213 void
object_ready_with_error(gpointer object,ReadyCallback ready_func,gpointer user_data,GError * error)214 object_ready_with_error (gpointer       object,
215 			 ReadyCallback  ready_func,
216 			 gpointer       user_data,
217 			 GError        *error)
218 {
219 	ObjectReadyData *data;
220 
221 	data = g_new0 (ObjectReadyData, 1);
222 
223 	data->object = object;
224 	data->ready_func = ready_func;
225 	data->user_data = user_data;
226 	data->error = error;
227 	data->id = g_idle_add (exec_object_ready_func, data);
228 }
229 
230 
231 typedef struct {
232 	ReadyFunc  ready_func;
233 	gpointer   user_data;
234 	GError    *error;
235 	guint      id;
236 } ReadyData;
237 
238 
239 static gboolean
exec_ready_func(gpointer user_data)240 exec_ready_func (gpointer user_data)
241 {
242 	ReadyData *data = user_data;
243 
244 	g_source_remove (data->id);
245 	data->ready_func (data->error, data->user_data);
246 	g_free (data);
247 
248 	return FALSE;
249 }
250 
251 
252 void
ready_with_error(ReadyFunc ready_func,gpointer user_data,GError * error)253 ready_with_error (ReadyFunc  ready_func,
254 		  gpointer   user_data,
255 		  GError    *error)
256 {
257 	ReadyData *data;
258 
259 	data = g_new0 (ReadyData, 1);
260 	data->ready_func = ready_func;
261 	data->user_data = user_data;
262 	data->error = error;
263 	data->id = g_idle_add (exec_ready_func, data);
264 }
265 
266 
267 /* debug */
268 
269 
270 void
debug(const char * file,int line,const char * function,const char * format,...)271 debug (const char *file,
272        int         line,
273        const char *function,
274        const char *format,
275        ...)
276 {
277 #ifdef DEBUG
278 	static   gboolean first_time = 0;
279 	static   gboolean print_debug_info = 0;
280 	va_list  args;
281 	char    *str;
282 
283 	if (! first_time) {
284 		first_time = 1;
285 		if (g_getenv ("GOOBOX_DEBUG"))
286 			print_debug_info = 1;
287 	}
288 
289 	if (! print_debug_info)
290 		return;
291 
292 	g_return_if_fail (format != NULL);
293 
294 	va_start (args, format);
295 	str = g_strdup_vprintf (format, args);
296 	va_end (args);
297 
298 	g_fprintf (stderr, "[%s] %s:%d (%s):\n\t%s\n", g_get_prgname(), file, line, function, str);
299 
300 	g_free (str);
301 #endif
302 }
303 
304 
305 void
performance(const char * file,int line,const char * function,const char * format,...)306 performance (const char *file,
307 	     int         line,
308 	     const char *function,
309 	     const char *format,
310 	     ...)
311 {
312 #ifdef DEBUG
313 	va_list args;
314 	char *formatted, *str, *filename;
315 
316 	filename = g_path_get_basename (file);
317 
318 	va_start (args, format);
319 	formatted = g_strdup_vprintf (format, args);
320 	va_end (args);
321 
322 	str = g_strdup_printf ("MARK: %s: (%s:%d) [%s] : %s", g_get_prgname(), filename, line, function, formatted);
323 	g_free (formatted);
324 
325 	access (str, F_OK);
326 	g_free (str);
327 	g_free (filename);
328 #endif
329 }
330 
331 
332 /* GTimeVal utils */
333 
334 
335 int
_g_time_val_cmp(GTimeVal * a,GTimeVal * b)336 _g_time_val_cmp (GTimeVal *a,
337 		 GTimeVal *b)
338 {
339 	if (a->tv_sec == b->tv_sec) {
340 		if (a->tv_usec == b->tv_usec)
341 			return 0;
342 		else
343 			return a->tv_usec > b->tv_usec ? 1 : -1;
344 	}
345 	else if (a->tv_sec > b->tv_sec)
346 		return 1;
347 	else
348 		return -1;
349 }
350 
351 
352 void
_g_time_val_reset(GTimeVal * time_)353 _g_time_val_reset (GTimeVal *time_)
354 {
355 	time_->tv_sec = 0;
356 	time_->tv_usec = 0;
357 }
358 
359 
360 gboolean
_g_time_val_from_exif_date(const char * exif_date,GTimeVal * time_)361 _g_time_val_from_exif_date (const char *exif_date,
362 			    GTimeVal   *time_)
363 {
364 	struct tm tm;
365 	long   val;
366 
367 	g_return_val_if_fail (time_ != NULL, FALSE);
368 
369 	if (exif_date == NULL)
370 		return FALSE;
371 
372 	while (g_ascii_isspace (*exif_date))
373 		exif_date++;
374 
375 	if (*exif_date == '\0')
376 		return FALSE;
377 
378 	if (! g_ascii_isdigit (*exif_date))
379 		return FALSE;
380 
381 	/* YYYY */
382 
383 	val = g_ascii_strtoull (exif_date, (char **)&exif_date, 10);
384 	tm.tm_year = val - 1900;
385 
386 	if (*exif_date != ':')
387 		return FALSE;
388 
389 	/* MM */
390 
391 	exif_date++;
392 	tm.tm_mon = g_ascii_strtoull (exif_date, (char **)&exif_date, 10) - 1;
393 
394 	if (*exif_date != ':')
395 		return FALSE;
396 
397 	/* DD */
398 
399 	exif_date++;
400 	tm.tm_mday = g_ascii_strtoull (exif_date, (char **)&exif_date, 10);
401 
402   	if (*exif_date != ' ')
403 		return FALSE;
404 
405   	/* hh */
406 
407   	val = g_ascii_strtoull (exif_date, (char **)&exif_date, 10);
408   	tm.tm_hour = val;
409 
410   	if (*exif_date != ':')
411 		return FALSE;
412 
413   	/* mm */
414 
415 	exif_date++;
416 	tm.tm_min = g_ascii_strtoull (exif_date, (char **)&exif_date, 10);
417 
418 	if (*exif_date != ':')
419 		return FALSE;
420 
421       	/* ss */
422 
423 	exif_date++;
424 	tm.tm_sec = strtoul (exif_date, (char **)&exif_date, 10);
425 
426 	time_->tv_sec = mktime (&tm);
427 	time_->tv_usec = 0;
428 
429 	/* usec */
430 
431 	if ((*exif_date == ',') || (*exif_date == '.')) {
432 		glong mul = 100000;
433 
434 		while (g_ascii_isdigit (*++exif_date)) {
435 			time_->tv_usec += (*exif_date - '0') * mul;
436 			mul /= 10;
437 		}
438 	}
439 
440 	while (g_ascii_isspace (*exif_date))
441 		exif_date++;
442 
443 	return *exif_date == '\0';
444 }
445 
446 
447 char *
_g_time_val_to_exif_date(GTimeVal * time_)448 _g_time_val_to_exif_date (GTimeVal *time_)
449 {
450 	char      *retval;
451 	struct tm *tm;
452 	time_t     secs;
453 
454 	g_return_val_if_fail (time_->tv_usec >= 0 && time_->tv_usec < G_USEC_PER_SEC, NULL);
455 
456 	secs = time_->tv_sec;
457 	tm = localtime (&secs);
458 
459 	retval = g_strdup_printf ("%4d:%02d:%02d %02d:%02d:%02d",
460 				  tm->tm_year + 1900,
461 				  tm->tm_mon + 1,
462 				  tm->tm_mday,
463 				  tm->tm_hour,
464 				  tm->tm_min,
465 				  tm->tm_sec);
466 
467 	return retval;
468 }
469 
470 
471 /* Bookmark file utils */
472 
473 
474 void
_g_bookmark_file_clear(GBookmarkFile * bookmark)475 _g_bookmark_file_clear (GBookmarkFile *bookmark)
476 {
477 	char **uris;
478 	int    i;
479 
480 	uris = g_bookmark_file_get_uris (bookmark, NULL);
481 	for (i = 0; uris[i] != NULL; i++)
482 		g_bookmark_file_remove_item (bookmark, uris[i], NULL);
483 	g_strfreev (uris);
484 }
485 
486 
487 void
_g_bookmark_file_add_uri(GBookmarkFile * bookmark,const char * uri)488 _g_bookmark_file_add_uri (GBookmarkFile *bookmark,
489 			  const char    *uri)
490 {
491 	g_bookmark_file_set_is_private (bookmark, uri, TRUE);
492 	g_bookmark_file_add_application (bookmark, uri, NULL, NULL);
493 }
494 
495 
496 void
_g_bookmark_file_set_uris(GBookmarkFile * bookmark,GList * uri_list)497 _g_bookmark_file_set_uris (GBookmarkFile *bookmark,
498 			   GList         *uri_list)
499 {
500 	GList *scan;
501 
502 	_g_bookmark_file_clear (bookmark);
503 	for (scan = uri_list; scan; scan = scan->next)
504 		_g_bookmark_file_add_uri (bookmark, scan->data);
505 }
506 
507 
508 /* String utils */
509 
510 
511 void
_g_strset(char ** s,const char * value)512 _g_strset (char       **s,
513 	   const char  *value)
514 {
515 	if (*s == value)
516 		return;
517 
518 	if (*s != NULL) {
519 		g_free (*s);
520 		*s = NULL;
521 	}
522 
523 	if (value != NULL)
524 		*s = g_strdup (value);
525 }
526 
527 
528 char *
_g_strdup_with_max_size(const char * s,int max_size)529 _g_strdup_with_max_size (const char *s,
530 			 int         max_size)
531 {
532 	char *result;
533 	int   l = strlen (s);
534 
535 	if (l > max_size) {
536 		char *first_half;
537 		char *second_half;
538 		int   offset;
539 		int   half_max_size = max_size / 2 + 1;
540 
541 		first_half = g_strndup (s, half_max_size);
542 		offset = half_max_size + l - max_size;
543 		second_half = g_strndup (s + offset, half_max_size);
544 
545 		result = g_strconcat (first_half, "...", second_half, NULL);
546 
547 		g_free (first_half);
548 		g_free (second_half);
549 	} else
550 		result = g_strdup (s);
551 
552 	return result;
553 }
554 
555 
556 /**
557  * example 1 : "xxx##yy#" --> [0] = xxx
558  *                            [1] = ##
559  *                            [2] = yy
560  *                            [3] = #
561  *                            [4] = NULL
562  *
563  * example 2 : ""         --> [0] = NULL
564  **/
565 char **
_g_get_template_from_text(const char * utf8_template)566 _g_get_template_from_text (const char *utf8_template)
567 {
568 	const char  *chunk_start = utf8_template;
569 	char       **str_vect;
570 	GList       *str_list = NULL, *scan;
571 	int          n = 0;
572 
573 	if (utf8_template == NULL)
574 		return NULL;
575 
576 	while (*chunk_start != 0) {
577 		gunichar    ch;
578 		gboolean    reading_sharps;
579 		char       *chunk;
580 		const char *chunk_end;
581 		int         chunk_len = 0;
582 
583 		reading_sharps = (g_utf8_get_char (chunk_start) == '#');
584 		chunk_end = chunk_start;
585 
586 		ch = g_utf8_get_char (chunk_end);
587 		while (reading_sharps
588 		       && (*chunk_end != 0)
589 		       && (ch == '#')) {
590 			chunk_end = g_utf8_next_char (chunk_end);
591 			ch = g_utf8_get_char (chunk_end);
592 			chunk_len++;
593 		}
594 
595 		ch = g_utf8_get_char (chunk_end);
596 		while (! reading_sharps
597 		       && (*chunk_end != 0)
598 		       && (*chunk_end != '#')) {
599 			chunk_end = g_utf8_next_char (chunk_end);
600 			ch = g_utf8_get_char (chunk_end);
601 			chunk_len++;
602 		}
603 
604 		chunk = _g_utf8_strndup (chunk_start, chunk_len);
605 		str_list = g_list_prepend (str_list, chunk);
606 		n++;
607 
608 		chunk_start = chunk_end;
609 	}
610 
611 	str_vect = g_new (char*, n + 1);
612 
613 	str_vect[n--] = NULL;
614 	for (scan = str_list; scan; scan = scan->next)
615 		str_vect[n--] = scan->data;
616 
617 	g_list_free (str_list);
618 
619 	return str_vect;
620 }
621 
622 
623 char *
_g_get_name_from_template(char ** utf8_template,int n)624 _g_get_name_from_template (char **utf8_template,
625 			   int    n)
626 {
627 	GString *s;
628 	int      i;
629 	char    *result;
630 
631 	s = g_string_new (NULL);
632 
633 	for (i = 0; utf8_template[i] != NULL; i++) {
634 		const char *chunk = utf8_template[i];
635 		gunichar    ch = g_utf8_get_char (chunk);
636 
637 		if (ch != '#')
638 			g_string_append (s, chunk);
639 		else {
640 			char *s_n;
641 			int   s_n_len;
642 			int   sharps_len = g_utf8_strlen (chunk, -1);
643 
644 			s_n = g_strdup_printf ("%d", n);
645 			s_n_len = strlen (s_n);
646 
647 			while (s_n_len < sharps_len) {
648 				g_string_append_c (s, '0');
649 				sharps_len--;
650 			}
651 
652 			g_string_append (s, s_n);
653 			g_free (s_n);
654 		}
655 	}
656 
657 	result = s->str;
658 	g_string_free (s, FALSE);
659 
660 	return result;
661 }
662 
663 
664 char *
_g_replace(const char * str,const char * from_str,const char * to_str)665 _g_replace (const char *str,
666 	    const char *from_str,
667 	    const char *to_str)
668 {
669 	char    **tokens;
670 	int       i;
671 	GString  *gstr;
672 
673 	if (str == NULL)
674 		return NULL;
675 
676 	if (from_str == NULL)
677 		return g_strdup (str);
678 
679 	if (strcmp (str, from_str) == 0)
680 		return g_strdup (to_str);
681 
682 	tokens = g_strsplit (str, from_str, -1);
683 
684 	gstr = g_string_new (NULL);
685 	for (i = 0; tokens[i] != NULL; i++) {
686 		g_string_append (gstr, tokens[i]);
687 		if ((to_str != NULL) && (tokens[i+1] != NULL))
688 			g_string_append (gstr, to_str);
689 	}
690 
691 	g_strfreev (tokens);
692 
693 	return g_string_free (gstr, FALSE);
694 }
695 
696 
697 char *
_g_replace_pattern(const char * utf8_text,gunichar pattern,const char * value)698 _g_replace_pattern (const char *utf8_text,
699 		    gunichar    pattern,
700 		    const char *value)
701 {
702 	const char *s;
703 	GString    *r;
704 	char       *r_str;
705 
706 	if (utf8_text == NULL)
707 		return NULL;
708 
709 	if (g_utf8_strchr (utf8_text, -1, '%') == NULL)
710 		return g_strdup (utf8_text);
711 
712 	r = g_string_new (NULL);
713 	for (s = utf8_text; *s != 0; s = g_utf8_next_char (s)) {
714 		gunichar ch = g_utf8_get_char (s);
715 
716 		if (ch == '%') {
717 			s = g_utf8_next_char (s);
718 
719 			if (*s == 0) {
720 				g_string_append_unichar (r, ch);
721 				break;
722 			}
723 
724 			ch = g_utf8_get_char (s);
725 			if (ch == pattern) {
726 				if (value)
727 					g_string_append (r, value);
728 			}
729 			else {
730 				g_string_append (r, "%");
731 				g_string_append_unichar (r, ch);
732 			}
733 
734 		} else
735 			g_string_append_unichar (r, ch);
736 	}
737 
738 	r_str = r->str;
739 	g_string_free (r, FALSE);
740 
741 	return r_str;
742 }
743 
744 
745 char *
_g_utf8_replace(const char * string,const char * pattern,const char * replacement)746 _g_utf8_replace (const char  *string,
747 		 const char  *pattern,
748 		 const char  *replacement)
749 {
750 	GRegex *regex;
751 	char   *result;
752 
753 	if (string == NULL)
754 		return NULL;
755 
756 	regex = g_regex_new (pattern, 0, 0, NULL);
757 	if (regex == NULL)
758 		return NULL;
759 
760 	result = g_regex_replace_literal (regex, string, -1, 0, replacement, 0, NULL);
761 
762 	g_regex_unref (regex);
763 
764 	return result;
765 }
766 
767 
768 char *
_g_utf8_strndup(const char * str,gsize n)769 _g_utf8_strndup (const char *str,
770 		 gsize       n)
771 {
772 	const char *s = str;
773 	char       *result;
774 
775 	while (n && *s) {
776 		s = g_utf8_next_char (s);
777 		n--;
778 	}
779 
780 	result = g_strndup (str, s - str);
781 
782 	return result;
783 }
784 
785 
786 static const char *
_g_utf8_strstr(const char * haystack,const char * needle)787 _g_utf8_strstr (const char *haystack,
788 		const char *needle)
789 {
790 	const char *s;
791 	gsize       i;
792 	gsize       haystack_len = g_utf8_strlen (haystack, -1);
793 	gsize       needle_len = g_utf8_strlen (needle, -1);
794 	int         needle_size = strlen (needle);
795 
796 	s = haystack;
797 	for (i = 0; i <= haystack_len - needle_len; i++) {
798 		if (strncmp (s, needle, needle_size) == 0)
799 			return s;
800 		s = g_utf8_next_char(s);
801 	}
802 
803 	return NULL;
804 }
805 
806 
807 char **
_g_utf8_strsplit(const char * string,const char * delimiter,int max_tokens)808 _g_utf8_strsplit (const char *string,
809 		  const char *delimiter,
810 		  int         max_tokens)
811 {
812 	GSList      *string_list = NULL, *slist;
813 	char       **str_array;
814 	const char  *s;
815 	guint        n = 0;
816 	const char  *remainder;
817 
818 	g_return_val_if_fail (string != NULL, NULL);
819 	g_return_val_if_fail (delimiter != NULL, NULL);
820 	g_return_val_if_fail (delimiter[0] != '\0', NULL);
821 
822 	if (max_tokens < 1)
823 		max_tokens = G_MAXINT;
824 
825 	remainder = string;
826 	s = _g_utf8_strstr (remainder, delimiter);
827 	if (s != NULL) {
828 		gsize delimiter_size = strlen (delimiter);
829 
830 		while (--max_tokens && (s != NULL)) {
831 			gsize  size = s - remainder;
832 			char  *new_string;
833 
834 			new_string = g_new (char, size + 1);
835 			strncpy (new_string, remainder, size);
836 			new_string[size] = 0;
837 
838 			string_list = g_slist_prepend (string_list, new_string);
839 			n++;
840 			remainder = s + delimiter_size;
841 			s = _g_utf8_strstr (remainder, delimiter);
842 		}
843 	}
844 	if (*string) {
845 		n++;
846 		string_list = g_slist_prepend (string_list, g_strdup (remainder));
847 	}
848 
849 	str_array = g_new (char*, n + 1);
850 
851 	str_array[n--] = NULL;
852 	for (slist = string_list; slist; slist = slist->next)
853 		str_array[n--] = slist->data;
854 
855 	g_slist_free (string_list);
856 
857 	return str_array;
858 }
859 
860 
861 char *
_g_utf8_strstrip(const char * str)862 _g_utf8_strstrip (const char *str)
863 {
864 	if (str == NULL)
865 		return NULL;
866 	return g_strstrip (g_strdup (str));
867 }
868 
869 
870 gboolean
_g_utf8_all_spaces(const char * utf8_string)871 _g_utf8_all_spaces (const char *utf8_string)
872 {
873 	gunichar c;
874 
875 	if (utf8_string == NULL)
876 		return TRUE;
877 
878 	c = g_utf8_get_char (utf8_string);
879 	while (c != 0) {
880 		if (! g_unichar_isspace (c))
881 			return FALSE;
882 		utf8_string = g_utf8_next_char (utf8_string);
883 		c = g_utf8_get_char (utf8_string);
884 	}
885 
886 	return TRUE;
887 }
888 
889 
890 char *
_g_utf8_remove_extension(const char * str)891 _g_utf8_remove_extension (const char *str)
892 {
893 	char *p;
894 	char *ext;
895 	char *dest;
896 
897 	if ((str == NULL) || ! g_utf8_validate (str, -1, NULL))
898 		return NULL;
899 
900 	p = (char *) str;
901 	ext = g_utf8_strrchr (p, -1, g_utf8_get_char ("."));
902 	dest = g_strdup (p);
903 	g_utf8_strncpy (dest, p, g_utf8_strlen (p, -1) - g_utf8_strlen (ext, -1));
904 
905 	return dest;
906 }
907 
908 
909 GList *
_g_list_insert_list_before(GList * list1,GList * sibling,GList * list2)910 _g_list_insert_list_before (GList *list1,
911 			    GList *sibling,
912 			    GList *list2)
913 {
914   if (!list2)
915     {
916       return list1;
917     }
918   else if (!list1)
919     {
920       return list2;
921     }
922   else if (sibling)
923     {
924       GList *list2_last = g_list_last (list2);
925       if (sibling->prev)
926 	{
927 	  sibling->prev->next = list2;
928 	  list2->prev = sibling->prev;
929 	  sibling->prev = list2_last;
930 	  list2_last->next = sibling;
931 	  return list1;
932 	}
933       else
934 	{
935 	  sibling->prev = list2_last;
936 	  list2_last->next = sibling;
937 	  return list2;
938 	}
939     }
940   else
941     {
942       return g_list_concat (list1, list2);
943     }
944 }
945 
946 
947 GHashTable *static_strings = NULL;
948 
949 
950 const char *
get_static_string(const char * s)951 get_static_string (const char *s)
952 {
953 	static GMutex  static_strings_mutex;
954 	const char    *result;
955 
956 	if (s == NULL)
957 		return NULL;
958 
959 	g_mutex_lock (&static_strings_mutex);
960 
961 	if (static_strings == NULL)
962 		static_strings = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
963 
964 	if (! g_hash_table_lookup_extended (static_strings, s, (gpointer) &result, NULL)) {
965 		result = g_strdup (s);
966 		g_hash_table_insert (static_strings,
967 				     (gpointer) result,
968 				     GINT_TO_POINTER (1));
969 	}
970 
971 	g_mutex_unlock (&static_strings_mutex);
972 
973 	return result;
974 }
975 
976 
977 char *
_g_rand_string(int len)978 _g_rand_string (int len)
979 {
980 	static char *alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
981 	static int   letters_only = 52;
982 	static int   whole_alphabet = 62;
983 	char        *s;
984 	GRand       *rand_gen;
985 	int          i;
986 
987 	s = g_malloc (sizeof (char) * (len + 1));
988 	rand_gen = g_rand_new ();
989 	for (i = 0; i < len; i++)
990 		s[i] = alphabet[g_rand_int_range (rand_gen, 0, (i == 0) ? letters_only : whole_alphabet)];
991 	g_rand_free (rand_gen);
992 	s[len] = 0;
993 
994 	return s;
995 }
996 
997 
998 int
_g_strv_find(char ** v,const char * s)999 _g_strv_find (char       **v,
1000 	      const char  *s)
1001 {
1002 	int i;
1003 
1004 	for (i = 0; v[i] != NULL; i++) {
1005 		if (strcmp (v[i], s) == 0)
1006 			return i;
1007 	}
1008 
1009 	return -1;
1010 }
1011 
1012 
1013 char *
_g_str_remove_suffix(const char * s,const char * suffix)1014 _g_str_remove_suffix (const char *s,
1015 		      const char *suffix)
1016 {
1017 	int s_len;
1018 	int suffix_len;
1019 
1020 	if (s == NULL)
1021 		return NULL;
1022 	if (suffix == NULL)
1023 		return g_strdup (s);
1024 
1025 	s_len = strlen (s);
1026 	suffix_len = strlen (suffix);
1027 
1028 	if (suffix_len >= s_len)
1029 		return g_strdup ("");
1030 	else
1031 		return g_strndup (s, s_len - suffix_len);
1032 }
1033 
1034 
1035 /* Regexp utils */
1036 
1037 static char **
get_patterns_from_pattern(const char * pattern_string)1038 get_patterns_from_pattern (const char *pattern_string)
1039 {
1040 	char **patterns;
1041 	int    i;
1042 
1043 	if (pattern_string == NULL)
1044 		return NULL;
1045 
1046 	patterns = _g_utf8_strsplit (pattern_string, ";", MAX_PATTERNS);
1047 	for (i = 0; patterns[i] != NULL; i++) {
1048 		char *p1, *p2;
1049 
1050 		p1 = _g_utf8_strstrip (patterns[i]);
1051 		p2 = _g_replace (p1, ".", "\\.");
1052 		patterns[i] = _g_replace (p2, "*", ".*");
1053 
1054 		g_free (p2);
1055 		g_free (p1);
1056 	}
1057 
1058 	return patterns;
1059 }
1060 
1061 
1062 GRegex **
get_regexps_from_pattern(const char * pattern_string,GRegexCompileFlags compile_options)1063 get_regexps_from_pattern (const char         *pattern_string,
1064 			  GRegexCompileFlags  compile_options)
1065 {
1066 	char   **patterns;
1067 	GRegex **regexps;
1068 	int      i;
1069 
1070 	patterns = get_patterns_from_pattern (pattern_string);
1071 	if (patterns == NULL)
1072 		return NULL;
1073 
1074 	regexps = g_new0 (GRegex*, g_strv_length (patterns) + 1);
1075 	for (i = 0; patterns[i] != NULL; i++)
1076 		regexps[i] = g_regex_new (patterns[i],
1077 					  G_REGEX_OPTIMIZE | compile_options,
1078 					  G_REGEX_MATCH_NOTEMPTY,
1079 					  NULL);
1080 	g_strfreev (patterns);
1081 
1082 	return regexps;
1083 }
1084 
1085 
1086 gboolean
string_matches_regexps(GRegex ** regexps,const char * string,GRegexMatchFlags match_options)1087 string_matches_regexps (GRegex           **regexps,
1088 			const char        *string,
1089 			GRegexMatchFlags   match_options)
1090 {
1091 	gboolean matched;
1092 	int      i;
1093 
1094 	if ((regexps == NULL) || (regexps[0] == NULL))
1095 		return TRUE;
1096 
1097 	if (string == NULL)
1098 		return FALSE;
1099 
1100 	matched = FALSE;
1101 	for (i = 0; regexps[i] != NULL; i++)
1102 		if (g_regex_match (regexps[i], string, match_options, NULL)) {
1103 			matched = TRUE;
1104 			break;
1105 	}
1106 
1107 	return matched;
1108 }
1109 
1110 
1111 void
free_regexps(GRegex ** regexps)1112 free_regexps (GRegex **regexps)
1113 {
1114 	int i;
1115 
1116 	if (regexps == NULL)
1117 		return;
1118 
1119 	for (i = 0; regexps[i] != NULL; i++)
1120 		g_regex_unref (regexps[i]);
1121 	g_free (regexps);
1122 }
1123 
1124 
1125 /* URI utils  */
1126 
1127 
1128 const char *
get_home_uri(void)1129 get_home_uri (void)
1130 {
1131 	static char *home_uri = NULL;
1132 
1133 	if (home_uri == NULL) {
1134 		const char *path;
1135 		char       *uri;
1136 
1137 		path = g_get_home_dir ();
1138 		uri = g_uri_escape_string (path, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH, TRUE);
1139 
1140 		home_uri = g_strconcat ("file://", uri, NULL);
1141 
1142 		g_free (uri);
1143 	}
1144 
1145 	return home_uri;
1146 }
1147 
1148 
1149 const char *
get_desktop_uri(void)1150 get_desktop_uri (void)
1151 {
1152 	static char *desktop_uri = NULL;
1153 
1154 	if (desktop_uri == NULL) {
1155 		const char *path;
1156 
1157 		path = g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP);
1158 		desktop_uri = g_filename_to_uri (path, NULL, NULL);
1159 	}
1160 
1161 	return desktop_uri;
1162 }
1163 
1164 
1165 int
uricmp(const char * uri1,const char * uri2)1166 uricmp (const char *uri1,
1167 	const char *uri2)
1168 {
1169 	if (uri1 == NULL) {
1170 		if (uri2 == NULL)
1171 			return 0;
1172 		else
1173 			return -1;
1174 	}
1175 
1176 	if (uri2 == NULL) {
1177 		if (uri1 == NULL)
1178 			return 0;
1179 		else
1180 			return 1;
1181 	}
1182 
1183 	return g_strcmp0 (uri1, uri2);
1184 }
1185 
1186 
1187 gboolean
same_uri(const char * uri1,const char * uri2)1188 same_uri (const char *uri1,
1189 	  const char *uri2)
1190 {
1191 	return uricmp (uri1, uri2) == 0;
1192 }
1193 
1194 
1195 void
_g_string_list_free(GList * string_list)1196 _g_string_list_free (GList *string_list)
1197 {
1198 	if (string_list == NULL)
1199 		return;
1200 	g_list_foreach (string_list, (GFunc) g_free, NULL);
1201 	g_list_free (string_list);
1202 
1203 }
1204 
1205 
1206 GList *
_g_string_list_dup(GList * string_list)1207 _g_string_list_dup (GList *string_list)
1208 {
1209 	GList *new_list = NULL;
1210 	GList *scan;
1211 
1212 	for (scan = string_list; scan; scan = scan->next)
1213 		new_list = g_list_prepend (new_list, g_strdup (scan->data));
1214 
1215 	return g_list_reverse (new_list);
1216 }
1217 
1218 
1219 GType
g_string_list_get_type(void)1220 g_string_list_get_type (void)
1221 {
1222 	static GType type = 0;
1223 
1224 	if (type == 0)
1225 		type = g_boxed_type_register_static ("GStringList",
1226 						     (GBoxedCopyFunc) _g_string_list_dup,
1227 						     (GBoxedFreeFunc) _g_string_list_free);
1228 
1229 	return type;
1230 }
1231 
1232 
1233 GList *
get_file_list_from_url_list(char * url_list)1234 get_file_list_from_url_list (char *url_list)
1235 {
1236 	GList *list = NULL;
1237 	int    i;
1238 	char  *url_start, *url_end;
1239 
1240 	url_start = url_list;
1241 	while (url_start[0] != '\0') {
1242 		char *url;
1243 
1244 		if (strncmp (url_start, "file:", 5) == 0) {
1245 			url_start += 5;
1246 			if ((url_start[0] == '/')
1247 			    && (url_start[1] == '/')) url_start += 2;
1248 		}
1249 
1250 		i = 0;
1251 		while ((url_start[i] != '\0')
1252 		       && (url_start[i] != '\r')
1253 		       && (url_start[i] != '\n')) i++;
1254 		url_end = url_start + i;
1255 
1256 		url = g_strndup (url_start, url_end - url_start);
1257 		list = g_list_prepend (list, url);
1258 
1259 		url_start = url_end;
1260 		i = 0;
1261 		while ((url_start[i] != '\0')
1262 		       && ((url_start[i] == '\r')
1263 			   || (url_start[i] == '\n'))) i++;
1264 		url_start += i;
1265 	}
1266 
1267 	return g_list_reverse (list);
1268 }
1269 
1270 
1271 const char *
_g_uri_get_basename(const char * uri)1272 _g_uri_get_basename (const char *uri)
1273 {
1274 	register char   *base;
1275 	register gssize  last_char;
1276 
1277 	if (uri == NULL)
1278 		return NULL;
1279 
1280 	if (uri[0] == '\0')
1281 		return "";
1282 
1283 	last_char = strlen (uri) - 1;
1284 
1285 	if (uri[last_char] == G_DIR_SEPARATOR)
1286 		return "";
1287 
1288 	base = g_utf8_strrchr (uri, -1, G_DIR_SEPARATOR);
1289 	if (! base)
1290 		return uri;
1291 
1292 	return base + 1;
1293 }
1294 
1295 
1296 const char *
_g_uri_get_file_extension(const char * uri)1297 _g_uri_get_file_extension (const char *uri)
1298 {
1299 	int         len;
1300 	int         p;
1301 	const char *ptr = uri;
1302 
1303 	if (uri == NULL)
1304 		return NULL;
1305 
1306 	len = strlen (uri);
1307 	if (len <= 1)
1308 		return NULL;
1309 
1310 	p = len - 1;
1311 	while ((p >= 0) && (ptr[p] != '.'))
1312 		p--;
1313 
1314 	if (p < 0)
1315 		return NULL;
1316 
1317 	return uri + p;
1318 }
1319 
1320 
1321 static gboolean
uri_is_filetype(const char * uri,GFileType file_type)1322 uri_is_filetype (const char *uri,
1323 		 GFileType   file_type)
1324 {
1325 	gboolean   result = FALSE;
1326 	GFile     *file;
1327 	GFileInfo *info;
1328 	GError    *error = NULL;
1329 
1330 	file = g_file_new_for_uri (uri);
1331 
1332 	if (! g_file_query_exists (file, NULL)) {
1333 		g_object_unref (file);
1334 		return FALSE;
1335 	}
1336 
1337 	info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_TYPE, 0, NULL, &error);
1338 	if (error == NULL) {
1339 		result = (g_file_info_get_file_type (info) == file_type);
1340 	}
1341 	else {
1342 		g_warning ("Failed to get file type for uri %s: %s", uri, error->message);
1343 		g_error_free (error);
1344 	}
1345 
1346 	g_object_unref (info);
1347 	g_object_unref (file);
1348 
1349 	return result;
1350 }
1351 
1352 
1353 gboolean
_g_uri_is_file(const char * uri)1354 _g_uri_is_file (const char *uri)
1355 {
1356 	return uri_is_filetype (uri, G_FILE_TYPE_REGULAR);
1357 }
1358 
1359 
1360 gboolean
_g_uri_is_dir(const char * uri)1361 _g_uri_is_dir (const char *uri)
1362 {
1363 	return uri_is_filetype (uri, G_FILE_TYPE_DIRECTORY);
1364 }
1365 
1366 
1367 gboolean
_g_uri_parent_of_uri(const char * dirname,const char * filename)1368 _g_uri_parent_of_uri (const char *dirname,
1369 		      const char *filename)
1370 {
1371 	int dirname_l, filename_l, separator_position;
1372 
1373 	if ((dirname == NULL) || (filename == NULL))
1374 		return FALSE;
1375 
1376 	dirname_l = strlen (dirname);
1377 	filename_l = strlen (filename);
1378 
1379 	if ((dirname_l == filename_l + 1)
1380 	    && (dirname[dirname_l - 1] == '/'))
1381 		return FALSE;
1382 
1383 	if ((filename_l == dirname_l + 1)
1384 	    && (filename[filename_l - 1] == '/'))
1385 		return FALSE;
1386 
1387 	if (dirname[dirname_l - 1] == '/')
1388 		separator_position = dirname_l - 1;
1389 	else
1390 		separator_position = dirname_l;
1391 
1392 	return ((filename_l > dirname_l)
1393 		&& (strncmp (dirname, filename, dirname_l) == 0)
1394 		&& (filename[separator_position] == '/'));
1395 }
1396 
1397 
1398 char *
_g_uri_get_parent(const char * uri)1399 _g_uri_get_parent (const char *uri)
1400 {
1401 	int         p;
1402 	const char *ptr = uri;
1403 	char       *new_uri;
1404 
1405 	if (uri == NULL)
1406 		return NULL;
1407 
1408 	p = strlen (uri) - 1;
1409 	if (p < 0)
1410 		return NULL;
1411 
1412 	while ((p > 0) && (ptr[p] != '/'))
1413 		p--;
1414 	if ((p == 0) && (ptr[p] == '/'))
1415 		p++;
1416 	new_uri = g_strndup (uri, (guint)p);
1417 
1418 	return new_uri;
1419 }
1420 
1421 
1422 char *
_g_uri_remove_extension(const char * uri)1423 _g_uri_remove_extension (const char *uri)
1424 {
1425 	int   len;
1426 	int   p;
1427 	char *new_path;
1428 
1429 	if (uri == NULL)
1430 		return NULL;
1431 
1432 	len = strlen (uri);
1433 	if (len == 1)
1434 		return g_strdup (uri);
1435 
1436 	p = len - 1;
1437 	while ((p > 0) && (uri[p] != '.'))
1438 		p--;
1439 	if (p == 0)
1440 		p = len;
1441 	new_path = g_strndup (uri, (guint) p);
1442 
1443 	return new_path;
1444 }
1445 
1446 
1447 char *
_g_build_uri(const char * base,...)1448 _g_build_uri (const char *base, ...)
1449 {
1450 	va_list     args;
1451 	const char *child;
1452 	GString    *uri;
1453 
1454 	uri = g_string_new (base);
1455 
1456 	va_start (args, base);
1457 	while ((child = va_arg (args, const char *)) != NULL) {
1458 		if (! g_str_has_suffix (uri->str, "/") && ! g_str_has_prefix (child, "/"))
1459 			g_string_append (uri, "/");
1460 		g_string_append (uri, child);
1461 	}
1462 	va_end (args);
1463 
1464 	return g_string_free (uri, FALSE);
1465 }
1466 
1467 
1468 /* GIO utils */
1469 
1470 
1471 gboolean
_g_file_equal(GFile * file1,GFile * file2)1472 _g_file_equal (GFile *file1,
1473 	       GFile *file2)
1474 {
1475 	if ((file1 == NULL) && (file2 == NULL))
1476 		return TRUE;
1477 	if ((file1 == NULL) || (file2 == NULL))
1478 		return FALSE;
1479 
1480 	return g_file_equal (file1, file2);
1481 }
1482 
1483 
1484 char *
_g_file_get_display_name(GFile * file)1485 _g_file_get_display_name (GFile *file)
1486 {
1487 	char      *name = NULL;
1488 	GFileInfo *file_info;
1489 
1490 	file_info = g_file_query_info (file,
1491 				       G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
1492 				       G_FILE_QUERY_INFO_NONE,
1493 				       NULL,
1494 				       NULL);
1495 	if (file_info != NULL)
1496 		name = g_strdup (g_file_info_get_attribute_string (file_info, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME));
1497 	else
1498 		name = g_file_get_parse_name (file);
1499 
1500 	return name;
1501 }
1502 
1503 
1504 GFileType
_g_file_get_standard_type(GFile * file)1505 _g_file_get_standard_type (GFile *file)
1506 {
1507 	GFileType  result;
1508 	GFileInfo *info;
1509 	GError    *error = NULL;
1510 
1511 	info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_TYPE, 0, NULL, &error);
1512 	if (error == NULL) {
1513 		result = g_file_info_get_file_type (info);
1514 	}
1515 	else {
1516 		result = G_FILE_ATTRIBUTE_TYPE_INVALID;
1517 		g_error_free (error);
1518 	}
1519 
1520 	g_object_unref (info);
1521 
1522 	return result;
1523 }
1524 
1525 
1526 GFile *
_g_file_get_destination(GFile * source,GFile * source_base,GFile * destination_folder)1527 _g_file_get_destination (GFile *source,
1528 		         GFile *source_base,
1529 		         GFile *destination_folder)
1530 {
1531 	char       *source_uri;
1532 	const char *source_suffix;
1533 	char       *destination_folder_uri;
1534 	char       *destination_uri;
1535 	GFile      *destination;
1536 
1537 	source_uri = g_file_get_uri (source);
1538 	if (source_base != NULL) {
1539 		char *source_base_uri;
1540 
1541 		source_base_uri = g_file_get_uri (source_base);
1542 		source_suffix = source_uri + strlen (source_base_uri);
1543 
1544 		g_free (source_base_uri);
1545 	}
1546 	else
1547 		source_suffix = _g_uri_get_basename (source_uri);
1548 
1549 	destination_folder_uri = g_file_get_uri (destination_folder);
1550 	destination_uri = g_strconcat (destination_folder_uri, "/", source_suffix, NULL);
1551 	destination = g_file_new_for_uri (destination_uri);
1552 
1553 	g_free (destination_uri);
1554 	g_free (destination_folder_uri);
1555 	g_free (source_uri);
1556 
1557 	return destination;
1558 }
1559 
1560 
1561 GFile *
_g_file_get_child(GFile * file,...)1562 _g_file_get_child (GFile *file,
1563 		   ...)
1564 {
1565 	va_list     args;
1566 	const char *name;
1567 	GFile      *child;
1568 
1569 	child = g_object_ref (file);
1570 
1571 	va_start (args, file);
1572 	while ((name = va_arg (args, const char *)) != NULL) {
1573 		GFile *tmp;
1574 
1575 		tmp = g_file_get_child (child, name);
1576 		g_object_unref (child);
1577 		child = tmp;
1578 	}
1579 	va_end (args);
1580 
1581 	return child;
1582 }
1583 
1584 
1585 GIcon *
_g_file_get_icon(GFile * file)1586 _g_file_get_icon (GFile *file)
1587 {
1588 	GIcon     *icon = NULL;
1589 	GFileInfo *file_info;
1590 
1591 	file_info = g_file_query_info (file,
1592 				       G_FILE_ATTRIBUTE_STANDARD_ICON,
1593 				       G_FILE_QUERY_INFO_NONE,
1594 				       NULL,
1595 				       NULL);
1596 	if (file_info != NULL)
1597 		icon = (GIcon*) g_file_info_get_attribute_object (file_info, G_FILE_ATTRIBUTE_STANDARD_ICON);
1598 	else
1599 		icon = g_themed_icon_new ("file");
1600 
1601 	return icon;
1602 }
1603 
1604 
1605 GList *
_g_file_list_dup(GList * l)1606 _g_file_list_dup (GList *l)
1607 {
1608 	GList *r = NULL, *scan;
1609 	for (scan = l; scan; scan = scan->next)
1610 		r = g_list_prepend (r, g_file_dup ((GFile*) scan->data));
1611 	return g_list_reverse (r);
1612 }
1613 
1614 
1615 void
_g_file_list_free(GList * l)1616 _g_file_list_free (GList *l)
1617 {
1618 	GList *scan;
1619 	for (scan = l; scan; scan = scan->next)
1620 		g_object_unref (scan->data);
1621 	g_list_free (l);
1622 }
1623 
1624 
1625 GList *
_g_file_list_new_from_uri_list(GList * uris)1626 _g_file_list_new_from_uri_list (GList *uris)
1627 {
1628 	GList *r = NULL, *scan;
1629 	for (scan = uris; scan; scan = scan->next)
1630 		r = g_list_prepend (r, g_file_new_for_uri ((char*)scan->data));
1631 	return g_list_reverse (r);
1632 }
1633 
1634 
1635 GList *
_g_file_list_new_from_uriv(char ** uris)1636 _g_file_list_new_from_uriv (char **uris)
1637 {
1638 	GList *r = NULL;
1639 	int    i;
1640 
1641 	if (uris == NULL)
1642 		return NULL;
1643 
1644 	for (i = 0; uris[i] != NULL; i++)
1645 		r = g_list_prepend (r, g_file_new_for_uri (uris[i]));
1646 
1647 	return g_list_reverse (r);
1648 }
1649 
1650 
1651 GList *
_g_file_list_find_file(GList * l,GFile * file)1652 _g_file_list_find_file (GList *l,
1653 			GFile *file)
1654 {
1655 	GList *scan;
1656 
1657 	for (scan = l; scan; scan = scan->next)
1658 		if (g_file_equal (file, (GFile *) scan->data))
1659 			return scan;
1660 	return NULL;
1661 }
1662 
1663 
1664 const char*
_g_file_get_mime_type(GFile * file,gboolean fast_file_type)1665 _g_file_get_mime_type (GFile    *file,
1666 		       gboolean  fast_file_type)
1667 {
1668 	GFileInfo  *info;
1669 	GError     *err = NULL;
1670  	const char *result = NULL;
1671 
1672 	info = g_file_query_info (file,
1673 				  fast_file_type ?
1674 				  G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE :
1675 				  G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
1676 				  0, NULL, &err);
1677 	if (info == NULL) {
1678 		char *uri;
1679 
1680 		uri = g_file_get_uri (file);
1681 		g_warning ("could not get content type for %s: %s", uri, err->message);
1682 		g_free (uri);
1683 		g_clear_error (&err);
1684 	}
1685 	else {
1686 		result = get_static_string (g_content_type_get_mime_type (g_file_info_get_content_type (info)));
1687 		g_object_unref (info);
1688 	}
1689 
1690 	return result;
1691 }
1692 
1693 
1694 void
_g_file_get_modification_time(GFile * file,GTimeVal * result)1695 _g_file_get_modification_time (GFile    *file,
1696 			       GTimeVal *result)
1697 {
1698 	GFileInfo *info;
1699 	GError    *err = NULL;
1700 
1701 	result->tv_sec = 0;
1702 	result->tv_usec = 0;
1703 
1704 	info = g_file_query_info (file,
1705 				  G_FILE_ATTRIBUTE_TIME_MODIFIED "," G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC,
1706 				  0,
1707 				  NULL,
1708 				  &err);
1709 	if (info != NULL) {
1710 		g_file_info_get_modification_time (info, result);
1711 		g_object_unref (info);
1712 	}
1713 	else {
1714 		char *uri;
1715 
1716 		uri = g_file_get_uri (file);
1717 		g_warning ("could not get modification time for %s: %s", uri, err->message);
1718 		g_free (uri);
1719 		g_clear_error (&err);
1720 	}
1721 }
1722 
1723 
1724 time_t
_g_file_get_mtime(GFile * file)1725 _g_file_get_mtime (GFile *file)
1726 {
1727 	GTimeVal timeval;
1728 
1729 	_g_file_get_modification_time (file, &timeval);
1730 	return (time_t) timeval.tv_sec;
1731 }
1732 
1733 
1734 int
_g_file_cmp_uris(GFile * a,GFile * b)1735 _g_file_cmp_uris (GFile *a,
1736 		  GFile *b)
1737 {
1738 	return g_file_equal (a, b) ? 0 : 1;
1739 }
1740 
1741 
1742 int
_g_file_cmp_modification_time(GFile * file_a,GFile * file_b)1743 _g_file_cmp_modification_time (GFile *file_a,
1744 			       GFile *file_b)
1745 {
1746 	GTimeVal timeval_a;
1747 	GTimeVal timeval_b;
1748 
1749 	_g_file_get_modification_time (file_a, &timeval_a);
1750 	_g_file_get_modification_time (file_b, &timeval_b);
1751 
1752 	return _g_time_val_cmp (&timeval_a, &timeval_b);
1753 }
1754 
1755 
1756 goffset
_g_file_get_size(GFile * file)1757 _g_file_get_size (GFile *file)
1758 {
1759 	GFileInfo *info;
1760 	GError    *err = NULL;
1761 	goffset    size = 0;
1762 
1763 	info = g_file_query_info (file, G_FILE_ATTRIBUTE_FILESYSTEM_SIZE, 0, NULL, &err);
1764 	if (info != NULL) {
1765 		size = g_file_info_get_size (info);
1766 		g_object_unref (info);
1767 	}
1768 	else {
1769 		char *uri;
1770 
1771 		uri = g_file_get_uri (file);
1772 		g_warning ("could not get size for %s: %s", uri, err->message);
1773 		g_free (uri);
1774 		g_clear_error (&err);
1775 	}
1776 
1777 	return size;
1778 }
1779 
1780 
1781 #define MAX_SYMLINKS 32
1782 
1783 
1784 static GFile *
resolve_symlinks(GFile * file,GError ** error,int level)1785 resolve_symlinks (GFile   *file,
1786 		  GError **error,
1787 		  int      level)
1788 {
1789 	GFile *resolved;
1790 	char  *path;
1791 	char **names;
1792 	int    i;
1793 
1794 	if (level > MAX_SYMLINKS) {
1795 		char *uri;
1796 
1797 		uri = g_file_get_uri (file);
1798 		*error = g_error_new (G_IO_ERROR, G_IO_ERROR_TOO_MANY_LINKS, "Too many symbolic links for file: %s.", uri);
1799 		g_free (uri);
1800 
1801 		return NULL;
1802 	}
1803 
1804 	path = g_file_get_path (file);
1805 	if (path == NULL) {
1806 		char *uri;
1807 
1808 		uri = g_file_get_uri (file);
1809 		*error = g_error_new (G_IO_ERROR, G_IO_ERROR_FAILED, "No local pathname for file: %s.", uri);
1810 		g_free (uri);
1811 
1812 		return NULL;
1813 	}
1814 
1815 	resolved = g_file_new_for_path (G_DIR_SEPARATOR_S);
1816 
1817 	names = g_strsplit (path, G_DIR_SEPARATOR_S, -1);
1818 	for (i = 0; names[i] != NULL; i++) {
1819 		GFile     *child;
1820 		GFileInfo *info;
1821 		GFile     *new_resolved;
1822 
1823 		if (strcmp (names[i], "") == 0)
1824 			continue;
1825 
1826 		child = g_file_get_child (resolved, names[i]);
1827 		info = g_file_query_info (child, G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK "," G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET, 0, NULL, error);
1828 		if (info == NULL) {
1829 			g_object_unref (child);
1830 			g_object_unref (resolved);
1831 			resolved = NULL;
1832 			break;
1833 		}
1834 
1835 		/* if names[i] isn't a symbolic link add it to the resolved path and continue */
1836 
1837 		if (! g_file_info_get_is_symlink (info)) {
1838 			g_object_unref (info);
1839 			g_object_unref (resolved);
1840 			resolved = child;
1841 			continue;
1842 		}
1843 
1844 		g_object_unref (child);
1845 
1846 		/* names[i] is a symbolic link */
1847 
1848 		new_resolved = g_file_resolve_relative_path (resolved, g_file_info_get_symlink_target (info));
1849 
1850 		g_object_unref (resolved);
1851 		g_object_unref (info);
1852 
1853 		resolved = resolve_symlinks (new_resolved, error, level + 1);
1854 
1855 		g_object_unref (new_resolved);
1856 	}
1857 
1858 	g_strfreev (names);
1859 	g_free (path);
1860 
1861 	return resolved;
1862 }
1863 
1864 
1865 GFile *
_g_file_resolve_all_symlinks(GFile * file,GError ** error)1866 _g_file_resolve_all_symlinks (GFile   *file,
1867 			      GError **error)
1868 {
1869 	return resolve_symlinks (file, error, 0);
1870 }
1871 
1872 
1873 GFile *
_g_file_append_prefix(GFile * file,const char * prefix)1874 _g_file_append_prefix (GFile      *file,
1875 		       const char *prefix)
1876 {
1877 	char  *uri;
1878 	char  *new_uri;
1879 	GFile *new_file;
1880 
1881 	uri = g_file_get_uri (file);
1882 	new_uri = g_strconcat (prefix, uri, NULL);
1883 	new_file = g_file_new_for_uri (new_uri);
1884 
1885 	g_free (new_uri);
1886 	g_free (uri);
1887 
1888 	return new_file;
1889 }
1890 
1891 
1892 GFile *
_g_file_append_path(GFile * file,const char * path)1893 _g_file_append_path (GFile      *file,
1894 		     const char *path)
1895 {
1896 	char  *uri;
1897 	char  *escaped;
1898 	char  *new_uri;
1899 	GFile *new_file;
1900 
1901 	if (path == NULL)
1902 		return g_file_dup (file);
1903 
1904 	uri = g_file_get_uri (file);
1905 	escaped = g_uri_escape_string (path, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH, FALSE);
1906 	new_uri = _g_build_uri (uri, escaped, NULL);
1907 	new_file = g_file_new_for_uri (new_uri);
1908 
1909 	g_free (new_uri);
1910 	g_free (escaped);
1911 	g_free (uri);
1912 
1913 	return new_file;
1914 }
1915 
1916 
1917 static gboolean
_g_file_attributes_matches_mask(const char * attributes,const char * mask)1918 _g_file_attributes_matches_mask (const char *attributes,
1919 			         const char *mask)
1920 {
1921 	gboolean   matches = FALSE;
1922 	char     **attributes_v;
1923 	char     **mask_v;
1924 	int        i;
1925 
1926 	attributes_v = g_strsplit (attributes, ",", -1);
1927 	mask_v = g_strsplit (mask, ",", -1);
1928 	for (i = 0; ! matches && (mask_v[i] != NULL); i++) {
1929 		GFileAttributeMatcher *matcher;
1930 		int                    j;
1931 
1932 		matcher = g_file_attribute_matcher_new (mask_v[i]);
1933 		for (j = 0; ! matches && (attributes_v[j] != NULL); j++)
1934 			matches = g_file_attribute_matcher_matches (matcher, attributes_v[j]);
1935 
1936 		g_file_attribute_matcher_unref (matcher);
1937 	}
1938 
1939 	g_strfreev (mask_v);
1940 	g_strfreev (attributes_v);
1941 
1942 	return matches;
1943 }
1944 
1945 
1946 gboolean
_g_file_attributes_matches(const char * attributes,const char * mask)1947 _g_file_attributes_matches (const char *attributes,
1948 			    const char *mask)
1949 {
1950 	return _g_file_attributes_matches_mask (attributes, mask) || _g_file_attributes_matches_mask (mask, attributes);
1951 }
1952 
1953 
1954 /* -- _g_file_info_swap_attributes -- */
1955 
1956 
1957 typedef struct {
1958 	GFileAttributeType type;
1959 	union {
1960 		char      *string;
1961 		char     **stringv;
1962 		gboolean   boolean;
1963 		guint32    uint32;
1964 		gint32     int32;
1965 		guint64    uint64;
1966 		gint64     int64;
1967 		gpointer   object;
1968 	} v;
1969 } _GFileAttributeValue;
1970 
1971 
1972 static void
_g_file_attribute_value_free(_GFileAttributeValue * attr_value)1973 _g_file_attribute_value_free (_GFileAttributeValue *attr_value)
1974 {
1975 	switch (attr_value->type) {
1976 	case G_FILE_ATTRIBUTE_TYPE_STRING:
1977 	case G_FILE_ATTRIBUTE_TYPE_BYTE_STRING:
1978 		g_free (attr_value->v.string);
1979 		break;
1980 /* FIXME: add if glib >= 2.22
1981 	case G_FILE_ATTRIBUTE_TYPE_STRINGV:
1982 		g_strfreev (attr_value->v.stringv);
1983 		break;
1984 */
1985 	case G_FILE_ATTRIBUTE_TYPE_OBJECT:
1986 		g_object_unref (attr_value->v.object);
1987 		break;
1988 	default:
1989 		break;
1990 	}
1991 
1992 	g_free (attr_value);
1993 }
1994 
1995 
1996 static _GFileAttributeValue *
_g_file_info_get_value(GFileInfo * info,const char * attr)1997 _g_file_info_get_value (GFileInfo  *info,
1998 			const char *attr)
1999 {
2000 	_GFileAttributeValue  *attr_value;
2001 	GFileAttributeType     type;
2002 	gpointer               value;
2003 	GFileAttributeStatus   status;
2004 
2005 	attr_value = g_new (_GFileAttributeValue, 1);
2006 	attr_value->type = G_FILE_ATTRIBUTE_TYPE_INVALID;
2007 
2008 	if (! g_file_info_get_attribute_data (info, attr, &type, &value, &status))
2009 		return attr_value;
2010 
2011 	attr_value->type = type;
2012 	switch (type) {
2013 	case G_FILE_ATTRIBUTE_TYPE_INVALID:
2014 		break;
2015 	case G_FILE_ATTRIBUTE_TYPE_STRING:
2016 	case G_FILE_ATTRIBUTE_TYPE_BYTE_STRING:
2017 		attr_value->v.string = g_strdup ((char *) value);
2018 		break;
2019 /* FIXME: add if glib >= 2.22
2020 	case G_FILE_ATTRIBUTE_TYPE_STRINGV:
2021 		attr_value->v.stringv = g_strdupv ((char **) value);
2022 		break;
2023 */
2024 	case G_FILE_ATTRIBUTE_TYPE_BOOLEAN:
2025 		attr_value->v.boolean = * ((gboolean *) value);
2026 		break;
2027 	case G_FILE_ATTRIBUTE_TYPE_UINT32:
2028 		attr_value->v.uint32 = * ((guint32 *) value);
2029 		break;
2030 	case G_FILE_ATTRIBUTE_TYPE_INT32:
2031 		attr_value->v.int32 = * ((gint32 *) value);
2032 		break;
2033 	case G_FILE_ATTRIBUTE_TYPE_UINT64:
2034 		attr_value->v.uint64 = * ((guint64 *) value);
2035 		break;
2036 	case G_FILE_ATTRIBUTE_TYPE_INT64:
2037 		attr_value->v.int64 = * ((gint64 *) value);
2038 		break;
2039 	case G_FILE_ATTRIBUTE_TYPE_OBJECT:
2040 		attr_value->v.object = g_object_ref ((GObject *) value);
2041 		break;
2042 	default:
2043 		g_warning ("unknown attribute type: %d", type);
2044 		break;
2045 	}
2046 
2047 	return attr_value;
2048 }
2049 
2050 
2051 static void
_g_file_info_set_value(GFileInfo * info,const char * attr,_GFileAttributeValue * attr_value)2052 _g_file_info_set_value (GFileInfo            *info,
2053 			const char           *attr,
2054 			_GFileAttributeValue *attr_value)
2055 {
2056 	gpointer value = NULL;
2057 
2058 	if (attr_value->type == G_FILE_ATTRIBUTE_TYPE_INVALID)
2059 		return;
2060 
2061 	switch (attr_value->type) {
2062 	case G_FILE_ATTRIBUTE_TYPE_STRING:
2063 	case G_FILE_ATTRIBUTE_TYPE_BYTE_STRING:
2064 		value = attr_value->v.string;
2065 		break;
2066 /* FIXME: add if glib >= 2.22
2067 	case G_FILE_ATTRIBUTE_TYPE_STRINGV:
2068 		value = attr_value->v.stringv;
2069 		break;
2070 */
2071 	case G_FILE_ATTRIBUTE_TYPE_BOOLEAN:
2072 		value = &attr_value->v.boolean;
2073 		break;
2074 	case G_FILE_ATTRIBUTE_TYPE_UINT32:
2075 		value = &attr_value->v.uint32;
2076 		break;
2077 	case G_FILE_ATTRIBUTE_TYPE_INT32:
2078 		value = &attr_value->v.int32;
2079 		break;
2080 	case G_FILE_ATTRIBUTE_TYPE_UINT64:
2081 		value = &attr_value->v.uint64;
2082 		break;
2083 	case G_FILE_ATTRIBUTE_TYPE_INT64:
2084 		value = &attr_value->v.int64;
2085 		break;
2086 	case G_FILE_ATTRIBUTE_TYPE_OBJECT:
2087 		value = attr_value->v.object;
2088 		break;
2089 	default:
2090 		g_warning ("Unknown attribute type: %d", attr_value->type);
2091 		break;
2092 	}
2093 
2094 	g_file_info_set_attribute (info, attr, attr_value->type, value);
2095 }
2096 
2097 
2098 void
_g_file_info_swap_attributes(GFileInfo * info,const char * attr1,const char * attr2)2099 _g_file_info_swap_attributes (GFileInfo  *info,
2100 			      const char *attr1,
2101 			      const char *attr2)
2102 {
2103 	_GFileAttributeValue *value1;
2104 	_GFileAttributeValue *value2;
2105 
2106 	value1 = _g_file_info_get_value (info, attr1);
2107 	value2 = _g_file_info_get_value (info, attr2);
2108 
2109 	_g_file_info_set_value (info, attr1, value2);
2110 	_g_file_info_set_value (info, attr2, value1);
2111 
2112 	_g_file_attribute_value_free (value1);
2113 	_g_file_attribute_value_free (value2);
2114 }
2115 
2116 
2117 gboolean
_g_mime_type_is_image(const char * mime_type)2118 _g_mime_type_is_image (const char *mime_type)
2119 {
2120 	g_return_val_if_fail (mime_type != NULL, FALSE);
2121 
2122 	/* Valid image mime types:
2123 		1. All *image* types,
2124 		2. application/x-crw
2125 			This is a RAW photo file, which for some reason
2126 			uses an "application" prefix instead of "image".
2127 	*/
2128 
2129 	return (g_content_type_is_a (mime_type, "image/*")
2130 		|| (strcmp (mime_type, "application/x-crw") == 0));
2131 }
2132 
2133 
2134 gboolean
_g_mime_type_is_video(const char * mime_type)2135 _g_mime_type_is_video (const char *mime_type)
2136 {
2137 	g_return_val_if_fail (mime_type != NULL, FALSE);
2138 
2139 	return (g_content_type_is_a (mime_type, "video/*")
2140 		|| (strcmp (mime_type, "application/ogg") == 0)
2141 		|| (strcmp (mime_type, "application/vnd.rn-realmedia") == 0));
2142 }
2143 
2144 
2145 gboolean
_g_mime_type_is_audio(const char * mime_type)2146 _g_mime_type_is_audio (const char *mime_type)
2147 {
2148 	g_return_val_if_fail (mime_type != NULL, FALSE);
2149 
2150 	return g_content_type_is_a (mime_type, "audio/*");
2151 }
2152 
2153 
2154 gboolean
_g_volume_equal(GVolume * v1,GVolume * v2)2155 _g_volume_equal (GVolume *v1,
2156 		 GVolume *v2)
2157 {
2158 	char     *id1;
2159 	char     *id2;
2160 	gboolean  result;
2161 
2162 	id1 = g_volume_get_identifier (v1, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE);
2163 	id2 = g_volume_get_identifier (v2, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE);
2164 	result = g_strcmp0 (id1, id2) == 0;
2165 
2166 	g_free (id1);
2167 	g_free (id2);
2168 
2169 	return result;
2170 }
2171 
2172 
2173 gboolean
_g_drive_equal(GDrive * d1,GDrive * d2)2174 _g_drive_equal (GDrive *d1,
2175 		GDrive *d2)
2176 {
2177 	char     *id1;
2178 	char     *id2;
2179 	gboolean  result;
2180 
2181 	id1 = g_drive_get_identifier (d1, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE);
2182 	id2 = g_drive_get_identifier (d2, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE);
2183 	result = g_strcmp0 (id1, id2) == 0;
2184 
2185 	g_free (id1);
2186 	g_free (id2);
2187 
2188 	return result;
2189 }
2190 
2191 
2192 char *
_g_make_temp_directory(void)2193 _g_make_temp_directory (void)
2194 {
2195 	char *template;
2196 
2197 	template = g_strconcat (g_get_tmp_dir (), "/goobox-XXXXXX", NULL);
2198 	g_assert (mkdtemp (template) != NULL);
2199 
2200 	return template;
2201 }
2202 
2203 
2204 /* this is totem_time_to_string renamed, thanks to the authors :) */
2205 char *
_g_format_duration_for_display(gint64 msecs)2206 _g_format_duration_for_display (gint64 msecs)
2207 {
2208         int sec, min, hour, _time;
2209 
2210         _time = (int) (msecs / 1000);
2211         sec = _time % 60;
2212         _time = _time - sec;
2213         min = (_time % (60*60)) / 60;
2214         _time = _time - (min * 60);
2215         hour = _time / (60*60);
2216 
2217         if (hour > 0)
2218         {
2219                 /* hour:minutes:seconds */
2220                 /* Translators: This is a time format, like "9:05:02" for 9
2221                  * hours, 5 minutes, and 2 seconds. You may change ":" to
2222                  * the separator that your locale uses or use "%Id" instead
2223                  * of "%d" if your locale uses localized digits.
2224                  */
2225                 return g_strdup_printf (C_("long time format", "%d∶%02d∶%02d"), hour, min, sec);
2226         }
2227 
2228         /* minutes:seconds */
2229         /* Translators: This is a time format, like "5:02" for 5
2230          * minutes and 2 seconds. You may change ":" to the
2231          * separator that your locale uses or use "%Id" instead of
2232          * "%d" if your locale uses localized digits.
2233          */
2234         return g_strdup_printf (C_("short time format", "%d∶%02d"), min, sec);
2235 }
2236 
2237 
2238 void
_g_toggle_action_activated(GSimpleAction * action,GVariant * parameter,gpointer data)2239 _g_toggle_action_activated (GSimpleAction *action,
2240 			    GVariant      *parameter,
2241 			    gpointer       data)
2242 {
2243 	GVariant *state;
2244 
2245 	state = g_action_get_state (G_ACTION (action));
2246 	g_action_change_state (G_ACTION (action), g_variant_new_boolean (! g_variant_get_boolean (state)));
2247 
2248 	g_variant_unref (state);
2249 }
2250