1 /* radare - LGPL - Copyright 2009-2020 - pancake */
2 
3 #include <r_util.h>
4 
5 /* Validate if char is printable , why not use ISPRINTABLE() ?? */
r_name_validate_print(const char ch)6 R_API bool r_name_validate_print(const char ch) {
7 	// TODO: support utf8
8 	if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || IS_DIGIT (ch)) {
9 		return true;
10 	}
11 	switch (ch) {
12 	case '(':
13 	case ')':
14 	case '[':
15 	case ']':
16 	case '<':
17 	case '+':
18 	case '-':
19 	case '>':
20 	case '$':
21 	case '%':
22 	case '@':
23 	case ' ':
24 	case '.':
25 	case ',':
26 	case ':':
27 	case '_':
28 		return true;
29 	case '\b':
30 	case '\t':
31 	case '\n':
32 	case '\r':
33 		// must be replaced with ' ' and trimmed later
34 		return false;
35 	}
36 	return false;
37 }
38 
39 // used to determine if we want to replace those chars with '_' in r_name_filter()
r_name_validate_dash(const char ch)40 R_API bool r_name_validate_dash(const char ch) {
41 	switch (ch) {
42 	case ' ':
43 	case '-':
44 	case '_':
45 	case '/':
46 	case '\\':
47 	case '(':
48 	case ')':
49 	case '[':
50 	case ']':
51 	case '<':
52 	case '>':
53 	case '!':
54 	case '?':
55 	case '$':
56 	case ';':
57 	case '%':
58 	case '@':
59 	case '`':
60 	case ',':
61 	case '"':
62 		return true;
63 	}
64 	return false;
65 }
66 
r_name_validate_char(const char ch)67 R_API bool r_name_validate_char(const char ch) {
68 	if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || IS_DIGIT (ch)) {
69 		return true;
70 	}
71 	switch (ch) {
72 	case '.':
73 	case ':':
74 	case '_':
75 		return true;
76 	}
77 	return false;
78 }
79 
r_name_validate_first(const char ch)80 R_API bool r_name_validate_first(const char ch) {
81 	if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) {
82 		return true;
83 	}
84 	switch (ch) {
85 	case '_':
86 	case ':':
87 		return true;
88 	}
89 	return false;
90 }
91 
r_name_check(const char * s)92 R_API bool r_name_check(const char *s) {
93 	if (!r_name_validate_first (*s)) {
94 		return false;
95 	}
96 	for (s++; *s; s++) {
97 		if (!r_name_validate_char (*s)) {
98 			return false;
99 		}
100 	}
101 	return true;
102 }
103 
is_special_char(char n)104 static inline bool is_special_char(char n) {
105 	return (n == 'b' || n == 'f' || n == 'n' || n == 'r' || n == 't' || n == 'v' || n == 'a');
106 }
107 
r_name_filter_ro(const char * a)108 R_API const char *r_name_filter_ro(const char *a) {
109 	while (*a++ == '_');
110 	return a - 1;
111 }
112 
113 // filter string for printing purposes
r_name_filter_print(char * s)114 R_API bool r_name_filter_print(char *s) {
115 	char *es = s + strlen (s);
116 	char *os = s;
117 	while (*s && s < es) {
118 		int us = r_utf8_size ((const ut8*)s);
119 		if (us > 1) {
120 			s += us;
121 			continue;
122 		}
123 		if (!r_name_validate_print (*s)) {
124 			r_str_cpy (s, s + 1);
125 		}
126 		s++;
127 	}
128 	return os;
129 }
130 
r_name_filter(char * s,int maxlen)131 R_API bool r_name_filter(char *s, int maxlen) {
132 	// if maxlen == -1 : R_FLAG_NAME_SIZE
133 	// maxlen is ignored, the function signature must change
134 	if (maxlen > 0) {
135 		int slen = strlen (s);
136 		if (slen > maxlen) {
137 			s[maxlen] = 0;
138 		}
139 	}
140 	char *os = s;
141 	while (*s) {
142 		if (r_name_validate_first (*s)) {
143 			break;
144 		}
145 		if (r_name_validate_dash (*s)) {
146 			*s = '_';
147 			break;
148 		}
149 		r_str_cpy (s, s + 1);
150 	}
151 	for (s++; *s; s++) {
152 		if (*s == '\\') {
153 			if (is_special_char (s[1])) {
154 				*s = '_';
155 			} else {
156 				r_str_cpy (s, s + 1);
157 				s--;
158 			}
159 		}
160 		if (!r_name_validate_char (*s)) {
161 			if (r_name_validate_dash (*s)) {
162 				*s = '_';
163 			} else {
164 				r_str_cpy (s, s + 1);
165 				s--;
166 			}
167 		}
168 	}
169 	r_str_trim (os);
170 	return r_name_check (os);
171 }
172 
r_name_filter2(const char * name)173 R_API char *r_name_filter2(const char *name) {
174 	char *s = strdup (name);
175 	r_name_filter (s, -1);
176 	return s;
177 }
178