83683f2133379f3d9ec67a769b8aa9d82f6a3c7d
[platform/upstream/glib.git] / glib / gconvert.c
1 /* GLIB - Library of useful routines for C programming
2  *
3  * gconvert.c: Convert between character sets using iconv
4  * Copyright Red Hat Inc., 2000
5  * Authors: Havoc Pennington <hp@redhat.com>, Owen Taylor <otaylor@redhat.com
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 #include "config.h"
24
25 #include <iconv.h>
26 #include <errno.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <stdlib.h>
30
31 #include "glib.h"
32 #include "gprintfint.h"
33 #include "gthreadinit.h"
34
35 #ifdef G_PLATFORM_WIN32
36 #define STRICT
37 #include <windows.h>
38 #undef STRICT
39 #endif
40
41 #include "glibintl.h"
42
43 #if defined(USE_LIBICONV_GNU) && !defined (_LIBICONV_H)
44 #error GNU libiconv in use but included iconv.h not from libiconv
45 #endif
46 #if !defined(USE_LIBICONV_GNU) && defined (_LIBICONV_H)
47 #error GNU libiconv not in use but included iconv.h is from libiconv
48 #endif
49
50 #include "galias.h"
51
52 GQuark 
53 g_convert_error_quark (void)
54 {
55   static GQuark quark;
56   if (!quark)
57     quark = g_quark_from_static_string ("g_convert_error");
58
59   return quark;
60 }
61
62 static gboolean
63 try_conversion (const char *to_codeset,
64                 const char *from_codeset,
65                 iconv_t    *cd)
66 {
67   *cd = iconv_open (to_codeset, from_codeset);
68
69   if (*cd == (iconv_t)-1 && errno == EINVAL)
70     return FALSE;
71   else
72     return TRUE;
73 }
74
75 static gboolean
76 try_to_aliases (const char **to_aliases,
77                 const char  *from_codeset,
78                 iconv_t     *cd)
79 {
80   if (to_aliases)
81     {
82       const char **p = to_aliases;
83       while (*p)
84         {
85           if (try_conversion (*p, from_codeset, cd))
86             return TRUE;
87
88           p++;
89         }
90     }
91
92   return FALSE;
93 }
94
95 extern const char **_g_charset_get_aliases (const char *canonical_name) G_GNUC_INTERNAL;
96
97 /**
98  * g_iconv_open:
99  * @to_codeset: destination codeset
100  * @from_codeset: source codeset
101  * 
102  * Same as the standard UNIX routine iconv_open(), but
103  * may be implemented via libiconv on UNIX flavors that lack
104  * a native implementation.
105  * 
106  * GLib provides g_convert() and g_locale_to_utf8() which are likely
107  * more convenient than the raw iconv wrappers.
108  * 
109  * Return value: a "conversion descriptor", or (GIConv)-1 if
110  *  opening the converter failed.
111  **/
112 GIConv
113 g_iconv_open (const gchar  *to_codeset,
114               const gchar  *from_codeset)
115 {
116   iconv_t cd;
117   
118   if (!try_conversion (to_codeset, from_codeset, &cd))
119     {
120       const char **to_aliases = _g_charset_get_aliases (to_codeset);
121       const char **from_aliases = _g_charset_get_aliases (from_codeset);
122
123       if (from_aliases)
124         {
125           const char **p = from_aliases;
126           while (*p)
127             {
128               if (try_conversion (to_codeset, *p, &cd))
129                 goto out;
130
131               if (try_to_aliases (to_aliases, *p, &cd))
132                 goto out;
133
134               p++;
135             }
136         }
137
138       if (try_to_aliases (to_aliases, from_codeset, &cd))
139         goto out;
140     }
141
142  out:
143   return (cd == (iconv_t)-1) ? (GIConv)-1 : (GIConv)cd;
144 }
145
146 /**
147  * g_iconv:
148  * @converter: conversion descriptor from g_iconv_open()
149  * @inbuf: bytes to convert
150  * @inbytes_left: inout parameter, bytes remaining to convert in @inbuf
151  * @outbuf: converted output bytes
152  * @outbytes_left: inout parameter, bytes available to fill in @outbuf
153  * 
154  * Same as the standard UNIX routine iconv(), but
155  * may be implemented via libiconv on UNIX flavors that lack
156  * a native implementation.
157  *
158  * GLib provides g_convert() and g_locale_to_utf8() which are likely
159  * more convenient than the raw iconv wrappers.
160  * 
161  * Return value: count of non-reversible conversions, or -1 on error
162  **/
163 size_t 
164 g_iconv (GIConv   converter,
165          gchar  **inbuf,
166          gsize   *inbytes_left,
167          gchar  **outbuf,
168          gsize   *outbytes_left)
169 {
170   iconv_t cd = (iconv_t)converter;
171
172   return iconv (cd, inbuf, inbytes_left, outbuf, outbytes_left);
173 }
174
175 /**
176  * g_iconv_close:
177  * @converter: a conversion descriptor from g_iconv_open()
178  *
179  * Same as the standard UNIX routine iconv_close(), but
180  * may be implemented via libiconv on UNIX flavors that lack
181  * a native implementation. Should be called to clean up
182  * the conversion descriptor from g_iconv_open() when
183  * you are done converting things.
184  *
185  * GLib provides g_convert() and g_locale_to_utf8() which are likely
186  * more convenient than the raw iconv wrappers.
187  * 
188  * Return value: -1 on error, 0 on success
189  **/
190 gint
191 g_iconv_close (GIConv converter)
192 {
193   iconv_t cd = (iconv_t)converter;
194
195   return iconv_close (cd);
196 }
197
198
199 #define ICONV_CACHE_SIZE   (16)
200
201 struct _iconv_cache_bucket {
202   gchar *key;
203   guint32 refcount;
204   gboolean used;
205   GIConv cd;
206 };
207
208 static GList *iconv_cache_list;
209 static GHashTable *iconv_cache;
210 static GHashTable *iconv_open_hash;
211 static guint iconv_cache_size = 0;
212 G_LOCK_DEFINE_STATIC (iconv_cache_lock);
213
214 /* caller *must* hold the iconv_cache_lock */
215 static void
216 iconv_cache_init (void)
217 {
218   static gboolean initialized = FALSE;
219   
220   if (initialized)
221     return;
222   
223   iconv_cache_list = NULL;
224   iconv_cache = g_hash_table_new (g_str_hash, g_str_equal);
225   iconv_open_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
226   
227   initialized = TRUE;
228 }
229
230
231 /**
232  * iconv_cache_bucket_new:
233  * @key: cache key
234  * @cd: iconv descriptor
235  *
236  * Creates a new cache bucket, inserts it into the cache and
237  * increments the cache size.
238  *
239  * Returns a pointer to the newly allocated cache bucket.
240  **/
241 static struct _iconv_cache_bucket *
242 iconv_cache_bucket_new (const gchar *key, GIConv cd)
243 {
244   struct _iconv_cache_bucket *bucket;
245   
246   bucket = g_new (struct _iconv_cache_bucket, 1);
247   bucket->key = g_strdup (key);
248   bucket->refcount = 1;
249   bucket->used = TRUE;
250   bucket->cd = cd;
251   
252   g_hash_table_insert (iconv_cache, bucket->key, bucket);
253   
254   /* FIXME: if we sorted the list so items with few refcounts were
255      first, then we could expire them faster in iconv_cache_expire_unused () */
256   iconv_cache_list = g_list_prepend (iconv_cache_list, bucket);
257   
258   iconv_cache_size++;
259   
260   return bucket;
261 }
262
263
264 /**
265  * iconv_cache_bucket_expire:
266  * @node: cache bucket's node
267  * @bucket: cache bucket
268  *
269  * Expires a single cache bucket @bucket. This should only ever be
270  * called on a bucket that currently has no used iconv descriptors
271  * open.
272  *
273  * @node is not a required argument. If @node is not supplied, we
274  * search for it ourselves.
275  **/
276 static void
277 iconv_cache_bucket_expire (GList *node, struct _iconv_cache_bucket *bucket)
278 {
279   g_hash_table_remove (iconv_cache, bucket->key);
280   
281   if (node == NULL)
282     node = g_list_find (iconv_cache_list, bucket);
283   
284   g_assert (node != NULL);
285   
286   if (node->prev)
287     {
288       node->prev->next = node->next;
289       if (node->next)
290         node->next->prev = node->prev;
291     }
292   else
293     {
294       iconv_cache_list = node->next;
295       if (node->next)
296         node->next->prev = NULL;
297     }
298   
299   g_list_free_1 (node);
300   
301   g_free (bucket->key);
302   g_iconv_close (bucket->cd);
303   g_free (bucket);
304   
305   iconv_cache_size--;
306 }
307
308
309 /**
310  * iconv_cache_expire_unused:
311  *
312  * Expires as many unused cache buckets as it needs to in order to get
313  * the total number of buckets < ICONV_CACHE_SIZE.
314  **/
315 static void
316 iconv_cache_expire_unused (void)
317 {
318   struct _iconv_cache_bucket *bucket;
319   GList *node, *next;
320   
321   node = iconv_cache_list;
322   while (node && iconv_cache_size >= ICONV_CACHE_SIZE)
323     {
324       next = node->next;
325       
326       bucket = node->data;
327       if (bucket->refcount == 0)
328         iconv_cache_bucket_expire (node, bucket);
329       
330       node = next;
331     }
332 }
333
334 static GIConv
335 open_converter (const gchar *to_codeset,
336                 const gchar *from_codeset,
337                 GError     **error)
338 {
339   struct _iconv_cache_bucket *bucket;
340   gchar *key;
341   GIConv cd;
342   
343   /* create our key */
344   key = g_alloca (strlen (from_codeset) + strlen (to_codeset) + 2);
345   _g_sprintf (key, "%s:%s", from_codeset, to_codeset);
346   
347   G_LOCK (iconv_cache_lock);
348   
349   /* make sure the cache has been initialized */
350   iconv_cache_init ();
351   
352   bucket = g_hash_table_lookup (iconv_cache, key);
353   if (bucket)
354     {
355       if (bucket->used)
356         {
357           cd = g_iconv_open (to_codeset, from_codeset);
358           if (cd == (GIConv) -1)
359             goto error;
360         }
361       else
362         {
363           /* Apparently iconv on Solaris <= 7 segfaults if you pass in
364            * NULL for anything but inbuf; work around that. (NULL outbuf
365            * or NULL *outbuf is allowed by Unix98.)
366            */
367           gsize inbytes_left = 0;
368           gchar *outbuf = NULL;
369           gsize outbytes_left = 0;
370                 
371           cd = bucket->cd;
372           bucket->used = TRUE;
373           
374           /* reset the descriptor */
375           g_iconv (cd, NULL, &inbytes_left, &outbuf, &outbytes_left);
376         }
377       
378       bucket->refcount++;
379     }
380   else
381     {
382       cd = g_iconv_open (to_codeset, from_codeset);
383       if (cd == (GIConv) -1)
384         goto error;
385       
386       iconv_cache_expire_unused ();
387       
388       bucket = iconv_cache_bucket_new (key, cd);
389     }
390   
391   g_hash_table_insert (iconv_open_hash, cd, bucket->key);
392   
393   G_UNLOCK (iconv_cache_lock);
394   
395   return cd;
396   
397  error:
398   
399   G_UNLOCK (iconv_cache_lock);
400   
401   /* Something went wrong.  */
402   if (error)
403     {
404       if (errno == EINVAL)
405         g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_NO_CONVERSION,
406                      _("Conversion from character set '%s' to '%s' is not supported"),
407                      from_codeset, to_codeset);
408       else
409         g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_FAILED,
410                      _("Could not open converter from '%s' to '%s'"),
411                      from_codeset, to_codeset);
412     }
413   
414   return cd;
415 }
416
417 static int
418 close_converter (GIConv converter)
419 {
420   struct _iconv_cache_bucket *bucket;
421   const gchar *key;
422   GIConv cd;
423   
424   cd = converter;
425   
426   if (cd == (GIConv) -1)
427     return 0;
428   
429   G_LOCK (iconv_cache_lock);
430   
431   key = g_hash_table_lookup (iconv_open_hash, cd);
432   if (key)
433     {
434       g_hash_table_remove (iconv_open_hash, cd);
435       
436       bucket = g_hash_table_lookup (iconv_cache, key);
437       g_assert (bucket);
438       
439       bucket->refcount--;
440       
441       if (cd == bucket->cd)
442         bucket->used = FALSE;
443       else
444         g_iconv_close (cd);
445       
446       if (!bucket->refcount && iconv_cache_size > ICONV_CACHE_SIZE)
447         {
448           /* expire this cache bucket */
449           iconv_cache_bucket_expire (NULL, bucket);
450         }
451     }
452   else
453     {
454       G_UNLOCK (iconv_cache_lock);
455       
456       g_warning ("This iconv context wasn't opened using open_converter");
457       
458       return g_iconv_close (converter);
459     }
460   
461   G_UNLOCK (iconv_cache_lock);
462   
463   return 0;
464 }
465
466 /**
467  * g_convert_with_iconv:
468  * @str:           the string to convert
469  * @len:           the length of the string, or -1 if the string is 
470  *                 nul-terminated<footnoteref linkend="nul-unsafe"/>. 
471  * @converter:     conversion descriptor from g_iconv_open()
472  * @bytes_read:    location to store the number of bytes in the
473  *                 input string that were successfully converted, or %NULL.
474  *                 Even if the conversion was successful, this may be 
475  *                 less than @len if there were partial characters
476  *                 at the end of the input. If the error
477  *                 #G_CONVERT_ERROR_ILLEGAL_SEQUENCE occurs, the value
478  *                 stored will the byte offset after the last valid
479  *                 input sequence.
480  * @bytes_written: the number of bytes stored in the output buffer (not 
481  *                 including the terminating nul).
482  * @error:         location to store the error occuring, or %NULL to ignore
483  *                 errors. Any of the errors in #GConvertError may occur.
484  *
485  * Converts a string from one character set to another. 
486  * 
487  * Note that despite the fact that @byes_read can return information
488  * about partial characters, this function is not generally suitable
489  * for streaming. It may not handle stateful encodings like CP1255 
490  * correctly, since it doesn't keep the @converter state across
491  * multiple invocations. If you need to do streaming conversions
492  * which may involve stateful encodings, you have to use g_iconv()
493  * directly.
494  *
495  * Note that you should use g_iconv() for streaming 
496  * conversions<footnote id="streaming-state">
497  *  <para>
498  * Despite the fact that @byes_read can return information about partial 
499  * characters, the <literal>g_convert_...</literal> functions
500  * are not generally suitable for streaming. If the underlying converter 
501  * being used maintains internal state, then this won't be preserved 
502  * across successive calls to g_convert(), g_convert_with_iconv() or 
503  * g_convert_with_fallback(). (An example of this is the GNU C converter 
504  * for CP1255 which does not emit a base character until it knows that 
505  * the next character is not a mark that could combine with the base 
506  * character.)
507  *  </para>
508  * </footnote>. 
509  *
510  * Return value: If the conversion was successful, a newly allocated
511  *               nul-terminated string, which must be freed with
512  *               g_free(). Otherwise %NULL and @error will be set.
513  **/
514 gchar*
515 g_convert_with_iconv (const gchar *str,
516                       gssize       len,
517                       GIConv       converter,
518                       gsize       *bytes_read, 
519                       gsize       *bytes_written, 
520                       GError     **error)
521 {
522   gchar *dest;
523   gchar *outp;
524   const gchar *p;
525   const gchar *shift_p = NULL;
526   gsize inbytes_remaining;
527   gsize outbytes_remaining;
528   gsize err;
529   gsize outbuf_size;
530   gboolean have_error = FALSE;
531   gboolean done = FALSE;
532   
533   g_return_val_if_fail (converter != (GIConv) -1, NULL);
534      
535   if (len < 0)
536     len = strlen (str);
537
538   p = str;
539   inbytes_remaining = len;
540   outbuf_size = len + 1; /* + 1 for nul in case len == 1 */
541   
542   outbytes_remaining = outbuf_size - 1; /* -1 for nul */
543   outp = dest = g_malloc (outbuf_size);
544
545   while (!done && !have_error)
546     {
547       err = g_iconv (converter, (char **)&p, &inbytes_remaining, &outp, &outbytes_remaining);
548
549       if (err == (size_t) -1)
550         {
551           switch (errno)
552             {
553             case EINVAL:
554               /* Incomplete text, do not report an error */
555               break;
556             case E2BIG:
557               {
558                 size_t used = outp - dest;
559                 
560                 outbuf_size *= 2;
561                 dest = g_realloc (dest, outbuf_size);
562                 
563                 outp = dest + used;
564                 outbytes_remaining = outbuf_size - used - 1; /* -1 for nul */
565               }
566               break;
567             case EILSEQ:
568               if (error)
569                 g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
570                              _("Invalid byte sequence in conversion input"));
571               have_error = TRUE;
572               break;
573             default:
574               if (error)
575                 g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_FAILED,
576                              _("Error during conversion: %s"),
577                              g_strerror (errno));
578               have_error = TRUE;
579               break;
580             }
581         }
582       else 
583         {
584           if (!shift_p)
585             {
586               /* call g_iconv with NULL inbuf to cleanup shift state */
587               shift_p = p;
588               p = NULL;
589               inbytes_remaining = 0;
590             }
591           else
592             done = TRUE;
593         }
594     }
595
596   if (shift_p)
597     p = shift_p;
598
599   *outp = '\0';
600   
601   if (bytes_read)
602     *bytes_read = p - str;
603   else
604     {
605       if ((p - str) != len) 
606         {
607           if (!have_error)
608             {
609               if (error)
610                 g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_PARTIAL_INPUT,
611                              _("Partial character sequence at end of input"));
612               have_error = TRUE;
613             }
614         }
615     }
616
617   if (bytes_written)
618     *bytes_written = outp - dest;       /* Doesn't include '\0' */
619
620   if (have_error)
621     {
622       g_free (dest);
623       return NULL;
624     }
625   else
626     return dest;
627 }
628
629 /**
630  * g_convert:
631  * @str:           the string to convert
632  * @len:           the length of the string, or -1 if the string is 
633  *                 nul-terminated<footnote id="nul-unsafe">
634                      <para>
635                        Note that some encodings may allow nul bytes to 
636                        occur inside strings. In that case, using -1 for 
637                        the @len parameter is unsafe.
638                      </para>
639                    </footnote>. 
640  * @to_codeset:    name of character set into which to convert @str
641  * @from_codeset:  character set of @str.
642  * @bytes_read:    location to store the number of bytes in the
643  *                 input string that were successfully converted, or %NULL.
644  *                 Even if the conversion was successful, this may be 
645  *                 less than @len if there were partial characters
646  *                 at the end of the input. If the error
647  *                 #G_CONVERT_ERROR_ILLEGAL_SEQUENCE occurs, the value
648  *                 stored will the byte offset after the last valid
649  *                 input sequence.
650  * @bytes_written: the number of bytes stored in the output buffer (not 
651  *                 including the terminating nul).
652  * @error:         location to store the error occuring, or %NULL to ignore
653  *                 errors. Any of the errors in #GConvertError may occur.
654  *
655  * Converts a string from one character set to another.
656  *
657  * Note that despite the fact that @byes_read can return information
658  * about partial characters, this function is not generally suitable
659  * for streaming. It may not handle stateful encodings like CP1255 
660  * correctly, since it doesn't keep the @converter state across
661  * multiple invocations. If you need to do streaming conversions
662  * which may involve stateful encodings, you have to use g_iconv()
663  * directly.
664  *
665  * Note that you should use g_iconv() for streaming 
666  * conversions<footnoteref linkend="streaming-state"/>.
667  *
668  * Return value: If the conversion was successful, a newly allocated
669  *               nul-terminated string, which must be freed with
670  *               g_free(). Otherwise %NULL and @error will be set.
671  **/
672 gchar*
673 g_convert (const gchar *str,
674            gssize       len,  
675            const gchar *to_codeset,
676            const gchar *from_codeset,
677            gsize       *bytes_read, 
678            gsize       *bytes_written, 
679            GError     **error)
680 {
681   gchar *res;
682   GIConv cd;
683
684   g_return_val_if_fail (str != NULL, NULL);
685   g_return_val_if_fail (to_codeset != NULL, NULL);
686   g_return_val_if_fail (from_codeset != NULL, NULL);
687   
688   cd = open_converter (to_codeset, from_codeset, error);
689
690   if (cd == (GIConv) -1)
691     {
692       if (bytes_read)
693         *bytes_read = 0;
694       
695       if (bytes_written)
696         *bytes_written = 0;
697       
698       return NULL;
699     }
700
701   res = g_convert_with_iconv (str, len, cd,
702                               bytes_read, bytes_written,
703                               error);
704
705   close_converter (cd);
706
707   return res;
708 }
709
710 /**
711  * g_convert_with_fallback:
712  * @str:          the string to convert
713  * @len:          the length of the string, or -1 if the string is 
714  *                nul-terminated<footnoteref linkend="nul-unsafe"/>. 
715  * @to_codeset:   name of character set into which to convert @str
716  * @from_codeset: character set of @str.
717  * @fallback:     UTF-8 string to use in place of character not
718  *                present in the target encoding. (The string must be
719  *                representable in the target encoding). 
720                   If %NULL, characters not in the target encoding will 
721                   be represented as Unicode escapes \uxxxx or \Uxxxxyyyy.
722  * @bytes_read:   location to store the number of bytes in the
723  *                input string that were successfully converted, or %NULL.
724  *                Even if the conversion was successful, this may be 
725  *                less than @len if there were partial characters
726  *                at the end of the input.
727  * @bytes_written: the number of bytes stored in the output buffer (not 
728  *                including the terminating nul).
729  * @error:        location to store the error occuring, or %NULL to ignore
730  *                errors. Any of the errors in #GConvertError may occur.
731  *
732  * Converts a string from one character set to another, possibly
733  * including fallback sequences for characters not representable
734  * in the output. Note that it is not guaranteed that the specification
735  * for the fallback sequences in @fallback will be honored. Some
736  * systems may do a approximate conversion from @from_codeset
737  * to @to_codeset in their iconv() functions, 
738  * in which case GLib will simply return that approximate conversion.
739  *
740  * Note that you should use g_iconv() for streaming 
741  * conversions<footnoteref linkend="streaming-state"/>.
742  *
743  * Return value: If the conversion was successful, a newly allocated
744  *               nul-terminated string, which must be freed with
745  *               g_free(). Otherwise %NULL and @error will be set.
746  **/
747 gchar*
748 g_convert_with_fallback (const gchar *str,
749                          gssize       len,    
750                          const gchar *to_codeset,
751                          const gchar *from_codeset,
752                          gchar       *fallback,
753                          gsize       *bytes_read,
754                          gsize       *bytes_written,
755                          GError     **error)
756 {
757   gchar *utf8;
758   gchar *dest;
759   gchar *outp;
760   const gchar *insert_str = NULL;
761   const gchar *p;
762   gsize inbytes_remaining;   
763   const gchar *save_p = NULL;
764   gsize save_inbytes = 0;
765   gsize outbytes_remaining; 
766   gsize err;
767   GIConv cd;
768   gsize outbuf_size;
769   gboolean have_error = FALSE;
770   gboolean done = FALSE;
771
772   GError *local_error = NULL;
773   
774   g_return_val_if_fail (str != NULL, NULL);
775   g_return_val_if_fail (to_codeset != NULL, NULL);
776   g_return_val_if_fail (from_codeset != NULL, NULL);
777      
778   if (len < 0)
779     len = strlen (str);
780   
781   /* Try an exact conversion; we only proceed if this fails
782    * due to an illegal sequence in the input string.
783    */
784   dest = g_convert (str, len, to_codeset, from_codeset, 
785                     bytes_read, bytes_written, &local_error);
786   if (!local_error)
787     return dest;
788
789   if (!g_error_matches (local_error, G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE))
790     {
791       g_propagate_error (error, local_error);
792       return NULL;
793     }
794   else
795     g_error_free (local_error);
796
797   local_error = NULL;
798   
799   /* No go; to proceed, we need a converter from "UTF-8" to
800    * to_codeset, and the string as UTF-8.
801    */
802   cd = open_converter (to_codeset, "UTF-8", error);
803   if (cd == (GIConv) -1)
804     {
805       if (bytes_read)
806         *bytes_read = 0;
807       
808       if (bytes_written)
809         *bytes_written = 0;
810       
811       return NULL;
812     }
813
814   utf8 = g_convert (str, len, "UTF-8", from_codeset, 
815                     bytes_read, &inbytes_remaining, error);
816   if (!utf8)
817     {
818       close_converter (cd);
819       if (bytes_written)
820         *bytes_written = 0;
821       return NULL;
822     }
823
824   /* Now the heart of the code. We loop through the UTF-8 string, and
825    * whenever we hit an offending character, we form fallback, convert
826    * the fallback to the target codeset, and then go back to
827    * converting the original string after finishing with the fallback.
828    *
829    * The variables save_p and save_inbytes store the input state
830    * for the original string while we are converting the fallback
831    */
832   p = utf8;
833
834   outbuf_size = len + 1; /* + 1 for nul in case len == 1 */
835   outbytes_remaining = outbuf_size - 1; /* -1 for nul */
836   outp = dest = g_malloc (outbuf_size);
837
838   while (!done && !have_error)
839     {
840       size_t inbytes_tmp = inbytes_remaining;
841       err = g_iconv (cd, (char **)&p, &inbytes_tmp, &outp, &outbytes_remaining);
842       inbytes_remaining = inbytes_tmp;
843
844       if (err == (size_t) -1)
845         {
846           switch (errno)
847             {
848             case EINVAL:
849               g_assert_not_reached();
850               break;
851             case E2BIG:
852               {
853                 size_t used = outp - dest;
854
855                 outbuf_size *= 2;
856                 dest = g_realloc (dest, outbuf_size);
857                 
858                 outp = dest + used;
859                 outbytes_remaining = outbuf_size - used - 1; /* -1 for nul */
860                 
861                 break;
862               }
863             case EILSEQ:
864               if (save_p)
865                 {
866                   /* Error converting fallback string - fatal
867                    */
868                   g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
869                                _("Cannot convert fallback '%s' to codeset '%s'"),
870                                insert_str, to_codeset);
871                   have_error = TRUE;
872                   break;
873                 }
874               else if (p)
875                 {
876                   if (!fallback)
877                     { 
878                       gunichar ch = g_utf8_get_char (p);
879                       insert_str = g_strdup_printf (ch < 0x10000 ? "\\u%04x" : "\\U%08x",
880                                                     ch);
881                     }
882                   else
883                     insert_str = fallback;
884                   
885                   save_p = g_utf8_next_char (p);
886                   save_inbytes = inbytes_remaining - (save_p - p);
887                   p = insert_str;
888                   inbytes_remaining = strlen (p);
889                   break;
890                 }
891               /* fall thru if p is NULL */
892             default:
893               g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_FAILED,
894                            _("Error during conversion: %s"),
895                            g_strerror (errno));
896               have_error = TRUE;
897               break;
898             }
899         }
900       else
901         {
902           if (save_p)
903             {
904               if (!fallback)
905                 g_free ((gchar *)insert_str);
906               p = save_p;
907               inbytes_remaining = save_inbytes;
908               save_p = NULL;
909             }
910           else if (p)
911             {
912               /* call g_iconv with NULL inbuf to cleanup shift state */
913               p = NULL;
914               inbytes_remaining = 0;
915             }
916           else
917             done = TRUE;
918         }
919     }
920
921   /* Cleanup
922    */
923   *outp = '\0';
924   
925   close_converter (cd);
926
927   if (bytes_written)
928     *bytes_written = outp - dest;       /* Doesn't include '\0' */
929
930   g_free (utf8);
931
932   if (have_error)
933     {
934       if (save_p && !fallback)
935         g_free ((gchar *)insert_str);
936       g_free (dest);
937       return NULL;
938     }
939   else
940     return dest;
941 }
942
943 /*
944  * g_locale_to_utf8
945  *
946  * 
947  */
948
949 static gchar *
950 strdup_len (const gchar *string,
951             gssize       len,
952             gsize       *bytes_written,
953             gsize       *bytes_read,
954             GError      **error)
955          
956 {
957   gsize real_len;
958
959   if (!g_utf8_validate (string, len, NULL))
960     {
961       if (bytes_read)
962         *bytes_read = 0;
963       if (bytes_written)
964         *bytes_written = 0;
965
966       g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
967                    _("Invalid byte sequence in conversion input"));
968       return NULL;
969     }
970   
971   if (len < 0)
972     real_len = strlen (string);
973   else
974     {
975       real_len = 0;
976       
977       while (real_len < len && string[real_len])
978         real_len++;
979     }
980   
981   if (bytes_read)
982     *bytes_read = real_len;
983   if (bytes_written)
984     *bytes_written = real_len;
985
986   return g_strndup (string, real_len);
987 }
988
989 /**
990  * g_locale_to_utf8:
991  * @opsysstring:   a string in the encoding of the current locale. On Windows
992  *                 this means the system codepage.
993  * @len:           the length of the string, or -1 if the string is
994  *                 nul-terminated<footnoteref linkend="nul-unsafe"/>. 
995  * @bytes_read:    location to store the number of bytes in the
996  *                 input string that were successfully converted, or %NULL.
997  *                 Even if the conversion was successful, this may be 
998  *                 less than @len if there were partial characters
999  *                 at the end of the input. If the error
1000  *                 #G_CONVERT_ERROR_ILLEGAL_SEQUENCE occurs, the value
1001  *                 stored will the byte offset after the last valid
1002  *                 input sequence.
1003  * @bytes_written: the number of bytes stored in the output buffer (not 
1004  *                 including the terminating nul).
1005  * @error:         location to store the error occuring, or %NULL to ignore
1006  *                 errors. Any of the errors in #GConvertError may occur.
1007  * 
1008  * Converts a string which is in the encoding used for strings by
1009  * the C runtime (usually the same as that used by the operating
1010  * system) in the current locale into a UTF-8 string.
1011  * 
1012  * Return value: The converted string, or %NULL on an error.
1013  **/
1014 gchar *
1015 g_locale_to_utf8 (const gchar  *opsysstring,
1016                   gssize        len,            
1017                   gsize        *bytes_read,    
1018                   gsize        *bytes_written,
1019                   GError      **error)
1020 {
1021   const char *charset;
1022
1023   if (g_get_charset (&charset))
1024     return strdup_len (opsysstring, len, bytes_read, bytes_written, error);
1025   else
1026     return g_convert (opsysstring, len, 
1027                       "UTF-8", charset, bytes_read, bytes_written, error);
1028 }
1029
1030 /**
1031  * g_locale_from_utf8:
1032  * @utf8string:    a UTF-8 encoded string 
1033  * @len:           the length of the string, or -1 if the string is
1034  *                 nul-terminated<footnoteref linkend="nul-unsafe"/>. 
1035  * @bytes_read:    location to store the number of bytes in the
1036  *                 input string that were successfully converted, or %NULL.
1037  *                 Even if the conversion was successful, this may be 
1038  *                 less than @len if there were partial characters
1039  *                 at the end of the input. If the error
1040  *                 #G_CONVERT_ERROR_ILLEGAL_SEQUENCE occurs, the value
1041  *                 stored will the byte offset after the last valid
1042  *                 input sequence.
1043  * @bytes_written: the number of bytes stored in the output buffer (not 
1044  *                 including the terminating nul).
1045  * @error:         location to store the error occuring, or %NULL to ignore
1046  *                 errors. Any of the errors in #GConvertError may occur.
1047  * 
1048  * Converts a string from UTF-8 to the encoding used for strings by
1049  * the C runtime (usually the same as that used by the operating
1050  * system) in the current locale.
1051  * 
1052  * Return value: The converted string, or %NULL on an error.
1053  **/
1054 gchar *
1055 g_locale_from_utf8 (const gchar *utf8string,
1056                     gssize       len,            
1057                     gsize       *bytes_read,    
1058                     gsize       *bytes_written,
1059                     GError     **error)
1060 {
1061   const gchar *charset;
1062
1063   if (g_get_charset (&charset))
1064     return strdup_len (utf8string, len, bytes_read, bytes_written, error);
1065   else
1066     return g_convert (utf8string, len,
1067                       charset, "UTF-8", bytes_read, bytes_written, error);
1068 }
1069
1070 #ifndef G_PLATFORM_WIN32
1071
1072 typedef struct _GFilenameCharsetCache GFilenameCharsetCache;
1073
1074 struct _GFilenameCharsetCache {
1075   gboolean is_utf8;
1076   gchar *charset;
1077   gchar **filename_charsets;
1078 };
1079
1080 static void
1081 filename_charset_cache_free (gpointer data)
1082 {
1083   GFilenameCharsetCache *cache = data;
1084   g_free (cache->charset);
1085   g_strfreev (cache->filename_charsets);
1086   g_free (cache);
1087 }
1088
1089 /**
1090  * g_get_filename_charsets:
1091  * @charsets: return location for the %NULL-terminated list of encoding names
1092  *
1093  * Determines the preferred character sets used for filenames.
1094  * The first character set from the @charsets is the filename encoding, the
1095  * subsequent character sets are used when trying to generate a displayable
1096  * representation of a filename, see g_filename_display_name().
1097  *
1098  * On Unix, the character sets are determined by consulting the
1099  * environment variables <envar>G_FILENAME_ENCODING</envar> and
1100  * <envar>G_BROKEN_FILENAMES</envar>. On Windows, the character set
1101  * used in the GLib API is always UTF-8 and said environment variables
1102  * have no effect.
1103  *
1104  * <envar>G_FILENAME_ENCODING</envar> may be set to a comma-separated list 
1105  * of character set names. The special token "@locale" is taken to mean the 
1106  * character set for the current locale. If <envar>G_FILENAME_ENCODING</envar> 
1107  * is not set, but <envar>G_BROKEN_FILENAMES</envar> is, the character set of 
1108  * the current locale is taken as the filename encoding. If neither environment
1109  * variable is set, UTF-8 is taken as the filename encoding, but the character
1110  * set of the current locale is also put in the list of encodings.
1111  *
1112  * The returned @charsets belong to GLib and must not be freed.
1113  *
1114  * Note that on Unix, regardless of the locale character set or
1115  * <envar>G_FILENAME_ENCODING</envar> value, the actual file names present on a
1116  * system might be in any random encoding or just gibberish.
1117  *
1118  * Return value: %TRUE if the filename encoding is UTF-8.
1119  * 
1120  * Since: 2.6
1121  */
1122 gboolean
1123 g_get_filename_charsets (G_CONST_RETURN gchar ***filename_charsets)
1124 {
1125   static GStaticPrivate cache_private = G_STATIC_PRIVATE_INIT;
1126   GFilenameCharsetCache *cache = g_static_private_get (&cache_private);
1127   const gchar *charset;
1128
1129   if (!cache)
1130     {
1131       cache = g_new0 (GFilenameCharsetCache, 1);
1132       g_static_private_set (&cache_private, cache, filename_charset_cache_free);
1133     }
1134
1135   g_get_charset (&charset);
1136
1137   if (!(cache->charset && strcmp (cache->charset, charset) == 0))
1138     {
1139       const gchar *new_charset;
1140       gchar *p;
1141       gint i;
1142
1143       g_free (cache->charset);
1144       g_strfreev (cache->filename_charsets);
1145       cache->charset = g_strdup (charset);
1146       
1147       p = getenv ("G_FILENAME_ENCODING");
1148       if (p != NULL && p[0] != '\0') 
1149         {
1150           cache->filename_charsets = g_strsplit (p, ",", 0);
1151           cache->is_utf8 = (strcmp (cache->filename_charsets[0], "UTF-8") == 0);
1152
1153           for (i = 0; cache->filename_charsets[i]; i++)
1154             {
1155               if (strcmp ("@locale", cache->filename_charsets[i]) == 0)
1156                 {
1157                   g_get_charset (&new_charset);
1158                   g_free (cache->filename_charsets[i]);
1159                   cache->filename_charsets[i] = g_strdup (new_charset);
1160                 }
1161             }
1162         }
1163       else if (getenv ("G_BROKEN_FILENAMES") != NULL)
1164         {
1165           cache->filename_charsets = g_new0 (gchar *, 2);
1166           cache->is_utf8 = g_get_charset (&new_charset);
1167           cache->filename_charsets[0] = g_strdup (new_charset);
1168         }
1169       else 
1170         {
1171           cache->filename_charsets = g_new0 (gchar *, 3);
1172           cache->is_utf8 = TRUE;
1173           cache->filename_charsets[0] = g_strdup ("UTF-8");
1174           if (!g_get_charset (&new_charset))
1175             cache->filename_charsets[1] = g_strdup (new_charset);
1176         }
1177     }
1178
1179   if (filename_charsets)
1180     *filename_charsets = (const gchar **)cache->filename_charsets;
1181
1182   return cache->is_utf8;
1183 }
1184
1185 #else /* G_PLATFORM_WIN32 */
1186
1187 gboolean
1188 g_get_filename_charsets (G_CONST_RETURN gchar ***filename_charsets) 
1189 {
1190   static const gchar *charsets[] = {
1191     "UTF-8",
1192     NULL
1193   };
1194
1195 #ifdef G_OS_WIN32
1196   /* On Windows GLib pretends that the filename charset is UTF-8 */
1197   if (filename_charsets)
1198     *filename_charsets = charsets;
1199
1200   return TRUE;
1201 #else
1202   gboolean result;
1203
1204   /* Cygwin works like before */
1205   result = g_get_charset (&(charsets[0]));
1206
1207   if (filename_charsets)
1208     *filename_charsets = charsets;
1209
1210   return result;
1211 #endif
1212 }
1213
1214 #endif /* G_PLATFORM_WIN32 */
1215
1216 static gboolean
1217 get_filename_charset (const gchar **filename_charset)
1218 {
1219   const gchar **charsets;
1220   gboolean is_utf8;
1221   
1222   is_utf8 = g_get_filename_charsets (&charsets);
1223
1224   if (filename_charset)
1225     *filename_charset = charsets[0];
1226   
1227   return is_utf8;
1228 }
1229
1230 /* This is called from g_thread_init(). It's used to
1231  * initialize some static data in a threadsafe way.
1232  */
1233 void 
1234 _g_convert_thread_init (void)
1235 {
1236   const gchar **dummy;
1237   (void) g_get_filename_charsets (&dummy);
1238 }
1239
1240 /**
1241  * g_filename_to_utf8:
1242  * @opsysstring:   a string in the encoding for filenames
1243  * @len:           the length of the string, or -1 if the string is
1244  *                 nul-terminated<footnoteref linkend="nul-unsafe"/>. 
1245  * @bytes_read:    location to store the number of bytes in the
1246  *                 input string that were successfully converted, or %NULL.
1247  *                 Even if the conversion was successful, this may be 
1248  *                 less than @len if there were partial characters
1249  *                 at the end of the input. If the error
1250  *                 #G_CONVERT_ERROR_ILLEGAL_SEQUENCE occurs, the value
1251  *                 stored will the byte offset after the last valid
1252  *                 input sequence.
1253  * @bytes_written: the number of bytes stored in the output buffer (not 
1254  *                 including the terminating nul).
1255  * @error:         location to store the error occuring, or %NULL to ignore
1256  *                 errors. Any of the errors in #GConvertError may occur.
1257  * 
1258  * Converts a string which is in the encoding used by GLib for
1259  * filenames into a UTF-8 string. Note that on Windows GLib uses UTF-8
1260  * for filenames.
1261  * 
1262  * Return value: The converted string, or %NULL on an error.
1263  **/
1264 gchar*
1265 g_filename_to_utf8 (const gchar *opsysstring, 
1266                     gssize       len,           
1267                     gsize       *bytes_read,   
1268                     gsize       *bytes_written,
1269                     GError     **error)
1270 {
1271   const gchar *charset;
1272
1273   if (get_filename_charset (&charset))
1274     return strdup_len (opsysstring, len, bytes_read, bytes_written, error);
1275   else
1276     return g_convert (opsysstring, len, 
1277                       "UTF-8", charset, bytes_read, bytes_written, error);
1278 }
1279
1280 #ifdef G_OS_WIN32
1281
1282 #undef g_filename_to_utf8
1283
1284 /* Binary compatibility version. Not for newly compiled code. */
1285
1286 gchar*
1287 g_filename_to_utf8 (const gchar *opsysstring, 
1288                     gssize       len,           
1289                     gsize       *bytes_read,   
1290                     gsize       *bytes_written,
1291                     GError     **error)
1292 {
1293   const gchar *charset;
1294
1295   if (g_get_charset (&charset))
1296     return strdup_len (opsysstring, len, bytes_read, bytes_written, error);
1297   else
1298     return g_convert (opsysstring, len, 
1299                       "UTF-8", charset, bytes_read, bytes_written, error);
1300 }
1301
1302 #endif
1303
1304 /**
1305  * g_filename_from_utf8:
1306  * @utf8string:    a UTF-8 encoded string.
1307  * @len:           the length of the string, or -1 if the string is
1308  *                 nul-terminated.
1309  * @bytes_read:    location to store the number of bytes in the
1310  *                 input string that were successfully converted, or %NULL.
1311  *                 Even if the conversion was successful, this may be 
1312  *                 less than @len if there were partial characters
1313  *                 at the end of the input. If the error
1314  *                 #G_CONVERT_ERROR_ILLEGAL_SEQUENCE occurs, the value
1315  *                 stored will the byte offset after the last valid
1316  *                 input sequence.
1317  * @bytes_written: the number of bytes stored in the output buffer (not 
1318  *                 including the terminating nul).
1319  * @error:         location to store the error occuring, or %NULL to ignore
1320  *                 errors. Any of the errors in #GConvertError may occur.
1321  * 
1322  * Converts a string from UTF-8 to the encoding GLib uses for
1323  * filenames. Note that on Windows GLib uses UTF-8 for filenames.
1324  * 
1325  * Return value: The converted string, or %NULL on an error.
1326  **/
1327 gchar*
1328 g_filename_from_utf8 (const gchar *utf8string,
1329                       gssize       len,            
1330                       gsize       *bytes_read,    
1331                       gsize       *bytes_written,
1332                       GError     **error)
1333 {
1334   const gchar *charset;
1335
1336   if (get_filename_charset (&charset))
1337     return strdup_len (utf8string, len, bytes_read, bytes_written, error);
1338   else
1339     return g_convert (utf8string, len,
1340                       charset, "UTF-8", bytes_read, bytes_written, error);
1341 }
1342
1343 #ifdef G_OS_WIN32
1344
1345 #undef g_filename_from_utf8
1346
1347 /* Binary compatibility version. Not for newly compiled code. */
1348
1349 gchar*
1350 g_filename_from_utf8 (const gchar *utf8string,
1351                       gssize       len,            
1352                       gsize       *bytes_read,    
1353                       gsize       *bytes_written,
1354                       GError     **error)
1355 {
1356   const gchar *charset;
1357
1358   if (g_get_charset (&charset))
1359     return strdup_len (utf8string, len, bytes_read, bytes_written, error);
1360   else
1361     return g_convert (utf8string, len,
1362                       charset, "UTF-8", bytes_read, bytes_written, error);
1363 }
1364
1365 #endif
1366
1367 /* Test of haystack has the needle prefix, comparing case
1368  * insensitive. haystack may be UTF-8, but needle must
1369  * contain only ascii. */
1370 static gboolean
1371 has_case_prefix (const gchar *haystack, const gchar *needle)
1372 {
1373   const gchar *h, *n;
1374   
1375   /* Eat one character at a time. */
1376   h = haystack;
1377   n = needle;
1378
1379   while (*n && *h &&
1380          g_ascii_tolower (*n) == g_ascii_tolower (*h))
1381     {
1382       n++;
1383       h++;
1384     }
1385   
1386   return *n == '\0';
1387 }
1388
1389 typedef enum {
1390   UNSAFE_ALL        = 0x1,  /* Escape all unsafe characters   */
1391   UNSAFE_ALLOW_PLUS = 0x2,  /* Allows '+'  */
1392   UNSAFE_PATH       = 0x8,  /* Allows '/', '&', '=', ':', '@', '+', '$' and ',' */
1393   UNSAFE_HOST       = 0x10, /* Allows '/' and ':' and '@' */
1394   UNSAFE_SLASHES    = 0x20  /* Allows all characters except for '/' and '%' */
1395 } UnsafeCharacterSet;
1396
1397 static const guchar acceptable[96] = {
1398   /* A table of the ASCII chars from space (32) to DEL (127) */
1399   /*      !    "    #    $    %    &    '    (    )    *    +    ,    -    .    / */ 
1400   0x00,0x3F,0x20,0x20,0x28,0x00,0x2C,0x3F,0x3F,0x3F,0x3F,0x2A,0x28,0x3F,0x3F,0x1C,
1401   /* 0    1    2    3    4    5    6    7    8    9    :    ;    <    =    >    ? */
1402   0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x38,0x20,0x20,0x2C,0x20,0x20,
1403   /* @    A    B    C    D    E    F    G    H    I    J    K    L    M    N    O */
1404   0x38,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,
1405   /* P    Q    R    S    T    U    V    W    X    Y    Z    [    \    ]    ^    _ */
1406   0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x20,0x20,0x20,0x20,0x3F,
1407   /* `    a    b    c    d    e    f    g    h    i    j    k    l    m    n    o */
1408   0x20,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,
1409   /* p    q    r    s    t    u    v    w    x    y    z    {    |    }    ~  DEL */
1410   0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x20,0x20,0x20,0x3F,0x20
1411 };
1412
1413 static const gchar hex[16] = "0123456789ABCDEF";
1414
1415 /* Note: This escape function works on file: URIs, but if you want to
1416  * escape something else, please read RFC-2396 */
1417 static gchar *
1418 g_escape_uri_string (const gchar *string, 
1419                      UnsafeCharacterSet mask)
1420 {
1421 #define ACCEPTABLE(a) ((a)>=32 && (a)<128 && (acceptable[(a)-32] & use_mask))
1422
1423   const gchar *p;
1424   gchar *q;
1425   gchar *result;
1426   int c;
1427   gint unacceptable;
1428   UnsafeCharacterSet use_mask;
1429   
1430   g_return_val_if_fail (mask == UNSAFE_ALL
1431                         || mask == UNSAFE_ALLOW_PLUS
1432                         || mask == UNSAFE_PATH
1433                         || mask == UNSAFE_HOST
1434                         || mask == UNSAFE_SLASHES, NULL);
1435   
1436   unacceptable = 0;
1437   use_mask = mask;
1438   for (p = string; *p != '\0'; p++)
1439     {
1440       c = (guchar) *p;
1441       if (!ACCEPTABLE (c)) 
1442         unacceptable++;
1443     }
1444   
1445   result = g_malloc (p - string + unacceptable * 2 + 1);
1446   
1447   use_mask = mask;
1448   for (q = result, p = string; *p != '\0'; p++)
1449     {
1450       c = (guchar) *p;
1451       
1452       if (!ACCEPTABLE (c))
1453         {
1454           *q++ = '%'; /* means hex coming */
1455           *q++ = hex[c >> 4];
1456           *q++ = hex[c & 15];
1457         }
1458       else
1459         *q++ = *p;
1460     }
1461   
1462   *q = '\0';
1463   
1464   return result;
1465 }
1466
1467
1468 static gchar *
1469 g_escape_file_uri (const gchar *hostname,
1470                    const gchar *pathname)
1471 {
1472   char *escaped_hostname = NULL;
1473   char *escaped_path;
1474   char *res;
1475
1476 #ifdef G_OS_WIN32
1477   char *p, *backslash;
1478
1479   /* Turn backslashes into forward slashes. That's what Netscape
1480    * does, and they are actually more or less equivalent in Windows.
1481    */
1482   
1483   pathname = g_strdup (pathname);
1484   p = (char *) pathname;
1485   
1486   while ((backslash = strchr (p, '\\')) != NULL)
1487     {
1488       *backslash = '/';
1489       p = backslash + 1;
1490     }
1491 #endif
1492
1493   if (hostname && *hostname != '\0')
1494     {
1495       escaped_hostname = g_escape_uri_string (hostname, UNSAFE_HOST);
1496     }
1497
1498   escaped_path = g_escape_uri_string (pathname, UNSAFE_PATH);
1499
1500   res = g_strconcat ("file://",
1501                      (escaped_hostname) ? escaped_hostname : "",
1502                      (*escaped_path != '/') ? "/" : "",
1503                      escaped_path,
1504                      NULL);
1505
1506 #ifdef G_OS_WIN32
1507   g_free ((char *) pathname);
1508 #endif
1509
1510   g_free (escaped_hostname);
1511   g_free (escaped_path);
1512   
1513   return res;
1514 }
1515
1516 static int
1517 unescape_character (const char *scanner)
1518 {
1519   int first_digit;
1520   int second_digit;
1521
1522   first_digit = g_ascii_xdigit_value (scanner[0]);
1523   if (first_digit < 0) 
1524     return -1;
1525   
1526   second_digit = g_ascii_xdigit_value (scanner[1]);
1527   if (second_digit < 0) 
1528     return -1;
1529   
1530   return (first_digit << 4) | second_digit;
1531 }
1532
1533 static gchar *
1534 g_unescape_uri_string (const char *escaped,
1535                        int         len,
1536                        const char *illegal_escaped_characters,
1537                        gboolean    ascii_must_not_be_escaped)
1538 {
1539   const gchar *in, *in_end;
1540   gchar *out, *result;
1541   int c;
1542   
1543   if (escaped == NULL)
1544     return NULL;
1545
1546   if (len < 0)
1547     len = strlen (escaped);
1548
1549   result = g_malloc (len + 1);
1550   
1551   out = result;
1552   for (in = escaped, in_end = escaped + len; in < in_end; in++)
1553     {
1554       c = *in;
1555
1556       if (c == '%')
1557         {
1558           /* catch partial escape sequences past the end of the substring */
1559           if (in + 3 > in_end)
1560             break;
1561
1562           c = unescape_character (in + 1);
1563
1564           /* catch bad escape sequences and NUL characters */
1565           if (c <= 0)
1566             break;
1567
1568           /* catch escaped ASCII */
1569           if (ascii_must_not_be_escaped && c <= 0x7F)
1570             break;
1571
1572           /* catch other illegal escaped characters */
1573           if (strchr (illegal_escaped_characters, c) != NULL)
1574             break;
1575
1576           in += 2;
1577         }
1578
1579       *out++ = c;
1580     }
1581   
1582   g_assert (out - result <= len);
1583   *out = '\0';
1584
1585   if (in != in_end)
1586     {
1587       g_free (result);
1588       return NULL;
1589     }
1590
1591   return result;
1592 }
1593
1594 static gboolean
1595 is_asciialphanum (gunichar c)
1596 {
1597   return c <= 0x7F && g_ascii_isalnum (c);
1598 }
1599
1600 static gboolean
1601 is_asciialpha (gunichar c)
1602 {
1603   return c <= 0x7F && g_ascii_isalpha (c);
1604 }
1605
1606 /* allows an empty string */
1607 static gboolean
1608 hostname_validate (const char *hostname)
1609 {
1610   const char *p;
1611   gunichar c, first_char, last_char;
1612
1613   p = hostname;
1614   if (*p == '\0')
1615     return TRUE;
1616   do
1617     {
1618       /* read in a label */
1619       c = g_utf8_get_char (p);
1620       p = g_utf8_next_char (p);
1621       if (!is_asciialphanum (c))
1622         return FALSE;
1623       first_char = c;
1624       do
1625         {
1626           last_char = c;
1627           c = g_utf8_get_char (p);
1628           p = g_utf8_next_char (p);
1629         }
1630       while (is_asciialphanum (c) || c == '-');
1631       if (last_char == '-')
1632         return FALSE;
1633       
1634       /* if that was the last label, check that it was a toplabel */
1635       if (c == '\0' || (c == '.' && *p == '\0'))
1636         return is_asciialpha (first_char);
1637     }
1638   while (c == '.');
1639   return FALSE;
1640 }
1641
1642 /**
1643  * g_filename_from_uri:
1644  * @uri: a uri describing a filename (escaped, encoded in ASCII).
1645  * @hostname: Location to store hostname for the URI, or %NULL.
1646  *            If there is no hostname in the URI, %NULL will be
1647  *            stored in this location.
1648  * @error: location to store the error occuring, or %NULL to ignore
1649  *         errors. Any of the errors in #GConvertError may occur.
1650  * 
1651  * Converts an escaped ASCII-encoded URI to a local filename in the
1652  * encoding used for filenames. 
1653  * 
1654  * Return value: a newly-allocated string holding the resulting
1655  *               filename, or %NULL on an error.
1656  **/
1657 gchar *
1658 g_filename_from_uri (const gchar *uri,
1659                      gchar      **hostname,
1660                      GError     **error)
1661 {
1662   const char *path_part;
1663   const char *host_part;
1664   char *unescaped_hostname;
1665   char *result;
1666   char *filename;
1667   int offs;
1668 #ifdef G_OS_WIN32
1669   char *p, *slash;
1670 #endif
1671
1672   if (hostname)
1673     *hostname = NULL;
1674
1675   if (!has_case_prefix (uri, "file:/"))
1676     {
1677       g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_BAD_URI,
1678                    _("The URI '%s' is not an absolute URI using the \"file\" scheme"),
1679                    uri);
1680       return NULL;
1681     }
1682   
1683   path_part = uri + strlen ("file:");
1684   
1685   if (strchr (path_part, '#') != NULL)
1686     {
1687       g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_BAD_URI,
1688                    _("The local file URI '%s' may not include a '#'"),
1689                    uri);
1690       return NULL;
1691     }
1692         
1693   if (has_case_prefix (path_part, "///")) 
1694     path_part += 2;
1695   else if (has_case_prefix (path_part, "//"))
1696     {
1697       path_part += 2;
1698       host_part = path_part;
1699
1700       path_part = strchr (path_part, '/');
1701
1702       if (path_part == NULL)
1703         {
1704           g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_BAD_URI,
1705                        _("The URI '%s' is invalid"),
1706                        uri);
1707           return NULL;
1708         }
1709
1710       unescaped_hostname = g_unescape_uri_string (host_part, path_part - host_part, "", TRUE);
1711
1712       if (unescaped_hostname == NULL ||
1713           !hostname_validate (unescaped_hostname))
1714         {
1715           g_free (unescaped_hostname);
1716           g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_BAD_URI,
1717                        _("The hostname of the URI '%s' is invalid"),
1718                        uri);
1719           return NULL;
1720         }
1721       
1722       if (hostname)
1723         *hostname = unescaped_hostname;
1724       else
1725         g_free (unescaped_hostname);
1726     }
1727
1728   filename = g_unescape_uri_string (path_part, -1, "/", FALSE);
1729
1730   if (filename == NULL)
1731     {
1732       g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_BAD_URI,
1733                    _("The URI '%s' contains invalidly escaped characters"),
1734                    uri);
1735       return NULL;
1736     }
1737
1738   offs = 0;
1739 #ifdef G_OS_WIN32
1740   /* Drop localhost */
1741   if (hostname && *hostname != NULL &&
1742       g_ascii_strcasecmp (*hostname, "localhost") == 0)
1743     {
1744       g_free (*hostname);
1745       *hostname = NULL;
1746     }
1747
1748   /* Turn slashes into backslashes, because that's the canonical spelling */
1749   p = filename;
1750   while ((slash = strchr (p, '/')) != NULL)
1751     {
1752       *slash = '\\';
1753       p = slash + 1;
1754     }
1755
1756   /* Windows URIs with a drive letter can be like "file://host/c:/foo"
1757    * or "file://host/c|/foo" (some Netscape versions). In those cases, start
1758    * the filename from the drive letter.
1759    */
1760   if (g_ascii_isalpha (filename[1]))
1761     {
1762       if (filename[2] == ':')
1763         offs = 1;
1764       else if (filename[2] == '|')
1765         {
1766           filename[2] = ':';
1767           offs = 1;
1768         }
1769     }
1770 #endif
1771
1772   result = g_strdup (filename + offs);
1773   g_free (filename);
1774
1775   return result;
1776 }
1777
1778 #ifdef G_OS_WIN32
1779
1780 #undef g_filename_from_uri
1781
1782 gchar *
1783 g_filename_from_uri (const gchar *uri,
1784                      gchar      **hostname,
1785                      GError     **error)
1786 {
1787   gchar *utf8_filename;
1788   gchar *retval = NULL;
1789
1790   utf8_filename = g_filename_from_uri_utf8 (uri, hostname, error);
1791   if (utf8_filename)
1792     {
1793       retval = g_locale_from_utf8 (utf8_filename, -1, NULL, NULL, error);
1794       g_free (utf8_filename);
1795     }
1796   return retval;
1797 }
1798
1799 #endif
1800
1801 /**
1802  * g_filename_to_uri:
1803  * @filename: an absolute filename specified in the GLib file name encoding,
1804  *            which is the on-disk file name bytes on Unix, and UTF-8 on 
1805  *            Windows
1806  * @hostname: A UTF-8 encoded hostname, or %NULL for none.
1807  * @error: location to store the error occuring, or %NULL to ignore
1808  *         errors. Any of the errors in #GConvertError may occur.
1809  * 
1810  * Converts an absolute filename to an escaped ASCII-encoded URI.
1811  * 
1812  * Return value: a newly-allocated string holding the resulting
1813  *               URI, or %NULL on an error.
1814  **/
1815 gchar *
1816 g_filename_to_uri (const gchar *filename,
1817                    const gchar *hostname,
1818                    GError     **error)
1819 {
1820   char *escaped_uri;
1821
1822   g_return_val_if_fail (filename != NULL, NULL);
1823
1824   if (!g_path_is_absolute (filename))
1825     {
1826       g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_NOT_ABSOLUTE_PATH,
1827                    _("The pathname '%s' is not an absolute path"),
1828                    filename);
1829       return NULL;
1830     }
1831
1832   if (hostname &&
1833       !(g_utf8_validate (hostname, -1, NULL)
1834         && hostname_validate (hostname)))
1835     {
1836       g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
1837                    _("Invalid hostname"));
1838       return NULL;
1839     }
1840   
1841 #ifdef G_OS_WIN32
1842   /* Don't use localhost unnecessarily */
1843   if (hostname && g_ascii_strcasecmp (hostname, "localhost") == 0)
1844     hostname = NULL;
1845 #endif
1846
1847   escaped_uri = g_escape_file_uri (hostname, filename);
1848
1849   return escaped_uri;
1850 }
1851
1852 #ifdef G_OS_WIN32
1853
1854 #undef g_filename_to_uri
1855
1856 gchar *
1857 g_filename_to_uri (const gchar *filename,
1858                    const gchar *hostname,
1859                    GError     **error)
1860 {
1861   gchar *utf8_filename;
1862   gchar *retval = NULL;
1863
1864   utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, error);
1865
1866   if (utf8_filename)
1867     {
1868       retval = g_filename_to_uri_utf8 (utf8_filename, hostname, error);
1869       g_free (utf8_filename);
1870     }
1871
1872   return retval;
1873 }
1874
1875 #endif
1876
1877 /**
1878  * g_uri_list_extract_uris:
1879  * @uri_list: an URI list 
1880  *
1881  * Splits an URI list conforming to the text/uri-list
1882  * mime type defined in RFC 2483 into individual URIs,
1883  * discarding any comments. The URIs are not validated.
1884  *
1885  * Returns: a newly allocated %NULL-terminated list of
1886  *   strings holding the individual URIs. The array should
1887  *   be freed with g_strfreev().
1888  *
1889  * Since: 2.6
1890  */
1891 gchar **
1892 g_uri_list_extract_uris (const gchar *uri_list)
1893 {
1894   GSList *uris, *u;
1895   const gchar *p, *q;
1896   gchar **result;
1897   gint n_uris = 0;
1898
1899   uris = NULL;
1900
1901   p = uri_list;
1902
1903   /* We don't actually try to validate the URI according to RFC
1904    * 2396, or even check for allowed characters - we just ignore
1905    * comments and trim whitespace off the ends.  We also
1906    * allow LF delimination as well as the specified CRLF.
1907    *
1908    * We do allow comments like specified in RFC 2483.
1909    */
1910   while (p)
1911     {
1912       if (*p != '#')
1913         {
1914           while (g_ascii_isspace (*p))
1915             p++;
1916
1917           q = p;
1918           while (*q && (*q != '\n') && (*q != '\r'))
1919             q++;
1920
1921           if (q > p)
1922             {
1923               q--;
1924               while (q > p && g_ascii_isspace (*q))
1925                 q--;
1926
1927               if (q > p)
1928                 {
1929                   uris = g_slist_prepend (uris, g_strndup (p, q - p + 1));
1930                   n_uris++;
1931                 }
1932             }
1933         }
1934       p = strchr (p, '\n');
1935       if (p)
1936         p++;
1937     }
1938
1939   result = g_new (gchar *, n_uris + 1);
1940
1941   result[n_uris--] = NULL;
1942   for (u = uris; u; u = u->next)
1943     result[n_uris--] = u->data;
1944
1945   g_slist_free (uris);
1946
1947   return result;
1948 }
1949
1950 static gchar *
1951 make_valid_utf8 (const gchar *name)
1952 {
1953   GString *string;
1954   const gchar *remainder, *invalid;
1955   gint remaining_bytes, valid_bytes;
1956   
1957   string = NULL;
1958   remainder = name;
1959   remaining_bytes = strlen (name);
1960   
1961   while (remaining_bytes != 0) 
1962     {
1963       if (g_utf8_validate (remainder, remaining_bytes, &invalid)) 
1964         break;
1965       valid_bytes = invalid - remainder;
1966     
1967       if (string == NULL) 
1968         string = g_string_sized_new (remaining_bytes);
1969
1970       g_string_append_len (string, remainder, valid_bytes);
1971       g_string_append_c (string, '?');
1972       
1973       remaining_bytes -= valid_bytes + 1;
1974       remainder = invalid + 1;
1975     }
1976   
1977   if (string == NULL)
1978     return g_strdup (name);
1979   
1980   g_string_append (string, remainder);
1981   g_string_append (string, " (invalid encoding)");
1982
1983   g_assert (g_utf8_validate (string->str, -1, NULL));
1984   
1985   return g_string_free (string, FALSE);
1986 }
1987
1988 /**
1989  * g_filename_display_basename:
1990  * @filename: an absolute pathname in the GLib file name encoding
1991  *
1992  * Returns the display basename for the particular filename, guaranteed
1993  * to be valid UTF-8. The display name might not be identical to the filename,
1994  * for instance there might be problems converting it to UTF-8, and some files
1995  * can be translated in the display
1996  *
1997  * You must pass the whole absolute pathname to this functions so that
1998  * translation of well known locations can be done.
1999  *
2000  * This function is preferred over g_filename_display_name() if you know the
2001  * whole path, as it allows translation.
2002  *
2003  * Return value: a newly allocated string containing
2004  *   a rendition of the basename of the filename in valid UTF-8
2005  *
2006  * Since: 2.6
2007  **/
2008 gchar *
2009 g_filename_display_basename (const gchar *filename)
2010 {
2011   char *basename;
2012   char *display_name;
2013
2014   g_return_val_if_fail (filename != NULL, NULL);
2015   
2016   basename = g_path_get_basename (filename);
2017   display_name = g_filename_display_name (basename);
2018   g_free (basename);
2019   return display_name;
2020 }
2021
2022 /**
2023  * g_filename_display_name:
2024  * @filename: a pathname hopefully in the GLib file name encoding
2025  * 
2026  * Converts a filename into a valid UTF-8 string. The 
2027  * conversion is not necessarily reversible, so you 
2028  * should keep the original around and use the return
2029  * value of this function only for display purposes.
2030  * Unlike g_filename_to_utf8(), the result is guaranteed 
2031  * to be non-NULL even if the filename actually isn't in the GLib
2032  * file name encoding.
2033  *
2034  * If you know the whole pathname of the file you should use
2035  * g_filename_display_basename(), since that allows location-based
2036  * translation of filenames.
2037  *
2038  * Return value: a newly allocated string containing
2039  *   a rendition of the filename in valid UTF-8
2040  *
2041  * Since: 2.6
2042  **/
2043 gchar *
2044 g_filename_display_name (const gchar *filename)
2045 {
2046   gint i;
2047   const gchar **charsets;
2048   gchar *display_name = NULL;
2049   gboolean is_utf8;
2050  
2051   is_utf8 = g_get_filename_charsets (&charsets);
2052
2053   if (is_utf8)
2054     {
2055       if (g_utf8_validate (filename, -1, NULL))
2056         display_name = g_strdup (filename);
2057     }
2058   
2059   if (!display_name)
2060     {
2061       /* Try to convert from the filename charsets to UTF-8.
2062        * Skip the first charset if it is UTF-8.
2063        */
2064       for (i = is_utf8 ? 1 : 0; charsets[i]; i++)
2065         {
2066           display_name = g_convert (filename, -1, "UTF-8", charsets[i], 
2067                                     NULL, NULL, NULL);
2068
2069           if (display_name)
2070             break;
2071         }
2072     }
2073   
2074   /* if all conversions failed, we replace invalid UTF-8
2075    * by a question mark
2076    */
2077   if (!display_name) 
2078     display_name = make_valid_utf8 (filename);
2079
2080   return display_name;
2081 }
2082
2083 #define __G_CONVERT_C__
2084 #include "galiasdef.c"