static int cs_read_chunk(const char *buf, int i, int len) { /* inside chunked body .. */ while (1) { int chunk_len = 0; #if CHUNK_DEBUG if (i < len-2) { int j; printf ("\n<<<"); for (j = i; j <= i+3; j++) printf ("%c", buf[j]); printf (">>>\n"); } #endif /* read chunk length */ while (1) if (i >= len-2) { #if CHUNK_DEBUG printf ("returning incomplete read at 1\n"); printf ("i=%d len=%d\n", i, len); #endif return 0; } else if (yaz_isdigit(buf[i])) chunk_len = chunk_len * 16 + (buf[i++] - '0'); else if (yaz_isupper(buf[i])) chunk_len = chunk_len * 16 + (buf[i++] - ('A'-10)); else if (yaz_islower(buf[i])) chunk_len = chunk_len * 16 + (buf[i++] - ('a'-10)); else break; if (chunk_len == 0) break; if (chunk_len < 0) return i; while (1) { if (i >= len -1) return 0; if (skip_crlf(buf, len, &i)) break; i++; } /* got CRLF */ #if CHUNK_DEBUG printf ("chunk_len=%d\n", chunk_len); #endif i += chunk_len; if (i >= len-2) return 0; if (!skip_crlf(buf, len, &i)) return 0; } /* consider trailing headers .. */ while (i < len) { if (skip_crlf(buf, len, &i)) { if (skip_crlf(buf, len, &i)) return i; } else i++; } #if CHUNK_DEBUG printf ("returning incomplete read at 2\n"); printf ("i=%d len=%d\n", i, len); #endif return 0; }
static int decode_headers_content(ODR o, int off, Z_HTTP_Header **headers, char **content_buf, int *content_len) { int i = off; int chunked = 0; *headers = 0; while (i < o->size-1 && o->buf[i] == '\n') { int po; i++; if (o->buf[i] == '\r' && i < o->size-1 && o->buf[i+1] == '\n') { i++; break; } if (o->buf[i] == '\n') break; for (po = i; ; i++) { if (i == o->size) { o->error = OHTTP; return 0; } else if (o->buf[i] == ':') break; } *headers = (Z_HTTP_Header *) odr_malloc(o, sizeof(**headers)); (*headers)->name = (char*) odr_malloc(o, i - po + 1); memcpy ((*headers)->name, o->buf + po, i - po); (*headers)->name[i - po] = '\0'; i++; while (i < o->size-1 && o->buf[i] == ' ') i++; for (po = i; i < o->size-1 && !strchr("\r\n", o->buf[i]); i++) ; (*headers)->value = (char*) odr_malloc(o, i - po + 1); memcpy ((*headers)->value, o->buf + po, i - po); (*headers)->value[i - po] = '\0'; if (!strcasecmp((*headers)->name, "Transfer-Encoding") && !strcasecmp((*headers)->value, "chunked")) chunked = 1; headers = &(*headers)->next; if (i < o->size-1 && o->buf[i] == '\r') i++; } *headers = 0; if (o->buf[i] != '\n') { o->error = OHTTP; return 0; } i++; if (chunked) { int off = 0; /* we know buffer will be smaller than o->size - i*/ *content_buf = (char*) odr_malloc(o, o->size - i); while (1) { /* chunk length .. */ int chunk_len = 0; for (; i < o->size-2; i++) if (yaz_isdigit(o->buf[i])) chunk_len = chunk_len * 16 + (o->buf[i] - '0'); else if (yaz_isupper(o->buf[i])) chunk_len = chunk_len * 16 + (o->buf[i] - ('A'-10)); else if (yaz_islower(o->buf[i])) chunk_len = chunk_len * 16 + (o->buf[i] - ('a'-10)); else break; /* chunk extension ... */ while (o->buf[i] != '\r' && o->buf[i+1] != '\n') { if (i >= o->size-2) { o->error = OHTTP; return 0; } i++; } i += 2; /* skip CRLF */ if (chunk_len == 0) break; if (chunk_len < 0 || off + chunk_len > o->size) { o->error = OHTTP; return 0; } /* copy chunk .. */ memcpy (*content_buf + off, o->buf + i, chunk_len); i += chunk_len + 2; /* skip chunk+CRLF */ off += chunk_len; } if (!off) *content_buf = 0; *content_len = off; } else { if (i > o->size) { o->error = OHTTP; return 0; } else if (i == o->size) { *content_buf = 0; *content_len = 0; } else { *content_len = o->size - i; *content_buf = (char*) odr_malloc(o, *content_len + 1); memcpy(*content_buf, o->buf + i, *content_len); (*content_buf)[*content_len] = '\0'; } } return 1; }