summaryrefslogtreecommitdiff
path: root/main/http.c
diff options
context:
space:
mode:
Diffstat (limited to 'main/http.c')
-rw-r--r--main/http.c103
1 files changed, 90 insertions, 13 deletions
diff --git a/main/http.c b/main/http.c
index a9c8a3564..0c9b09a90 100644
--- a/main/http.c
+++ b/main/http.c
@@ -65,6 +65,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/_private.h"
#include "asterisk/astobj2.h"
#include "asterisk/netsock2.h"
+#include "asterisk/json.h"
#define MAX_PREFIX 80
#define DEFAULT_PORT 8088
@@ -607,6 +608,91 @@ void ast_http_uri_unlink_all_with_key(const char *key)
#define MAX_POST_CONTENT 1025
+static const char *get_content_type(struct ast_variable *headers)
+{
+ struct ast_variable *v;
+
+ for (v = headers; v; v = v->next) {
+ if (strcasecmp(v->name, "Content-Type") == 0) {
+ return v->value;
+ }
+ }
+
+ /* Missing content type; assume empty string */
+ return "";
+}
+
+static int get_content_length(struct ast_variable *headers)
+{
+ struct ast_variable *v;
+
+ for (v = headers; v; v = v->next) {
+ if (!strcasecmp(v->name, "Content-Length")) {
+ return atoi(v->value);
+ }
+ }
+
+ /* Missing content length; assume zero */
+ return 0;
+}
+
+struct ast_json *ast_http_get_json(
+ struct ast_tcptls_session_instance *ser, struct ast_variable *headers)
+{
+ int content_length = 0;
+ int res;
+ struct ast_json *body;
+ RAII_VAR(char *, buf, NULL, ast_free);
+
+ /* Use errno to distinguish errors from no body */
+ errno = 0;
+
+ if (strcasecmp(get_content_type(headers), "application/json") != 0) {
+ /* Content type is not JSON */
+ return NULL;
+ }
+
+ content_length = get_content_length(headers);
+
+ if (content_length <= 0) {
+ /* No content (or streaming content). */
+ return NULL;
+ }
+
+ if (content_length > MAX_POST_CONTENT - 1) {
+ ast_log(LOG_WARNING,
+ "Excessively long HTTP content. (%d > %d)\n",
+ content_length, MAX_POST_CONTENT);
+ errno = EFBIG;
+ return NULL;
+ }
+
+ buf = ast_malloc(content_length);
+ if (!buf) {
+ /* Malloc sets ENOMEM */
+ return NULL;
+ }
+
+ res = fread(buf, 1, content_length, ser->f);
+ if (res < content_length) {
+ /* Error, distinguishable by ferror() or feof(), but neither
+ * is good. Treat either one as I/O error */
+ ast_log(LOG_WARNING, "Short HTTP request body (%d < %d)\n",
+ res, content_length);
+ errno = EIO;
+ return NULL;
+ }
+
+ body = ast_json_load_buf(buf, content_length, NULL);
+ if (body == NULL) {
+ /* Failed to parse JSON; treat as an I/O error */
+ errno = EIO;
+ return NULL;
+ }
+
+ return body;
+}
+
/*
* get post variables from client Request Entity-Body, if content type is
* application/x-www-form-urlencoded
@@ -623,21 +709,12 @@ struct ast_variable *ast_http_get_post_vars(
/* Use errno to distinguish errors from no params */
errno = 0;
- for (v = headers; v; v = v->next) {
- if (!strcasecmp(v->name, "Content-Type")) {
- if (strcasecmp(v->value, "application/x-www-form-urlencoded")) {
- return NULL;
- }
- break;
- }
+ if (strcasecmp(get_content_type(headers), "application/x-www-form-urlencoded") != 0) {
+ /* Content type is not form data */
+ return NULL;
}
- for (v = headers; v; v = v->next) {
- if (!strcasecmp(v->name, "Content-Length")) {
- content_length = atoi(v->value);
- break;
- }
- }
+ content_length = get_content_length(headers);
if (content_length <= 0) {
return NULL;