mirror of
https://github.com/curl/curl.git
synced 2026-07-23 18:37:17 +03:00
mime: latch last read callback status.
In case a read callback returns a status (pause, abort, eof, error) instead of a byte count, drain the bytes read so far but remember this status for further processing. Takes care of not losing data when pausing, and properly resume a paused mime structure when requested. New tests 670-673 check unpausing cases, with easy or multi interface and mime or form api. Fixes #4813 Reported-by: MrdUkk on github
This commit is contained in:
parent
3dce9849be
commit
96972ec1c0
13 changed files with 628 additions and 13 deletions
|
|
@ -1003,6 +1003,14 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
|
|||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/* Unpause parts in active mime tree. */
|
||||
if((k->keepon & ~newstate & KEEP_SEND_PAUSE) &&
|
||||
(data->mstate == CURLM_STATE_PERFORM ||
|
||||
data->mstate == CURLM_STATE_TOOFAST) &&
|
||||
data->state.fread_func == (curl_read_callback) Curl_mime_read) {
|
||||
Curl_mime_unpause(data->state.in);
|
||||
}
|
||||
|
||||
/* put it back in the keepon */
|
||||
k->keepon = newstate;
|
||||
|
||||
|
|
|
|||
|
|
@ -728,14 +728,10 @@ int curl_formget(struct curl_httppost *form, void *arg,
|
|||
if(!nread)
|
||||
break;
|
||||
|
||||
switch(nread) {
|
||||
default:
|
||||
if(append(arg, buffer, nread) != nread)
|
||||
result = CURLE_READ_ERROR;
|
||||
break;
|
||||
case CURL_READFUNC_ABORT:
|
||||
case CURL_READFUNC_PAUSE:
|
||||
break;
|
||||
if(nread > sizeof(buffer) || append(arg, buffer, nread) != nread) {
|
||||
result = CURLE_READ_ERROR;
|
||||
if(nread == CURL_READFUNC_ABORT)
|
||||
result = CURLE_ABORTED_BY_CALLBACK;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
39
lib/mime.c
39
lib/mime.c
|
|
@ -740,9 +740,19 @@ static size_t read_part_content(curl_mimepart *part,
|
|||
{
|
||||
size_t sz = 0;
|
||||
|
||||
if(part->readfunc)
|
||||
sz = part->readfunc(buffer, 1, bufsize, part->arg);
|
||||
return sz;
|
||||
switch(part->lastreadstatus) {
|
||||
case 0:
|
||||
case CURL_READFUNC_ABORT:
|
||||
case CURL_READFUNC_PAUSE:
|
||||
case READ_ERROR:
|
||||
break;
|
||||
default:
|
||||
if(part->readfunc)
|
||||
sz = part->readfunc(buffer, 1, bufsize, part->arg);
|
||||
part->lastreadstatus = sz;
|
||||
break;
|
||||
}
|
||||
return part->lastreadstatus;
|
||||
}
|
||||
|
||||
/* Read and encode part content. */
|
||||
|
|
@ -1031,6 +1041,7 @@ static int mime_part_rewind(curl_mimepart *part)
|
|||
if(res == CURL_SEEKFUNC_OK)
|
||||
mimesetstate(&part->state, targetstate, NULL);
|
||||
|
||||
part->lastreadstatus = 1; /* Successful read status. */
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
@ -1073,6 +1084,7 @@ static void cleanup_part_content(curl_mimepart *part)
|
|||
part->datasize = (curl_off_t) 0; /* No size yet. */
|
||||
cleanup_encoder_state(&part->encstate);
|
||||
part->kind = MIMEKIND_NONE;
|
||||
part->lastreadstatus = 1; /* Successful read status. */
|
||||
}
|
||||
|
||||
static void mime_subparts_free(void *ptr)
|
||||
|
|
@ -1238,6 +1250,7 @@ void Curl_mime_initpart(curl_mimepart *part, struct Curl_easy *easy)
|
|||
{
|
||||
memset((char *) part, 0, sizeof(*part));
|
||||
part->easy = easy;
|
||||
part->lastreadstatus = 1; /* Successful read status. */
|
||||
mimesetstate(&part->state, MIMESTATE_BEGIN, NULL);
|
||||
}
|
||||
|
||||
|
|
@ -1805,6 +1818,26 @@ CURLcode Curl_mime_prepare_headers(curl_mimepart *part,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* Recursively reset paused status in the given part. */
|
||||
void Curl_mime_unpause(curl_mimepart *part)
|
||||
{
|
||||
if(part) {
|
||||
if(part->lastreadstatus == CURL_READFUNC_PAUSE)
|
||||
part->lastreadstatus = 1; /* Successful read status. */
|
||||
if(part->kind == MIMEKIND_MULTIPART) {
|
||||
curl_mime *mime = (curl_mime *) part->arg;
|
||||
|
||||
if(mime) {
|
||||
curl_mimepart *subpart;
|
||||
|
||||
for(subpart = mime->firstpart; subpart; subpart = subpart->nextpart)
|
||||
Curl_mime_unpause(subpart);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#else /* !CURL_DISABLE_HTTP || !CURL_DISABLE_SMTP || !CURL_DISABLE_IMAP */
|
||||
|
||||
/* Mime not compiled in: define stubs for externally-referenced functions. */
|
||||
|
|
|
|||
|
|
@ -125,6 +125,7 @@ struct curl_mimepart_s {
|
|||
mime_state state; /* Current readback state. */
|
||||
const mime_encoder *encoder; /* Content data encoder. */
|
||||
mime_encoder_state encstate; /* Data encoder state. */
|
||||
size_t lastreadstatus; /* Last read callback returned status. */
|
||||
};
|
||||
|
||||
CURLcode Curl_mime_add_header(struct curl_slist **slp, const char *fmt, ...);
|
||||
|
|
@ -147,6 +148,7 @@ size_t Curl_mime_read(char *buffer, size_t size, size_t nitems,
|
|||
void *instream);
|
||||
CURLcode Curl_mime_rewind(curl_mimepart *part);
|
||||
const char *Curl_mime_contenttype(const char *filename);
|
||||
void Curl_mime_unpause(curl_mimepart *part);
|
||||
|
||||
#else
|
||||
/* if disabled */
|
||||
|
|
@ -158,6 +160,7 @@ const char *Curl_mime_contenttype(const char *filename);
|
|||
#define Curl_mime_size(x) (curl_off_t) -1
|
||||
#define Curl_mime_read NULL
|
||||
#define Curl_mime_rewind(x) ((void)x, CURLE_NOT_BUILT_IN)
|
||||
#define Curl_mime_unpause(x)
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue