aboutsummaryrefslogtreecommitdiff
path: root/src/curl.cpp
blob: a3c5e2816e9c060e891face409a56d1b03b6e314 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
#include "../include/curl.hpp"
#include "../include/env.hpp"
#include <curl/curl.h>
#include <cstring>

using namespace std;

#if OS_FAMILY == OS_FAMILY_WINDOWS
#pragma comment(lib, "Ws2_32.lib")
#pragma comment(lib, "Wldap32.lib")
#pragma comment(lib, "Crypt32.lib")
#endif

#ifdef DEBUG
#define CURL_DEBUG
#endif

#undef CURL_DEBUG

class CurlSession
{
public:
    CurlSession()
    {
        curl_global_init(CURL_GLOBAL_ALL);
    }

    ~CurlSession()
    {
        curl_global_cleanup();
    }
};

static CurlSession curlSession;

namespace sibs
{
    // TODO: Instead of writing to file, reading from file and extracting it;
    // we can extract to file directly by putting libarchive code here
    size_t writeToFile(char *data, size_t size, size_t nmemb, FILE *stream)
    {
        if(!stream) return 0;
        return fwrite(data, size, nmemb, stream);
    }

    size_t writeToString(char *data, size_t size, size_t nmemb, string *writerData)
    {
        if(!writerData) return 0;
        writerData->append(data, size * nmemb);
        return size * nmemb;
    }

    Result<bool> curl::downloadFile(const char *url, const _tinydir_char_t *filepath)
    {
        CURL *curl_handle = curl_easy_init();
        curl_easy_setopt(curl_handle, CURLOPT_URL, url);
#ifdef CURL_DEBUG
        long verbose = 1L;
        long noProgressMeter = 0L;
#else
        long verbose = 0L;
        long noProgressMeter = 1L;
#endif
        curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, verbose);
        curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, noProgressMeter);
        curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, writeToFile);
        curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, true);
        curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "SIBS");
        curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, FALSE);
#if OS_FAMILY == OS_FAMILY_POSIX
        FILE *file = fopen(filepath, "wb");
#else
        FILE *file = _wfopen(filepath, L"wb");
#endif
        if(!file)
        {
            int error = errno;
            curl_easy_cleanup(curl_handle);

            string errMsg = "Failed to open file for writing: ";
            errMsg += toUtf8(filepath);
            if(error != 0)
            {
                errMsg += "; Reason: ";
                errMsg += strerror(error);
                return Result<bool>::Err(errMsg);
            }
            else
            {
                return Result<bool>::Err(errMsg);
            }
        }

        curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, file);
        printf("Downloading from url: %s\n", url);
        CURLcode curlResponse = curl_easy_perform(curl_handle);

        long httpCode = 0;
        curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &httpCode);
        curl_easy_cleanup(curl_handle);
        fclose(file);

        if(httpCode == 200 && curlResponse == CURLE_OK)
            return Result<bool>::Ok(true);

        if(httpCode != 200)
        {
            string errMsg = "Failed to download file from url: ";
            errMsg += url;
            errMsg += "\nReason: Expected http response code 200 (OK), got: ";
            errMsg += to_string(httpCode);
            errMsg += " (";
            errMsg += curl_easy_strerror(curlResponse);
            errMsg += ")";
            return Result<bool>::Err(errMsg);
        }
        else
        {
            string errMsg = "Failed to download file from url: ";
            errMsg += url;
            errMsg += "\nReason: ";
            errMsg += curl_easy_strerror(curlResponse);
            return Result<bool>::Err(errMsg);
        }
    }

    HttpResult curl::get(const char *url)
    {
        HttpResult result;

        CURL *curl_handle = curl_easy_init();
        curl_easy_setopt(curl_handle, CURLOPT_URL, url);
#ifdef CURL_DEBUG
        long verbose = 1L;
        long noProgressMeter = 0L;
#else
        long verbose = 0L;
        long noProgressMeter = 1L;
#endif
        curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, verbose);
        curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, noProgressMeter);
        curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, writeToString);
        curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, true);
        curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "SIBS");
        curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, FALSE);
		
        curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, &result.str);
        printf("Downloading from url: %s\n", url);
        CURLcode curlResponse = curl_easy_perform(curl_handle);

        long httpCode = 0;
        curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &httpCode);
        curl_easy_cleanup(curl_handle);

        result.httpCode = httpCode;
        if(httpCode == 200 && curlResponse == CURLE_OK)
        {
            result.success = true;
            return result;
        }

        result.success = false;
        if(httpCode != 200)
        {
            string errMsg = "Failed to download file from url: ";
            errMsg += url;
            errMsg += "\nReason: Expected http response code 200 (OK), got: ";
            errMsg += to_string(httpCode);
            errMsg += " (";
            errMsg += curl_easy_strerror(curlResponse);
            errMsg += ")";
            return result;
        }
        else
        {
            string errMsg = "Failed to download file from url: ";
            errMsg += url;
            errMsg += "\nReason: ";
            errMsg += curl_easy_strerror(curlResponse);
            return result;
        }
    }
}