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