1 /*
2  *  Copyright (C) 2004-2008 Christos Tsantilas
3  *
4  *  This program is free software; you can redistribute it and/or
5  *  modify it under the terms of the GNU Lesser General Public
6  *  License as published by the Free Software Foundation; either
7  *  version 2.1 of the License, or (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  *  Lesser General Public License for more details.
13  *
14  *  You should have received a copy of the GNU Lesser General Public
15  *  License along with this library; if not, write to the Free Software
16  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17  *  MA  02110-1301  USA.
18  */
19 
20 #include "common.h"
21 #include "c-icap.h"
22 #include <stdio.h>
23 #include <fcntl.h>
24 #include <ctype.h>
25 #include "debug.h"
26 #include "header.h"
27 
28 
29 const char *ci_common_headers[] = {
30     "Cache-Control",
31     "Connection",
32     "Date",
33     "Expires",
34     "Pragma",
35     "Trailer",
36     "Upgrade",
37     /*And ICAP speciffic headers ..... */
38     "Encapsulated"
39 };
40 
41 
42 
43 const char *ci_methods[] = {
44     "",                        /*0x00 */
45     "OPTIONS",                 /*0x01 */
46     "REQMOD",                  /*0x02 */
47     "",                        /*0x03 */
48     "RESPMOD"                  /*0x04 */
49 };
50 
51 
52 const char *ci_request_headers[] = {
53     "Authorization",
54     "Allow",
55     "From",
56     "Host",                    /*REQUIRED ...... */
57     "Referer",
58     "User-Agent",
59     /*And ICAP specific headers ..... */
60     "Preview"
61 };
62 
63 const char *ci_responce_headers[] = {
64     "Server",
65     /*ICAP spacific headers */
66     "ISTag"
67 };
68 
69 const char *ci_options_headers[] = {
70     "Methods",
71     "Service",
72     "ISTag",
73     "Encapsulated",
74     "Opt-body-type",
75     "Max-Connections",
76     "Options-TTL",
77     "Date",
78     "Service-ID",
79     "Allow",
80     "Preview",
81     "Transfer-Preview",
82     "Transfer-Ignore",
83     "Transfer-Complete"
84 };
85 
86 
87 const struct ci_error_code ci_error_codes[] = {
88     {100, "Continue"},         /*Continue after ICAP Preview */
89     {200, "OK"},
90     {204, "Unmodified"},       /*No modifications needed */
91     {206, "Partial Content"},  /*Partial content modification*/
92     {400, "Bad request"},      /*Bad request */
93     {401, "Unauthorized"},
94     {403, "Forbidden"},
95     {404, "Service not found"},        /*ICAP Service not found */
96     {405, "Not allowed"},      /*Method not allowed for service (e.g., RESPMOD requested for
97                                    service that supports only REQMOD). */
98     {407, "Authentication Required"},
99     {408, "Request timeout"},  /*Request timeout.  ICAP server gave up waiting for a request
100                                    from an ICAP client */
101     {500, "Server error"},     /*Server error.  Error on the ICAP server, such as "out of disk
102                                    space" */
103     {501, "Not implemented"},  /*Method not implemented.  This response is illegal for an
104                                    OPTIONS request since implementation of OPTIONS is mandatory. */
105     {502, "Bad Gateway"},      /*Bad Gateway.  This is an ICAP proxy and proxying produced an
106                                    error. */
107     {503, "Service overloaded"},       /*Service overloaded.  The ICAP server has exceeded a maximum
108                                            connection limit associated with this service; the ICAP client
109                                            should not exceed this limit in the future. */
110     {505, "Unsupported version"}       /*ICAP version not supported by server. */
111 };
112 
113 /*
114 #ifdef __CYGWIN__
115 int ci_error_code(int ec){
116      return (ec >= EC_100 && ec < EC_MAX ? ci_error_codes[ec].code:1000);
117 }
118 
119 const char *unknownerrorcode = "UNKNOWN ERROR CODE";
120 
121 const char *ci_error_code_string(int ec){
122      return (ec >= EC_100 && ec < EC_MAX?ci_error_codes[ec].str:unknownerrorcode);
123 }
124 #endif
125 */
126 
127 
128 const char *ci_encaps_entities[] = {
129     "req-hdr",
130     "res-hdr",
131     "req-body",
132     "res-body",
133     "null-body",
134     "opt-body"
135 };
136 
137 #ifdef __CYGWIN__
138 
139 const char *unknownentity = "UNKNOWN";
140 const char *unknownmethod = "UNKNOWN";
141 
ci_method_string(int method)142 const char *ci_method_string(int method)
143 {
144     return (method <= ICAP_RESPMOD
145             && method >= ICAP_OPTIONS ? CI_Methods[method] : unknownmethod);
146 }
147 
148 
ci_encaps_entity_string(int e)149 const char *ci_encaps_entity_string(int e)
150 {
151     return (e <= ICAP_OPT_BODY
152             && e >= ICAP_REQ_HDR ? CI_EncapsEntities[e] : unknownentity);
153 }
154 #endif
155 
ci_headers_create()156 ci_headers_list_t *ci_headers_create()
157 {
158     ci_headers_list_t *h;
159     h = malloc(sizeof(ci_headers_list_t));
160     if (!h) {
161         ci_debug_printf(1, "Error allocation memory for ci_headers_list_t (header.c: ci_headers_create)\n");
162         return NULL;
163     }
164     h->headers = NULL;
165     h->buf = NULL;
166     if (!(h->headers = malloc(HEADERSTARTSIZE * sizeof(char *)))
167             || !(h->buf = malloc(HEADSBUFSIZE * sizeof(char)))) {
168         ci_debug_printf(1, "Server Error: Error allocation memory \n");
169         if (h->headers)
170             free(h->headers);
171         if (h->buf)
172             free(h->buf);
173         free(h);
174         return NULL;
175     }
176 
177     h->size = HEADERSTARTSIZE;
178     h->used = 0;
179     h->bufsize = HEADSBUFSIZE;
180     h->bufused = 0;
181     h->packed = 0;
182 
183     return h;
184 }
185 
ci_headers_destroy(ci_headers_list_t * h)186 void ci_headers_destroy(ci_headers_list_t * h)
187 {
188     free(h->headers);
189     free(h->buf);
190     free(h);
191 }
192 
193 
194 
ci_headers_setsize(ci_headers_list_t * h,int size)195 int ci_headers_setsize(ci_headers_list_t * h, int size)
196 {
197     char *newbuf;
198     int new_size;
199     if (size < h->bufsize)
200         return 1;
201     /*Allocate buffer of size multiple of HEADSBUFSIZE */
202     new_size = (size / HEADSBUFSIZE + 1) * HEADSBUFSIZE;
203     newbuf = realloc(h->buf, new_size * sizeof(char));
204     if (!newbuf) {
205         ci_debug_printf(1, "Server Error:Error allocation memory \n");
206         return 0;
207     }
208     h->buf = newbuf;
209     h->bufsize = new_size;
210     return 1;
211 }
212 
ci_headers_reset(ci_headers_list_t * h)213 void ci_headers_reset(ci_headers_list_t * h)
214 {
215     h->packed = 0;
216     h->used = 0;
217     h->bufused = 0;
218 }
219 
ci_headers_add(ci_headers_list_t * h,const char * line)220 const char *ci_headers_add(ci_headers_list_t * h, const char *line)
221 {
222     char *newhead, **newspace, *newbuf;
223     int len, linelen;
224     int i = 0;
225 
226     if (h->packed) { /*Not in edit mode*/
227         return NULL;
228     }
229 
230     if (h->used == h->size) {
231         len = h->size + HEADERSTARTSIZE;
232         newspace = realloc(h->headers, len * sizeof(char *));
233         if (!newspace) {
234             ci_debug_printf(1, "Server Error:Error allocation memory \n");
235             return NULL;
236         }
237         h->headers = newspace;
238         h->size = len;
239     }
240     linelen = strlen(line);
241     len = h->bufsize;
242     while ( len - h->bufused < linelen + 4 )
243         len += HEADSBUFSIZE;
244     if (len > h->bufsize) {
245         newbuf = realloc(h->buf, len * sizeof(char));
246         if (!newbuf) {
247             ci_debug_printf(1, "Server Error:Error allocation memory \n");
248             return NULL;
249         }
250         h->buf = newbuf;
251         h->bufsize = len;
252         h->headers[0] = h->buf;
253         for (i = 1; i < h->used; i++)
254             h->headers[i] = h->headers[i - 1] + strlen(h->headers[i - 1]) + 2;
255     }
256     newhead = h->buf + h->bufused;
257     memcpy(newhead, line, linelen);
258     newhead[linelen] = '\0';
259     h->bufused += linelen + 2; //2 char size for \r\n at the end of each header
260     *(newhead + linelen + 1) = '\n';
261     *(newhead + linelen + 3) = '\n';
262     if (newhead)
263         h->headers[h->used++] = newhead;
264 
265     return newhead;
266 }
267 
268 
ci_headers_addheaders(ci_headers_list_t * h,const ci_headers_list_t * headers)269 int ci_headers_addheaders(ci_headers_list_t * h, const ci_headers_list_t * headers)
270 {
271     int len, i;
272     char *newbuf, **newspace;
273 
274     if (h->packed) { /*Not in edit mode*/
275         return 0;
276     }
277     len = h->size;
278     while ( len - h->used < headers->used )
279         len += HEADERSTARTSIZE;
280 
281     if ( len > h->size ) {
282         newspace = realloc(h->headers, len * sizeof(char *));
283         if (!newspace) {
284             ci_debug_printf(1, "Server Error: Error allocating memory \n");
285             return 0;
286         }
287         h->headers = newspace;
288         h->size = len;
289     }
290 
291     len = h->bufsize;
292     while (len - h->bufused < headers->bufused + 2)
293         len += HEADSBUFSIZE;
294     if (len > h->bufsize) {
295         newbuf = realloc(h->buf, len * sizeof(char));
296         if (!newbuf) {
297             ci_debug_printf(1, "Server Error: Error allocating memory \n");
298             return 0;
299         }
300         h->buf = newbuf;
301         h->bufsize = len;
302     }
303 
304     memcpy(h->buf + h->bufused, headers->buf, headers->bufused + 2);
305 
306     h->bufused += headers->bufused;
307     h->used += headers->used;
308 
309     h->headers[0] = h->buf;
310     for (i = 1; i < h->used; i++)
311         h->headers[i] = h->headers[i - 1] + strlen(h->headers[i - 1]) + 2;
312     return 1;
313 }
314 
ci_headers_first_line2(ci_headers_list_t * h,size_t * return_size)315 const char *ci_headers_first_line2(ci_headers_list_t *h, size_t *return_size)
316 {
317     const char *eol;
318     if (h->used == 0)
319         return NULL;
320 
321     eol = h->used > 1 ? (h->headers[1] - 1)  : (h->buf + h->bufused);
322     while ((eol > h->buf) && (*eol == '\0' || *eol == '\r' || *eol == '\n')) --eol;
323     *return_size = eol - h->buf + 1;
324 
325     return h->buf;
326 }
327 
ci_headers_first_line(ci_headers_list_t * h)328 const char *ci_headers_first_line(ci_headers_list_t *h)
329 {
330     if (h->used == 0)
331         return NULL;
332     return h->buf;
333 }
334 
do_header_search(ci_headers_list_t * h,const char * header,const char ** value,const char ** end)335 static const char *do_header_search(ci_headers_list_t * h, const char *header, const char **value, const char **end)
336 {
337     int i;
338     size_t header_size = strlen(header);
339     const char *h_end = (h->buf + h->bufused);
340     const char *check_head, *lval;
341 
342     if (!header_size)
343         return NULL;
344 
345     for (i = 0; i < h->used; i++) {
346         check_head = h->headers[i];
347         if (h_end < check_head + header_size)
348             return NULL;
349         if (*(check_head + header_size) != ':')
350             continue;
351         if (strncasecmp(check_head, header, header_size) == 0) {
352             lval = check_head + header_size + 1;
353             if (value) {
354                 while (lval <= h_end && (*lval == ' ' || *lval == '\t'))
355                     ++(lval);
356                 *value = lval;
357             }
358             if (end) {
359                 *end = (i < h->used -1) ? (h->headers[i + 1] - 1) : (h->buf + h->bufused - 1);
360                 if (*end < lval) /*parse error in headers ?*/
361                     return NULL;
362                 while ((*end > lval) && (**end == '\0' || **end == '\r' || **end == '\n')) --(*end);
363             }
364             return check_head;
365         }
366     }
367     return NULL;
368 }
369 
ci_headers_search(ci_headers_list_t * h,const char * header)370 const char *ci_headers_search(ci_headers_list_t * h, const char *header)
371 {
372     return do_header_search(h, header, NULL, NULL);
373 }
374 
ci_headers_search2(ci_headers_list_t * h,const char * header,size_t * return_size)375 const char *ci_headers_search2(ci_headers_list_t * h, const char *header, size_t *return_size)
376 {
377     const char *phead, *pend = NULL;
378     if ((phead = do_header_search(h, header, NULL, &pend))) {
379         *return_size = (pend != NULL) ? (pend - phead + 1) : 0;
380         return phead;
381     }
382     *return_size = 0;
383     return NULL;
384 }
385 
ci_headers_value(ci_headers_list_t * h,const char * header)386 const char *ci_headers_value(ci_headers_list_t * h, const char *header)
387 {
388     const char *pval, *phead;
389     pval = NULL;
390     if ((phead = do_header_search(h, header, &pval, NULL)))
391         return pval;
392     return NULL;
393 }
394 
ci_headers_value2(ci_headers_list_t * h,const char * header,size_t * return_size)395 const char *ci_headers_value2(ci_headers_list_t * h, const char *header, size_t *return_size)
396 {
397     const char *pval, *phead, *pend = NULL;
398     pval = NULL;
399     if ((phead = do_header_search(h, header, &pval, &pend))) {
400         *return_size = (pend != NULL) ? (pend - pval + 1) : 0;
401         return pval;
402     }
403     return NULL;
404 }
405 
ci_headers_copy_value(ci_headers_list_t * h,const char * header,char * buf,size_t len)406 const char *ci_headers_copy_value(ci_headers_list_t * h, const char *header, char *buf, size_t len)
407 {
408     const char *phead = NULL, *pval = NULL, *pend = NULL;
409     char *dest, *dest_end;
410     phead = do_header_search(h, header, &pval, &pend);
411     if (phead == NULL || pval == NULL || pend == NULL)
412         return NULL;
413 
414     /*skip spaces at the beginning*/
415     while (isspace(*pval) && pval < pend)
416         pval++;
417     while (isspace(*pend) && pend > pval)
418         pend--;
419 
420     /*copy value to buf*/
421     dest = buf;
422     dest_end = buf + len -1;
423     for (; dest < dest_end && pval <= pend; dest++, pval++)
424         *dest = *pval;
425     *dest = '\0';
426     return buf;
427 }
428 
ci_headers_remove(ci_headers_list_t * h,const char * header)429 int ci_headers_remove(ci_headers_list_t * h, const char *header)
430 {
431     const char *h_end;
432     char *phead;
433     int i, j, cur_head_size, rest_len;
434     size_t header_size;
435 
436     if (h->packed) { /*Not in edit mode*/
437         return 0;
438     }
439 
440     h_end = (h->buf + h->bufused);
441     header_size = strlen(header);
442     for (i = 0; i < h->used; i++) {
443         phead = h->headers[i];
444         if (h_end < phead + header_size)
445             return 0;
446         if (*(phead + header_size) != ':')
447             continue;
448         if (strncasecmp(phead, header, header_size) == 0) {
449             /*remove it........ */
450             if (i == h->used - 1) {
451                 phead = h->headers[i];
452                 *phead = '\r';
453                 *(phead + 1) = '\n';
454                 h->bufused = (phead - h->buf);
455                 (h->used)--;
456                 return 1;
457             } else {
458                 cur_head_size = h->headers[i + 1] - h->headers[i];
459                 rest_len =
460                     h->bufused - (h->headers[i] - h->buf) - cur_head_size;
461                 ci_debug_printf(5, "remove_header : remain len %d\n",
462                                 rest_len);
463                 memmove(phead, h->headers[i + 1], rest_len);
464                 /*reconstruct index..... */
465                 h->bufused -= cur_head_size;
466                 (h->used)--;
467                 for (j = i + 1; j < h->used; j++) {
468                     cur_head_size = strlen(h->headers[j - 1]);
469                     h->headers[j] = h->headers[j - 1] + cur_head_size + 1;
470                     if (h->headers[j][0] == '\n')
471                         (h->headers[j])++;
472                 }
473 
474                 return 1;
475             }
476         }
477     }
478     return 0;
479 }
480 
ci_headers_replace(ci_headers_list_t * h,const char * header,const char * newval)481 const char *ci_headers_replace(ci_headers_list_t * h, const char *header, const char *newval)
482 {
483     if (h->packed) /*Not in edit mode*/
484         return NULL;
485 
486     return NULL;
487 }
488 
489 #define eoh(s) ((*s == '\r' && *(s+1) == '\n' && *(s+2) != '\t' && *(s+2) != ' ') || (*s == '\n' && *(s+1) != '\t' && *(s+1) != ' '))
490 
ci_headers_iterate(ci_headers_list_t * h,void * data,void (* fn)(void *,const char * head,const char * value))491 int ci_headers_iterate(ci_headers_list_t * h, void *data, void (*fn)(void *, const char  *head, const char  *value))
492 {
493     char header[256];
494     char value[8196];
495     char *s;
496     int i, j;
497     for (i = 0; i < h->used; i++) {
498         s = h->headers[i];
499         for (j = 0;  j < sizeof(header)-1 && *s != ':' && *s != ' ' &&  *s != '\0' && *s != '\r' && *s != '\n'; s++, j++)
500             header[j] = *s;
501         header[j] = '\0';
502         if (*s == ':') {
503             s++;
504         } else {
505             header[0] = '\0';
506             s = h->headers[i];
507         }
508         while (*s == ' ') s++;
509         for (j = 0;  j < sizeof(value)-1 &&  *s != '\0' && !eoh(s); s++, j++)
510             value[j] = *s;
511         value[j] = '\0';
512         fn(data, header, value);
513     }
514     return 1;
515 }
516 
ci_headers_pack(ci_headers_list_t * h)517 void ci_headers_pack(ci_headers_list_t * h)
518 {
519     /*Put the \r\n sequence at the end of each header before sending...... */
520     int i = 0, len = 0;
521     for (i = 0; i < h->used; i++) {
522         len = strlen(h->headers[i]);
523         if (h->headers[i][len + 1] == '\n') {
524             h->headers[i][len] = '\r';
525             /*         h->headers[i][len+1] = '\n';*/
526         } else {              /*   handle the case that headers seperated with a '\n' only */
527             h->headers[i][len] = '\n';
528         }
529     }
530 
531     if (h->buf[h->bufused + 1] == '\n') {
532         h->buf[h->bufused] = '\r';
533         /*    h->buf[h->bufused+1] = '\n';*/
534         h->bufused += 2;
535     } else {                   /*   handle the case that headers seperated with a '\n' only */
536         h->buf[h->bufused] = '\n';
537         h->bufused++;
538     }
539     h->packed = 1;
540 }
541 
542 
ci_headers_unpack(ci_headers_list_t * h)543 int ci_headers_unpack(ci_headers_list_t * h)
544 {
545     int len, eoh;
546     char **newspace;
547     char *ebuf, *str;
548 
549     if (h->bufused < 2)        /*???????????? */
550         return EC_400;
551 
552     ebuf = h->buf + h->bufused - 2;
553     /* ebuf now must indicate the last \r\n so: */
554     if (*ebuf != '\r' && *ebuf != '\n') {      /*Some sites return (this is bug ) a simple '\n' as end of header ..... */
555         ci_debug_printf(3,
556                         "Parse error. The end chars are %c %c (%d %d) not the \\r \n",
557                         *ebuf, *(ebuf + 1), (unsigned int) *ebuf,
558                         (unsigned int) *(ebuf + 1));
559         return EC_400;        /*Bad request .... */
560     }
561     *ebuf = '\0';
562 
563     h->headers[0] = h->buf;
564     h->used = 1;
565 
566     for (str = h->buf; str < ebuf; str++) {    /*Construct index of headers */
567         eoh = 0;
568 
569         if ((*str == '\r' && *(str + 1) == '\n')) {
570             if ((str + 2) >= ebuf
571                     || (*(str + 2) != '\t' && *(str + 2) != ' '))
572                 eoh = 1;
573         } else if (*str == '\n' && *(str + 1) != '\t' && *(str + 1) != ' ') {
574             /*handle the case that headers seperated with a '\n' only */
575             eoh = 1;
576         } else if (*str == '\0')      /*Then we have a problem. This char is important for us. Yes can happen! */
577             *str = ' ';
578 
579         if (eoh) {
580             *str = '\0';
581             if (h->size <= h->used) {        /*  Resize the headers index space ........ */
582                 len = h->size + HEADERSTARTSIZE;
583                 newspace = realloc(h->headers, len * sizeof(char *));
584                 if (!newspace) {
585                     ci_debug_printf(1,
586                                     "Server Error: Error allocating memory \n");
587                     return EC_500;
588                 }
589                 h->headers = newspace;
590                 h->size = len;
591             }
592             str++;
593             if (*str == '\n')
594                 str++;      /*   handle the case that headers seperated with a '\n' only */
595             h->headers[h->used] = str;
596             h->used++;
597         }
598     }
599     h->packed = 0;
600     /*OK headers index construction ...... */
601     return EC_100;
602 }
603 
ci_headers_pack_to_buffer(ci_headers_list_t * heads,char * buf,size_t size)604 size_t ci_headers_pack_to_buffer(ci_headers_list_t *heads, char *buf, size_t size)
605 {
606     size_t n;
607     int i;
608     char *pos;
609 
610     n = heads->bufused;
611     if (!heads->packed)
612         n += 2;
613 
614     if (n > size)
615         return 0;
616 
617     memcpy(buf, heads->buf, heads->bufused);
618 
619     if (!heads->packed) {
620         pos = buf;
621         for (i = 0; i < heads->used; ++i) {
622             pos = strchr(pos, '\0');
623             if (pos[1] == '\n')
624                 pos[0] = '\r';
625             else
626                 pos[0] = '\n';
627         }
628         buf[heads->bufused] = '\r';
629         buf[heads->bufused+1] = '\n';
630     }
631     return n;
632 }
633 
634 /********************************************************************************************/
635 /*             Entities List                                                                */
636 
637 
mk_encaps_entity(int type,int val)638 ci_encaps_entity_t *mk_encaps_entity(int type, int val)
639 {
640     ci_encaps_entity_t *h;
641     h = malloc(sizeof(ci_encaps_entity_t));
642     if (!h)
643         return NULL;
644 
645     h->start = val;
646     h->type = type;
647     if (type == ICAP_REQ_HDR || type == ICAP_RES_HDR)
648         h->entity = ci_headers_create();
649     else
650         h->entity = NULL;
651     return h;
652 }
653 
destroy_encaps_entity(ci_encaps_entity_t * e)654 void destroy_encaps_entity(ci_encaps_entity_t * e)
655 {
656     if (e->type == ICAP_REQ_HDR || e->type == ICAP_RES_HDR) {
657         ci_headers_destroy((ci_headers_list_t *) e->entity);
658     } else
659         free(e->entity);
660     free(e);
661 }
662 
get_encaps_type(const char * buf,int * val,char ** endpoint)663 int get_encaps_type(const char *buf, int *val, char **endpoint)
664 {
665 
666     if (0 == strncmp(buf, "req-hdr", 7)) {
667         *val = strtol(buf + 8, endpoint, 10);
668         return ICAP_REQ_HDR;
669     }
670     if (0 == strncmp(buf, "res-hdr", 7)) {
671         *val = strtol(buf + 8, endpoint, 10);
672         return ICAP_RES_HDR;
673     }
674     if (0 == strncmp(buf, "req-body", 8)) {
675         *val = strtol(buf + 9, endpoint, 10);
676         return ICAP_REQ_BODY;
677     }
678     if (0 == strncmp(buf, "res-body", 8)) {
679         *val = strtol(buf + 9, endpoint, 10);
680         return ICAP_RES_BODY;
681     }
682     if (0 == strncmp(buf, "null-body", 9)) {
683         *val = strtol(buf + 10, endpoint, 10);
684         return ICAP_NULL_BODY;
685     }
686     return -1;
687 }
688 
689 
sizeofheader(ci_headers_list_t * h)690 int sizeofheader(ci_headers_list_t * h)
691 {
692     /*
693       int size=0,i;
694       for(i=0;i<h->used;i++){
695         size+=strlen(h->headers[i])+2;
696       }
697       size+=2;
698       return size;
699     */
700     return h->bufused + 2;
701 }
702 
sizeofencaps(ci_encaps_entity_t * e)703 int sizeofencaps(ci_encaps_entity_t * e)
704 {
705     if (e->type == ICAP_REQ_HDR || e->type == ICAP_RES_HDR) {
706         return sizeofheader((ci_headers_list_t *) e->entity);
707     }
708     return 0;
709 }
710