1 /*----------------------------------------------------------------------------*/
2 /* Xymon monitor library.                                                     */
3 /*                                                                            */
4 /* This is a library module, part of libxymon.                                */
5 /* It contains string handling routines.                                      */
6 /*                                                                            */
7 /* Copyright (C) 2002-2011 Henrik Storner <henrik@storner.dk>                 */
8 /*                                                                            */
9 /* This program is released under the GNU General Public License (GPL),       */
10 /* version 2. See the file "COPYING" for details.                             */
11 /*                                                                            */
12 /*----------------------------------------------------------------------------*/
13 
14 static char rcsid[] = "$Id: strfunc.c 7600 2015-03-15 17:55:51Z jccleaver $";
15 
16 #include "config.h"
17 
18 #include <ctype.h>
19 #include <string.h>
20 #include <stdlib.h>
21 #include <stdarg.h>
22 #include <errno.h>
23 
24 #include "libxymon.h"
25 #include "version.h"
26 
27 #define BUFSZINCREMENT 4096
28 
newstrbuffer(int initialsize)29 strbuffer_t *newstrbuffer(int initialsize)
30 {
31 	strbuffer_t *newbuf;
32 
33 	newbuf = calloc(1, sizeof(strbuffer_t));
34 
35 	if (!initialsize) initialsize = 4096;
36 
37 	newbuf->s = (char *)malloc(initialsize);
38 	if (newbuf->s == NULL) {
39 		errprintf("newstrbuffer: Attempt to allocate failed (initialsize=%d): %s\n", initialsize, strerror(errno));
40 		xfree(newbuf);
41 		return NULL;
42 	}
43 	*(newbuf->s) = '\0';
44 	newbuf->sz = initialsize;
45 
46 	return newbuf;
47 }
48 
convertstrbuffer(char * buffer,int bufsz)49 strbuffer_t *convertstrbuffer(char *buffer, int bufsz)
50 {
51 	strbuffer_t *newbuf;
52 
53 	newbuf = calloc(1, sizeof(strbuffer_t));
54 	newbuf->s = buffer;
55 	newbuf->used = strlen(buffer);
56 	newbuf->sz = (bufsz ? bufsz : newbuf->used+1);
57 
58 	return newbuf;
59 }
60 
freestrbuffer(strbuffer_t * buf)61 void freestrbuffer(strbuffer_t *buf)
62 {
63 	if (buf == NULL) return;
64 
65 	if (buf->s) xfree(buf->s);
66 	xfree(buf);
67 }
68 
clearstrbuffer(strbuffer_t * buf)69 void clearstrbuffer(strbuffer_t *buf)
70 {
71 	if (buf == NULL) return;
72 
73 	if (buf->s) {
74 		*(buf->s) = '\0';
75 		buf->used = 0;
76 	}
77 }
78 
grabstrbuffer(strbuffer_t * buf)79 char *grabstrbuffer(strbuffer_t *buf)
80 {
81 	char *result;
82 
83 	if (buf == NULL) return NULL;
84 
85 	result = buf->s;
86 	xfree(buf);
87 
88 	return result;
89 }
90 
dupstrbuffer(char * src)91 strbuffer_t *dupstrbuffer(char *src)
92 {
93 	strbuffer_t *newbuf;
94 	int len = 0;
95 
96 	newbuf = newstrbuffer(0);
97 	if (src) {
98 		newbuf->s = strdup(src);
99 		len = strlen(src);
100 		newbuf->used = newbuf->sz = len;
101 	}
102 
103 	return newbuf;
104 }
105 
strbuf_addtobuffer(strbuffer_t * buf,char * newtext,int newlen)106 static void strbuf_addtobuffer(strbuffer_t *buf, char *newtext, int newlen)
107 {
108 	if (buf->s == NULL) {
109 		buf->used = 0;
110 		buf->sz = newlen + BUFSZINCREMENT;
111 		buf->s = (char *) malloc(buf->sz);
112 		*(buf->s) = '\0';
113 	}
114 	else if ((buf->used + newlen + 1) > buf->sz) {
115 		buf->sz += (newlen + BUFSZINCREMENT);
116 		buf->s = (char *) realloc(buf->s, buf->sz);
117 	}
118 
119 	if (newtext) {
120 		memcpy(buf->s+buf->used, newtext, newlen);
121 		buf->used += newlen;
122 		/* Make sure result buffer is NUL-terminated; newtext might not be. */
123 		*(buf->s + buf->used) = '\0';
124 	}
125 }
126 
addtobuffer(strbuffer_t * buf,char * newtext)127 void addtobuffer(strbuffer_t *buf, char *newtext)
128 {
129 	if (newtext) strbuf_addtobuffer(buf, newtext, strlen(newtext));
130 }
131 
addtobuffer_many(strbuffer_t * buf,...)132 void addtobuffer_many(strbuffer_t *buf, ...)
133 {
134 	va_list ap;
135 	char *newtext;
136 
137 	va_start(ap, buf);
138 	newtext = va_arg(ap, char *);
139 	while (newtext) {
140 		strbuf_addtobuffer(buf, newtext, strlen(newtext));
141 		newtext = va_arg(ap, char *);
142 	}
143 	va_end(ap);
144 }
145 
addtostrbuffer(strbuffer_t * buf,strbuffer_t * newtext)146 void addtostrbuffer(strbuffer_t *buf, strbuffer_t *newtext)
147 {
148 	strbuf_addtobuffer(buf, STRBUF(newtext), STRBUFLEN(newtext));
149 }
150 
addtobufferraw(strbuffer_t * buf,char * newdata,int bytes)151 void addtobufferraw(strbuffer_t *buf, char *newdata, int bytes)
152 {
153 	/* Add binary data to the buffer */
154 	strbuf_addtobuffer(buf, newdata, bytes);
155 }
156 
strbufferchop(strbuffer_t * buf,int count)157 void strbufferchop(strbuffer_t *buf, int count)
158 {
159 	/* Remove COUNT characters from end of buffer */
160 	if ((buf == NULL) || (buf->s == NULL)) return;
161 
162 	if (count >= buf->used) count = buf->used;
163 
164 	buf->used -= count;
165 	*(buf->s+buf->used) = '\0';
166 }
167 
strbufferrecalc(strbuffer_t * buf)168 void strbufferrecalc(strbuffer_t *buf)
169 {
170 	if (buf == NULL) return;
171 
172 	if (buf->s == NULL) {
173 		buf->used = 0;
174 		return;
175 	}
176 
177 	buf->used = strlen(buf->s);
178 }
179 
strbuffergrow(strbuffer_t * buf,int bytes)180 void strbuffergrow(strbuffer_t *buf, int bytes)
181 {
182 	if (buf == NULL) return;
183 
184 	buf->sz += bytes;
185 	buf->s = (char *) realloc(buf->s, buf->sz);
186 }
187 
strbufferuse(strbuffer_t * buf,int bytes)188 void strbufferuse(strbuffer_t *buf, int bytes)
189 {
190 	if (buf == NULL) return;
191 
192 	if ((buf->used + bytes) < buf->sz) {
193 		buf->used += bytes;
194 	}
195 	else {
196 		errprintf("strbuffer: Attempt to use more than allocated (sz=%d, used=%d, growbytes=%d\n",
197 			  buf->sz, buf->used, bytes);
198 	}
199 	*(buf->s+buf->used) = '\0';
200 }
201 
htmlquoted(char * s)202 char *htmlquoted(char *s)
203 {
204 	/*
205 	 * This routine converts a plain string into an html-quoted string
206 	 */
207 
208 	static strbuffer_t *result = NULL;
209 	char *inp, *endp;
210 	char c;
211 
212 	if (!s) return NULL;
213 
214 	if (!result) result = newstrbuffer(4096);
215 	clearstrbuffer(result);
216 
217 	inp = s;
218 	do {
219 		endp = inp + strcspn(inp, "\"&<> ");
220 		c = *endp;
221 		if (endp > inp) addtobufferraw(result, inp, endp-inp);
222 		switch (c) {
223 		  case '"': addtobuffer(result, "&quot;"); break;
224 		  case '&': addtobuffer(result, "&amp;"); break;
225 		  case '<': addtobuffer(result, "&lt;"); break;
226 		  case '>': addtobuffer(result, "&gt;"); break;
227 		  case ' ': addtobuffer(result, "&nbsp;"); break;
228 		  default: break;
229 		}
230 		inp = (c == '\0') ? NULL : endp+1;
231 	} while (inp);
232 
233 	return STRBUF(result);
234 }
235 
prehtmlquoted(char * s)236 char *prehtmlquoted(char *s)
237 {
238 	/*
239 	 * This routine converts a string which may contain html to a string
240 	 * safe to include in a PRE block. It's similar to above, but escapes
241 	 * only the minmum characters for efficiency.
242 	 */
243 
244 	static strbuffer_t *result = NULL;
245 	char *inp, *endp;
246 	char c;
247 
248 	if (!s) return NULL;
249 
250 	if (!result) result = newstrbuffer(4096);
251 	clearstrbuffer(result);
252 
253 	inp = s;
254 	do {
255 		endp = inp + strcspn(inp, "&<>");
256 		c = *endp;
257 		if (endp > inp) addtobufferraw(result, inp, endp-inp);
258 		switch (c) {
259 		  case '&': addtobuffer(result, "&amp;"); break;
260 		  case '<': addtobuffer(result, "&lt;"); break;
261 		  case '>': addtobuffer(result, "&gt;"); break;	// this is not, strictly speaking, needed, but unbalanced encoding might confuse automated readers
262 		  default: break;
263 		}
264 		inp = (c == '\0') ? NULL : endp+1;
265 	} while (inp);
266 
267 	return STRBUF(result);
268 }
269 
replacetext(char * original,char * oldtext,char * newtext)270 strbuffer_t *replacetext(char *original, char *oldtext, char *newtext)
271 {
272 	strbuffer_t *result = newstrbuffer(0);
273 	char *pos = original, *start;
274 
275 	do {
276 		start = pos; pos = strstr(pos, oldtext);
277 		if (pos) {
278 			if (pos > start) strbuf_addtobuffer(result, start, (pos - start));
279 			addtobuffer(result, newtext);
280 			pos += strlen(oldtext);
281 		}
282 		else
283 			addtobuffer(result, start);
284 	} while (pos);
285 
286 	return result;
287 }
288 
289