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, """); break;
224 case '&': addtobuffer(result, "&"); break;
225 case '<': addtobuffer(result, "<"); break;
226 case '>': addtobuffer(result, ">"); break;
227 case ' ': addtobuffer(result, " "); 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, "&"); break;
260 case '<': addtobuffer(result, "<"); break;
261 case '>': addtobuffer(result, ">"); 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