From 9eb0439d55f4b47286a42a6b731d36884ae79cdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Cs=C3=A1rdi?= Date: Wed, 18 Dec 2024 23:43:57 +0100 Subject: [PATCH] Update embedded curl to 5.2.3 (#728) * Update embedded curl to 5.2.3 * Patch curl to compile on FreeBSD --- src/library/curl/DESCRIPTION | 14 +- src/library/curl/NAMESPACE | 1 - src/library/curl/NEWS | 18 ++ src/library/curl/R/email.R | 11 +- src/library/curl/R/handle.R | 21 +- src/library/curl/configure | 18 +- src/library/curl/src/Makevars.in | 2 +- src/library/curl/src/Makevars.win | 2 +- src/library/curl/src/callbacks.c | 18 +- src/library/curl/src/curl.c | 24 +- src/library/curl/src/download.c | 28 +- src/library/curl/src/escape.c | 8 +- src/library/curl/src/fetch.c | 22 +- src/library/curl/src/findport.c | 2 +- src/library/curl/src/form.c | 30 +- src/library/curl/src/getdate.c | 8 +- src/library/curl/src/handle.c | 145 +++++----- src/library/curl/src/ieproxy.c | 68 ++--- src/library/curl/src/init.c | 1 - src/library/curl/src/multi.c | 72 ++--- src/library/curl/src/nslookup.c | 6 +- src/library/curl/src/reflist.c | 8 +- src/library/curl/src/split.c | 6 +- src/library/curl/src/utils.c | 18 +- src/library/curl/src/version.c | 44 +-- src/library/curl/src/writer.c | 6 +- src/library/curl/vignettes/intro.Rmd | 403 --------------------------- 27 files changed, 316 insertions(+), 688 deletions(-) delete mode 100644 src/library/curl/vignettes/intro.Rmd diff --git a/src/library/curl/DESCRIPTION b/src/library/curl/DESCRIPTION index 8a0afcc0a..d30f08985 100644 --- a/src/library/curl/DESCRIPTION +++ b/src/library/curl/DESCRIPTION @@ -1,9 +1,9 @@ Package: curl Type: Package Title: A Modern and Flexible Web Client for R -Version: 5.2.0 +Version: 5.2.3 Authors@R: c( - person("Jeroen", "Ooms", role = c("aut", "cre"), email = "jeroen@berkeley.edu", + person("Jeroen", "Ooms", role = c("aut", "cre"), email = "jeroenooms@gmail.com", comment = c(ORCID = "0000-0002-4035-0289")), person("Hadley", "Wickham", , "hadley@rstudio.com", role = "ctb"), person("RStudio", role = "cph") @@ -23,17 +23,17 @@ SystemRequirements: libcurl: libcurl-devel (rpm) or URL: https://jeroen.r-universe.dev/curl https://curl.se/libcurl/ BugReports: https://github.com/jeroen/curl/issues Suggests: spelling, testthat (>= 1.0.0), knitr, jsonlite, later, - rmarkdown, magrittr, httpuv (>= 1.4.4), webutils + rmarkdown, httpuv (>= 1.4.4), webutils VignetteBuilder: knitr Depends: R (>= 3.0.0) -RoxygenNote: 7.2.3 +RoxygenNote: 7.3.0 Encoding: UTF-8 Language: en-US NeedsCompilation: yes -Packaged: 2023-12-07 23:07:08 UTC; jeroen +Packaged: 2024-09-19 15:43:51 UTC; jeroen Author: Jeroen Ooms [aut, cre] (), Hadley Wickham [ctb], RStudio [cph] -Maintainer: Jeroen Ooms +Maintainer: Jeroen Ooms Repository: CRAN -Date/Publication: 2023-12-08 07:30:02 UTC +Date/Publication: 2024-09-20 11:50:24 UTC diff --git a/src/library/curl/NAMESPACE b/src/library/curl/NAMESPACE index b3ce75e16..3cd613d39 100644 --- a/src/library/curl/NAMESPACE +++ b/src/library/curl/NAMESPACE @@ -64,7 +64,6 @@ useDynLib(curl,R_handle_getcustom) useDynLib(curl,R_handle_getheaders) useDynLib(curl,R_handle_reset) useDynLib(curl,R_handle_setform) -useDynLib(curl,R_handle_setheaders) useDynLib(curl,R_handle_setopt) useDynLib(curl,R_multi_add) useDynLib(curl,R_multi_cancel) diff --git a/src/library/curl/NEWS b/src/library/curl/NEWS index ca33b30ce..67f8f1a3d 100644 --- a/src/library/curl/NEWS +++ b/src/library/curl/NEWS @@ -1,3 +1,21 @@ +5.2.3 + - Remove some CMD check verbosity per new CRAN rules + - New maintainer email address + +5.2.2 + - Disable a compression test for libcurl 8.7.1 which has a bug for deflate + - Change a unit test to work around firewall problems on CRANs WinBuilder + +5.2.1 + - In handle_setheader(), setting a header to a non-empty whitespace string will + now send a blank header. Using an empty string will still remove the header + altogether (this has not changed). + - Internally simplify handle_setheader() as a wrapper for handle_setopt(httpheader) + - Fix an issue where curl_fetch_stream() might not return all bytes received + by the C layer if the server closed the connection mid-response. + - No longer enable CURLOPT_UNRESTRICTED_AUTH by default + - Fix code to build with -DR_NO_REMAP (add all the Rf_ prefixes) + 5.2.0 - The CURL_CA_BUNDLE envvar is now also used on non-Windows. - curl_echo() now uses a random available port to run httpuv diff --git a/src/library/curl/R/email.R b/src/library/curl/R/email.R index 92b649822..955f41682 100644 --- a/src/library/curl/R/email.R +++ b/src/library/curl/R/email.R @@ -19,6 +19,13 @@ #' By default, the port will be 25, unless \code{smtps://} is specified--then #' the default will be 465 instead. #' +#' For internet SMTP servers you probably need to pass a +#' \href{https://curl.se/libcurl/c/CURLOPT_USERNAME.html}{username} and +#' \href{https://curl.se/libcurl/c/CURLOPT_PASSWORD.html}{passwords} option. +#' For some servers you also need to pass a string with +#' \href{https://curl.se/libcurl/c/CURLOPT_LOGIN_OPTIONS.html}{login_options} +#' for example \code{login_options="AUTH=NTLM"}. +#' #' @section Encrypting connections via SMTPS or STARTTLS: #' #' There are two different ways in which SMTP can be encrypted: SMTPS servers @@ -51,8 +58,8 @@ #' for details. Default will try to SSL, proceed as normal otherwise. #' @param verbose print output #' @param ... other options passed to \code{\link{handle_setopt}}. In most cases -#' you will need to set a \code{username} and \code{password} to authenticate -#' with the SMTP server. +#' you will need to set a \code{username} and \code{password} or \code{login_options} +#' to authenticate with the SMTP server, see details. #' @examples \dontrun{# Set sender and recipients (email addresses only) #' recipients <- readline("Enter your email address to receive test: ") #' sender <- 'test@noreply.com' diff --git a/src/library/curl/R/handle.R b/src/library/curl/R/handle.R index 02c4d7cbf..af96da528 100644 --- a/src/library/curl/R/handle.R +++ b/src/library/curl/R/handle.R @@ -69,20 +69,21 @@ handle_setopt <- function(handle, ..., .list = list()){ } #' @export -#' @useDynLib curl R_handle_setheaders #' @rdname handle handle_setheaders <- function(handle, ..., .list = list()){ - stopifnot(inherits(handle, "curl_handle")) - opts <- c(list(...), .list) - if(!all(vapply(opts, is.character, logical(1)))){ + x <- c(list(...), .list) + if(!all(vapply(x, is.character, logical(1)))){ stop("All headers must be strings.") } - opts$Expect = "" - names <- names(opts) - values <- as.character(unlist(opts)) - vec <- paste0(names, ": ", values) - .Call(R_handle_setheaders, handle, vec) - invisible(handle) + handle_setopt(handle, httpheader = format_request_headers(x)) +} + +format_request_headers <- function(x){ + x$Expect = "" + names <- names(x) + values <- as.character(unlist(x)) + postfix <- ifelse(grepl("^\\s+$", values), ";", paste(":", values)) + paste0(names, postfix) } #' @useDynLib curl R_handle_getheaders diff --git a/src/library/curl/configure b/src/library/curl/configure index 6912c42b3..153309a23 100755 --- a/src/library/curl/configure +++ b/src/library/curl/configure @@ -64,21 +64,21 @@ if [ $? -ne 0 ]; then exit 1 fi -# Hack for MacOS 11 which has newer headers than the libcurl lib -# if [ `uname` = "Darwin" ]; then -# MACVERSION=`sw_vers -productVersion` || true -# case "$MACVERSION" in -# "11"*) -# PKG_CFLAGS="$PKG_CFLAGS -DDISABLE_CURL_EASY_OPTION";; -# esac -# fi +# Disable purling on oldrel due to https://github.com/yihui/knitr/issues/2338 +if [ `uname` = "Darwin" ] && [ "${R_VERSION}" = "4.3.3" ]; then + for file in vignettes/*.Rmd; do + sed -i '' '/```/,$d' $file || true + touch inst/doc/* || true + done +fi # Write to Makevars sed -e "s|@cflags@|$PKG_CFLAGS|" -e "s|@libs@|$PKG_LIBS|" src/Makevars.in > src/Makevars # Extract curlopt symbols echo '#include ' | ${CC} ${CPPFLAGS} ${PKG_CFLAGS} ${CFLAGS} -E -xc - \ - | grep "^[ \t]*CURLOPT_.*," | sed s/,// > tools/option_table.txt + | grep "^[ \t]*CURLOPT_.*," | sed s/,// | sed 's/__attribute__[(][(].*[)][)] =/=/' \ + > tools/option_table.txt # Success exit 0 diff --git a/src/library/curl/src/Makevars.in b/src/library/curl/src/Makevars.in index 07959ac6e..8d833e2ef 100644 --- a/src/library/curl/src/Makevars.in +++ b/src/library/curl/src/Makevars.in @@ -1,5 +1,5 @@ PKG_CFLAGS=$(C_VISIBILITY) -PKG_CPPFLAGS=@cflags@ -DSTRICT_R_HEADERS +PKG_CPPFLAGS=@cflags@ -DSTRICT_R_HEADERS -DR_NO_REMAP PKG_LIBS=@libs@ all: clean diff --git a/src/library/curl/src/Makevars.win b/src/library/curl/src/Makevars.win index aebb10428..8019d6287 100644 --- a/src/library/curl/src/Makevars.win +++ b/src/library/curl/src/Makevars.win @@ -7,7 +7,7 @@ PKG_LIBS = \ -lwinhttp -lcurl -lnghttp2 -lssh2 -lz -lssl -lcrypto -pthread -lgdi32 -lws2_32 -lcrypt32 -lbcrypt -lwldap32 PKG_CPPFLAGS= \ - -I$(RWINLIB)/include -DCURL_STATICLIB -DSTRICT_R_HEADERS + -I$(RWINLIB)/include -DCURL_STATICLIB -DSTRICT_R_HEADERS -DR_NO_REMAP all: clean winlibs diff --git a/src/library/curl/src/callbacks.c b/src/library/curl/src/callbacks.c index babe93e89..a01dfe158 100644 --- a/src/library/curl/src/callbacks.c +++ b/src/library/curl/src/callbacks.c @@ -4,11 +4,11 @@ int R_curl_callback_progress(SEXP fun, double dltotal, double dlnow, double ultotal, double ulnow) { - SEXP down = PROTECT(allocVector(REALSXP, 2)); + SEXP down = PROTECT(Rf_allocVector(REALSXP, 2)); REAL(down)[0] = dltotal; REAL(down)[1] = dlnow; - SEXP up = PROTECT(allocVector(REALSXP, 2)); + SEXP up = PROTECT(Rf_allocVector(REALSXP, 2)); REAL(up)[0] = ultotal; REAL(up)[1] = ulnow; @@ -21,19 +21,19 @@ int R_curl_callback_progress(SEXP fun, return CURL_READFUNC_ABORT; } - if (TYPEOF(res) != LGLSXP || length(res) != 1) { + if (TYPEOF(res) != LGLSXP || Rf_length(res) != 1) { UNPROTECT(4); Rf_warning("progress callback must return boolean"); return 0; } - int out = asLogical(res); + int out = Rf_asLogical(res); UNPROTECT(4); return !out; } size_t R_curl_callback_read(char *buffer, size_t size, size_t nitems, SEXP fun) { - SEXP nbytes = PROTECT(ScalarInteger(size * nitems)); + SEXP nbytes = PROTECT(Rf_ScalarInteger(size * nitems)); SEXP call = PROTECT(Rf_lang2(fun, nbytes)); int ok; @@ -50,7 +50,7 @@ size_t R_curl_callback_read(char *buffer, size_t size, size_t nitems, SEXP fun) return CURL_READFUNC_ABORT; } - size_t bytes_read = length(res); + size_t bytes_read = Rf_length(res); memcpy(buffer, RAW(res), bytes_read); UNPROTECT(3); @@ -59,7 +59,7 @@ size_t R_curl_callback_read(char *buffer, size_t size, size_t nitems, SEXP fun) /* origin is always SEEK_SET in libcurl, not really useful to pass on */ int R_curl_callback_seek(SEXP fun, curl_off_t offset, int origin){ - SEXP soffset = PROTECT(ScalarReal(offset)); + SEXP soffset = PROTECT(Rf_ScalarReal(offset)); SEXP call = PROTECT(Rf_lang2(fun, soffset)); int ok; R_tryEval(call, R_GlobalEnv, &ok); @@ -71,8 +71,8 @@ int R_curl_callback_debug(CURL *handle, curl_infotype type_, char *data, size_t size, SEXP fun) { /* wrap type and msg into R types */ - SEXP type = PROTECT(ScalarInteger(type_)); - SEXP msg = PROTECT(allocVector(RAWSXP, size)); + SEXP type = PROTECT(Rf_ScalarInteger(type_)); + SEXP msg = PROTECT(Rf_allocVector(RAWSXP, size)); memcpy(RAW(msg), data, size); /* call the R function */ diff --git a/src/library/curl/src/curl.c b/src/library/curl/src/curl.c index b23837852..29b3d6600 100644 --- a/src/library/curl/src/curl.c +++ b/src/library/curl/src/curl.c @@ -77,7 +77,7 @@ static size_t push(void *contents, size_t sz, size_t nmemb, void *ctx) { //Rprintf("Resizing buffer to %d.\n", newlimit); void *newbuf = realloc(req->buf, newlimit); if(!newbuf) - error("Failure in realloc. Out of memory?"); + Rf_error("Failure in realloc. Out of memory?"); req->buf = newbuf; req->limit = newlimit; } @@ -130,6 +130,16 @@ static size_t rcurl_read(void *target, size_t sz, size_t ni, Rconnection con) { /* append data to the target buffer */ size_t total_size = pop(target, req_size, req); + + if (total_size > 0 && (!con->blocking || req->partial)) { + // If we can return data without waiting, and the connection is + // non-blocking (or using curl_fetch_stream()), do so. + // This ensures that bytes we already received get flushed + // to the target buffer before a connection error. + con->incomplete = req->has_more || req->size; + return total_size; + } + while((req_size > total_size) && req->has_more) { /* wait for activity, timeout or "nothing" */ #ifdef HAS_MULTI_WAIT @@ -246,14 +256,14 @@ static Rboolean rcurl_open(Rconnection con) { } SEXP R_curl_connection(SEXP url, SEXP ptr, SEXP partial) { - if(!isString(url)) - error("Argument 'url' must be string."); + if(!Rf_isString(url)) + Rf_error("Argument 'url' must be string."); /* create the R connection object, mimicking base::url() */ Rconnection con; /* R wants description in native encoding, but we use UTF-8 URL below */ - SEXP rc = PROTECT(R_new_custom_connection(translateChar(STRING_ELT(url, 0)), "r", "curl", &con)); + SEXP rc = PROTECT(R_new_custom_connection(Rf_translateChar(STRING_ELT(url, 0)), "r", "curl", &con)); /* setup curl. These are the parts that are recycable. */ request *req = malloc(sizeof(request)); @@ -262,12 +272,12 @@ SEXP R_curl_connection(SEXP url, SEXP ptr, SEXP partial) { req->limit = CURL_MAX_WRITE_SIZE; req->buf = malloc(req->limit); req->manager = curl_multi_init(); - req->partial = asLogical(partial); //only for curl_fetch_stream() + req->partial = Rf_asLogical(partial); //only for curl_fetch_stream() req->used = 0; /* allocate url string */ - req->url = malloc(strlen(translateCharUTF8(asChar(url))) + 1); - strcpy(req->url, translateCharUTF8(asChar(url))); + req->url = malloc(strlen(Rf_translateCharUTF8(Rf_asChar(url))) + 1); + strcpy(req->url, Rf_translateCharUTF8(Rf_asChar(url))); /* set connection properties */ con->incomplete = FALSE; diff --git a/src/library/curl/src/download.c b/src/library/curl/src/download.c index fb0471f73..1f149aa42 100644 --- a/src/library/curl/src/download.c +++ b/src/library/curl/src/download.c @@ -4,35 +4,35 @@ #include "curl-common.h" SEXP R_download_curl(SEXP url, SEXP destfile, SEXP quiet, SEXP mode, SEXP ptr, SEXP nonblocking) { - if(!isString(url)) - error("Argument 'url' must be string."); + if(!Rf_isString(url)) + Rf_error("Argument 'url' must be string."); - if(!isString(destfile)) - error("Argument 'destfile' must be string."); + if(!Rf_isString(destfile)) + Rf_error("Argument 'destfile' must be string."); - if(!isLogical(quiet)) - error("Argument 'quiet' must be TRUE/FALSE."); + if(!Rf_isLogical(quiet)) + Rf_error("Argument 'quiet' must be TRUE/FALSE."); - if(!isString(mode)) - error("Argument 'mode' must be string."); + if(!Rf_isString(mode)) + Rf_error("Argument 'mode' must be string."); /* get the handle */ CURL *handle = get_handle(ptr); reset_errbuf(get_ref(ptr)); /* open file */ - FILE *dest = fopen(CHAR(asChar(destfile)), CHAR(asChar(mode))); + FILE *dest = fopen(CHAR(Rf_asChar(destfile)), CHAR(Rf_asChar(mode))); if(!dest) - error("Failed to open file %s.", CHAR(asChar(destfile))); + Rf_error("Failed to open file %s.", CHAR(Rf_asChar(destfile))); /* set options */ - curl_easy_setopt(handle, CURLOPT_URL, translateCharUTF8(asChar(url))); - curl_easy_setopt(handle, CURLOPT_NOPROGRESS, asLogical(quiet)); + curl_easy_setopt(handle, CURLOPT_URL, Rf_translateCharUTF8(Rf_asChar(url))); + curl_easy_setopt(handle, CURLOPT_NOPROGRESS, Rf_asLogical(quiet)); curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, push_disk); curl_easy_setopt(handle, CURLOPT_WRITEDATA, dest); /* perform blocking request */ - CURLcode status = asLogical(nonblocking) ? + CURLcode status = Rf_asLogical(nonblocking) ? curl_perform_with_interrupt(handle) : curl_easy_perform(handle); /* cleanup */ @@ -47,5 +47,5 @@ SEXP R_download_curl(SEXP url, SEXP destfile, SEXP quiet, SEXP mode, SEXP ptr, S /* check for success */ stop_for_status(handle); - return ScalarInteger(0); + return Rf_ScalarInteger(0); } diff --git a/src/library/curl/src/escape.c b/src/library/curl/src/escape.c index d6d48b6ae..ce2d0b695 100644 --- a/src/library/curl/src/escape.c +++ b/src/library/curl/src/escape.c @@ -3,17 +3,17 @@ SEXP R_curl_escape(SEXP url, SEXP unescape_) { if (!Rf_isString(url)) - error("`url` must be a character vector."); + Rf_error("`url` must be a character vector."); CURL *handle = curl_easy_init(); int n = Rf_length(url); - SEXP output = PROTECT(allocVector(STRSXP, n)); + SEXP output = PROTECT(Rf_allocVector(STRSXP, n)); for (int i = 0; i < n; i++) { const char *input = CHAR(STRING_ELT(url, i)); - char *out = asLogical(unescape_) ? + char *out = Rf_asLogical(unescape_) ? curl_easy_unescape(handle, input, 0, NULL) : curl_easy_escape(handle, input, 0); if(out != NULL){ - SET_STRING_ELT(output, i, mkCharCE(out, CE_UTF8)); + SET_STRING_ELT(output, i, Rf_mkCharCE(out, CE_UTF8)); curl_free(out); } } diff --git a/src/library/curl/src/fetch.c b/src/library/curl/src/fetch.c index 75f167512..cb515fe9f 100644 --- a/src/library/curl/src/fetch.c +++ b/src/library/curl/src/fetch.c @@ -6,8 +6,8 @@ #include "curl-common.h" SEXP R_curl_fetch_memory(SEXP url, SEXP ptr, SEXP nonblocking){ - if (!isString(url) || length(url) != 1) - error("Argument 'url' must be string."); + if (!Rf_isString(url) || Rf_length(url) != 1) + Rf_error("Argument 'url' must be string."); /* get the handle */ CURL *handle = get_handle(ptr); @@ -25,7 +25,7 @@ SEXP R_curl_fetch_memory(SEXP url, SEXP ptr, SEXP nonblocking){ curl_easy_setopt(handle, CURLOPT_WRITEDATA, &body); /* perform blocking request */ - CURLcode status = asLogical(nonblocking) ? + CURLcode status = Rf_asLogical(nonblocking) ? curl_perform_with_interrupt(handle) : curl_easy_perform(handle); /* Reset for reuse */ @@ -39,7 +39,7 @@ SEXP R_curl_fetch_memory(SEXP url, SEXP ptr, SEXP nonblocking){ } /* create output */ - SEXP out = PROTECT(allocVector(RAWSXP, body.size)); + SEXP out = PROTECT(Rf_allocVector(RAWSXP, body.size)); /* copy only if there is actual content */ if(body.size) @@ -52,10 +52,10 @@ SEXP R_curl_fetch_memory(SEXP url, SEXP ptr, SEXP nonblocking){ } SEXP R_curl_fetch_disk(SEXP url, SEXP ptr, SEXP path, SEXP mode, SEXP nonblocking){ - if (!isString(url) || length(url) != 1) - error("Argument 'url' must be string."); - if (!isString(path) || length(path) != 1) - error("`path` must be string."); + if (!Rf_isString(url) || Rf_length(url) != 1) + Rf_error("Argument 'url' must be string."); + if (!Rf_isString(path) || Rf_length(path) != 1) + Rf_error("`path` must be string."); /* get the handle */ CURL *handle = get_handle(ptr); @@ -68,14 +68,14 @@ SEXP R_curl_fetch_disk(SEXP url, SEXP ptr, SEXP path, SEXP mode, SEXP nonblockin reset_errbuf(get_ref(ptr)); /* open file */ - FILE *dest = fopen(CHAR(asChar(path)), CHAR(asChar(mode))); + FILE *dest = fopen(CHAR(Rf_asChar(path)), CHAR(Rf_asChar(mode))); if(!dest) - error("Failed to open file %s.", CHAR(asChar(path))); + Rf_error("Failed to open file %s.", CHAR(Rf_asChar(path))); curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, push_disk); curl_easy_setopt(handle, CURLOPT_WRITEDATA, dest); /* perform blocking request */ - CURLcode status = asLogical(nonblocking) ? + CURLcode status = Rf_asLogical(nonblocking) ? curl_perform_with_interrupt(handle): curl_easy_perform(handle); /* cleanup */ diff --git a/src/library/curl/src/findport.c b/src/library/curl/src/findport.c index 29b871de9..e69c655dc 100644 --- a/src/library/curl/src/findport.c +++ b/src/library/curl/src/findport.c @@ -76,7 +76,7 @@ SEXP R_findport(SEXP candidates){ for(int i = 0; i < Rf_length(candidates); i++){ int port = INTEGER(candidates)[i]; if(port_is_available(port)){ - return ScalarInteger(port); + return Rf_ScalarInteger(port); } } return R_NilValue; diff --git a/src/library/curl/src/form.c b/src/library/curl/src/form.c index d2a788b5c..47cc278b2 100644 --- a/src/library/curl/src/form.c +++ b/src/library/curl/src/form.c @@ -3,9 +3,9 @@ struct curl_httppost* make_form(SEXP form){ struct curl_httppost* post = NULL; struct curl_httppost* last = NULL; - SEXP ln = PROTECT(getAttrib(form, R_NamesSymbol)); - for(int i = 0; i < length(form); i++){ - const char *name = translateCharUTF8(STRING_ELT(ln, i)); + SEXP ln = PROTECT(Rf_getAttrib(form, R_NamesSymbol)); + for(int i = 0; i < Rf_length(form); i++){ + const char *name = Rf_translateCharUTF8(STRING_ELT(ln, i)); SEXP val = VECTOR_ELT(form, i); if(TYPEOF(val) == RAWSXP){ long datalen = Rf_length(val); @@ -16,21 +16,21 @@ struct curl_httppost* make_form(SEXP form){ //Note if 'CURLFORM_CONTENTLEN == 0' then libcurl assumes strlen() ! curl_formadd(&post, &last, CURLFORM_COPYNAME, name, CURLFORM_COPYCONTENTS, "", CURLFORM_END); } - } else if(isVector(val) && Rf_length(val)){ - if(isString(VECTOR_ELT(val, 0))){ + } else if(Rf_isVector(val) && Rf_length(val)){ + if(Rf_isString(VECTOR_ELT(val, 0))){ //assume a form_file upload - const char *path = CHAR(asChar(VECTOR_ELT(val, 0))); - if(isString(VECTOR_ELT(val, 1))) { - const char *content_type = CHAR(asChar(VECTOR_ELT(val, 1))); - if(isString(VECTOR_ELT(val, 2))) { - const char *file_name = CHAR(asChar(VECTOR_ELT(val, 2))); + const char *path = CHAR(Rf_asChar(VECTOR_ELT(val, 0))); + if(Rf_isString(VECTOR_ELT(val, 1))) { + const char *content_type = CHAR(Rf_asChar(VECTOR_ELT(val, 1))); + if(Rf_isString(VECTOR_ELT(val, 2))) { + const char *file_name = CHAR(Rf_asChar(VECTOR_ELT(val, 2))); curl_formadd(&post, &last, CURLFORM_COPYNAME, name, CURLFORM_FILE, path, CURLFORM_CONTENTTYPE, content_type, CURLFORM_FILENAME, file_name, CURLFORM_END); } else { curl_formadd(&post, &last, CURLFORM_COPYNAME, name, CURLFORM_FILE, path, CURLFORM_CONTENTTYPE, content_type, CURLFORM_END); } } else { - if(isString(VECTOR_ELT(val, 2))) { - const char *file_name = CHAR(asChar(VECTOR_ELT(val, 2))); + if(Rf_isString(VECTOR_ELT(val, 2))) { + const char *file_name = CHAR(Rf_asChar(VECTOR_ELT(val, 2))); curl_formadd(&post, &last, CURLFORM_COPYNAME, name, CURLFORM_FILE, path, CURLFORM_FILENAME, file_name, CURLFORM_END); } else { curl_formadd(&post, &last, CURLFORM_COPYNAME, name, CURLFORM_FILE, path, CURLFORM_END); @@ -40,15 +40,15 @@ struct curl_httppost* make_form(SEXP form){ //assume a form_value upload unsigned char * data = RAW(VECTOR_ELT(val, 0)); long datalen = Rf_length(VECTOR_ELT(val, 0)); - if(isString(VECTOR_ELT(val, 1))){ - const char * content_type = CHAR(asChar(VECTOR_ELT(val, 1))); + if(Rf_isString(VECTOR_ELT(val, 1))){ + const char * content_type = CHAR(Rf_asChar(VECTOR_ELT(val, 1))); curl_formadd(&post, &last, CURLFORM_COPYNAME, name, CURLFORM_COPYCONTENTS, data, CURLFORM_CONTENTSLENGTH, datalen, CURLFORM_CONTENTTYPE, content_type, CURLFORM_END); } else { curl_formadd(&post, &last, CURLFORM_COPYNAME, name, CURLFORM_COPYCONTENTS, data, CURLFORM_CONTENTSLENGTH, datalen, CURLFORM_END); } } } else { - error("form value %s not supported", name); + Rf_error("form value %s not supported", name); } } UNPROTECT(1); diff --git a/src/library/curl/src/getdate.c b/src/library/curl/src/getdate.c index 40f5495f5..edeb3c224 100644 --- a/src/library/curl/src/getdate.c +++ b/src/library/curl/src/getdate.c @@ -2,11 +2,11 @@ #include SEXP R_curl_getdate(SEXP datestring) { - if(!isString(datestring)) - error("Argument 'datestring' must be string."); + if(!Rf_isString(datestring)) + Rf_error("Argument 'datestring' must be string."); - int len = length(datestring); - SEXP out = PROTECT(allocVector(INTSXP, len)); + int len = Rf_length(datestring); + SEXP out = PROTECT(Rf_allocVector(INTSXP, len)); for(int i = 0; i < len; i++){ time_t date = curl_getdate(CHAR(STRING_ELT(datestring, i)), NULL); diff --git a/src/library/curl/src/handle.c b/src/library/curl/src/handle.c index 1b6426eda..dfc900712 100644 --- a/src/library/curl/src/handle.c +++ b/src/library/curl/src/handle.c @@ -8,7 +8,7 @@ extern int r_curl_is_off_t_option(CURLoption x); extern int r_curl_is_string_option(CURLoption x); extern int r_curl_is_postfields_option(CURLoption x); -#define make_string(x) x ? Rf_mkString(x) : ScalarString(NA_STRING) +#define make_string(x) x ? Rf_mkString(x) : Rf_ScalarString(NA_STRING) #ifndef MAX_PATH #define MAX_PATH 1024 @@ -148,8 +148,11 @@ static void set_handle_defaults(reference *ref){ curl_easy_setopt(handle, CURLOPT_CAINFO, ca_bundle); } - /* needed to support compressed responses */ - assert(curl_easy_setopt(handle, CURLOPT_ENCODING, "")); + static const curl_version_info_data *version = NULL; + if(version == NULL) + version = curl_version_info(CURLVERSION_NOW); + /* Enable compression. On MacOS libcurl 8.7.1, deflate is broken, so dont ask for it */ + assert(curl_easy_setopt(handle, CURLOPT_ENCODING, version->version_num == 0x080701 ? "gzip" : "")); /* follow redirect */ assert(curl_easy_setopt(handle, CURLOPT_FOLLOWLOCATION, 1L)); @@ -163,8 +166,8 @@ static void set_handle_defaults(reference *ref){ assert(curl_easy_setopt(handle, CURLOPT_FILETIME, 1L)); /* set the default user agent */ - SEXP agent = GetOption1(install("HTTPUserAgent")); - if(isString(agent) && Rf_length(agent)){ + SEXP agent = Rf_GetOption1(Rf_install("HTTPUserAgent")); + if(Rf_isString(agent) && Rf_length(agent)){ assert(curl_easy_setopt(handle, CURLOPT_USERAGENT, CHAR(STRING_ELT(agent, 0)))); } else { assert(curl_easy_setopt(handle, CURLOPT_USERAGENT, "r/curl/jeroen")); @@ -172,7 +175,6 @@ static void set_handle_defaults(reference *ref){ /* allow all authentication methods */ assert(curl_easy_setopt(handle, CURLOPT_HTTPAUTH, CURLAUTH_ANY)); - assert(curl_easy_setopt(handle, CURLOPT_UNRESTRICTED_AUTH, 1L)); assert(curl_easy_setopt(handle, CURLOPT_PROXYAUTH, CURLAUTH_ANY)); /* enables HTTP2 on HTTPS (match behavior of curl cmd util) */ @@ -210,10 +212,10 @@ SEXP R_new_handle(void){ ref->handle = curl_easy_init(); total_handles++; set_handle_defaults(ref); - SEXP prot = PROTECT(allocVector(VECSXP, 7)); //for protecting callback functions + SEXP prot = PROTECT(Rf_allocVector(VECSXP, 7)); //for protecting callback functions SEXP ptr = PROTECT(R_MakeExternalPtr(ref, R_NilValue, prot)); R_RegisterCFinalizerEx(ptr, fin_handle, TRUE); - setAttrib(ptr, R_ClassSymbol, mkString("curl_handle")); + Rf_setAttrib(ptr, R_ClassSymbol, Rf_mkString("curl_handle")); UNPROTECT(2); ref->handleptr = ptr; return ptr; @@ -234,14 +236,7 @@ SEXP R_handle_reset(SEXP ptr){ //restore default settings set_handle_defaults(ref); - return ScalarLogical(1); -} - -SEXP R_handle_setheaders(SEXP ptr, SEXP vec){ - if(!isString(vec)) - error("header vector must be a string."); - set_headers(get_ref(ptr), vec_to_slist(vec)); - return ScalarLogical(1); + return Rf_ScalarLogical(1); } SEXP R_handle_getheaders(SEXP ptr){ @@ -258,15 +253,15 @@ SEXP R_handle_setopt(SEXP ptr, SEXP keys, SEXP values){ reference *ref = get_ref(ptr); CURL *handle = get_handle(ptr); SEXP prot = R_ExternalPtrProtected(ptr); - SEXP optnames = PROTECT(getAttrib(values, R_NamesSymbol)); + SEXP optnames = PROTECT(Rf_getAttrib(values, R_NamesSymbol)); - if(!isInteger(keys)) - error("keys` must be an integer"); + if(!Rf_isInteger(keys)) + Rf_error("keys` must be an integer"); - if(!isVector(values)) - error("`values` must be a list"); + if(!Rf_isVector(values)) + Rf_error("`values` must be a list"); - for(int i = 0; i < length(keys); i++){ + for(int i = 0; i < Rf_length(keys); i++){ int key = INTEGER(keys)[i]; const char* optname = CHAR(STRING_ELT(optnames, i)); SEXP val = VECTOR_ELT(values, i); @@ -275,7 +270,7 @@ SEXP R_handle_setopt(SEXP ptr, SEXP keys, SEXP values){ #ifdef HAS_XFERINFOFUNCTION } else if (key == CURLOPT_XFERINFOFUNCTION) { if (TYPEOF(val) != CLOSXP) - error("Value for option %s (%d) must be a function.", optname, key); + Rf_error("Value for option %s (%d) must be a function.", optname, key); assert(curl_easy_setopt(handle, CURLOPT_XFERINFOFUNCTION, (curl_progress_callback) R_curl_callback_xferinfo)); @@ -285,7 +280,7 @@ SEXP R_handle_setopt(SEXP ptr, SEXP keys, SEXP values){ #endif } else if (key == CURLOPT_PROGRESSFUNCTION) { if (TYPEOF(val) != CLOSXP) - error("Value for option %s (%d) must be a function.", optname, key); + Rf_error("Value for option %s (%d) must be a function.", optname, key); assert(curl_easy_setopt(handle, CURLOPT_PROGRESSFUNCTION, (curl_progress_callback) R_curl_callback_progress)); @@ -294,7 +289,7 @@ SEXP R_handle_setopt(SEXP ptr, SEXP keys, SEXP values){ SET_VECTOR_ELT(prot, 2, val); //protect gc } else if (key == CURLOPT_READFUNCTION) { if (TYPEOF(val) != CLOSXP) - error("Value for option %s (%d) must be a function.", optname, key); + Rf_error("Value for option %s (%d) must be a function.", optname, key); assert(curl_easy_setopt(handle, CURLOPT_READFUNCTION, (curl_read_callback) R_curl_callback_read)); @@ -302,7 +297,7 @@ SEXP R_handle_setopt(SEXP ptr, SEXP keys, SEXP values){ SET_VECTOR_ELT(prot, 3, val); //protect gc } else if (key == CURLOPT_DEBUGFUNCTION) { if (TYPEOF(val) != CLOSXP) - error("Value for option %s (%d) must be a function.", optname, key); + Rf_error("Value for option %s (%d) must be a function.", optname, key); assert(curl_easy_setopt(handle, CURLOPT_DEBUGFUNCTION, (curl_debug_callback) R_curl_callback_debug)); @@ -310,7 +305,7 @@ SEXP R_handle_setopt(SEXP ptr, SEXP keys, SEXP values){ SET_VECTOR_ELT(prot, 4, val); //protect gc } else if (key == CURLOPT_SSL_CTX_FUNCTION){ if (TYPEOF(val) != CLOSXP) - error("Value for option %s (%d) must be a function.", optname, key); + Rf_error("Value for option %s (%d) must be a function.", optname, key); assert(curl_easy_setopt(handle, CURLOPT_SSL_CTX_FUNCTION, (curl_ssl_ctx_callback) R_curl_callback_ssl_ctx)); @@ -318,32 +313,34 @@ SEXP R_handle_setopt(SEXP ptr, SEXP keys, SEXP values){ SET_VECTOR_ELT(prot, 5, val); //protect gc } else if (key == CURLOPT_SEEKFUNCTION) { if (TYPEOF(val) != CLOSXP) - error("Value for option %s (%d) must be a function.", optname, key); + Rf_error("Value for option %s (%d) must be a function.", optname, key); assert(curl_easy_setopt(handle, CURLOPT_SEEKFUNCTION, (curl_seek_callback) R_curl_callback_seek)); assert(curl_easy_setopt(handle, CURLOPT_SEEKDATA, val)); SET_VECTOR_ELT(prot, 6, val); //protect gc } else if (key == CURLOPT_URL) { /* always use utf-8 for urls */ - const char * url_utf8 = translateCharUTF8(STRING_ELT(val, 0)); + const char * url_utf8 = Rf_translateCharUTF8(STRING_ELT(val, 0)); assert(curl_easy_setopt(handle, CURLOPT_URL, url_utf8)); } else if(key == CURLOPT_HTTPHEADER){ - R_handle_setheaders(ptr, val); + if(!Rf_isString(val)) + Rf_error("Value for option %s (%d) must be a string vector", optname, key); + set_headers(get_ref(ptr), vec_to_slist(val)); } else if (r_curl_is_slist_option(key)) { - if(!isString(val)) - error("Value for option %s (%d) must be a string vector", optname, key); + if(!Rf_isString(val)) + Rf_error("Value for option %s (%d) must be a string vector", optname, key); ref->custom = vec_to_slist(val); assert(curl_easy_setopt(handle, key, ref->custom)); } else if(r_curl_is_long_option(key)){ - if(!isNumeric(val) || length(val) != 1) { - error("Value for option %s (%d) must be a number.", optname, key); + if(!Rf_isNumeric(val) || Rf_length(val) != 1) { + Rf_error("Value for option %s (%d) must be a number.", optname, key); } - assert(curl_easy_setopt(handle, key, (long) asInteger(val))); + assert(curl_easy_setopt(handle, key, (long) Rf_asInteger(val))); } else if(r_curl_is_off_t_option(key)){ - if(!isNumeric(val) || length(val) != 1) { - error("Value for option %s (%d) must be a number.", optname, key); + if(!Rf_isNumeric(val) || Rf_length(val) != 1) { + Rf_error("Value for option %s (%d) must be a number.", optname, key); } - assert(curl_easy_setopt(handle, key, (curl_off_t) asReal(val))); + assert(curl_easy_setopt(handle, key, (curl_off_t) Rf_asReal(val))); } else if(r_curl_is_postfields_option(key) || r_curl_is_string_option(key)){ if(key == CURLOPT_POSTFIELDS){ key = CURLOPT_COPYPOSTFIELDS; @@ -355,26 +352,26 @@ SEXP R_handle_setopt(SEXP ptr, SEXP keys, SEXP values){ assert(curl_easy_setopt(handle, key, RAW(val))); break; case STRSXP: - if (length(val) != 1) - error("Value for option %s (%d) must be length-1 string", optname, key); + if (Rf_length(val) != 1) + Rf_error("Value for option %s (%d) must be length-1 string", optname, key); assert(curl_easy_setopt(handle, key, CHAR(STRING_ELT(val, 0)))); break; default: - error("Value for option %s (%d) must be a string or raw vector.", optname, key); + Rf_error("Value for option %s (%d) must be a string or raw vector.", optname, key); } } else { - error("Option %s (%d) has unknown or unsupported type.", optname, key); + Rf_error("Option %s (%d) has unknown or unsupported type.", optname, key); } } UNPROTECT(1); - return ScalarLogical(1); + return Rf_ScalarLogical(1); } SEXP R_handle_setform(SEXP ptr, SEXP form){ - if(!isVector(form)) - error("Form must be a list."); + if(!Rf_isVector(form)) + Rf_error("Form must be a list."); set_form(get_ref(ptr), make_form(form)); - return ScalarLogical(1); + return Rf_ScalarLogical(1); } SEXP make_timevec(CURL *handle){ @@ -386,7 +383,7 @@ SEXP make_timevec(CURL *handle){ assert(curl_easy_getinfo(handle, CURLINFO_STARTTRANSFER_TIME, &time_start)); assert(curl_easy_getinfo(handle, CURLINFO_TOTAL_TIME, &time_total)); - SEXP result = PROTECT(allocVector(REALSXP, 6)); + SEXP result = PROTECT(Rf_allocVector(REALSXP, 6)); REAL(result)[0] = time_redirect; REAL(result)[1] = time_lookup; REAL(result)[2] = time_connect; @@ -394,14 +391,14 @@ SEXP make_timevec(CURL *handle){ REAL(result)[4] = time_start; REAL(result)[5] = time_total; - SEXP names = PROTECT(allocVector(STRSXP, 6)); - SET_STRING_ELT(names, 0, mkChar("redirect")); - SET_STRING_ELT(names, 1, mkChar("namelookup")); - SET_STRING_ELT(names, 2, mkChar("connect")); - SET_STRING_ELT(names, 3, mkChar("pretransfer")); - SET_STRING_ELT(names, 4, mkChar("starttransfer")); - SET_STRING_ELT(names, 5, mkChar("total")); - setAttrib(result, R_NamesSymbol, names); + SEXP names = PROTECT(Rf_allocVector(STRSXP, 6)); + SET_STRING_ELT(names, 0, Rf_mkChar("redirect")); + SET_STRING_ELT(names, 1, Rf_mkChar("namelookup")); + SET_STRING_ELT(names, 2, Rf_mkChar("connect")); + SET_STRING_ELT(names, 3, Rf_mkChar("pretransfer")); + SET_STRING_ELT(names, 4, Rf_mkChar("starttransfer")); + SET_STRING_ELT(names, 5, Rf_mkChar("total")); + Rf_setAttrib(result, R_NamesSymbol, names); UNPROTECT(2); return result; } @@ -419,7 +416,7 @@ SEXP make_cookievec(CURL *handle){ SEXP make_status(CURL *handle){ long res_status; assert(curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, &res_status)); - return ScalarInteger(res_status); + return Rf_ScalarInteger(res_status); } SEXP make_ctype(CURL *handle){ @@ -431,7 +428,7 @@ SEXP make_ctype(CURL *handle){ SEXP make_url(CURL *handle){ char *res_url; assert(curl_easy_getinfo(handle, CURLINFO_EFFECTIVE_URL, &res_url)); - return ScalarString(mkCharCE(res_url, CE_UTF8)); + return Rf_ScalarString(Rf_mkCharCE(res_url, CE_UTF8)); } SEXP make_filetime(CURL *handle){ @@ -441,18 +438,18 @@ SEXP make_filetime(CURL *handle){ filetime = NA_INTEGER; } - SEXP classes = PROTECT(allocVector(STRSXP, 2)); - SET_STRING_ELT(classes, 0, mkChar("POSIXct")); - SET_STRING_ELT(classes, 1, mkChar("POSIXt")); + SEXP classes = PROTECT(Rf_allocVector(STRSXP, 2)); + SET_STRING_ELT(classes, 0, Rf_mkChar("POSIXct")); + SET_STRING_ELT(classes, 1, Rf_mkChar("POSIXt")); - SEXP out = PROTECT(ScalarInteger(filetime)); - setAttrib(out, R_ClassSymbol, classes); + SEXP out = PROTECT(Rf_ScalarInteger(filetime)); + Rf_setAttrib(out, R_ClassSymbol, classes); UNPROTECT(2); return out; } SEXP make_rawvec(unsigned char *ptr, size_t size){ - SEXP out = PROTECT(allocVector(RAWSXP, size)); + SEXP out = PROTECT(Rf_allocVector(RAWSXP, size)); if(size > 0) memcpy(RAW(out), ptr, size); UNPROTECT(1); @@ -460,14 +457,14 @@ SEXP make_rawvec(unsigned char *ptr, size_t size){ } SEXP make_namesvec(void){ - SEXP names = PROTECT(allocVector(STRSXP, 7)); - SET_STRING_ELT(names, 0, mkChar("url")); - SET_STRING_ELT(names, 1, mkChar("status_code")); - SET_STRING_ELT(names, 2, mkChar("type")); - SET_STRING_ELT(names, 3, mkChar("headers")); - SET_STRING_ELT(names, 4, mkChar("modified")); - SET_STRING_ELT(names, 5, mkChar("times")); - SET_STRING_ELT(names, 6, mkChar("content")); + SEXP names = PROTECT(Rf_allocVector(STRSXP, 7)); + SET_STRING_ELT(names, 0, Rf_mkChar("url")); + SET_STRING_ELT(names, 1, Rf_mkChar("status_code")); + SET_STRING_ELT(names, 2, Rf_mkChar("type")); + SET_STRING_ELT(names, 3, Rf_mkChar("headers")); + SET_STRING_ELT(names, 4, Rf_mkChar("modified")); + SET_STRING_ELT(names, 5, Rf_mkChar("times")); + SET_STRING_ELT(names, 6, Rf_mkChar("content")); UNPROTECT(1); return names; } @@ -478,7 +475,7 @@ SEXP R_get_handle_cookies(SEXP ptr){ SEXP make_handle_response(reference *ref){ CURL *handle = ref->handle; - SEXP res = PROTECT(allocVector(VECSXP, 7)); + SEXP res = PROTECT(Rf_allocVector(VECSXP, 7)); SET_VECTOR_ELT(res, 0, make_url(handle)); SET_VECTOR_ELT(res, 1, make_status(handle)); SET_VECTOR_ELT(res, 2, make_ctype(handle)); @@ -486,7 +483,7 @@ SEXP make_handle_response(reference *ref){ SET_VECTOR_ELT(res, 4, make_filetime(handle)); SET_VECTOR_ELT(res, 5, make_timevec(handle)); SET_VECTOR_ELT(res, 6, R_NilValue); - setAttrib(res, R_NamesSymbol, make_namesvec()); + Rf_setAttrib(res, R_NamesSymbol, make_namesvec()); UNPROTECT(1); return res; } @@ -545,5 +542,5 @@ SEXP R_get_handle_mtime(SEXP ptr){ } SEXP R_total_handles(void){ - return(ScalarInteger(total_handles)); + return(Rf_ScalarInteger(total_handles)); } diff --git a/src/library/curl/src/ieproxy.c b/src/library/curl/src/ieproxy.c index 17a9659af..3fd850492 100644 --- a/src/library/curl/src/ieproxy.c +++ b/src/library/curl/src/ieproxy.c @@ -13,20 +13,20 @@ #define WINHTTP_AUTOPROXY_RUN_OUTPROCESS_ONLY 0x00020000 static SEXP proxy_namesvec(void){ - SEXP names = PROTECT(allocVector(STRSXP, 4)); - SET_STRING_ELT(names, 0, mkChar("AutoDetect")); - SET_STRING_ELT(names, 1, mkChar("AutoConfigUrl")); - SET_STRING_ELT(names, 2, mkChar("Proxy")); - SET_STRING_ELT(names, 3, mkChar("ProxyBypass")); + SEXP names = PROTECT(Rf_allocVector(STRSXP, 4)); + SET_STRING_ELT(names, 0, Rf_mkChar("AutoDetect")); + SET_STRING_ELT(names, 1, Rf_mkChar("AutoConfigUrl")); + SET_STRING_ELT(names, 2, Rf_mkChar("Proxy")); + SET_STRING_ELT(names, 3, Rf_mkChar("ProxyBypass")); UNPROTECT(1); return names; } static SEXP auto_namesvec(void){ - SEXP names = PROTECT(allocVector(STRSXP, 3)); - SET_STRING_ELT(names, 0, mkChar("HasProxy")); - SET_STRING_ELT(names, 1, mkChar("Proxy")); - SET_STRING_ELT(names, 2, mkChar("ProxyBypass")); + SEXP names = PROTECT(Rf_allocVector(STRSXP, 3)); + SET_STRING_ELT(names, 0, Rf_mkChar("HasProxy")); + SET_STRING_ELT(names, 1, Rf_mkChar("Proxy")); + SET_STRING_ELT(names, 2, Rf_mkChar("ProxyBypass")); UNPROTECT(1); return names; } @@ -37,24 +37,24 @@ SEXP R_proxy_info(void){ return R_NilValue; } char buffer[500]; - SEXP vec = PROTECT(allocVector(VECSXP, 4)); - SET_VECTOR_ELT(vec, 0, ScalarLogical(MyProxyConfig.fAutoDetect)); + SEXP vec = PROTECT(Rf_allocVector(VECSXP, 4)); + SET_VECTOR_ELT(vec, 0, Rf_ScalarLogical(MyProxyConfig.fAutoDetect)); if(MyProxyConfig.lpszAutoConfigUrl != NULL) { wcstombs(buffer, MyProxyConfig.lpszAutoConfigUrl, 500); - SET_VECTOR_ELT(vec, 1, mkString(buffer)); + SET_VECTOR_ELT(vec, 1, Rf_mkString(buffer)); } if(MyProxyConfig.lpszProxy != NULL) { wcstombs(buffer, MyProxyConfig.lpszProxy, 500); - SET_VECTOR_ELT(vec, 2, mkString(buffer)); + SET_VECTOR_ELT(vec, 2, Rf_mkString(buffer)); } if(MyProxyConfig.lpszProxyBypass != NULL) { wcstombs(buffer, MyProxyConfig.lpszProxyBypass, 500); - SET_VECTOR_ELT(vec, 3, mkString(buffer)); + SET_VECTOR_ELT(vec, 3, Rf_mkString(buffer)); } - setAttrib(vec, R_NamesSymbol, proxy_namesvec()); + Rf_setAttrib(vec, R_NamesSymbol, proxy_namesvec()); UNPROTECT(1); return vec; } @@ -78,16 +78,16 @@ SEXP R_get_proxy_for_url(SEXP target_url, SEXP auto_detect, SEXP autoproxy_url){ // Exit if WinHttpOpen failed. if( !hHttpSession ) - error("Call to WinHttpOpen failed."); + Rf_error("Call to WinHttpOpen failed."); // Auto-detection doesn't work very well - if(asLogical(auto_detect)){ + if(Rf_asLogical(auto_detect)){ AutoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT; AutoProxyOptions.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DHCP | WINHTTP_AUTO_DETECT_TYPE_DNS_A; } // Use manual URL instead - if(isString(autoproxy_url) && LENGTH(autoproxy_url)){ + if(Rf_isString(autoproxy_url) && LENGTH(autoproxy_url)){ wchar_t *autourl = (wchar_t *) calloc(10000, sizeof(int)); mbstowcs(autourl, CHAR(STRING_ELT(autoproxy_url, 0)), LENGTH(STRING_ELT(autoproxy_url, 0))); AutoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_CONFIG_URL; @@ -102,44 +102,44 @@ SEXP R_get_proxy_for_url(SEXP target_url, SEXP auto_detect, SEXP autoproxy_url){ DWORD err = GetLastError(); switch(err){ case ERROR_WINHTTP_AUTO_PROXY_SERVICE_ERROR: - error("ERROR_WINHTTP_AUTO_PROXY_SERVICE_ERROR"); + Rf_error("ERROR_WINHTTP_AUTO_PROXY_SERVICE_ERROR"); case ERROR_WINHTTP_BAD_AUTO_PROXY_SCRIPT: - error("ERROR_WINHTTP_BAD_AUTO_PROXY_SCRIPT"); + Rf_error("ERROR_WINHTTP_BAD_AUTO_PROXY_SCRIPT"); case ERROR_WINHTTP_INCORRECT_HANDLE_TYPE: - error("ERROR_WINHTTP_INCORRECT_HANDLE_TYPE"); + Rf_error("ERROR_WINHTTP_INCORRECT_HANDLE_TYPE"); case ERROR_WINHTTP_INTERNAL_ERROR: - error("ERROR_WINHTTP_INTERNAL_ERROR"); + Rf_error("ERROR_WINHTTP_INTERNAL_ERROR"); case ERROR_WINHTTP_INVALID_URL: - error("ERROR_WINHTTP_INVALID_URL"); + Rf_error("ERROR_WINHTTP_INVALID_URL"); case ERROR_WINHTTP_LOGIN_FAILURE: - error("ERROR_WINHTTP_LOGIN_FAILURE"); + Rf_error("ERROR_WINHTTP_LOGIN_FAILURE"); case ERROR_WINHTTP_OPERATION_CANCELLED: - error("ERROR_WINHTTP_OPERATION_CANCELLED"); + Rf_error("ERROR_WINHTTP_OPERATION_CANCELLED"); case ERROR_WINHTTP_UNABLE_TO_DOWNLOAD_SCRIPT: - error("ERROR_WINHTTP_UNABLE_TO_DOWNLOAD_SCRIPT"); + Rf_error("ERROR_WINHTTP_UNABLE_TO_DOWNLOAD_SCRIPT"); case ERROR_WINHTTP_UNRECOGNIZED_SCHEME: - error("ERROR_WINHTTP_UNRECOGNIZED_SCHEME"); + Rf_error("ERROR_WINHTTP_UNRECOGNIZED_SCHEME"); case ERROR_NOT_ENOUGH_MEMORY: - error("ERROR_NOT_ENOUGH_MEMORY"); + Rf_error("ERROR_NOT_ENOUGH_MEMORY"); } } //store output data char buffer[500]; - SEXP vec = PROTECT(allocVector(VECSXP, 3)); - SET_VECTOR_ELT(vec, 0, ScalarLogical( + SEXP vec = PROTECT(Rf_allocVector(VECSXP, 3)); + SET_VECTOR_ELT(vec, 0, Rf_ScalarLogical( ProxyInfo.dwAccessType == WINHTTP_ACCESS_TYPE_NAMED_PROXY || ProxyInfo.dwAccessType == WINHTTP_ACCESS_TYPE_DEFAULT_PROXY)); if(ProxyInfo.lpszProxy != NULL) { wcstombs(buffer, ProxyInfo.lpszProxy, 500); - SET_VECTOR_ELT(vec, 1, mkString(buffer)); + SET_VECTOR_ELT(vec, 1, Rf_mkString(buffer)); GlobalFree((void*) ProxyInfo.lpszProxy); } if(ProxyInfo.lpszProxyBypass != NULL) { wcstombs(buffer, ProxyInfo.lpszProxyBypass, 500); - SET_VECTOR_ELT(vec, 2, mkString(buffer)); + SET_VECTOR_ELT(vec, 2, Rf_mkString(buffer)); GlobalFree((void*) ProxyInfo.lpszProxyBypass ); } @@ -147,7 +147,7 @@ SEXP R_get_proxy_for_url(SEXP target_url, SEXP auto_detect, SEXP autoproxy_url){ WinHttpCloseHandle( hHttpSession ); //return - setAttrib(vec, R_NamesSymbol, auto_namesvec()); + Rf_setAttrib(vec, R_NamesSymbol, auto_namesvec()); UNPROTECT(1); return vec; } @@ -157,7 +157,7 @@ SEXP R_windows_build(void){ DWORD dwVersion = GetVersion(); if (dwVersion < 0x80000000) dwBuild = (DWORD)(HIWORD(dwVersion)); - return ScalarInteger(dwBuild); + return Rf_ScalarInteger(dwBuild); } #else //_WIN32 diff --git a/src/library/curl/src/init.c b/src/library/curl/src/init.c index 2dc2cc652..a76a61577 100644 --- a/src/library/curl/src/init.c +++ b/src/library/curl/src/init.c @@ -65,7 +65,6 @@ static const R_CallMethodDef CallEntries[] = { {"R_handle_getheaders", (DL_FUNC) &R_handle_getheaders, 1}, {"R_handle_reset", (DL_FUNC) &R_handle_reset, 1}, {"R_handle_setform", (DL_FUNC) &R_handle_setform, 2}, - {"R_handle_setheaders", (DL_FUNC) &R_handle_setheaders, 2}, {"R_handle_setopt", (DL_FUNC) &R_handle_setopt, 3}, {"R_option_types", (DL_FUNC) &R_option_types, 0}, {"R_multi_add", (DL_FUNC) &R_multi_add, 5}, diff --git a/src/library/curl/src/multi.c b/src/library/curl/src/multi.c index 069271438..2e0be9c36 100644 --- a/src/library/curl/src/multi.c +++ b/src/library/curl/src/multi.c @@ -3,7 +3,7 @@ /* Notes: * - First check for unhandled messages in curl_multi_info_read() before curl_multi_perform() - * - Use eval() to callback instead of R_tryEval() to propagate interrupt or error back to C + * - Use Rf_eval() to callback instead of R_tryEval() to propagate interrupt or error back to C */ #if LIBCURL_VERSION_MAJOR > 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR >= 30) @@ -104,8 +104,8 @@ SEXP R_multi_run(SEXP pool_ptr, SEXP timeout, SEXP max){ int total_pending = -1; int total_success = 0; int total_fail = 0; - int result_max = asInteger(max); - double time_max = asReal(timeout); + int result_max = Rf_asInteger(max); + double time_max = Rf_asReal(timeout); time_t time_start = time(NULL); double seconds_elapsed = 0; @@ -126,7 +126,7 @@ SEXP R_multi_run(SEXP pool_ptr, SEXP timeout, SEXP max){ SEXP cb_complete = PROTECT(ref->async.complete); SEXP cb_error = PROTECT(ref->async.error); SEXP cb_data = PROTECT(ref->async.data); - SEXP buf = PROTECT(allocVector(RAWSXP, ref->async.content.size)); + SEXP buf = PROTECT(Rf_allocVector(RAWSXP, ref->async.content.size)); if(ref->async.content.buf && ref->async.content.size) memcpy(RAW(buf), ref->async.content.buf, ref->async.content.size); @@ -137,8 +137,8 @@ SEXP R_multi_run(SEXP pool_ptr, SEXP timeout, SEXP max){ // This also ensures that a file is consistently created, even for empty responses if(Rf_isFunction(cb_data)){ SEXP buf = PROTECT(Rf_allocVector(RAWSXP, 0)); - SEXP call = PROTECT(Rf_lang3(cb_data, buf, ScalarInteger(1))); - eval(call, R_GlobalEnv); + SEXP call = PROTECT(Rf_lang3(cb_data, buf, Rf_ScalarInteger(1))); + Rf_eval(call, R_GlobalEnv); UNPROTECT(2); } @@ -149,19 +149,19 @@ SEXP R_multi_run(SEXP pool_ptr, SEXP timeout, SEXP max){ int arglen = Rf_length(FORMALS(cb_complete)); SEXP out = PROTECT(make_handle_response(ref)); SET_VECTOR_ELT(out, 6, buf); - SEXP call = PROTECT(LCONS(cb_complete, arglen ? LCONS(out, R_NilValue) : R_NilValue)); + SEXP call = PROTECT(Rf_lcons(cb_complete, arglen ? Rf_lcons(out, R_NilValue) : R_NilValue)); //R_tryEval(call, R_GlobalEnv, &cbfail); - eval(call, R_GlobalEnv); //OK to error here + Rf_eval(call, R_GlobalEnv); //OK to error here UNPROTECT(2); } } else { total_fail++; if(Rf_isFunction(cb_error)){ int arglen = Rf_length(FORMALS(cb_error)); - SEXP buf = PROTECT(mkString(strlen(ref->errbuf) ? ref->errbuf : curl_easy_strerror(status))); - SEXP call = PROTECT(LCONS(cb_error, arglen ? LCONS(buf, R_NilValue) : R_NilValue)); + SEXP buf = PROTECT(Rf_mkString(strlen(ref->errbuf) ? ref->errbuf : curl_easy_strerror(status))); + SEXP call = PROTECT(Rf_lcons(cb_error, arglen ? Rf_lcons(buf, R_NilValue) : R_NilValue)); //R_tryEval(call, R_GlobalEnv, &cbfail); - eval(call, R_GlobalEnv); //OK to error here + Rf_eval(call, R_GlobalEnv); //OK to error here UNPROTECT(2); } } @@ -205,16 +205,16 @@ SEXP R_multi_run(SEXP pool_ptr, SEXP timeout, SEXP max){ break; } - SEXP res = PROTECT(allocVector(VECSXP, 3)); - SET_VECTOR_ELT(res, 0, ScalarInteger(total_success)); - SET_VECTOR_ELT(res, 1, ScalarInteger(total_fail)); - SET_VECTOR_ELT(res, 2, ScalarInteger(total_pending)); + SEXP res = PROTECT(Rf_allocVector(VECSXP, 3)); + SET_VECTOR_ELT(res, 0, Rf_ScalarInteger(total_success)); + SET_VECTOR_ELT(res, 1, Rf_ScalarInteger(total_fail)); + SET_VECTOR_ELT(res, 2, Rf_ScalarInteger(total_pending)); - SEXP names = PROTECT(allocVector(STRSXP, 3)); - SET_STRING_ELT(names, 0, mkChar("success")); - SET_STRING_ELT(names, 1, mkChar("error")); - SET_STRING_ELT(names, 2, mkChar("pending")); - setAttrib(res, R_NamesSymbol, names); + SEXP names = PROTECT(Rf_allocVector(STRSXP, 3)); + SET_STRING_ELT(names, 0, Rf_mkChar("success")); + SET_STRING_ELT(names, 1, Rf_mkChar("error")); + SET_STRING_ELT(names, 2, Rf_mkChar("pending")); + Rf_setAttrib(res, R_NamesSymbol, names); UNPROTECT(2); return res; } @@ -238,7 +238,7 @@ SEXP R_multi_new(void){ SEXP ptr = PROTECT(R_MakeExternalPtr(ref, R_NilValue, ref->handles)); ref->multiptr = ptr; R_RegisterCFinalizerEx(ptr, fin_multi, 1); - setAttrib(ptr, R_ClassSymbol, mkString("curl_multi")); + Rf_setAttrib(ptr, R_ClassSymbol, Rf_mkString("curl_multi")); UNPROTECT(1); return ptr; } @@ -246,14 +246,14 @@ SEXP R_multi_new(void){ SEXP R_multi_setopt(SEXP pool_ptr, SEXP total_con, SEXP host_con, SEXP multiplex){ #ifdef HAS_CURLMOPT_MAX_TOTAL_CONNECTIONS CURLM *multi = get_multiref(pool_ptr)->m; - massert(curl_multi_setopt(multi, CURLMOPT_MAX_TOTAL_CONNECTIONS, (long) asInteger(total_con))); - massert(curl_multi_setopt(multi, CURLMOPT_MAX_HOST_CONNECTIONS, (long) asInteger(host_con))); + massert(curl_multi_setopt(multi, CURLMOPT_MAX_TOTAL_CONNECTIONS, (long) Rf_asInteger(total_con))); + massert(curl_multi_setopt(multi, CURLMOPT_MAX_HOST_CONNECTIONS, (long) Rf_asInteger(host_con))); #endif // NOTE: CURLPIPE_HTTP1 is unsafe for non idempotent requests #ifdef CURLPIPE_MULTIPLEX massert(curl_multi_setopt(multi, CURLMOPT_PIPELINING, - asLogical(multiplex) ? CURLPIPE_MULTIPLEX : CURLPIPE_NOTHING)); + Rf_asLogical(multiplex) ? CURLPIPE_MULTIPLEX : CURLPIPE_NOTHING)); #endif return pool_ptr; @@ -287,18 +287,18 @@ SEXP R_multi_fdset(SEXP pool_ptr){ if (FD_ISSET(i, &exc_fd_set)) num_exc++; } - result = PROTECT(allocVector(VECSXP, 4)); - SET_VECTOR_ELT(result, 0, allocVector(INTSXP, num_read)); - SET_VECTOR_ELT(result, 1, allocVector(INTSXP, num_write)); - SET_VECTOR_ELT(result, 2, allocVector(INTSXP, num_exc)); - SET_VECTOR_ELT(result, 3, ScalarReal((double) timeout)); - - names = PROTECT(allocVector(STRSXP, 4)); - SET_STRING_ELT(names, 0, mkChar("reads")); - SET_STRING_ELT(names, 1, mkChar("writes")); - SET_STRING_ELT(names, 2, mkChar("exceptions")); - SET_STRING_ELT(names, 3, mkChar("timeout")); - setAttrib(result, R_NamesSymbol, names); + result = PROTECT(Rf_allocVector(VECSXP, 4)); + SET_VECTOR_ELT(result, 0, Rf_allocVector(INTSXP, num_read)); + SET_VECTOR_ELT(result, 1, Rf_allocVector(INTSXP, num_write)); + SET_VECTOR_ELT(result, 2, Rf_allocVector(INTSXP, num_exc)); + SET_VECTOR_ELT(result, 3, Rf_ScalarReal((double) timeout)); + + names = PROTECT(Rf_allocVector(STRSXP, 4)); + SET_STRING_ELT(names, 0, Rf_mkChar("reads")); + SET_STRING_ELT(names, 1, Rf_mkChar("writes")); + SET_STRING_ELT(names, 2, Rf_mkChar("exceptions")); + SET_STRING_ELT(names, 3, Rf_mkChar("timeout")); + Rf_setAttrib(result, R_NamesSymbol, names); pread = INTEGER(VECTOR_ELT(result, 0)); pwrite = INTEGER(VECTOR_ELT(result, 1)); diff --git a/src/library/curl/src/nslookup.c b/src/library/curl/src/nslookup.c index 9cb41d652..31f03fe98 100644 --- a/src/library/curl/src/nslookup.c +++ b/src/library/curl/src/nslookup.c @@ -29,7 +29,7 @@ int jeroen_win32_idn_to_ascii(const char *in, char **out); SEXP R_nslookup(SEXP hostname, SEXP ipv4_only) { /* Because gethostbyname() is deprecated */ struct addrinfo hints = {0}; - if(asLogical(ipv4_only)) + if(Rf_asLogical(ipv4_only)) hints.ai_family = AF_INET; //only allow ipv4 struct addrinfo *addr; const char * hoststr = CHAR(STRING_ELT(hostname, 0)); @@ -52,7 +52,7 @@ SEXP R_nslookup(SEXP hostname, SEXP ipv4_only) { } //allocate output - SEXP out = PROTECT(allocVector(STRSXP, len)); + SEXP out = PROTECT(Rf_allocVector(STRSXP, len)); //extract the values cur = addr; @@ -68,7 +68,7 @@ SEXP R_nslookup(SEXP hostname, SEXP ipv4_only) { struct sockaddr_in6 *sa_in = (struct sockaddr_in6*) sa; inet_ntop(AF_INET6, &(sa_in->sin6_addr), ip, INET6_ADDRSTRLEN); } - SET_STRING_ELT(out, i, mkChar(ip)); + SET_STRING_ELT(out, i, Rf_mkChar(ip)); cur = cur->ai_next; } UNPROTECT(1); diff --git a/src/library/curl/src/reflist.c b/src/library/curl/src/reflist.c index 566fcf156..c868c0c34 100644 --- a/src/library/curl/src/reflist.c +++ b/src/library/curl/src/reflist.c @@ -8,7 +8,7 @@ SEXP reflist_init(void){ SEXP reflist_add(SEXP x, SEXP target){ if(!Rf_isPairList(x)) Rf_error("Not a LISTSXP"); - return(CONS(target, x)); + return(Rf_cons(target, x)); } SEXP reflist_has(SEXP x, SEXP target){ @@ -16,10 +16,10 @@ SEXP reflist_has(SEXP x, SEXP target){ Rf_error("Not a LISTSXP"); while(x != R_NilValue){ if(CAR(x) == target) - return(ScalarLogical(1)); + return(Rf_ScalarLogical(1)); x = CDR(x); } - return(ScalarLogical(0)); + return(Rf_ScalarLogical(0)); } SEXP reflist_remove(SEXP x, SEXP target){ @@ -52,5 +52,5 @@ SEXP reflist_length(SEXP x) { i++; x = CDR(x); } - return ScalarInteger(i); + return Rf_ScalarInteger(i); } diff --git a/src/library/curl/src/split.c b/src/library/curl/src/split.c index 91fa21ac6..dff6622ac 100644 --- a/src/library/curl/src/split.c +++ b/src/library/curl/src/split.c @@ -8,9 +8,9 @@ SEXP R_split_string(SEXP string, SEXP split){ char * out = strstr(str, cut); if(!out) return string; - SEXP res = PROTECT(allocVector(STRSXP, 2)); - SET_STRING_ELT(res, 0, mkCharLenCE(str, out - str, enc)); - SET_STRING_ELT(res, 1, mkCharCE(out + strlen(cut), enc)); + SEXP res = PROTECT(Rf_allocVector(STRSXP, 2)); + SET_STRING_ELT(res, 0, Rf_mkCharLenCE(str, out - str, enc)); + SET_STRING_ELT(res, 1, Rf_mkCharCE(out + strlen(cut), enc)); UNPROTECT(1); return res; } diff --git a/src/library/curl/src/utils.c b/src/library/curl/src/utils.c index 54c6c1b65..584b16415 100644 --- a/src/library/curl/src/utils.c +++ b/src/library/curl/src/utils.c @@ -9,7 +9,7 @@ reference* get_ref(SEXP ptr){ if(TYPEOF(ptr) != EXTPTRSXP || !Rf_inherits(ptr, "curl_handle")) Rf_error("handle is not a curl_handle()"); if(!R_ExternalPtrAddr(ptr)) - error("handle is dead"); + Rf_error("handle is dead"); reference *ref = (reference*) R_ExternalPtrAddr(ptr); return ref; } @@ -84,15 +84,15 @@ void stop_for_status(CURL *http_handle){ /* check http status code. Not sure what this does for ftp. */ if(status >= 300) - error("HTTP error %ld.", status); + Rf_error("HTTP error %ld.", status); } /* make sure to call curl_slist_free_all on this object */ struct curl_slist* vec_to_slist(SEXP vec){ - if(!isString(vec)) - error("vec is not a character vector"); + if(!Rf_isString(vec)) + Rf_error("vec is not a character vector"); struct curl_slist *slist = NULL; - for(int i = 0; i < length(vec); i++){ + for(int i = 0; i < Rf_length(vec); i++){ slist = curl_slist_append(slist, CHAR(STRING_ELT(vec, i))); } return slist; @@ -109,10 +109,10 @@ SEXP slist_to_vec(struct curl_slist *slist){ cursor = cursor->next; } - SEXP out = PROTECT(allocVector(STRSXP, n)); + SEXP out = PROTECT(Rf_allocVector(STRSXP, n)); cursor = slist; for(int i = 0; i < n; i++){ - SET_STRING_ELT(out, i, mkChar(cursor->data)); + SET_STRING_ELT(out, i, Rf_mkChar(cursor->data)); cursor = cursor->next; } UNPROTECT(1); @@ -162,12 +162,12 @@ size_t append_buffer(void *contents, size_t sz, size_t nmemb, void *ctx) { size_t data_callback(void * data, size_t sz, size_t nmemb, SEXP fun) { size_t size = sz * nmemb; - SEXP buf = PROTECT(allocVector(RAWSXP, size)); + SEXP buf = PROTECT(Rf_allocVector(RAWSXP, size)); memcpy(RAW(buf), data, size); /* call the R function */ int err; - SEXP call = PROTECT(Rf_lang3(fun, buf, ScalarInteger(0))); + SEXP call = PROTECT(Rf_lang3(fun, buf, Rf_ScalarInteger(0))); R_tryEval(call, R_GlobalEnv, &err); UNPROTECT(2); return err ? 0 : size; diff --git a/src/library/curl/src/version.c b/src/library/curl/src/version.c index e98eb78d7..869712b85 100644 --- a/src/library/curl/src/version.c +++ b/src/library/curl/src/version.c @@ -1,14 +1,14 @@ #include #include -#define make_string(x) x ? Rf_mkString(x) : ScalarString(NA_STRING) +#define make_string(x) x ? Rf_mkString(x) : Rf_ScalarString(NA_STRING) SEXP R_curl_version(void) { /* retrieve info from curl */ const curl_version_info_data *data = curl_version_info(CURLVERSION_NOW); /* put stuff in a list */ - SEXP list = PROTECT(allocVector(VECSXP, 10)); + SEXP list = PROTECT(Rf_allocVector(VECSXP, 10)); SET_VECTOR_ELT(list, 0, make_string(data->version)); SET_VECTOR_ELT(list, 1, make_string(data->ssl_version)); SET_VECTOR_ELT(list, 2, make_string(data->libz_version)); @@ -20,42 +20,42 @@ SEXP R_curl_version(void) { int len = 0; const char *const * temp = data->protocols; while(*temp++) len++; - SEXP protocols = PROTECT(allocVector(STRSXP, len)); + SEXP protocols = PROTECT(Rf_allocVector(STRSXP, len)); for (int i = 0; i < len; i++){ - SET_STRING_ELT(protocols, i, mkChar(*(data->protocols + i))); + SET_STRING_ELT(protocols, i, Rf_mkChar(*(data->protocols + i))); } SET_VECTOR_ELT(list, 6, protocols); /* add list names */ - SEXP names = PROTECT(allocVector(STRSXP, 10)); - SET_STRING_ELT(names, 0, mkChar("version")); - SET_STRING_ELT(names, 1, mkChar("ssl_version")); - SET_STRING_ELT(names, 2, mkChar("libz_version")); - SET_STRING_ELT(names, 3, mkChar("libssh_version")); - SET_STRING_ELT(names, 4, mkChar("libidn_version")); - SET_STRING_ELT(names, 5, mkChar("host")); - SET_STRING_ELT(names, 6, mkChar("protocols")); - SET_STRING_ELT(names, 7, mkChar("ipv6")); - SET_STRING_ELT(names, 8, mkChar("http2")); - SET_STRING_ELT(names, 9, mkChar("idn")); - setAttrib(list, R_NamesSymbol, names); + SEXP names = PROTECT(Rf_allocVector(STRSXP, 10)); + SET_STRING_ELT(names, 0, Rf_mkChar("version")); + SET_STRING_ELT(names, 1, Rf_mkChar("ssl_version")); + SET_STRING_ELT(names, 2, Rf_mkChar("libz_version")); + SET_STRING_ELT(names, 3, Rf_mkChar("libssh_version")); + SET_STRING_ELT(names, 4, Rf_mkChar("libidn_version")); + SET_STRING_ELT(names, 5, Rf_mkChar("host")); + SET_STRING_ELT(names, 6, Rf_mkChar("protocols")); + SET_STRING_ELT(names, 7, Rf_mkChar("ipv6")); + SET_STRING_ELT(names, 8, Rf_mkChar("http2")); + SET_STRING_ELT(names, 9, Rf_mkChar("idn")); + Rf_setAttrib(list, R_NamesSymbol, names); #ifdef CURL_VERSION_IPV6 - SET_VECTOR_ELT(list, 7, ScalarLogical(data->features & CURL_VERSION_IPV6)); + SET_VECTOR_ELT(list, 7, Rf_ScalarLogical(data->features & CURL_VERSION_IPV6)); #else - SET_VECTOR_ELT(list, 7, ScalarLogical(0)); + SET_VECTOR_ELT(list, 7, Rf_ScalarLogical(0)); #endif #ifdef CURL_VERSION_HTTP2 - SET_VECTOR_ELT(list, 8, ScalarLogical(data->features & CURL_VERSION_HTTP2)); + SET_VECTOR_ELT(list, 8, Rf_ScalarLogical(data->features & CURL_VERSION_HTTP2)); #else - SET_VECTOR_ELT(list, 8, ScalarLogical(0)); + SET_VECTOR_ELT(list, 8, Rf_ScalarLogical(0)); #endif #ifdef CURL_VERSION_IDN - SET_VECTOR_ELT(list, 9, ScalarLogical(data->features & CURL_VERSION_IDN)); + SET_VECTOR_ELT(list, 9, Rf_ScalarLogical(data->features & CURL_VERSION_IDN)); #else - SET_VECTOR_ELT(list, 9, ScalarLogical(0)); + SET_VECTOR_ELT(list, 9, Rf_ScalarLogical(0)); #endif /* return */ diff --git a/src/library/curl/src/writer.c b/src/library/curl/src/writer.c index 381e769cc..baca24af1 100644 --- a/src/library/curl/src/writer.c +++ b/src/library/curl/src/writer.c @@ -36,17 +36,17 @@ SEXP R_write_file_writer(SEXP ptr, SEXP buf, SEXP close){ } else if(Rf_length(buf)) { fflush(fp); } - return ScalarInteger(len); + return Rf_ScalarInteger(len); } SEXP R_new_file_writer(SEXP opts){ SEXP ptr = PROTECT(R_MakeExternalPtr(NULL, opts, R_NilValue)); R_RegisterCFinalizerEx(ptr, fin_file_writer, TRUE); - setAttrib(ptr, R_ClassSymbol, mkString("file_writer")); + Rf_setAttrib(ptr, R_ClassSymbol, Rf_mkString("file_writer")); UNPROTECT(1); return ptr; } SEXP R_total_writers(void){ - return(ScalarInteger(total_open_writers)); + return(Rf_ScalarInteger(total_open_writers)); } diff --git a/src/library/curl/vignettes/intro.Rmd b/src/library/curl/vignettes/intro.Rmd deleted file mode 100644 index b3da55ab2..000000000 --- a/src/library/curl/vignettes/intro.Rmd +++ /dev/null @@ -1,403 +0,0 @@ ---- -title: "The curl package: a modern R interface to libcurl" -date: "`r Sys.Date()`" -output: - html_document: - fig_caption: false - toc: true - toc_float: - collapsed: false - smooth_scroll: false - toc_depth: 3 -vignette: > - %\VignetteIndexEntry{The curl package: a modern R interface to libcurl} - %\VignetteEngine{knitr::rmarkdown} - %\VignetteEncoding{UTF-8} ---- - - -```{r, echo = FALSE, message = FALSE} -knitr::opts_chunk$set(comment = "") -options(width = 120, max.print = 100) -wrap.simpleError <- function(x, options) { - paste0("```\n## Error: ", x$message, "\n```") -} -library(curl) -library(jsonlite) -``` - -The curl package provides bindings to the [libcurl](https://curl.se/libcurl/) C library for R. The package supports retrieving data in-memory, downloading to disk, or streaming using the [R "connection" interface](https://stat.ethz.ch/R-manual/R-devel/library/base/html/connections.html). Some knowledge of curl is recommended to use this package. For a more user-friendly HTTP client, have a look at the [httr](https://cran.r-project.org/package=httr/vignettes/quickstart.html) package which builds on curl with HTTP specific tools and logic. - -## Request interfaces - -The curl package implements several interfaces to retrieve data from a URL: - - - `curl_fetch_memory()` saves response in memory - - `curl_download()` or `curl_fetch_disk()` writes response to disk - - `curl()` or `curl_fetch_stream()` streams response data - - `curl_fetch_multi()` (Advanced) process responses via callback functions - -Each interface performs the same HTTP request, they only differ in how response data is processed. - -### Getting in memory - -The `curl_fetch_memory` function is a blocking interface which waits for the request to complete and returns a list with all content (data, headers, status, timings) of the server response. - - -```{r} -req <- curl_fetch_memory("https://hb.cran.dev/get?foo=123") -str(req) -parse_headers(req$headers) -jsonlite::prettify(rawToChar(req$content)) -``` - -The `curl_fetch_memory` interface is the easiest interface and most powerful for building API clients. However it is not suitable for downloading really large files because it is fully in-memory. If you are expecting 100G of data, you probably need one of the other interfaces. - -### Downloading to disk - -The second method is `curl_download`, which has been designed as a drop-in replacement for `download.file` in r-base. It writes the response straight to disk, which is useful for downloading (large) files. - -```{r} -tmp <- tempfile() -curl_download("https://hb.cran.dev/get?bar=456", tmp) -jsonlite::prettify(readLines(tmp)) -``` - -### Streaming data - -The most flexible interface is the `curl` function, which has been designed as a drop-in replacement for base `url`. It will create a so-called connection object, which allows for incremental (asynchronous) reading of the response. - -```{r} -con <- curl("https://hb.cran.dev/get") -open(con) - -# Get 3 lines -out <- readLines(con, n = 3) -cat(out, sep = "\n") - -# Get 3 more lines -out <- readLines(con, n = 3) -cat(out, sep = "\n") - -# Get remaining lines -out <- readLines(con) -close(con) -cat(out, sep = "\n") -``` - -The example shows how to use `readLines` on an opened connection to read `n` lines at a time. Similarly `readBin` is used to read `n` bytes at a time for stream parsing binary data. - -#### Non blocking connections - -As of version 2.3 it is also possible to open connections in non-blocking mode. In this case `readBin` and `readLines` will return immediately with data that is available without waiting. For non-blocking connections we use `isIncomplete` to check if the download has completed yet. - -```{r, eval=FALSE} -# This httpbin mirror doesn't cache -con <- curl("https://nghttp2.org/httpbin/drip?duration=1&numbytes=50") -open(con, "rb", blocking = FALSE) -while(isIncomplete(con)){ - buf <- readBin(con, raw(), 1024) - if(length(buf)) - cat("received: ", rawToChar(buf), "\n") -} -close(con) -``` - -The `curl_fetch_stream` function provides a very simple wrapper around a non-blocking connection. - - -### Async requests - -As of `curl 2.0` the package provides an async interface which can perform multiple simultaneous requests concurrently. The `curl_fetch_multi` adds a request to a pool and returns immediately; it does not actually perform the request. - -```{r} -pool <- new_pool() -cb <- function(req){cat("done:", req$url, ": HTTP:", req$status, "\n")} -curl_fetch_multi('https://www.google.com', done = cb, pool = pool) -curl_fetch_multi('https://cloud.r-project.org', done = cb, pool = pool) -curl_fetch_multi('https://hb.cran.dev/blabla', done = cb, pool = pool) -``` - -When we call `multi_run()`, all scheduled requests are performed concurrently. The callback functions get triggered when each request completes. - -```{r} -# This actually performs requests: -out <- multi_run(pool = pool) -print(out) -``` - -The system allows for running many concurrent non-blocking requests. However it is quite complex and requires careful specification of handler functions. - -## Exception handling - -A HTTP requests can encounter two types of errors: - - 1. Connection failure: network down, host not found, invalid SSL certificate, etc - 2. HTTP non-success status: 401 (DENIED), 404 (NOT FOUND), 503 (SERVER PROBLEM), etc - -The first type of errors (connection failures) will always raise an error in R for each interface. However if the requests succeeds and the server returns a non-success HTTP status code, only `curl()` and `curl_download()` will raise an error. Let's dive a little deeper into this. - -### Error automatically - -The `curl` and `curl_download` functions are safest to use because they automatically raise an error if the request was completed but the server returned a non-success (400 or higher) HTTP status. This mimics behavior of base functions `url` and `download.file`. Therefore we can safely write code like this: - -```{r} -# This is OK -curl_download('https://cloud.r-project.org/CRAN_mirrors.csv', 'mirrors.csv') -mirros <- read.csv('mirrors.csv') -unlink('mirrors.csv') -``` - -If the HTTP request was unsuccessful, R will not continue: - -```{r, error=TRUE, purl = FALSE} -# Oops! A typo in the URL! -curl_download('https://cloud.r-project.org/CRAN_mirrorZ.csv', 'mirrors.csv') -con <- curl('https://cloud.r-project.org/CRAN_mirrorZ.csv') -open(con) -``` - -```{r, echo = FALSE, message = FALSE, warning=FALSE} -close(con) -rm(con) -``` - - -### Check manually - -When using any of the `curl_fetch_*` functions it is important to realize that these do **not** raise an error if the request was completed but returned a non-200 status code. When using `curl_fetch_memory` or `curl_fetch_disk` you need to implement such application logic yourself and check if the response was successful. - -```{r} -req <- curl_fetch_memory('https://cloud.r-project.org/CRAN_mirrors.csv') -print(req$status_code) -``` - -Same for downloading to disk. If you do not check your status, you might have downloaded an error page! - -```{r} -# Oops a typo! -req <- curl_fetch_disk('https://cloud.r-project.org/CRAN_mirrorZ.csv', 'mirrors.csv') -print(req$status_code) - -# This is not the CSV file we were expecting! -head(readLines('mirrors.csv')) -unlink('mirrors.csv') -``` - -If you *do* want the `curl_fetch_*` functions to automatically raise an error, you should set the [`FAILONERROR`](https://curl.se/libcurl/c/CURLOPT_FAILONERROR.html) option to `TRUE` in the handle of the request. - -```{r, error=TRUE, purl = FALSE} -h <- new_handle(failonerror = TRUE) -curl_fetch_memory('https://cloud.r-project.org/CRAN_mirrorZ.csv', handle = h) -``` - -## Customizing requests - -By default libcurl uses HTTP GET to issue a request to an HTTP url. To send a customized request, we first need to create and configure a curl handle object that is passed to the specific download interface. - -### Setting handle options - -Creating a new handle is done using `new_handle`. After creating a handle object, we can set the libcurl options and http request headers. - -```{r} -h <- new_handle() -handle_setopt(h, copypostfields = "moo=moomooo"); -handle_setheaders(h, - "Content-Type" = "text/moo", - "Cache-Control" = "no-cache", - "User-Agent" = "A cow" -) -``` - -Use the `curl_options()` function to get a list of the options supported by your version of libcurl. The [libcurl documentation](https://curl.se/libcurl/c/curl_easy_setopt.html) explains what each option does. Option names are not case sensitive. - -It is important you check the [libcurl documentation](https://curl.se/libcurl/c/curl_easy_setopt.html) to set options of the correct type. Options in libcurl take several types: - - - number - - string - - slist (vector of strings) - - enum (long) option - -The R bindings will automatically do some type checking and coercion to convert R values to appropriate libcurl option values. Logical (boolean) values in R automatically get converted to `0` or `1` for example [CURLOPT_VERBOSE](https://curl.se/libcurl/c/CURLOPT_VERBOSE.html): - - -```{r} -handle <- new_handle(verbose = TRUE) -``` - -However R does not know if an option is actually boolean. So passing `TRUE`/ `FALSE` to any numeric option will simply set it to `0` or `1` without a warning or error. If an option value cannot be coerced, you get an error: - -```{r, error = TRUE} -# URLOPT_MASFILESIZE must be a number -handle_setopt(handle, maxfilesize = "foo") - -# CURLOPT_USERAGENT must be a string -handle_setopt(handle, useragent = 12345) -``` - - -### ENUM (long) options - -Some curl options take an long in C that actually corresponds to an ENUM value. - -For example the [CURLOPT_USE_SSL](https://curl.se/libcurl/c/CURLOPT_USE_SSL.html) docs explains that there are 4 possible values for this option: `CURLUSESSL_NONE`, `CURLUSESSL_TRY`, `CURLUSESSL_CONTROL`, and `CURLUSESSL_ALL`. To use this option you have to lookup the integer values for these enums in the symbol table. These symbol values never change, so you only need to lookup the value you need once and then hardcode the integer value in your R code. - -```{r} -curl::curl_symbols("CURLUSESSL") -``` - -So suppose we want to set `CURLOPT_USE_SSL` to `CURLUSESSL_ALL` we would use this R code: - -```{r} -handle_setopt(handle, use_ssl = 3) -``` - -### Disabling HTTP/2 - -Another example is the [CURLOPT_HTTP_VERSION](https://curl.se/libcurl/c/CURLOPT_HTTP_VERSION.html) option. This option is needed to disable or enable HTTP/2. However some users are not aware this is actually an ENUM and not a regular numeric value! - -The [docs](https://curl.se/libcurl/c/CURLOPT_HTTP_VERSION.html) explain HTTP_VERSION can be set to one of several strategies for negotiating the HTTP version between client and server. Valid values are: - -```{r} -curl_symbols('CURL_HTTP_VERSION_') -``` - -As seen, the value `2` corresponds to `CURL_HTTP_VERSION_1_1` and `3` corresponds to `CURL_HTTP_VERSION_2_0`. - -As of libcurl 7.62.0, the default `http_version` is `CURL_HTTP_VERSION_2TLS` which uses HTTP/2 when possible, but only for HTTPS connections. Package authors should usually leave the default to let curl select the best appropriate http protocol. - -One exception is when writing a client for a server that seems to be running a buggy HTTP/2 server. Unfortunately this is not uncommon, and curl is a bit more picky than browsers. If you are frequently seeing `Error in the HTTP2 framing layer` error messages, then there is likely a problem with the HTTP/2 layer on the server. - -The easiest remedy is to __disable http/2__ for this server by forcing http 1.1 until the service has upgraded their webservers. To do so, set the `http_version` to `CURL_HTTP_VERSION_1_1` (value: `2`): - -```{r} -# Force using HTTP 1.1 (the number 2 is an enum value, see above) -handle_setopt(handle, http_version = 2) -``` - -Note that the value `1` corresponds to HTTP 1.0 which is a legacy version of HTTP that you should not use! -Code that sets `http_version` to `1` (or even `1.1` which R simply rounds to 1) is almost always a bug. - -## Performing the request - -After the handle has been configured, it can be used with any of the download interfaces to perform the request. For example `curl_fetch_memory` will load store the output of the request in memory: - -```{r} -req <- curl_fetch_memory("https://hb.cran.dev/post", handle = h) -jsonlite::prettify(rawToChar(req$content)) -``` - -Alternatively we can use `curl()` to read the data of via a connection interface: - -```{r} -con <- curl("https://hb.cran.dev/post", handle = h) -jsonlite::prettify(readLines(con)) -``` - -```{r, echo = FALSE, message = FALSE, warning=FALSE} -close(con) -``` - -Or we can use `curl_download` to write the response to disk: - -```{r} -tmp <- tempfile() -curl_download("https://hb.cran.dev/post", destfile = tmp, handle = h) -jsonlite::prettify(readLines(tmp)) -``` - -Or perform the same request with a multi pool: - -```{r} -curl_fetch_multi("https://hb.cran.dev/post", handle = h, done = function(res){ - cat("Request complete! Response content:\n") - cat(rawToChar(res$content)) -}) - -# Perform the request -out <- multi_run() -``` - -### Reading cookies - -Curl handles automatically keep track of cookies set by the server. At any given point we can use `handle_cookies` to see a list of current cookies in the handle. - -```{r} -# Start with a fresh handle -h <- new_handle() - -# Ask server to set some cookies -req <- curl_fetch_memory("https://hb.cran.dev/cookies/set?foo=123&bar=ftw", handle = h) -req <- curl_fetch_memory("https://hb.cran.dev/cookies/set?baz=moooo", handle = h) -handle_cookies(h) - -# Unset a cookie -req <- curl_fetch_memory("https://hb.cran.dev/cookies/delete?foo", handle = h) -handle_cookies(h) -``` - -The `handle_cookies` function returns a data frame with 7 columns as specified in the [netscape cookie file format](http://www.cookiecentral.com/faq/#3.5). - -### On reusing handles - -In most cases you should not re-use a single handle object for more than one request. The only benefit of reusing a handle for multiple requests is to keep track of cookies set by the server (seen above). This could be needed if your server uses session cookies, but this is rare these days. Most APIs set state explicitly via http headers or parameters, rather than implicitly via cookies. - -In recent versions of the curl package there are no performance benefits of reusing handles. The overhead of creating and configuring a new handle object is negligible. The safest way to issue multiple requests, either to a single server or multiple servers is by using a separate handle for each request (which is the default) - -```{r} -req1 <- curl_fetch_memory("https://hb.cran.dev/get") -req2 <- curl_fetch_memory("https://www.r-project.org") -``` - -In past versions of this package you needed to manually use a handle to take advantage of http Keep-Alive. However as of version 2.3 this is no longer the case: curl automatically maintains global a pool of open http connections shared by all handles. When performing many requests to the same server, curl automatically uses existing connections when possible, eliminating TCP/SSL handshaking overhead: - -```{r} -req <- curl_fetch_memory("https://api.github.com/users/ropensci") -req$times - -req2 <- curl_fetch_memory("https://api.github.com/users/rstudio") -req2$times -``` - -If you really need to re-use a handle, do note that that curl does not cleanup the handle after each request. All of the options and internal fields will linger around for all future request until explicitly reset or overwritten. This can sometimes leads to unexpected behavior. - -```{r} -handle_reset(h) -``` - -The `handle_reset` function will reset all curl options and request headers to the default values. It will **not** erase cookies and it will still keep alive the connections. Therefore it is good practice to call `handle_reset` after performing a request if you want to reuse the handle for a subsequent request. Still it is always safer to create a new fresh handle when possible, rather than recycling old ones. - -### Posting forms - -The `handle_setform` function is used to perform a `multipart/form-data` HTTP POST request (a.k.a. posting a form). Values can be either strings, raw vectors (for binary data) or files. - -```{r} -# Posting multipart -h <- new_handle() -handle_setform(h, - foo = "blabla", - bar = charToRaw("boeboe"), - iris = form_data(serialize(iris, NULL), "application/rda"), - description = form_file(system.file("DESCRIPTION")), - logo = form_file(file.path(R.home('doc'), "html/logo.jpg"), "image/jpeg") -) -req <- curl_fetch_memory("https://hb.cran.dev/post", handle = h) -``` - -The `form_file` function is used to upload files with the form post. It has two arguments: a file path, and optionally a content-type value. If no content-type is set, curl will guess the content type of the file based on the file extension. - -The `form_data` function is similar but simply posts a string or raw value with a custom content-type. - -### Using pipes - -All of the `handle_xxx` functions return the handle object so that function calls can be chained using the popular pipe operators: - -```{r} -library(magrittr) - -new_handle() %>% - handle_setopt(copypostfields = "moo=moomooo") %>% - handle_setheaders("Content-Type"="text/moo", "Cache-Control"="no-cache", "User-Agent"="A cow") %>% - curl_fetch_memory(url = "https://hb.cran.dev/post") %$% content %>% - rawToChar %>% jsonlite::prettify() -```