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