From 55d889c4327c813548474492098022eb55e7204e Mon Sep 17 00:00:00 2001 From: tiymat <138939221+tiymat@users.noreply.github.com> Date: Sat, 11 Jan 2025 17:20:12 -0330 Subject: [PATCH 01/16] src: add CURLOPT_UPLOAD_FLAGS --- docs/TODO | 7 -- docs/cmdline-opts/Makefile.inc | 1 + docs/cmdline-opts/upload-file.md | 2 +- docs/cmdline-opts/upload-flags.md | 23 +++++ docs/internals/STRPARSE.md | 2 +- docs/libcurl/curl_easy_setopt.md | 4 + docs/libcurl/opts/CURLOPT_UPLOAD_FLAGS.md | 100 ++++++++++++++++++++++ docs/libcurl/symbols-in-versions | 7 ++ docs/options-in-versions | 1 + include/curl/curl.h | 11 +++ lib/easyoptions.c | 3 +- lib/imap.c | 89 ++++++++++++++++++- lib/setopt.c | 4 +- lib/urldata.h | 1 + src/tool_cfgable.c | 1 + src/tool_cfgable.h | 1 + src/tool_getparam.c | 60 +++++++++++++ src/tool_getparam.h | 1 + src/tool_listhelp.c | 3 + src/tool_operate.c | 3 + src/tool_setopt.c | 1 + tests/data/Makefile.am | 2 +- tests/data/test3208 | 63 ++++++++++++++ tests/data/test3209 | 63 ++++++++++++++ 24 files changed, 438 insertions(+), 15 deletions(-) create mode 100644 docs/cmdline-opts/upload-flags.md create mode 100644 docs/libcurl/opts/CURLOPT_UPLOAD_FLAGS.md create mode 100644 tests/data/test3208 create mode 100644 tests/data/test3209 diff --git a/docs/TODO b/docs/TODO index 0c35701765..f935a15fb5 100644 --- a/docs/TODO +++ b/docs/TODO @@ -92,7 +92,6 @@ 9. IMAP 9.1 Enhanced capability support - 9.2 upload unread 10. LDAP 10.1 SASL based authentication mechanisms @@ -720,12 +719,6 @@ Add the ability, for an application that uses libcurl, to obtain the list of capabilities returned from the CAPABILITY command. -9.2 upload unread - - Uploads over IMAP currently always set the email as "read" (or "seen"). It - would be good to offer a way for users to select for uploads to remain - unread. - 10. LDAP 10.1 SASL based authentication mechanisms diff --git a/docs/cmdline-opts/Makefile.inc b/docs/cmdline-opts/Makefile.inc index be6fadd26b..3cc44c9896 100644 --- a/docs/cmdline-opts/Makefile.inc +++ b/docs/cmdline-opts/Makefile.inc @@ -301,6 +301,7 @@ DPAGES = \ trace.md \ unix-socket.md \ upload-file.md \ + upload-flags.md \ url.md \ url-query.md \ use-ascii.md \ diff --git a/docs/cmdline-opts/upload-file.md b/docs/cmdline-opts/upload-file.md index 7e9ffbf1e6..5a2842e58a 100644 --- a/docs/cmdline-opts/upload-file.md +++ b/docs/cmdline-opts/upload-file.md @@ -31,7 +31,7 @@ filename or curl thinks that your last directory name is the remote filename to use. When putting the local filename at the end of the URL, curl ignores what is on -the left side of any slash (/) or backslash (\) used in the filename and only +the left side of any slash (/) or backslash (\\) used in the filename and only appends what is on the right side of the rightmost such character. Use the filename `-` (a single dash) to use stdin instead of a given file. diff --git a/docs/cmdline-opts/upload-flags.md b/docs/cmdline-opts/upload-flags.md new file mode 100644 index 0000000000..80cad4baa1 --- /dev/null +++ b/docs/cmdline-opts/upload-flags.md @@ -0,0 +1,23 @@ +--- +c: Copyright (C) Daniel Stenberg, , et al. +SPDX-License-Identifier: curl +Long: upload-flags +Arg: +Help: Specify additional upload behaviour +Category: curl output +Added: 8.12.0 +Multi: single +See-also: + - upload-file +Example: + - --upload-flags Flagged,!Seen --upload-file local/dir/file $URL +--- + +# `--upload-flags` + +Specify additional behaviour to apply to uploaded files. Flags are +specified as either a single flag value or a comma-separated list +of flag values. Flag values may be negated by prepending them with +a '!' character. Currently the following case-sensitive flag values +are accepted: Answered, Deleted, Draft, Flagged, and Seen. The +currently-accepted flag values are used to set flags on IMAP uploads. diff --git a/docs/internals/STRPARSE.md b/docs/internals/STRPARSE.md index a50448cdff..e0750f2694 100644 --- a/docs/internals/STRPARSE.md +++ b/docs/internals/STRPARSE.md @@ -68,7 +68,7 @@ int Curl_str_quotedword(char **linep, struct Curl_str *out, const size_t max); ~~~ Get a "quoted" word. This means everything that is provided within a leading -and an ending double character. No escaping possible. +and an ending double quote character. No escaping possible. `max` is the longest accepted word, or it returns error. diff --git a/docs/libcurl/curl_easy_setopt.md b/docs/libcurl/curl_easy_setopt.md index b6e08912ee..bf5f90e25f 100644 --- a/docs/libcurl/curl_easy_setopt.md +++ b/docs/libcurl/curl_easy_setopt.md @@ -1273,6 +1273,10 @@ Upload data. See CURLOPT_UPLOAD(3) Set upload buffer size. See CURLOPT_UPLOAD_BUFFERSIZE(3) +## CURLOPT_UPLOAD_FLAGS + +Set upload flags. See CURLOPT_UPLOAD_FLAGS(3) + ## CURLOPT_URL URL to work on. See CURLOPT_URL(3) diff --git a/docs/libcurl/opts/CURLOPT_UPLOAD_FLAGS.md b/docs/libcurl/opts/CURLOPT_UPLOAD_FLAGS.md new file mode 100644 index 0000000000..2208f3ec95 --- /dev/null +++ b/docs/libcurl/opts/CURLOPT_UPLOAD_FLAGS.md @@ -0,0 +1,100 @@ +--- +c: Copyright (C) Daniel Stenberg, , et al. +SPDX-License-Identifier: curl +Title: CURLOPT_UPLOAD_FLAGS +Section: 3 +Source: libcurl +See-also: + - CURLOPT_UPLOAD (3) +Protocol: + - IMAP + - IMAPS +Added-in: 8.12.0 +--- + +# NAME + +CURLOPT_UPLOAD_FLAGS - configure upload flags + +# SYNOPSIS + +~~~c +#include + +CURLcode curl_easy_setopt(CURL *handle, CURLOPT_UPLOAD_FLAGS, long bitmask); +~~~ + +# DESCRIPTION + +Pass a long as parameter, which is set to a bitmask, to tell libcurl which +flags to send the server relating to uploaded files. The current supported +flags are *CURLUPLOADFLAG_ANSWERED*, which sets the *Answered* flag for IMAP +uploads, *CURLUPLOADFLAG_DELETED*, which sets the *Deleted* flag for IMAP +uploads, *CURLUPLOADFLAG_DRAFT*, which sets the *Draft* flag for IMAP uploads, +*CURLUPLOADFLAG_FLAGGED*, which sets the *Flagged* flag for IMAP uploads, and +*CURLUPLOADFLAG_SEEN*, which sets the *Seen* flag for IMAP uploads. + +# DEFAULT + +A bitmask with only the CURLUPLOADFLAG_SEEN flag set. + +# %PROTOCOLS% + +# EXAMPLE + +~~~c +static size_t read_cb(char *ptr, size_t size, size_t nmemb, void *userdata) +{ + FILE *src = userdata; + /* copy as much data as possible into the 'ptr' buffer, but no more than + 'size' * 'nmemb' bytes */ + size_t retcode = fread(ptr, size, nmemb, src); + + return retcode; +} + +int main(void) +{ + CURL *curl = curl_easy_init(); + if(curl) { + FILE *src = fopen("local-file", "r"); + curl_off_t fsize; /* set this to the size of the input file */ + + /* we want to use our own read function */ + curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_cb); + + /* enable uploading */ + curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); + + /* specify target */ + curl_easy_setopt(curl, CURLOPT_URL, "imap://example.com:993/mailbox"); + + /* provide username */ + curl_easy_setopt(curl, CURLOPT_USERNAME, "user@example.com"); + + /* provide password */ + curl_easy_setopt(curl, CURLOPT_PASSWORD, "password"); + + /* specify that uploaded mail should be considered flagged */ + curl_easy_setopt(curl, CURLOPT_UPLOAD_FLAGS, CURLOPTUPLOADFLAG_FLAGGED); + + /* now specify which pointer to pass to our callback */ + curl_easy_setopt(curl, CURLOPT_READDATA, src); + + /* Set the size of the file to upload */ + curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)fsize); + + /* perform the upload */ + curl_easy_perform(curl); + } +} +~~~ + +# %AVAILABILITY% + +# RETURN VALUE + +curl_easy_setopt(3) returns a CURLcode indicating success or error. + +CURLE_OK (0) means everything was OK, non-zero means an error occurred, see +libcurl-errors(3). diff --git a/docs/libcurl/symbols-in-versions b/docs/libcurl/symbols-in-versions index 0fd02ff092..e437f91047 100644 --- a/docs/libcurl/symbols-in-versions +++ b/docs/libcurl/symbols-in-versions @@ -891,6 +891,7 @@ CURLOPT_UNRESTRICTED_AUTH 7.10.4 CURLOPT_UPKEEP_INTERVAL_MS 7.62.0 CURLOPT_UPLOAD 7.1 CURLOPT_UPLOAD_BUFFERSIZE 7.62.0 +CURLOPT_UPLOAD_FLAGS 8.12.0 CURLOPT_URL 7.1 CURLOPT_USE_SSL 7.17.0 CURLOPT_USERAGENT 7.1 @@ -1124,6 +1125,12 @@ CURLUPART_SCHEME 7.62.0 CURLUPART_URL 7.62.0 CURLUPART_USER 7.62.0 CURLUPART_ZONEID 7.65.0 +CURLUPLOADFLAG_ANSWERED 8.12.0 +CURLUPLOADFLAG_DELETED 8.12.0 +CURLUPLOADFLAG_DRAFT 8.12.0 +CURLUPLOADFLAG_FLAGGED 8.12.0 +CURLUPLOADFLAG_MAX_LEN 8.12.0 +CURLUPLOADFLAG_SEEN 8.12.0 CURLUSESSL_ALL 7.17.0 CURLUSESSL_CONTROL 7.17.0 CURLUSESSL_NONE 7.17.0 diff --git a/docs/options-in-versions b/docs/options-in-versions index 057cbafccd..d0f70df420 100644 --- a/docs/options-in-versions +++ b/docs/options-in-versions @@ -266,6 +266,7 @@ --trace-time 7.14.0 --unix-socket 7.40.0 --upload-file (-T) 4.0 +--upload-flags 8.12.0 --url 7.5 --url-query 7.87.0 --use-ascii (-B) 5.0 diff --git a/include/curl/curl.h b/include/curl/curl.h index 84cf5f2f52..88d69c9d0d 100644 --- a/include/curl/curl.h +++ b/include/curl/curl.h @@ -1015,6 +1015,15 @@ typedef enum { #define CURLALTSVC_H2 (1<<4) #define CURLALTSVC_H3 (1<<5) +/* bitmask values for CURLOPT_UPLOAD_FLAGS */ +#define CURLUPLOADFLAG_ANSWERED (1<<0) +#define CURLUPLOADFLAG_DELETED (1<<1) +#define CURLUPLOADFLAG_DRAFT (1<<2) +#define CURLUPLOADFLAG_FLAGGED (1<<3) +#define CURLUPLOADFLAG_SEEN (1<<4) + +/* max allowable flag length for a CURLOPT_UPLOAD_FLAGS flag */ +#define CURLUPLOADFLAG_MAX_LEN 20 struct curl_hstsentry { char *name; @@ -2228,6 +2237,8 @@ typedef enum { /* maximum number of keepalive probes (Linux, *BSD, macOS, etc.) */ CURLOPT(CURLOPT_TCP_KEEPCNT, CURLOPTTYPE_LONG, 326), + CURLOPT(CURLOPT_UPLOAD_FLAGS, CURLOPTTYPE_LONG, 327), + CURLOPT_LASTENTRY /* the last unused */ } CURLoption; diff --git a/lib/easyoptions.c b/lib/easyoptions.c index 81091c405a..b444010439 100644 --- a/lib/easyoptions.c +++ b/lib/easyoptions.c @@ -353,6 +353,7 @@ struct curl_easyoption Curl_easyopts[] = { {"UPKEEP_INTERVAL_MS", CURLOPT_UPKEEP_INTERVAL_MS, CURLOT_LONG, 0}, {"UPLOAD", CURLOPT_UPLOAD, CURLOT_LONG, 0}, {"UPLOAD_BUFFERSIZE", CURLOPT_UPLOAD_BUFFERSIZE, CURLOT_LONG, 0}, + {"UPLOAD_FLAGS", CURLOPT_UPLOAD_FLAGS, CURLOT_LONG, 0}, {"URL", CURLOPT_URL, CURLOT_STRING, 0}, {"USERAGENT", CURLOPT_USERAGENT, CURLOT_STRING, 0}, {"USERNAME", CURLOPT_USERNAME, CURLOT_STRING, 0}, @@ -377,6 +378,6 @@ struct curl_easyoption Curl_easyopts[] = { */ int Curl_easyopts_check(void) { - return ((CURLOPT_LASTENTRY%10000) != (326 + 1)); + return ((CURLOPT_LASTENTRY%10000) != (327 + 1)); } #endif diff --git a/lib/imap.c b/lib/imap.c index e424cdb056..6999948855 100644 --- a/lib/imap.c +++ b/lib/imap.c @@ -765,6 +765,7 @@ static CURLcode imap_perform_append(struct Curl_easy *data) CURLcode result = CURLE_OK; struct IMAP *imap = data->req.p.imap; char *mailbox; + bool first_flag = TRUE; /* Check we have a mailbox */ if(!imap->mailbox) { @@ -813,9 +814,91 @@ static CURLcode imap_perform_append(struct Curl_easy *data) if(!mailbox) return CURLE_OUT_OF_MEMORY; - /* Send the APPEND command */ - result = imap_sendf(data, "APPEND %s (\\Seen) {%" FMT_OFF_T "}", - mailbox, data->state.infilesize); + /* Generate flags string and send the APPEND command */ + if(data->set.upload_flags) { + struct dynbuf flags; + Curl_dyn_init(&flags, 100); + if(Curl_dyn_add(&flags, "(")) { + result = CURLE_OUT_OF_MEMORY; + goto cleanup; + } + + if(data->set.upload_flags & CURLUPLOADFLAG_ANSWERED) { + if(first_flag) + first_flag = FALSE; + else if(Curl_dyn_add(&flags, " ")) { + result = CURLE_OUT_OF_MEMORY; + goto cleanup; + } + if(Curl_dyn_add(&flags, "\\Answered")) { + result = CURLE_OUT_OF_MEMORY; + goto cleanup; + } + } + if(data->set.upload_flags & CURLUPLOADFLAG_DELETED) { + if(first_flag) + first_flag = FALSE; + else if(Curl_dyn_add(&flags, " ")) { + result = CURLE_OUT_OF_MEMORY; + goto cleanup; + } + if(Curl_dyn_add(&flags, "\\Deleted")) { + result = CURLE_OUT_OF_MEMORY; + goto cleanup; + } + } + if(data->set.upload_flags & CURLUPLOADFLAG_DRAFT) { + if(first_flag) + first_flag = FALSE; + else if(Curl_dyn_add(&flags, " ")) { + result = CURLE_OUT_OF_MEMORY; + goto cleanup; + } + if(Curl_dyn_add(&flags, "\\Draft")) { + result = CURLE_OUT_OF_MEMORY; + goto cleanup; + } + } + if(data->set.upload_flags & CURLUPLOADFLAG_FLAGGED) { + if(first_flag) + first_flag = FALSE; + else if(Curl_dyn_add(&flags, " ")) { + result = CURLE_OUT_OF_MEMORY; + goto cleanup; + } + if(Curl_dyn_add(&flags, "\\Flagged")) { + result = CURLE_OUT_OF_MEMORY; + goto cleanup; + } + } + if(data->set.upload_flags & CURLUPLOADFLAG_SEEN) { + if(first_flag) + first_flag = FALSE; + else if(Curl_dyn_add(&flags, " ")) { + result = CURLE_OUT_OF_MEMORY; + goto cleanup; + } + if(Curl_dyn_add(&flags, "\\Seen")) { + result = CURLE_OUT_OF_MEMORY; + goto cleanup; + } + } + + if(Curl_dyn_add(&flags, ")")) { + result = CURLE_OUT_OF_MEMORY; + goto cleanup; + } + + result = imap_sendf(data, "APPEND %s %s {%" FMT_OFF_T "}", + mailbox, Curl_dyn_ptr(&flags), data->state.infilesize); + +cleanup: + Curl_dyn_free(&flags); + } + else{ + result = imap_sendf(data, "APPEND %s {%" FMT_OFF_T "}", + mailbox, data->state.infilesize); + } free(mailbox); diff --git a/lib/setopt.c b/lib/setopt.c index 7366d4a3e6..b94ed49beb 100644 --- a/lib/setopt.c +++ b/lib/setopt.c @@ -1403,7 +1403,9 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option, */ Curl_safefree(data->set.str[STRING_SSL_ENGINE]); return Curl_ssl_set_engine_default(data); - + case CURLOPT_UPLOAD_FLAGS: + data->set.upload_flags = arg; + break; default: /* unknown option */ return CURLE_UNKNOWN_OPTION; diff --git a/lib/urldata.h b/lib/urldata.h index 224167f7f0..d785ff811e 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -1822,6 +1822,7 @@ struct UserDefined { #ifdef USE_ECH int tls_ech; /* TLS ECH configuration */ #endif + long upload_flags; }; #ifndef CURL_DISABLE_MIME diff --git a/src/tool_cfgable.c b/src/tool_cfgable.c index d7ee7b1b22..a10e392b1a 100644 --- a/src/tool_cfgable.c +++ b/src/tool_cfgable.c @@ -45,6 +45,7 @@ void config_init(struct OperationConfig *config) config->http09_allowed = FALSE; config->ftp_skip_ip = TRUE; config->file_clobber_mode = CLOBBER_DEFAULT; + config->upload_flags = CURLUPLOADFLAG_SEEN; curlx_dyn_init(&config->postdata, MAX_FILE2MEMORY); } diff --git a/src/tool_cfgable.h b/src/tool_cfgable.h index e1799f8833..bb0d8c9fac 100644 --- a/src/tool_cfgable.h +++ b/src/tool_cfgable.h @@ -310,6 +310,7 @@ struct OperationConfig { char *ech; /* Config set by --ech keywords */ char *ech_config; /* Config set by "--ech esl:" option */ char *ech_public; /* Config set by "--ech pn:" option */ + unsigned long upload_flags; /* Bitmask for --upload-flags */ }; struct GlobalConfig { diff --git a/src/tool_getparam.c b/src/tool_getparam.c index 5eb3794519..571d10cd9d 100644 --- a/src/tool_getparam.c +++ b/src/tool_getparam.c @@ -41,6 +41,7 @@ #include "tool_main.h" #include "dynbuf.h" #include "tool_stderr.h" +#include "strparse.h" #include "var.h" #include "memdebug.h" /* keep this as LAST include */ @@ -335,6 +336,7 @@ static const struct LongShort aliases[]= { {"trace-time", ARG_BOOL, ' ', C_TRACE_TIME}, {"unix-socket", ARG_FILE, ' ', C_UNIX_SOCKET}, {"upload-file", ARG_FILE, 'T', C_UPLOAD_FILE}, + {"upload-flags", ARG_STRG, ' ', C_UPLOAD_FLAGS}, {"url", ARG_STRG, ' ', C_URL}, {"url-query", ARG_STRG, ' ', C_URL_QUERY}, {"use-ascii", ARG_BOOL, 'B', C_USE_ASCII}, @@ -1560,6 +1562,61 @@ static ParameterError parse_time_cond(struct GlobalConfig *global, return err; } +static ParameterError parse_upload_flags(struct OperationConfig *config, + char *nextarg) +{ + struct Curl_str segment; + ParameterError err = PARAM_OK; + bool negative = FALSE; + + while(!Curl_str_until(&nextarg, &segment, CURLUPLOADFLAG_MAX_LEN, ',')) { + negative = !Curl_str_single(&segment.str, '!'); + if(negative) + --segment.len; /* The leading '!' was removed in Curl_str_single */ + + if(segment.len == 8 && !strncmp(segment.str, "Answered", segment.len)) { + if(negative) + config->upload_flags &= ~CURLUPLOADFLAG_ANSWERED; + else + config->upload_flags |= CURLUPLOADFLAG_ANSWERED; + } + else if(segment.len == 7 && !strncmp(segment.str, "Deleted", + segment.len)) { + if(negative) + config->upload_flags &= ~CURLUPLOADFLAG_DELETED; + else + config->upload_flags |= CURLUPLOADFLAG_DELETED; + } + else if(segment.len == 5 && !strncmp(segment.str, "Draft", segment.len)) { + if(negative) + config->upload_flags &= ~CURLUPLOADFLAG_DRAFT; + else + config->upload_flags |= CURLUPLOADFLAG_DRAFT; + } + else if(segment.len == 7 && + !strncmp(segment.str, "Flagged", segment.len)) { + if(negative) + config->upload_flags &= ~CURLUPLOADFLAG_FLAGGED; + else + config->upload_flags |= CURLUPLOADFLAG_FLAGGED; + } + else if(segment.len == 4 && !strncmp(segment.str, "Seen", segment.len)) { + if(negative) + config->upload_flags &= ~CURLUPLOADFLAG_SEEN; + else + config->upload_flags |= CURLUPLOADFLAG_SEEN; + } + else{ + err = PARAM_OPTION_UNKNOWN; + break; + } + + Curl_str_single(&nextarg, ','); + } + + return err; +} + ParameterError getparameter(const char *flag, /* f or -long-flag */ char *nextarg, /* NULL if unset */ argv_item_t cleararg, @@ -2853,6 +2910,9 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ case C_MPTCP: /* --mptcp */ config->mptcp = TRUE; break; + case C_UPLOAD_FLAGS: /* --upload-flags */ + err = parse_upload_flags(config, nextarg); + break; default: /* unknown flag */ err = PARAM_OPTION_UNKNOWN; break; diff --git a/src/tool_getparam.h b/src/tool_getparam.h index af083d06c7..2deb5b6e3f 100644 --- a/src/tool_getparam.h +++ b/src/tool_getparam.h @@ -293,6 +293,7 @@ typedef enum { C_IP_TOS, C_UNIX_SOCKET, C_UPLOAD_FILE, + C_UPLOAD_FLAGS, C_URL, C_URL_QUERY, C_USE_ASCII, diff --git a/src/tool_listhelp.c b/src/tool_listhelp.c index 70b5e37817..7b6c68fa19 100644 --- a/src/tool_listhelp.c +++ b/src/tool_listhelp.c @@ -808,6 +808,9 @@ const struct helptxt helptext[] = { {"-T, --upload-file ", "Transfer local FILE to destination", CURLHELP_IMPORTANT | CURLHELP_UPLOAD}, + {" --upload-flags ", + "Specify additional upload behaviour", + CURLHELP_CURL | CURLHELP_OUTPUT}, {" --url ", "URL to work with", CURLHELP_CURL}, diff --git a/src/tool_operate.c b/src/tool_operate.c index da807ab857..7ab5a39000 100644 --- a/src/tool_operate.c +++ b/src/tool_operate.c @@ -1756,6 +1756,9 @@ static CURLcode config2setopts(struct GlobalConfig *global, } #endif } + /* new in 8.12.0 */ + if(config->upload_flags) + my_setopt(curl, CURLOPT_UPLOAD_FLAGS, config->upload_flags); return result; } diff --git a/src/tool_setopt.c b/src/tool_setopt.c index 52ae0f9607..2d2b3b1e68 100644 --- a/src/tool_setopt.c +++ b/src/tool_setopt.c @@ -164,6 +164,7 @@ static const struct NameValue setopt_nv_CURLNONZERODEFAULTS[] = { NV1(CURLOPT_PROXY_SSL_VERIFYPEER, 1), NV1(CURLOPT_PROXY_SSL_VERIFYHOST, 1), NV1(CURLOPT_SOCKS5_AUTH, 1), + NV1(CURLOPT_UPLOAD_FLAGS, CURLUPLOADFLAG_SEEN), NVEND }; diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am index f915a3630c..2cdb3515d5 100644 --- a/tests/data/Makefile.am +++ b/tests/data/Makefile.am @@ -271,6 +271,6 @@ test3024 test3025 test3026 test3027 test3028 test3029 test3030 test3031 \ \ test3100 test3101 test3102 test3103 test3104 test3105 \ test3200 \ -test3201 test3202 test3203 test3204 test3205 test3207 +test3201 test3202 test3203 test3204 test3205 test3207 test3208 test3209 EXTRA_DIST = $(TESTCASES) DISABLED diff --git a/tests/data/test3208 b/tests/data/test3208 new file mode 100644 index 0000000000..4ca0bfa140 --- /dev/null +++ b/tests/data/test3208 @@ -0,0 +1,63 @@ + + + +IMAP +Clear Text +APPEND +UPLOAD + + + +# +# Server-side + + + +# +# Client-side + + +imap + + +Upload message unread via IMAP + + +imap://%HOSTIP:%IMAPPORT/%TESTNUMBER -T %LOGDIR/upload%TESTNUMBER -u user:secret --upload-flags !Seen + + +Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST) +From: Fred Foobar +Subject: afternoon meeting +To: joe@example.com +Message-Id: +MIME-Version: 1.0 +Content-Type: TEXT/PLAIN; CHARSET=US-ASCII + +Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + + + +# +# Verify data after the test has been "shot" + + +A001 CAPABILITY +A002 LOGIN user secret +A003 APPEND %TESTNUMBER {356} +A004 LOGOUT + + +Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST) +From: Fred Foobar +Subject: afternoon meeting +To: joe@example.com +Message-Id: +MIME-Version: 1.0 +Content-Type: TEXT/PLAIN; CHARSET=US-ASCII + +Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + + + + diff --git a/tests/data/test3209 b/tests/data/test3209 new file mode 100644 index 0000000000..1f64480893 --- /dev/null +++ b/tests/data/test3209 @@ -0,0 +1,63 @@ + + + +IMAP +Clear Text +APPEND +UPLOAD + + + +# +# Server-side + + + +# +# Client-side + + +imap + + +Upload message via IMAP with upload flags + + +imap://%HOSTIP:%IMAPPORT/%TESTNUMBER -T %LOGDIR/upload%TESTNUMBER -u user:secret --upload-flags Answered,Deleted,Draft,Flagged,Seen + + +Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST) +From: Fred Foobar +Subject: afternoon meeting +To: joe@example.com +Message-Id: +MIME-Version: 1.0 +Content-Type: TEXT/PLAIN; CHARSET=US-ASCII + +Hello Joe, do you think we can meet at 3:30 tomorrow? + + + +# +# Verify data after the test has been "shot" + + +A001 CAPABILITY +A002 LOGIN user secret +A003 APPEND %TESTNUMBER (\Answered \Deleted \Draft \Flagged \Seen) {286} +A004 LOGOUT + + +Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST) +From: Fred Foobar +Subject: afternoon meeting +To: joe@example.com +Message-Id: +MIME-Version: 1.0 +Content-Type: TEXT/PLAIN; CHARSET=US-ASCII + +Hello Joe, do you think we can meet at 3:30 tomorrow? + + + + From 3794c006525a599f3da65fdeb587a6db7477547b Mon Sep 17 00:00:00 2001 From: tiymat <138939221+tiymat@users.noreply.github.com> Date: Tue, 14 Jan 2025 22:58:59 -0330 Subject: [PATCH 02/16] imap: Fix build errors, refactor IMAP append logic --- docs/cmdline-opts/upload-flags.md | 2 +- docs/libcurl/opts/CURLOPT_UPLOAD_FLAGS.md | 16 ++-- docs/libcurl/symbols-in-versions | 13 ++- docs/options-in-versions | 2 +- include/curl/curl.h | 13 +-- lib/imap.c | 109 +++++++--------------- lib/urldata.h | 2 +- src/tool_cfgable.c | 2 +- src/tool_cfgable.h | 2 +- src/tool_getparam.c | 76 +++++++-------- src/tool_operate.c | 2 +- src/tool_setopt.c | 2 +- tests/data/test3208 | 2 +- tests/data/test3209 | 2 +- 14 files changed, 98 insertions(+), 147 deletions(-) diff --git a/docs/cmdline-opts/upload-flags.md b/docs/cmdline-opts/upload-flags.md index 80cad4baa1..43808d223f 100644 --- a/docs/cmdline-opts/upload-flags.md +++ b/docs/cmdline-opts/upload-flags.md @@ -5,7 +5,7 @@ Long: upload-flags Arg: Help: Specify additional upload behaviour Category: curl output -Added: 8.12.0 +Added: 8.13.0 Multi: single See-also: - upload-file diff --git a/docs/libcurl/opts/CURLOPT_UPLOAD_FLAGS.md b/docs/libcurl/opts/CURLOPT_UPLOAD_FLAGS.md index 2208f3ec95..d55e95bfec 100644 --- a/docs/libcurl/opts/CURLOPT_UPLOAD_FLAGS.md +++ b/docs/libcurl/opts/CURLOPT_UPLOAD_FLAGS.md @@ -9,7 +9,7 @@ See-also: Protocol: - IMAP - IMAPS -Added-in: 8.12.0 +Added-in: 8.13.0 --- # NAME @@ -28,15 +28,15 @@ CURLcode curl_easy_setopt(CURL *handle, CURLOPT_UPLOAD_FLAGS, long bitmask); Pass a long as parameter, which is set to a bitmask, to tell libcurl which flags to send the server relating to uploaded files. The current supported -flags are *CURLUPLOADFLAG_ANSWERED*, which sets the *Answered* flag for IMAP -uploads, *CURLUPLOADFLAG_DELETED*, which sets the *Deleted* flag for IMAP -uploads, *CURLUPLOADFLAG_DRAFT*, which sets the *Draft* flag for IMAP uploads, -*CURLUPLOADFLAG_FLAGGED*, which sets the *Flagged* flag for IMAP uploads, and -*CURLUPLOADFLAG_SEEN*, which sets the *Seen* flag for IMAP uploads. +flags are *CURLULFLAG_ANSWERED*, which sets the *Answered* flag for IMAP +uploads, *CURLULFLAG_DELETED*, which sets the *Deleted* flag for IMAP +uploads, *CURLULFLAG_DRAFT*, which sets the *Draft* flag for IMAP uploads, +*CURLULFLAG_FLAGGED*, which sets the *Flagged* flag for IMAP uploads, and +*CURLULFLAG_SEEN*, which sets the *Seen* flag for IMAP uploads. # DEFAULT -A bitmask with only the CURLUPLOADFLAG_SEEN flag set. +A bitmask with only the CURLULFLAG_SEEN flag set. # %PROTOCOLS% @@ -76,7 +76,7 @@ int main(void) curl_easy_setopt(curl, CURLOPT_PASSWORD, "password"); /* specify that uploaded mail should be considered flagged */ - curl_easy_setopt(curl, CURLOPT_UPLOAD_FLAGS, CURLOPTUPLOADFLAG_FLAGGED); + curl_easy_setopt(curl, CURLOPT_UPLOAD_FLAGS, CURLULFLAG_FLAGGED); /* now specify which pointer to pass to our callback */ curl_easy_setopt(curl, CURLOPT_READDATA, src); diff --git a/docs/libcurl/symbols-in-versions b/docs/libcurl/symbols-in-versions index e437f91047..51cfb9bf12 100644 --- a/docs/libcurl/symbols-in-versions +++ b/docs/libcurl/symbols-in-versions @@ -891,7 +891,7 @@ CURLOPT_UNRESTRICTED_AUTH 7.10.4 CURLOPT_UPKEEP_INTERVAL_MS 7.62.0 CURLOPT_UPLOAD 7.1 CURLOPT_UPLOAD_BUFFERSIZE 7.62.0 -CURLOPT_UPLOAD_FLAGS 8.12.0 +CURLOPT_UPLOAD_FLAGS 8.13.0 CURLOPT_URL 7.1 CURLOPT_USE_SSL 7.17.0 CURLOPT_USERAGENT 7.1 @@ -1125,12 +1125,11 @@ CURLUPART_SCHEME 7.62.0 CURLUPART_URL 7.62.0 CURLUPART_USER 7.62.0 CURLUPART_ZONEID 7.65.0 -CURLUPLOADFLAG_ANSWERED 8.12.0 -CURLUPLOADFLAG_DELETED 8.12.0 -CURLUPLOADFLAG_DRAFT 8.12.0 -CURLUPLOADFLAG_FLAGGED 8.12.0 -CURLUPLOADFLAG_MAX_LEN 8.12.0 -CURLUPLOADFLAG_SEEN 8.12.0 +CURLULFLAG_ANSWERED 8.13.0 +CURLULFLAG_DELETED 8.13.0 +CURLULFLAG_DRAFT 8.13.0 +CURLULFLAG_FLAGGED 8.13.0 +CURLULFLAG_SEEN 8.13.0 CURLUSESSL_ALL 7.17.0 CURLUSESSL_CONTROL 7.17.0 CURLUSESSL_NONE 7.17.0 diff --git a/docs/options-in-versions b/docs/options-in-versions index d0f70df420..fceff631bf 100644 --- a/docs/options-in-versions +++ b/docs/options-in-versions @@ -266,7 +266,7 @@ --trace-time 7.14.0 --unix-socket 7.40.0 --upload-file (-T) 4.0 ---upload-flags 8.12.0 +--upload-flags 8.13.0 --url 7.5 --url-query 7.87.0 --use-ascii (-B) 5.0 diff --git a/include/curl/curl.h b/include/curl/curl.h index 88d69c9d0d..f130b767ff 100644 --- a/include/curl/curl.h +++ b/include/curl/curl.h @@ -1016,14 +1016,11 @@ typedef enum { #define CURLALTSVC_H3 (1<<5) /* bitmask values for CURLOPT_UPLOAD_FLAGS */ -#define CURLUPLOADFLAG_ANSWERED (1<<0) -#define CURLUPLOADFLAG_DELETED (1<<1) -#define CURLUPLOADFLAG_DRAFT (1<<2) -#define CURLUPLOADFLAG_FLAGGED (1<<3) -#define CURLUPLOADFLAG_SEEN (1<<4) - -/* max allowable flag length for a CURLOPT_UPLOAD_FLAGS flag */ -#define CURLUPLOADFLAG_MAX_LEN 20 +#define CURLULFLAG_ANSWERED (1<<0) +#define CURLULFLAG_DELETED (1<<1) +#define CURLULFLAG_DRAFT (1<<2) +#define CURLULFLAG_FLAGGED (1<<3) +#define CURLULFLAG_SEEN (1<<4) struct curl_hstsentry { char *name; diff --git a/lib/imap.c b/lib/imap.c index 6999948855..538dfecaa3 100644 --- a/lib/imap.c +++ b/lib/imap.c @@ -36,6 +36,7 @@ ***************************************************************************/ #include "curl_setup.h" +#include "dynbuf.h" #ifndef CURL_DISABLE_IMAP @@ -190,6 +191,11 @@ static const struct SASLproto saslimap = { SASL_FLAG_BASE64 /* Configuration flags */ }; +struct ulbits { + int bit; + const char *flag; +}; + #ifdef USE_SSL static void imap_to_imaps(struct connectdata *conn) @@ -765,7 +771,7 @@ static CURLcode imap_perform_append(struct Curl_easy *data) CURLcode result = CURLE_OK; struct IMAP *imap = data->req.p.imap; char *mailbox; - bool first_flag = TRUE; + struct dynbuf flags; /* Check we have a mailbox */ if(!imap->mailbox) { @@ -815,91 +821,44 @@ static CURLcode imap_perform_append(struct Curl_easy *data) return CURLE_OUT_OF_MEMORY; /* Generate flags string and send the APPEND command */ + Curl_dyn_init(&flags, 100); if(data->set.upload_flags) { - struct dynbuf flags; - Curl_dyn_init(&flags, 100); - if(Curl_dyn_add(&flags, "(")) { - result = CURLE_OUT_OF_MEMORY; + struct ulbits ulflag[] = { + {CURLULFLAG_ANSWERED, "Answered"}, + {CURLULFLAG_DELETED, "Deleted"}, + {CURLULFLAG_DRAFT, "Draft"}, + {CURLULFLAG_FLAGGED, "Flagged"}, + {CURLULFLAG_SEEN, "Seen"}, + {0, NULL} + }; + + result = CURLE_OUT_OF_MEMORY; + if(Curl_dyn_add(&flags, " (")) { goto cleanup; } - if(data->set.upload_flags & CURLUPLOADFLAG_ANSWERED) { - if(first_flag) - first_flag = FALSE; - else if(Curl_dyn_add(&flags, " ")) { - result = CURLE_OUT_OF_MEMORY; - goto cleanup; - } - if(Curl_dyn_add(&flags, "\\Answered")) { - result = CURLE_OUT_OF_MEMORY; - goto cleanup; - } - } - if(data->set.upload_flags & CURLUPLOADFLAG_DELETED) { - if(first_flag) - first_flag = FALSE; - else if(Curl_dyn_add(&flags, " ")) { - result = CURLE_OUT_OF_MEMORY; - goto cleanup; - } - if(Curl_dyn_add(&flags, "\\Deleted")) { - result = CURLE_OUT_OF_MEMORY; - goto cleanup; - } - } - if(data->set.upload_flags & CURLUPLOADFLAG_DRAFT) { - if(first_flag) - first_flag = FALSE; - else if(Curl_dyn_add(&flags, " ")) { - result = CURLE_OUT_OF_MEMORY; - goto cleanup; - } - if(Curl_dyn_add(&flags, "\\Draft")) { - result = CURLE_OUT_OF_MEMORY; - goto cleanup; - } - } - if(data->set.upload_flags & CURLUPLOADFLAG_FLAGGED) { - if(first_flag) - first_flag = FALSE; - else if(Curl_dyn_add(&flags, " ")) { - result = CURLE_OUT_OF_MEMORY; - goto cleanup; - } - if(Curl_dyn_add(&flags, "\\Flagged")) { - result = CURLE_OUT_OF_MEMORY; - goto cleanup; - } - } - if(data->set.upload_flags & CURLUPLOADFLAG_SEEN) { - if(first_flag) - first_flag = FALSE; - else if(Curl_dyn_add(&flags, " ")) { - result = CURLE_OUT_OF_MEMORY; - goto cleanup; - } - if(Curl_dyn_add(&flags, "\\Seen")) { - result = CURLE_OUT_OF_MEMORY; - goto cleanup; + for(int i = 0; ulflag[i].bit; i++) { + if(data->set.upload_flags & ulflag[i].bit) { + if(Curl_dyn_len(&flags)) { + if(Curl_dyn_len(&flags) > 2 && Curl_dyn_add(&flags, " ")) + goto cleanup; + } + if(Curl_dyn_add(&flags, "\\") || Curl_dyn_add(&flags, ulflag[i].flag)) + goto cleanup; } } - if(Curl_dyn_add(&flags, ")")) { - result = CURLE_OUT_OF_MEMORY; + if(Curl_dyn_add(&flags, ")")) goto cleanup; - } + } + else if(Curl_dyn_add(&flags, "")) + goto cleanup; - result = imap_sendf(data, "APPEND %s %s {%" FMT_OFF_T "}", - mailbox, Curl_dyn_ptr(&flags), data->state.infilesize); + result = imap_sendf(data, "APPEND %s%s {%" FMT_OFF_T "}", + mailbox, Curl_dyn_ptr(&flags), data->state.infilesize); cleanup: - Curl_dyn_free(&flags); - } - else{ - result = imap_sendf(data, "APPEND %s {%" FMT_OFF_T "}", - mailbox, data->state.infilesize); - } - + Curl_dyn_free(&flags); free(mailbox); if(!result) diff --git a/lib/urldata.h b/lib/urldata.h index d785ff811e..4bada41426 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -1610,6 +1610,7 @@ struct UserDefined { unsigned char method; /* what kind of HTTP request: Curl_HttpReq */ unsigned char httpwant; /* when non-zero, a specific HTTP version requested to be used in the library's request(s) */ + unsigned char upload_flags; struct ssl_config_data ssl; /* user defined SSL stuff */ #ifndef CURL_DISABLE_PROXY struct ssl_config_data proxy_ssl; /* user defined SSL stuff for proxy */ @@ -1822,7 +1823,6 @@ struct UserDefined { #ifdef USE_ECH int tls_ech; /* TLS ECH configuration */ #endif - long upload_flags; }; #ifndef CURL_DISABLE_MIME diff --git a/src/tool_cfgable.c b/src/tool_cfgable.c index a10e392b1a..3de7cbd921 100644 --- a/src/tool_cfgable.c +++ b/src/tool_cfgable.c @@ -45,7 +45,7 @@ void config_init(struct OperationConfig *config) config->http09_allowed = FALSE; config->ftp_skip_ip = TRUE; config->file_clobber_mode = CLOBBER_DEFAULT; - config->upload_flags = CURLUPLOADFLAG_SEEN; + config->upload_flags = CURLULFLAG_SEEN; curlx_dyn_init(&config->postdata, MAX_FILE2MEMORY); } diff --git a/src/tool_cfgable.h b/src/tool_cfgable.h index bb0d8c9fac..2c786ed5a4 100644 --- a/src/tool_cfgable.h +++ b/src/tool_cfgable.h @@ -310,7 +310,7 @@ struct OperationConfig { char *ech; /* Config set by --ech keywords */ char *ech_config; /* Config set by "--ech esl:" option */ char *ech_public; /* Config set by "--ech pn:" option */ - unsigned long upload_flags; /* Bitmask for --upload-flags */ + unsigned char upload_flags; /* Bitmask for --upload-flags */ }; struct GlobalConfig { diff --git a/src/tool_getparam.c b/src/tool_getparam.c index 571d10cd9d..60e2184539 100644 --- a/src/tool_getparam.c +++ b/src/tool_getparam.c @@ -1565,55 +1565,51 @@ static ParameterError parse_time_cond(struct GlobalConfig *global, static ParameterError parse_upload_flags(struct OperationConfig *config, char *nextarg) { - struct Curl_str segment; + char *tmp, *upload_flag; ParameterError err = PARAM_OK; - bool negative = FALSE; + size_t flag_len; - while(!Curl_str_until(&nextarg, &segment, CURLUPLOADFLAG_MAX_LEN, ',')) { - negative = !Curl_str_single(&segment.str, '!'); - if(negative) - --segment.len; /* The leading '!' was removed in Curl_str_single */ + tmp = strdup(nextarg); + if(!tmp) + return PARAM_NO_MEM; - if(segment.len == 8 && !strncmp(segment.str, "Answered", segment.len)) { - if(negative) - config->upload_flags &= ~CURLUPLOADFLAG_ANSWERED; - else - config->upload_flags |= CURLUPLOADFLAG_ANSWERED; - } - else if(segment.len == 7 && !strncmp(segment.str, "Deleted", - segment.len)) { - if(negative) - config->upload_flags &= ~CURLUPLOADFLAG_DELETED; - else - config->upload_flags |= CURLUPLOADFLAG_DELETED; - } - else if(segment.len == 5 && !strncmp(segment.str, "Draft", segment.len)) { - if(negative) - config->upload_flags &= ~CURLUPLOADFLAG_DRAFT; - else - config->upload_flags |= CURLUPLOADFLAG_DRAFT; - } - else if(segment.len == 7 && - !strncmp(segment.str, "Flagged", segment.len)) { - if(negative) - config->upload_flags &= ~CURLUPLOADFLAG_FLAGGED; - else - config->upload_flags |= CURLUPLOADFLAG_FLAGGED; - } - else if(segment.len == 4 && !strncmp(segment.str, "Seen", segment.len)) { - if(negative) - config->upload_flags &= ~CURLUPLOADFLAG_SEEN; - else - config->upload_flags |= CURLUPLOADFLAG_SEEN; - } - else{ + /* Allow strtok() here since this is not used threaded */ + /* !checksrc! disable BANNEDFUNC 2 */ + upload_flag = strtok(tmp, ","); + + while(upload_flag) { + flag_len = strlen(upload_flag); + + if(flag_len == 8 && !strncmp(upload_flag, "Answered", 8)) + config->upload_flags |= CURLULFLAG_ANSWERED; + else if(flag_len == 9 && !strncmp(upload_flag, "!Answered", 9)) + config->upload_flags &= ~CURLULFLAG_ANSWERED; + else if(flag_len == 7 && !strncmp(upload_flag, "Deleted", 7)) + config->upload_flags |= CURLULFLAG_DELETED; + else if(flag_len == 8 && !strncmp(upload_flag, "!Deleted", 8)) + config->upload_flags &= ~CURLULFLAG_DELETED; + else if(flag_len == 5 && !strncmp(upload_flag, "Draft", 5)) + config->upload_flags |= CURLULFLAG_DRAFT; + else if(flag_len == 6 && !strncmp(upload_flag, "!Draft", 6)) + config->upload_flags &= ~CURLULFLAG_DRAFT; + else if(flag_len == 7 && !strncmp(upload_flag, "Flagged", 7)) + config->upload_flags |= CURLULFLAG_FLAGGED; + else if(flag_len == 8 && !strncmp(upload_flag, "!Flagged", 8)) + config->upload_flags &= ~CURLULFLAG_FLAGGED; + else if(flag_len == 4 && !strncmp(upload_flag, "Seen", 4)) + config->upload_flags |= CURLULFLAG_SEEN; + else if(flag_len == 5 && !strncmp(upload_flag, "!Seen", 5)) + config->upload_flags &= ~CURLULFLAG_SEEN; + else { err = PARAM_OPTION_UNKNOWN; break; } - Curl_str_single(&nextarg, ','); + upload_flag = strtok(NULL, ","); } + free(tmp); + return err; } diff --git a/src/tool_operate.c b/src/tool_operate.c index 7ab5a39000..57be20a099 100644 --- a/src/tool_operate.c +++ b/src/tool_operate.c @@ -1756,7 +1756,7 @@ static CURLcode config2setopts(struct GlobalConfig *global, } #endif } - /* new in 8.12.0 */ + /* new in 8.13.0 */ if(config->upload_flags) my_setopt(curl, CURLOPT_UPLOAD_FLAGS, config->upload_flags); return result; diff --git a/src/tool_setopt.c b/src/tool_setopt.c index 2d2b3b1e68..942e659a49 100644 --- a/src/tool_setopt.c +++ b/src/tool_setopt.c @@ -164,7 +164,7 @@ static const struct NameValue setopt_nv_CURLNONZERODEFAULTS[] = { NV1(CURLOPT_PROXY_SSL_VERIFYPEER, 1), NV1(CURLOPT_PROXY_SSL_VERIFYHOST, 1), NV1(CURLOPT_SOCKS5_AUTH, 1), - NV1(CURLOPT_UPLOAD_FLAGS, CURLUPLOADFLAG_SEEN), + NV1(CURLOPT_UPLOAD_FLAGS, CURLULFLAG_SEEN), NVEND }; diff --git a/tests/data/test3208 b/tests/data/test3208 index 4ca0bfa140..973d3b2591 100644 --- a/tests/data/test3208 +++ b/tests/data/test3208 @@ -41,7 +41,7 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor i # # Verify data after the test has been "shot" - + A001 CAPABILITY A002 LOGIN user secret A003 APPEND %TESTNUMBER {356} diff --git a/tests/data/test3209 b/tests/data/test3209 index 1f64480893..ffb0a979ab 100644 --- a/tests/data/test3209 +++ b/tests/data/test3209 @@ -41,7 +41,7 @@ Hello Joe, do you think we can meet at 3:30 tomorrow? # # Verify data after the test has been "shot" - + A001 CAPABILITY A002 LOGIN user secret A003 APPEND %TESTNUMBER (\Answered \Deleted \Draft \Flagged \Seen) {286} From e09a8e7ded8278d6355978ee7330d3c31c08543c Mon Sep 17 00:00:00 2001 From: tiymat <138939221+tiymat@users.noreply.github.com> Date: Fri, 17 Jan 2025 00:27:01 -0330 Subject: [PATCH 03/16] imap: explicitly cast upload flag arg --- lib/imap.c | 7 ++----- lib/setopt.c | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/imap.c b/lib/imap.c index 538dfecaa3..19a5b9f17c 100644 --- a/lib/imap.c +++ b/lib/imap.c @@ -839,11 +839,8 @@ static CURLcode imap_perform_append(struct Curl_easy *data) for(int i = 0; ulflag[i].bit; i++) { if(data->set.upload_flags & ulflag[i].bit) { - if(Curl_dyn_len(&flags)) { - if(Curl_dyn_len(&flags) > 2 && Curl_dyn_add(&flags, " ")) - goto cleanup; - } - if(Curl_dyn_add(&flags, "\\") || Curl_dyn_add(&flags, ulflag[i].flag)) + if((Curl_dyn_len(&flags) > 2 && Curl_dyn_add(&flags, " ")) || + Curl_dyn_add(&flags, "\\") || Curl_dyn_add(&flags, ulflag[i].flag)) goto cleanup; } } diff --git a/lib/setopt.c b/lib/setopt.c index 23feaf7c80..1991506795 100644 --- a/lib/setopt.c +++ b/lib/setopt.c @@ -1404,7 +1404,7 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option, Curl_safefree(data->set.str[STRING_SSL_ENGINE]); return Curl_ssl_set_engine_default(data); case CURLOPT_UPLOAD_FLAGS: - data->set.upload_flags = arg; + data->set.upload_flags = (unsigned char)arg; break; default: /* unknown option */ From c6ca0b2ffc73e6cb451a1721b14bbfa260146820 Mon Sep 17 00:00:00 2001 From: tiymat <138939221+tiymat@users.noreply.github.com> Date: Fri, 17 Jan 2025 17:26:39 -0330 Subject: [PATCH 04/16] Re-generate easyoptions.c and remove unneeded strparse include --- lib/easyoptions.c | 2 +- src/tool_getparam.c | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/easyoptions.c b/lib/easyoptions.c index b444010439..be617b5d2a 100644 --- a/lib/easyoptions.c +++ b/lib/easyoptions.c @@ -378,6 +378,6 @@ struct curl_easyoption Curl_easyopts[] = { */ int Curl_easyopts_check(void) { - return ((CURLOPT_LASTENTRY%10000) != (327 + 1)); + return (CURLOPT_LASTENTRY % 10000) != (327 + 1); } #endif diff --git a/src/tool_getparam.c b/src/tool_getparam.c index 60e2184539..df90997aac 100644 --- a/src/tool_getparam.c +++ b/src/tool_getparam.c @@ -41,7 +41,6 @@ #include "tool_main.h" #include "dynbuf.h" #include "tool_stderr.h" -#include "strparse.h" #include "var.h" #include "memdebug.h" /* keep this as LAST include */ From 9e3fb7ae9bc0d5172f8a114a498a1d7958c7fee2 Mon Sep 17 00:00:00 2001 From: tiymat <138939221+tiymat@users.noreply.github.com> Date: Tue, 21 Jan 2025 19:40:18 -0330 Subject: [PATCH 05/16] docs: Add upload flags page to Makefile --- docs/libcurl/opts/Makefile.inc | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/libcurl/opts/Makefile.inc b/docs/libcurl/opts/Makefile.inc index 9d8606dd06..24f668cb07 100644 --- a/docs/libcurl/opts/Makefile.inc +++ b/docs/libcurl/opts/Makefile.inc @@ -411,6 +411,7 @@ man_MANS = \ CURLOPT_UPKEEP_INTERVAL_MS.3 \ CURLOPT_UPLOAD.3 \ CURLOPT_UPLOAD_BUFFERSIZE.3 \ + CURLOPT_UPLOAD_FLAGS.3 \ CURLOPT_URL.3 \ CURLOPT_USE_SSL.3 \ CURLOPT_USERAGENT.3 \ From 0ad29e0521ab9c1302e2e29ad128fcb2a381efdb Mon Sep 17 00:00:00 2001 From: tiymat <138939221+tiymat@users.noreply.github.com> Date: Wed, 5 Feb 2025 00:15:47 -0330 Subject: [PATCH 06/16] imap: fix loop variable declaration --- lib/imap.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/imap.c b/lib/imap.c index 19a5b9f17c..f67c797456 100644 --- a/lib/imap.c +++ b/lib/imap.c @@ -823,6 +823,7 @@ static CURLcode imap_perform_append(struct Curl_easy *data) /* Generate flags string and send the APPEND command */ Curl_dyn_init(&flags, 100); if(data->set.upload_flags) { + int i; struct ulbits ulflag[] = { {CURLULFLAG_ANSWERED, "Answered"}, {CURLULFLAG_DELETED, "Deleted"}, @@ -837,7 +838,7 @@ static CURLcode imap_perform_append(struct Curl_easy *data) goto cleanup; } - for(int i = 0; ulflag[i].bit; i++) { + for(i = 0; ulflag[i].bit; i++) { if(data->set.upload_flags & ulflag[i].bit) { if((Curl_dyn_len(&flags) > 2 && Curl_dyn_add(&flags, " ")) || Curl_dyn_add(&flags, "\\") || Curl_dyn_add(&flags, ulflag[i].flag)) From 399465b12739b19d1ae10bada5558ba62cc1d57a Mon Sep 17 00:00:00 2001 From: tiymat <138939221+tiymat@users.noreply.github.com> Date: Wed, 5 Feb 2025 17:40:19 -0330 Subject: [PATCH 07/16] tests: removed trailing newline from 3208 and 3209 --- tests/data/test3208 | 1 - tests/data/test3209 | 1 - 2 files changed, 2 deletions(-) diff --git a/tests/data/test3208 b/tests/data/test3208 index 973d3b2591..9bdc3323b7 100644 --- a/tests/data/test3208 +++ b/tests/data/test3208 @@ -60,4 +60,3 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor i - diff --git a/tests/data/test3209 b/tests/data/test3209 index ffb0a979ab..9ca4313f9f 100644 --- a/tests/data/test3209 +++ b/tests/data/test3209 @@ -60,4 +60,3 @@ Hello Joe, do you think we can meet at 3:30 tomorrow? - From 2ea14cd1721eba875b421dab633fd9078006e50b Mon Sep 17 00:00:00 2001 From: tiymat <138939221+tiymat@users.noreply.github.com> Date: Wed, 5 Feb 2025 17:41:02 -0330 Subject: [PATCH 08/16] docs: American spelling of 'behaviour' --- docs/cmdline-opts/upload-flags.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/cmdline-opts/upload-flags.md b/docs/cmdline-opts/upload-flags.md index 43808d223f..b935f3f261 100644 --- a/docs/cmdline-opts/upload-flags.md +++ b/docs/cmdline-opts/upload-flags.md @@ -3,7 +3,7 @@ c: Copyright (C) Daniel Stenberg, , et al. SPDX-License-Identifier: curl Long: upload-flags Arg: -Help: Specify additional upload behaviour +Help: Specify additional upload behavior Category: curl output Added: 8.13.0 Multi: single @@ -15,7 +15,7 @@ Example: # `--upload-flags` -Specify additional behaviour to apply to uploaded files. Flags are +Specify additional behavior to apply to uploaded files. Flags are specified as either a single flag value or a comma-separated list of flag values. Flag values may be negated by prepending them with a '!' character. Currently the following case-sensitive flag values From 358e9f21905d8122f81416888d79c260160822dd Mon Sep 17 00:00:00 2001 From: tiymat <138939221+tiymat@users.noreply.github.com> Date: Wed, 5 Feb 2025 17:41:59 -0330 Subject: [PATCH 09/16] docs: bolded CURLULFLAG properly so the spellchecker ignores it --- docs/libcurl/opts/CURLOPT_UPLOAD_FLAGS.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/libcurl/opts/CURLOPT_UPLOAD_FLAGS.md b/docs/libcurl/opts/CURLOPT_UPLOAD_FLAGS.md index d55e95bfec..b74a9b7a7d 100644 --- a/docs/libcurl/opts/CURLOPT_UPLOAD_FLAGS.md +++ b/docs/libcurl/opts/CURLOPT_UPLOAD_FLAGS.md @@ -28,11 +28,11 @@ CURLcode curl_easy_setopt(CURL *handle, CURLOPT_UPLOAD_FLAGS, long bitmask); Pass a long as parameter, which is set to a bitmask, to tell libcurl which flags to send the server relating to uploaded files. The current supported -flags are *CURLULFLAG_ANSWERED*, which sets the *Answered* flag for IMAP -uploads, *CURLULFLAG_DELETED*, which sets the *Deleted* flag for IMAP -uploads, *CURLULFLAG_DRAFT*, which sets the *Draft* flag for IMAP uploads, -*CURLULFLAG_FLAGGED*, which sets the *Flagged* flag for IMAP uploads, and -*CURLULFLAG_SEEN*, which sets the *Seen* flag for IMAP uploads. +flags are **CURLULFLAG_ANSWERED**, which sets the **Answered** flag for IMAP +uploads, **CURLULFLAG_DELETED**, which sets the **Deleted** flag for IMAP +uploads, **CURLULFLAG_DRAFT**, which sets the **Draft** flag for IMAP uploads, +**CURLULFLAG_FLAGGED**, which sets the **Flagged** flag for IMAP uploads, and +**CURLULFLAG_SEEN**, which sets the **Seen** flag for IMAP uploads. # DEFAULT From b4831282ef8a9042ed9745bbdf2c569460cf344c Mon Sep 17 00:00:00 2001 From: tiymat <138939221+tiymat@users.noreply.github.com> Date: Wed, 5 Feb 2025 19:28:44 -0330 Subject: [PATCH 10/16] src: Regenerate tool_listhelp.c --- src/tool_listhelp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tool_listhelp.c b/src/tool_listhelp.c index 7b6c68fa19..7871010237 100644 --- a/src/tool_listhelp.c +++ b/src/tool_listhelp.c @@ -809,7 +809,7 @@ const struct helptxt helptext[] = { "Transfer local FILE to destination", CURLHELP_IMPORTANT | CURLHELP_UPLOAD}, {" --upload-flags ", - "Specify additional upload behaviour", + "Specify additional upload behavior", CURLHELP_CURL | CURLHELP_OUTPUT}, {" --url ", "URL to work with", From 4df0aedbeeedc3fdaa7a9f559290031e2f02db6c Mon Sep 17 00:00:00 2001 From: tiymat <138939221+tiymat@users.noreply.github.com> Date: Wed, 5 Feb 2025 23:59:46 -0330 Subject: [PATCH 11/16] imap: Changed data type of CURLULFLAGS from int to unsigned char --- include/curl/curl.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/curl/curl.h b/include/curl/curl.h index f130b767ff..d1a4ad77d4 100644 --- a/include/curl/curl.h +++ b/include/curl/curl.h @@ -1016,11 +1016,11 @@ typedef enum { #define CURLALTSVC_H3 (1<<5) /* bitmask values for CURLOPT_UPLOAD_FLAGS */ -#define CURLULFLAG_ANSWERED (1<<0) -#define CURLULFLAG_DELETED (1<<1) -#define CURLULFLAG_DRAFT (1<<2) -#define CURLULFLAG_FLAGGED (1<<3) -#define CURLULFLAG_SEEN (1<<4) +#define CURLULFLAG_ANSWERED (((unsigned char)1)<<0) +#define CURLULFLAG_DELETED (((unsigned char)1)<<1) +#define CURLULFLAG_DRAFT (((unsigned char)1)<<2) +#define CURLULFLAG_FLAGGED (((unsigned char)1)<<3) +#define CURLULFLAG_SEEN (((unsigned char)1)<<4) struct curl_hstsentry { char *name; From 89314ecb4e41152e56f55c16e37052d1b7db543c Mon Sep 17 00:00:00 2001 From: tiymat <138939221+tiymat@users.noreply.github.com> Date: Sat, 8 Feb 2025 00:32:14 -0330 Subject: [PATCH 12/16] tool_getparam.c: fix uncasted negation --- src/tool_getparam.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/tool_getparam.c b/src/tool_getparam.c index c1a89faa66..1bbc26f819 100644 --- a/src/tool_getparam.c +++ b/src/tool_getparam.c @@ -1580,23 +1580,23 @@ static ParameterError parse_upload_flags(struct OperationConfig *config, if(flag_len == 8 && !strncmp(upload_flag, "Answered", 8)) config->upload_flags |= CURLULFLAG_ANSWERED; else if(flag_len == 9 && !strncmp(upload_flag, "!Answered", 9)) - config->upload_flags &= ~CURLULFLAG_ANSWERED; + config->upload_flags &= (unsigned char)~CURLULFLAG_ANSWERED; else if(flag_len == 7 && !strncmp(upload_flag, "Deleted", 7)) config->upload_flags |= CURLULFLAG_DELETED; else if(flag_len == 8 && !strncmp(upload_flag, "!Deleted", 8)) - config->upload_flags &= ~CURLULFLAG_DELETED; + config->upload_flags &= (unsigned char)~CURLULFLAG_DELETED; else if(flag_len == 5 && !strncmp(upload_flag, "Draft", 5)) config->upload_flags |= CURLULFLAG_DRAFT; else if(flag_len == 6 && !strncmp(upload_flag, "!Draft", 6)) - config->upload_flags &= ~CURLULFLAG_DRAFT; + config->upload_flags &= (unsigned char)~CURLULFLAG_DRAFT; else if(flag_len == 7 && !strncmp(upload_flag, "Flagged", 7)) config->upload_flags |= CURLULFLAG_FLAGGED; else if(flag_len == 8 && !strncmp(upload_flag, "!Flagged", 8)) - config->upload_flags &= ~CURLULFLAG_FLAGGED; + config->upload_flags &= (unsigned char)~CURLULFLAG_FLAGGED; else if(flag_len == 4 && !strncmp(upload_flag, "Seen", 4)) config->upload_flags |= CURLULFLAG_SEEN; else if(flag_len == 5 && !strncmp(upload_flag, "!Seen", 5)) - config->upload_flags &= ~CURLULFLAG_SEEN; + config->upload_flags &= (unsigned char)~CURLULFLAG_SEEN; else { err = PARAM_OPTION_UNKNOWN; break; From cfaf7ff49a48443df7e8d24ebbeb83b8ed5a9066 Mon Sep 17 00:00:00 2001 From: tiymat <138939221+tiymat@users.noreply.github.com> Date: Sat, 8 Feb 2025 12:00:46 -0330 Subject: [PATCH 13/16] docs: Bolded remaining CURLULFLAG in docs --- docs/libcurl/opts/CURLOPT_UPLOAD_FLAGS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/libcurl/opts/CURLOPT_UPLOAD_FLAGS.md b/docs/libcurl/opts/CURLOPT_UPLOAD_FLAGS.md index b74a9b7a7d..10327eeb2f 100644 --- a/docs/libcurl/opts/CURLOPT_UPLOAD_FLAGS.md +++ b/docs/libcurl/opts/CURLOPT_UPLOAD_FLAGS.md @@ -36,7 +36,7 @@ uploads, **CURLULFLAG_DRAFT**, which sets the **Draft** flag for IMAP uploads, # DEFAULT -A bitmask with only the CURLULFLAG_SEEN flag set. +A bitmask with only the **CURLULFLAG_SEEN** flag set. # %PROTOCOLS% From ad5834e9f390a62dedc66f795ccf66ab3da32a9a Mon Sep 17 00:00:00 2001 From: tiymat <138939221+tiymat@users.noreply.github.com> Date: Sun, 9 Feb 2025 01:48:07 -0330 Subject: [PATCH 14/16] tool_operate: cast upload_flags properly --- src/tool_operate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tool_operate.c b/src/tool_operate.c index 6352fe2a96..1f2c120992 100644 --- a/src/tool_operate.c +++ b/src/tool_operate.c @@ -1758,7 +1758,7 @@ static CURLcode config2setopts(struct GlobalConfig *global, } /* new in 8.13.0 */ if(config->upload_flags) - my_setopt(curl, CURLOPT_UPLOAD_FLAGS, config->upload_flags); + my_setopt(curl, CURLOPT_UPLOAD_FLAGS, (long)config->upload_flags); return result; } From 8b992f61c9ffe26e51a00c1c2b508a81c988b11f Mon Sep 17 00:00:00 2001 From: tiymat <138939221+tiymat@users.noreply.github.com> Date: Sun, 9 Feb 2025 02:29:44 -0330 Subject: [PATCH 15/16] tests: move test3208 for merge --- tests/data/{test3208 => test3210} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/data/{test3208 => test3210} (100%) diff --git a/tests/data/test3208 b/tests/data/test3210 similarity index 100% rename from tests/data/test3208 rename to tests/data/test3210 From 0a5d368eab91b9560643d674e82bd4dec0c3aec3 Mon Sep 17 00:00:00 2001 From: tiymat <138939221+tiymat@users.noreply.github.com> Date: Sun, 9 Feb 2025 02:33:07 -0330 Subject: [PATCH 16/16] tests: fix moved test in Makefile --- tests/data/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am index 464437af39..f2255a2a17 100644 --- a/tests/data/Makefile.am +++ b/tests/data/Makefile.am @@ -272,6 +272,6 @@ test3032 \ \ test3100 test3101 test3102 test3103 test3104 test3105 \ test3200 \ -test3201 test3202 test3203 test3204 test3205 test3207 test3208 test3209 +test3201 test3202 test3203 test3204 test3205 test3207 test3209 test3210 EXTRA_DIST = $(TESTCASES) DISABLED