octstr.c
上传用户:gzpyjq
上传日期:2013-01-31
资源大小:1852k
文件大小:49k
源码类别:

手机WAP编程

开发平台:

WINDOWS

  1. /*
  2.  * octstr.c - implementation of Octet strings
  3.  *
  4.  * See octstr.h for explanations of what public functions should do.
  5.  *
  6.  * Lars Wirzenius
  7.  */
  8. #include <ctype.h>
  9. #include <limits.h>
  10. #include <errno.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <unistd.h>
  14. #include <sys/types.h>
  15. #include <sys/socket.h>
  16. #include <netinet/in.h>
  17. #include "gwlib.h"
  18. /* 
  19.  * Unfortunately some platforms base va_list an an array type
  20.  * which makes passing of the &args a bit tricky 
  21.  */
  22. #if defined(__linux__) && (defined(__powerpc__) || defined(__s390__))
  23. #define VARGS(x)   (x)
  24. #define VALPARM(y) va_list y
  25. #define VALST(z)   (z)
  26. #else
  27. #define VARGS(x)   (&x)
  28. #define VALPARM(y) va_list *y
  29. #define VALST(z)   (*z)
  30. #endif
  31. /***********************************************************************
  32.  * Definitions of data structures. These are not visible to the external
  33.  * world -- they may be accessed only via the functions declared in
  34.  * octstr.h. This ensures they really are abstract.
  35.  */
  36. /*
  37.  * The octet string.
  38.  *
  39.  * `data' is a pointer to dynamically allocated memory are where the 
  40.  * octets in the string. It may be bigger than the actual length of the
  41.  * string.
  42.  *
  43.  * `len' is the length of the string.
  44.  *
  45.  * `size' is the size of the memory area `data' points at.
  46.  *
  47.  * When `size' is greater than zero, it is at least `len+1', and the
  48.  * character at `len' is ''. This is so that octstr_get_cstr will
  49.  * always work.
  50.  *
  51.  * `immutable' defines whether the octet string is immutable or not.
  52.  */
  53. struct Octstr
  54. {
  55.     unsigned char *data;
  56.     long len;
  57.     long size;
  58.     int immutable;
  59. };
  60. /**********************************************************************
  61.  * Hash table of immutable octet strings.
  62.  */
  63. #define MAX_IMMUTABLES 1024
  64. static Octstr *immutables[MAX_IMMUTABLES];
  65. static Mutex immutables_mutex;
  66. static int immutables_init = 0;
  67. static char is_safe[UCHAR_MAX + 1];
  68. /*
  69.  * Convert a pointer to a C string literal to a long that can be used
  70.  * for hashing. This is done by converting the pointer into an integer
  71.  * and discarding the lowest to bits to get rid of typical alignment
  72.  * bits.
  73.  */
  74. #define CSTR_TO_LONG(ptr) (((long) ptr) >> 2)
  75. /***********************************************************************
  76.  * Declarations of internal functions. These are defined at the end of
  77.  * the file.
  78.  */
  79. static void seems_valid_real(Octstr *ostr, const char *filename, long lineno,
  80.                              const char *function);
  81. #ifdef NO_GWASSERT
  82. #define seems_valid(ostr)
  83. #else
  84. #define seems_valid(ostr) 
  85.     (seems_valid_real(ostr, __FILE__, __LINE__, __func__))
  86. #endif
  87. /***********************************************************************
  88.  * Implementations of the functions declared in octstr.h. See the
  89.  * header for explanations of what they should do.
  90.  */
  91. /* Reserve space for at least 'size' octets */
  92. static void octstr_grow(Octstr *ostr, long size)
  93. {
  94.     gw_assert(!ostr->immutable);
  95.     seems_valid(ostr);
  96.     gw_assert(size >= 0);
  97.     size++;   /* make room for the invisible terminating NUL */
  98.     if (size > ostr->size) {
  99.         ostr->data = gw_realloc(ostr->data, size);
  100.         ostr->size = size;
  101.     }
  102. }
  103. /*
  104.  * Fill is_safe table. is_safe[c] means that c can be left as such when
  105.  * url-encoded.
  106.  * RFC 2396 defines the list of characters that need to be encoded.
  107.  * Space is treated as an exception by the encoding routine;
  108.  * it's listed as safe here, but is actually changed to '+'.
  109.  */
  110. static void urlcode_init(void)
  111. {
  112.     int i;
  113.     unsigned char *safe = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  114. "abcdefghijklmnopqrstuvwxyz-_.!~*'()";
  115.     for (i = 0; safe[i] != ''; ++i)
  116. is_safe[safe[i]] = 1;
  117. }
  118. void octstr_init(void)
  119. {
  120.     urlcode_init();
  121.     mutex_init_static(&immutables_mutex);
  122.     immutables_init = 1;
  123. }
  124. void octstr_shutdown(void)
  125. {
  126.     long i, n;
  127.     n = 0;
  128.     for (i = 0; i < MAX_IMMUTABLES; ++i) {
  129.         if (immutables[i] != NULL) {
  130.     gw_free(immutables[i]);
  131.             ++n;
  132.         }
  133.     }
  134.     if(n>0)
  135.         debug("gwlib.octstr", 0, "Immutable octet strings: %ld.", n);
  136.     mutex_destroy(&immutables_mutex);
  137. }
  138. Octstr *octstr_create_real(const char *cstr)
  139. {
  140.     gw_assert(cstr != NULL);
  141.     return octstr_create_from_data(cstr, strlen(cstr));
  142. }
  143. Octstr *octstr_create_from_data_real(const char *data, long len)
  144. {
  145.     Octstr *ostr;
  146.     gw_assert(len >= 0);
  147.     if (data == NULL)
  148.         gw_assert(len == 0);
  149.     ostr = gw_malloc(sizeof(*ostr));
  150.     if (len == 0) {
  151.         ostr->len = 0;
  152.         ostr->size = 0;
  153.         ostr->data = NULL;
  154.     } else {
  155.         ostr->len = len;
  156.         ostr->size = len + 1;
  157.         ostr->data = gw_malloc(ostr->size);
  158.         memcpy(ostr->data, data, len);
  159.         ostr->data[len] = '';
  160.     }
  161.     ostr->immutable = 0;
  162.     seems_valid(ostr);
  163.     return ostr;
  164. }
  165. Octstr *octstr_imm(const char *cstr)
  166. {
  167.     Octstr *os;
  168.     long i, index;
  169.     unsigned char *data;
  170.     gw_assert(immutables_init);
  171.     gw_assert(cstr != NULL);
  172.     index = CSTR_TO_LONG(cstr) % MAX_IMMUTABLES;
  173.     data = (unsigned char *) cstr;
  174.     mutex_lock(&immutables_mutex);
  175.     i = index;
  176.     for (; ; ) {
  177. if (immutables[i] == NULL || immutables[i]->data == data)
  178.             break;
  179.         i = (i + 1) % MAX_IMMUTABLES;
  180.         if (i == index)
  181.             panic(0, "Too many immutable strings.");
  182.     }
  183.     os = immutables[i];
  184.     if (os == NULL) {
  185. /*
  186.  * Can't use octstr_create() because it copies the string,
  187.  * which would break our hashing.
  188.  */
  189. os = gw_malloc(sizeof(*os));
  190.         os->data = data;
  191.         os->len = strlen(data);
  192.         os->size = os->len + 1;
  193.         os->immutable = 1;
  194. immutables[i] = os;
  195. seems_valid(os);
  196.     }
  197.     mutex_unlock(&immutables_mutex);
  198.     return os;
  199. }
  200. void octstr_destroy(Octstr *ostr)
  201. {
  202.     if (ostr != NULL) {
  203.         seems_valid(ostr);
  204. if (!ostr->immutable) {
  205.             gw_free(ostr->data);
  206.             gw_free(ostr);
  207.         }
  208.     }
  209. }
  210. void octstr_destroy_item(void *os)
  211. {
  212.     octstr_destroy(os);
  213. }
  214. long octstr_len(Octstr *ostr)
  215. {
  216.     if (ostr == NULL)
  217.         return 0;
  218.     seems_valid(ostr);
  219.     return ostr->len;
  220. }
  221. Octstr *octstr_copy_real(Octstr *ostr, long from, long len)
  222. {
  223.     seems_valid(ostr);
  224.     gw_assert(from >= 0);
  225.     gw_assert(len >= 0);
  226.     if (from >= ostr->len)
  227.         return octstr_create("");
  228.     if (len > ostr->len - from)
  229.         len = ostr->len - from;
  230.     return octstr_create_from_data(ostr->data + from, len);
  231. }
  232. Octstr *octstr_duplicate_real(Octstr *ostr)
  233. {
  234.     if (ostr == NULL)
  235.         return NULL;
  236.     seems_valid(ostr);
  237.     return octstr_create_from_data(ostr->data, ostr->len);
  238. }
  239. Octstr *octstr_cat(Octstr *ostr1, Octstr *ostr2)
  240. {
  241.     Octstr *ostr;
  242.     seems_valid(ostr1);
  243.     seems_valid(ostr2);
  244.     gw_assert(!ostr1->immutable);
  245.     ostr = octstr_create("");
  246.     ostr->len = ostr1->len + ostr2->len;
  247.     ostr->size = ostr->len + 1;
  248.     ostr->data = gw_malloc(ostr->size);
  249.     if (ostr1->len > 0)
  250.         memcpy(ostr->data, ostr1->data, ostr1->len);
  251.     if (ostr2->len > 0)
  252.         memcpy(ostr->data + ostr1->len, ostr2->data, ostr2->len);
  253.     ostr->data[ostr->len] = '';
  254.     seems_valid(ostr);
  255.     return ostr;
  256. }
  257. int octstr_get_char(Octstr *ostr, long pos)
  258. {
  259.     seems_valid(ostr);
  260.     if (pos >= ostr->len || pos < 0)
  261.         return -1;
  262.     return ostr->data[pos];
  263. }
  264. void octstr_set_char(Octstr *ostr, long pos, int ch)
  265. {
  266.     seems_valid(ostr);
  267.     gw_assert(!ostr->immutable);
  268.     if (pos < ostr->len)
  269.         ostr->data[pos] = ch;
  270.     seems_valid(ostr);
  271. }
  272. void octstr_get_many_chars(char *buf, Octstr *ostr, long pos, long len)
  273. {
  274.     gw_assert(buf != NULL);
  275.     seems_valid(ostr);
  276.     if (pos >= ostr->len)
  277.         return;
  278.     if (pos + len > ostr->len)
  279.         len = ostr->len - pos;
  280.     if (len > 0)
  281.         memcpy(buf, ostr->data + pos, len);
  282. }
  283. char *octstr_get_cstr_real(Octstr *ostr, const char *file, long line, 
  284.                   const char *func)
  285. {
  286.     if (!ostr)
  287.         return "(null)";
  288.     seems_valid_real(ostr, file, line, func);
  289.     if (ostr->len == 0)
  290.         return "";
  291.     return ostr->data;
  292. }
  293. void octstr_append_from_hex(Octstr *ostr, char *hex)
  294. {
  295.     Octstr *output;
  296.     seems_valid(ostr);
  297.     gw_assert(!ostr->immutable);
  298.     output = octstr_create(hex);
  299.     octstr_hex_to_binary(output);
  300.     octstr_append(ostr, output);
  301.     octstr_destroy(output);
  302. }
  303. void octstr_binary_to_hex(Octstr *ostr, int uppercase)
  304. {
  305.     unsigned char *hexits;
  306.     long i;
  307.     seems_valid(ostr);
  308.     gw_assert(!ostr->immutable);
  309.     if (ostr->len == 0)
  310.         return;
  311.     hexits = uppercase ? "0123456789ABCDEF" : "0123456789abcdef";
  312.     octstr_grow(ostr, ostr->len * 2);
  313.     /* In-place modification must be done back-to-front to avoid
  314.      * overwriting the data while we read it.  Even the order of
  315.      * the two assignments is important, to get i == 0 right. */
  316.     for (i = ostr->len - 1; i >= 0; i--) {
  317.         ostr->data[i * 2 + 1] = hexits[ostr->data[i] % 16];
  318.         ostr->data[i * 2] = hexits[(ostr->data[i] / 16) & 0xf];
  319.     }
  320.     ostr->len = ostr->len * 2;
  321.     ostr->data[ostr->len] = '';
  322.     seems_valid(ostr);
  323. }
  324. int octstr_hex_to_binary(Octstr *ostr)
  325. {
  326.     long len, i;
  327.     unsigned char *p;
  328.     seems_valid(ostr);
  329.     gw_assert(!ostr->immutable);
  330.     if (ostr->len == 0)
  331.         return 0;
  332.     /* Check if it's in the right format */
  333.     if (!octstr_check_range(ostr, 0, ostr->len, gw_isxdigit))
  334.         return -1;
  335.     len = ostr->len;
  336.     /* Convert ascii data to binary values */
  337.     for (i = 0, p = ostr->data; i < len; i++, p++) {
  338.         if (*p >= '0' && *p <= '9')
  339.             *p -= '0';
  340.         else if (*p >= 'a' && *p <= 'f')
  341.             *p = *p - 'a' + 10;
  342.         else if (*p >= 'A' && *p <= 'F')
  343.             *p = *p - 'A' + 10;
  344.         else {
  345.             /* isxdigit checked the whole string, so we should
  346.              * not be able to get here. */
  347.             gw_assert(0);
  348.             *p = 0;
  349.         }
  350.     }
  351.     /* De-hexing will compress data by factor of 2 */
  352.     len = ostr->len / 2;
  353.     for (i = 0; i < len; i++) {
  354.         ostr->data[i] = ostr->data[i * 2] * 16 | ostr->data[i * 2 + 1];
  355.     }
  356.     ostr->len = len;
  357.     ostr->data[len] = '';
  358.     seems_valid(ostr);
  359.     return 0;
  360. }
  361. void octstr_binary_to_base64(Octstr *ostr)
  362. {
  363.     static const unsigned char base64[64] =
  364.         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  365.     long triplets;
  366.     long lines;
  367.     long orig_len;
  368.     unsigned char *data;
  369.     long from, to;
  370.     int left_on_line;
  371.     seems_valid(ostr);
  372.     gw_assert(!ostr->immutable);
  373.     if (ostr->len == 0) {
  374.         /* Always terminate with CR LF */
  375.         octstr_insert(ostr, octstr_imm("1512"), 0);
  376.         return;
  377.     }
  378.     /* The lines must be 76 characters each (or less), and each
  379.      * triplet will expand to 4 characters, so we can fit 19
  380.      * triplets on one line.  We need a CR LF after each line,
  381.      * which will add 2 octets per 19 triplets (rounded up). */
  382.     triplets = (ostr->len + 2) / 3;   /* round up */
  383.     lines = (triplets + 18) / 19;
  384.     octstr_grow(ostr, triplets * 4 + lines * 2);
  385.     orig_len = ostr->len;
  386.     data = ostr->data;
  387.     ostr->len = triplets * 4 + lines * 2;
  388.     data[ostr->len] = '';
  389.     /* This function works back-to-front, so that encoded data will
  390.      * not overwrite source data.
  391.      * from points to the start of the last triplet (which may be
  392.      * an odd-sized one), and to points to the start of where the
  393.      * last quad should go.  */
  394.     from = (triplets - 1) * 3;
  395.     to = (triplets - 1) * 4 + (lines - 1) * 2;
  396.     /* First write the CR LF after the last quad */
  397.     data[to + 5] = 10;   /* LF */
  398.     data[to + 4] = 13;   /* CR */
  399.     left_on_line = triplets - ((lines - 1) * 19);
  400.     /* base64 encoding is in 3-octet units.  To handle leftover
  401.      * octets, conceptually we have to zero-pad up to the next
  402.      * 6-bit unit, and pad with '=' characters for missing 6-bit
  403.      * units.
  404.      * We do it by first completing the first triplet with 
  405.      * zero-octets, and after the loop replacing some of the
  406.      * result characters with '=' characters.
  407.      * There is enough room for this, because even with a 1 or 2
  408.      * octet source string, space for four octets of output
  409.      * will be reserved.
  410.      */
  411.     switch (orig_len % 3) {
  412.     case 0:
  413.         break;
  414.     case 1:
  415.         data[orig_len] = 0;
  416.         data[orig_len + 1] = 0;
  417.         break;
  418.     case 2:
  419.         data[orig_len + 1] = 0;
  420.         break;
  421.     }
  422.     /* Now we only have perfect triplets. */
  423.     while (from >= 0) {
  424.         long whole_triplet;
  425.         /* Add a newline, if necessary */
  426.         if (left_on_line == 0) {
  427.             to -= 2;
  428.             data[to + 5] = 10;  /* LF */
  429.             data[to + 4] = 13;  /* CR */
  430.             left_on_line = 19;
  431.         }
  432.         whole_triplet = (data[from] << 16) |
  433.                         (data[from + 1] << 8) |
  434.                         data[from + 2];
  435.         data[to + 3] = base64[whole_triplet % 64];
  436.         data[to + 2] = base64[(whole_triplet >> 6) % 64];
  437.         data[to + 1] = base64[(whole_triplet >> 12) % 64];
  438.         data[to] = base64[(whole_triplet >> 18) % 64];
  439.         to -= 4;
  440.         from -= 3;
  441.         left_on_line--;
  442.     }
  443.     gw_assert(left_on_line == 0);
  444.     gw_assert(from == -3);
  445.     gw_assert(to == -4);
  446.     /* Insert padding characters in the last quad.  Remember that
  447.      * there is a CR LF between the last quad and the end of the
  448.      * string. */
  449.     switch (orig_len % 3) {
  450.     case 0:
  451.         break;
  452.     case 1:
  453.         gw_assert(data[ostr->len - 3] == 'A');
  454.         gw_assert(data[ostr->len - 4] == 'A');
  455.         data[ostr->len - 3] = '=';
  456.         data[ostr->len - 4] = '=';
  457.         break;
  458.     case 2:
  459.         gw_assert(data[ostr->len - 3] == 'A');
  460.         data[ostr->len - 3] = '=';
  461.         break;
  462.     }
  463.     seems_valid(ostr);
  464. }
  465. void octstr_base64_to_binary(Octstr *ostr)
  466. {
  467.     long triplet;
  468.     long pos, len;
  469.     long to;
  470.     int quadpos = 0;
  471.     int warned = 0;
  472.     unsigned char *data;
  473.     seems_valid(ostr);
  474.     gw_assert(!ostr->immutable);
  475.     len = ostr->len;
  476.     data = ostr->data;
  477.     if (len == 0)
  478.         return;
  479.     to = 0;
  480.     triplet = 0;
  481.     quadpos = 0;
  482.     for (pos = 0; pos < len; pos++) {
  483.         int c = data[pos];
  484.         int sixbits;
  485.         if (c >= 'A' && c <= 'Z') {
  486.             sixbits = c - 'A';
  487.         } else if (c >= 'a' && c <= 'z') {
  488.             sixbits = 26 + c - 'a';
  489.         } else if (c >= '0' && c <= '9') {
  490.             sixbits = 52 + c - '0';
  491.         } else if (c == '+') {
  492.             sixbits = 62;
  493.         } else if (c == '/') {
  494.             sixbits = 63;
  495.         } else if (c == '=') {
  496.             /* These can only occur at the end of encoded
  497.              * text.  RFC 2045 says we can assume it really
  498.              * is the end. */
  499.             break;
  500.         } else if (isspace(c)) {
  501.             /* skip whitespace */
  502.             continue;
  503.         } else {
  504.             if (!warned) {
  505.                 warning(0, "Unusual characters in base64 "
  506.                         "encoded text.");
  507.                 warned = 1;
  508.             }
  509.             continue;
  510.         }
  511.         triplet = (triplet << 6) | sixbits;
  512.         quadpos++;
  513.         if (quadpos == 4) {
  514.             data[to++] = (triplet >> 16) & 0xff;
  515.             data[to++] = (triplet >> 8) & 0xff;
  516.             data[to++] = triplet & 0xff;
  517.             quadpos = 0;
  518.         }
  519.     }
  520.     /* Deal with leftover octets */
  521.     switch (quadpos) {
  522.     case 0:
  523.         break;
  524.     case 3:  /* triplet has 18 bits, we want the first 16 */
  525.         data[to++] = (triplet >> 10) & 0xff;
  526.         data[to++] = (triplet >> 2) & 0xff;
  527.         break;
  528.     case 2:  /* triplet has 12 bits, we want the first 8 */
  529.         data[to++] = (triplet >> 4) & 0xff;
  530.         break;
  531.     case 1:
  532.         warning(0, "Bad padding in base64 encoded text.");
  533.         break;
  534.     }
  535.     ostr->len = to;
  536.     data[to] = '';
  537.     seems_valid(ostr);
  538. }
  539. long octstr_parse_long(long *nump, Octstr *ostr, long pos, int base)
  540. {
  541.     /* strtol wants a char *, and we have to compare the result to
  542.      * an unsigned char *.  The easiest way to avoid warnings without
  543.      * introducing typecasts is to use two variables. */
  544.     char *endptr;
  545.     unsigned char *endpos;
  546.     long number;
  547.     seems_valid(ostr);
  548.     gw_assert(nump != NULL);
  549.     gw_assert(base == 0 || (base >= 2 && base <= 36));
  550.     if (pos >= ostr->len) {
  551.         errno = EINVAL;
  552.         return -1;
  553.     }
  554.     errno = 0;
  555.     number = strtol(ostr->data + pos, &endptr, base);
  556.     endpos = endptr;
  557.     if (errno == ERANGE)
  558.         return -1;
  559.     if (endpos == ostr->data + pos) {
  560.         errno = EINVAL;
  561.         return -1;
  562.     }
  563.     *nump = number;
  564.     return endpos - ostr->data;
  565. }
  566. int octstr_check_range(Octstr *ostr, long pos, long len,
  567.                        octstr_func_t filter)
  568. {
  569.     long end = pos + len;
  570.     seems_valid(ostr);
  571.     gw_assert(len >= 0);
  572.     if (pos >= ostr->len)
  573.         return 1;
  574.     if (end > ostr->len)
  575.         end = ostr->len;
  576.     for ( ; pos < end; pos++) {
  577.         if (!filter(ostr->data[pos]))
  578.             return 0;
  579.     }
  580.     return 1;
  581. }
  582. void octstr_convert_range(Octstr *ostr, long pos, long len,
  583.                           octstr_func_t map)
  584. {
  585.     long end = pos + len;
  586.     seems_valid(ostr);
  587.     gw_assert(!ostr->immutable);
  588.     gw_assert(len >= 0);
  589.     if (pos >= ostr->len)
  590.         return;
  591.     if (end > ostr->len)
  592.         end = ostr->len;
  593.     for ( ; pos < end; pos++) {
  594.         ostr->data[pos] = map(ostr->data[pos]);
  595.     }
  596.     seems_valid(ostr);
  597. }
  598. int octstr_compare(Octstr *ostr1, Octstr *ostr2)
  599. {
  600.     int ret;
  601.     long len;
  602.     seems_valid(ostr1);
  603.     seems_valid(ostr2);
  604.     if (ostr1->len < ostr2->len)
  605.         len = ostr1->len;
  606.     else
  607.         len = ostr2->len;
  608.     if (len == 0) {
  609. if (ostr1->len == 0 && ostr2->len > 0)
  610.     return -1;
  611. if (ostr1->len > 0 && ostr2->len == 0)
  612.     return 1;
  613.         return 0;
  614.     }
  615.     ret = memcmp(ostr1->data, ostr2->data, len);
  616.     if (ret == 0) {
  617.         if (ostr1->len < ostr2->len)
  618.             ret = -1;
  619.         else if (ostr1->len > ostr2->len)
  620.             ret = 1;
  621.     }
  622.     return ret;
  623. }
  624. int octstr_case_compare(Octstr *os1, Octstr *os2)
  625. {
  626.     int c1, c2;
  627.     long i, len;
  628.     seems_valid(os1);
  629.     seems_valid(os2);
  630.     if (os1->len < os2->len)
  631.         len = os1->len;
  632.     else
  633.         len = os2->len;
  634.     if (len == 0) {
  635. if (os1->len == 0 && os2->len > 0)
  636.     return -1;
  637. if (os1->len > 0 && os2->len == 0)
  638.     return 1;
  639.         return 0;
  640.     }
  641.     for (i = 0; i < len; ++i) {
  642. c1 = toupper(os1->data[i]);
  643. c2 = toupper(os2->data[i]);
  644. if (c1 != c2)
  645.     break;
  646.     }
  647.     if (i == len) {
  648. if (i == os1->len && i == os2->len)
  649.     return 0;
  650. if (i == os1->len)
  651.     return -1;
  652. return 1;
  653.     } else {
  654. c1 = toupper(os1->data[i]);
  655. c2 = toupper(os2->data[i]);
  656. if (c1 < c2)
  657.     return -1;
  658. if (c1 == c2)
  659.     return 0;
  660. return 1;
  661.     }
  662. }
  663. int octstr_ncompare(Octstr *ostr1, Octstr *ostr2, long n)
  664. {
  665.     long len;
  666.     seems_valid(ostr1);
  667.     seems_valid(ostr2);
  668.     if ((ostr1->len < ostr2->len) && (ostr1->len < n))
  669.         len = ostr1->len;
  670.     else if ((ostr2->len < ostr1->len) && (ostr2->len < n))
  671.         len = ostr2->len;
  672.     else
  673.         len = n;
  674.     if (len == 0)
  675.         return 0;
  676.     return memcmp(ostr1->data, ostr2->data, len);
  677. }
  678. int octstr_str_compare(Octstr *ostr, const char *str)
  679. {
  680.     seems_valid(ostr);
  681.     if (str == NULL)
  682.         return -1;
  683.     if (ostr->data == NULL)
  684. return strcmp("", str);
  685.     return strcmp(ostr->data, str);
  686. }
  687. int octstr_search_char(Octstr *ostr, int ch, long pos)
  688. {
  689.     unsigned char *p;
  690.     seems_valid(ostr);
  691.     gw_assert(ch >= 0);
  692.     gw_assert(ch <= UCHAR_MAX);
  693.     gw_assert(pos >= 0);
  694.     if (pos >= ostr->len)
  695.         return -1;
  696.     p = memchr(ostr->data + pos, ch, ostr->len - pos);
  697.     if (!p)
  698.         return -1;
  699.     return p - ostr->data;
  700. }
  701. int octstr_search(Octstr *haystack, Octstr *needle, long pos)
  702. {
  703.     int first;
  704.     seems_valid(haystack);
  705.     seems_valid(needle);
  706.     gw_assert(pos >= 0);
  707.     /* Always "find" an empty string */
  708.     if (needle->len == 0)
  709.         return 0;
  710.     if (needle->len == 1)
  711.         return octstr_search_char(haystack, needle->data[0], pos);
  712.     /* For each occurrence of needle's first character in ostr,
  713.      * check if the rest of needle follows.  Stop if there are no
  714.      * more occurrences, or if the rest of needle can't possibly
  715.      * fit in the haystack. */
  716.     first = needle->data[0];
  717.     pos = octstr_search_char(haystack, first, pos);
  718.     while (pos >= 0 && haystack->len - pos >= needle->len) {
  719.         if (memcmp(haystack->data + pos,
  720.                    needle->data, needle->len) == 0)
  721.             return pos;
  722.         pos = octstr_search_char(haystack, first, pos + 1);
  723.     }
  724.     return -1;
  725. }
  726. int octstr_case_search(Octstr *haystack, Octstr *needle, long pos)
  727. {
  728.     long i, j;
  729.     int c1, c2;
  730.     seems_valid(haystack);
  731.     seems_valid(needle);
  732.     gw_assert(pos >= 0);
  733.     /* Always "find" an empty string */
  734.     if (needle->len == 0)
  735.         return 0;
  736.     for (i = pos; i <= haystack->len - needle->len; ++i) {
  737. for (j = 0; j < needle->len; ++j) {
  738.     c1 = toupper(haystack->data[i + j]);
  739.     c2 = toupper(needle->data[j]);
  740.     if (c1 != c2)
  741.      break;
  742. }
  743. if (j == needle->len)
  744.     return i;
  745.     }
  746.     return -1;    
  747. }
  748. int octstr_print(FILE *f, Octstr *ostr)
  749. {
  750.     gw_assert(f != NULL);
  751.     seems_valid(ostr);
  752.     if (ostr->len == 0)
  753.         return 0;
  754.     if (fwrite(ostr->data, ostr->len, 1, f) != 1) {
  755.         error(errno, "Couldn't write all of octet string to file.");
  756.         return -1;
  757.     }
  758.     return 0;
  759. }
  760. int octstr_pretty_print(FILE *f, Octstr *ostr)
  761. {
  762.     unsigned char *p;
  763.     long i;
  764.     gw_assert(f != NULL);
  765.     seems_valid(ostr);
  766.     p = ostr->data;
  767.     for (i = 0; i < ostr->len; ++i, ++p) {
  768.         if (isprint(*p))
  769.             fprintf(f, "%c", *p);
  770.         else
  771.             fprintf(f, "\x%02x", *p);
  772.     }
  773.     if (ferror(f))
  774.         return -1;
  775.     return 0;
  776. }
  777. int octstr_write_to_socket(int socket, Octstr *ostr)
  778. {
  779.     long len;
  780.     unsigned char *data;
  781.     int ret;
  782.     gw_assert(socket >= 0);
  783.     seems_valid(ostr);
  784.     data = ostr->data;
  785.     len = ostr->len;
  786.     while (len > 0) {
  787.         ret = write(socket, data, len);
  788.         if (ret == -1) {
  789.             if (errno != EINTR) {
  790.                 error(errno, "Writing to socket failed");
  791.                 return -1;
  792.             }
  793.         } else {
  794.             /* ret may be less than len */
  795.             len -= ret;
  796.             data += ret;
  797.         }
  798.     }
  799.     return 0;
  800. }
  801. long octstr_write_data(Octstr *ostr, int fd, long from)
  802. {
  803.     long ret;
  804.     gw_assert(fd >= 0);
  805.     gw_assert(from >= 0);
  806.     seems_valid(ostr);
  807.     if (from >= ostr->len)
  808.         return 0;
  809.     ret = write(fd, ostr->data + from, ostr->len - from);
  810.     if (ret < 0) {
  811.         if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)
  812.             return 0;
  813.         error(errno, "Error writing %ld octets to fd %d:",
  814.               ostr->len - from, fd);
  815.         return -1;
  816.     }
  817.     return ret;
  818. }
  819. int octstr_append_from_socket(Octstr *ostr, int socket)
  820. {
  821.     unsigned char buf[4096];
  822.     int len;
  823.     seems_valid(ostr);
  824.     gw_assert(!ostr->immutable);
  825. again:
  826.     len = recv(socket, buf, sizeof(buf), 0);
  827.     if (len < 0 && errno == EINTR)
  828.         goto again;
  829.     if (len < 0) {
  830.         error(errno, "Could not read from socket %d", socket);
  831.         return -1;
  832.     }
  833.     octstr_append_data(ostr, buf, len);
  834.     return len;
  835. }
  836. void octstr_insert(Octstr *ostr1, Octstr *ostr2, long pos)
  837. {
  838.     seems_valid(ostr1);
  839.     seems_valid(ostr2);
  840.     gw_assert(pos <= ostr1->len);
  841.     gw_assert(!ostr1->immutable);
  842.     if (ostr2->len == 0)
  843.         return;
  844.     octstr_grow(ostr1, ostr1->len + ostr2->len);
  845.     memmove(ostr1->data + pos + ostr2->len, ostr1->data + pos,
  846.             ostr1->len - pos);
  847.     memcpy(ostr1->data + pos, ostr2->data, ostr2->len);
  848.     ostr1->len += ostr2->len;
  849.     ostr1->data[ostr1->len] = '';
  850.     seems_valid(ostr1);
  851. }
  852. void octstr_truncate(Octstr *ostr, int new_len)
  853. {
  854.     seems_valid(ostr);
  855.     gw_assert(!ostr->immutable);
  856.     gw_assert(new_len >= 0);
  857.     if (new_len >= ostr->len)
  858.         return;
  859.     ostr->len = new_len;
  860.     ostr->data[new_len] = '';
  861.     seems_valid(ostr);
  862. }
  863. void octstr_strip_blanks(Octstr *text)
  864. {
  865.     int start = 0, end, len = 0;
  866.     seems_valid(text);
  867.     gw_assert(!text->immutable);
  868.     /* Remove white space from the beginning of the text */
  869.     while (isspace(octstr_get_char(text, start)) && 
  870.    start <= octstr_len(text))
  871.         start ++;
  872.     if (start > 0)
  873.         octstr_delete(text, 0, start);
  874.     /* and from the end. */
  875.     if ((len = octstr_len(text)) > 0) {
  876.         end = len = len - 1;
  877.         while (isspace(octstr_get_char(text, end)) && end >= 0)
  878.             end--;
  879.         octstr_delete(text, end + 1, len - end);
  880.     }
  881.     seems_valid(text);
  882. }
  883. static int iscrlf(unsigned char c)
  884. {
  885.     return c == 'n' || c == 'r';
  886. }
  887. void octstr_strip_crlfs(Octstr *text)
  888. {
  889.     int start = 0, end, len = 0;
  890.     seems_valid(text);
  891.     gw_assert(!text->immutable);
  892.     /* Remove white space from the beginning of the text */
  893.     while (iscrlf(octstr_get_char(text, start)) && 
  894.    start <= octstr_len(text))
  895.         start ++;
  896.     if (start > 0)
  897.         octstr_delete(text, 0, start);
  898.     /* and from the end. */
  899.     if ((len = octstr_len(text)) > 0) {
  900.         end = len = len - 1;
  901.         while (iscrlf(octstr_get_char(text, end)) && end >= 0)
  902.             end--;
  903.         octstr_delete(text, end + 1, len - end);
  904.     }
  905.     seems_valid(text);
  906. }
  907. void octstr_strip_nonalphanums(Octstr *text)
  908. {
  909.     int start = 0, end, len = 0;
  910.     seems_valid(text);
  911.     gw_assert(!text->immutable);
  912.     /* Remove white space from the beginning of the text */
  913.     while (!isalnum(octstr_get_char(text, start)) && 
  914.    start <= octstr_len(text))
  915.         start ++;
  916.     if (start > 0)
  917.         octstr_delete(text, 0, start);
  918.     /* and from the end. */
  919.     if ((len = octstr_len(text)) > 0) {
  920.         end = len = len - 1;
  921.         while (!isalnum(octstr_get_char(text, end)) && end >= 0)
  922.             end--;
  923.         octstr_delete(text, end + 1, len - end);
  924.     }
  925.     seems_valid(text);
  926. }
  927. void octstr_shrink_blanks(Octstr *text)
  928. {
  929.     int i, j, end;
  930.     seems_valid(text);
  931.     gw_assert(!text->immutable);
  932.     end = octstr_len(text);
  933.     /* Shrink white spaces to one  */
  934.     for (i = 0; i < end; i++) {
  935.         if (isspace(octstr_get_char(text, i))) {
  936.             /* Change the remaining space into single space. */
  937.             if (octstr_get_char(text, i) != ' ')
  938.                 octstr_set_char(text, i, ' ');
  939.             j = i = i + 1;
  940.             while (isspace(octstr_get_char(text, j)))
  941.                 j ++;
  942.             if (j - i > 1)
  943.                 octstr_delete(text, i, j - i);
  944.         }
  945.     }
  946.     seems_valid(text);
  947. }
  948. void octstr_insert_data(Octstr *ostr, long pos, const char *data, long len)
  949. {
  950.     seems_valid(ostr);
  951.     gw_assert(!ostr->immutable);
  952.     gw_assert(pos <= ostr->len);
  953.     if (len == 0)
  954.         return;
  955.     octstr_grow(ostr, ostr->len + len);
  956.     if (ostr->len > pos) { /* only if neccessary*/
  957.         memmove(ostr->data + pos + len, ostr->data + pos, ostr->len - pos);
  958.     }
  959.     memcpy(ostr->data + pos, data, len);
  960.     ostr->len += len;
  961.     ostr->data[ostr->len] = '';
  962.     seems_valid(ostr);
  963. }
  964. void octstr_insert_char(Octstr *ostr, long pos, const char c)
  965. {
  966.     seems_valid(ostr);
  967.     gw_assert(!ostr->immutable);
  968.     gw_assert(pos <= ostr->len);
  969.     
  970.     octstr_grow(ostr, ostr->len + 1);
  971.     if (ostr->len > pos)
  972.         memmove(ostr->data + pos + 1, ostr->data + pos, ostr->len - pos);
  973.     memcpy(ostr->data + pos, &c, 1);
  974.     ostr->len += 1;
  975.     ostr->data[ostr->len] = '';
  976.     
  977.     seems_valid(ostr);
  978. }
  979. void octstr_append_data(Octstr *ostr, const char *data, long len)
  980. {
  981.     gw_assert(ostr != NULL);
  982.     octstr_insert_data(ostr, ostr->len, data, len);
  983. }
  984. void octstr_append(Octstr *ostr1, Octstr *ostr2)
  985. {
  986.     gw_assert(ostr1 != NULL);
  987.     octstr_insert(ostr1, ostr2, ostr1->len);
  988. }
  989. void octstr_append_cstr(Octstr *ostr, const char *cstr)
  990. {
  991.     octstr_insert_data(ostr, ostr->len, cstr, strlen(cstr));
  992. }
  993. void octstr_append_char(Octstr *ostr, int ch)
  994. {
  995.     unsigned char c = ch;
  996.     gw_assert(ch >= 0);
  997.     gw_assert(ch <= UCHAR_MAX);
  998.     octstr_insert_data(ostr, ostr->len, &c, 1);
  999. }
  1000. void octstr_delete(Octstr *ostr1, long pos, long len)
  1001. {
  1002.     seems_valid(ostr1);
  1003.     gw_assert(!ostr1->immutable);
  1004.     if (pos > ostr1->len)
  1005.         pos = ostr1->len;
  1006.     if (pos + len > ostr1->len)
  1007.         len = ostr1->len - pos;
  1008.     if (len > 0) {
  1009.         memmove(ostr1->data + pos, ostr1->data + pos + len,
  1010.                 ostr1->len - pos - len);
  1011.         ostr1->len -= len;
  1012.         ostr1->data[ostr1->len] = '';
  1013.     }
  1014.     seems_valid(ostr1);
  1015. }
  1016. Octstr *octstr_read_file(const char *filename)
  1017. {
  1018.     FILE *f;
  1019.     Octstr *os;
  1020.     char buf[4096];
  1021.     long n;
  1022.     gw_assert(filename != NULL);
  1023.     f = fopen(filename, "r");
  1024.     if (f == NULL) {
  1025.         error(errno, "fopen failed: couldn't open `%s'", filename);
  1026.         return NULL;
  1027.     }
  1028.     os = octstr_create("");
  1029.     if (os == NULL)
  1030.         goto error;
  1031.     while ((n = fread(buf, 1, sizeof(buf), f)) > 0)
  1032.         octstr_insert_data(os, octstr_len(os), buf, n);
  1033.     (void) fclose(f);
  1034.     return os;
  1035. error:
  1036.     (void) fclose(f);
  1037.     octstr_destroy(os);
  1038.     return NULL;
  1039. }
  1040. Octstr *octstr_read_pipe(FILE *f)
  1041. {
  1042.     Octstr *os;
  1043.     char buf[4096];
  1044.     gw_assert(f != NULL);
  1045.     os = octstr_create("");
  1046.     if (os == NULL)
  1047.         goto error;
  1048.     while (fgets(buf, sizeof(buf), f) != NULL)
  1049.         octstr_append_data(os, buf, strlen(buf));
  1050.     return os;
  1051. error:
  1052.     octstr_destroy(os);
  1053.     return NULL;
  1054. }
  1055. List *octstr_split_words(Octstr *ostr)
  1056. {
  1057.     unsigned char *p;
  1058.     List *list;
  1059.     Octstr *word;
  1060.     long i, start, end;
  1061.     seems_valid(ostr);
  1062.     list = list_create();
  1063.     p = ostr->data;
  1064.     i = 0;
  1065.     for (; ; ) {
  1066.         while (i < ostr->len && isspace(*p)) {
  1067.             ++p;
  1068.             ++i;
  1069.         }
  1070.         start = i;
  1071.         while (i < ostr->len && !isspace(*p)) {
  1072.             ++p;
  1073.             ++i;
  1074.         }
  1075.         end = i;
  1076.         if (start == end)
  1077.             break;
  1078.         word = octstr_create_from_data(ostr->data + start,
  1079.                                        end - start);
  1080.         list_append(list, word);
  1081.     }
  1082.     return list;
  1083. }
  1084. List *octstr_split(Octstr *os, Octstr *sep)
  1085. {
  1086.     List *list;
  1087.     long next, pos, seplen;
  1088.     
  1089.     list = list_create();
  1090.     pos = 0;
  1091.     seplen = octstr_len(sep);
  1092.     while ((next = octstr_search(os, sep, pos)) != -1) {
  1093. list_append(list, octstr_copy(os, pos, next - pos));
  1094. pos = next + seplen;
  1095.     }
  1096.     
  1097.     if (pos < octstr_len(os))
  1098.      list_append(list, octstr_copy(os, pos, octstr_len(os)));
  1099.     
  1100.     return list;
  1101. }
  1102. int octstr_item_match(void *item, void *pattern)
  1103. {
  1104.     return octstr_compare(item, pattern) == 0;
  1105. }
  1106. void octstr_dump(Octstr *ostr, int level)
  1107. {
  1108.     unsigned char *p, *d, buf[1024], charbuf[256];
  1109.     long pos;
  1110.     const int octets_per_line = 8;
  1111.     int c, this_line_begins_at;
  1112.     if (ostr == NULL)
  1113.         return;
  1114.     seems_valid(ostr);
  1115.     debug("gwlib.octstr", 0, "%*sOctet string at %p:", level, "",
  1116.           (void *) ostr);
  1117.     debug("gwlib.octstr", 0, "%*s  len:  %lu", level, "",
  1118.           (unsigned long) ostr->len);
  1119.     debug("gwlib.octstr", 0, "%*s  size: %lu", level, "",
  1120.           (unsigned long) ostr->size);
  1121.     debug("gwlib.octstr", 0, "%*s  immutable: %d", level, "",
  1122.           ostr->immutable);
  1123.     buf[0] = '';
  1124.     p = buf;
  1125.     d = charbuf;
  1126.     this_line_begins_at = 0;
  1127.     for (pos = 0; pos < octstr_len(ostr); ) {
  1128.         c = octstr_get_char(ostr, pos);
  1129.         sprintf(p, "%02x ", c);
  1130.         p = strchr(p, '');
  1131.         if (isprint(c))
  1132.             *d++ = c;
  1133.         else
  1134.             *d++ = '.';
  1135.         ++pos;
  1136.         if (pos - this_line_begins_at == octets_per_line) {
  1137.             *d = '';
  1138.             debug("gwlib.octstr", 0, "%*s  data: %s  %s", level, "",
  1139.                   buf, charbuf);
  1140.             buf[0] = '';
  1141.             charbuf[0] = '';
  1142.             p = buf;
  1143.             d = charbuf;
  1144.             this_line_begins_at = pos;
  1145.         }
  1146.     }
  1147.     if (pos - this_line_begins_at > 0) {
  1148.         *d = '';
  1149.         debug("gwlib.octstr", 0, "%*s  data: %-*.*s  %s", level, "",
  1150.               octets_per_line*3,
  1151.               octets_per_line*3, buf, charbuf);
  1152.     }
  1153.     debug("gwlib.octstr", 0, "%*sOctet string dump ends.", level, "");
  1154. }
  1155. void octstr_dump_short(Octstr *ostr, int level, const char *name)
  1156. {
  1157.     char buf[100];
  1158.     char *p;
  1159.     long i;
  1160.     int c;
  1161.     if (ostr == NULL) {
  1162.         debug("gwlib.octstr", 0, "%*s%s: NULL", level, "", name);
  1163.         return;
  1164.     }
  1165.     seems_valid(ostr);
  1166.     if (ostr->len < 20) {
  1167.         p = buf;
  1168.         for (i = 0; i < ostr->len; i++) {
  1169.             c = ostr->data[i];
  1170.             if (c == 'n') {
  1171.                 *p++ = '\';
  1172.                 *p++ = 'n';
  1173.             } else if (!isprint(c)) {
  1174.                 break;
  1175.             } else if (c == '"') {
  1176.                 *p++ = '\';
  1177.                 *p++ = '"';
  1178.             } else if (c == '\') {
  1179.                 *p++ = '\';
  1180.                 *p++ = '\';
  1181.             } else {
  1182.                 *p++ = c;
  1183.             }
  1184.         }
  1185.         if (i == ostr->len) {
  1186.             *p++ = 0;
  1187.             /* We got through the loop without hitting nonprintable
  1188.              * characters. */
  1189.             debug("gwlib.octstr", 0, "%*s%s: "%s"", level, "", name, buf);
  1190.             return;
  1191.         }
  1192.     }
  1193.     debug("gwlib.octstr", 0, "%*s%s:", level, "", name);
  1194.     octstr_dump(ostr, level + 1);
  1195. }
  1196. void octstr_url_encode(Octstr *ostr)
  1197. {
  1198.     int i, n, newlen;
  1199.     unsigned char *str, *str2, *hexits;
  1200.     unsigned char c;
  1201.     Octstr *res;
  1202.     seems_valid(ostr);
  1203.     if (ostr->len == 0)
  1204. return;
  1205.     res = octstr_create("");
  1206.     str = ostr->data;
  1207.     n = 0;
  1208.     for (i = 0; i < ostr->len; i++)
  1209. if (!is_safe[*str++])
  1210.     n++;
  1211.     newlen = ostr->len + 2 * n;
  1212.     res->len = newlen;
  1213.     res->size = res->len + 1;
  1214.     res->data = gw_malloc(res->size);
  1215.     hexits = "0123456789ABCDEF";
  1216.     str = ostr->data;
  1217.     str2 = res->data;
  1218.     for (i = 0; i < ostr->len; i++) {
  1219. c = *str++;
  1220. if (!is_safe[c]) {
  1221.     *str2++ = '%';
  1222.     *str2++ = hexits[c >> 4 & 0xf];
  1223.     *str2++ = hexits[c & 0xf];
  1224. }
  1225. else if (c == ' ')
  1226.     *str2++ = '+';
  1227. else
  1228.     *str2++ = c;
  1229.     }
  1230.     *str2 = 0;
  1231.     seems_valid(res);
  1232.     
  1233.     octstr_truncate(ostr, 0);
  1234.     octstr_insert(ostr, res, 0);
  1235.     octstr_destroy(res);
  1236. }
  1237. int octstr_url_decode(Octstr *ostr)
  1238. {
  1239.     long value;
  1240.     unsigned char *string = ostr->data;
  1241.     unsigned char *dptr = ostr->data;
  1242.     unsigned char buf[3];     /* buffer for strtol conversion */
  1243.     buf[2] = '';
  1244.     seems_valid(ostr);
  1245.     gw_assert(!ostr->immutable);
  1246.     if (ostr->len == 0)
  1247.         return 0;
  1248.     do {
  1249.         if (*string == '%') {
  1250.             if (*(string + 1) == '' || *(string + 2) == '')
  1251.                 goto error;
  1252.             buf[0] = *(string + 1);
  1253.             buf[1] = *(string + 2);
  1254.             value = strtol(buf, NULL, 16);
  1255.             if (value >= 0 && value < 256) {
  1256.                 *dptr = (unsigned char)value;
  1257.                 string += 3;
  1258.                 dptr++;
  1259.                 continue;
  1260.             }
  1261.             warning(0, "Garbage encoded (value = %ld)", value);
  1262.         }
  1263.         if (*string == '+') {
  1264.             *dptr++ = ' ';
  1265.             string++;
  1266.         } else
  1267.             *dptr++ = *string++;
  1268.     } while (*string);  /* we stop here because it terimates encoded string */
  1269.     *dptr = '';
  1270.     ostr->len = (dptr - ostr->data);
  1271.     seems_valid(ostr);
  1272.     return 0;
  1273. error:
  1274.     *dptr = '';
  1275.     ostr->len = (dptr - ostr->data);
  1276.     warning(0, "octstr_url_decode: corrupted end-of-string <%s>", string);
  1277.     seems_valid(ostr);
  1278.     return -1;
  1279. }
  1280. long octstr_get_bits(Octstr *ostr, long bitpos, int numbits)
  1281. {
  1282.     long pos;
  1283.     long result;
  1284.     int mask;
  1285.     int shiftwidth;
  1286.     seems_valid(ostr);
  1287.     gw_assert(bitpos >= 0);
  1288.     gw_assert(numbits <= 32);
  1289.     gw_assert(numbits >= 0);
  1290.     pos = bitpos / 8;
  1291.     bitpos = bitpos % 8;
  1292.     /* This also takes care of the len == 0 case */
  1293.     if (pos >= ostr->len)
  1294.         return 0;
  1295.     mask = (1 << numbits) - 1;
  1296.     /* It's easy if the range fits in one octet */
  1297.     if (bitpos + numbits <= 8) {
  1298.         /* shiftwidth is the number of bits to ignore on the right.
  1299.          * bitpos 0 is the leftmost bit. */
  1300.         shiftwidth = 8 - (bitpos + numbits);
  1301.         return (ostr->data[pos] >> shiftwidth) & mask;
  1302.     }
  1303.     /* Otherwise... */
  1304.     result = 0;
  1305.     while (bitpos + numbits > 8) {
  1306.         result = (result << 8) | ostr->data[pos];
  1307.         numbits -= (8 - bitpos);
  1308.         bitpos = 0;
  1309.         pos++;
  1310.         if (pos >= ostr->len)
  1311.             return (result << numbits) & mask;
  1312.     }
  1313.     gw_assert(bitpos == 0);
  1314.     result <<= numbits;
  1315.     result |= ostr->data[pos] >> (8 - numbits);
  1316.     return result & mask;
  1317. }
  1318. void octstr_set_bits(Octstr *ostr, long bitpos, int numbits,
  1319.                      unsigned long value)
  1320. {
  1321.     long pos;
  1322.     unsigned long mask;
  1323.     int shiftwidth;
  1324.     int bits;
  1325.     int maxlen;
  1326.     int c;
  1327.     seems_valid(ostr);
  1328.     gw_assert(!ostr->immutable);
  1329.     gw_assert(bitpos >= 0);
  1330.     gw_assert(numbits <= 32);
  1331.     gw_assert(numbits >= 0);
  1332.     maxlen = (bitpos + numbits + 7) / 8;
  1333.     if (maxlen > ostr->len) {
  1334.         octstr_grow(ostr, maxlen);
  1335.         /* Make sure the new octets start out with value 0 */
  1336.         for (pos = ostr->len; pos < maxlen; pos++) {
  1337.             ostr->data[pos] = 0;
  1338.         }
  1339.         ostr->len = maxlen;
  1340.         ostr->data[maxlen] = 0;
  1341.     }
  1342.     mask = (1 << numbits) - 1;
  1343.     /* mask is also the largest value that fits */
  1344.     gw_assert(value <= mask);
  1345.     pos = bitpos / 8;
  1346.     bitpos = bitpos % 8;
  1347.     /* Does the range fit in one octet? */
  1348.     if (bitpos + numbits <= 8) {
  1349.         /* shiftwidth is the number of bits to ignore on the right.
  1350.          * bitpos 0 is the leftmost bit. */
  1351.         shiftwidth = 8 - (bitpos + numbits);
  1352.         /* Extract the bits we don't want to affect */
  1353.         c = ostr->data[pos] & ~(mask << shiftwidth);
  1354.         c |= value << shiftwidth;
  1355.         gw_assert(pos < ostr->len);
  1356.         ostr->data[pos] = c;
  1357.         return;
  1358.     }
  1359.     /* Otherwise... */
  1360.     /* If speed is a problem here, we could have separate cases for
  1361.      * the first octet (which may have bitpos > 0), and the rest,
  1362.      * which don't. */
  1363.     while (bitpos + numbits > 8) {
  1364.         /* We want this many bits from the value */
  1365.         bits = 8 - bitpos;
  1366.         /* There are this many bits to their right in the value */
  1367.         shiftwidth = numbits - bits;
  1368.         /* Construct a mask for "bits" bits on the far right */
  1369.         mask = (1 << bits) - 1;
  1370.         /* Get the bits we want */
  1371.         c = (value >> shiftwidth) & mask;
  1372.         /* Merge them with the bits that are already there */
  1373.         gw_assert(pos < ostr->len);
  1374.         ostr->data[pos] = (ostr->data[pos] & ~mask) | c;
  1375.         numbits -= (8 - bitpos);
  1376.         bitpos = 0;
  1377.         pos++;
  1378.     }
  1379.     gw_assert(bitpos == 0);
  1380.     gw_assert(pos < ostr->len);
  1381.     /* Set remaining bits.  This is just like the single-octet case
  1382.      * before the loop, except that we know bitpos is 0. */
  1383.     mask = (1 << numbits) - 1;
  1384.     shiftwidth = 8 - numbits;
  1385.     c = ostr->data[pos] & ~(mask << shiftwidth);
  1386.     c |= value << shiftwidth;
  1387.     ostr->data[pos] = c;
  1388.     seems_valid(ostr);
  1389. }
  1390. void octstr_append_uintvar(Octstr *ostr, unsigned long value)
  1391. {
  1392.     /* A uintvar is defined to be up to 32 bits large, so it will
  1393.      * fit in 5 octets. */
  1394.     unsigned char octets[5];
  1395.     int i;
  1396.     int start;
  1397.     /* Handle last byte separately; it has no continuation bit,
  1398.      * and must be encoded even if value is 0. */
  1399.     octets[4] = value & 0x7f;
  1400.     value >>= 7;
  1401.     for (i = 3; value > 0 && i >= 0; i--) {
  1402.         octets[i] = 0x80 | (value & 0x7f);
  1403.         value >>= 7;
  1404.     }
  1405.     start = i + 1;
  1406.     octstr_append_data(ostr, octets + start, 5 - start);
  1407. }
  1408. long octstr_extract_uintvar(Octstr *ostr, unsigned long *value, long pos)
  1409. {
  1410.     int c;
  1411.     int count;
  1412.     unsigned long ui;
  1413.     ui = 0;
  1414.     for (count = 0; count < 5; count++) {
  1415.         c = octstr_get_char(ostr, pos + count);
  1416.         if (c < 0)
  1417.             return -1;
  1418.         ui = (ui << 7) | (c & 0x7f);
  1419.         if (!(c & 0x80)) {
  1420.             *value = ui;
  1421.             return pos + count + 1;
  1422.         }
  1423.     }
  1424.     return -1;
  1425. }
  1426. void octstr_append_decimal(Octstr *ostr, long value)
  1427. {
  1428.     char tmp[128];
  1429.     Octstr *ostmp;
  1430.     sprintf(tmp, "%ld", value);
  1431.     ostmp = octstr_create(tmp);
  1432.     octstr_append(ostr, ostmp);
  1433.     octstr_destroy(ostmp);
  1434. }
  1435. /**********************************************************************
  1436.  * octstr_format and related private functions
  1437.  */
  1438. /*
  1439.  * A parsed form of the format string. This struct has been carefully
  1440.  * defined so that it can be initialized with {0} and it will have 
  1441.  * the correct defaults.
  1442.  */
  1443. struct format
  1444. {
  1445.     int minus;
  1446.     int zero;
  1447.     long min_width;
  1448.     int has_prec;
  1449.     long prec;
  1450.     long type;
  1451. };
  1452. static void format_flags(struct format *format, const char **fmt)
  1453. {
  1454.     int done;
  1455.     done = 0;
  1456.     do
  1457.     {
  1458.         switch (**fmt) {
  1459.         case '-':
  1460.             format->minus = 1;
  1461.             break;
  1462.         case '0':
  1463.             format->zero = 1;
  1464.             break;
  1465.         default:
  1466.             done = 1;
  1467.         }
  1468.         if (!done)
  1469.             ++(*fmt);
  1470.     } while (!done);
  1471. }
  1472. static void format_width(struct format *format, const char **fmt,
  1473.                          VALPARM(args))
  1474. {
  1475.     char *end;
  1476.     if (**fmt == '*')
  1477.     {
  1478.         format->min_width = va_arg(VALST(args), int);
  1479.         ++(*fmt);
  1480.     } else if (isdigit(**(const unsigned char **) fmt))
  1481.     {
  1482.         format->min_width = strtol(*fmt, &end, 10);
  1483.         *fmt = end;
  1484.         /* XXX error checking is missing from here */
  1485.     }
  1486. }
  1487. static void format_prec(struct format *format, const char **fmt,
  1488.                         VALPARM(args))
  1489. {
  1490.     char *end;
  1491.     if (**fmt != '.')
  1492.         return;
  1493.     ++(*fmt);
  1494.     if (**fmt == '*')
  1495.     {
  1496.         format->has_prec = 1;
  1497.         format->prec = va_arg(VALST(args), int);
  1498.         ++(*fmt);
  1499.     } else if (isdigit(**(const unsigned char **) fmt))
  1500.     {
  1501.         format->has_prec = 1;
  1502.         format->prec = strtol(*fmt, &end, 10);
  1503.         *fmt = end;
  1504.         /* XXX error checking is missing from here */
  1505.     }
  1506. }
  1507. static void format_type(struct format *format, const char **fmt)
  1508. {
  1509.     switch (**fmt)
  1510.     {
  1511.     case 'h':
  1512.     case 'l':
  1513.         format->type = **fmt;
  1514.         ++(*fmt);
  1515.         break;
  1516.     }
  1517. }
  1518. static void convert(Octstr *os, struct format *format, const char **fmt,
  1519.                     VALPARM(args))
  1520. {
  1521.     Octstr *new;
  1522.     char *s, *pad;
  1523.     long n;
  1524.     unsigned long u;
  1525.     char tmpfmt[1024];
  1526.     char tmpbuf[1024];
  1527.     char c;
  1528.     void *p;
  1529.     new = NULL;
  1530.     switch (**fmt)
  1531.     {
  1532.     case 'c':
  1533.         c = va_arg(VALST(args), int);
  1534.         new = octstr_create_from_data(&c, 1);
  1535.         break;
  1536.     case 'd':
  1537.     case 'i':
  1538.         switch (format->type) {
  1539.         case 'l':
  1540.             n = va_arg(VALST(args), long);
  1541.             break;
  1542.         case 'h':
  1543.             n = (short) va_arg(VALST(args), int);
  1544.             break;
  1545.         default:
  1546.             n = va_arg(VALST(args), int);
  1547.             break;
  1548.         }
  1549.         new = octstr_create("");
  1550.         octstr_append_decimal(new, n);
  1551.         break;
  1552.     case 'o':
  1553.     case 'u':
  1554.     case 'x':
  1555.     case 'X':
  1556. switch (format->type) {
  1557. case 'l':
  1558.     u = va_arg(VALST(args), unsigned long);
  1559.     break;
  1560.         case 'h':
  1561.             u = (unsigned short) va_arg(VALST(args), unsigned int);
  1562.             break;
  1563.         default:
  1564.             u = va_arg(VALST(args), unsigned int);
  1565.             break;
  1566.         }
  1567.         tmpfmt[0] = '%';
  1568. tmpfmt[1] = 'l';
  1569. tmpfmt[2] = **fmt;
  1570. tmpfmt[3] = '';
  1571. sprintf(tmpbuf, tmpfmt, u);
  1572.         new = octstr_create(tmpbuf);
  1573.         break;
  1574.     case 'e':
  1575.     case 'f':
  1576.     case 'g':
  1577.         sprintf(tmpfmt, "%%");
  1578.         if (format->minus)
  1579.             strcat(tmpfmt, "-");
  1580.         if (format->zero)
  1581.             strcat(tmpfmt, "0");
  1582.         if (format->min_width > 0)
  1583.             sprintf(strchr(tmpfmt, ''),
  1584.                     "%ld", format->min_width);
  1585.         if (format->has_prec)
  1586.             sprintf(strchr(tmpfmt, ''),
  1587.                     ".%ld", format->prec);
  1588.         if (format->type != '')
  1589.             sprintf(strchr(tmpfmt, ''),
  1590.                     "%c", (int) format->type);
  1591.         sprintf(strchr(tmpfmt, ''), "%c", **fmt);
  1592.         snprintf(tmpbuf, sizeof(tmpbuf),
  1593.                  tmpfmt, va_arg(VALST(args), double));
  1594.         new = octstr_create(tmpbuf);
  1595.         break;
  1596.     case 's':
  1597.         s = va_arg(VALST(args), char *);
  1598.         if (format->has_prec && format->prec < (long) strlen(s))
  1599.             n = format->prec;
  1600.         else
  1601.             n = (long) strlen(s);
  1602.         new = octstr_create_from_data(s, n);
  1603.         break;
  1604.     case 'p':
  1605.      p = va_arg(VALST(args), void *);
  1606. sprintf(tmpfmt, "%p", p);
  1607. new = octstr_create(tmpfmt);
  1608. break;
  1609.     case 'S':
  1610.         new = octstr_duplicate(va_arg(VALST(args), Octstr *));
  1611.         if (!new)
  1612.             new = octstr_imm("(null)");
  1613.         if (format->has_prec)
  1614.             octstr_truncate(new, format->prec);
  1615.         break;
  1616.     case 'E':
  1617.         new = octstr_duplicate(va_arg(VALST(args), Octstr *));
  1618.         if (!new)
  1619.             new = octstr_imm("(null)");
  1620. octstr_url_encode(new);
  1621. /*
  1622.  * note: we use blind truncate - encoded character can get cut half-way.
  1623.          */
  1624.         if (format->has_prec)
  1625.             octstr_truncate(new, format->prec);
  1626.         break;
  1627.     case '%':
  1628.      new = octstr_imm("%");
  1629.      break;
  1630.     default:
  1631.         panic(0, "octstr_format format string syntax error.");
  1632.     }
  1633.     if (format->zero)
  1634.         pad = "0";
  1635.     else
  1636.         pad = " ";
  1637.     if (format->minus) {
  1638.         while (format->min_width > octstr_len(new))
  1639.             octstr_append_data(new, pad, 1);
  1640.     } else {
  1641.         while (format->min_width > octstr_len(new))
  1642.             octstr_insert_data(new, 0, pad, 1);
  1643.     }
  1644.     octstr_append(os, new);
  1645.     octstr_destroy(new);
  1646.     if (**fmt != '')
  1647.         ++(*fmt);
  1648. }
  1649. Octstr *octstr_format(const char *fmt, ...)
  1650. {
  1651.     Octstr *os;
  1652.     va_list args;
  1653.     va_start(args, fmt);
  1654.     os = octstr_format_valist(fmt, args);
  1655.     va_end(args);
  1656.     return os;
  1657. }
  1658. Octstr *octstr_format_valist_real(const char *fmt, va_list args)
  1659. {
  1660.     Octstr *os;
  1661.     size_t n;
  1662.     os = octstr_create("");
  1663.     while (*fmt != '') {
  1664.         struct format format = { 0, };
  1665.         n = strcspn(fmt, "%");
  1666.         octstr_append_data(os, fmt, n);
  1667.         fmt += n;
  1668.         gw_assert(*fmt == '%' || *fmt == '');
  1669.         if (*fmt == '')
  1670.             continue;
  1671.         ++fmt;
  1672.         format_flags(&format, &fmt);
  1673.         format_width(&format, &fmt, VARGS(args));
  1674.         format_prec(&format, &fmt, VARGS(args));
  1675.         format_type(&format, &fmt);
  1676.         convert(os, &format, &fmt, VARGS(args));
  1677.     }
  1678.     seems_valid(os);
  1679.     return os;
  1680. }
  1681. void octstr_format_append(Octstr *os, const char *fmt, ...)
  1682. {
  1683.     Octstr *temp;
  1684.     va_list args;
  1685.     va_start(args, fmt);
  1686.     temp = octstr_format_valist(fmt, args);
  1687.     va_end(args);
  1688.     octstr_append(os, temp);
  1689.     octstr_destroy(temp);
  1690. }
  1691. unsigned long octstr_hash_key(Octstr *ostr)
  1692. {
  1693.     unsigned long key = 0;
  1694.     long i;
  1695.     if (ostr == NULL)
  1696. return 0;
  1697.     for (i = 0; i < octstr_len(ostr); i++)
  1698. key = key + octstr_get_char(ostr, i);
  1699.     return key;
  1700. }
  1701. /**********************************************************************
  1702.  * Local functions.
  1703.  */
  1704. static void seems_valid_real(Octstr *ostr, const char *filename, long lineno,
  1705.                              const char *function)
  1706. {
  1707.     gw_assert(immutables_init);
  1708.     gw_assert_place(ostr != NULL,
  1709.                     filename, lineno, function);
  1710.     gw_assert_allocated(ostr,
  1711.                         filename, lineno, function);
  1712.     gw_assert_place(ostr->len >= 0,
  1713.                     filename, lineno, function);
  1714.     gw_assert_place(ostr->size >= 0,
  1715.                     filename, lineno, function);
  1716.     if (ostr->size == 0) {
  1717.         gw_assert_place(ostr->len == 0,
  1718.                         filename, lineno, function);
  1719.         gw_assert_place(ostr->data == NULL,
  1720.                         filename, lineno, function);
  1721.     } else {
  1722.         gw_assert_place(ostr->len + 1 <= ostr->size,
  1723.                         filename, lineno, function);
  1724.         gw_assert_place(ostr->data != NULL,
  1725.                         filename, lineno, function);
  1726. if (!ostr->immutable)
  1727.             gw_assert_allocated(ostr->data,
  1728.                                 filename, lineno, function);
  1729.         gw_assert_place(ostr->data[ostr->len] == '',
  1730.                         filename, lineno, function);
  1731.     }
  1732. }
  1733. int
  1734. octstr_recode (Octstr *tocode, Octstr *fromcode, Octstr *orig)
  1735. {
  1736.     Octstr *octstr_utf8 = NULL;
  1737.     Octstr *octstr_final = NULL;
  1738.     int resultcode = 0;
  1739.     
  1740.     if (octstr_case_compare(tocode, fromcode) == 0) {
  1741. goto cleanup_and_exit;
  1742.     }
  1743.     if ((octstr_case_compare(fromcode, octstr_imm ("utf-8")) != 0) &&
  1744. (octstr_case_compare(fromcode, octstr_imm ("utf8")) != 0)) {
  1745. if (charset_to_utf8(orig, &octstr_utf8, fromcode) < 0) {
  1746.     resultcode = -1;
  1747.     goto cleanup_and_exit;
  1748. }
  1749.     } else {
  1750. octstr_utf8 = octstr_duplicate(orig);
  1751.     }
  1752.     if ((octstr_case_compare(tocode, octstr_imm ("utf-8")) != 0) &&
  1753. (octstr_case_compare(tocode, octstr_imm ("utf8")) != 0)) {
  1754. if (charset_from_utf8(octstr_utf8, &octstr_final, tocode) < 0) {
  1755.     resultcode = -1;
  1756.     goto cleanup_and_exit;
  1757. }
  1758.     } else {
  1759. octstr_final = octstr_duplicate(octstr_utf8);
  1760.     }
  1761.     octstr_truncate(orig, 0);
  1762.     octstr_append(orig, octstr_final);
  1763.  cleanup_and_exit:
  1764.     octstr_destroy (octstr_utf8);
  1765.     octstr_destroy (octstr_final);
  1766.     return resultcode;
  1767. }