1 #ifndef EL__UTIL_CONV_H
2 #define EL__UTIL_CONV_H
3 
4 #include "util/string.h"
5 #include "util/time.h" /* timeval_T types */
6 
7 static inline int
is_safe_in_shell(unsigned char c)8 is_safe_in_shell(unsigned char c)
9 {
10 	/* Note: '-' is often used to indicate a command-line option and thus
11 	 * is not always safe. */
12 	return isasciialnum(c)
13 		|| c == '@' || c == '+' || c == '.'
14 		|| c == '/' || c == ':' || c == '_';
15 }
16 
17 
18 long strtolx(unsigned char *, unsigned char **);
19 
20 /* Convert a decimal number to hexadecimal (lowercase) (0 <= a <= 15). */
21 static inline unsigned char
hx(register int a)22 hx(register int a)
23 {
24 	return a >= 10 ? a + 'a' - 10 : a + '0';
25 }
26 
27 /* Convert a decimal number to hexadecimal (uppercase) (0 <= a <= 15). */
28 static inline unsigned char
Hx(register int a)29 Hx(register int a)
30 {
31 	return a >= 10 ? a + 'A' - 10 : a + '0';
32 }
33 
34 /* Convert an hexadecimal char ([0-9][a-z][A-Z]) to
35  * its decimal value (0 <= result <= 15)
36  * returns -1 if parameter is not an hexadecimal char. */
37 static inline int
unhx(register unsigned char a)38 unhx(register unsigned char a)
39 {
40 	if (isdigit(a)) return a - '0';
41 	if (a >= 'a' && a <= 'f') return a - 'a' + 10;
42 	if (a >= 'A' && a <= 'F') return a - 'A' + 10;
43 	return -1;
44 }
45 
46 /* These use granular allocation stuff. */
47 struct string *add_long_to_string(struct string *string, long number);
48 struct string *add_knum_to_string(struct string *string, long number);
49 struct string *add_xnum_to_string(struct string *string, off_t number);
50 struct string *add_duration_to_string(struct string *string, long seconds);
51 struct string *add_timeval_to_string(struct string *string, timeval_T *timeval);
52 
53 #ifdef HAVE_STRFTIME
54 /* Uses strftime() to add @fmt time format to @string. If @time is NULL
55  * time(NULL) will be used. */
56 struct string *add_date_to_string(struct string *string, unsigned char *format, time_t *time);
57 #endif
58 
59 
60 /* Encoders: */
61 /* They encode and add to the string. This way we don't need to first allocate
62  * and encode a temporary string, add it and then free it. Can be used as
63  * backends for encoder. */
64 
65 /* A simple generic encoder. Should maybe take @replaceable as a string so we
66  * could also use it for adding shell safe strings. */
67 struct string *
68 add_string_replace(struct string *string, unsigned char *src, int len,
69 		   unsigned char replaceable, unsigned char replacement);
70 
71 #define add_optname_to_string(str, src, len) \
72 	add_string_replace(str, src, len, '.', '*')
73 
74 /* Maybe a bad name but it is actually the real name, but you may also think of
75  * it as adding the decoded option name. */
76 #define add_real_optname_to_string(str, src, len) \
77 	add_string_replace(str, src, len, '*', '.')
78 
79 /* Convert reserved chars to html &#xx */
80 struct string *add_html_to_string(struct string *string, unsigned char *html, int htmllen);
81 
82 /* Escapes \ and " with a \ */
83 struct string *add_quoted_to_string(struct string *string, unsigned char *q, int qlen);
84 
85 /* Adds ', |len| bytes of |src| with all single-quotes converted to '\'',
86  * and ' to |string|. */
87 struct string *add_shell_quoted_to_string(struct string *string,
88 					  unsigned char *src, int len);
89 
90 /* Escapes non shell safe chars with '_'. */
91 struct string *add_shell_safe_to_string(struct string *string, unsigned char *cmd, int cmdlen);
92 
93 
94 /* These are fast functions to convert integers to string, or to hexadecimal string. */
95 
96 int elinks_ulongcat(unsigned char *s, unsigned int *slen, unsigned long number,
97 		    unsigned int width, unsigned char fillchar, unsigned int base,
98 		    unsigned int upper);
99 
100 int elinks_longcat(unsigned char *s, unsigned int *slen, long number,
101 		   unsigned int width, unsigned char fillchar, unsigned int base,
102 		   unsigned int upper);
103 
104 /* Type casting is enforced, to shorten calls. --Zas */
105 /* unsigned long to decimal string */
106 #define ulongcat(s, slen, number, width, fillchar) \
107 	elinks_ulongcat((unsigned char *) (s), \
108 			(unsigned int *) (slen), \
109 			(unsigned long) (number), \
110 			(unsigned int) (width), \
111 			(unsigned char) (fillchar), \
112 			(unsigned int) 10, \
113 			(unsigned int) 0)
114 
115 /* signed long to decimal string */
116 #define longcat(s, slen, number, width, fillchar) \
117 	 elinks_longcat((unsigned char *) (s), \
118 			(unsigned int *) (slen), \
119 			(long) (number), \
120 			(unsigned int) (width), \
121 			(unsigned char) (fillchar), \
122 			(unsigned int) 10, \
123 			(unsigned int) 0)
124 
125 /* unsigned long to hexadecimal string */
126 #define ulonghexcat(s, slen, number, width, fillchar, upper) \
127 	elinks_ulongcat((unsigned char *) (s), \
128 			(unsigned int *) (slen), \
129 			(unsigned long) (number), \
130 			(unsigned int) (width), \
131 			(unsigned char) (fillchar), \
132 			(unsigned int) 16, \
133 			(unsigned int) (upper))
134 
135 
136 /* XXX: Compatibility only. Remove these at some time. --Zas */
137 #define snprint(str, len, num) ulongcat(str, NULL, num, len, 0);
138 #define snzprint(str, len, num) longcat(str, NULL, num, len, 0);
139 
140 /* Return 0 if starting with jan, 11 for dec, -1 for failure.
141  * @month must be a lowercased string. */
142 int month2num(const unsigned char *month);
143 
144 #include <string.h>
145 
146 /* Trim starting and ending chars equal to @c in string @s.
147  * If @len != NULL, it stores new string length in pointed integer.
148  * It returns @s for convenience. */
149 static inline unsigned char *
trim_chars(unsigned char * s,unsigned char c,int * len)150 trim_chars(unsigned char *s, unsigned char c, int *len)
151 {
152 	int l = strlen(s);
153 	unsigned char *p = s;
154 
155 	while (*p == c) p++, l--;
156 	while (l && p[l - 1] == c) p[--l] = '\0';
157 
158 	memmove(s, p, l + 1);
159 	if (len) *len = l;
160 
161 	return s;
162 }
163 
164 /* Convert a character to {lower|upper}case using the
165  * ASCII character set (as if in the C locale) */
166 int c_tolower(int c);
167 int c_toupper(int c);
168 
169 /* Check whether a character is {lower|upper}case using the
170  * the ASCII character set (as if in the C locale) */
171 int c_islower(int c);
172 int c_isupper(int c);
173 
174 /* Convert uppercase letters in @string with the given @length to lowercase. */
175 static inline void
convert_to_lowercase(unsigned char * string,int length)176 convert_to_lowercase(unsigned char *string, int length)
177 {
178 	for (length--; length >= 0; length--)
179 		if (isupper(string[length]))
180 			string[length] = tolower(string[length]);
181 }
182 
183 /* Convert uppercase letters in @string with the given @length to lowercase
184  * using the ASCII character set (as if in the C locale) */
185 static inline void
convert_to_lowercase_locale_indep(unsigned char * string,int length)186 convert_to_lowercase_locale_indep(unsigned char *string, int length)
187 {
188 	for (length--; length >= 0; length--)
189 		if (c_isupper(string[length]))
190 			string[length] = c_tolower(string[length]);
191 }
192 
193 /* This function drops control chars, nbsp char and limit the number of consecutive
194  * space chars to one. It modifies its argument. */
195 void clr_spaces(unsigned char *str);
196 
197 /* Replace invalid chars in @title with ' ' and trim all starting/ending
198  * spaces. */
199 void sanitize_title(unsigned char *title);
200 
201 /* Returns 0 if @url contains invalid chars, 1 if ok.
202  * It trims starting/ending spaces. */
203 int sanitize_url(unsigned char *url);
204 
205 #endif
206