2005-03-08 Ben Maurer <bmaurer@ximian.com>
[mono.git] / mono / utils / mono-uri.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 #include <glib.h>
23 #include "mono-uri.h"
24
25 typedef enum {
26   UNSAFE_ALL        = 0x1,  /* Escape all unsafe characters   */
27   UNSAFE_ALLOW_PLUS = 0x2,  /* Allows '+'  */
28   UNSAFE_PATH       = 0x4,  /* Allows '/' and '?' and '&' and '='  */
29   UNSAFE_DOS_PATH   = 0x8,  /* Allows '/' and '?' and '&' and '=' and ':' */
30   UNSAFE_HOST       = 0x10, /* Allows '/' and ':' and '@' */
31   UNSAFE_SLASHES    = 0x20  /* Allows all characters except for '/' and '%' */
32 } UnsafeCharacterSet;
33
34 static const guchar acceptable[96] = {
35   /* A table of the ASCII chars from space (32) to DEL (127) */
36   /*      !    "    #    $    %    &    '    (    )    *    +    ,    -    .    / */ 
37   0x00,0x3F,0x20,0x20,0x20,0x00,0x2C,0x3F,0x3F,0x3F,0x3F,0x22,0x20,0x3F,0x3F,0x1C,
38   /* 0    1    2    3    4    5    6    7    8    9    :    ;    <    =    >    ? */
39   0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x38,0x20,0x20,0x2C,0x20,0x2C,
40   /* @    A    B    C    D    E    F    G    H    I    J    K    L    M    N    O */
41   0x30,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,
42   /* P    Q    R    S    T    U    V    W    X    Y    Z    [    \    ]    ^    _ */
43   0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x20,0x20,0x20,0x20,0x3F,
44   /* `    a    b    c    d    e    f    g    h    i    j    k    l    m    n    o */
45   0x20,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,
46   /* p    q    r    s    t    u    v    w    x    y    z    {    |    }    ~  DEL */
47   0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x20,0x20,0x20,0x3F,0x20
48 };
49
50 static const gchar hex[] = "0123456789ABCDEF";
51
52 /* Note: This escape function works on file: URIs, but if you want to
53  * escape something else, please read RFC-2396 */
54 gchar *
55 mono_escape_uri_string (const gchar *string)
56 {
57 #define ACCEPTABLE(a) ((a)>=32 && (a)<128 && (acceptable[(a)-32] & use_mask))
58
59   const gchar *p;
60   gchar *q;
61   gchar *result;
62   int c;
63   gint unacceptable;
64   UnsafeCharacterSet use_mask;
65   
66   unacceptable = 0;
67   use_mask = UNSAFE_DOS_PATH;
68   for (p = string; *p != '\0'; p++)
69     {
70       c = (guchar) *p;
71       if (!ACCEPTABLE (c)) 
72         unacceptable++;
73     }
74   
75   result = g_malloc (p - string + unacceptable * 2 + 1);
76   
77   for (q = result, p = string; *p != '\0'; p++)
78     {
79       c = (guchar) *p;
80       
81       if (!ACCEPTABLE (c))
82         {
83           *q++ = '%'; /* means hex coming */
84           *q++ = hex[c >> 4];
85           *q++ = hex[c & 15];
86         }
87       else
88         *q++ = *p;
89     }
90   
91   *q = '\0';
92   
93   return result;
94 }
95