1 /* *
2  * Blocking easy interfaces to libcurl for R.
3  * Example: https://curl.se/libcurl/c/getinmemory.html
4  */
5 
6 #include "curl-common.h"
7 
R_curl_fetch_memory(SEXP url,SEXP ptr,SEXP nonblocking)8 SEXP R_curl_fetch_memory(SEXP url, SEXP ptr, SEXP nonblocking){
9   if (!isString(url) || length(url) != 1)
10     error("Argument 'url' must be string.");
11 
12   /* get the handle */
13   CURL *handle = get_handle(ptr);
14 
15   /* update the url */
16   curl_easy_setopt(handle, CURLOPT_URL, CHAR(STRING_ELT(url, 0)));
17 
18   /* reset the response header buffer */
19   reset_resheaders(get_ref(ptr));
20   reset_errbuf(get_ref(ptr));
21 
22   /* buffer body */
23   memory body = {NULL, 0};
24   curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, append_buffer);
25   curl_easy_setopt(handle, CURLOPT_WRITEDATA, &body);
26 
27   /* perform blocking request */
28   CURLcode status = asLogical(nonblocking) ?
29     curl_perform_with_interrupt(handle) : curl_easy_perform(handle);
30 
31   /* Reset for reuse */
32   curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, NULL);
33   curl_easy_setopt(handle, CURLOPT_WRITEDATA, NULL);
34 
35   /* check for errors */
36   if (status != CURLE_OK) {
37     free(body.buf);
38     assert_status(status, get_ref(ptr));
39   }
40 
41   /* create output */
42   SEXP out = PROTECT(allocVector(RAWSXP, body.size));
43 
44   /* copy only if there is actual content */
45   if(body.size)
46     memcpy(RAW(out), body.buf, body.size);
47 
48   /* cleanup and return */
49   UNPROTECT(1);
50   free(body.buf);
51   return out;
52 }
53 
R_curl_fetch_disk(SEXP url,SEXP ptr,SEXP path,SEXP mode,SEXP nonblocking)54 SEXP R_curl_fetch_disk(SEXP url, SEXP ptr, SEXP path, SEXP mode, SEXP nonblocking){
55   if (!isString(url) || length(url) != 1)
56     error("Argument 'url' must be string.");
57   if (!isString(path) || length(path) != 1)
58     error("`path` must be string.");
59 
60   /* get the handle */
61   CURL *handle = get_handle(ptr);
62 
63   /* update the url */
64   curl_easy_setopt(handle, CURLOPT_URL, CHAR(STRING_ELT(url, 0)));
65 
66   /* reset the response header buffer */
67   reset_resheaders(get_ref(ptr));
68   reset_errbuf(get_ref(ptr));
69 
70   /* open file */
71   FILE *dest = fopen(CHAR(asChar(path)), CHAR(asChar(mode)));
72   if(!dest)
73     error("Failed to open file %s.", CHAR(asChar(path)));
74   curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, push_disk);
75   curl_easy_setopt(handle, CURLOPT_WRITEDATA, dest);
76 
77   /* perform blocking request */
78   CURLcode status = asLogical(nonblocking) ?
79     curl_perform_with_interrupt(handle): curl_easy_perform(handle);
80 
81   /* cleanup */
82   curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, NULL);
83   curl_easy_setopt(handle, CURLOPT_WRITEDATA, NULL);
84   fclose(dest);
85 
86   /* check for errors */
87   assert_status(status, get_ref(ptr));
88 
89   /* return the file path */
90   return path;
91 }
92