You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
172 lines
5.5 KiB
C
172 lines
5.5 KiB
C
|
|
#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);
|
|
}
|