diff --git a/include/libwebsockets/lws-spa.h b/include/libwebsockets/lws-spa.h index c5ddab2c7..1045dc4a5 100644 --- a/include/libwebsockets/lws-spa.h +++ b/include/libwebsockets/lws-spa.h @@ -102,7 +102,8 @@ lws_spa_create(struct lws *wsi, const char * const *param_names, void *opt_data); typedef struct lws_spa_create_info { - const char * const *param_names; /* array of form parameter names, like "username" */ + const char * const *param_names; /**< array of form parameter names, like "username" + These may be NULL, to make space for arbitrary POST items */ int count_params; /* count of param_names */ int max_storage; /* total amount of form parameter values we can store */ lws_spa_fileupload_cb opt_cb; /* NULL, or callback to receive file upload data. */ diff --git a/lib/roles/http/server/lws-spa.c b/lib/roles/http/server/lws-spa.c index a39c66138..990c360c1 100644 --- a/lib/roles/http/server/lws-spa.c +++ b/lib/roles/http/server/lws-spa.c @@ -1,7 +1,7 @@ /* * libwebsockets - small server side websockets and web server implementation * - * Copyright (C) 2010 - 2019 Andy Green + * Copyright (C) 2010 - 2021 Andy Green * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -482,7 +482,23 @@ lws_urldecode_spa_lookup(struct lws_spa *spa, const char *name) int n; for (n = 0; n < spa->i.count_params; n++) { - if (!strcmp(*pp, name)) + if (!*pp && !spa->i.param_names_stride && spa->i.ac) { + unsigned int len = (unsigned int)strlen(name); + char **ptr = (char**)spa->i.param_names; + + /* Use NULLs at end of list to dynamically create + * unknown entries */ + + ptr[n] = lwsac_use(spa->i.ac, len + 1, spa->i.ac_chunk_size); + if (!ptr[n]) + return -1; + + memcpy(ptr[n], name, len); + ptr[n][len] = '\0'; + + return n; + } + if (*pp && !strcmp(*pp, name)) return n; if (spa->i.param_names_stride) diff --git a/minimal-examples-lowlevel/http-server/minimal-http-server-form-post-lwsac/minimal-http-server-form-post.c b/minimal-examples-lowlevel/http-server/minimal-http-server-form-post-lwsac/minimal-http-server-form-post.c index 225cdd619..b4e16064b 100644 --- a/minimal-examples-lowlevel/http-server/minimal-http-server-form-post-lwsac/minimal-http-server-form-post.c +++ b/minimal-examples-lowlevel/http-server/minimal-http-server-form-post-lwsac/minimal-http-server-form-post.c @@ -27,9 +27,13 @@ struct pss { static int interrupted; -static const char * const param_names[] = { +/* get 2 parameters at predefined pos and up to 3 unknown parameters */ +static const char * param_names[] = { "text1", "send", + NULL, + NULL, + NULL }; enum enum_param_names { @@ -98,6 +102,8 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, /* we just dump the decoded things to the log */ for (n = 0; n < (int)LWS_ARRAY_SIZE(param_names); n++) { + if (!param_names[n]) + break; if (!lws_spa_get_string(pss->spa, n)) lwsl_user("%s: undefined\n", param_names[n]); else @@ -107,8 +113,6 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, lws_spa_get_string(pss->spa, n)); } - lwsac_free(&pss->ac); - /* * Our response is to redirect to a static page. We could * have generated a dynamic html page here instead. @@ -123,10 +127,9 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, case LWS_CALLBACK_HTTP_DROP_PROTOCOL: /* called when our wsi user_space is going to be destroyed */ if (pss->spa) { - lws_spa_destroy(pss->spa); + lws_spa_destroy(pss->spa); /* lwsac_free called this */ pss->spa = NULL; } - lwsac_free(&pss->ac); break; default: