1 /* ====================================================================
2  * The Kannel Software License, Version 1.0
3  *
4  * Copyright (c) 2001-2014 Kannel Group
5  * Copyright (c) 1998-2001 WapIT Ltd.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  *    if any, must include the following acknowledgment:
22  *       "This product includes software developed by the
23  *        Kannel Group (http://www.kannel.org/)."
24  *    Alternately, this acknowledgment may appear in the software itself,
25  *    if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Kannel" and "Kannel Group" must not be used to
28  *    endorse or promote products derived from this software without
29  *    prior written permission. For written permission, please
30  *    contact org@kannel.org.
31  *
32  * 5. Products derived from this software may not be called "Kannel",
33  *    nor may "Kannel" appear in their name, without prior written
34  *    permission of the Kannel Group.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED.  IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS
40  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
41  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
42  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
43  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
45  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
46  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of the Kannel Group.  For more information on
51  * the Kannel Group, please see <http://www.kannel.org/>.
52  *
53  * Portions of this software are based upon software originally written at
54  * WapIT Ltd., Helsinki, Finland for the Kannel project.
55  */
56 
57 /*
58  * octstr.c - implementation of Octet strings
59  *
60  * See octstr.h for explanations of what public functions should do.
61  *
62  * Lars Wirzenius
63  */
64 
65 
66 #include <ctype.h>
67 #include <limits.h>
68 #include <errno.h>
69 #include <stdlib.h>
70 #include <string.h>
71 #include <unistd.h>
72 #include <sys/types.h>
73 #include <sys/socket.h>
74 #include <netinet/in.h>
75 
76 #include "gwlib.h"
77 
78 /*
79  * Unfortunately some platforms base va_list an an array type
80  * which makes passing of the &args a bit tricky
81  */
82 #if (defined(__linux__) && (defined(__powerpc__) || defined(__s390__) || defined(__x86_64))) || \
83     (defined(__FreeBSD__) && defined(__amd64__)) || \
84     (defined(DARWIN) && defined(__x86_64__))
85 #define VARGS(x)   (x)
86 #define VALPARM(y) va_list y
87 #define VALST(z)   (z)
88 #else
89 #define VARGS(x)   (&x)
90 #define VALPARM(y) va_list *y
91 #define VALST(z)   (*z)
92 #endif
93 
94 
95 /***********************************************************************
96  * Definitions of data structures. These are not visible to the external
97  * world -- they may be accessed only via the functions declared in
98  * octstr.h. This ensures they really are abstract.
99  */
100 
101 /*
102  * The octet string.
103  *
104  * `data' is a pointer to dynamically allocated memory are where the
105  * octets in the string. It may be bigger than the actual length of the
106  * string.
107  *
108  * `len' is the length of the string.
109  *
110  * `size' is the size of the memory area `data' points at.
111  *
112  * When `size' is greater than zero, it is at least `len+1', and the
113  * character at `len' is '\0'. This is so that octstr_get_cstr will
114  * always work.
115  *
116  * `immutable' defines whether the octet string is immutable or not.
117  */
118 struct Octstr
119 {
120     unsigned char *data;
121     long len;
122     long size;
123     int immutable;
124 };
125 
126 
127 /**********************************************************************
128  * Hash table of immutable octet strings.
129  */
130 
131 #define MAX_IMMUTABLES 1024
132 
133 static Octstr *immutables[MAX_IMMUTABLES];
134 static Mutex immutables_mutex;
135 static int immutables_init = 0;
136 
137 static char is_safe[UCHAR_MAX + 1];
138 
139 /*
140  * Convert a pointer to a C string literal to a long that can be used
141  * for hashing. This is done by converting the pointer into an integer
142  * and discarding the lowest to bits to get rid of typical alignment
143  * bits.
144  */
145 #define CSTR_TO_LONG(ptr)	(((unsigned long) ptr) >> 2)
146 
147 
148 /*
149  * HEX to ASCII preprocessor macro
150  */
151 #define H2B(a) (a >= '0' && a <= '9' ? \
152     a - '0' : (a >= 'a' && a <= 'f' ? \
153         a - 'a' + 10 : (a >= 'A' && a <= 'F' ? a - 'A' + 10 : -1) \
154         ) \
155     )
156 
157 
158 /***********************************************************************
159  * Declarations of internal functions. These are defined at the end of
160  * the file.
161  */
162 
163 
164 static void seems_valid_real(const Octstr *ostr, const char *filename, long lineno,
165                              const char *function);
166 #ifdef NO_GWASSERT
167 #define seems_valid(ostr)
168 #else
169 #define seems_valid(ostr) \
170     (seems_valid_real(ostr, __FILE__, __LINE__, __func__))
171 #endif
172 
173 
174 /***********************************************************************
175  * Implementations of the functions declared in octstr.h. See the
176  * header for explanations of what they should do.
177  */
178 
179 
180 /* Reserve space for at least 'size' octets */
octstr_grow(Octstr * ostr,long size)181 static void octstr_grow(Octstr *ostr, long size)
182 {
183     gw_assert(!ostr->immutable);
184     seems_valid(ostr);
185     gw_assert(size >= 0);
186 
187     size++;   /* make room for the invisible terminating NUL */
188 
189     if (size > ostr->size) {
190         /* always reallocate in 1kB chunks */
191         size += 1024 - (size % 1024);
192         ostr->data = gw_realloc(ostr->data, size);
193         ostr->size = size;
194     }
195 }
196 
197 
198 /*
199  * Fill is_safe table. is_safe[c] means that c can be left as such when
200  * url-encoded.
201  * RFC 2396 defines the list of characters that need to be encoded.
202  * Space is treated as an exception by the encoding routine;
203  * it's listed as safe here, but is actually changed to '+'.
204  */
urlcode_init(void)205 static void urlcode_init(void)
206 {
207     int i;
208 
209     unsigned char *safe = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
210                           "abcdefghijklmnopqrstuvwxyz-_.!~*'()";
211     for (i = 0; safe[i] != '\0'; ++i)
212         is_safe[safe[i]] = 1;
213 }
214 
215 
octstr_init(void)216 void octstr_init(void)
217 {
218     urlcode_init();
219     mutex_init_static(&immutables_mutex);
220     immutables_init = 1;
221 }
222 
223 
octstr_shutdown(void)224 void octstr_shutdown(void)
225 {
226     long i, n;
227 
228     n = 0;
229     for (i = 0; i < MAX_IMMUTABLES; ++i) {
230         if (immutables[i] != NULL) {
231 	    gw_free(immutables[i]);
232             ++n;
233         }
234     }
235     if(n>0)
236         debug("gwlib.octstr", 0, "Immutable octet strings: %ld.", n);
237     mutex_destroy(&immutables_mutex);
238 }
239 
240 
octstr_create_real(const char * cstr,const char * file,long line,const char * func)241 Octstr *octstr_create_real(const char *cstr, const char *file, long line,
242                            const char *func)
243 {
244     gw_assert(cstr != NULL);
245     return octstr_create_from_data_trace(cstr, strlen(cstr), file, line, func);
246 }
247 
octstr_create_from_data_real(const char * data,long len,const char * file,long line,const char * func)248 Octstr *octstr_create_from_data_real(const char *data, long len, const char *file,
249                                      long line, const char *func)
250 {
251     Octstr *ostr;
252 
253     gw_assert(len >= 0);
254     if (data == NULL)
255         gw_assert(len == 0);
256 
257     /* if gw_assert is disabled just return NULL
258      * and caller will check for NULL or just crash.
259      */
260     if (len < 0 || (data == NULL && len != 0))
261         return NULL;
262 
263     ostr = gw_malloc_trace(sizeof(*ostr), file, line, func);
264     if (len == 0) {
265         ostr->len = 0;
266         ostr->size = 0;
267         ostr->data = NULL;
268     } else {
269         ostr->len = len;
270         ostr->size = len + 1;
271         ostr->data = gw_malloc_trace(ostr->size, file, line, func);
272         memcpy(ostr->data, data, len);
273         ostr->data[len] = '\0';
274     }
275     ostr->immutable = 0;
276     seems_valid(ostr);
277     return ostr;
278 }
279 
280 
octstr_imm(const char * cstr)281 Octstr *octstr_imm(const char *cstr)
282 {
283     Octstr *os;
284     long i, index;
285     unsigned char *data;
286 
287     gw_assert(immutables_init);
288     gw_assert(cstr != NULL);
289 
290     index = CSTR_TO_LONG(cstr) % MAX_IMMUTABLES;
291     data = (unsigned char *) cstr;
292 
293     mutex_lock(&immutables_mutex);
294     i = index;
295     for (; ; ) {
296 	if (immutables[i] == NULL || immutables[i]->data == data)
297             break;
298         i = (i + 1) % MAX_IMMUTABLES;
299         if (i == index)
300             panic(0, "Too many immutable strings.");
301     }
302     os = immutables[i];
303     if (os == NULL) {
304 	/*
305 	 * Can't use octstr_create() because it copies the string,
306 	 * which would break our hashing.
307 	 */
308 	os = gw_malloc(sizeof(*os));
309         os->data = data;
310         os->len = strlen(data);
311         os->size = os->len + 1;
312         os->immutable = 1;
313 	immutables[i] = os;
314 	seems_valid(os);
315     }
316     mutex_unlock(&immutables_mutex);
317 
318     return os;
319 }
320 
321 
octstr_destroy(Octstr * ostr)322 void octstr_destroy(Octstr *ostr)
323 {
324     if (ostr != NULL) {
325         seems_valid(ostr);
326 	if (!ostr->immutable) {
327             gw_free(ostr->data);
328             gw_free(ostr);
329         }
330     }
331 }
332 
333 
octstr_destroy_item(void * os)334 void octstr_destroy_item(void *os)
335 {
336     octstr_destroy(os);
337 }
338 
339 
octstr_len(const Octstr * ostr)340 long octstr_len(const Octstr *ostr)
341 {
342     if (ostr == NULL)
343         return 0;
344     seems_valid(ostr);
345     return ostr->len;
346 }
347 
348 
octstr_copy_real(const Octstr * ostr,long from,long len,const char * file,long line,const char * func)349 Octstr *octstr_copy_real(const Octstr *ostr, long from, long len, const char *file, long line,
350                          const char *func)
351 {
352     if (ostr == NULL)
353         return octstr_create("");
354 
355     seems_valid_real(ostr, file, line, func);
356     gw_assert(from >= 0);
357     gw_assert(len >= 0);
358 
359     if (from >= ostr->len)
360         return octstr_create("");
361 
362     if (len > ostr->len - from)
363         len = ostr->len - from;
364 
365     return octstr_create_from_data_trace(ostr->data + from, len, file,
366                                          line, func);
367 }
368 
369 
370 
octstr_duplicate_real(const Octstr * ostr,const char * file,long line,const char * func)371 Octstr *octstr_duplicate_real(const Octstr *ostr, const char *file, long line,
372                               const char *func)
373 {
374     if (ostr == NULL)
375         return NULL;
376     seems_valid_real(ostr, file, line, func);
377     return octstr_create_from_data_trace(ostr->data, ostr->len, file, line, func);
378 }
379 
380 
octstr_cat(Octstr * ostr1,Octstr * ostr2)381 Octstr *octstr_cat(Octstr *ostr1, Octstr *ostr2)
382 {
383     Octstr *ostr;
384 
385     seems_valid(ostr1);
386     seems_valid(ostr2);
387     gw_assert(!ostr1->immutable);
388 
389     ostr = octstr_create("");
390     ostr->len = ostr1->len + ostr2->len;
391     ostr->size = ostr->len + 1;
392     ostr->data = gw_malloc(ostr->size);
393 
394     if (ostr1->len > 0)
395         memcpy(ostr->data, ostr1->data, ostr1->len);
396     if (ostr2->len > 0)
397         memcpy(ostr->data + ostr1->len, ostr2->data, ostr2->len);
398     ostr->data[ostr->len] = '\0';
399 
400     seems_valid(ostr);
401     return ostr;
402 }
403 
404 
octstr_get_char(const Octstr * ostr,long pos)405 int octstr_get_char(const Octstr *ostr, long pos)
406 {
407     seems_valid(ostr);
408     if (pos >= ostr->len || pos < 0)
409         return -1;
410     return ostr->data[pos];
411 }
412 
413 
octstr_set_char(Octstr * ostr,long pos,int ch)414 void octstr_set_char(Octstr *ostr, long pos, int ch)
415 {
416     seems_valid(ostr);
417     gw_assert(!ostr->immutable);
418     if (pos < ostr->len)
419         ostr->data[pos] = ch;
420     seems_valid(ostr);
421 }
422 
423 
octstr_get_many_chars(char * buf,Octstr * ostr,long pos,long len)424 void octstr_get_many_chars(char *buf, Octstr *ostr, long pos, long len)
425 {
426     gw_assert(buf != NULL);
427     seems_valid(ostr);
428 
429     if (pos >= ostr->len)
430         return;
431     if (pos + len > ostr->len)
432         len = ostr->len - pos;
433     if (len > 0)
434         memcpy(buf, ostr->data + pos, len);
435 }
436 
437 
octstr_get_cstr_real(const Octstr * ostr,const char * file,long line,const char * func)438 char *octstr_get_cstr_real(const Octstr *ostr, const char *file, long line,
439     	    	    	   const char *func)
440 {
441     if (!ostr)
442         return "(null)";
443     seems_valid_real(ostr, file, line, func);
444     if (ostr->len == 0)
445         return "";
446     return ostr->data;
447 }
448 
449 
octstr_append_from_hex(Octstr * ostr,char * hex)450 void octstr_append_from_hex(Octstr *ostr, char *hex)
451 {
452     Octstr *output;
453 
454     seems_valid(ostr);
455     gw_assert(!ostr->immutable);
456 
457     output = octstr_create(hex);
458     octstr_hex_to_binary(output);
459     octstr_append(ostr, output);
460     octstr_destroy(output);
461 }
462 
463 
octstr_binary_to_hex(Octstr * ostr,int uppercase)464 void octstr_binary_to_hex(Octstr *ostr, int uppercase)
465 {
466     unsigned char *hexits;
467     long i, tmp;
468 
469     seems_valid(ostr);
470     gw_assert(!ostr->immutable);
471     if (ostr->len == 0)
472         return;
473 
474     hexits = uppercase ? "0123456789ABCDEF" : "0123456789abcdef";
475     octstr_grow(ostr, ostr->len * 2);
476 
477     /* In-place modification must be done back-to-front to avoid
478      * overwriting the data while we read it.  Even the order of
479      * the two assignments is important, to get i == 0 right. */
480     for (i = ostr->len - 1; i >= 0; i--) {
481         tmp = i << 1; /* tmp = i * 2; */
482         ostr->data[tmp + 1] = hexits[ostr->data[i] & 0xf];
483         ostr->data[tmp] = hexits[ostr->data[i] >> 4];
484     }
485 
486     ostr->len = ostr->len * 2;
487     ostr->data[ostr->len] = '\0';
488 
489     seems_valid(ostr);
490 }
491 
492 
octstr_hex_to_binary(Octstr * ostr)493 int octstr_hex_to_binary(Octstr *ostr)
494 {
495     long len, i;
496     unsigned char *p;
497 
498     seems_valid(ostr);
499     gw_assert(!ostr->immutable);
500 
501     if (ostr->len == 0)
502         return 0;
503 
504     /* Check if it's in the right format */
505     if (!octstr_check_range(ostr, 0, ostr->len, gw_isxdigit))
506         return -1;
507 
508     len = ostr->len;
509 
510     /* Convert ascii data to binary values */
511     for (i = 0, p = ostr->data; i < len; i++, p++) {
512         if (*p >= '0' && *p <= '9')
513             *p -= '0';
514         else if (*p >= 'a' && *p <= 'f')
515             *p = *p - 'a' + 10;
516         else if (*p >= 'A' && *p <= 'F')
517             *p = *p - 'A' + 10;
518         else {
519             /* isxdigit checked the whole string, so we should
520              * not be able to get here. */
521             gw_assert(0);
522             *p = 0;
523         }
524     }
525 
526     /* De-hexing will compress data by factor of 2 */
527     len = ostr->len / 2;
528 
529     for (i = 0; i < len; i++) {
530         ostr->data[i] = ostr->data[i * 2] * 16 | ostr->data[i * 2 + 1];
531     }
532 
533     ostr->len = len;
534     ostr->data[len] = '\0';
535 
536     seems_valid(ostr);
537     return 0;
538 }
539 
540 
octstr_binary_to_base64(Octstr * ostr)541 void octstr_binary_to_base64(Octstr *ostr)
542 {
543     static const unsigned char base64[64] =
544         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
545     long triplets;
546     long lines;
547     long orig_len;
548     unsigned char *data;
549     long from, to;
550     int left_on_line;
551 
552     seems_valid(ostr);
553     gw_assert(!ostr->immutable);
554 
555     if (ostr->len == 0) {
556         /* Always terminate with CR LF */
557         octstr_insert(ostr, octstr_imm("\015\012"), 0);
558         return;
559     }
560 
561     /* The lines must be 76 characters each (or less), and each
562      * triplet will expand to 4 characters, so we can fit 19
563      * triplets on one line.  We need a CR LF after each line,
564      * which will add 2 octets per 19 triplets (rounded up). */
565     triplets = (ostr->len + 2) / 3;   /* round up */
566     lines = (triplets + 18) / 19;
567 
568     octstr_grow(ostr, triplets * 4 + lines * 2);
569     orig_len = ostr->len;
570     data = ostr->data;
571 
572     ostr->len = triplets * 4 + lines * 2;
573     data[ostr->len] = '\0';
574 
575     /* This function works back-to-front, so that encoded data will
576      * not overwrite source data.
577      * from points to the start of the last triplet (which may be
578      * an odd-sized one), and to points to the start of where the
579      * last quad should go.  */
580     from = (triplets - 1) * 3;
581     to = (triplets - 1) * 4 + (lines - 1) * 2;
582 
583     /* First write the CR LF after the last quad */
584     data[to + 5] = 10;   /* LF */
585     data[to + 4] = 13;   /* CR */
586     left_on_line = triplets - ((lines - 1) * 19);
587 
588     /* base64 encoding is in 3-octet units.  To handle leftover
589      * octets, conceptually we have to zero-pad up to the next
590      * 6-bit unit, and pad with '=' characters for missing 6-bit
591      * units.
592      * We do it by first completing the first triplet with
593      * zero-octets, and after the loop replacing some of the
594      * result characters with '=' characters.
595      * There is enough room for this, because even with a 1 or 2
596      * octet source string, space for four octets of output
597      * will be reserved.
598      */
599     switch (orig_len % 3) {
600     case 0:
601         break;
602     case 1:
603         data[orig_len] = 0;
604         data[orig_len + 1] = 0;
605         break;
606     case 2:
607         data[orig_len + 1] = 0;
608         break;
609     }
610 
611     /* Now we only have perfect triplets. */
612     while (from >= 0) {
613         long whole_triplet;
614 
615         /* Add a newline, if necessary */
616         if (left_on_line == 0) {
617             to -= 2;
618             data[to + 5] = 10;  /* LF */
619             data[to + 4] = 13;  /* CR */
620             left_on_line = 19;
621         }
622 
623         whole_triplet = (data[from] << 16) |
624                         (data[from + 1] << 8) |
625                         data[from + 2];
626         data[to + 3] = base64[whole_triplet % 64];
627         data[to + 2] = base64[(whole_triplet >> 6) % 64];
628         data[to + 1] = base64[(whole_triplet >> 12) % 64];
629         data[to] = base64[(whole_triplet >> 18) % 64];
630 
631         to -= 4;
632         from -= 3;
633         left_on_line--;
634     }
635 
636     gw_assert(left_on_line == 0);
637     gw_assert(from == -3);
638     gw_assert(to == -4);
639 
640     /* Insert padding characters in the last quad.  Remember that
641      * there is a CR LF between the last quad and the end of the
642      * string. */
643     switch (orig_len % 3) {
644     case 0:
645         break;
646     case 1:
647         gw_assert(data[ostr->len - 3] == 'A');
648         gw_assert(data[ostr->len - 4] == 'A');
649         data[ostr->len - 3] = '=';
650         data[ostr->len - 4] = '=';
651         break;
652     case 2:
653         gw_assert(data[ostr->len - 3] == 'A');
654         data[ostr->len - 3] = '=';
655         break;
656     }
657 
658     seems_valid(ostr);
659 }
660 
661 
octstr_base64_to_binary(Octstr * ostr)662 void octstr_base64_to_binary(Octstr *ostr)
663 {
664     long triplet;
665     long pos, len;
666     long to;
667     int quadpos = 0;
668     int warned = 0;
669     unsigned char *data;
670 
671     seems_valid(ostr);
672     gw_assert(!ostr->immutable);
673 
674     len = ostr->len;
675     data = ostr->data;
676 
677     if (len == 0)
678         return;
679 
680     to = 0;
681     triplet = 0;
682     quadpos = 0;
683     for (pos = 0; pos < len; pos++) {
684         int c = data[pos];
685         int sixbits;
686 
687         if (c >= 'A' && c <= 'Z') {
688             sixbits = c - 'A';
689         } else if (c >= 'a' && c <= 'z') {
690             sixbits = 26 + c - 'a';
691         } else if (c >= '0' && c <= '9') {
692             sixbits = 52 + c - '0';
693         } else if (c == '+') {
694             sixbits = 62;
695         } else if (c == '/') {
696             sixbits = 63;
697         } else if (c == '=') {
698             /* These can only occur at the end of encoded
699              * text.  RFC 2045 says we can assume it really
700              * is the end. */
701             break;
702         } else if (isspace(c)) {
703             /* skip whitespace */
704             continue;
705         } else {
706             if (!warned) {
707                 warning(0, "Unusual characters in base64 "
708                         "encoded text.");
709                 warned = 1;
710             }
711             continue;
712         }
713 
714         triplet = (triplet << 6) | sixbits;
715         quadpos++;
716 
717         if (quadpos == 4) {
718             data[to++] = (triplet >> 16) & 0xff;
719             data[to++] = (triplet >> 8) & 0xff;
720             data[to++] = triplet & 0xff;
721             quadpos = 0;
722         }
723     }
724 
725     /* Deal with leftover octets */
726     switch (quadpos) {
727     case 0:
728         break;
729     case 3:  /* triplet has 18 bits, we want the first 16 */
730         data[to++] = (triplet >> 10) & 0xff;
731         data[to++] = (triplet >> 2) & 0xff;
732         break;
733     case 2:  /* triplet has 12 bits, we want the first 8 */
734         data[to++] = (triplet >> 4) & 0xff;
735         break;
736     case 1:
737         warning(0, "Bad padding in base64 encoded text.");
738         break;
739     }
740 
741     ostr->len = to;
742     data[to] = '\0';
743 
744     seems_valid(ostr);
745 }
746 
747 
octstr_parse_long(long * nump,Octstr * ostr,long pos,int base)748 long octstr_parse_long(long *nump, Octstr *ostr, long pos, int base)
749 {
750     /* strtol wants a char *, and we have to compare the result to
751      * an unsigned char *.  The easiest way to avoid warnings without
752      * introducing typecasts is to use two variables. */
753     char *endptr;
754     unsigned char *endpos;
755     long number;
756 
757     seems_valid(ostr);
758     gw_assert(nump != NULL);
759     gw_assert(base == 0 || (base >= 2 && base <= 36));
760 
761     if (pos >= ostr->len) {
762         errno = EINVAL;
763         return -1;
764     }
765 
766     errno = 0;
767     number = strtol(ostr->data + pos, &endptr, base);
768     endpos = endptr;
769     if (errno == ERANGE)
770         return -1;
771     if (endpos == ostr->data + pos) {
772         errno = EINVAL;
773         return -1;
774     }
775 
776     *nump = number;
777     return endpos - ostr->data;
778 }
779 
780 
octstr_parse_double(double * nump,Octstr * ostr,long pos)781 long octstr_parse_double(double *nump, Octstr *ostr, long pos)
782 {
783     /* strtod wants a char *, and we have to compare the result to
784      * an unsigned char *.  The easiest way to avoid warnings without
785      * introducing typecasts is to use two variables. */
786     char *endptr;
787     unsigned char *endpos;
788     double number;
789 
790     seems_valid(ostr);
791     gw_assert(nump != NULL);
792 
793     if (pos >= ostr->len) {
794         errno = EINVAL;
795         return -1;
796     }
797 
798     errno = 0;
799     number = strtod(ostr->data + pos, &endptr);
800     endpos = endptr;
801     if (errno == ERANGE)
802         return -1;
803     if (endpos == ostr->data + pos) {
804         errno = EINVAL;
805         return -1;
806     }
807 
808     *nump = number;
809     return endpos - ostr->data;
810 }
811 
812 
octstr_check_range(Octstr * ostr,long pos,long len,octstr_func_t filter)813 int octstr_check_range(Octstr *ostr, long pos, long len,
814                        octstr_func_t filter)
815 {
816     long end = pos + len;
817 
818     seems_valid(ostr);
819     gw_assert(len >= 0);
820 
821     if (pos >= ostr->len)
822         return 1;
823     if (end > ostr->len)
824         end = ostr->len;
825 
826     for ( ; pos < end; pos++) {
827         if (!filter(ostr->data[pos]))
828             return 0;
829     }
830 
831     return 1;
832 }
833 
834 
octstr_convert_range(Octstr * ostr,long pos,long len,octstr_func_t map)835 void octstr_convert_range(Octstr *ostr, long pos, long len,
836                           octstr_func_t map)
837 {
838     long end = pos + len;
839 
840     seems_valid(ostr);
841     gw_assert(!ostr->immutable);
842     gw_assert(len >= 0);
843 
844     if (pos >= ostr->len)
845         return;
846     if (end > ostr->len)
847         end = ostr->len;
848 
849     for ( ; pos < end; pos++) {
850         ostr->data[pos] = map(ostr->data[pos]);
851     }
852 
853     seems_valid(ostr);
854 }
855 
856 
make_printable(int c)857 static int inline make_printable(int c)
858 {
859     return isprint(c) ? c : '.';
860 }
861 
862 
octstr_convert_printable(Octstr * ostr)863 void octstr_convert_printable(Octstr *ostr)
864 {
865     octstr_convert_range(ostr, 0, ostr->len, make_printable);
866 }
867 
868 
869 
octstr_compare(const Octstr * ostr1,const Octstr * ostr2)870 int octstr_compare(const Octstr *ostr1, const Octstr *ostr2)
871 {
872     int ret;
873     long len;
874 
875     seems_valid(ostr1);
876     seems_valid(ostr2);
877 
878     if (ostr1->len < ostr2->len)
879         len = ostr1->len;
880     else
881         len = ostr2->len;
882 
883     if (len == 0) {
884 	if (ostr1->len == 0 && ostr2->len > 0)
885 	    return -1;
886 	if (ostr1->len > 0 && ostr2->len == 0)
887 	    return 1;
888         return 0;
889     }
890 
891     ret = memcmp(ostr1->data, ostr2->data, len);
892     if (ret == 0) {
893         if (ostr1->len < ostr2->len)
894             ret = -1;
895         else if (ostr1->len > ostr2->len)
896             ret = 1;
897     }
898     return ret;
899 }
900 
901 
octstr_case_compare(const Octstr * os1,const Octstr * os2)902 int octstr_case_compare(const Octstr *os1, const Octstr *os2)
903 {
904     int c1, c2;
905     long i, len;
906 
907     seems_valid(os1);
908     seems_valid(os2);
909 
910     if (os1->len < os2->len)
911         len = os1->len;
912     else
913         len = os2->len;
914 
915     if (len == 0) {
916         if (os1->len == 0 && os2->len > 0)
917             return -1;
918         if (os1->len > 0 && os2->len == 0)
919             return 1;
920         return 0;
921     }
922 
923     c1 = c2 = 0;
924     for (i = 0; i < len; ++i) {
925         c1 = toupper(os1->data[i]);
926         c2 = toupper(os2->data[i]);
927         if (c1 != c2)
928             break;
929     }
930 
931     if (i == len) {
932         if (i == os1->len && i == os2->len)
933             return 0;
934         if (i == os1->len)
935             return -1;
936         return 1;
937     } else {
938         /*
939         c1 = toupper(os1->data[i]);
940         c2 = toupper(os2->data[i]);
941         */
942         if (c1 < c2)
943             return -1;
944         if (c1 == c2)
945             return 0;
946         return 1;
947     }
948 }
949 
950 
octstr_ncompare(const Octstr * ostr1,const Octstr * ostr2,long n)951 int octstr_ncompare(const Octstr *ostr1, const Octstr *ostr2, long n)
952 {
953     long len;
954 
955     seems_valid(ostr1);
956     seems_valid(ostr2);
957 
958     if ((ostr1->len < ostr2->len) && (ostr1->len < n))
959         len = ostr1->len;
960     else if ((ostr2->len < ostr1->len) && (ostr2->len < n))
961         len = ostr2->len;
962     else
963         len = n;
964 
965     if (len == 0)
966         return 0;
967 
968     return memcmp(ostr1->data, ostr2->data, len);
969 }
970 
971 
octstr_str_compare(const Octstr * ostr,const char * str)972 int octstr_str_compare(const Octstr *ostr, const char *str)
973 {
974     seems_valid(ostr);
975 
976     if (str == NULL)
977         return -1;
978     if (ostr->data == NULL)
979 	return strcmp("", str);
980 
981     return strcmp(ostr->data, str);
982 }
983 
984 
octstr_str_case_compare(const Octstr * ostr,const char * str)985 int octstr_str_case_compare(const Octstr *ostr, const char *str)
986 {
987     seems_valid(ostr);
988 
989     if (str == NULL)
990         return -1;
991     if (ostr->data == NULL)
992        return strcasecmp("", str);
993 
994     return strcasecmp(ostr->data, str);
995 }
996 
997 
octstr_str_ncompare(const Octstr * ostr,const char * str,long n)998 int octstr_str_ncompare(const Octstr *ostr, const char *str, long n)
999 {
1000     seems_valid(ostr);
1001 
1002     if (str == NULL)
1003         return -1;
1004     if (ostr->data == NULL)
1005         return 1; /* str grater */
1006 
1007     return strncmp(ostr->data, str, n);
1008 }
1009 
1010 
octstr_search_char(const Octstr * ostr,int ch,long pos)1011 long octstr_search_char(const Octstr *ostr, int ch, long pos)
1012 {
1013     unsigned char *p;
1014 
1015     seems_valid(ostr);
1016     gw_assert(ch >= 0);
1017     gw_assert(ch <= UCHAR_MAX);
1018     gw_assert(pos >= 0);
1019 
1020     if (pos >= ostr->len)
1021         return -1;
1022 
1023     p = memchr(ostr->data + pos, ch, ostr->len - pos);
1024     if (!p)
1025         return -1;
1026     return p - ostr->data;
1027 }
1028 
1029 
octstr_rsearch_char(const Octstr * ostr,int ch,long pos)1030 long octstr_rsearch_char(const Octstr *ostr, int ch, long pos)
1031 {
1032     long i;
1033 
1034     seems_valid(ostr);
1035     gw_assert(ch >= 0);
1036     gw_assert(ch <= UCHAR_MAX);
1037     gw_assert(pos >= 0);
1038 
1039     if (pos >= ostr->len)
1040         return -1;
1041 
1042     for (i = pos; i >= 0; i--) {
1043         if (ostr->data[i] == ch)
1044             return i;
1045     }
1046 
1047     return -1;
1048 }
1049 
1050 
octstr_search_chars(const Octstr * ostr,const Octstr * chars,long pos)1051 long octstr_search_chars(const Octstr *ostr, const Octstr *chars, long pos)
1052 {
1053     long i, j;
1054 
1055     seems_valid(ostr);
1056     seems_valid(chars);
1057     gw_assert(pos >= 0);
1058 
1059     for (i = 0; i < octstr_len(chars); i++) {
1060 	j = octstr_search_char(ostr, octstr_get_char(chars, i), pos);
1061 	if (j != -1)
1062 	    return j;
1063     }
1064 
1065     return -1;
1066 }
1067 
1068 
octstr_search(const Octstr * haystack,const Octstr * needle,long pos)1069 long octstr_search(const Octstr *haystack, const Octstr *needle, long pos)
1070 {
1071     int first;
1072 
1073     seems_valid(haystack);
1074     seems_valid(needle);
1075     gw_assert(pos >= 0);
1076 
1077     /* Always "find" an empty string */
1078     if (needle->len == 0)
1079         return 0;
1080 
1081     if (needle->len == 1)
1082         return octstr_search_char(haystack, needle->data[0], pos);
1083 
1084     /* For each occurrence of needle's first character in ostr,
1085      * check if the rest of needle follows.  Stop if there are no
1086      * more occurrences, or if the rest of needle can't possibly
1087      * fit in the haystack. */
1088     first = needle->data[0];
1089     pos = octstr_search_char(haystack, first, pos);
1090     while (pos >= 0 && haystack->len - pos >= needle->len) {
1091         if (memcmp(haystack->data + pos,
1092                    needle->data, needle->len) == 0)
1093             return pos;
1094         pos = octstr_search_char(haystack, first, pos + 1);
1095     }
1096 
1097     return -1;
1098 }
1099 
1100 
octstr_case_search(const Octstr * haystack,const Octstr * needle,long pos)1101 long octstr_case_search(const Octstr *haystack, const Octstr *needle, long pos)
1102 {
1103     long i, j;
1104     int c1, c2;
1105 
1106     seems_valid(haystack);
1107     seems_valid(needle);
1108     gw_assert(pos >= 0);
1109 
1110     /* Always "find" an empty string */
1111     if (needle->len == 0)
1112         return 0;
1113 
1114     for (i = pos; i <= haystack->len - needle->len; ++i) {
1115 	for (j = 0; j < needle->len; ++j) {
1116 	    c1 = toupper(haystack->data[i + j]);
1117 	    c2 = toupper(needle->data[j]);
1118 	    if (c1 != c2)
1119 	    	break;
1120 	}
1121 	if (j == needle->len)
1122 	    return i;
1123     }
1124 
1125     return -1;
1126 }
1127 
octstr_case_nsearch(const Octstr * haystack,const Octstr * needle,long pos,long n)1128 long octstr_case_nsearch(const Octstr *haystack, const Octstr *needle, long pos, long n)
1129 {
1130     long i, j;
1131     int c1, c2;
1132 
1133     seems_valid(haystack);
1134     seems_valid(needle);
1135     gw_assert(pos >= 0);
1136 
1137     /* Always "find" an empty string */
1138     if (needle->len == 0)
1139         return 0;
1140 
1141     for (i = pos; i <= haystack->len - needle->len && i < n; ++i) {
1142         for (j = 0; j < needle->len && j < n; ++j) {
1143             c1 = toupper(haystack->data[i + j]);
1144             c2 = toupper(needle->data[j]);
1145             if (c1 != c2)
1146                 break;
1147         }
1148         if (j == needle->len)
1149             return i;
1150     }
1151 
1152     return -1;
1153 }
1154 
1155 
octstr_str_search(const Octstr * haystack,const char * needle,long pos)1156 long octstr_str_search(const Octstr *haystack, const char *needle, long pos)
1157 {
1158     int first;
1159     int needle_len;
1160 
1161     seems_valid(haystack);
1162     gw_assert(pos >= 0);
1163 
1164     /* Always "find" an empty string */
1165     if (needle == NULL || needle[0] == '\0')
1166         return 0;
1167 
1168     needle_len = strlen(needle);
1169 
1170     if (needle_len == 1)
1171         return octstr_search_char(haystack, needle[0], pos);
1172 
1173     /* For each occurrence of needle's first character in ostr,
1174      * check if the rest of needle follows.  Stop if there are no
1175      * more occurrences, or if the rest of needle can't possibly
1176      * fit in the haystack. */
1177     first = needle[0];
1178     pos = octstr_search_char(haystack, first, pos);
1179     while (pos >= 0 && haystack->len - pos >= needle_len) {
1180         if (memcmp(haystack->data + pos,
1181                    needle, needle_len) == 0)
1182             return pos;
1183         pos = octstr_search_char(haystack, first, pos + 1);
1184     }
1185 
1186     return -1;
1187 }
1188 
1189 
octstr_print(FILE * f,Octstr * ostr)1190 int octstr_print(FILE *f, Octstr *ostr)
1191 {
1192     gw_assert(f != NULL);
1193     seems_valid(ostr);
1194 
1195     if (ostr->len == 0)
1196         return 0;
1197     if (fwrite(ostr->data, ostr->len, 1, f) != 1) {
1198         error(errno, "Couldn't write all of octet string to file.");
1199         return -1;
1200     }
1201     return 0;
1202 }
1203 
1204 
octstr_pretty_print(FILE * f,Octstr * ostr)1205 int octstr_pretty_print(FILE *f, Octstr *ostr)
1206 {
1207     unsigned char *p;
1208     long i;
1209 
1210     gw_assert(f != NULL);
1211     seems_valid(ostr);
1212 
1213     p = ostr->data;
1214     for (i = 0; i < ostr->len; ++i, ++p) {
1215         if (isprint(*p))
1216             fprintf(f, "%c", *p);
1217         else
1218             fprintf(f, "\\x%02x", *p);
1219     }
1220     if (ferror(f))
1221         return -1;
1222     return 0;
1223 }
1224 
1225 
octstr_write_to_socket(int socket,Octstr * ostr)1226 int octstr_write_to_socket(int socket, Octstr *ostr)
1227 {
1228     long len;
1229     unsigned char *data;
1230     int ret;
1231 
1232     gw_assert(socket >= 0);
1233     seems_valid(ostr);
1234 
1235     data = ostr->data;
1236     len = ostr->len;
1237     while (len > 0) {
1238         ret = write(socket, data, len);
1239         if (ret == -1) {
1240             if (errno != EINTR) {
1241                 error(errno, "Writing to socket failed");
1242                 return -1;
1243             }
1244         } else {
1245             /* ret may be less than len */
1246             len -= ret;
1247             data += ret;
1248         }
1249     }
1250     return 0;
1251 }
1252 
1253 
octstr_write_data(Octstr * ostr,int fd,long from)1254 long octstr_write_data(Octstr *ostr, int fd, long from)
1255 {
1256     long ret;
1257 
1258     gw_assert(fd >= 0);
1259     gw_assert(from >= 0);
1260     seems_valid(ostr);
1261 
1262     if (from >= ostr->len)
1263         return 0;
1264 
1265     ret = write(fd, ostr->data + from, ostr->len - from);
1266 
1267     if (ret < 0) {
1268         if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)
1269             return 0;
1270         error(errno, "Error writing %ld octets to fd %d:",
1271               ostr->len - from, fd);
1272         return -1;
1273     }
1274 
1275     return ret;
1276 }
1277 
1278 
octstr_append_from_socket(Octstr * ostr,int socket)1279 int octstr_append_from_socket(Octstr *ostr, int socket)
1280 {
1281     unsigned char buf[4096];
1282     int len;
1283 
1284     seems_valid(ostr);
1285     gw_assert(!ostr->immutable);
1286 
1287 again:
1288     len = recv(socket, buf, sizeof(buf), 0);
1289     if (len < 0 && errno == EINTR)
1290         goto again;
1291 
1292     if (len < 0) {
1293         error(errno, "Could not read from socket %d", socket);
1294         return -1;
1295     }
1296 
1297     octstr_append_data(ostr, buf, len);
1298     return len;
1299 }
1300 
1301 
octstr_insert(Octstr * ostr1,const Octstr * ostr2,long pos)1302 void octstr_insert(Octstr *ostr1, const Octstr *ostr2, long pos)
1303 {
1304     if (ostr2 == NULL)
1305         return;
1306 
1307     seems_valid(ostr1);
1308     seems_valid(ostr2);
1309     gw_assert(pos <= ostr1->len);
1310     gw_assert(!ostr1->immutable);
1311 
1312     if (ostr2->len == 0)
1313         return;
1314 
1315     octstr_grow(ostr1, ostr1->len + ostr2->len);
1316     memmove(ostr1->data + pos + ostr2->len, ostr1->data + pos,
1317             ostr1->len - pos);
1318     memcpy(ostr1->data + pos, ostr2->data, ostr2->len);
1319     ostr1->len += ostr2->len;
1320     ostr1->data[ostr1->len] = '\0';
1321 
1322     seems_valid(ostr1);
1323 }
1324 
1325 
octstr_truncate(Octstr * ostr,int new_len)1326 void octstr_truncate(Octstr *ostr, int new_len)
1327 {
1328     if (ostr == NULL)
1329         return;
1330 
1331     seems_valid(ostr);
1332     gw_assert(!ostr->immutable);
1333     gw_assert(new_len >= 0);
1334 
1335     if (new_len >= ostr->len)
1336         return;
1337 
1338     ostr->len = new_len;
1339     ostr->data[new_len] = '\0';
1340 
1341     seems_valid(ostr);
1342 }
1343 
1344 
octstr_strip_blanks(Octstr * text)1345 void octstr_strip_blanks(Octstr *text)
1346 {
1347     int start = 0, end, len = 0;
1348 
1349     seems_valid(text);
1350     gw_assert(!text->immutable);
1351 
1352     /* Remove white space from the beginning of the text */
1353     while (isspace(octstr_get_char(text, start)) &&
1354 	   start <= octstr_len(text))
1355         start ++;
1356 
1357     if (start > 0)
1358         octstr_delete(text, 0, start);
1359 
1360     /* and from the end. */
1361 
1362     if ((len = octstr_len(text)) > 0) {
1363         end = len = len - 1;
1364         while (isspace(octstr_get_char(text, end)) && end >= 0)
1365             end--;
1366         octstr_delete(text, end + 1, len - end);
1367     }
1368 
1369     seems_valid(text);
1370 }
1371 
iscrlf(unsigned char c)1372 static int iscrlf(unsigned char c)
1373 {
1374     return c == '\n' || c == '\r';
1375 }
1376 
octstr_strip_crlfs(Octstr * text)1377 void octstr_strip_crlfs(Octstr *text)
1378 {
1379     int start = 0, end, len = 0;
1380 
1381     seems_valid(text);
1382     gw_assert(!text->immutable);
1383 
1384     /* Remove white space from the beginning of the text */
1385     while (iscrlf(octstr_get_char(text, start)) &&
1386 	   start <= octstr_len(text))
1387         start ++;
1388 
1389     if (start > 0)
1390         octstr_delete(text, 0, start);
1391 
1392     /* and from the end. */
1393 
1394     if ((len = octstr_len(text)) > 0) {
1395         end = len = len - 1;
1396         while (iscrlf(octstr_get_char(text, end)) && end >= 0)
1397             end--;
1398         octstr_delete(text, end + 1, len - end);
1399     }
1400 
1401     seems_valid(text);
1402 }
1403 
octstr_strip_nonalphanums(Octstr * text)1404 void octstr_strip_nonalphanums(Octstr *text)
1405 {
1406     int start = 0, end, len = 0;
1407 
1408     seems_valid(text);
1409     gw_assert(!text->immutable);
1410 
1411     /* Remove white space from the beginning of the text */
1412     while (!isalnum(octstr_get_char(text, start)) &&
1413 	   start <= octstr_len(text))
1414         start ++;
1415 
1416     if (start > 0)
1417         octstr_delete(text, 0, start);
1418 
1419     /* and from the end. */
1420 
1421     if ((len = octstr_len(text)) > 0) {
1422         end = len = len - 1;
1423         while (!isalnum(octstr_get_char(text, end)) && end >= 0)
1424             end--;
1425         octstr_delete(text, end + 1, len - end);
1426     }
1427 
1428     seems_valid(text);
1429 }
1430 
1431 
octstr_shrink_blanks(Octstr * text)1432 void octstr_shrink_blanks(Octstr *text)
1433 {
1434     int i, j, end;
1435 
1436     seems_valid(text);
1437     gw_assert(!text->immutable);
1438 
1439     end = octstr_len(text);
1440 
1441     /* Shrink white spaces to one  */
1442     for (i = 0; i < end; i++) {
1443         if (isspace(octstr_get_char(text, i))) {
1444             /* Change the remaining space into single space. */
1445             if (octstr_get_char(text, i) != ' ')
1446                 octstr_set_char(text, i, ' ');
1447 
1448             j = i = i + 1;
1449             while (isspace(octstr_get_char(text, j)))
1450                 j ++;
1451             if (j - i > 1)
1452                 octstr_delete(text, i, j - i);
1453         }
1454     }
1455 
1456     seems_valid(text);
1457 }
1458 
1459 
octstr_insert_data(Octstr * ostr,long pos,const char * data,long len)1460 void octstr_insert_data(Octstr *ostr, long pos, const char *data, long len)
1461 {
1462     seems_valid(ostr);
1463     gw_assert(!ostr->immutable);
1464     gw_assert(pos <= ostr->len);
1465 
1466     if (len == 0)
1467         return;
1468 
1469     octstr_grow(ostr, ostr->len + len);
1470     if (ostr->len > pos) {	/* only if neccessary*/
1471         memmove(ostr->data + pos + len, ostr->data + pos, ostr->len - pos);
1472     }
1473     memcpy(ostr->data + pos, data, len);
1474     ostr->len += len;
1475     ostr->data[ostr->len] = '\0';
1476 
1477     seems_valid(ostr);
1478 }
1479 
octstr_insert_char(Octstr * ostr,long pos,const char c)1480 void octstr_insert_char(Octstr *ostr, long pos, const char c)
1481 {
1482     seems_valid(ostr);
1483     gw_assert(!ostr->immutable);
1484     gw_assert(pos <= ostr->len);
1485 
1486     octstr_grow(ostr, ostr->len + 1);
1487     if (ostr->len > pos)
1488         memmove(ostr->data + pos + 1, ostr->data + pos, ostr->len - pos);
1489     memcpy(ostr->data + pos, &c, 1);
1490     ostr->len += 1;
1491     ostr->data[ostr->len] = '\0';
1492 
1493     seems_valid(ostr);
1494 }
1495 
octstr_append_data(Octstr * ostr,const char * data,long len)1496 void octstr_append_data(Octstr *ostr, const char *data, long len)
1497 {
1498     gw_assert(ostr != NULL);
1499     octstr_insert_data(ostr, ostr->len, data, len);
1500 }
1501 
1502 
octstr_append(Octstr * ostr1,const Octstr * ostr2)1503 void octstr_append(Octstr *ostr1, const Octstr *ostr2)
1504 {
1505     gw_assert(ostr1 != NULL);
1506     octstr_insert(ostr1, ostr2, ostr1->len);
1507 }
1508 
1509 
octstr_append_cstr(Octstr * ostr,const char * cstr)1510 void octstr_append_cstr(Octstr *ostr, const char *cstr)
1511 {
1512     octstr_insert_data(ostr, ostr->len, cstr, strlen(cstr));
1513 }
1514 
1515 
octstr_append_char(Octstr * ostr,int ch)1516 void octstr_append_char(Octstr *ostr, int ch)
1517 {
1518     unsigned char c = ch;
1519 
1520     gw_assert(ch >= 0);
1521     gw_assert(ch <= UCHAR_MAX);
1522     octstr_insert_data(ostr, ostr->len, &c, 1);
1523 }
1524 
1525 
octstr_delete(Octstr * ostr1,long pos,long len)1526 void octstr_delete(Octstr *ostr1, long pos, long len)
1527 {
1528     seems_valid(ostr1);
1529     gw_assert(!ostr1->immutable);
1530 
1531     if (pos > ostr1->len)
1532         pos = ostr1->len;
1533     if (pos + len > ostr1->len)
1534         len = ostr1->len - pos;
1535     if (len > 0) {
1536         memmove(ostr1->data + pos, ostr1->data + pos + len,
1537                 ostr1->len - pos - len);
1538         ostr1->len -= len;
1539         ostr1->data[ostr1->len] = '\0';
1540     }
1541 
1542     seems_valid(ostr1);
1543 }
1544 
1545 
1546 
octstr_read_file(const char * filename)1547 Octstr *octstr_read_file(const char *filename)
1548 {
1549     FILE *f;
1550     Octstr *os;
1551     char buf[4096];
1552     long n;
1553 
1554     gw_assert(filename != NULL);
1555 
1556     f = fopen(filename, "r");
1557     if (f == NULL) {
1558         error(errno, "fopen failed: couldn't open `%s'", filename);
1559         return NULL;
1560     }
1561 
1562     os = octstr_create("");
1563     if (os == NULL)
1564         goto error;
1565 
1566     while ((n = fread(buf, 1, sizeof(buf), f)) > 0)
1567         octstr_insert_data(os, octstr_len(os), buf, n);
1568 
1569     (void) fclose(f);
1570     return os;
1571 
1572 error:
1573     (void) fclose(f);
1574     octstr_destroy(os);
1575     return NULL;
1576 }
1577 
1578 
octstr_read_pipe(FILE * f)1579 Octstr *octstr_read_pipe(FILE *f)
1580 {
1581     Octstr *os;
1582     char buf[4096];
1583 
1584     gw_assert(f != NULL);
1585 
1586     os = octstr_create("");
1587     if (os == NULL)
1588         goto error;
1589 
1590     while (fgets(buf, sizeof(buf), f) != NULL)
1591         octstr_append_data(os, buf, strlen(buf));
1592 
1593     return os;
1594 
1595 error:
1596     octstr_destroy(os);
1597     return NULL;
1598 }
1599 
1600 
octstr_split_words(const Octstr * ostr)1601 List *octstr_split_words(const Octstr *ostr)
1602 {
1603     unsigned char *p;
1604     List *list;
1605     Octstr *word;
1606     long i, start, end;
1607 
1608     seems_valid(ostr);
1609 
1610     list = gwlist_create();
1611 
1612     p = ostr->data;
1613     i = 0;
1614     for (; ; ) {
1615         while (i < ostr->len && isspace(*p)) {
1616             ++p;
1617             ++i;
1618         }
1619         start = i;
1620 
1621         while (i < ostr->len && !isspace(*p)) {
1622             ++p;
1623             ++i;
1624         }
1625         end = i;
1626 
1627         if (start == end)
1628             break;
1629 
1630         word = octstr_create_from_data(ostr->data + start,
1631                                        end - start);
1632         gwlist_append(list, word);
1633     }
1634 
1635     return list;
1636 }
1637 
1638 
octstr_split(const Octstr * os,const Octstr * sep)1639 List *octstr_split(const Octstr *os, const Octstr *sep)
1640 {
1641     List *list;
1642     long next, pos, seplen;
1643 
1644     list = gwlist_create();
1645     pos = 0;
1646     seplen = octstr_len(sep);
1647 
1648     while ((next = octstr_search(os, sep, pos)) >= 0) {
1649         gwlist_append(list, octstr_copy(os, pos, next - pos));
1650         pos = next + seplen;
1651     }
1652 
1653     if (pos < octstr_len(os))
1654         gwlist_append(list, octstr_copy(os, pos, octstr_len(os)));
1655 
1656     return list;
1657 }
1658 
1659 
octstr_item_match(void * item,void * pattern)1660 int octstr_item_match(void *item, void *pattern)
1661 {
1662     return octstr_compare(item, pattern) == 0;
1663 }
1664 
1665 
octstr_item_case_match(void * item,void * pattern)1666 int octstr_item_case_match(void *item, void *pattern)
1667 {
1668     return octstr_case_compare(item, pattern) == 0;
1669 }
1670 
1671 
octstr_url_encode(Octstr * ostr)1672 void octstr_url_encode(Octstr *ostr)
1673 {
1674     long i, n, len = 0;
1675     int all_safe;
1676     unsigned char c, *str, *str2, *res, *hexits;
1677 
1678     if (ostr == NULL)
1679         return;
1680 
1681     seems_valid(ostr);
1682     gw_assert(!ostr->immutable);
1683 
1684     if (ostr->len == 0)
1685         return;
1686 
1687     /* calculate new length */
1688     for (i = n = 0, str = ostr->data, all_safe = 1; i < ostr->len; i++) {
1689         c = *str++;
1690 
1691         if (c == ' ') {
1692             all_safe = 0;
1693             continue;
1694         }
1695 
1696         if (!is_safe[c]) {
1697 	    n++;
1698             all_safe = 0;
1699         }
1700      }
1701 
1702     if (all_safe) /* we are done, all chars are safe */
1703        return;
1704 
1705     hexits = "0123456789ABCDEF";
1706 
1707     /*
1708      * no need to reallocate if n == 0, so we make replace in place.
1709      * NOTE: we don't do if (xxx) ... else ... because conditional jump
1710      * is not so fast as just compare (alex).
1711      */
1712     res = str2 = (n ? gw_malloc((len = ostr->len + 2 * n + 1)) : ostr->data);
1713 
1714     for (i = 0, str = ostr->data; i < ostr->len; i++) {
1715         c = *str++;
1716 
1717         if (c == ' ') {
1718             *str2++ = '+';
1719             continue;
1720         }
1721 
1722         if (!is_safe[c]) {
1723             *str2++ = '%';
1724             *str2++ = hexits[c >> 4 & 0xf];
1725             *str2++ = hexits[c & 0xf];
1726             continue;
1727         }
1728 
1729         *str2++ = c;
1730     }
1731     *str2 = 0;
1732 
1733     /* we made replace in place */
1734     if (n) {
1735         gw_free(ostr->data);
1736         ostr->data = res;
1737         ostr->size = len;
1738         ostr->len = len - 1;
1739     }
1740 
1741     seems_valid(ostr);
1742 }
1743 
1744 
octstr_url_decode(Octstr * ostr)1745 int octstr_url_decode(Octstr *ostr)
1746 {
1747     unsigned char *string;
1748     unsigned char *dptr;
1749     int code, code2, ret = 0;
1750 
1751     if (ostr == NULL)
1752         return 0;
1753 
1754     seems_valid(ostr);
1755     gw_assert(!ostr->immutable);
1756 
1757     if (ostr->len == 0)
1758         return 0;
1759 
1760     string = ostr->data;
1761     dptr = ostr->data;
1762 
1763     do {
1764         if (*string == '%') {
1765             if (*(string + 1) == '\0' || *(string + 2) == '\0') {
1766                 warning(0, "octstr_url_decode: corrupted end-of-string <%s>", string);
1767                 ret = -1;
1768                 break;
1769             }
1770 
1771             code = H2B(*(string + 1));
1772             code2 = H2B(*(string + 2));
1773 
1774             if (code == -1 || code2 == -1) {
1775                 warning(0, "octstr_url_decode: garbage detected (%c%c%c) skipping.",
1776                             *string, *(string + 1), *(string + 2));
1777                 *dptr++ = *string++;
1778                 *dptr++ = *string++;
1779                 *dptr++ = *string++;
1780                 ret = -1;
1781                 continue;
1782             }
1783 
1784             *dptr++ = code << 4 | code2;
1785             string += 3;
1786         }
1787         else if (*string == '+') {
1788             *dptr++ = ' ';
1789             string++;
1790         } else
1791             *dptr++ = *string++;
1792     } while (*string); 	/* we stop here because it terimates encoded string */
1793 
1794     *dptr = '\0';
1795     ostr->len = (dptr - ostr->data);
1796 
1797     seems_valid(ostr);
1798     return ret;
1799 }
1800 
1801 
octstr_get_bits(Octstr * ostr,long bitpos,int numbits)1802 long octstr_get_bits(Octstr *ostr, long bitpos, int numbits)
1803 {
1804     long pos;
1805     long result;
1806     int mask;
1807     int shiftwidth;
1808 
1809     seems_valid(ostr);
1810     gw_assert(bitpos >= 0);
1811     gw_assert(numbits <= 32);
1812     gw_assert(numbits >= 0);
1813 
1814     pos = bitpos / 8;
1815     bitpos = bitpos % 8;
1816 
1817     /* This also takes care of the len == 0 case */
1818     if (pos >= ostr->len)
1819         return 0;
1820 
1821     mask = (1 << numbits) - 1;
1822 
1823     /* It's easy if the range fits in one octet */
1824     if (bitpos + numbits <= 8) {
1825         /* shiftwidth is the number of bits to ignore on the right.
1826          * bitpos 0 is the leftmost bit. */
1827         shiftwidth = 8 - (bitpos + numbits);
1828         return (ostr->data[pos] >> shiftwidth) & mask;
1829     }
1830 
1831     /* Otherwise... */
1832     result = 0;
1833     while (bitpos + numbits > 8) {
1834         result = (result << 8) | ostr->data[pos];
1835         numbits -= (8 - bitpos);
1836         bitpos = 0;
1837         pos++;
1838         if (pos >= ostr->len)
1839             return (result << numbits) & mask;
1840     }
1841 
1842     gw_assert(bitpos == 0);
1843     result <<= numbits;
1844     result |= ostr->data[pos] >> (8 - numbits);
1845     return result & mask;
1846 }
1847 
octstr_set_bits(Octstr * ostr,long bitpos,int numbits,unsigned long value)1848 void octstr_set_bits(Octstr *ostr, long bitpos, int numbits,
1849                      unsigned long value)
1850 {
1851     long pos;
1852     unsigned long mask;
1853     int shiftwidth;
1854     int bits;
1855     int maxlen;
1856     int c;
1857 
1858     seems_valid(ostr);
1859     gw_assert(!ostr->immutable);
1860     gw_assert(bitpos >= 0);
1861     gw_assert(numbits <= 32);
1862     gw_assert(numbits >= 0);
1863 
1864     maxlen = (bitpos + numbits + 7) / 8;
1865     if (maxlen > ostr->len) {
1866         octstr_grow(ostr, maxlen);
1867         /* Make sure the new octets start out with value 0 */
1868         for (pos = ostr->len; pos < maxlen; pos++) {
1869             ostr->data[pos] = 0;
1870         }
1871         ostr->len = maxlen;
1872         ostr->data[maxlen] = 0;
1873     }
1874 
1875     mask = (1 << numbits) - 1;
1876     /* mask is also the largest value that fits */
1877     gw_assert(value <= mask);
1878 
1879     pos = bitpos / 8;
1880     bitpos = bitpos % 8;
1881 
1882     /* Does the range fit in one octet? */
1883     if (bitpos + numbits <= 8) {
1884         /* shiftwidth is the number of bits to ignore on the right.
1885          * bitpos 0 is the leftmost bit. */
1886         shiftwidth = 8 - (bitpos + numbits);
1887         /* Extract the bits we don't want to affect */
1888         c = ostr->data[pos] & ~(mask << shiftwidth);
1889         c |= value << shiftwidth;
1890         gw_assert(pos < ostr->len);
1891         ostr->data[pos] = c;
1892         return;
1893     }
1894 
1895     /* Otherwise... */
1896     /* If speed is a problem here, we could have separate cases for
1897      * the first octet (which may have bitpos > 0), and the rest,
1898      * which don't. */
1899     while (bitpos + numbits > 8) {
1900         /* We want this many bits from the value */
1901         bits = 8 - bitpos;
1902         /* There are this many bits to their right in the value */
1903         shiftwidth = numbits - bits;
1904         /* Construct a mask for "bits" bits on the far right */
1905         mask = (1 << bits) - 1;
1906         /* Get the bits we want */
1907         c = (value >> shiftwidth) & mask;
1908         /* Merge them with the bits that are already there */
1909         gw_assert(pos < ostr->len);
1910         ostr->data[pos] = (ostr->data[pos] & ~mask) | c;
1911         numbits -= (8 - bitpos);
1912         bitpos = 0;
1913         pos++;
1914     }
1915 
1916     gw_assert(bitpos == 0);
1917     gw_assert(pos < ostr->len);
1918     /* Set remaining bits.  This is just like the single-octet case
1919      * before the loop, except that we know bitpos is 0. */
1920     mask = (1 << numbits) - 1;
1921     shiftwidth = 8 - numbits;
1922     c = ostr->data[pos] & ~(mask << shiftwidth);
1923     c |= value << shiftwidth;
1924     ostr->data[pos] = c;
1925 
1926     seems_valid(ostr);
1927 }
1928 
1929 
octstr_append_uintvar(Octstr * ostr,unsigned long value)1930 void octstr_append_uintvar(Octstr *ostr, unsigned long value)
1931 {
1932     /* A uintvar is defined to be up to 32 bits large, so it will
1933      * fit in 5 octets. */
1934     unsigned char octets[5];
1935     int i;
1936     int start;
1937 
1938     /* Handle last byte separately; it has no continuation bit,
1939      * and must be encoded even if value is 0. */
1940     octets[4] = value & 0x7f;
1941     value >>= 7;
1942 
1943     for (i = 3; value > 0 && i >= 0; i--) {
1944         octets[i] = 0x80 | (value & 0x7f);
1945         value >>= 7;
1946     }
1947     start = i + 1;
1948 
1949     octstr_append_data(ostr, octets + start, 5 - start);
1950 }
1951 
1952 
octstr_extract_uintvar(Octstr * ostr,unsigned long * value,long pos)1953 long octstr_extract_uintvar(Octstr *ostr, unsigned long *value, long pos)
1954 {
1955     int c;
1956     int count;
1957     unsigned long ui;
1958 
1959     ui = 0;
1960     for (count = 0; count < 5; count++) {
1961         c = octstr_get_char(ostr, pos + count);
1962         if (c < 0)
1963             return -1;
1964         ui = (ui << 7) | (c & 0x7f);
1965         if (!(c & 0x80)) {
1966             *value = ui;
1967             return pos + count + 1;
1968         }
1969     }
1970 
1971     return -1;
1972 }
1973 
1974 
octstr_append_decimal(Octstr * ostr,long value)1975 void octstr_append_decimal(Octstr *ostr, long value)
1976 {
1977     char tmp[128];
1978 
1979     sprintf(tmp, "%ld", value);
1980     octstr_append_cstr(ostr, tmp);
1981 }
1982 
1983 
1984 
1985 /**********************************************************************
1986  * octstr_dump... and related private functions
1987  */
1988 
octstr_dump_debug(const Octstr * ostr,int level)1989 static void octstr_dump_debug(const Octstr *ostr, int level)
1990 {
1991     unsigned char *p, *d, buf[1024], charbuf[256];
1992     long pos;
1993     const int octets_per_line = 16;
1994     int c, this_line_begins_at;
1995 
1996     if (ostr == NULL)
1997         return;
1998 
1999     seems_valid(ostr);
2000 
2001     debug("gwlib.octstr", 0, "%*sOctet string at %p:", level, "",
2002           (void *) ostr);
2003     debug("gwlib.octstr", 0, "%*s  len:  %lu", level, "",
2004           (unsigned long) ostr->len);
2005     debug("gwlib.octstr", 0, "%*s  size: %lu", level, "",
2006           (unsigned long) ostr->size);
2007     debug("gwlib.octstr", 0, "%*s  immutable: %d", level, "",
2008           ostr->immutable);
2009 
2010     buf[0] = '\0';
2011     p = buf;
2012     d = charbuf;
2013     this_line_begins_at = 0;
2014     for (pos = 0; pos < octstr_len(ostr); ) {
2015         c = octstr_get_char(ostr, pos);
2016         sprintf(p, "%02x ", c);
2017         p = strchr(p, '\0');
2018         if (isprint(c))
2019             *d++ = c;
2020         else
2021             *d++ = '.';
2022         ++pos;
2023         if (pos - this_line_begins_at == octets_per_line) {
2024             *d = '\0';
2025             debug("gwlib.octstr", 0, "%*s  data: %s  %s", level, "",
2026                   buf, charbuf);
2027             buf[0] = '\0';
2028             charbuf[0] = '\0';
2029             p = buf;
2030             d = charbuf;
2031             this_line_begins_at = pos;
2032         }
2033     }
2034     if (pos - this_line_begins_at > 0) {
2035         *d = '\0';
2036         debug("gwlib.octstr", 0, "%*s  data: %-*.*s  %s", level, "",
2037               octets_per_line*3,
2038               octets_per_line*3, buf, charbuf);
2039     }
2040 
2041     debug("gwlib.octstr", 0, "%*sOctet string dump ends.", level, "");
2042 }
2043 
2044 
2045 /*
2046  * We do some pre-processor mangling here in order to reduce code for
2047  * the 3 log levels info(), warning() and error() that have the same
2048  * argument list.
2049  * We need to map the function calls via ## concatenation and revert
2050  * to the original function call by a define.
2051  * The do-while loop emulates a function call.
2052  */
2053 
2054 #define LLinfo info
2055 #define LLwarning warning
2056 #define LLerror error
2057 
2058 #define octstr_dump_LOGLEVEL(loglevel, ostr, level) \
2059 do { \
2060     unsigned char *p, *d, buf[1024], charbuf[256]; \
2061     long pos; \
2062     const int octets_per_line = 16; \
2063     int c, this_line_begins_at; \
2064     \
2065     if (ostr == NULL) \
2066         return; \
2067     \
2068     seems_valid(ostr); \
2069     \
2070     LL##loglevel(0, "%*sOctet string at %p:", level, "", \
2071           (void *) ostr); \
2072     LL##loglevel(0, "%*s  len:  %lu", level, "", \
2073           (unsigned long) ostr->len); \
2074     LL##loglevel(0, "%*s  size: %lu", level, "", \
2075           (unsigned long) ostr->size); \
2076     LL##loglevel(0, "%*s  immutable: %d", level, "", \
2077           ostr->immutable); \
2078     \
2079     buf[0] = '\0'; \
2080     p = buf; \
2081     d = charbuf; \
2082     this_line_begins_at = 0; \
2083     for (pos = 0; pos < octstr_len(ostr); ) { \
2084         c = octstr_get_char(ostr, pos); \
2085         sprintf(p, "%02x ", c); \
2086         p = strchr(p, '\0'); \
2087         if (isprint(c)) \
2088             *d++ = c; \
2089         else \
2090             *d++ = '.'; \
2091         ++pos; \
2092         if (pos - this_line_begins_at == octets_per_line) { \
2093             *d = '\0'; \
2094             LL##loglevel(0, "%*s  data: %s  %s", level, "", \
2095                   buf, charbuf); \
2096             buf[0] = '\0'; \
2097             charbuf[0] = '\0'; \
2098             p = buf; \
2099             d = charbuf; \
2100             this_line_begins_at = pos; \
2101         } \
2102     } \
2103     if (pos - this_line_begins_at > 0) { \
2104         *d = '\0'; \
2105         LL##loglevel(0, "%*s  data: %-*.*s  %s", level, "", \
2106               octets_per_line*3, \
2107               octets_per_line*3, buf, charbuf); \
2108     } \
2109     \
2110     LL##loglevel(0, "%*sOctet string dump ends.", level, ""); \
2111 } while (0)
2112 
2113 
octstr_dump_real(const Octstr * ostr,int level,...)2114 void octstr_dump_real(const Octstr *ostr, int level, ...)
2115 {
2116     va_list p;
2117     unsigned int loglevel;
2118 
2119     va_start(p, level);
2120     loglevel = va_arg(p, unsigned int);
2121     va_end(p);
2122 
2123     switch (loglevel) {
2124         case GW_DEBUG:
2125             octstr_dump_debug(ostr, level);
2126             break;
2127         case GW_INFO:
2128             octstr_dump_LOGLEVEL(info, ostr, level);
2129             break;
2130         case GW_WARNING:
2131             octstr_dump_LOGLEVEL(warning, ostr, level);
2132             break;
2133         case GW_ERROR:
2134             octstr_dump_LOGLEVEL(error, ostr, level);
2135             break;
2136         default:
2137             octstr_dump_debug(ostr, level);
2138             break;
2139     }
2140 }
2141 
2142 
octstr_dump_short(Octstr * ostr,int level,const char * name)2143 void octstr_dump_short(Octstr *ostr, int level, const char *name)
2144 {
2145     char buf[100];
2146     char *p;
2147     long i;
2148     int c;
2149 
2150     if (ostr == NULL) {
2151         debug("gwlib.octstr", 0, "%*s%s: NULL", level, "", name);
2152         return;
2153     }
2154 
2155     seems_valid(ostr);
2156 
2157     if (ostr->len < 20) {
2158         p = buf;
2159         for (i = 0; i < ostr->len; i++) {
2160             c = ostr->data[i];
2161             if (c == '\n') {
2162                 *p++ = '\\';
2163                 *p++ = 'n';
2164             } else if (!isprint(c)) {
2165                 break;
2166             } else if (c == '"') {
2167                 *p++ = '\\';
2168                 *p++ = '"';
2169             } else if (c == '\\') {
2170                 *p++ = '\\';
2171                 *p++ = '\\';
2172             } else {
2173                 *p++ = c;
2174             }
2175         }
2176         if (i == ostr->len) {
2177             *p++ = 0;
2178             /* We got through the loop without hitting nonprintable
2179              * characters. */
2180             debug("gwlib.octstr", 0, "%*s%s: \"%s\"", level, "", name, buf);
2181             return;
2182         }
2183     }
2184 
2185     debug("gwlib.octstr", 0, "%*s%s:", level, "", name);
2186     octstr_dump(ostr, level + 1);
2187 }
2188 
2189 
2190 /**********************************************************************
2191  * octstr_format and related private functions
2192  */
2193 
2194 
2195 /*
2196  * A parsed form of the format string. This struct has been carefully
2197  * defined so that it can be initialized with {0} and it will have
2198  * the correct defaults.
2199  */
2200 struct format
2201 {
2202     int minus;
2203     int zero;
2204 
2205     long min_width;
2206 
2207     int has_prec;
2208     long prec;
2209 
2210     long type;
2211 };
2212 
2213 
format_flags(struct format * format,const char ** fmt)2214 static void format_flags(struct format *format, const char **fmt)
2215 {
2216     int done;
2217 
2218     done = 0;
2219     do
2220     {
2221         switch (**fmt) {
2222         case '-':
2223             format->minus = 1;
2224             break;
2225 
2226         case '0':
2227             format->zero = 1;
2228             break;
2229 
2230         default:
2231             done = 1;
2232         }
2233 
2234         if (!done)
2235             ++(*fmt);
2236     } while (!done);
2237 }
2238 
2239 
format_width(struct format * format,const char ** fmt,VALPARM (args))2240 static void format_width(struct format *format, const char **fmt,
2241                          VALPARM(args))
2242 {
2243     char *end;
2244 
2245     if (**fmt == '*')
2246     {
2247         format->min_width = va_arg(VALST(args), int);
2248         ++(*fmt);
2249     } else if (isdigit(**(const unsigned char **) fmt))
2250     {
2251         format->min_width = strtol(*fmt, &end, 10);
2252         *fmt = end;
2253         /* XXX error checking is missing from here */
2254     }
2255 }
2256 
2257 
format_prec(struct format * format,const char ** fmt,VALPARM (args))2258 static void format_prec(struct format *format, const char **fmt,
2259                         VALPARM(args))
2260 {
2261     char *end;
2262 
2263     if (**fmt != '.')
2264         return;
2265     ++(*fmt);
2266     if (**fmt == '*')
2267     {
2268         format->has_prec = 1;
2269         format->prec = va_arg(VALST(args), int);
2270         ++(*fmt);
2271     } else if (isdigit(**(const unsigned char **) fmt))
2272     {
2273         format->has_prec = 1;
2274         format->prec = strtol(*fmt, &end, 10);
2275         *fmt = end;
2276         /* XXX error checking is missing from here */
2277     }
2278 }
2279 
2280 
format_type(struct format * format,const char ** fmt)2281 static void format_type(struct format *format, const char **fmt)
2282 {
2283     switch (**fmt) {
2284     case 'h':
2285         format->type = **fmt;
2286         ++(*fmt);
2287         break;
2288     case 'l':
2289         if (*(*fmt + 1) == 'l'){
2290            format->type = 'L';
2291            ++(*fmt);
2292         } else format->type = **fmt;
2293         ++(*fmt);
2294         break;
2295     }
2296 }
2297 
2298 
convert(Octstr * os,struct format * format,const char ** fmt,VALPARM (args))2299 static void convert(Octstr *os, struct format *format, const char **fmt,
2300                     VALPARM(args))
2301 {
2302     Octstr *new;
2303     char *s, *pad;
2304     long long n;
2305     unsigned long long u;
2306     char tmpfmt[1024];
2307     char tmpbuf[1024];
2308     char c;
2309     void *p;
2310 
2311     new = NULL;
2312 
2313     switch (**fmt)
2314     {
2315     case 'c':
2316         c = va_arg(VALST(args), int);
2317         new = octstr_create_from_data(&c, 1);
2318         break;
2319 
2320     case 'd':
2321     case 'i':
2322         switch (format->type) {
2323         case 'L':
2324             n = va_arg(VALST(args), long long);
2325             break;
2326         case 'l':
2327             n = va_arg(VALST(args), long);
2328             break;
2329         case 'h':
2330             n = (short) va_arg(VALST(args), int);
2331             break;
2332         default:
2333             n = va_arg(VALST(args), int);
2334             break;
2335         }
2336         new = octstr_create("");
2337         octstr_append_decimal(new, n);
2338         break;
2339 
2340     case 'o':
2341     case 'u':
2342     case 'x':
2343     case 'X':
2344    switch (format->type) {
2345    case 'l':
2346       u = va_arg(VALST(args), unsigned long);
2347       break;
2348    case 'L':
2349       u = va_arg(VALST(args), unsigned long long);
2350       break;
2351    case 'h':
2352       u = (unsigned short) va_arg(VALST(args), unsigned int);
2353       break;
2354    default:
2355       u = va_arg(VALST(args), unsigned int);
2356       break;
2357    }
2358    tmpfmt[0] = '%';
2359 	tmpfmt[1] = 'l';
2360 	tmpfmt[2] = **fmt;
2361 	tmpfmt[3] = '\0';
2362 	sprintf(tmpbuf, tmpfmt, u);
2363         new = octstr_create(tmpbuf);
2364         break;
2365 
2366     case 'e':
2367     case 'f':
2368     case 'g':
2369         sprintf(tmpfmt, "%%");
2370         if (format->minus)
2371             strcat(tmpfmt, "-");
2372         if (format->zero)
2373             strcat(tmpfmt, "0");
2374         if (format->min_width > 0)
2375             sprintf(strchr(tmpfmt, '\0'),
2376                     "%ld", format->min_width);
2377         if (format->has_prec)
2378             sprintf(strchr(tmpfmt, '\0'),
2379                     ".%ld", format->prec);
2380         if (format->type != '\0')
2381             sprintf(strchr(tmpfmt, '\0'),
2382                     "%c", (int) format->type);
2383         sprintf(strchr(tmpfmt, '\0'), "%c", **fmt);
2384         snprintf(tmpbuf, sizeof(tmpbuf),
2385                  tmpfmt, va_arg(VALST(args), double));
2386         new = octstr_create(tmpbuf);
2387         break;
2388 
2389     case 's':
2390         s = va_arg(VALST(args), char *);
2391         if (format->has_prec && format->prec < (long) strlen(s))
2392             n = format->prec;
2393         else
2394             n = (long) strlen(s);
2395         new = octstr_create_from_data(s, n);
2396         break;
2397 
2398     case 'p':
2399     	p = va_arg(VALST(args), void *);
2400 	sprintf(tmpfmt, "%p", p);
2401 	new = octstr_create(tmpfmt);
2402 	break;
2403 
2404     case 'S':
2405         new = octstr_duplicate(va_arg(VALST(args), Octstr *));
2406         if (!new)
2407             new = octstr_create("(null)");
2408         if (format->has_prec)
2409             octstr_truncate(new, format->prec);
2410         break;
2411 
2412     case 'E':
2413         new = octstr_duplicate(va_arg(VALST(args), Octstr *));
2414         if (!new)
2415             new = octstr_create("(null)");
2416         octstr_url_encode(new);
2417         /*
2418          * note: we use blind truncate - encoded character can get cut half-way.
2419          */
2420         if (format->has_prec)
2421             octstr_truncate(new, format->prec);
2422         break;
2423 
2424     case 'H':
2425         new = octstr_duplicate(va_arg(VALST(args), Octstr *));
2426         if (!new)
2427             new = octstr_create("(null)");
2428         /* upper case */
2429         octstr_binary_to_hex(new, 1);
2430         if (format->has_prec)
2431             octstr_truncate(new, (format->prec % 2 ? format->prec - 1 : format->prec));
2432         break;
2433 
2434     case '%':
2435     	new = octstr_create("%");
2436     	break;
2437 
2438     default:
2439         panic(0, "octstr_format format string syntax error.");
2440     }
2441 
2442     if (format->zero)
2443         pad = "0";
2444     else
2445         pad = " ";
2446 
2447     if (format->minus) {
2448         while (format->min_width > octstr_len(new))
2449             octstr_append_data(new, pad, 1);
2450     } else {
2451         while (format->min_width > octstr_len(new))
2452             octstr_insert_data(new, 0, pad, 1);
2453     }
2454 
2455     octstr_append(os, new);
2456     octstr_destroy(new);
2457 
2458     if (**fmt != '\0')
2459         ++(*fmt);
2460 }
2461 
2462 
octstr_format(const char * fmt,...)2463 Octstr *octstr_format(const char *fmt, ...)
2464 {
2465     Octstr *os;
2466     va_list args;
2467 
2468     va_start(args, fmt);
2469     os = octstr_format_valist(fmt, args);
2470     va_end(args);
2471     return os;
2472 }
2473 
2474 
octstr_format_valist_real(const char * fmt,va_list args)2475 Octstr *octstr_format_valist_real(const char *fmt, va_list args)
2476 {
2477     Octstr *os;
2478     size_t n;
2479 
2480     os = octstr_create("");
2481 
2482     while (*fmt != '\0') {
2483         struct format format = { 0, };
2484 
2485         n = strcspn(fmt, "%");
2486         octstr_append_data(os, fmt, n);
2487         fmt += n;
2488 
2489         gw_assert(*fmt == '%' || *fmt == '\0');
2490         if (*fmt == '\0')
2491             continue;
2492 
2493         ++fmt;
2494         format_flags(&format, &fmt);
2495         format_width(&format, &fmt, VARGS(args));
2496         format_prec(&format, &fmt, VARGS(args));
2497         format_type(&format, &fmt);
2498         convert(os, &format, &fmt, VARGS(args));
2499     }
2500 
2501     seems_valid(os);
2502     return os;
2503 }
2504 
2505 
octstr_format_append(Octstr * os,const char * fmt,...)2506 void octstr_format_append(Octstr *os, const char *fmt, ...)
2507 {
2508     Octstr *temp;
2509     va_list args;
2510 
2511     va_start(args, fmt);
2512     temp = octstr_format_valist(fmt, args);
2513     va_end(args);
2514     octstr_append(os, temp);
2515     octstr_destroy(temp);
2516 }
2517 
2518 
2519 /*
2520  * Hash implementation ala Robert Sedgewick.
2521  */
octstr_hash_key(Octstr * ostr)2522 unsigned long octstr_hash_key(Octstr *ostr)
2523 {
2524     unsigned long b    = 378551;
2525     unsigned long a    = 63689;
2526     unsigned long hash = 0;
2527     unsigned long i    = 0;
2528     unsigned long len = octstr_len(ostr);
2529     const char *str = octstr_get_cstr(ostr);
2530 
2531     for(i = 0; i < len; str++, i++) {
2532         hash = hash*a+(*str);
2533         a = a*b;
2534     }
2535 
2536     return (hash & 0x7FFFFFFF);
2537 }
2538 
2539 
2540 /**********************************************************************
2541  * Local functions.
2542  */
2543 
seems_valid_real(const Octstr * ostr,const char * filename,long lineno,const char * function)2544 static void seems_valid_real(const Octstr *ostr, const char *filename, long lineno,
2545                              const char *function)
2546 {
2547     gw_assert(immutables_init);
2548     gw_assert_place(ostr != NULL,
2549                     filename, lineno, function);
2550     gw_assert_allocated(ostr,
2551                         filename, lineno, function);
2552     gw_assert_place(ostr->len >= 0,
2553                     filename, lineno, function);
2554     gw_assert_place(ostr->size >= 0,
2555                     filename, lineno, function);
2556     if (ostr->size == 0) {
2557         gw_assert_place(ostr->len == 0,
2558                         filename, lineno, function);
2559         gw_assert_place(ostr->data == NULL,
2560                         filename, lineno, function);
2561     } else {
2562         gw_assert_place(ostr->len + 1 <= ostr->size,
2563                         filename, lineno, function);
2564         gw_assert_place(ostr->data != NULL,
2565                         filename, lineno, function);
2566 	if (!ostr->immutable)
2567             gw_assert_allocated(ostr->data,
2568                                 filename, lineno, function);
2569         gw_assert_place(ostr->data[ostr->len] == '\0',
2570                         filename, lineno, function);
2571     }
2572 }
2573 
2574 int
octstr_recode(Octstr * tocode,Octstr * fromcode,Octstr * orig)2575 octstr_recode (Octstr *tocode, Octstr *fromcode, Octstr *orig)
2576 {
2577     Octstr *octstr_utf8 = NULL;
2578     Octstr *octstr_final = NULL;
2579     int resultcode = 0;
2580 
2581     if (octstr_case_compare(tocode, fromcode) == 0) {
2582 	goto cleanup_and_exit;
2583     }
2584 
2585     if ((octstr_case_compare(fromcode, octstr_imm ("UTF-8")) != 0) &&
2586 	(octstr_case_compare(fromcode, octstr_imm ("UTF8")) != 0)) {
2587 	if (charset_to_utf8(orig, &octstr_utf8, fromcode) < 0) {
2588 	    resultcode = -1;
2589 	    goto cleanup_and_exit;
2590 	}
2591     } else {
2592 	octstr_utf8 = octstr_duplicate(orig);
2593     }
2594 
2595     if ((octstr_case_compare(tocode, octstr_imm ("UTF-8")) != 0) &&
2596 	(octstr_case_compare(tocode, octstr_imm ("UTF8")) != 0)) {
2597 	if (charset_from_utf8(octstr_utf8, &octstr_final, tocode) < 0) {
2598 	    resultcode = -1;
2599 	    goto cleanup_and_exit;
2600 	}
2601     } else {
2602 	octstr_final = octstr_duplicate(octstr_utf8);
2603     }
2604 
2605     octstr_truncate(orig, 0);
2606     octstr_append(orig, octstr_final);
2607 
2608  cleanup_and_exit:
2609     octstr_destroy (octstr_utf8);
2610     octstr_destroy (octstr_final);
2611 
2612     return resultcode;
2613 }
2614 
octstr_strip_char(Octstr * text,char ch)2615 void octstr_strip_char(Octstr *text, char ch)
2616 {
2617     int start = 0;
2618 
2619     seems_valid(text);
2620     gw_assert(!text->immutable);
2621 
2622     /* Remove char from the beginning of the text */
2623     while ((ch == octstr_get_char(text, start)) &&
2624            start <= octstr_len(text))
2625         start ++;
2626 
2627     if (start > 0)
2628         octstr_delete(text, 0, start);
2629 
2630     seems_valid(text);
2631 }
2632 
octstr_isnum(Octstr * ostr1)2633 int octstr_isnum(Octstr *ostr1)
2634 {
2635     int start = 0;
2636     char c;
2637 
2638     seems_valid(ostr1);
2639     while (start < octstr_len(ostr1)) {
2640         c = octstr_get_char(ostr1, start);
2641         if (!isdigit(c) && (c!='+'))
2642             return 0;
2643         start++;
2644     }
2645     return 1;
2646 }
2647 
octstr_replace(Octstr * haystack,Octstr * needle,Octstr * repl)2648 void octstr_replace(Octstr *haystack, Octstr *needle, Octstr *repl)
2649 {
2650     int p = 0;
2651     long len, repl_len;
2652 
2653     len = octstr_len(needle);
2654     repl_len = octstr_len(repl);
2655 
2656     while ((p = octstr_search(haystack, needle, p)) != -1) {
2657         octstr_delete(haystack, p, len);
2658         octstr_insert(haystack, repl, p);
2659         p += repl_len;
2660     }
2661 }
2662 
octstr_replace_first(Octstr * haystack,Octstr * needle,Octstr * repl)2663 void octstr_replace_first(Octstr *haystack, Octstr *needle, Octstr *repl)
2664 {
2665     int p = 0;
2666     long len, repl_len;
2667 
2668     len = octstr_len(needle);
2669     repl_len = octstr_len(repl);
2670 
2671     p = octstr_search(haystack, needle, p);
2672     if (p != -1) {
2673         octstr_delete(haystack, p, len);
2674         octstr_insert(haystack, repl, p);
2675     }
2676 }
2677 
octstr_symbolize(Octstr * ostr)2678 int octstr_symbolize(Octstr *ostr)
2679 {
2680     long len, i;
2681 
2682     seems_valid(ostr);
2683     gw_assert(!ostr->immutable);
2684 
2685     if (ostr->len == 0)
2686         return 0;
2687 
2688     /* Check if it's in the right format */
2689     if (!octstr_check_range(ostr, 0, ostr->len, gw_isxdigit))
2690         return -1;
2691 
2692     len = ostr->len + (ostr->len/2);
2693     octstr_grow(ostr, ostr->len * 2);
2694 
2695     for (i = 0; i < len; i += 3)
2696         octstr_insert_data(ostr, i, "%", 1);
2697 
2698     return 1;
2699 }
2700 
octstr_delete_matching(Octstr * haystack,Octstr * needle)2701 void octstr_delete_matching(Octstr *haystack, Octstr *needle)
2702 {
2703     int p = 0;
2704     long len;
2705 
2706     seems_valid(haystack);
2707     seems_valid(needle);
2708     gw_assert(!haystack->immutable);
2709     len = octstr_len(needle);
2710 
2711     while ((p = octstr_search(haystack, needle, p)) != -1) {
2712         octstr_delete(haystack, p, len);
2713     }
2714 }
2715 
octstr_is_all_hex(Octstr * os)2716 int octstr_is_all_hex(Octstr *os)
2717 {
2718     long len, i;
2719     int ch;
2720 
2721     seems_valid(os);
2722     len = octstr_len(os);
2723     for (i = 0; i < len; ++i) {
2724         ch = octstr_get_char(os, i);
2725         if (!gw_isxdigit(ch))
2726             return 0;
2727     }
2728 
2729     return 1;
2730 }
2731 
2732 /*
2733  * function octstr_convert_to_html_entities()
2734  *      make data HTML safe by converting appropriate characters to HTML entities
2735  * Input: data to be inserted in HTML
2736  **/
octstr_convert_to_html_entities(Octstr * input)2737 void octstr_convert_to_html_entities(Octstr* input)
2738 {
2739     int i;
2740 
2741     for (i = 0; i < octstr_len(input); ++i) {
2742         switch (octstr_get_char(input, i)) {
2743 #define ENTITY(a,b) \
2744     case a: \
2745     octstr_delete(input, i, 1); \
2746     octstr_insert(input, octstr_imm("&" b ";"), i); \
2747     i += sizeof(b); break;
2748 #include "gwlib/html-entities.def"
2749 #undef ENTITY
2750         }
2751     }
2752 }
2753 
2754 /*
2755  * This function is meant to find html entities in an octstr.
2756  * The html-entities.def file must be sorted alphabetically for
2757  * this function to work (according to current Locale in use).
2758 */
octstr_find_entity(Octstr * input,int startfind,int endfind)2759 static int octstr_find_entity(Octstr* input, int startfind, int endfind)
2760 {
2761 #define ENTITY(a,b) { a, b },
2762     struct entity_struct {
2763         int entity;
2764         char *entity_str;
2765     };
2766     const struct entity_struct entities[] = {
2767 #include "html-entities.def"
2768         { -1, "" } /* pivot */
2769     };
2770 #undef ENTITY
2771     int center;         /* position in table that we are about to compare */
2772     int matchresult;    /* result of match agains found entity name. indicates less, equal or greater */
2773 
2774     if (endfind == 0) {
2775         /* when calling this function we do not (nor even want to) know the
2776          * sizeof(entities). Hence this check. */
2777         endfind = (sizeof(entities) / sizeof(struct entity_struct)) - 1;
2778     }
2779     center = startfind + ((endfind - startfind) / 2);
2780     matchresult = octstr_str_compare(input, entities[center].entity_str);
2781     if (matchresult == 0) {
2782         return entities[center].entity;
2783     }
2784     if (endfind - startfind <= 1) {
2785         /* we are at the end of our results */
2786         return -1;
2787     }
2788     if  (matchresult < 0) {
2789         /* keep searching in first part of the table */
2790         return octstr_find_entity(input, startfind, center);
2791     } else {
2792         /* keep searching in last part of the table */
2793         return octstr_find_entity(input, center, endfind);
2794     }
2795 }
2796 
2797 /*
2798  * function octstr_convert_from_html_entities()
2799  *   convert HTML safe data back to binary data by replacing HTML entities with their
2800  *   respective character values
2801  * Input: data to be inserted in HTML
2802  **/
octstr_convert_from_html_entities(Octstr * input)2803 void octstr_convert_from_html_entities(Octstr* input)
2804 {
2805     int startpos = 0, endpos;
2806     int entity;
2807     Octstr *match;
2808 
2809     while ((startpos = octstr_search_char(input, '&', startpos)) != -1) {
2810         endpos = octstr_search_char(input, ';', startpos + 1);
2811         if (endpos >= 0) {
2812             match = octstr_copy(input, startpos + 1, endpos - startpos - 1);
2813             entity = octstr_find_entity(match, 0, 0);
2814             if (entity >= 0) {
2815                 octstr_delete(input, startpos, endpos - startpos + 1);
2816                 octstr_insert_char(input, startpos, entity);
2817             }
2818             octstr_destroy(match);
2819         }
2820         startpos++;
2821     }
2822 }
2823