1 /*
2 parser.c
3 Copyright (C) 2017 Belledonne Communications SARL
4 
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18 */
19 
20 
21 #include "bctoolbox/port.h"
22 #include "bctoolbox/parser.h"
23 #include "bctoolbox/logging.h"
24 
25 
26 
bctbx_escape(const char * buff,const bctbx_noescape_rules_t noescapes)27 char* bctbx_escape(const char* buff, const bctbx_noescape_rules_t noescapes) {
28 	size_t outbuf_size=strlen(buff);
29 	size_t orig_size=outbuf_size;
30 	char *output_buff=(char*)bctbx_malloc(outbuf_size + 1);
31 	int i;
32 	size_t out_buff_index=0;
33 
34 	for(i=0; buff[i] != '\0'; i++) {
35 		int c = ((unsigned char*)buff)[i];
36 		if (outbuf_size < out_buff_index + 3){
37 			// we will possibly add 3 chars
38 			outbuf_size += MAX(orig_size/2,3);
39 			output_buff = bctbx_realloc(output_buff, outbuf_size + 1);
40 		}
41 		if (noescapes[c] == 1) {
42 			output_buff[out_buff_index++]=c;
43 		} else {
44 			// this will write 3 characters
45 			out_buff_index+=snprintf(output_buff+out_buff_index, outbuf_size +1 - out_buff_index, "%%%02x", c);
46 		}
47 	}
48 	output_buff[out_buff_index]='\0';
49 	return output_buff;
50 }
51 
bctbx_noescape_rules_add_list(bctbx_noescape_rules_t noescapes,const char * allowed)52 void bctbx_noescape_rules_add_list(bctbx_noescape_rules_t noescapes, const char *allowed) {
53 	while (*allowed) {
54 		noescapes[(unsigned int) *allowed] = 1;
55 		++allowed;
56 	}
57 }
58 
bctbx_noescape_rules_add_range(bctbx_noescape_rules_t noescapes,char first,char last)59 void bctbx_noescape_rules_add_range(bctbx_noescape_rules_t noescapes, char first, char last) {
60 	memset(noescapes + (unsigned int)first, 1, last-first+1);
61 }
62 
bctbx_noescape_rules_add_alfanums(bctbx_noescape_rules_t noescapes)63 void bctbx_noescape_rules_add_alfanums(bctbx_noescape_rules_t noescapes) {
64 	bctbx_noescape_rules_add_range(noescapes, '0', '9');
65 	bctbx_noescape_rules_add_range(noescapes, 'A', 'Z');
66 	bctbx_noescape_rules_add_range(noescapes, 'a', 'z');
67 }
68 
is_escaped_char(const char * a)69 static int is_escaped_char(const char *a){
70 	return a[0] == '%' && a[1] != '\0' && a[2] != '\0';
71 }
72 
bctbx_get_char(const char * a,char * out)73 size_t bctbx_get_char (const char*a, char*out) {
74 	if (is_escaped_char(a)) {
75 		unsigned int tmp;
76 		sscanf(a+1,"%02x",&tmp);
77 		*out=(char)tmp;
78 		return 3;
79 	} else {
80 		*out=*a;
81 		return 1;
82 	}
83 }
84 
bctbx_unescaped_string(const char * buff)85 char* bctbx_unescaped_string(const char* buff) {
86 	char *output_buff=bctbx_malloc(strlen(buff)+1);
87 	size_t i;
88 	size_t out_buff_index=0;
89 
90 	for(i=0; buff[i]!='\0'; out_buff_index++) {
91 		i+=bctbx_get_char(buff+i,output_buff+out_buff_index);
92 	}
93 	output_buff[out_buff_index]='\0';
94 	return output_buff;
95 }
96