/* SPDX-License-Identifier: GPL-3.0-or-later */ /* Copyright 2022 Ivan Polyakov */ #include "response.h" #include #include #include static size_t calc_res_headers_sz(const rpd_res *res); void rpd_res_init(rpd_res *dest) { dest->status = rpd_res_st_ok; dest->location = dest->content_type = NULL; dest->body = NULL; rpd_keyval_init(&dest->cookie, 0); } int rpd_res_headers_str(char **dest, const rpd_res *src) { size_t size = calc_res_headers_sz(src); char *ptr; *dest = (char *) malloc(sizeof(char) * size); if (!*dest) { perror("malloc"); return 1; } ptr = *dest; if (src->content_type) { ptr += sprintf(ptr, "Content-Type: %s\r\n", src->content_type); } if (src->location) { ptr += sprintf(ptr, "Location: %s\r\n", src->location); } return 0; } int rpd_res_str(char **dest, const rpd_res *res) { size_t headers_size, size; char *ptr, *headers; size = headers_size = calc_res_headers_sz(res); if (res->body) size += 2 + strlen(res->body); *dest = (char *) malloc(sizeof(char) * size); if (!*dest) { perror("malloc"); return 1; } /* header */ ptr = *dest; ptr += sprintf(ptr, "Status: %d\r\n", res->status); if (rpd_res_headers_str(&headers, res)) { return 1; } memcpy(ptr, headers, headers_size); free(headers); ptr += headers_size; memcpy(ptr, "\r\n", 2); ptr += 2; /* body */ if (res->body) { int bodylen = strlen(res->body); memcpy(ptr, res->body, bodylen); ptr += bodylen; } return 0; } static size_t calc_res_headers_sz(const rpd_res *res) { size_t size = 0; size += strlen("Status: \r\n") + 3; if (res->location) { size += strlen("Location: \r\n") + strlen(res->location); } if (res->content_type) { size += strlen("Content-Type: \r\n") + strlen(res->content_type); } if (res->cookie.size) { size += strlen("Set-Cookie: \r\n") * res->cookie.size; for (int i = 0; i < res->cookie.size; i++) { rpd_keyval_item *item = res->cookie.items + i; size += strlen(item->key) + strlen(item->val); } } return size; } void rpd_res_cleanup(rpd_res *res) { res->status = rpd_res_st_ok; if (res->location) { free(res->location); res->location = NULL; } if (res->content_type) { free(res->content_type); res->content_type = NULL; } if (res->body) { free(res->body); res->body = NULL; } if (res->cookie.capacity) { rpd_keyval_cleanup(&res->cookie); } }