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 "includes.h" 25 26/** 27 * @file 28 * @brief Substitute utilities. 29 **/ 30 31/** 32 Substitute a string for a pattern in another string. Make sure there is 33 enough room! 34 35 This routine looks for pattern in s and replaces it with 36 insert. It may do multiple replacements. 37 38 Any of " ; ' $ or ` in the insert string are replaced with _ 39 if len==0 then the string cannot be extended. This is different from the old 40 use of len==0 which was for no length checks to be done. 41**/ 42 43_PUBLIC_ void string_sub(char *s, const char *pattern, const char *insert, size_t len) 44{ 45 char *p; 46 ssize_t ls, lp, li, i; 47 48 if (!insert || !pattern || !*pattern || !s) 49 return; 50 51 ls = (ssize_t)strlen(s); 52 lp = (ssize_t)strlen(pattern); 53 li = (ssize_t)strlen(insert); 54 55 if (len == 0) 56 len = ls + 1; /* len is number of *bytes* */ 57 58 while (lp <= ls && (p = strstr(s, pattern))) { 59 if (ls + (li-lp) >= len) { 60 DEBUG(0,("ERROR: string overflow by %d in string_sub(%.50s, %d)\n", 61 (int)(ls + (li-lp) - len), 62 pattern, (int)len)); 63 break; 64 } 65 if (li != lp) { 66 memmove(p+li,p+lp,strlen(p+lp)+1); 67 } 68 for (i=0;i<li;i++) { 69 switch (insert[i]) { 70 case '`': 71 case '"': 72 case '\'': 73 case ';': 74 case '$': 75 case '%': 76 case '\r': 77 case '\n': 78 p[i] = '_'; 79 break; 80 default: 81 p[i] = insert[i]; 82 } 83 } 84 s = p + li; 85 ls += (li-lp); 86 } 87} 88 89/** 90 * Talloc'ed version of string_sub 91 */ 92_PUBLIC_ char *string_sub_talloc(TALLOC_CTX *mem_ctx, const char *s, 93 const char *pattern, const char *insert) 94{ 95 const char *p; 96 char *ret; 97 size_t len, alloc_len; 98 99 if (insert == NULL || pattern == NULL || !*pattern || s == NULL) 100 return NULL; 101 102 /* determine length needed */ 103 len = strlen(s); 104 105 for (p = strstr(s, pattern); p != NULL; 106 p = strstr(p+strlen(pattern), pattern)) { 107 len += strlen(insert) - strlen(pattern); 108 } 109 110 alloc_len = MAX(len, strlen(s))+1; 111 ret = talloc_array(mem_ctx, char, alloc_len); 112 if (ret == NULL) 113 return NULL; 114 strncpy(ret, s, alloc_len); 115 string_sub(ret, pattern, insert, alloc_len); 116 117 ret = talloc_realloc(mem_ctx, ret, char, len+1); 118 if (ret == NULL) 119 return NULL; 120 121 SMB_ASSERT(ret[len] == '\0'); 122 123 talloc_set_name_const(ret, ret); 124 125 return ret; 126} 127 128/** 129 Similar to string_sub() but allows for any character to be substituted. 130 Use with caution! 131 if len==0 then the string cannot be extended. This is different from the old 132 use of len==0 which was for no length checks to be done. 133**/ 134 135_PUBLIC_ void all_string_sub(char *s,const char *pattern,const char *insert, size_t len) 136{ 137 char *p; 138 ssize_t ls,lp,li; 139 140 if (!insert || !pattern || !s) 141 return; 142 143 ls = (ssize_t)strlen(s); 144 lp = (ssize_t)strlen(pattern); 145 li = (ssize_t)strlen(insert); 146 147 if (!*pattern) 148 return; 149 150 if (len == 0) 151 len = ls + 1; /* len is number of *bytes* */ 152 153 while (lp <= ls && (p = strstr(s,pattern))) { 154 if (ls + (li-lp) >= len) { 155 DEBUG(0,("ERROR: string overflow by %d in all_string_sub(%.50s, %d)\n", 156 (int)(ls + (li-lp) - len), 157 pattern, (int)len)); 158 break; 159 } 160 if (li != lp) { 161 memmove(p+li,p+lp,strlen(p+lp)+1); 162 } 163 memcpy(p, insert, li); 164 s = p + li; 165 ls += (li-lp); 166 } 167} 168