-
Notifications
You must be signed in to change notification settings - Fork 0
/
echttp_encoding.c
116 lines (105 loc) · 3.63 KB
/
echttp_encoding.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
/* echttp - Embedded HTTP server.
*
* Copyright 2019, Pascal Martin
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*
* ------------------------------------------------------------------------
* A module to handle the HTTP encoding rules.
*
* char *echttp_encoding_escape (const char *s, char *d, int size);
*
* This function encodes the s string and stores the result to d.
* The result string cannot be longer than the specified size.
* The d parameter is returned (to allow using the function in a parameter
* list).
*
* char *echttp_encoding_unescape (char *data);
*
* This function decodes the HTTP escape sequence and restore the original
* data. The change is made in the original string. The data parameter is
* returned (to allow using this function in a parameter list).
*
*/
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "echttp_encoding.h"
static int echttp_encoding_hextoi (char a) {
if (isdigit(a)) return a - '0';
return tolower(a) - 'a' + 10;
}
static char echttp_encoding_itohex (unsigned int a) {
if (a > 15) return 'F';
if (a < 0) return '0';
if (a < 10) return '0' + a;
return 'A' + a - 10;
}
static char echttp_encoding_table[128]; // Encoding for punctuation.
static void echttp_encoding_init (void) {
echttp_encoding_table['%'] = 1; // Used as the "initialized" flag.
echttp_encoding_table[','] = 1;
echttp_encoding_table['/'] = 1;
echttp_encoding_table[':'] = 1;
echttp_encoding_table[';'] = 1;
echttp_encoding_table['<'] = 1;
echttp_encoding_table['='] = 1;
echttp_encoding_table['>'] = 1;
echttp_encoding_table['?'] = 1;
echttp_encoding_table['@'] = 1;
echttp_encoding_table['['] = 1;
echttp_encoding_table['\\'] = 1;
echttp_encoding_table[']'] = 1;
echttp_encoding_table['^'] = 1;
echttp_encoding_table['`'] = 1;
}
char *echttp_encoding_unescape (char *data) {
char *f = data;
char *t = data;
while (*f) {
if (*f == '%') {
if ((!isxdigit(f[1])) || (!isxdigit(f[2]))) return 0;
*t = 16 * echttp_encoding_hextoi(f[1])
+ echttp_encoding_hextoi(f[2]);
f += 2;
} else if (t != f) {
*t = *f;
}
t += 1;
f += 1;
}
*t = 0; // Force a terminator.
return data;
}
char *echttp_encoding_escape (const char *s, char *d, int size) {
int i = 0;
if (!echttp_encoding_table['%']) echttp_encoding_init();
size -= 1; // Reserve space for the null terminator.
while (i < size) {
int c = *(s++) & 0xff;
if (c <= 41 || c >= 123 || echttp_encoding_table[c]) {
if (c <= 0) break;
if (i >= size - 3) break;
d[i++] = '%';
d[i++] = echttp_encoding_itohex (c >> 4);
d[i++] = echttp_encoding_itohex (c & 0x0f);
} else { // Compatible character.
d[i++] = (char)c;
}
}
d[i] = 0;
return d;
}