Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : Samba utility functions
4 :
5 : Copyright (C) Andrew Tridgell 1992-2001
6 : Copyright (C) Simo Sorce 2001-2002
7 : Copyright (C) Martin Pool 2003
8 : Copyright (C) James Peach 2005
9 :
10 : This program is free software; you can redistribute it and/or modify
11 : it under the terms of the GNU General Public License as published by
12 : the Free Software Foundation; either version 3 of the License, or
13 : (at your option) any later version.
14 :
15 : This program is distributed in the hope that it will be useful,
16 : but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : GNU General Public License for more details.
19 :
20 : You should have received a copy of the GNU General Public License
21 : along with this program. If not, see <http://www.gnu.org/licenses/>.
22 : */
23 :
24 : #include "replace.h"
25 : #include "debug.h"
26 : #ifndef SAMBA_UTIL_CORE_ONLY
27 : #include "charset/charset.h"
28 : #else
29 : #include "charset_compat.h"
30 : #endif
31 : #include "substitute.h"
32 :
33 : /**
34 : * @file
35 : * @brief Substitute utilities.
36 : **/
37 :
38 : /**
39 : Substitute a string for a pattern in another string. Make sure there is
40 : enough room!
41 :
42 : This routine looks for pattern in s and replaces it with
43 : insert. It may do multiple replacements or just one.
44 :
45 : Any of " ; ' $ or ` in the insert string are replaced with _
46 : if len==0 then the string cannot be extended. This is different from the old
47 : use of len==0 which was for no length checks to be done.
48 : **/
49 :
50 0 : static void string_sub2(char *s,const char *pattern, const char *insert, size_t len,
51 : bool remove_unsafe_characters, bool replace_once,
52 : bool allow_trailing_dollar)
53 : {
54 : char *p;
55 : size_t ls, lp, li, i;
56 :
57 0 : if (!insert || !pattern || !*pattern || !s)
58 0 : return;
59 :
60 0 : ls = strlen(s);
61 0 : lp = strlen(pattern);
62 0 : li = strlen(insert);
63 :
64 0 : if (len == 0)
65 0 : len = ls + 1; /* len is number of *bytes* */
66 :
67 0 : while (lp <= ls && (p = strstr_m(s,pattern))) {
68 0 : if (ls + li - lp >= len) {
69 0 : DBG_ERR("ERROR: string overflow by "
70 : "%zu in string_sub(%.50s, %zu)\n",
71 : ls + li - lp + 1 - len,
72 : pattern,
73 : len);
74 0 : break;
75 : }
76 0 : if (li != lp) {
77 0 : memmove(p+li,p+lp,strlen(p+lp)+1);
78 : }
79 0 : for (i=0;i<li;i++) {
80 0 : switch (insert[i]) {
81 0 : case '$':
82 : /* allow a trailing $
83 : * (as in machine accounts) */
84 0 : if (allow_trailing_dollar && (i == li - 1 )) {
85 0 : p[i] = insert[i];
86 0 : break;
87 : }
88 : FALL_THROUGH;
89 : case '`':
90 : case '"':
91 : case '\'':
92 : case ';':
93 : case '%':
94 : case '\r':
95 : case '\n':
96 0 : if ( remove_unsafe_characters ) {
97 0 : p[i] = '_';
98 : /* yes this break should be here
99 : * since we want to fall throw if
100 : * not replacing unsafe chars */
101 0 : break;
102 : }
103 : FALL_THROUGH;
104 : default:
105 0 : p[i] = insert[i];
106 : }
107 : }
108 0 : s = p + li;
109 0 : ls = ls + li - lp;
110 :
111 0 : if (replace_once)
112 0 : break;
113 : }
114 : }
115 :
116 0 : void string_sub(char *s,const char *pattern, const char *insert, size_t len)
117 : {
118 0 : string_sub2( s, pattern, insert, len, true, false, false );
119 0 : }
120 :
121 : /**
122 : Similar to string_sub() but allows for any character to be substituted.
123 : Use with caution!
124 : if len==0 then the string cannot be extended. This is different from the old
125 : use of len==0 which was for no length checks to be done.
126 : **/
127 :
128 13928 : _PUBLIC_ void all_string_sub(char *s,const char *pattern,const char *insert, size_t len)
129 : {
130 : char *p;
131 : size_t ls,lp,li;
132 :
133 13928 : if (!insert || !pattern || !s)
134 0 : return;
135 :
136 13928 : ls = strlen(s);
137 13928 : lp = strlen(pattern);
138 13928 : li = strlen(insert);
139 :
140 13928 : if (!*pattern)
141 0 : return;
142 :
143 13928 : if (len == 0)
144 13928 : len = ls + 1; /* len is number of *bytes* */
145 :
146 25538 : while (lp <= ls && (p = strstr_m(s,pattern))) {
147 1950 : if (ls + li - lp >= len) {
148 0 : DBG_ERR("ERROR: string overflow by "
149 : "%zu in all_string_sub(%.50s, %zu)\n",
150 : ls + li - lp + 1 - len,
151 : pattern,
152 : len);
153 0 : break;
154 : }
155 1950 : if (li != lp) {
156 18 : memmove(p+li,p+lp,strlen(p+lp)+1);
157 : }
158 1950 : memcpy(p, insert, li);
159 1950 : s = p + li;
160 1950 : ls = ls + li - lp;
161 : }
162 : }
163 :
164 : /*
165 : * Internal guts of talloc_string_sub and talloc_all_string_sub.
166 : * talloc version of string_sub2.
167 : */
168 :
169 21115 : char *talloc_string_sub2(TALLOC_CTX *mem_ctx, const char *src,
170 : const char *pattern,
171 : const char *insert,
172 : bool remove_unsafe_characters,
173 : bool replace_once,
174 : bool allow_trailing_dollar)
175 : {
176 : char *p, *in;
177 : char *s;
178 : char *string;
179 : ssize_t ls,lp,li,ld, i;
180 :
181 21115 : if (!insert || !pattern || !*pattern || !src) {
182 0 : return NULL;
183 : }
184 :
185 21115 : string = talloc_strdup(mem_ctx, src);
186 21115 : if (string == NULL) {
187 0 : DEBUG(0, ("talloc_string_sub2: "
188 : "talloc_strdup failed\n"));
189 0 : return NULL;
190 : }
191 :
192 21115 : s = string;
193 :
194 21115 : in = talloc_strdup(mem_ctx, insert);
195 21115 : if (!in) {
196 0 : DEBUG(0, ("talloc_string_sub2: ENOMEM\n"));
197 0 : talloc_free(string);
198 0 : return NULL;
199 : }
200 21115 : ls = (ssize_t)strlen(s);
201 21115 : lp = (ssize_t)strlen(pattern);
202 21115 : li = (ssize_t)strlen(insert);
203 21115 : ld = li - lp;
204 :
205 224349 : for (i=0;i<li;i++) {
206 203234 : switch (in[i]) {
207 490 : case '$':
208 : /* allow a trailing $
209 : * (as in machine accounts) */
210 490 : if (allow_trailing_dollar && (i == li - 1 )) {
211 0 : break;
212 : }
213 :
214 : FALL_THROUGH;
215 : case '`':
216 : case '"':
217 : case '\'':
218 : case ';':
219 : case '%':
220 : case '\r':
221 : case '\n':
222 490 : if (remove_unsafe_characters) {
223 489 : in[i] = '_';
224 489 : break;
225 : }
226 :
227 : FALL_THROUGH;
228 : default:
229 : /* ok */
230 202745 : break;
231 : }
232 : }
233 :
234 50593 : while ((p = strstr_m(s,pattern))) {
235 14465 : if (ld > 0) {
236 14381 : int offset = PTR_DIFF(s,string);
237 14381 : string = (char *)talloc_realloc_size(mem_ctx, string,
238 : ls + ld + 1);
239 14381 : if (!string) {
240 0 : DEBUG(0, ("talloc_string_sub: out of "
241 : "memory!\n"));
242 0 : TALLOC_FREE(in);
243 0 : return NULL;
244 : }
245 14381 : p = string + offset + (p - s);
246 : }
247 14465 : if (li != lp) {
248 14465 : memmove(p+li,p+lp,strlen(p+lp)+1);
249 : }
250 14465 : memcpy(p, in, li);
251 14465 : s = p + li;
252 14465 : ls += ld;
253 :
254 14465 : if (replace_once) {
255 0 : break;
256 : }
257 : }
258 21115 : TALLOC_FREE(in);
259 21115 : return string;
260 : }
261 :
262 : /* Same as string_sub, but returns a talloc'ed string */
263 :
264 17024 : char *talloc_string_sub(TALLOC_CTX *mem_ctx,
265 : const char *src,
266 : const char *pattern,
267 : const char *insert)
268 : {
269 17024 : return talloc_string_sub2(mem_ctx, src, pattern, insert,
270 : true, false, false);
271 : }
272 :
273 4091 : char *talloc_all_string_sub(TALLOC_CTX *ctx,
274 : const char *src,
275 : const char *pattern,
276 : const char *insert)
277 : {
278 4091 : return talloc_string_sub2(ctx, src, pattern, insert,
279 : false, false, false);
280 : }
|