Coverage Report

Created: 2025-12-14 06:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}