From 588cf0b8dbb4af1b8ad5077ab0ed80fc4295d414 Mon Sep 17 00:00:00 2001
From: Andy Green <andy@warmcat.com>
Date: Fri, 22 Mar 2019 16:55:51 +0800
Subject: [PATCH] lws_spa: add CLOSE callback

This should ease the situation where there was creation done in the
callback for LWS_UFS_OPEN
---
 include/libwebsockets/lws-spa.h               |  4 +++-
 lib/roles/http/server/lws-spa.c               | 23 +++++++++++--------
 .../minimal-http-server-form-post-file.c      |  2 ++
 plugins/deaddrop/protocol_lws_deaddrop.c      |  2 ++
 plugins/protocol_post_demo.c                  |  2 ++
 5 files changed, 23 insertions(+), 10 deletions(-)

diff --git a/include/libwebsockets/lws-spa.h b/include/libwebsockets/lws-spa.h
index fcaf3889..89627c31 100644
--- a/include/libwebsockets/lws-spa.h
+++ b/include/libwebsockets/lws-spa.h
@@ -47,8 +47,10 @@ enum lws_spa_fileupload_states {
 	/**< a chunk of file content has arrived */
 	LWS_UFS_FINAL_CONTENT,
 	/**< the last chunk (possibly zero length) of file content has arrived */
-	LWS_UFS_OPEN
+	LWS_UFS_OPEN,
 	/**< a new file is starting to arrive */
+	LWS_UFS_CLOSE
+	/**< the file decode stuff is being destroyed */
 };
 
 /**
diff --git a/lib/roles/http/server/lws-spa.c b/lib/roles/http/server/lws-spa.c
index 190b5023..bc8d3ce6 100644
--- a/lib/roles/http/server/lws-spa.c
+++ b/lib/roles/http/server/lws-spa.c
@@ -136,7 +136,8 @@ lws_urldecode_s_process(struct lws_urldecode_stateful *s, const char *in,
 
 	while (len--) {
 		if (s->pos == s->out_len - s->mp - 1) {
-			if (s->output(s->data, s->name, &s->out, s->pos, 0))
+			if (s->output(s->data, s->name, &s->out, s->pos,
+				      LWS_UFS_CONTENT))
 				return -1;
 
 			was_end = s->pos;
@@ -158,7 +159,7 @@ lws_urldecode_s_process(struct lws_urldecode_stateful *s, const char *in,
 			if (*in == '&') {
 				s->name[s->pos] = '\0';
 				if (s->output(s->data, s->name, &s->out,
-					      s->pos, 1))
+					      s->pos, LWS_UFS_FINAL_CONTENT))
 					return -1;
 				s->pos = 0;
 				s->state = US_IDLE;
@@ -180,7 +181,7 @@ lws_urldecode_s_process(struct lws_urldecode_stateful *s, const char *in,
 			if (*in == '&') {
 				s->out[s->pos] = '\0';
 				if (s->output(s->data, s->name, &s->out,
-					      s->pos, 1))
+					      s->pos, LWS_UFS_FINAL_CONTENT))
 					return -1;
 				s->pos = 0;
 				s->state = US_NAME;
@@ -229,7 +230,8 @@ retry_as_first:
 
 					if (s->pos || was_end)
 						if (s->output(s->data, s->name,
-						      &s->out, s->pos, 1))
+						      &s->out, s->pos,
+						      LWS_UFS_FINAL_CONTENT))
 							return -1;
 
 					s->pos = 0;
@@ -409,9 +411,13 @@ lws_urldecode_s_destroy(struct lws_urldecode_stateful *s)
 		ret = -1;
 
 	if (!ret)
-		if (s->output(s->data, s->name, &s->out, s->pos, 1))
+		if (s->output(s->data, s->name, &s->out, s->pos,
+			      LWS_UFS_FINAL_CONTENT))
 			ret = -1;
 
+	if (s->output(s->data, s->name, NULL, 0, LWS_UFS_CLOSE))
+		return -1;
+
 	lws_free(s);
 
 	return ret;
@@ -448,15 +454,14 @@ static int
 lws_urldecode_spa_cb(void *data, const char *name, char **buf, int len,
 		     int final)
 {
-	struct lws_spa *spa =
-			(struct lws_spa *)data;
+	struct lws_spa *spa = (struct lws_spa *)data;
 	int n;
 
-	if (spa->s->content_disp_filename[0]) {
+	if (final == LWS_UFS_CLOSE || spa->s->content_disp_filename[0]) {
 		if (spa->opt_cb) {
 			n = spa->opt_cb(spa->opt_data, name,
 					spa->s->content_disp_filename,
-					*buf, len, final);
+					buf ? *buf : NULL, len, final);
 
 			if (n < 0)
 				return -1;
diff --git a/minimal-examples/http-server/minimal-http-server-form-post-file/minimal-http-server-form-post-file.c b/minimal-examples/http-server/minimal-http-server-form-post-file/minimal-http-server-form-post-file.c
index 0abc714a..4f669fa0 100644
--- a/minimal-examples/http-server/minimal-http-server-form-post-file/minimal-http-server-form-post-file.c
+++ b/minimal-examples/http-server/minimal-http-server-form-post-file/minimal-http-server-form-post-file.c
@@ -88,6 +88,8 @@ file_upload_cb(void *data, const char *name, const char *filename,
 		close(pss->fd);
 		pss->fd = -1;
 		break;
+	case LWS_UFS_CLOSE:
+		break;
 	}
 
 	return 0;
diff --git a/plugins/deaddrop/protocol_lws_deaddrop.c b/plugins/deaddrop/protocol_lws_deaddrop.c
index 9fa851b2..7c40f693 100644
--- a/plugins/deaddrop/protocol_lws_deaddrop.c
+++ b/plugins/deaddrop/protocol_lws_deaddrop.c
@@ -322,6 +322,8 @@ file_upload_cb(void *data, const char *name, const char *filename,
 		pss->response_code = HTTP_STATUS_OK;
 		scan_upload_dir(pss->vhd);
 
+		break;
+	case LWS_UFS_CLOSE:
 		break;
 	}
 
diff --git a/plugins/protocol_post_demo.c b/plugins/protocol_post_demo.c
index e373cf64..927f7a81 100644
--- a/plugins/protocol_post_demo.c
+++ b/plugins/protocol_post_demo.c
@@ -107,6 +107,8 @@ file_upload_cb(void *data, const char *name, const char *filename,
 		pss->fd = LWS_INVALID_FILE;
 #endif
 		break;
+	case LWS_UFS_CLOSE:
+		break;
 	}
 
 	return 0;
-- 
GitLab