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 5 : 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 5 : char *p;
55 5 : size_t ls, lp, li, i;
56 :
57 5 : if (!insert || !pattern || !*pattern || !s)
58 0 : return;
59 :
60 5 : ls = strlen(s);
61 5 : lp = strlen(pattern);
62 5 : li = strlen(insert);
63 :
64 5 : if (len == 0)
65 0 : len = ls + 1; /* len is number of *bytes* */
66 :
67 11 : while (lp <= ls && (p = strstr_m(s,pattern))) {
68 6 : 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 6 : if (li != lp) {
77 3 : memmove(p+li,p+lp,strlen(p+lp)+1);
78 : }
79 25 : for (i=0;i<li;i++) {
80 19 : 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 2 : FALL_THROUGH;
89 : case '`':
90 : case '"':
91 : case '\'':
92 : case ';':
93 : case '%':
94 : case '\r':
95 : case '\n':
96 2 : if ( remove_unsafe_characters ) {
97 2 : p[i] = '_';
98 : /* yes this break should be here
99 : * since we want to fall throw if
100 : * not replacing unsafe chars */
101 2 : break;
102 : }
103 17 : FALL_THROUGH;
104 : default:
105 17 : p[i] = insert[i];
106 : }
107 : }
108 6 : s = p + li;
109 6 : ls = ls + li - lp;
110 :
111 6 : if (replace_once)
112 0 : break;
113 : }
114 : }
115 :
116 5 : void string_sub(char *s,const char *pattern, const char *insert, size_t len)
117 : {
118 5 : string_sub2( s, pattern, insert, len, true, false, false );
119 5 : }
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 103581 : _PUBLIC_ void all_string_sub(char *s,const char *pattern,const char *insert, size_t len)
129 : {
130 1639 : char *p;
131 1639 : size_t ls,lp,li;
132 :
133 103581 : if (!insert || !pattern || !s)
134 0 : return;
135 :
136 103581 : ls = strlen(s);
137 103581 : lp = strlen(pattern);
138 103581 : li = strlen(insert);
139 :
140 103581 : if (!*pattern)
141 0 : return;
142 :
143 103581 : if (len == 0)
144 103581 : len = ls + 1; /* len is number of *bytes* */
145 :
146 105671 : while (lp <= ls && (p = strstr_m(s,pattern))) {
147 2090 : 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 2090 : if (li != lp) {
156 98 : memmove(p+li,p+lp,strlen(p+lp)+1);
157 : }
158 2090 : memcpy(p, insert, li);
159 2090 : s = p + li;
160 2090 : 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 302228 : 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 129 : char *p, *in;
177 129 : char *s;
178 129 : char *string;
179 129 : ssize_t ls,lp,li,ld, i;
180 :
181 302228 : if (!insert || !pattern || !*pattern || !src) {
182 0 : return NULL;
183 : }
184 :
185 302228 : string = talloc_strdup(mem_ctx, src);
186 302228 : if (string == NULL) {
187 0 : DEBUG(0, ("talloc_string_sub2: "
188 : "talloc_strdup failed\n"));
189 0 : return NULL;
190 : }
191 :
192 302228 : s = string;
193 :
194 302228 : in = talloc_strdup(mem_ctx, insert);
195 302228 : if (!in) {
196 0 : DEBUG(0, ("talloc_string_sub2: ENOMEM\n"));
197 0 : talloc_free(string);
198 0 : return NULL;
199 : }
200 302228 : ls = (ssize_t)strlen(s);
201 302228 : lp = (ssize_t)strlen(pattern);
202 302228 : li = (ssize_t)strlen(insert);
203 302228 : ld = li - lp;
204 :
205 2398860 : for (i=0;i<li;i++) {
206 2096632 : switch (in[i]) {
207 182 : case '$':
208 : /* allow a trailing $
209 : * (as in machine accounts) */
210 182 : if (allow_trailing_dollar && (i == li - 1 )) {
211 0 : break;
212 : }
213 :
214 0 : FALL_THROUGH;
215 : case '`':
216 : case '"':
217 : case '\'':
218 : case ';':
219 : case '%':
220 : case '\r':
221 : case '\n':
222 182 : if (remove_unsafe_characters) {
223 100 : in[i] = '_';
224 100 : break;
225 : }
226 :
227 : FALL_THROUGH;
228 : default:
229 : /* ok */
230 2095563 : break;
231 : }
232 : }
233 :
234 528378 : while ((p = strstr_m(s,pattern))) {
235 226150 : if (ld > 0) {
236 223356 : int offset = PTR_DIFF(s,string);
237 223356 : string = (char *)talloc_realloc_size(mem_ctx, string,
238 : ls + ld + 1);
239 223356 : 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 223356 : p = string + offset + (p - s);
246 : }
247 226150 : if (li != lp) {
248 225232 : memmove(p+li,p+lp,strlen(p+lp)+1);
249 : }
250 226150 : memcpy(p, in, li);
251 226150 : s = p + li;
252 226150 : ls += ld;
253 :
254 226150 : if (replace_once) {
255 0 : break;
256 : }
257 : }
258 302228 : TALLOC_FREE(in);
259 302228 : return string;
260 : }
261 :
262 : /* Same as string_sub, but returns a talloc'ed string */
263 :
264 234712 : char *talloc_string_sub(TALLOC_CTX *mem_ctx,
265 : const char *src,
266 : const char *pattern,
267 : const char *insert)
268 : {
269 234712 : return talloc_string_sub2(mem_ctx, src, pattern, insert,
270 : true, false, false);
271 : }
272 :
273 63460 : char *talloc_all_string_sub(TALLOC_CTX *ctx,
274 : const char *src,
275 : const char *pattern,
276 : const char *insert)
277 : {
278 63460 : return talloc_string_sub2(ctx, src, pattern, insert,
279 : false, false, false);
280 : }
|