simplehttplib/httputil.c

178 lines
4.6 KiB
C

#include <string.h>
#include <stdlib.h>
#include "httplib.h"
#include "httplib_internal.h"
#include <stdio.h>
http_header * httplib_header_new(char * key, char * value) {
http_header * header = malloc(sizeof(http_header));
header->next = 0;
header->key = malloc(strlen(key)+1);
header->value = malloc(strlen(value)+1);
strcpy(header->key, key);
strcpy(header->value, value);
return header;
}
http_request * httplib_request_new() {
http_request * req = malloc(sizeof(http_request));
req->method = GET;
req->headers = 0;
req->path = 0;
req->query = 0;
req->content_length = 0;
req->body = 0;
return req;
}
http_response * httplib_response_new() {
http_response * res = malloc(sizeof(http_request));
res->status_message = 0;
res->headers = 0;
res->body = 0;
res->content_length = 0;
res->status_code = 100;
return res;
}
int httplib_response_add_header(http_response * self, char * key, char * value) {
if (!httplib_is_valid_header(key, value)) return -1;
if (self->headers == 0) {
self->headers = httplib_header_new(key, value);
} else {
http_header * run = self->headers;
while (run) {
if (run->next == 0) {
run->next = httplib_header_new(key, value);
break;
}
run = run->next;
}
}
return 0;
}
char * httplib_request_get_header(http_request * self, char * key) {
http_header * run = self->headers;
while (run) {
if (!strcasecmp(key, run->key)) {
char * value = malloc(strlen(run->value)+1);
strcpy(value, run->value);
return value;
}
run = run->next;
}
return NULL;
}
int httplib_is_valid_header(const char * key, const char * value) {
for (int i = 0; key[i] != '\0'; i++) {
char c = key[i];
if ((c < 'A' && c != '-') || (c > 'Z' && c < 'a' && c != '_') || c > 'z') {
return 0;
}
}
for (int i = 0; value[i] != '\0'; i++) {
char c = value[i];
if (c < ' ' || c > '~') {
return 0;
}
}
return 1;
}
void httplib_request_free(http_request * self) {
if (self->headers != 0) {
httplib_headers_free(self->headers);
}
if (self->query != 0) free(self->query);
if (self->body != 0) free(self->body);
if (self->path != 0) free(self->path);
free(self);
}
void httplib_response_free(http_response * self) {
if (self->headers != 0) {
httplib_headers_free(self->headers);
}
if (self->status_message != 0) free(self->status_message);
if (self->body != 0) free(self->body);
free(self);
}
void httplib_headers_free(http_header * self) {
http_header * run = self;
while (run) {
http_header * to_free = run;
run = run->next;
if (to_free->key != 0) free(to_free->key);
if (to_free->value != 0) free(to_free->value);
free(to_free);
}
}
char * httplib_request_get_query_value(http_request * self, char * key) {
if (self->query == 0) return NULL;
char * tmp = malloc(strlen(self->query)+1);
int pos = 0;
int value_start = -1;
for (int i = 0; self->query[i] != '\0'; i++) {
if (self->query[i] == '=') {
tmp[pos] = '\0';
if (!strcmp(key, tmp)) {
value_start = i+1;
}
pos = 0;
} else if (self->query[i] == '&') {
if (value_start > 0) {
break;
} else {
pos = 0;
}
} else {
tmp[pos] = self->query[i];
pos++;
}
}
tmp[pos] = '\0';
if (value_start > 0) {
char * value = malloc(strlen(tmp)+1);
strcpy(value, tmp);
free(tmp);
return value;
}
free(tmp);
return NULL;
}
void httplib_response_set_content_length(http_response * self, size_t length) {
self->content_length = length;
if (length > 0)
self->body = realloc(self->body, length);
}
void httplib_response_set_status(http_response * self, int code, char * message) {
self->status_code = code;
self->status_message = realloc(self->status_message, strlen(message)+1);
strcpy(self->status_message, message);
}
void httplib_tmp_increase(struct tmp * tmp) {
tmp->size += 1024;
tmp->buf = realloc(tmp->buf, tmp->size);
bzero(tmp->buf + tmp->pos, 1024);
}
void httplib_tmp_reset(struct tmp * tmp) {
tmp->pos = 0;
bzero(tmp->buf, tmp->size);
}
char httplib_decode_hex(const char * encoded) {
char input[3];
input[0] = encoded[0];
input[1] = encoded[1];
input[2] = '\0';
return (char) strtoul(input, 0, 16);
}