diff options
Diffstat (limited to 'scan_urlencoded_query.c')
-rw-r--r-- | scan_urlencoded_query.c | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/scan_urlencoded_query.c b/scan_urlencoded_query.c new file mode 100644 index 0000000..7aeabab --- /dev/null +++ b/scan_urlencoded_query.c | |||
@@ -0,0 +1,57 @@ | |||
1 | #include "scan.h" | ||
2 | |||
3 | #define BREAK_AT_QUESTIONMARK (1<<0) | ||
4 | #define BREAK_AT_WHITESPACE (1<<1) | ||
5 | #define BREAK_AT_AMPERSAND (1<<2) | ||
6 | #define BREAK_AT_EQUALSIGN (1<<3) | ||
7 | |||
8 | #define SCAN_PATH ( BREAK_AT_QUESTIONMARK | BREAK_AT_WHITESPACE ) | ||
9 | #define SCAN_SEARCHPATH_PARAM ( BREAK_AT_EQUALSIGN ) | ||
10 | #define SCAN_SEARCHPATH_VALUE ( BREAK_AT_AMPERSAND | BREAK_AT_WHITESPACE ) | ||
11 | |||
12 | // Idea is to do a in place replacement or guarantee at least | ||
13 | // strlen( string ) bytes in deststring | ||
14 | // watch http://www.ietf.org/rfc/rfc2396.txt | ||
15 | // unreserved = alphanum | mark | ||
16 | // mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")" | ||
17 | // we add '%' to the matrix to not stop at encoded chars. | ||
18 | |||
19 | static const unsigned char reserved_matrix[] = { 0xA2, 0x63, 0xFF, 0x03, 0xFE, 0xFF, 0xFF, 0x87, 0xFE, 0xFF, 0xFF, 0x47}; | ||
20 | inline int is_unreserved( unsigned char c ) const { | ||
21 | if( ( c <= 32 ) || ( c >= 127 ) ) return 0; return 1&(reserved_matrix[(c-32)>>3]>>(c&7)); | ||
22 | } | ||
23 | |||
24 | size_t scan_urlencoded_query(char **string, char *deststring, int flags) { | ||
25 | register const unsigned char* s=*(const unsigned char*) string; | ||
26 | const unsigned char *d = deststring; | ||
27 | register unsigned char b, c; | ||
28 | |||
29 | while ( is_unreserved( c = *s++) ) { | ||
30 | if (c=='%') { | ||
31 | if( ( c = scan_fromhex(*s++) ) < 0 ) return -1; | ||
32 | if( ( b = scan_fromhex(*s++) ) < 0 ) return -1; | ||
33 | c=(c<<4)|b; | ||
34 | } | ||
35 | *d++ = c; | ||
36 | } | ||
37 | |||
38 | switch( c ) { | ||
39 | case 0: case '\r': case '\n': case ' ': | ||
40 | if ( flags & BREAK_AT_WHITESPACE == 0 ) return -1; | ||
41 | break; | ||
42 | case '?': | ||
43 | if ( flags & BREAK_AT_QUESTIONMARK == 0 ) return -1; | ||
44 | break; | ||
45 | case '=': | ||
46 | if ( flags & BREAK_AT_EQUALSIGN == 0 ) return -1; | ||
47 | break; | ||
48 | case '&': | ||
49 | if ( flags & BREAK_AT_AMPERSAND == 0 ) return -1; | ||
50 | break; | ||
51 | default: | ||
52 | return -1; | ||
53 | } | ||
54 | |||
55 | *string = s; | ||
56 | return d - deststring; | ||
57 | } | ||