@@ -127,3 +127,11 @@
#endif
#endif
+
+/**
+ * CURLOPT_PROTOCOLS_STR was added in 7.83.0, released in August
+ * 2022.
+ */
+#if LIBCURL_VERSION_NUM >= 0x075500
+#define GIT_CURL_HAVE_CURLOPT_PROTOCOLS_STR 1
+#endif
@@ -198,13 +198,13 @@ static void curl_setup_http(CURL *curl, const char *url,
const char *custom_req, struct buffer *buffer,
curl_write_callback write_fn)
{
- curl_easy_setopt(curl, CURLOPT_PUT, 1);
+ curl_easy_setopt(curl, CURLOPT_UPLOAD, 1);
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_INFILE, buffer);
curl_easy_setopt(curl, CURLOPT_INFILESIZE, buffer->buf.len);
curl_easy_setopt(curl, CURLOPT_READFUNCTION, fread_buffer);
- curl_easy_setopt(curl, CURLOPT_IOCTLFUNCTION, ioctl_buffer);
- curl_easy_setopt(curl, CURLOPT_IOCTLDATA, buffer);
+ curl_easy_setopt(curl, CURLOPT_SEEKFUNCTION, ioctl_buffer);
+ curl_easy_setopt(curl, CURLOPT_SEEKDATA, buffer);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_fn);
curl_easy_setopt(curl, CURLOPT_NOBODY, 0);
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, custom_req);
@@ -157,21 +157,12 @@ size_t fread_buffer(char *ptr, size_t eltsize, size_t nmemb, void *buffer_)
return size / eltsize;
}
-curlioerr ioctl_buffer(CURL *handle, int cmd, void *clientp)
+int ioctl_buffer(void *userp, curl_off_t offset, int origin)
{
- struct buffer *buffer = clientp;
+ struct buffer *buffer = userp;
- switch (cmd) {
- case CURLIOCMD_NOP:
- return CURLIOE_OK;
-
- case CURLIOCMD_RESTARTREAD:
- buffer->posn = 0;
- return CURLIOE_OK;
-
- default:
- return CURLIOE_UNKNOWNCMD;
- }
+ buffer->posn = 0;
+ return CURL_SEEKFUNC_OK;
}
size_t fwrite_buffer(char *ptr, size_t eltsize, size_t nmemb, void *buffer_)
@@ -765,7 +756,52 @@ void setup_curl_trace(CURL *handle)
curl_easy_setopt(handle, CURLOPT_DEBUGFUNCTION, curl_trace);
curl_easy_setopt(handle, CURLOPT_DEBUGDATA, NULL);
}
+#ifdef GIT_CURL_HAVE_CURLOPT_PROTOCOLS_STR
+static void get_curl_allowed_protocols(int from_user, char *protocol)
+{
+ unsigned int i = 0;
+
+ if (is_transport_allowed("http", from_user)) {
+ protocol[i++] = 'h';
+ protocol[i++] = 't';
+ protocol[i++] = 't';
+ protocol[i++] = 'p';
+ }
+
+ if (is_transport_allowed("https", from_user)) {
+ if (i != 0) {
+ protocol[i++] = ',';
+ }
+
+ protocol[i++] = 'h';
+ protocol[i++] = 't';
+ protocol[i++] = 't';
+ protocol[i++] = 'p';
+ protocol[i++] = 's';
+ }
+ if (is_transport_allowed("ftp", from_user)) {
+ if (i != 0) {
+ protocol[i++] = ',';
+ }
+ protocol[i++] = 'f';
+ protocol[i++] = 't';
+ protocol[i++] = 'p';
+ }
+ if (is_transport_allowed("ftps", from_user)) {
+ if (i != 0) {
+ protocol[i++] = ',';
+ }
+
+ protocol[i++] = 'f';
+ protocol[i++] = 't';
+ protocol[i++] = 'p';
+ protocol[i++] = 's';
+ }
+
+ protocol[i] = '\0';
+}
+#else
static long get_curl_allowed_protocols(int from_user)
{
long allowed_protocols = 0;
@@ -781,6 +817,7 @@ static long get_curl_allowed_protocols(int from_user)
return allowed_protocols;
}
+#endif
#ifdef GIT_CURL_HAVE_CURL_HTTP_VERSION_2
static int get_curl_http_version_opt(const char *version_string, long *opt)
@@ -810,6 +847,9 @@ static int get_curl_http_version_opt(const char *version_string, long *opt)
static CURL *get_curl_handle(void)
{
CURL *result = curl_easy_init();
+#ifdef GIT_CURL_HAVE_CURLOPT_PROTOCOLS_STR
+ static char protocol[20], redir_protocol[20];
+#endif
if (!result)
die("curl_easy_init failed");
@@ -923,10 +963,18 @@ static CURL *get_curl_handle(void)
curl_easy_setopt(result, CURLOPT_MAXREDIRS, 20);
curl_easy_setopt(result, CURLOPT_POSTREDIR, CURL_REDIR_POST_ALL);
+#ifdef GIT_CURL_HAVE_CURLOPT_PROTOCOLS_STR
+ get_curl_allowed_protocols(0, redir_protocol);
+ curl_easy_setopt(result, CURLOPT_REDIR_PROTOCOLS_STR, redir_protocol);
+ get_curl_allowed_protocols(-1, protocol);
+ curl_easy_setopt(result, CURLOPT_PROTOCOLS_STR, protocol);
+#else
curl_easy_setopt(result, CURLOPT_REDIR_PROTOCOLS,
get_curl_allowed_protocols(0));
curl_easy_setopt(result, CURLOPT_PROTOCOLS,
get_curl_allowed_protocols(-1));
+#endif
+
if (getenv("GIT_CURL_VERBOSE"))
http_trace_curl_no_data();
setup_curl_trace(result);
@@ -40,7 +40,7 @@ struct buffer {
size_t fread_buffer(char *ptr, size_t eltsize, size_t nmemb, void *strbuf);
size_t fwrite_buffer(char *ptr, size_t eltsize, size_t nmemb, void *strbuf);
size_t fwrite_null(char *ptr, size_t eltsize, size_t nmemb, void *strbuf);
-curlioerr ioctl_buffer(CURL *handle, int cmd, void *clientp);
+int ioctl_buffer(void *userp, curl_off_t offset, int origin);
/* Slot lifecycle functions */
struct active_request_slot *get_active_slot(void);
@@ -717,25 +717,17 @@ static size_t rpc_out(void *ptr, size_t eltsize,
return avail;
}
-static curlioerr rpc_ioctl(CURL *handle, int cmd, void *clientp)
+static int rpc_ioctl(void *userp, curl_off_t offset, int origin)
{
- struct rpc_state *rpc = clientp;
+ struct rpc_state *rpc = userp;
- switch (cmd) {
- case CURLIOCMD_NOP:
- return CURLIOE_OK;
-
- case CURLIOCMD_RESTARTREAD:
- if (rpc->initial_buffer) {
- rpc->pos = 0;
- return CURLIOE_OK;
- }
- error(_("unable to rewind rpc post data - try increasing http.postBuffer"));
- return CURLIOE_FAILRESTART;
-
- default:
- return CURLIOE_UNKNOWNCMD;
+ if (rpc->initial_buffer) {
+ rpc->pos = 0;
+ return CURL_SEEKFUNC_OK;
}
+
+ error(_("unable to rewind rpc post data - try increasing http.postBuffer"));
+ return CURL_SEEKFUNC_FAIL;
}
struct check_pktline_state {
@@ -959,8 +951,8 @@ retry:
rpc->initial_buffer = 1;
curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, rpc_out);
curl_easy_setopt(slot->curl, CURLOPT_INFILE, rpc);
- curl_easy_setopt(slot->curl, CURLOPT_IOCTLFUNCTION, rpc_ioctl);
- curl_easy_setopt(slot->curl, CURLOPT_IOCTLDATA, rpc);
+ curl_easy_setopt(slot->curl, CURLOPT_SEEKFUNCTION, rpc_ioctl);
+ curl_easy_setopt(slot->curl, CURLOPT_SEEKDATA, rpc);
if (options.verbosity > 1) {
fprintf(stderr, "POST %s (chunked)\n", rpc->service_name);
fflush(stderr);