/** @return -2 if no data was read but the caller should retry; * -1 if an error occurred and *@a error was set; 0 at end of data; * a positive number if that many bytes were read. * * @relates http_post */ static int read_http_post_inline(struct http_post *http_post, unsigned char buffer[], int max, struct connection_state *error) { const unsigned char *post = http_post->post_data; const unsigned char *end = (const unsigned char *)strchr((char *)post, FILE_CHAR); int total = 0; assert(http_post->post_fd < 0); if_assert_failed { *error = connection_state(S_INTERNAL); return -1; } if (!end) end = (const unsigned char *)strchr((char *)post, '\0'); while (post < end && total < max) { int h1, h2; h1 = unhx(post[0]); assertm(h1 >= 0 && h1 < 16, "h1 in the POST buffer is %d (%d/%c)", h1, post[0], post[0]); if_assert_failed h1 = 0; h2 = unhx(post[1]); assertm(h2 >= 0 && h2 < 16, "h2 in the POST buffer is %d (%d/%c)", h2, post[1], post[1]); if_assert_failed h2 = 0; buffer[total++] = (h1<<4) + h2; post += 2; } if (post != end || *end != FILE_CHAR) { http_post->post_data = post; return total; } http_post->file_read = 0; end = (const unsigned char *)strchr((char *)(post + 1), FILE_CHAR); assert(end); http_post->post_fd = open((const char *)http_post->files[http_post->file_index].name, O_RDONLY); /* Be careful not to change errno here. */ if (http_post->post_fd < 0) { http_post->post_data = post; if (total > 0) return total; /* retry the open on the next call */ else { *error = connection_state_for_errno(errno); return -1; } } http_post->post_data = end + 1; return total ? total : -2; }
static void decode_q_segment(struct string *str, unsigned char *in, unsigned char *end) { int c; while ((c = *in++) != 0 && (in <= end)) { if (c == '=') { int d = *in++; if (d == '\n' || !d) break; /* drop trailing newline */ d = (unhx(d) << 4) | unhx(*in++); add_format_to_string(str, "&#%d;", d); continue; } if (c == '_') /* rfc2047 4.2 (2) */ c = 0x20; add_char_to_string(str, c); } }