Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
M
mongoose
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
esp
mongoose
Commits
96150bf5
Commit
96150bf5
authored
9 years ago
by
Deomid Ryabkov
Committed by
rojer
9 years ago
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Commonize file upload and make it part of Mongoose
PUBLISHED_FROM=23819ed308aeb8c1d6bdb08f5edd257df458ab38
parent
f49df515
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
167 additions
and
0 deletions
+167
-0
struct_mg_http_multipart_part.md
docs/c-api/http.h/struct_mg_http_multipart_part.md
+1
-0
mongoose.c
mongoose.c
+125
-0
mongoose.h
mongoose.h
+41
-0
No files found.
docs/c-api/http.h/struct_mg_http_multipart_part.md
View file @
96150bf5
...
@@ -8,6 +8,7 @@ signature: |
...
@@ -8,6 +8,7 @@ signature: |
const char *var_name;
const char *var_name;
struct mg_str data;
struct mg_str data;
int status; /* <0 on error */
int status; /* <0 on error */
void *user_data;
};
};
---
---
...
...
This diff is collapsed.
Click to expand it.
mongoose.c
View file @
96150bf5
...
@@ -4254,6 +4254,7 @@ struct mg_http_multipart_stream {
...
@@ -4254,6 +4254,7 @@ struct mg_http_multipart_stream {
int
boundary_len
;
int
boundary_len
;
const
char
*
var_name
;
const
char
*
var_name
;
const
char
*
file_name
;
const
char
*
file_name
;
void
*
user_data
;
int
prev_io_len
;
int
prev_io_len
;
enum
mg_http_multipart_stream_state
state
;
enum
mg_http_multipart_stream_state
state
;
int
processing_part
;
int
processing_part
;
...
@@ -5342,9 +5343,11 @@ static void mg_http_multipart_call_handler(struct mg_connection *c, int ev,
...
@@ -5342,9 +5343,11 @@ static void mg_http_multipart_call_handler(struct mg_connection *c, int ev,
mp
.
var_name
=
pd
->
mp_stream
.
var_name
;
mp
.
var_name
=
pd
->
mp_stream
.
var_name
;
mp
.
file_name
=
pd
->
mp_stream
.
file_name
;
mp
.
file_name
=
pd
->
mp_stream
.
file_name
;
mp
.
user_data
=
pd
->
mp_stream
.
user_data
;
mp
.
data
.
p
=
data
;
mp
.
data
.
p
=
data
;
mp
.
data
.
len
=
data_len
;
mp
.
data
.
len
=
data_len
;
mg_call
(
c
,
pd
->
endpoint_handler
,
ev
,
&
mp
);
mg_call
(
c
,
pd
->
endpoint_handler
,
ev
,
&
mp
);
pd
->
mp_stream
.
user_data
=
mp
.
user_data
;
}
}
static
int
mg_http_multipart_got_chunk
(
struct
mg_connection
*
c
)
{
static
int
mg_http_multipart_got_chunk
(
struct
mg_connection
*
c
)
{
...
@@ -5526,6 +5529,128 @@ static void mg_http_multipart_continue(struct mg_connection *c) {
...
@@ -5526,6 +5529,128 @@ static void mg_http_multipart_continue(struct mg_connection *c) {
}
}
}
}
struct
file_upload_state
{
char
*
lfn
;
size_t
num_recd
;
FILE
*
fp
;
};
void
mg_file_upload_handler
(
struct
mg_connection
*
nc
,
int
ev
,
void
*
ev_data
,
mg_fu_fname_fn
local_name_fn
)
{
switch
(
ev
)
{
case
MG_EV_HTTP_PART_BEGIN
:
{
struct
mg_http_multipart_part
*
mp
=
(
struct
mg_http_multipart_part
*
)
ev_data
;
struct
file_upload_state
*
fus
=
(
struct
file_upload_state
*
)
calloc
(
1
,
sizeof
(
*
fus
));
mp
->
user_data
=
NULL
;
struct
mg_str
lfn
=
local_name_fn
(
nc
,
mg_mk_str
(
mp
->
file_name
));
if
(
lfn
.
p
==
NULL
||
lfn
.
len
==
0
)
{
LOG
(
LL_ERROR
,
(
"%p Not allowed to upload %s"
,
nc
,
mp
->
file_name
));
mg_printf
(
nc
,
"HTTP/1.1 403 Not Allowed
\r\n
"
"Content-Type: text/plain
\r\n
"
"Connection: close
\r\n\r\n
"
"Not allowed to upload %s
\r\n
"
,
mp
->
file_name
);
nc
->
flags
|=
MG_F_SEND_AND_CLOSE
;
return
;
}
fus
->
lfn
=
(
char
*
)
malloc
(
lfn
.
len
+
1
);
memcpy
(
fus
->
lfn
,
lfn
.
p
,
lfn
.
len
);
fus
->
lfn
[
lfn
.
len
]
=
'\0'
;
if
(
lfn
.
p
!=
mp
->
file_name
)
free
((
char
*
)
lfn
.
p
);
LOG
(
LL_DEBUG
,
(
"%p Receiving file %s -> %s"
,
nc
,
mp
->
file_name
,
fus
->
lfn
));
fus
->
fp
=
fopen
(
fus
->
lfn
,
"w"
);
if
(
fus
->
fp
==
NULL
)
{
mg_printf
(
nc
,
"HTTP/1.1 500 Internal Server Error
\r\n
"
"Content-Type: text/plain
\r\n
"
"Connection: close
\r\n\r\n
"
);
LOG
(
LL_ERROR
,
(
"Failed to open %s: %d
\n
"
,
fus
->
lfn
,
errno
));
mg_printf
(
nc
,
"Failed to open %s: %d
\n
"
,
fus
->
lfn
,
errno
);
/* Do not close the connection just yet, discard remainder of the data.
* This is because at the time of writing some browsers (Chrome) fail to
* render response before all the data is sent. */
}
mp
->
user_data
=
(
void
*
)
fus
;
break
;
}
case
MG_EV_HTTP_PART_DATA
:
{
struct
mg_http_multipart_part
*
mp
=
(
struct
mg_http_multipart_part
*
)
ev_data
;
struct
file_upload_state
*
fus
=
(
struct
file_upload_state
*
)
mp
->
user_data
;
if
(
fus
==
NULL
||
fus
->
fp
==
NULL
)
break
;
if
(
fwrite
(
mp
->
data
.
p
,
1
,
mp
->
data
.
len
,
fus
->
fp
)
!=
mp
->
data
.
len
)
{
LOG
(
LL_ERROR
,
(
"Failed to write to %s: %d, wrote %d"
,
fus
->
lfn
,
errno
,
(
int
)
fus
->
num_recd
));
if
(
errno
==
ENOSPC
#ifdef SPIFFS_ERR_FULL
||
errno
==
SPIFFS_ERR_FULL
#endif
)
{
mg_printf
(
nc
,
"HTTP/1.1 413 Payload Too Large
\r\n
"
"Content-Type: text/plain
\r\n
"
"Connection: close
\r\n\r\n
"
);
mg_printf
(
nc
,
"Failed to write to %s: no space left; wrote %d
\r\n
"
,
fus
->
lfn
,
(
int
)
fus
->
num_recd
);
}
else
{
mg_printf
(
nc
,
"HTTP/1.1 500 Internal Server Error
\r\n
"
"Content-Type: text/plain
\r\n
"
"Connection: close
\r\n\r\n
"
);
mg_printf
(
nc
,
"Failed to write to %s: %d, wrote %d"
,
mp
->
file_name
,
errno
,
(
int
)
fus
->
num_recd
);
}
fclose
(
fus
->
fp
);
remove
(
fus
->
lfn
);
fus
->
fp
=
NULL
;
/* Do not close the connection just yet, discard remainder of the data.
* This is because at the time of writing some browsers (Chrome) fail to
* render response before all the data is sent. */
return
;
}
fus
->
num_recd
+=
mp
->
data
.
len
;
LOG
(
LL_DEBUG
,
(
"%p rec'd %d bytes, %d total"
,
nc
,
(
int
)
mp
->
data
.
len
,
(
int
)
fus
->
num_recd
));
break
;
}
case
MG_EV_HTTP_PART_END
:
{
struct
mg_http_multipart_part
*
mp
=
(
struct
mg_http_multipart_part
*
)
ev_data
;
struct
file_upload_state
*
fus
=
(
struct
file_upload_state
*
)
mp
->
user_data
;
if
(
fus
==
NULL
)
break
;
if
(
mp
->
status
>=
0
&&
fus
->
fp
!=
NULL
)
{
LOG
(
LL_DEBUG
,
(
"%p Uploaded %s (%s), %d bytes"
,
nc
,
mp
->
file_name
,
fus
->
lfn
,
(
int
)
fus
->
num_recd
));
mg_printf
(
nc
,
"HTTP/1.1 200 OK
\r\n
"
"Content-Type: text/plain
\r\n
"
"Connection: close
\r\n\r\n
"
"Ok, %s - %d bytes.
\r\n
"
,
mp
->
file_name
,
(
int
)
fus
->
num_recd
);
}
else
{
LOG
(
LL_ERROR
,
(
"Failed to store %s (%s)"
,
mp
->
file_name
,
fus
->
lfn
));
/*
* mp->status < 0 means connection was terminated, so no reason to send
* HTTP reply
*/
}
if
(
fus
->
fp
!=
NULL
)
fclose
(
fus
->
fp
);
free
(
fus
->
lfn
);
free
(
fus
);
mp
->
user_data
=
NULL
;
nc
->
flags
|=
MG_F_SEND_AND_CLOSE
;
break
;
}
}
}
#endif
/* MG_ENABLE_HTTP_STREAMING_MULTIPART */
#endif
/* MG_ENABLE_HTTP_STREAMING_MULTIPART */
void
mg_set_protocol_http_websocket
(
struct
mg_connection
*
nc
)
{
void
mg_set_protocol_http_websocket
(
struct
mg_connection
*
nc
)
{
...
...
This diff is collapsed.
Click to expand it.
mongoose.h
View file @
96150bf5
...
@@ -1994,6 +1994,7 @@ struct mg_http_multipart_part {
...
@@ -1994,6 +1994,7 @@ struct mg_http_multipart_part {
const
char
*
var_name
;
const
char
*
var_name
;
struct
mg_str
data
;
struct
mg_str
data
;
int
status
;
/* <0 on error */
int
status
;
/* <0 on error */
void
*
user_data
;
};
};
/* HTTP and websocket events. void *ev_data is described in a comment. */
/* HTTP and websocket events. void *ev_data is described in a comment. */
...
@@ -2526,6 +2527,46 @@ void mg_serve_http(struct mg_connection *nc, struct http_message *hm,
...
@@ -2526,6 +2527,46 @@ void mg_serve_http(struct mg_connection *nc, struct http_message *hm,
void
mg_register_http_endpoint
(
struct
mg_connection
*
nc
,
const
char
*
uri_path
,
void
mg_register_http_endpoint
(
struct
mg_connection
*
nc
,
const
char
*
uri_path
,
mg_event_handler_t
handler
);
mg_event_handler_t
handler
);
#ifdef MG_ENABLE_HTTP_STREAMING_MULTIPART
/*
* File upload handler.
* This handler can be used to implement file uploads with minimum code.
* This handler will process MG_EV_HTTP_PART_* events and store file data into
* a local file.
* `local_name_fn` will be invoked with whatever name was provided by the client
* and will expect the name of the local file to open. Return value of NULL will
* abort file upload (client will get a "403 Forbidden" response). If non-null,
* the returned string must be heap-allocated and will be freed by the caller.
* Exception: it is ok to return the same string verbatim.
*
* Example:
*
* ```c
* struct mg_str upload_fname(struct mg_connection *nc, struct mg_str fname) {
* // Just return the same filename. Do not actually do this except in test!
* // fname is user-controlled and needs to be sanitized.
* return fname;
* }
* void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
* switch (ev) {
* ...
* case MG_EV_HTTP_PART_BEGIN:
* case MG_EV_HTTP_PART_DATA:
* case MG_EV_HTTP_PART_END:
* mg_file_upload_handler(nc, ev, ev_data, upload_fname);
* break;
* }
* }
* ```
*/
typedef
struct
mg_str
(
*
mg_fu_fname_fn
)(
struct
mg_connection
*
nc
,
struct
mg_str
fname
);
void
mg_file_upload_handler
(
struct
mg_connection
*
nc
,
int
ev
,
void
*
ev_data
,
mg_fu_fname_fn
local_name_fn
);
#endif
/* MG_ENABLE_HTTP_STREAMING_MULTIPART */
#ifdef __cplusplus
#ifdef __cplusplus
}
}
#endif
/* __cplusplus */
#endif
/* __cplusplus */
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment