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