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