1 /*
2 *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 *
4 * Copyright (C) 2017 - ESI-Group - Cedric Delamarre
5 *
6 * This file is hereby licensed under the terms of the GNU GPL v2.0,
7 * pursuant to article 5.3.4 of the CeCILL v.2.1.
8 * This file was originally licensed under the terms of the CeCILL v2.1,
9 * and continues to be available under such terms.
10 * For more information, see the COPYING file which you should have received
11 * along with this program.
12 *
13 */
14 #include <stdio.h>
15 #include "sciCurl.hxx"
16 #include "string.hxx"
17 #include "json.hxx"
18 
19 extern "C"
20 {
21     #include "getScilabPreference.h"
22     #include "freeArrayOfString.h"
23     #include "getos.h"
24     #include "version.h"
25 }
26 
27 SciCurl* SciCurl::me = nullptr;
28 std::string SciCurl::data;
29 bool SciCurl::useFile = false;
30 
getInstance(void)31 SciCurl* SciCurl::getInstance(void)
32 {
33     if(me == nullptr)
34     {
35         me = new SciCurl();
36     }
37 
38     return me;
39 }
40 
destroyInstance(void)41 void SciCurl::destroyInstance(void)
42 {
43     if (me)
44     {
45         delete me;
46         me = nullptr;
47     }
48 }
49 
SciCurl()50 SciCurl::SciCurl()
51 {
52     curl_global_init(CURL_GLOBAL_ALL);
53 }
54 
~SciCurl()55 SciCurl::~SciCurl()
56 {
57     curl_global_cleanup();
58 }
59 
getResultAsObject(CURL * curl)60 void SciCurl::getResultAsObject(CURL* curl)
61 {
62     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, SciCurl::write_result);
63     useFile = false;
64 }
65 
getResultAsFile(CURL * curl,FILE * fd)66 void SciCurl::getResultAsFile(CURL* curl, FILE* fd)
67 {
68 #ifdef _MSC_VER
69     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, SciCurl::write_result);
70     curl_easy_setopt(curl, CURLOPT_WRITEDATA, fd);
71     useFile = true;
72 #else
73     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, NULL);
74     curl_easy_setopt(curl, CURLOPT_WRITEDATA, fd);
75 #endif
76 }
77 
getResult()78 types::InternalType* SciCurl::getResult()
79 {
80     types::InternalType* res = fromJSON(data);
81     if (res == nullptr)
82     {
83         res = new types::String(data.c_str());
84     }
85 
86     clear();
87 
88     return res;
89 }
90 
clear()91 void SciCurl::clear()
92 {
93     data.clear();
94 }
95 
write_result(char * pcInput,size_t size,size_t nmemb,void * output)96 int SciCurl::write_result(char* pcInput, size_t size, size_t nmemb, void* output)
97 {
98 #ifdef _MSC_VER
99     if(useFile)
100     {
101         FILE* fd = (FILE*)output;
102         fwrite(pcInput, size, nmemb, fd);
103         return static_cast<int>(size*nmemb);
104     }
105 #endif
106 
107     std::string d(pcInput, size * nmemb);
108     data += d;
109     return static_cast<int>(size*nmemb);
110 }
111 
112 // Proxy is configured in scilab preferences (internet tab)
setProxy(CURL * curl)113 int SciCurl::setProxy(CURL* curl)
114 {
115     char* proxyUserPwd = NULL;
116     const char* attrs[] = {"enabled", "host", "port", "user", "password"};
117     const unsigned int N = sizeof(attrs) / sizeof(char*);
118     char** values = getPrefAttributesValues("//web/body/proxy", attrs, N);
119 
120     if (values == NULL)
121     {
122         // no proxy configured
123         return 0;
124     }
125 
126     // proxy is configured and not enabled
127     if (stricmp(values[0]/*enabled*/, "false") == 0)
128     {
129         freeArrayOfString(values, N);
130         return 0;
131     }
132 
133     const unsigned int host_len = (const unsigned int)strlen(values[1]);
134     const unsigned int port_len = (const unsigned int)strlen(values[2]);
135     const unsigned int user_len = (const unsigned int)strlen(values[3]);
136     const unsigned int pwd_len  = (const unsigned int)strlen(values[4]);
137 
138     if(host_len == 0 || port_len == 0 || user_len == 0)
139     {
140         freeArrayOfString(values, N);
141         return 1;
142     }
143 
144     if (pwd_len == 0)
145     {
146         proxyUserPwd = values[3]; //user
147     }
148     else
149     {
150         proxyUserPwd = (char *)MALLOC((user_len + 1 + pwd_len + 1) * sizeof(char));
151         sprintf(proxyUserPwd, "%s:%s", values[3]/*user*/, values[4]/*password*/);
152         proxyUserPwd[user_len + 1 + pwd_len] = '\0';
153     }
154 
155     // set cURL options
156     if(curl_easy_setopt(curl, CURLOPT_PROXY, values[1]) != CURLE_OK) //host
157     {
158         FREE(proxyUserPwd);
159         freeArrayOfString(values, N);
160         return 1;
161     }
162 
163     if(curl_easy_setopt(curl, CURLOPT_PROXYPORT, strtol(values[2], NULL, 10)) != CURLE_OK) //port
164     {
165         FREE(proxyUserPwd);
166         freeArrayOfString(values, N);
167         return 1;
168     }
169 
170     if(curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, proxyUserPwd) != CURLE_OK) //port
171     {
172         FREE(proxyUserPwd);
173         freeArrayOfString(values, N);
174         return 1;
175     }
176 
177     FREE(proxyUserPwd);
178     freeArrayOfString(values, N);
179     return 0;
180 }
181 
setCommonHeaders(CURL * curl)182 void SciCurl::setCommonHeaders(CURL* curl)
183 {
184     char* OperatingSystem = getOSFullName();
185     char* Release = getOSRelease();
186 
187     // Scilab version
188     std::string pcUserAgent = "Scilab/" + std::to_string(SCI_VERSION_MAJOR)+"."+ std::to_string(SCI_VERSION_MINOR)+"."+ std::to_string(SCI_VERSION_MAINTENANCE);
189     // OS name
190     pcUserAgent += " (" + std::string(OperatingSystem) + " " + std::string(Release) + ")";
191     // set user agent header
192     curl_easy_setopt(curl, CURLOPT_USERAGENT, pcUserAgent.data());
193 
194     FREE(OperatingSystem);
195     FREE(Release);
196 }