/src/clib/deps/http-get/http-get.c
Line | Count | Source |
1 | | |
2 | | // |
3 | | // http-get.c |
4 | | // |
5 | | // Copyright (c) 2013 Stephen Mathieson |
6 | | // MIT licensed |
7 | | // |
8 | | |
9 | | #include <curl/curl.h> |
10 | | #include <string.h> |
11 | | #include <stdlib.h> |
12 | | #include "http-get.h" |
13 | | |
14 | | /** |
15 | | * HTTP GET write callback |
16 | | */ |
17 | | |
18 | 0 | static size_t http_get_cb(void *contents, size_t size, size_t nmemb, void *userp) { |
19 | 0 | size_t realsize = size * nmemb; |
20 | 0 | http_get_response_t *res = userp; |
21 | |
|
22 | 0 | if (0 == res->data) { |
23 | 0 | res->data = malloc(realsize + 1); |
24 | 0 | } else { |
25 | 0 | void *ptr = realloc(res->data, res->size + realsize + 1); |
26 | |
|
27 | 0 | if (NULL == ptr) { |
28 | 0 | fprintf(stderr, "not enough memory!"); |
29 | 0 | return 0; |
30 | 0 | } |
31 | | |
32 | 0 | res->data = ptr; |
33 | 0 | } |
34 | | |
35 | 0 | memset(res->data + res->size, 0, realsize); |
36 | 0 | memcpy(res->data + res->size, contents, realsize); |
37 | 0 | res->size += realsize; |
38 | 0 | res->data[res->size] = 0; |
39 | |
|
40 | 0 | return realsize; |
41 | 0 | } |
42 | | |
43 | 0 | http_get_response_t *http_get_shared(const char *url, CURLSH *share) { |
44 | 0 | CURL *req = curl_easy_init(); |
45 | |
|
46 | 0 | http_get_response_t *res = malloc(sizeof(http_get_response_t)); |
47 | 0 | memset(res, 0, sizeof(http_get_response_t)); |
48 | |
|
49 | 0 | if (share) { |
50 | 0 | curl_easy_setopt(req, CURLOPT_SHARE, share); |
51 | 0 | } |
52 | |
|
53 | 0 | curl_easy_setopt(req, CURLOPT_URL, url); |
54 | 0 | curl_easy_setopt(req, CURLOPT_HTTPGET, 1); |
55 | 0 | curl_easy_setopt(req, CURLOPT_FOLLOWLOCATION, 1); |
56 | 0 | curl_easy_setopt(req, CURLOPT_WRITEFUNCTION, http_get_cb); |
57 | 0 | curl_easy_setopt(req, CURLOPT_WRITEDATA, (void *) res); |
58 | 0 | curl_easy_setopt(req, CURLOPT_USERAGENT, "http-get.c/"HTTP_GET_VERSION); |
59 | |
|
60 | 0 | int c = curl_easy_perform(req); |
61 | |
|
62 | 0 | curl_easy_getinfo(req, CURLINFO_RESPONSE_CODE, &res->status); |
63 | 0 | res->ok = (200 == res->status && CURLE_ABORTED_BY_CALLBACK != c) ? 1 : 0; |
64 | 0 | curl_easy_cleanup(req); |
65 | |
|
66 | 0 | return res; |
67 | 0 | } |
68 | | |
69 | | /** |
70 | | * Perform an HTTP(S) GET on `url` |
71 | | */ |
72 | | |
73 | 0 | http_get_response_t *http_get(const char *url) { |
74 | 0 | return http_get_shared(url, NULL); |
75 | 0 | } |
76 | | |
77 | | /** |
78 | | * HTTP GET file write callback |
79 | | */ |
80 | | |
81 | 0 | static size_t http_get_file_cb(void *ptr, size_t size, size_t nmemb, void *stream) { |
82 | 0 | fflush(stream); |
83 | 0 | size_t n = fwrite(ptr, size, nmemb, stream); |
84 | 0 | return n; |
85 | 0 | } |
86 | | |
87 | | /** |
88 | | * Request `url` and save to `file` |
89 | | */ |
90 | | |
91 | 0 | int http_get_file_shared(const char *url, const char *file, CURLSH *share) { |
92 | 0 | CURL *req = curl_easy_init(); |
93 | 0 | if (!req) return -1; |
94 | | |
95 | 0 | FILE *fp = fopen(file, "wb"); |
96 | 0 | if (!fp) return -1; |
97 | | |
98 | 0 | if (share) { |
99 | 0 | curl_easy_setopt(req, CURLOPT_SHARE, share); |
100 | 0 | } |
101 | |
|
102 | 0 | curl_easy_setopt(req, CURLOPT_URL, url); |
103 | 0 | curl_easy_setopt(req, CURLOPT_HTTPGET, 1); |
104 | 0 | curl_easy_setopt(req, CURLOPT_FOLLOWLOCATION, 1); |
105 | 0 | curl_easy_setopt(req, CURLOPT_WRITEFUNCTION, http_get_file_cb); |
106 | 0 | curl_easy_setopt(req, CURLOPT_WRITEDATA, fp); |
107 | 0 | int res = curl_easy_perform(req); |
108 | |
|
109 | 0 | long status; |
110 | 0 | curl_easy_getinfo(req, CURLINFO_RESPONSE_CODE, &status); |
111 | |
|
112 | 0 | curl_easy_cleanup(req); |
113 | 0 | fclose(fp); |
114 | |
|
115 | 0 | return (200 == status && CURLE_ABORTED_BY_CALLBACK != res) ? 0 : -1; |
116 | 0 | } |
117 | | |
118 | 0 | int http_get_file(const char *url, const char *file) { |
119 | 0 | return http_get_file_shared(url, file, NULL); |
120 | 0 | } |
121 | | |
122 | | /** |
123 | | * Free the given `res` |
124 | | */ |
125 | | |
126 | 0 | void http_get_free(http_get_response_t *res) { |
127 | 0 | if (NULL == res) return; |
128 | 0 | if (NULL != res->data) free(res->data); |
129 | | res->data = NULL; |
130 | 0 | res->size = 0; |
131 | 0 | free(res); |
132 | 0 | } |