static void http_req_free(struct http_req *req) { unsigned i; free(req->response); for (i = 0; i < req->num_headers; i++) free(req->headers[i]); free(req->headers); free(req->body); http_req_zero(req); }
static int http_query(krb5_storage *sp, const char *host, const char *page, char **headers, unsigned num_headers, struct http_req *req) { enum { RESPONSE, HEADER, BODY } state; ssize_t ret; char in_buf[1024]; size_t in_len = 0, content_length; unsigned i; http_req_zero(req); if (verbose_flag) { for (i = 0; i < num_headers; i++) printf("outheader[%d]: %s\n", i, headers[0]); } storage_printf(sp, "GET %s HTTP/1.1\r\n", page); for (i = 0; i < num_headers; i++) storage_printf(sp, "%s\r\n", headers[i]); storage_printf(sp, "Host: %s\r\n\r\n", host); state = RESPONSE; while (1) { char *p; ret = krb5_storage_read(sp, in_buf + in_len, 1); if (ret != 1) errx(1, "storage foo"); in_len += 1; in_buf[in_len] = '\0'; p = strstr(in_buf, "\r\n"); if (p == NULL) continue; if (p == in_buf) { memmove(in_buf, in_buf + 2, sizeof(in_buf) - 2); state = BODY; break; } else if (state == RESPONSE) { req->response = strndup(in_buf, p - in_buf); state = HEADER; } else { req->headers = realloc(req->headers, (req->num_headers + 1) * sizeof(req->headers[0])); req->headers[req->num_headers] = strndup(in_buf, p - in_buf); if (req->headers[req->num_headers] == NULL) errx(1, "strdup"); req->num_headers++; } in_len = 0; } if (state != BODY) abort(); const char *h = http_find_header(req, "Content-Length:"); if (h == NULL) errx(1, "Missing `Content-Length'"); content_length = atoi(h); req->body_size = content_length; req->body = erealloc(req->body, content_length + 1); ret = krb5_storage_read(sp, req->body, req->body_size); if (ret < 0 || (size_t)ret != req->body_size) errx(1, "failed to read body"); ((char *)req->body)[req->body_size] = '\0'; if (verbose_flag) { printf("response: %s\n", req->response); for (i = 0; i < req->num_headers; i++) printf("response-header[%d] %s\n", i, req->headers[i]); printf("body: %.*s\n", (int)req->body_size, (char *)req->body); } return 0; }
static int http_query(const char *host, const char *page, char **headers, int num_headers, struct http_req *req) { enum { RESPONSE, HEADER, BODY } state; ssize_t ret; char in_buf[1024], *in_ptr = in_buf; size_t in_len = 0; int s, i; http_req_zero(req); s = do_connect(host, port_str); if (s < 0) errx(1, "connection failed"); fdprintf(s, "GET %s HTTP/1.0\r\n", page); for (i = 0; i < num_headers; i++) fdprintf(s, "%s\r\n", headers[i]); fdprintf(s, "Host: %s\r\n\r\n", host); state = RESPONSE; while (1) { ret = read (s, in_ptr, sizeof(in_buf) - in_len - 1); if (ret == 0) break; else if (ret < 0) err (1, "read: %lu", (unsigned long)ret); in_buf[ret + in_len] = '\0'; if (state == HEADER || state == RESPONSE) { char *p; in_len += ret; in_ptr += ret; while (1) { p = strstr(in_buf, "\r\n"); if (p == NULL) { break; } else if (p == in_buf) { memmove(in_buf, in_buf + 2, sizeof(in_buf) - 2); state = BODY; in_len -= 2; in_ptr -= 2; break; } else if (state == RESPONSE) { req->response = emalloc(p - in_buf + 1); memcpy(req->response, in_buf, p - in_buf); req->response[p - in_buf] = '\0'; state = HEADER; } else { req->headers = realloc(req->headers, (req->num_headers + 1) * sizeof(req->headers[0])); req->headers[req->num_headers] = emalloc(p - in_buf + 1); memcpy(req->headers[req->num_headers], in_buf, p - in_buf); req->headers[req->num_headers][p - in_buf] = '\0'; if (req->headers[req->num_headers] == NULL) errx(1, "strdup"); req->num_headers++; } memmove(in_buf, p + 2, sizeof(in_buf) - (p - in_buf) - 2); in_len -= (p - in_buf) + 2; in_ptr -= (p - in_buf) + 2; } } if (state == BODY) { req->body = erealloc(req->body, req->body_size + ret + 1); memcpy((char *)req->body + req->body_size, in_buf, ret); req->body_size += ret; ((char *)req->body)[req->body_size] = '\0'; in_ptr = in_buf; in_len = 0; } else abort(); } if (verbose_flag) { int i; printf("response: %s\n", req->response); for (i = 0; i < req->num_headers; i++) printf("header[%d] %s\n", i, req->headers[i]); printf("body: %.*s\n", (int)req->body_size, (char *)req->body); } close(s); return 0; }