1d0cef73dSGregory Neil Shapiro /*
25dd76dd0SGregory Neil Shapiro * Copyright (c) 2006 Proofpoint, Inc. and its suppliers.
3d0cef73dSGregory Neil Shapiro * All rights reserved.
4d0cef73dSGregory Neil Shapiro *
5d0cef73dSGregory Neil Shapiro * By using this file, you agree to the terms and conditions set
6d0cef73dSGregory Neil Shapiro * forth in the LICENSE file which can be found at the top level of
7d0cef73dSGregory Neil Shapiro * the sendmail distribution.
8d0cef73dSGregory Neil Shapiro *
9d0cef73dSGregory Neil Shapiro */
10d0cef73dSGregory Neil Shapiro
11d0cef73dSGregory Neil Shapiro #include <sm/gen.h>
12d0cef73dSGregory Neil Shapiro
134313cc83SGregory Neil Shapiro SM_RCSID("@(#)$Id: util.c,v 1.10 2013-11-22 20:51:44 ca Exp $")
14d0cef73dSGregory Neil Shapiro #include <sm/setjmp.h>
15d0cef73dSGregory Neil Shapiro #include <sm/conf.h>
16d0cef73dSGregory Neil Shapiro #include <sm/assert.h>
17d0cef73dSGregory Neil Shapiro #include <sm/heap.h>
18d0cef73dSGregory Neil Shapiro #include <sm/string.h>
19d0cef73dSGregory Neil Shapiro #include <sm/sendmail.h>
20d0cef73dSGregory Neil Shapiro #include <ctype.h>
21d0cef73dSGregory Neil Shapiro
22d0cef73dSGregory Neil Shapiro /*
23d0cef73dSGregory Neil Shapiro ** STR2PRT -- convert "unprintable" characters in a string to \oct
242fb4f839SGregory Neil Shapiro ** (except for some special chars, see below)
25d0cef73dSGregory Neil Shapiro **
26d0cef73dSGregory Neil Shapiro ** Parameters:
272fb4f839SGregory Neil Shapiro ** s -- string to convert [A]
28d0cef73dSGregory Neil Shapiro **
29d0cef73dSGregory Neil Shapiro ** Returns:
302fb4f839SGregory Neil Shapiro ** converted string [S][U]
31d0cef73dSGregory Neil Shapiro ** This is a static local buffer, string must be copied
32d0cef73dSGregory Neil Shapiro ** before this function is called again!
33d0cef73dSGregory Neil Shapiro */
34d0cef73dSGregory Neil Shapiro
35d0cef73dSGregory Neil Shapiro char *
36d0cef73dSGregory Neil Shapiro str2prt(s)
37d0cef73dSGregory Neil Shapiro char *s;
38d0cef73dSGregory Neil Shapiro {
39d0cef73dSGregory Neil Shapiro int l;
40d0cef73dSGregory Neil Shapiro char c, *h;
41d0cef73dSGregory Neil Shapiro bool ok;
42d0cef73dSGregory Neil Shapiro static int len = 0;
43d0cef73dSGregory Neil Shapiro static char *buf = NULL;
44d0cef73dSGregory Neil Shapiro
452fb4f839SGregory Neil Shapiro #if _FFR_LOGASIS >= 1
462fb4f839SGregory Neil Shapiro #define BADCHAR(ch) ((unsigned char)(ch) <= 31)
472fb4f839SGregory Neil Shapiro #else
482fb4f839SGregory Neil Shapiro #define BADCHAR(ch) (!(isascii(ch) && isprint(ch)))
492fb4f839SGregory Neil Shapiro #endif
502fb4f839SGregory Neil Shapiro
51d0cef73dSGregory Neil Shapiro if (s == NULL)
52d0cef73dSGregory Neil Shapiro return NULL;
53d0cef73dSGregory Neil Shapiro ok = true;
54d0cef73dSGregory Neil Shapiro for (h = s, l = 1; *h != '\0'; h++, l++)
55d0cef73dSGregory Neil Shapiro {
56d0cef73dSGregory Neil Shapiro if (*h == '\\')
57d0cef73dSGregory Neil Shapiro {
58d0cef73dSGregory Neil Shapiro ++l;
59d0cef73dSGregory Neil Shapiro ok = false;
60d0cef73dSGregory Neil Shapiro }
612fb4f839SGregory Neil Shapiro else if (BADCHAR(*h))
62d0cef73dSGregory Neil Shapiro {
63d0cef73dSGregory Neil Shapiro l += 3;
64d0cef73dSGregory Neil Shapiro ok = false;
65d0cef73dSGregory Neil Shapiro }
66d0cef73dSGregory Neil Shapiro }
67d0cef73dSGregory Neil Shapiro if (ok)
68d0cef73dSGregory Neil Shapiro return s;
69d0cef73dSGregory Neil Shapiro if (l > len)
70d0cef73dSGregory Neil Shapiro {
71d0cef73dSGregory Neil Shapiro char *nbuf = sm_pmalloc_x(l);
72d0cef73dSGregory Neil Shapiro
73d0cef73dSGregory Neil Shapiro if (buf != NULL)
74d0cef73dSGregory Neil Shapiro sm_free(buf);
75d0cef73dSGregory Neil Shapiro len = l;
76d0cef73dSGregory Neil Shapiro buf = nbuf;
77d0cef73dSGregory Neil Shapiro }
78d0cef73dSGregory Neil Shapiro for (h = buf; *s != '\0' && l > 0; s++, l--)
79d0cef73dSGregory Neil Shapiro {
80d0cef73dSGregory Neil Shapiro c = *s;
812fb4f839SGregory Neil Shapiro if (c != '\\' && !BADCHAR(c))
82d0cef73dSGregory Neil Shapiro {
83d0cef73dSGregory Neil Shapiro *h++ = c;
84d0cef73dSGregory Neil Shapiro }
85d0cef73dSGregory Neil Shapiro else
86d0cef73dSGregory Neil Shapiro {
87d0cef73dSGregory Neil Shapiro *h++ = '\\';
88d0cef73dSGregory Neil Shapiro --l;
89d0cef73dSGregory Neil Shapiro switch (c)
90d0cef73dSGregory Neil Shapiro {
91d0cef73dSGregory Neil Shapiro case '\\':
92d0cef73dSGregory Neil Shapiro *h++ = '\\';
93d0cef73dSGregory Neil Shapiro break;
94d0cef73dSGregory Neil Shapiro case '\t':
95d0cef73dSGregory Neil Shapiro *h++ = 't';
96d0cef73dSGregory Neil Shapiro break;
97d0cef73dSGregory Neil Shapiro case '\n':
98d0cef73dSGregory Neil Shapiro *h++ = 'n';
99d0cef73dSGregory Neil Shapiro break;
100d0cef73dSGregory Neil Shapiro case '\r':
101d0cef73dSGregory Neil Shapiro *h++ = 'r';
102d0cef73dSGregory Neil Shapiro break;
103d0cef73dSGregory Neil Shapiro default:
104d0cef73dSGregory Neil Shapiro SM_ASSERT(l >= 2);
105d0cef73dSGregory Neil Shapiro (void) sm_snprintf(h, l, "%03o",
106d0cef73dSGregory Neil Shapiro (unsigned int)((unsigned char) c));
107d0cef73dSGregory Neil Shapiro
108d0cef73dSGregory Neil Shapiro /*
1092fb4f839SGregory Neil Shapiro ** XXX since l is unsigned this may wrap
1102fb4f839SGregory Neil Shapiro ** around if the calculation is screwed up...
111d0cef73dSGregory Neil Shapiro */
112d0cef73dSGregory Neil Shapiro
113d0cef73dSGregory Neil Shapiro l -= 2;
114d0cef73dSGregory Neil Shapiro h += 3;
115d0cef73dSGregory Neil Shapiro break;
116d0cef73dSGregory Neil Shapiro }
117d0cef73dSGregory Neil Shapiro }
118d0cef73dSGregory Neil Shapiro }
119d0cef73dSGregory Neil Shapiro *h = '\0';
120d0cef73dSGregory Neil Shapiro buf[len - 1] = '\0';
121d0cef73dSGregory Neil Shapiro return buf;
122d0cef73dSGregory Neil Shapiro }
123d0cef73dSGregory Neil Shapiro
124d0cef73dSGregory Neil Shapiro /*
125d0cef73dSGregory Neil Shapiro ** QUOTE_INTERNAL_CHARS -- do quoting of internal characters
126d0cef73dSGregory Neil Shapiro **
127d0cef73dSGregory Neil Shapiro ** Necessary to make sure that we don't have metacharacters such
128d0cef73dSGregory Neil Shapiro ** as the internal versions of "$*" or "$&" in a string.
129d0cef73dSGregory Neil Shapiro ** The input and output pointers can be the same.
130d0cef73dSGregory Neil Shapiro **
131d0cef73dSGregory Neil Shapiro ** Parameters:
1322fb4f839SGregory Neil Shapiro ** ibp -- a pointer to the string to translate [x]
1332fb4f839SGregory Neil Shapiro ** obp -- a pointer to an output buffer [i][m:A]
134d0cef73dSGregory Neil Shapiro ** bsp -- pointer to the length of the output buffer
135*d39bd2c1SGregory Neil Shapiro ** rpool -- rpool for allocations
136d0cef73dSGregory Neil Shapiro **
137d0cef73dSGregory Neil Shapiro ** Returns:
138*d39bd2c1SGregory Neil Shapiro ** A possibly new obp (if the buffer needed to grow);
139*d39bd2c1SGregory Neil Shapiro ** if it is different, *bsp will updated to the size of
140d0cef73dSGregory Neil Shapiro ** the new buffer and the caller is responsible for
141d0cef73dSGregory Neil Shapiro ** freeing the memory.
142d0cef73dSGregory Neil Shapiro */
143d0cef73dSGregory Neil Shapiro
144d0cef73dSGregory Neil Shapiro #define SM_MM_QUOTE(ch) (((ch) & 0377) == METAQUOTE || (((ch) & 0340) == 0200))
145d0cef73dSGregory Neil Shapiro
146d0cef73dSGregory Neil Shapiro char *
1472fb4f839SGregory Neil Shapiro #if SM_HEAP_CHECK > 2
quote_internal_chars_tagged(ibp,obp,bsp,rpool,tag,line,group)1482fb4f839SGregory Neil Shapiro quote_internal_chars_tagged
1492fb4f839SGregory Neil Shapiro #else
1502fb4f839SGregory Neil Shapiro quote_internal_chars
1512fb4f839SGregory Neil Shapiro #endif
1522fb4f839SGregory Neil Shapiro (ibp, obp, bsp, rpool
1532fb4f839SGregory Neil Shapiro #if SM_HEAP_CHECK > 2
1542fb4f839SGregory Neil Shapiro , tag, line, group
1552fb4f839SGregory Neil Shapiro #endif
1562fb4f839SGregory Neil Shapiro )
157d0cef73dSGregory Neil Shapiro char *ibp;
158d0cef73dSGregory Neil Shapiro char *obp;
159d0cef73dSGregory Neil Shapiro int *bsp;
1602fb4f839SGregory Neil Shapiro SM_RPOOL_T *rpool;
1612fb4f839SGregory Neil Shapiro #if SM_HEAP_CHECK > 2
1622fb4f839SGregory Neil Shapiro char *tag;
1632fb4f839SGregory Neil Shapiro int line;
1642fb4f839SGregory Neil Shapiro int group;
1652fb4f839SGregory Neil Shapiro #else
1662fb4f839SGregory Neil Shapiro # define tag "quote_internal_chars"
1672fb4f839SGregory Neil Shapiro # define line 1
1682fb4f839SGregory Neil Shapiro # define group 1
1692fb4f839SGregory Neil Shapiro #endif
170d0cef73dSGregory Neil Shapiro {
171d0cef73dSGregory Neil Shapiro char *ip, *op;
172d0cef73dSGregory Neil Shapiro int bufused, olen;
173d0cef73dSGregory Neil Shapiro bool buffer_same, needs_quoting;
174d0cef73dSGregory Neil Shapiro
175*d39bd2c1SGregory Neil Shapiro if (NULL == ibp)
176*d39bd2c1SGregory Neil Shapiro return NULL;
177d0cef73dSGregory Neil Shapiro buffer_same = ibp == obp;
178*d39bd2c1SGregory Neil Shapiro SM_REQUIRE(NULL != bsp);
179*d39bd2c1SGregory Neil Shapiro if (NULL == obp)
180*d39bd2c1SGregory Neil Shapiro *bsp = 0;
181d0cef73dSGregory Neil Shapiro needs_quoting = false;
182d0cef73dSGregory Neil Shapiro
183d0cef73dSGregory Neil Shapiro /* determine length of output string (starts at 1 for trailing '\0') */
184d0cef73dSGregory Neil Shapiro for (ip = ibp, olen = 1; *ip != '\0'; ip++, olen++)
185d0cef73dSGregory Neil Shapiro {
186d0cef73dSGregory Neil Shapiro if (SM_MM_QUOTE(*ip))
187d0cef73dSGregory Neil Shapiro {
188d0cef73dSGregory Neil Shapiro olen++;
189d0cef73dSGregory Neil Shapiro needs_quoting = true;
190d0cef73dSGregory Neil Shapiro }
191d0cef73dSGregory Neil Shapiro }
192d0cef73dSGregory Neil Shapiro
193d0cef73dSGregory Neil Shapiro /* is the output buffer big enough? */
194d0cef73dSGregory Neil Shapiro if (olen > *bsp)
195d0cef73dSGregory Neil Shapiro {
1962fb4f839SGregory Neil Shapiro obp = sm_rpool_malloc_tagged_x(rpool, olen, tag, line, group);
197d0cef73dSGregory Neil Shapiro buffer_same = false;
198d0cef73dSGregory Neil Shapiro *bsp = olen;
199d0cef73dSGregory Neil Shapiro }
200d0cef73dSGregory Neil Shapiro
201d0cef73dSGregory Neil Shapiro /*
202d0cef73dSGregory Neil Shapiro ** shortcut: no change needed?
203d0cef73dSGregory Neil Shapiro ** Note: we don't check this first as some bozo may use the same
204d0cef73dSGregory Neil Shapiro ** buffers but restrict the size of the output buffer to less
205d0cef73dSGregory Neil Shapiro ** than the length of the input buffer in which case we need to
206d0cef73dSGregory Neil Shapiro ** allocate a new buffer.
207d0cef73dSGregory Neil Shapiro */
208d0cef73dSGregory Neil Shapiro
209d0cef73dSGregory Neil Shapiro if (!needs_quoting)
210d0cef73dSGregory Neil Shapiro {
211d0cef73dSGregory Neil Shapiro if (!buffer_same)
212d0cef73dSGregory Neil Shapiro {
213d0cef73dSGregory Neil Shapiro bufused = sm_strlcpy(obp, ibp, *bsp);
214d0cef73dSGregory Neil Shapiro SM_ASSERT(bufused <= olen);
215d0cef73dSGregory Neil Shapiro }
216d0cef73dSGregory Neil Shapiro return obp;
217d0cef73dSGregory Neil Shapiro }
218d0cef73dSGregory Neil Shapiro
219d0cef73dSGregory Neil Shapiro if (buffer_same)
220d0cef73dSGregory Neil Shapiro {
2212fb4f839SGregory Neil Shapiro obp = sm_malloc_tagged_x(olen, tag, line + 1, group);
222d0cef73dSGregory Neil Shapiro buffer_same = false;
223d0cef73dSGregory Neil Shapiro *bsp = olen;
224d0cef73dSGregory Neil Shapiro }
225d0cef73dSGregory Neil Shapiro
226d0cef73dSGregory Neil Shapiro for (ip = ibp, op = obp, bufused = 0; *ip != '\0'; ip++)
227d0cef73dSGregory Neil Shapiro {
228d0cef73dSGregory Neil Shapiro if (SM_MM_QUOTE(*ip))
229d0cef73dSGregory Neil Shapiro {
230d0cef73dSGregory Neil Shapiro SM_ASSERT(bufused < olen);
231d0cef73dSGregory Neil Shapiro op[bufused++] = METAQUOTE;
232d0cef73dSGregory Neil Shapiro }
233d0cef73dSGregory Neil Shapiro SM_ASSERT(bufused < olen);
234d0cef73dSGregory Neil Shapiro op[bufused++] = *ip;
235d0cef73dSGregory Neil Shapiro }
236d0cef73dSGregory Neil Shapiro op[bufused] = '\0';
237d0cef73dSGregory Neil Shapiro return obp;
238d0cef73dSGregory Neil Shapiro }
2392fb4f839SGregory Neil Shapiro #if SM_HEAP_CHECK <= 2
2402fb4f839SGregory Neil Shapiro # undef tag
2412fb4f839SGregory Neil Shapiro # undef line
2422fb4f839SGregory Neil Shapiro # undef group
2432fb4f839SGregory Neil Shapiro #endif
244d0cef73dSGregory Neil Shapiro
245d0cef73dSGregory Neil Shapiro /*
246d0cef73dSGregory Neil Shapiro ** DEQUOTE_INTERNAL_CHARS -- undo the effect of quote_internal_chars
247d0cef73dSGregory Neil Shapiro **
248d0cef73dSGregory Neil Shapiro ** Parameters:
2492fb4f839SGregory Neil Shapiro ** ibp -- a pointer to the string to be translated. [i]
2502fb4f839SGregory Neil Shapiro ** obp -- a pointer to the output buffer. [x]
2512fb4f839SGregory Neil Shapiro ** Can be the same as ibp.
252d0cef73dSGregory Neil Shapiro ** obs -- the size of the output buffer.
253d0cef73dSGregory Neil Shapiro **
254d0cef73dSGregory Neil Shapiro ** Returns:
255d0cef73dSGregory Neil Shapiro ** number of character added to obp
256d0cef73dSGregory Neil Shapiro */
257d0cef73dSGregory Neil Shapiro
258d0cef73dSGregory Neil Shapiro int
dequote_internal_chars(ibp,obp,obs)259d0cef73dSGregory Neil Shapiro dequote_internal_chars(ibp, obp, obs)
260d0cef73dSGregory Neil Shapiro char *ibp;
261d0cef73dSGregory Neil Shapiro char *obp;
262d0cef73dSGregory Neil Shapiro int obs;
263d0cef73dSGregory Neil Shapiro {
264d0cef73dSGregory Neil Shapiro char *ip, *op;
265d0cef73dSGregory Neil Shapiro int len;
266d0cef73dSGregory Neil Shapiro bool quoted;
267d0cef73dSGregory Neil Shapiro
268d0cef73dSGregory Neil Shapiro quoted = false;
269d0cef73dSGregory Neil Shapiro len = 0;
270d0cef73dSGregory Neil Shapiro for (ip = ibp, op = obp; *ip != '\0'; ip++)
271d0cef73dSGregory Neil Shapiro {
272d0cef73dSGregory Neil Shapiro if ((*ip & 0377) == METAQUOTE && !quoted)
273d0cef73dSGregory Neil Shapiro {
274d0cef73dSGregory Neil Shapiro quoted = true;
275d0cef73dSGregory Neil Shapiro continue;
276d0cef73dSGregory Neil Shapiro }
277d0cef73dSGregory Neil Shapiro if (op < &obp[obs - 1])
278d0cef73dSGregory Neil Shapiro {
279d0cef73dSGregory Neil Shapiro *op++ = *ip;
280d0cef73dSGregory Neil Shapiro ++len;
281d0cef73dSGregory Neil Shapiro }
282d0cef73dSGregory Neil Shapiro quoted = false;
283d0cef73dSGregory Neil Shapiro }
284d0cef73dSGregory Neil Shapiro *op = '\0';
285d0cef73dSGregory Neil Shapiro return len;
286d0cef73dSGregory Neil Shapiro }
287