the upcoming 2.0 version
https://redmine.lighttpd.net/projects/lighttpd2
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
171 lines
5.5 KiB
171 lines
5.5 KiB
|
|
#include <lighttpd/encoding.h> |
|
|
|
static const gchar hex_chars[] = "0123456789abcdef"; |
|
|
|
/* HEX */ |
|
static const gchar encode_map_hex[] = { |
|
/* |
|
0 1 2 3 4 5 6 7 8 9 A B C D E F |
|
*/ |
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 - 0F */ |
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */ |
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 20 - 2F */ |
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 30 - 3F */ |
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 - 40 */ |
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 50 - 50 */ |
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 - 60 */ |
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 70 - 70 */ |
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 80 - 8F */ |
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 90 - 9F */ |
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* A0 - AF */ |
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* B0 - BF */ |
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* C0 - CF */ |
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* D0 - DF */ |
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* E0 - EF */ |
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* F0 - FF */ |
|
}; |
|
|
|
/* HTML */ |
|
static const gchar encode_map_html[] = { |
|
/* |
|
0 1 2 3 4 5 6 7 8 9 A B C D E F |
|
*/ |
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 - 0F control chars */ |
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */ |
|
0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 20 - 2F & */ |
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, /* 30 - 3F < > */ |
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 40 - 40 */ |
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 50 - 50 */ |
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 60 - 60 */ |
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* 70 - 70 DEL */ |
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 - 8F */ |
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 - 9F */ |
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A0 - AF */ |
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* B0 - BF */ |
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* C0 - CF */ |
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* D0 - DF */ |
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* E0 - EF */ |
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F0 - FF */ |
|
}; |
|
|
|
/* relative URI, everything except: ! ( ) * - . / 0-9 A-Z _ a-z */ |
|
static const gchar encode_map_uri[] = { |
|
/* |
|
0 1 2 3 4 5 6 7 8 9 A B C D E F |
|
*/ |
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 - 0F control chars */ |
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */ |
|
1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, /* 20 - 2F space " # $ % & ' + , */ |
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, /* 30 - 3F : ; < = > ? */ |
|
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 40 - 40 @ */ |
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, /* 50 - 50 [ \ ] ^ */ |
|
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 60 - 60 ` */ |
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, /* 70 - 70 { | } ~ DEL */ |
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 80 - 8F */ |
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 90 - 9F */ |
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* A0 - AF */ |
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* B0 - BF */ |
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* C0 - CF */ |
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* D0 - DF */ |
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* E0 - EF */ |
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* F0 - FF */ |
|
}; |
|
|
|
GString *li_string_encode_append(const gchar *str, GString *dest, liEncoding encoding) { |
|
GString *result; |
|
guchar *c; |
|
guchar *pos = NULL; |
|
gsize new_len = 0; |
|
guint encoded_len = 0; |
|
const gchar *map = NULL; |
|
|
|
switch (encoding) { |
|
case LI_ENCODING_HTML: |
|
/* replace html chars with &#xHH; */ |
|
map = encode_map_html; |
|
encoded_len = 6; |
|
break; |
|
case LI_ENCODING_HEX: |
|
map = encode_map_hex; |
|
encoded_len = 2; |
|
break; |
|
case LI_ENCODING_URI: |
|
/* ? => %HH */ |
|
map = encode_map_uri; |
|
encoded_len = 3; |
|
break; |
|
} |
|
|
|
/* check how many chars need to be encoded */ |
|
for (c = (guchar*)str; *c != '\0'; c++) { |
|
if (map[*c]) |
|
new_len += encoded_len; |
|
else |
|
new_len++; |
|
} |
|
|
|
if (dest) { |
|
gsize oldlen = dest->len; |
|
result = dest; |
|
g_string_set_size(result, dest->len + new_len); |
|
pos = (guchar*) result->str + oldlen; |
|
} else { |
|
result = g_string_sized_new(new_len); |
|
pos = (guchar*) result->str; |
|
} |
|
|
|
switch (encoding) { |
|
case LI_ENCODING_HTML: |
|
for (c = (guchar*)str; *c != '\0'; c++) { |
|
if (map[*c]) { |
|
/* char needs to be encoded */ |
|
/* &#xHH */ |
|
*pos++ = '&'; |
|
*pos++ = '#'; |
|
*pos++ = 'x'; |
|
*pos++ = hex_chars[((*c) >> 4) & 0x0F]; |
|
*pos++ = hex_chars[(*c) & 0x0F]; |
|
*pos++ = ';'; |
|
} else { |
|
/* no encoding needed */ |
|
*pos++ = *c; |
|
} |
|
} |
|
break; |
|
case LI_ENCODING_HEX: |
|
for (c = (guchar*)str; *c != '\0'; c++) { |
|
if (map[*c]) { |
|
/* char needs to be encoded */ |
|
*pos++ = hex_chars[((*c) >> 4) & 0x0F]; |
|
*pos++ = hex_chars[(*c) & 0x0F]; |
|
} else { |
|
/* no encoding needed */ |
|
*pos++ = *c; |
|
} |
|
} |
|
break; |
|
case LI_ENCODING_URI: |
|
for (c = (guchar*)str; *c != '\0'; c++) { |
|
if (map[*c]) { |
|
/* char needs to be encoded */ |
|
*pos++ = '%'; |
|
*pos++ = hex_chars[((*c) >> 4) & 0x0F]; |
|
*pos++ = hex_chars[(*c) & 0x0F]; |
|
} else { |
|
/* no encoding needed */ |
|
*pos++ = *c; |
|
} |
|
} |
|
break; |
|
} |
|
|
|
*pos = '\0'; |
|
|
|
return result; |
|
} |
|
|
|
GString *li_string_encode(const gchar *str, GString *dest, liEncoding encoding) { |
|
if (dest) g_string_truncate(dest, 0); |
|
return li_string_encode_append(str, dest, encoding); |
|
}
|
|
|