goa: Add missing linker flag (for real).
[platform/upstream/evolution-data-server.git] / libedataserver / e-data-server-util.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of version 2 of the GNU Lesser General Public
7  * License as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  *
19  * Authors: Rodrigo Moya <rodrigo@ximian.com>
20  */
21
22 #include "config.h"
23
24 #include <string.h>
25 #include <sys/stat.h>
26 #include <time.h>
27 #include <unistd.h>
28
29 #ifdef G_OS_WIN32
30 #include <mbstring.h>
31 #endif
32
33 #include <glib-object.h>
34
35 #include "e-data-server-util.h"
36
37 /**
38  * e_get_user_cache_dir:
39  *
40  * Returns a base directory in which to store user-specific,
41  * non-essential cached data for Evolution or Evolution-Data-Server.
42  *
43  * The returned string is owned by libedataserver and must not be
44  * modified or freed.
45  *
46  * Returns: base directory for user-specific, non-essential data
47  *
48  * Since: 2.32
49  **/
50 const gchar *
51 e_get_user_cache_dir (void)
52 {
53         static gchar *dirname = NULL;
54
55         if (G_UNLIKELY (dirname == NULL)) {
56                 const gchar *cache_dir = g_get_user_cache_dir ();
57                 dirname = g_build_filename (cache_dir, "evolution", NULL);
58                 g_mkdir_with_parents (dirname, 0700);
59         }
60
61         return dirname;
62 }
63
64 /**
65  * e_get_user_config_dir:
66  *
67  * Returns a base directory in which to store user-specific configuration
68  * information for Evolution or Evolution-Data-Server.
69  *
70  * The returned string is owned by libedataserver and must not be
71  * modified or freed.
72  *
73  * Returns: base directory for user-specific configuration information
74  *
75  * Since: 2.32
76  **/
77 const gchar *
78 e_get_user_config_dir (void)
79 {
80         static gchar *dirname = NULL;
81
82         if (G_UNLIKELY (dirname == NULL)) {
83                 const gchar *config_dir = g_get_user_config_dir ();
84                 dirname = g_build_filename (config_dir, "evolution", NULL);
85                 g_mkdir_with_parents (dirname, 0700);
86         }
87
88         return dirname;
89 }
90
91 /**
92  * e_get_user_data_dir:
93  *
94  * Returns a base directory in which to store user-specific data for
95  * Evolution or Evolution-Data-Server.
96  *
97  * The returned string is owned by libedataserver and must not be
98  * modified or freed.
99  *
100  * Returns: base directory for user-specific data
101  *
102  * Since: 2.32
103  **/
104 const gchar *
105 e_get_user_data_dir (void)
106 {
107         static gchar *dirname = NULL;
108
109         if (G_UNLIKELY (dirname == NULL)) {
110                 const gchar *data_dir = g_get_user_data_dir ();
111                 dirname = g_build_filename (data_dir, "evolution", NULL);
112                 g_mkdir_with_parents (dirname, 0700);
113         }
114
115         return dirname;
116 }
117
118 /**
119  * e_util_strdup_strip:
120  * @string: (allow-none): a string value, or %NULL
121  *
122  * Duplicates @string and strips off any leading or trailing whitespace.
123  * The resulting string is returned unless it is empty or %NULL, in which
124  * case the function returns %NULL.
125  *
126  * Free the returned string with g_free().
127  *
128  * Returns: a newly-allocated, stripped copy of @string, or %NULL
129  *
130  * Since: 3.6
131  **/
132 gchar *
133 e_util_strdup_strip (const gchar *string)
134 {
135         gchar *duplicate;
136
137         duplicate = g_strdup (string);
138         if (duplicate != NULL) {
139                 g_strstrip (duplicate);
140                 if (*duplicate == '\0') {
141                         g_free (duplicate);
142                         duplicate = NULL;
143                 }
144         }
145
146         return duplicate;
147 }
148
149 /**
150  * e_util_strstrcase:
151  * @haystack: The string to search in.
152  * @needle: The string to search for.
153  *
154  * Find the first instance of @needle in @haystack, ignoring case for
155  * bytes that are ASCII characters.
156  *
157  * Returns: A pointer to the start of @needle in @haystack, or NULL if
158  *          @needle is not found.
159  **/
160 gchar *
161 e_util_strstrcase (const gchar *haystack,
162                    const gchar *needle)
163 {
164         /* find the needle in the haystack neglecting case */
165         const gchar *ptr;
166         guint len;
167
168         g_return_val_if_fail (haystack != NULL, NULL);
169         g_return_val_if_fail (needle != NULL, NULL);
170
171         len = strlen (needle);
172         if (len > strlen (haystack))
173                 return NULL;
174
175         if (len == 0)
176                 return (gchar *) haystack;
177
178         for (ptr = haystack; *(ptr + len - 1) != '\0'; ptr++)
179                 if (!g_ascii_strncasecmp (ptr, needle, len))
180                         return (gchar *) ptr;
181
182         return NULL;
183 }
184
185 /**
186  * e_util_unicode_get_utf8:
187  * @text: The string to take the UTF-8 character from.
188  * @out: The location to store the UTF-8 character in.
189  *
190  * Get a UTF-8 character from the beginning of @text.
191  *
192  * Returns: A pointer to the next character in @text after @out.
193  **/
194 gchar *
195 e_util_unicode_get_utf8 (const gchar *text,
196                          gunichar *out)
197 {
198         g_return_val_if_fail (text != NULL, NULL);
199         g_return_val_if_fail (out != NULL, NULL);
200
201         *out = g_utf8_get_char (text);
202         return (*out == (gunichar) -1) ? NULL : g_utf8_next_char (text);
203 }
204
205 /**
206  * e_util_utf8_strstrcase:
207  * @haystack: The string to search in.
208  * @needle: The string to search for.
209  *
210  * Find the first instance of @needle in @haystack, ignoring case. (No
211  * proper case folding or decomposing is done.) Both @needle and
212  * @haystack are UTF-8 strings.
213  *
214  * Returns: A pointer to the first instance of @needle in @haystack, or
215  *          %NULL if no match is found, or if either of the strings are
216  *          not legal UTF-8 strings.
217  **/
218 const gchar *
219 e_util_utf8_strstrcase (const gchar *haystack,
220                         const gchar *needle)
221 {
222         gunichar *nuni, unival;
223         gint nlen;
224         const gchar *o, *p;
225
226         if (haystack == NULL)
227                 return NULL;
228
229         if (needle == NULL)
230                 return NULL;
231
232         if (strlen (needle) == 0)
233                 return haystack;
234
235         if (strlen (haystack) == 0)
236                 return NULL;
237
238         nuni = g_alloca (sizeof (gunichar) * strlen (needle));
239
240         nlen = 0;
241         for (p = e_util_unicode_get_utf8 (needle, &unival);
242              p && unival;
243              p = e_util_unicode_get_utf8 (p, &unival)) {
244                 nuni[nlen++] = g_unichar_tolower (unival);
245         }
246         /* NULL means there was illegal utf-8 sequence */
247         if (!p) return NULL;
248
249         o = haystack;
250         for (p = e_util_unicode_get_utf8 (o, &unival);
251              p && unival;
252              p = e_util_unicode_get_utf8 (p, &unival)) {
253                 gunichar sc;
254                 sc = g_unichar_tolower (unival);
255                 /* We have valid stripped gchar */
256                 if (sc == nuni[0]) {
257                         const gchar *q = p;
258                         gint npos = 1;
259                         while (npos < nlen) {
260                                 q = e_util_unicode_get_utf8 (q, &unival);
261                                 if (!q || !unival) return NULL;
262                                 sc = g_unichar_tolower (unival);
263                                 if (sc != nuni[npos]) break;
264                                 npos++;
265                         }
266                         if (npos == nlen) {
267                                 return o;
268                         }
269                 }
270                 o = p;
271         }
272
273         return NULL;
274 }
275
276 static gunichar
277 stripped_char (gunichar ch)
278 {
279         gunichar decomp[4];
280         gunichar retval;
281         GUnicodeType utype;
282         gsize dlen;
283
284         utype = g_unichar_type (ch);
285
286         switch (utype) {
287         case G_UNICODE_CONTROL:
288         case G_UNICODE_FORMAT:
289         case G_UNICODE_UNASSIGNED:
290         case G_UNICODE_SPACING_MARK:
291                 /* Ignore those */
292                 return 0;
293         default:
294                 /* Convert to lowercase, fall through */
295                 ch = g_unichar_tolower (ch);
296         case G_UNICODE_LOWERCASE_LETTER:
297                 if ((dlen = g_unichar_fully_decompose (ch, FALSE, decomp, 4))) {
298                         retval = decomp[0];
299                         return retval;
300                 }
301                 break;
302         }
303
304         return 0;
305 }
306
307 /**
308  * e_util_utf8_strstrcasedecomp:
309  * @haystack: The string to search in.
310  * @needle: The string to search for.
311  *
312  * Find the first instance of @needle in @haystack, where both @needle
313  * and @haystack are UTF-8 strings. Both strings are stripped and
314  * decomposed for comparison, and case is ignored.
315  *
316  * Returns: A pointer to the first instance of @needle in @haystack, or
317  *          %NULL if either of the strings are not legal UTF-8 strings.
318  **/
319 const gchar *
320 e_util_utf8_strstrcasedecomp (const gchar *haystack,
321                               const gchar *needle)
322 {
323         gunichar *nuni;
324         gunichar unival;
325         gint nlen;
326         const gchar *o, *p;
327
328         if (haystack == NULL)
329                 return NULL;
330
331         if (needle == NULL)
332                 return NULL;
333
334         if (strlen (needle) == 0)
335                 return haystack;
336
337         if (strlen (haystack) == 0)
338                 return NULL;
339
340         nuni = g_alloca (sizeof (gunichar) * strlen (needle));
341
342         nlen = 0;
343         for (p = e_util_unicode_get_utf8 (needle, &unival);
344              p && unival;
345              p = e_util_unicode_get_utf8 (p, &unival)) {
346                 gunichar sc;
347                 sc = stripped_char (unival);
348                 if (sc) {
349                        nuni[nlen++] = sc;
350                 }
351         }
352         /* NULL means there was illegal utf-8 sequence */
353         if (!p) return NULL;
354         /* If everything is correct, we have decomposed,
355          * lowercase, stripped needle */
356         if (nlen < 1)
357                 return haystack;
358
359         o = haystack;
360         for (p = e_util_unicode_get_utf8 (o, &unival);
361              p && unival;
362              p = e_util_unicode_get_utf8 (p, &unival)) {
363                 gunichar sc;
364                 sc = stripped_char (unival);
365                 if (sc) {
366                         /* We have valid stripped gchar */
367                         if (sc == nuni[0]) {
368                                 const gchar *q = p;
369                                 gint npos = 1;
370                                 while (npos < nlen) {
371                                         q = e_util_unicode_get_utf8 (q, &unival);
372                                         if (!q || !unival) return NULL;
373                                         sc = stripped_char (unival);
374                                         if ((!sc) || (sc != nuni[npos])) break;
375                                         npos++;
376                                 }
377                                 if (npos == nlen) {
378                                         return o;
379                                 }
380                         }
381                 }
382                 o = p;
383         }
384
385         return NULL;
386 }
387
388 /**
389  * e_util_utf8_strcasecmp:
390  * @s1: a UTF-8 string
391  * @s2: another UTF-8 string
392  *
393  * Compares two UTF-8 strings using approximate case-insensitive ordering.
394  *
395  * Returns: < 0 if @s1 compares before @s2, 0 if they compare equal,
396  *          > 0 if @s1 compares after @s2
397  **/
398 gint
399 e_util_utf8_strcasecmp (const gchar *s1,
400                         const gchar *s2)
401 {
402         gchar *folded_s1, *folded_s2;
403         gint retval;
404
405         g_return_val_if_fail (s1 != NULL && s2 != NULL, -1);
406
407         if (strcmp (s1, s2) == 0)
408                 return 0;
409
410         folded_s1 = g_utf8_casefold (s1, -1);
411         folded_s2 = g_utf8_casefold (s2, -1);
412
413         retval = g_utf8_collate (folded_s1, folded_s2);
414
415         g_free (folded_s2);
416         g_free (folded_s1);
417
418         return retval;
419 }
420
421 /**
422  * e_util_utf8_remove_accents:
423  * @str: a UTF-8 string, or %NULL
424  *
425  * Returns a newly-allocated copy of @str with accents removed.
426  *
427  * Returns: a newly-allocated string
428  *
429  * Since: 2.28
430  **/
431 gchar *
432 e_util_utf8_remove_accents (const gchar *str)
433 {
434         gchar *res;
435         gint i, j;
436
437         if (str == NULL)
438                 return NULL;
439
440         res = g_utf8_normalize (str, -1, G_NORMALIZE_NFD);
441         if (!res)
442                 return g_strdup (str);
443
444         for (i = 0, j = 0; res[i]; i++) {
445                 if ((guchar) res[i] != 0xCC || res[i + 1] == 0) {
446                         res[j] = res[i];
447                         j++;
448                 } else {
449                         i++;
450                 }
451         }
452
453         res[j] = 0;
454
455         return res;
456 }
457
458 /**
459  * e_util_utf8_make_valid:
460  * @str: a UTF-8 string
461  *
462  * Returns a newly-allocated copy of @str, with invalid characters
463  * replaced by Unicode replacement characters (U+FFFD).
464  *
465  * Returns: a newly-allocated string
466  *
467  * Since: 3.0
468  **/
469 gchar *
470 e_util_utf8_make_valid (const gchar *str)
471 {
472         return e_util_utf8_data_make_valid (str, strlen (str));
473 }
474
475 /**
476  * e_util_utf8_data_make_valid:
477  * @data: UTF-8 binary data
478  * @data_bytes: length of the binary data
479  *
480  * Returns a newly-allocated NULL-terminated string with invalid characters
481  * replaced by Unicode replacement characters (U+FFFD).
482  *
483  * Returns: a newly-allocated string
484  *
485  * Since: 3.6
486  */
487 gchar *
488 e_util_utf8_data_make_valid (const gchar *data,
489                              gsize data_bytes)
490 {
491         /* almost identical copy of glib's _g_utf8_make_valid() */
492         GString *string;
493         const gchar *remainder, *invalid;
494         gint remaining_bytes, valid_bytes;
495
496         g_return_val_if_fail (data != NULL, NULL);
497
498         string = NULL;
499         remainder = (gchar *) data,
500         remaining_bytes = data_bytes;
501
502         while (remaining_bytes != 0) {
503                 if (g_utf8_validate (remainder, remaining_bytes, &invalid))
504                         break;
505                 valid_bytes = invalid - remainder;
506
507                 if (string == NULL)
508                         string = g_string_sized_new (remaining_bytes);
509
510                 g_string_append_len (string, remainder, valid_bytes);
511                 /* append U+FFFD REPLACEMENT CHARACTER */
512                 g_string_append (string, "\357\277\275");
513
514                 remaining_bytes -= valid_bytes + 1;
515                 remainder = invalid + 1;
516         }
517
518         if (string == NULL)
519                 return g_strndup ((gchar *) data, data_bytes);
520
521         g_string_append (string, remainder);
522
523         g_warn_if_fail (g_utf8_validate (string->str, -1, NULL));
524
525         return g_string_free (string, FALSE);
526 }
527
528 /**
529  * e_util_utf8_normalize:
530  * @str: a UTF-8 string
531  *
532  * Normalizes @str by making it all lower case and removing any accents from it.
533  *
534  * Returns: The normalized version of @str, or %NULL if @str was not valid UTF-8
535  *
536  * Since: 3.8
537  */
538 gchar *
539 e_util_utf8_normalize (const gchar *str)
540 {
541         gchar *valid = NULL;
542         gchar *normal, *casefolded = NULL;
543
544         if (str == NULL)
545                 return NULL;
546
547         if (!g_utf8_validate (str, -1, NULL)) {
548                 valid = e_util_utf8_make_valid (str);
549                 str = valid;
550         }
551
552         normal = e_util_utf8_remove_accents (str);
553         if (normal)
554                 casefolded = g_utf8_casefold (normal, -1);
555
556         g_free (valid);
557         g_free (normal);
558
559         return casefolded;
560 }
561
562 /**
563  * e_util_ensure_gdbus_string:
564  * @str: a possibly invalid UTF-8 string, or %NULL
565  * @gdbus_str: return location for the corrected string
566  *
567  * If @str is a valid UTF-8 string, the function returns @str and does
568  * not set @gdbus_str.
569  *
570  * If @str is an invalid UTF-8 string, the function calls
571  * e_util_utf8_make_valid() and points @gdbus_str to the newly-allocated,
572  * valid UTF-8 string, and also returns it.  The caller should free the
573  * string pointed to by @gdbus_str with g_free().
574  *
575  * If @str is %NULL, the function returns an empty string and does not
576  * set @gdbus_str.
577  *
578  * Admittedly, the function semantics are a little awkward.  The example
579  * below illustrates the easiest way to cope with the @gdbus_str argument:
580  *
581  * <informalexample>
582  *   <programlisting>
583  *     const gchar *trusted_utf8;
584  *     gchar *allocated = NULL;
585  *
586  *     trusted_utf8 = e_util_ensure_gdbus_string (untrusted_utf8, &allocated);
587  *
588  *     Do stuff with trusted_utf8, then clear it.
589  *
590  *     trusted_utf8 = NULL;
591  *
592  *     g_free (allocated);
593  *     allocated = NULL;
594  *   </programlisting>
595  * </informalexample>
596  *
597  * Returns: a valid UTF-8 string
598  *
599  * Since: 3.0
600  **/
601 const gchar *
602 e_util_ensure_gdbus_string (const gchar *str,
603                             gchar **gdbus_str)
604 {
605         g_return_val_if_fail (gdbus_str != NULL, NULL);
606
607         *gdbus_str = NULL;
608
609         if (!str || !*str)
610                 return "";
611
612         if (g_utf8_validate (str, -1, NULL))
613                 return str;
614
615         *gdbus_str = e_util_utf8_make_valid (str);
616
617         return *gdbus_str;
618 }
619
620 /**
621  * e_strftime:
622  * @string: The string array to store the result in.
623  * @max: The size of array @s.
624  * @fmt: The formatting to use on @tm.
625  * @tm: The time value to format.
626  *
627  * This function is a wrapper around the strftime (3) function, which
628  * converts the &percnt;l and &percnt;k (12h and 24h) format variables
629  * if necessary.
630  *
631  * Returns: The number of characters placed in @s.
632  **/
633 gsize
634 e_strftime (gchar *string,
635             gsize max,
636             const gchar *fmt,
637             const struct tm *tm)
638 {
639 #ifndef HAVE_LKSTRFTIME
640         gchar *c, *ffmt, *ff;
641 #endif
642         gsize ret;
643
644         g_return_val_if_fail (string != NULL, 0);
645         g_return_val_if_fail (fmt != NULL, 0);
646         g_return_val_if_fail (tm != NULL, 0);
647
648 #ifdef HAVE_LKSTRFTIME
649         ret = strftime (string, max, fmt, tm);
650 #else
651         ffmt = g_strdup (fmt);
652         ff = ffmt;
653         while ((c = strstr (ff, "%l")) != NULL) {
654                 c[1] = 'I';
655                 ff = c;
656         }
657
658         ff = ffmt;
659         while ((c = strstr (ff, "%k")) != NULL) {
660                 c[1] = 'H';
661                 ff = c;
662         }
663
664 #ifdef G_OS_WIN32
665         /* The Microsoft strftime () doesn't have %e either */
666         ff = ffmt;
667         while ((c = strstr (ff, "%e")) != NULL) {
668                 c[1] = 'd';
669                 ff = c;
670         }
671 #endif
672
673         ret = strftime (string, max, ffmt, tm);
674         g_free (ffmt);
675 #endif
676
677         if (ret == 0 && max > 0)
678                 string[0] = '\0';
679
680         return ret;
681 }
682
683 /**
684  * e_utf8_strftime:
685  * @string: The string array to store the result in.
686  * @max: The size of array @s.
687  * @fmt: The formatting to use on @tm.
688  * @tm: The time value to format.
689  *
690  * The UTF-8 equivalent of e_strftime ().
691  *
692  * Returns: The number of characters placed in @s.
693  **/
694 gsize
695 e_utf8_strftime (gchar *string,
696                  gsize max,
697                  const gchar *fmt,
698                  const struct tm *tm)
699 {
700         gsize sz, ret;
701         gchar *locale_fmt, *buf;
702
703         g_return_val_if_fail (string != NULL, 0);
704         g_return_val_if_fail (fmt != NULL, 0);
705         g_return_val_if_fail (tm != NULL, 0);
706
707         locale_fmt = g_locale_from_utf8 (fmt, -1, NULL, &sz, NULL);
708         if (!locale_fmt)
709                 return 0;
710
711         ret = e_strftime (string, max, locale_fmt, tm);
712         if (!ret) {
713                 g_free (locale_fmt);
714                 return 0;
715         }
716
717         buf = g_locale_to_utf8 (string, ret, NULL, &sz, NULL);
718         if (!buf) {
719                 g_free (locale_fmt);
720                 return 0;
721         }
722
723         if (sz >= max) {
724                 gchar *tmp = buf + max - 1;
725                 tmp = g_utf8_find_prev_char (buf, tmp);
726                 if (tmp)
727                         sz = tmp - buf;
728                 else
729                         sz = 0;
730         }
731
732         memcpy (string, buf, sz);
733         string[sz] = '\0';
734
735         g_free (locale_fmt);
736         g_free (buf);
737
738         return sz;
739 }
740
741 /**
742  * e_util_gthread_id:
743  * @thread: A #GThread pointer
744  *
745  * Returns a 64-bit integer hopefully uniquely identifying the
746  * thread. To be used in debugging output and logging only.
747  * The returned value is just a cast of a pointer to the 64-bit integer.
748  *
749  * There is no guarantee that calling e_util_gthread_id () on one
750  * thread first and later after that thread has dies on another won't
751  * return the same integer.
752  *
753  * On Linux and Win32, known to really return a unique id for each
754  * thread existing at a certain time. No guarantee that ids won't be
755  * reused after a thread has terminated, though.
756  *
757  * Returns: A 64-bit integer.
758  *
759  * Since: 2.32
760  */
761 guint64
762 e_util_gthread_id (GThread *thread)
763 {
764 #if GLIB_SIZEOF_VOID_P == 8
765         /* 64-bit Windows */
766         return (guint64) thread;
767 #else
768         return (gint) thread;
769 #endif
770 }
771
772 /* This only makes a filename safe for usage as a filename.
773  * It still may have shell meta-characters in it. */
774
775 /* This code is rather misguided and mostly pointless, but can't be
776  * changed because of backward compatibility, I guess.
777  *
778  * It replaces some perfectly safe characters like '%' with an
779  * underscore. (Recall that on Unix, the only bytes not allowed in a
780  * file name component are '\0' and '/'.) On the other hand, the UTF-8
781  * for a printable non-ASCII Unicode character (that thus consists of
782  * several very nonprintable non-ASCII bytes) is let through as
783  * such. But those bytes are of course also allowed in filenames, so
784  * it doesn't matter as such...
785  */
786 void
787 e_filename_make_safe (gchar *string)
788 {
789         gchar *p, *ts;
790         gunichar c;
791 #ifdef G_OS_WIN32
792         const gchar *unsafe_chars = " /'\"`&();|<>$%{}!\\:*?#";
793 #else
794         const gchar *unsafe_chars = " /'\"`&();|<>$%{}!#";
795 #endif
796
797         g_return_if_fail (string != NULL);
798
799         p = string;
800
801         while (p && *p) {
802                 c = g_utf8_get_char (p);
803                 ts = p;
804                 p = g_utf8_next_char (p);
805                 /* I wonder what this code is supposed to actually
806                  * achieve, and whether it does that as currently
807                  * written?
808                  */
809                 if (!g_unichar_isprint (c) ||
810                         (c < 0xff && strchr (unsafe_chars, c & 0xff))) {
811                         while (ts < p)
812                                 *ts++ = '_';
813                 }
814         }
815 }
816
817 /**
818  * e_filename_mkdir_encoded:
819  * @basepath: base path of a file name; this is left unchanged
820  * @fileprefix: prefix for the filename; this is encoded
821  * @filename: file name to use; this is encoded; can be %NULL
822  * @fileindex: used when @filename is NULL, then the filename
823  *        is generated as "file" + fileindex
824  *
825  * Creates a local path constructed from @basepath / @fileprefix + "-" + @filename,
826  * and makes sure the path @basepath exists. If creation of
827  * the path fails, then NULL is returned.
828  *
829  * Returns: Full local path like g_build_filename() except that @fileprefix
830  * and @filename are encoded to create a proper file elements for
831  * a file system. Free returned pointer with g_free().
832  *
833  * Since: 3.4
834  **/
835 gchar *
836 e_filename_mkdir_encoded (const gchar *basepath,
837                           const gchar *fileprefix,
838                           const gchar *filename,
839                           gint fileindex)
840 {
841         gchar *elem1, *elem2, *res, *fn;
842
843         g_return_val_if_fail (basepath != NULL, NULL);
844         g_return_val_if_fail (*basepath != 0, NULL);
845         g_return_val_if_fail (fileprefix != NULL, NULL);
846         g_return_val_if_fail (*fileprefix != 0, NULL);
847         g_return_val_if_fail (!filename || *filename, NULL);
848
849         if (g_mkdir_with_parents (basepath, 0700) < 0)
850                 return NULL;
851
852         elem1 = g_strdup (fileprefix);
853         if (filename)
854                 elem2 = g_strdup (filename);
855         else
856                 elem2 = g_strdup_printf ("file%d", fileindex);
857
858         e_filename_make_safe (elem1);
859         e_filename_make_safe (elem2);
860
861         fn = g_strconcat (elem1, "-", elem2, NULL);
862
863         res = g_build_filename (basepath, fn, NULL);
864
865         g_free (fn);
866         g_free (elem1);
867         g_free (elem2);
868
869         return res;
870 }
871
872 /**
873  * e_util_slist_to_strv:
874  * @strings: (element-type utf8): a #GSList of strings (const gchar *)
875  *
876  * Convert list of strings into NULL-terminates array of strings.
877  *
878  * Returns: (transfer full): Newly allocated %NULL-terminated array of strings.
879  * Returned pointer should be freed with g_strfreev().
880  *
881  * Note: Pair function for this is e_util_strv_to_slist().
882  *
883  * Since: 3.4
884  **/
885 gchar **
886 e_util_slist_to_strv (const GSList *strings)
887 {
888         const GSList *iter;
889         GPtrArray *array;
890
891         array = g_ptr_array_sized_new (g_slist_length ((GSList *) strings) + 1);
892
893         for (iter = strings; iter; iter = iter->next) {
894                 const gchar *str = iter->data;
895
896                 if (str)
897                         g_ptr_array_add (array, g_strdup (str));
898         }
899
900         /* NULL-terminated */
901         g_ptr_array_add (array, NULL);
902
903         return (gchar **) g_ptr_array_free (array, FALSE);
904 }
905
906 /**
907  * e_util_strv_to_slist:
908  * @strv: a NULL-terminated array of strings (const gchar *)
909  *
910  * Convert NULL-terminated array of strings to a list of strings.
911  *
912  * Returns: (transfer full) (element-type utf8): Newly allocated #GSList of
913  * newly allocated strings. The returned pointer should be freed with
914  * e_util_free_string_slist().
915  *
916  * Note: Pair function for this is e_util_slist_to_strv().
917  *
918  * Since: 3.4
919  **/
920 GSList *
921 e_util_strv_to_slist (const gchar * const *strv)
922 {
923         GSList *slist = NULL;
924         gint ii;
925
926         if (!strv)
927                 return NULL;
928
929         for (ii = 0; strv[ii]; ii++) {
930                 slist = g_slist_prepend (slist, g_strdup (strv[ii]));
931         }
932
933         return g_slist_reverse (slist);
934 }
935
936 /**
937  * e_util_copy_string_slist:
938  * @copy_to: (element-type utf8) (allow-none): Where to copy; can be %NULL
939  * @strings: (element-type utf8): #GSList of strings to be copied
940  *
941  * Copies #GSList of strings at the end of @copy_to.
942  *
943  * Returns: (transfer full) (element-type utf8): New head of @copy_to.
944  * Returned pointer can be freed with e_util_free_string_slist().
945  *
946  * Since: 3.4
947  *
948  * Deprecated: 3.8: Use g_slist_copy_deep() instead, and optionally
949  *                  g_slist_concat() to concatenate the copied list
950  *                  to another #GSList.
951  **/
952 GSList *
953 e_util_copy_string_slist (GSList *copy_to,
954                           const GSList *strings)
955 {
956         GSList *copied_list;
957
958         copied_list = g_slist_copy_deep (
959                 (GSList *) strings, (GCopyFunc) g_strdup, NULL);
960
961         return g_slist_concat (copy_to, copied_list);
962 }
963
964 /**
965  * e_util_copy_object_slist:
966  * @copy_to: (element-type GObject) (allow-none): Where to copy; can be %NULL
967  * @objects: (element-type GObject): #GSList of #GObject<!-- -->s to be copied
968  *
969  * Copies #GSList of #GObject<!-- -->s at the end of @copy_to.
970  *
971  * Returns: (transfer full) (element-type GObject): New head of @copy_to.
972  * Returned pointer can be freed with e_util_free_object_slist().
973  *
974  * Since: 3.4
975  *
976  * Deprecated: 3.8: Use g_slist_copy_deep() instead, and optionally
977  *                  g_slist_concat() to concatenate the copied list
978  *                  to another #GSList.
979  **/
980 GSList *
981 e_util_copy_object_slist (GSList *copy_to,
982                           const GSList *objects)
983 {
984         GSList *copied_list;
985
986         copied_list = g_slist_copy_deep (
987                 (GSList *) objects, (GCopyFunc) g_object_ref, NULL);
988
989         return g_slist_concat (copy_to, copied_list);
990 }
991
992 /**
993  * e_util_free_string_slist:
994  * @strings: (element-type utf8): a #GSList of strings (gchar *)
995  *
996  * Frees memory previously allocated by e_util_strv_to_slist().
997  *
998  * Since: 3.4
999  *
1000  * Deprecated: 3.8: Use g_slist_free_full() instead.
1001  **/
1002 void
1003 e_util_free_string_slist (GSList *strings)
1004 {
1005         g_slist_free_full (strings, (GDestroyNotify) g_free);
1006 }
1007
1008 /**
1009  * e_util_free_object_slist:
1010  * @objects: (element-type GObject): a #GSList of #GObject<!-- -->s
1011  *
1012  * Calls g_object_unref() on each member of @objects and then frees
1013  * also @objects itself.
1014  *
1015  * Since: 3.4
1016  *
1017  * Deprecated: 3.8: Use g_slist_free_full() instead.
1018  **/
1019 void
1020 e_util_free_object_slist (GSList *objects)
1021 {
1022         g_slist_free_full (objects, (GDestroyNotify) g_object_unref);
1023 }
1024
1025 /**
1026  * e_util_free_nullable_object_slist:
1027  * @objects: (element-type GObject): a #GSList of nullable #GObject<!-- -->s
1028  *
1029  * Calls g_object_unref() on each member of @objects if non-%NULL and then frees
1030  * also @objects itself.
1031  *
1032  * Since: 3.6
1033  **/
1034 void
1035 e_util_free_nullable_object_slist (GSList *objects)
1036 {
1037         const GSList *l;
1038         for (l = objects; l; l = l->next) {
1039                 if (l->data)
1040                         g_object_unref (l->data);
1041         }
1042         g_slist_free (objects);
1043 }
1044
1045 /**
1046  * e_queue_transfer:
1047  * @src_queue: a source #GQueue
1048  * @dst_queue: a destination #GQueue
1049  *
1050  * Transfers the contents of @src_queue to the tail of @dst_queue.
1051  * When the operation is complete, @src_queue will be empty.
1052  *
1053  * Since: 3.8
1054  **/
1055 void
1056 e_queue_transfer (GQueue *src_queue,
1057                   GQueue *dst_queue)
1058 {
1059         g_return_if_fail (src_queue != NULL);
1060         g_return_if_fail (dst_queue != NULL);
1061
1062         dst_queue->head = g_list_concat (dst_queue->head, src_queue->head);
1063         dst_queue->tail = g_list_last (dst_queue->head);
1064         dst_queue->length += src_queue->length;
1065
1066         src_queue->head = NULL;
1067         src_queue->tail = NULL;
1068         src_queue->length = 0;
1069 }
1070
1071 /* Helper for e_file_recursive_delete() */
1072 static void
1073 file_recursive_delete_thread (GSimpleAsyncResult *simple,
1074                               GObject *object,
1075                               GCancellable *cancellable)
1076 {
1077         GError *error = NULL;
1078
1079         e_file_recursive_delete_sync (G_FILE (object), cancellable, &error);
1080
1081         if (error != NULL)
1082                 g_simple_async_result_take_error (simple, error);
1083 }
1084
1085 /**
1086  * e_file_recursive_delete_sync:
1087  * @file: a #GFile to delete
1088  * @cancellable: optional #GCancellable object, or %NULL
1089  * @error: return location for a #GError, or %NULL
1090  *
1091  * Deletes @file.  If @file is a directory, its contents are deleted
1092  * recursively before @file itself is deleted.  The recursive delete
1093  * operation will stop on the first error.
1094  *
1095  * If @cancellable is not %NULL, then the operation can be cancelled
1096  * by triggering the cancellable object from another thread.  If the
1097  * operation was cancelled, the error #G_IO_ERROR_CANCELLED will be
1098  * returned.
1099  *
1100  * Returns: %TRUE if the file was deleted, %FALSE otherwise
1101  *
1102  * Since: 3.6
1103  **/
1104 gboolean
1105 e_file_recursive_delete_sync (GFile *file,
1106                               GCancellable *cancellable,
1107                               GError **error)
1108 {
1109         GFileEnumerator *file_enumerator;
1110         GFileInfo *file_info;
1111         GFileType file_type;
1112         gboolean success = TRUE;
1113         GError *local_error = NULL;
1114
1115         g_return_val_if_fail (G_IS_FILE (file), FALSE);
1116
1117         file_type = g_file_query_file_type (
1118                 file, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, cancellable);
1119
1120         /* If this is not a directory, delete like normal. */
1121         if (file_type != G_FILE_TYPE_DIRECTORY)
1122                 return g_file_delete (file, cancellable, error);
1123
1124         /* Note, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS is critical here
1125          * so we only delete files inside the directory being deleted. */
1126         file_enumerator = g_file_enumerate_children (
1127                 file, G_FILE_ATTRIBUTE_STANDARD_NAME,
1128                 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
1129                 cancellable, error);
1130
1131         if (file_enumerator == NULL)
1132                 return FALSE;
1133
1134         file_info = g_file_enumerator_next_file (
1135                 file_enumerator, cancellable, &local_error);
1136
1137         while (file_info != NULL) {
1138                 GFile *child;
1139                 const gchar *name;
1140
1141                 name = g_file_info_get_name (file_info);
1142
1143                 /* Here's the recursive part. */
1144                 child = g_file_get_child (file, name);
1145                 success = e_file_recursive_delete_sync (
1146                         child, cancellable, error);
1147                 g_object_unref (child);
1148
1149                 g_object_unref (file_info);
1150
1151                 if (!success)
1152                         break;
1153
1154                 file_info = g_file_enumerator_next_file (
1155                         file_enumerator, cancellable, &local_error);
1156         }
1157
1158         if (local_error != NULL) {
1159                 g_propagate_error (error, local_error);
1160                 success = FALSE;
1161         }
1162
1163         g_object_unref (file_enumerator);
1164
1165         if (!success)
1166                 return FALSE;
1167
1168         /* The directory should be empty now. */
1169         return g_file_delete (file, cancellable, error);
1170 }
1171
1172 /**
1173  * e_file_recursive_delete:
1174  * @file: a #GFile to delete
1175  * @io_priority: the I/O priority of the request
1176  * @cancellable: optional #GCancellable object, or %NULL
1177  * @callback: a #GAsyncReadyCallback to call when the request is satisfied
1178  * @user_data: data to pass to the callback function
1179  *
1180  * Asynchronously deletes @file.  If @file is a directory, its contents
1181  * are deleted recursively before @file itself is deleted.  The recursive
1182  * delete operation will stop on the first error.
1183  *
1184  * If @cancellable is not %NULL, then the operation can be cancelled
1185  * by triggering the cancellable object before the operation finishes.
1186  *
1187  * When the operation is finished, @callback will be called.  You can then
1188  * call e_file_recursive_delete_finish() to get the result of the operation.
1189  *
1190  * Since: 3.6
1191  **/
1192 void
1193 e_file_recursive_delete (GFile *file,
1194                          gint io_priority,
1195                          GCancellable *cancellable,
1196                          GAsyncReadyCallback callback,
1197                          gpointer user_data)
1198 {
1199         GSimpleAsyncResult *simple;
1200
1201         g_return_if_fail (G_IS_FILE (file));
1202
1203         simple = g_simple_async_result_new (
1204                 G_OBJECT (file), callback, user_data,
1205                 e_file_recursive_delete);
1206
1207         g_simple_async_result_set_check_cancellable (simple, cancellable);
1208
1209         g_simple_async_result_run_in_thread (
1210                 simple, file_recursive_delete_thread,
1211                 io_priority, cancellable);
1212
1213         g_object_unref (simple);
1214 }
1215
1216 /**
1217  * e_file_recursive_delete_finish:
1218  * @file: a #GFile to delete
1219  * @result: a #GAsyncResult
1220  * @error: return location for a #GError, or %NULL
1221  *
1222  * Finishes the operation started with e_file_recursive_delete().
1223  *
1224  * If the operation was cancelled, the error #G_IO_ERROR_CANCELLED will be
1225  * returned.
1226  *
1227  * Returns: %TRUE if the file was deleted, %FALSE otherwise
1228  *
1229  * Since: 3.6
1230  **/
1231 gboolean
1232 e_file_recursive_delete_finish (GFile *file,
1233                                 GAsyncResult *result,
1234                                 GError **error)
1235 {
1236         GSimpleAsyncResult *simple;
1237
1238         g_return_val_if_fail (
1239                 g_simple_async_result_is_valid (
1240                 result, G_OBJECT (file), e_file_recursive_delete), FALSE);
1241
1242         simple = G_SIMPLE_ASYNC_RESULT (result);
1243
1244         /* Assume success unless a GError is set. */
1245         return !g_simple_async_result_propagate_error (simple, error);
1246 }
1247
1248 /**
1249  * e_binding_transform_enum_value_to_nick:
1250  * @binding: a #GBinding
1251  * @source_value: a #GValue whose type is derived from #G_TYPE_ENUM
1252  * @target_value: a #GValue of type #G_TYPE_STRING
1253  * @not_used: not used
1254  *
1255  * Transforms an enumeration value to its corresponding nickname.
1256  *
1257  * Returns: %TRUE if the enum value has a corresponding nickname
1258  *
1259  * Since: 3.4
1260  **/
1261 gboolean
1262 e_binding_transform_enum_value_to_nick (GBinding *binding,
1263                                         const GValue *source_value,
1264                                         GValue *target_value,
1265                                         gpointer not_used)
1266 {
1267         GEnumClass *enum_class;
1268         GEnumValue *enum_value;
1269         gint value;
1270         gboolean success = FALSE;
1271
1272         g_return_val_if_fail (G_IS_BINDING (binding), FALSE);
1273
1274         enum_class = g_type_class_peek (G_VALUE_TYPE (source_value));
1275         g_return_val_if_fail (G_IS_ENUM_CLASS (enum_class), FALSE);
1276
1277         value = g_value_get_enum (source_value);
1278         enum_value = g_enum_get_value (enum_class, value);
1279         if (enum_value != NULL) {
1280                 g_value_set_string (target_value, enum_value->value_nick);
1281                 success = TRUE;
1282         }
1283
1284         return success;
1285 }
1286
1287 /**
1288  * e_binding_transform_enum_nick_to_value:
1289  * @binding: a #GBinding
1290  * @source_value: a #GValue of type #G_TYPE_STRING
1291  * @target_value: a #GValue whose type is derived from #G_TYPE_ENUM
1292  * @not_used: not used
1293  *
1294  * Transforms an enumeration nickname to its corresponding value.
1295  *
1296  * Returns: %TRUE if the enum nickname has a corresponding value
1297  *
1298  * Since: 3.4
1299  **/
1300 gboolean
1301 e_binding_transform_enum_nick_to_value (GBinding *binding,
1302                                         const GValue *source_value,
1303                                         GValue *target_value,
1304                                         gpointer not_used)
1305 {
1306         GEnumClass *enum_class;
1307         GEnumValue *enum_value;
1308         const gchar *string;
1309         gboolean success = FALSE;
1310
1311         g_return_val_if_fail (G_IS_BINDING (binding), FALSE);
1312
1313         enum_class = g_type_class_peek (G_VALUE_TYPE (target_value));
1314         g_return_val_if_fail (G_IS_ENUM_CLASS (enum_class), FALSE);
1315
1316         string = g_value_get_string (source_value);
1317         enum_value = g_enum_get_value_by_nick (enum_class, string);
1318         if (enum_value != NULL) {
1319                 g_value_set_enum (target_value, enum_value->value);
1320                 success = TRUE;
1321         }
1322
1323         return success;
1324 }
1325
1326 /**
1327  * e_enum_from_string:
1328  * @enum_type: The enum type
1329  * @string: The string containing the enum value or nick
1330  * @enum_value: A return location to store the result
1331  *
1332  * Fetches the appropriate enumeration value for @string in the given
1333  * enum type @type and stores the result in @enum_value
1334  *
1335  * Returns: %TRUE if the string was a valid name or nick
1336  *        for the given @type, %FALSE if the conversion failed.
1337  *
1338  * Since: 3.8
1339  */
1340 gboolean
1341 e_enum_from_string (GType enum_type,
1342                     const gchar *string,
1343                     gint *enum_value)
1344 {
1345         GEnumClass *enum_class;
1346         GEnumValue *ev;
1347         gchar *endptr;
1348         gint value;
1349         gboolean retval = TRUE;
1350
1351         g_return_val_if_fail (G_TYPE_IS_ENUM (enum_type), FALSE);
1352         g_return_val_if_fail (string != NULL, FALSE);
1353
1354         value = g_ascii_strtoull (string, &endptr, 0);
1355         if (endptr != string)
1356                 /* parsed a number */
1357                 *enum_value = value;
1358         else {
1359                 enum_class = g_type_class_ref (enum_type);
1360                 ev = g_enum_get_value_by_name (enum_class, string);
1361                 if (!ev)
1362                         ev = g_enum_get_value_by_nick (enum_class, string);
1363
1364                 if (ev)
1365                         *enum_value = ev->value;
1366                 else
1367                         retval = FALSE;
1368
1369                 g_type_class_unref (enum_class);
1370         }
1371
1372         return retval;
1373 }
1374
1375 /**
1376  * e_enum_to_string:
1377  * @enum_type: An enum type
1378  * @enum_value: The enum value to convert
1379  *
1380  * Converts an enum value to a string using strings from the GType system.
1381  *
1382  * Returns: the string representing @eval
1383  *
1384  * Since: 3.8
1385  */
1386 const gchar *
1387 e_enum_to_string (GType enum_type,
1388                   gint enum_value)
1389 {
1390         GEnumClass *enum_class;
1391         const gchar *string = NULL;
1392         guint i;
1393
1394         enum_class = g_type_class_ref (enum_type);
1395
1396         g_return_val_if_fail (enum_class != NULL, NULL);
1397
1398         for (i = 0; i < enum_class->n_values; i++) {
1399                 if (enum_value == enum_class->values[i].value) {
1400                         string = enum_class->values[i].value_nick;
1401                         break;
1402                 }
1403         }
1404
1405         g_type_class_unref (enum_class);
1406
1407         return string;
1408 }
1409
1410 /**
1411  * EAsyncClosure:
1412  *
1413  * #EAsyncClosure provides a simple way to run an asynchronous function
1414  * synchronously without blocking a running #GMainLoop or using threads.
1415  *
1416  * 1) Create an #EAsyncClosure with e_async_closure_new().
1417  *
1418  * 2) Call the asynchronous function passing e_async_closure_callback() as
1419  *    the #GAsyncReadyCallback argument and the #EAsyncClosure as the data
1420  *    argument.
1421  *
1422  * 3) Call e_async_closure_wait() and collect the #GAsyncResult.
1423  *
1424  * 4) Call the corresponding asynchronous "finish" function, passing the
1425  *    #GAsyncResult returned by e_async_closure_wait().
1426  *
1427  * 5) If needed, repeat steps 2-4 for additional asynchronous functions
1428  *    using the same #EAsyncClosure.
1429  *
1430  * 6) Finally, free the #EAsyncClosure with e_async_closure_free().
1431  *
1432  * Since: 3.6
1433  **/
1434 struct _EAsyncClosure {
1435         GMainLoop *loop;
1436         GMainContext *context;
1437         GAsyncResult *result;
1438 };
1439
1440 /**
1441  * e_async_closure_new:
1442  *
1443  * Creates a new #EAsyncClosure for use with asynchronous functions.
1444  *
1445  * Returns: a new #EAsyncClosure
1446  *
1447  * Since: 3.6
1448  **/
1449 EAsyncClosure *
1450 e_async_closure_new (void)
1451 {
1452         EAsyncClosure *closure;
1453
1454         closure = g_slice_new0 (EAsyncClosure);
1455         closure->context = g_main_context_new ();
1456         closure->loop = g_main_loop_new (closure->context, FALSE);
1457
1458         g_main_context_push_thread_default (closure->context);
1459
1460         return closure;
1461 }
1462
1463 /**
1464  * e_async_closure_wait:
1465  * @closure: an #EAsyncClosure
1466  *
1467  * Call this function immediately after starting an asynchronous operation.
1468  * The function waits for the asynchronous operation to complete and returns
1469  * its #GAsyncResult to be passed to the operation's "finish" function.
1470  *
1471  * This function can be called repeatedly on the same #EAsyncClosure to
1472  * easily string together multiple asynchronous operations.
1473  *
1474  * Returns: (transfer none): a #GAsyncResult which is owned by the closure
1475  *
1476  * Since: 3.6
1477  **/
1478 GAsyncResult *
1479 e_async_closure_wait (EAsyncClosure *closure)
1480 {
1481         g_return_val_if_fail (closure != NULL, NULL);
1482
1483         g_main_loop_run (closure->loop);
1484
1485         return closure->result;
1486 }
1487
1488 /**
1489  * e_async_closure_free:
1490  * @closure: an #EAsyncClosure
1491  *
1492  * Frees the @closure and the resources it holds.
1493  *
1494  * Since: 3.6
1495  **/
1496 void
1497 e_async_closure_free (EAsyncClosure *closure)
1498 {
1499         g_return_if_fail (closure != NULL);
1500
1501         g_main_context_pop_thread_default (closure->context);
1502
1503         g_main_loop_unref (closure->loop);
1504         g_main_context_unref (closure->context);
1505
1506         if (closure->result != NULL)
1507                 g_object_unref (closure->result);
1508
1509         g_slice_free (EAsyncClosure, closure);
1510 }
1511
1512 /**
1513  * e_async_closure_callback:
1514  * @object: a #GObject or %NULL, it is not used by the function at all
1515  * @result: a #GAsyncResult
1516  * @closure: an #EAsyncClosure
1517  *
1518  * Pass this function as the #GAsyncReadyCallback argument of an asynchronous
1519  * function, and the #EAsyncClosure as the data argument.
1520  *
1521  * This causes e_async_closure_wait() to terminate and return @result.
1522  *
1523  * Since: 3.6
1524  **/
1525 void
1526 e_async_closure_callback (GObject *object,
1527                           GAsyncResult *result,
1528                           gpointer closure)
1529 {
1530         EAsyncClosure *real_closure;
1531
1532         g_return_if_fail (G_IS_ASYNC_RESULT (result));
1533         g_return_if_fail (closure != NULL);
1534
1535         real_closure = closure;
1536
1537         /* Replace any previous result. */
1538         if (real_closure->result != NULL)
1539                 g_object_unref (real_closure->result);
1540         real_closure->result = g_object_ref (result);
1541
1542         g_main_loop_quit (real_closure->loop);
1543 }
1544
1545 #ifdef G_OS_WIN32
1546
1547 #include <windows.h>
1548
1549 static const gchar *prefix = NULL;
1550 static const gchar *cp_prefix;
1551
1552 static const gchar *localedir;
1553 static const gchar *extensiondir;
1554 static const gchar *imagesdir;
1555 static const gchar *ui_uidir;
1556
1557 static HMODULE hmodule;
1558 G_LOCK_DEFINE_STATIC (mutex);
1559
1560 /* Silence gcc with a prototype. Yes, this is silly. */
1561 BOOL WINAPI DllMain (HINSTANCE hinstDLL,
1562                      DWORD     fdwReason,
1563                      LPVOID    lpvReserved);
1564
1565 /* Minimal DllMain that just tucks away the DLL's HMODULE */
1566 BOOL WINAPI
1567 DllMain (HINSTANCE hinstDLL,
1568          DWORD fdwReason,
1569          LPVOID lpvReserved)
1570 {
1571         switch (fdwReason) {
1572         case DLL_PROCESS_ATTACH:
1573                 hmodule = hinstDLL;
1574                 break;
1575         }
1576         return TRUE;
1577 }
1578
1579 gchar *
1580 e_util_replace_prefix (const gchar *configure_time_prefix,
1581                        const gchar *runtime_prefix,
1582                        const gchar *configure_time_path)
1583 {
1584         gchar *c_t_prefix_slash;
1585         gchar *retval;
1586
1587         c_t_prefix_slash = g_strconcat (configure_time_prefix, "/", NULL);
1588
1589         if (runtime_prefix &&
1590             g_str_has_prefix (configure_time_path, c_t_prefix_slash)) {
1591                 retval = g_strconcat (
1592                         runtime_prefix,
1593                         configure_time_path + strlen (configure_time_prefix),
1594                         NULL);
1595         } else
1596                 retval = g_strdup (configure_time_path);
1597
1598         g_free (c_t_prefix_slash);
1599
1600         return retval;
1601 }
1602
1603 static gchar *
1604 replace_prefix (const gchar *runtime_prefix,
1605                 const gchar *configure_time_path)
1606 {
1607         return e_util_replace_prefix (
1608                 E_DATA_SERVER_PREFIX, runtime_prefix, configure_time_path);
1609 }
1610
1611 static void
1612 setup (void)
1613 {
1614         gchar *full_pfx;
1615         gchar *cp_pfx;
1616
1617         G_LOCK (mutex);
1618         if (prefix != NULL) {
1619                 G_UNLOCK (mutex);
1620                 return;
1621         }
1622
1623         /* This requires that the libedataserver DLL is installed in $bindir */
1624         full_pfx = g_win32_get_package_installation_directory_of_module (hmodule);
1625         cp_pfx = g_win32_locale_filename_from_utf8 (full_pfx);
1626
1627         prefix = g_strdup (full_pfx);
1628         cp_prefix = g_strdup (cp_pfx);
1629
1630         g_free (full_pfx);
1631         g_free (cp_pfx);
1632
1633         localedir = replace_prefix (cp_prefix, E_DATA_SERVER_LOCALEDIR);
1634         extensiondir = replace_prefix (prefix, E_DATA_SERVER_EXTENSIONDIR);
1635         imagesdir = replace_prefix (prefix, E_DATA_SERVER_IMAGESDIR);
1636         ui_uidir = replace_prefix (prefix, E_DATA_SERVER_UI_UIDIR);
1637
1638         G_UNLOCK (mutex);
1639 }
1640
1641 #include "libedataserver-private.h" /* For prototypes */
1642
1643 #define GETTER_IMPL(varbl)                      \
1644 {                                               \
1645         setup ();                               \
1646         return varbl;                           \
1647 }
1648
1649 #define PRIVATE_GETTER(varbl)                   \
1650 const gchar *                                   \
1651 _libedataserver_get_##varbl (void)              \
1652         GETTER_IMPL (varbl)
1653
1654 #define PUBLIC_GETTER(varbl)                    \
1655 const gchar *                                   \
1656 e_util_get_##varbl (void)                       \
1657         GETTER_IMPL (varbl)
1658
1659 PRIVATE_GETTER (extensiondir)
1660 PRIVATE_GETTER (imagesdir)
1661 PRIVATE_GETTER (ui_uidir)
1662
1663 PUBLIC_GETTER (prefix)
1664 PUBLIC_GETTER (cp_prefix)
1665 PUBLIC_GETTER (localedir)
1666
1667 #endif  /* G_OS_WIN32 */
1668
1669 static gint default_dbus_timeout = -1;
1670
1671 /**
1672  * e_data_server_util_set_dbus_call_timeout:
1673  * @timeout_msec: default timeout for D-Bus calls in miliseconds
1674  *
1675  * Sets default timeout, in milliseconds, for calls of g_dbus_proxy_call()
1676  * family functions.
1677  *
1678  * -1 means the default value as set by D-Bus itself.
1679  * G_MAXINT means no timeout at all.
1680  *
1681  * Default value is set also by configure option --with-dbus-call-timeout=ms
1682  * and -1 is used when not set.
1683  *
1684  * Since: 3.0
1685  *
1686  * Deprecated: 3.8: This value is not used anywhere.
1687  **/
1688 void
1689 e_data_server_util_set_dbus_call_timeout (gint timeout_msec)
1690 {
1691         default_dbus_timeout = timeout_msec;
1692 }
1693
1694 /**
1695  * e_data_server_util_get_dbus_call_timeout:
1696  *
1697  * Returns the value set by e_data_server_util_set_dbus_call_timeout().
1698  *
1699  * Returns: the D-Bus call timeout in milliseconds
1700  *
1701  * Since: 3.0
1702  *
1703  * Deprecated: 3.8: This value is not used anywhere.
1704  **/
1705 gint
1706 e_data_server_util_get_dbus_call_timeout (void)
1707 {
1708         return default_dbus_timeout;
1709 }
1710
1711 /**
1712  * e_named_parameters_new:
1713  *
1714  * Creates a new instance of an #ENamedParameters. This should be freed
1715  * with e_named_parameters_free(), when no longer needed. Names are
1716  * compared case insensitively.
1717  *
1718  * The structure is not thread safe, if the caller requires thread safety,
1719  * then it should provide it on its own.
1720  *
1721  * Returns: newly allocated #ENamedParameters
1722  *
1723  * Since: 3.8
1724  **/
1725 ENamedParameters *
1726 e_named_parameters_new (void)
1727 {
1728         return (ENamedParameters *) g_ptr_array_new_with_free_func (g_free);
1729 }
1730
1731 /**
1732  * e_named_parameters_new_strv:
1733  * @strv: NULL-terminated string array to be used as a content of a newly
1734  *     created #ENamedParameters
1735  *
1736  * Creates a new instance of an #ENamedParameters, with initial content
1737  * being taken from @strv. This should be freed with e_named_parameters_free(),
1738  * when no longer needed. Names are compared case insensitively.
1739  *
1740  * The structure is not thread safe, if the caller requires thread safety,
1741  * then it should provide it on its own.
1742  *
1743  * Returns: newly allocated #ENamedParameters
1744  *
1745  * Since: 3.8
1746  **/
1747 ENamedParameters *
1748 e_named_parameters_new_strv (const gchar * const *strv)
1749 {
1750         ENamedParameters *parameters;
1751         gint ii;
1752
1753         g_return_val_if_fail (strv != NULL, NULL);
1754
1755         parameters = e_named_parameters_new ();
1756         for (ii = 0; strv[ii]; ii++) {
1757                 g_ptr_array_add ((GPtrArray *) parameters, g_strdup (strv[ii]));
1758         }
1759
1760         return parameters;
1761 }
1762
1763 /**
1764  * e_named_parameters_free:
1765  * @parameters: an #ENamedParameters
1766  *
1767  * Frees an instance of #ENamedParameters, previously allocated
1768  * with e_named_parameters_new(). Function does nothing, if
1769  * @parameters is %NULL.
1770  *
1771  * Since: 3.8
1772  **/
1773 void
1774 e_named_parameters_free (ENamedParameters *parameters)
1775 {
1776         if (!parameters)
1777                 return;
1778
1779         g_ptr_array_unref ((GPtrArray *) parameters);
1780 }
1781
1782 /**
1783  * e_named_parameters_clear:
1784  * @parameters: an #ENamedParameters
1785  *
1786  * Removes all stored parameters from @parameters.
1787  *
1788  * Since: 3.8
1789  **/
1790 void
1791 e_named_parameters_clear (ENamedParameters *parameters)
1792 {
1793         GPtrArray *array;
1794         g_return_if_fail (parameters != NULL);
1795
1796         array = (GPtrArray *) parameters;
1797
1798         if (array->len)
1799                 g_ptr_array_remove_range (array, 0, array->len);
1800 }
1801
1802 /**
1803  * e_named_parameters_assign:
1804  * @parameters: an #ENamedParameters to assign values to
1805  * @from: (allow-none): an #ENamedParameters to get values from, or %NULL
1806  *
1807  * Makes content of the @parameters the same as @from.
1808  * Functions clears content of @parameters if @from is %NULL.
1809  *
1810  * Since: 3.8
1811  **/
1812 void
1813 e_named_parameters_assign (ENamedParameters *parameters,
1814                            const ENamedParameters *from)
1815 {
1816         g_return_if_fail (parameters != NULL);
1817
1818         e_named_parameters_clear (parameters);
1819
1820         if (from) {
1821                 gint ii;
1822                 GPtrArray *from_array = (GPtrArray *) from;
1823
1824                 for (ii = 0; ii < from_array->len; ii++) {
1825                         g_ptr_array_add (
1826                                 (GPtrArray *) parameters,
1827                                 g_strdup (from_array->pdata[ii]));
1828                 }
1829         }
1830 }
1831
1832 static gint
1833 get_parameter_index (const ENamedParameters *parameters,
1834                      const gchar *name)
1835 {
1836         GPtrArray *array;
1837         gint ii, name_len;
1838
1839         g_return_val_if_fail (parameters != NULL, -1);
1840         g_return_val_if_fail (name != NULL, -1);
1841
1842         name_len = strlen (name);
1843
1844         array = (GPtrArray *) parameters;
1845
1846         for (ii = 0; ii < array->len; ii++) {
1847                 const gchar *name_and_value = g_ptr_array_index (array, ii);
1848
1849                 if (name_and_value == NULL)
1850                         continue;
1851
1852                 if (name_and_value[name_len] != ':')
1853                         continue;
1854
1855                 if (g_ascii_strncasecmp (name_and_value, name, name_len) == 0)
1856                         return ii;
1857         }
1858
1859         return -1;
1860 }
1861
1862 /**
1863  * e_named_parameters_set:
1864  * @parameters: an #ENamedParameters
1865  * @name: name of a parameter to set
1866  * @value: (allow-none): value to set, or %NULL to unset
1867  *
1868  * Sets parameter named @name to value @value. If @value is NULL,
1869  * then the parameter is removed. @value can be an empty string.
1870  *
1871  * Note: There is a restriction on parameter names, it cannot be empty or
1872  * contain a colon character (':'), otherwise it can be pretty much anything.
1873  *
1874  * Since: 3.8
1875  **/
1876 void
1877 e_named_parameters_set (ENamedParameters *parameters,
1878                         const gchar *name,
1879                         const gchar *value)
1880 {
1881         GPtrArray *array;
1882         gint index;
1883         gchar *name_and_value;
1884
1885         g_return_if_fail (parameters != NULL);
1886         g_return_if_fail (name != NULL);
1887         g_return_if_fail (strchr (name, ':') == NULL);
1888         g_return_if_fail (*name != '\0');
1889
1890         array = (GPtrArray *) parameters;
1891
1892         index = get_parameter_index (parameters, name);
1893         if (!value) {
1894                 if (index != -1)
1895                         g_ptr_array_remove_index (array, index);
1896                 return;
1897         }
1898
1899         name_and_value = g_strconcat (name, ":", value, NULL);
1900         if (index != -1) {
1901                 g_free (array->pdata[index]);
1902                 array->pdata[index] = name_and_value;
1903         } else {
1904                 g_ptr_array_add (array, name_and_value);
1905         }
1906 }
1907
1908 /**
1909  * e_named_parameters_get:
1910  * @parameters: an #ENamedParameters
1911  * @name: name of a parameter to get
1912  *
1913  * Returns current value of a parameter with name @name. If not such
1914  * exists, then returns %NULL.
1915  *
1916  * Returns: value of a parameter named @name, or %NULL.
1917  *
1918  * Since: 3.8
1919  **/
1920 const gchar *
1921 e_named_parameters_get (const ENamedParameters *parameters,
1922                         const gchar *name)
1923 {
1924         gint index;
1925         const gchar *name_and_value;
1926
1927         g_return_val_if_fail (parameters != NULL, NULL);
1928         g_return_val_if_fail (name != NULL, NULL);
1929
1930         index = get_parameter_index (parameters, name);
1931         if (index == -1)
1932                 return NULL;
1933
1934         name_and_value = g_ptr_array_index ((GPtrArray *) parameters, index);
1935
1936         return name_and_value + strlen (name) + 1;
1937 }
1938
1939 /**
1940  * e_named_parameters_test:
1941  * @parameters: an #ENamedParameters
1942  * @name: name of a parameter to test
1943  * @value: value to test
1944  * @case_sensitively: whether to compare case sensitively
1945  *
1946  * Compares current value of parameter named @name with given @value
1947  * and returns whether they are equal, either case sensitively or
1948  * insensitively, based on @case_sensitively argument. Function
1949  * returns %FALSE, if no such parameter exists.
1950  *
1951  * Returns: Whether parameter of given name has stored value of given value.
1952  *
1953  * Since: 3.8
1954  **/
1955 gboolean
1956 e_named_parameters_test (const ENamedParameters *parameters,
1957                          const gchar *name,
1958                          const gchar *value,
1959                          gboolean case_sensitively)
1960 {
1961         const gchar *stored_value;
1962
1963         g_return_val_if_fail (parameters != NULL, FALSE);
1964         g_return_val_if_fail (name != NULL, FALSE);
1965         g_return_val_if_fail (value != NULL, FALSE);
1966
1967         stored_value = e_named_parameters_get (parameters, name);
1968         if (!stored_value)
1969                 return FALSE;
1970
1971         if (case_sensitively)
1972                 return strcmp (stored_value, value) == 0;
1973
1974         return g_ascii_strcasecmp (stored_value, value) == 0;
1975 }
1976
1977 /**
1978  * e_named_parameters_to_strv:
1979  * @parameters: an #ENamedParameters
1980  *
1981  * Returns: (transfer full): Contents of @parameters as a null-terminated strv
1982  *
1983  * Since: 3.8
1984  */
1985 gchar **
1986 e_named_parameters_to_strv (const ENamedParameters *parameters)
1987 {
1988         GPtrArray *array = (GPtrArray *) parameters;
1989         GPtrArray *ret = g_ptr_array_new ();
1990
1991         if (array) {
1992                 guint i;
1993                 for (i = 0; i < array->len; i++) {
1994                         g_ptr_array_add (ret, g_strdup (array->pdata[i]));
1995                 }
1996         }
1997
1998         g_ptr_array_add (ret, NULL);
1999
2000         return (gchar **) g_ptr_array_free (ret, FALSE);
2001 }
2002
2003 static ENamedParameters *
2004 e_named_parameters_ref (ENamedParameters *params)
2005 {
2006         return (ENamedParameters *) g_ptr_array_ref ((GPtrArray *) params);
2007 }
2008
2009 static void
2010 e_named_parameters_unref (ENamedParameters *params)
2011 {
2012         g_ptr_array_unref ((GPtrArray *) params);
2013 }
2014
2015 G_DEFINE_BOXED_TYPE (
2016         ENamedParameters,
2017         e_named_parameters,
2018         e_named_parameters_ref,
2019         e_named_parameters_unref);