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