static ret_t do_download__has_headers (cherokee_downloader_t *downloader, void *param) { cherokee_url_t *url; cherokee_buffer_t *req; cherokee_header_t *hdr; UNUSED(param); url = &downloader->request.url; req = &url->request; hdr = downloader->header; TRACE(ENTRIES, "quiet=%d http_code=%d\n", quiet, hdr->response); /* Check the response */ if (quiet == false) { cherokee_buffer_t tmp = CHEROKEE_BUF_INIT; cherokee_http_code_copy (HDR_RESPONSE(hdr), &tmp); print_tuple_str ("Response", tmp.buf); cherokee_buffer_mrproper (&tmp); } /* Open a new file if needed */ if (global_fd == UNSET_FD) { char *name; name = strrchr (req->buf, '/'); if (name == NULL) { name = "index.html"; } output_fd = open (name, O_WRONLY, O_CREAT); if (output_fd < 0) { return ret_error; } } else { output_fd = global_fd; } /* Save the headers? */ if (save_headers == true) { ssize_t written; uint32_t len; cherokee_header_get_length (hdr, &len); written = write (output_fd, hdr->input_buffer->buf, len); if (written < 0) { PRINT_MSG_S ("ERROR: Can not write to output file\n"); return ret_error; } } return ret_ok; }
static ret_t remove_surplus (cherokee_post_t *post, cherokee_connection_t *conn) { ret_t ret; cuint_t header_len; cint_t surplus_len; /* Get the HTTP request length */ ret = cherokee_header_get_length (&conn->header, &header_len); if (unlikely(ret != ret_ok)) { return ret; } /* Get the POST length */ if (post->len > 0) { /* Plain post: read what's pointed by Content-Length */ surplus_len = MIN (conn->incoming_header.len - header_len, post->len); } else { /* Chunked: Assume everything after the header is POST */ surplus_len = conn->incoming_header.len - header_len; } if (surplus_len <= 0) { return ret_ok; } TRACE (ENTRIES, "POST surplus: moving %d bytes\n", surplus_len); /* Move the surplus */ cherokee_buffer_add (&post->header_surplus, conn->incoming_header.buf + header_len, surplus_len); cherokee_buffer_remove_chunk (&conn->incoming_header, header_len, surplus_len); TRACE (ENTRIES, "POST surplus: incoming_header is %d bytes (header len=%d)\n", conn->incoming_header.len, header_len); return ret_ok; }
static ret_t downloader_header_read (cherokee_downloader_t *downloader, cherokee_buffer_t *tmp1, cherokee_buffer_t *tmp2) { ret_t ret; cuint_t len; size_t read_ = 0; cherokee_socket_t *sock = &downloader->socket; cherokee_http_t error_code = http_bad_request; UNUSED(tmp2); ret = cherokee_socket_bufread (sock, &downloader->reply_header, DEFAULT_RECV_SIZE, &read_); switch (ret) { case ret_eof: return ret_eof; case ret_eagain: return ret_eagain; case ret_ok: /* Count */ downloader->info.headers_recv += read_; /* Check the header. Is it complete? */ ret = cherokee_header_has_header (downloader->header, &downloader->reply_header, 0); switch (ret) { case ret_ok: break; case ret_not_found: /* It needs to read more headers ... */ return ret_eagain; default: /* Too many initial CRLF */ return ret_error; } /* Parse the header */ ret = cherokee_header_parse (downloader->header, &downloader->reply_header, &error_code); if (unlikely (ret != ret_ok)) return ret_error; /* Look for the length, it will need to drop out the header from the buffer */ cherokee_header_get_length (downloader->header, &len); /* Maybe it has some body */ if (downloader->reply_header.len > len) { uint32_t body_chunk; /* Skip the CRLF separator and copy the body */ len += 2; body_chunk = downloader->reply_header.len - len; downloader->info.body_recv += body_chunk; cherokee_buffer_add (&downloader->body, downloader->reply_header.buf + len, body_chunk); cherokee_buffer_drop_ending (&downloader->reply_header, body_chunk); } /* Try to read the "Content-Length" response header */ ret = cherokee_header_has_known (downloader->header, header_content_length); if (ret == ret_ok) { cherokee_buffer_clean (tmp1); ret = cherokee_header_copy_known (downloader->header, header_content_length, tmp1); if (ret == ret_ok) { ret = cherokee_atou (tmp1->buf, &downloader->content_length); #ifdef TRACE_ENABLED if (ret == ret_ok) { TRACE (ENTRIES, "Known length: %d bytes\n", downloader->content_length); } else { TRACE (ENTRIES, "Could not parse Content-Length\n"); } #endif } } return ret_ok; case ret_error: /* Opsss.. something has failed */ return ret_error; default: RET_UNKNOWN (ret); return ret; } return ret_error; }