1 /*
2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2017 - ESI-Group - Cedric DELAMARRE
4 *
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 /*--------------------------------------------------------------------------*/
15
16 #include <curl/curl.h>
17 #include "webtools_gw.hxx"
18 #include "function.hxx"
19 #include "string.hxx"
20 #include "double.hxx"
21 #include "json.hxx"
22 #include "sciCurl.hxx"
23
24 extern "C"
25 {
26 #include "localization.h"
27 #include "Scierror.h"
28 #include "sciprint.h"
29 #include "sci_malloc.h"
30 }
31
32 /*--------------------------------------------------------------------------*/
sci_http_put_post(types::typed_list & in,types::optional_list & opt,int _iRetCount,types::typed_list & out,const char * fname)33 types::Function::ReturnValue sci_http_put_post(types::typed_list &in, types::optional_list &opt, int _iRetCount, types::typed_list &out, const char* fname)
34 {
35 SciCurl* sciCurlObj = SciCurl::getInstance();
36 CURLcode res = CURLE_OK;
37 struct curl_slist *headers = NULL;
38 bool isJson = false;
39 char* pcData = NULL;
40
41 if (in.size() < 1 || in.size() > 2)
42 {
43 Scierror(77, _("%s: Wrong number of input argument(s): %d to %d expected.\n"), fname, 1, 2);
44 return types::Function::Error;
45 }
46
47 if (_iRetCount > 2)
48 {
49 Scierror(78, _("%s: Wrong number of output argument(s): %d to %d expected.\n"), fname, 1, 2);
50 return types::Function::Error;
51 }
52
53 // get URL
54 if(in[0]->isString() == false && in[0]->getAs<types::String>()->isScalar() == false)
55 {
56 Scierror(999, _("%s: Wrong type for input argument #%d: A scalar string expected.\n"), fname, 1);
57 return types::Function::Error;
58 }
59
60 CURL* curl = curl_easy_init();
61 if(curl == nullptr)
62 {
63 Scierror(999, _("%s: CURL initialization failed.\n"), fname);
64 return types::Function::Error;
65 }
66
67 sciCurlObj->setCommonHeaders(curl);
68
69 char* pcURL = wide_string_to_UTF8(in[0]->getAs<types::String>()->get(0));
70 curl_easy_setopt(curl, CURLOPT_URL, pcURL);
71 FREE(pcURL);
72
73 sciCurlObj->getResultAsObject(curl);
74 if(strcmp(fname, "http_put") == 0)
75 {
76 curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");
77 }
78 else if(strcmp(fname, "http_patch") == 0)
79 {
80 curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PATCH");
81 }
82 else
83 {
84 curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
85 }
86
87 // common optional argument
88 if(checkCommonOpt((void*)curl, opt, fname))
89 {
90 return types::Function::Error;
91 }
92
93 // set proxy information
94 if(sciCurlObj->setProxy(curl))
95 {
96 Scierror(999, _("%s: Wrong proxy information, please check in the 'internet' Scilab preference.\n"), fname);
97 return types::Function::Error;
98 }
99
100 // specific optional argument
101 for (const auto& o : opt)
102 {
103 if(o.first == L"format")
104 {
105 if(o.second->isString() == false && o.second->getAs<types::String>()->isScalar() == false)
106 {
107 Scierror(999, _("%s: Wrong type for input argument #%s: A scalar string expected.\n"), fname, o.first.data());
108 return types::Function::Error;
109 }
110
111 if( (wcscmp(o.second->getAs<types::String>()->get(0), L"JSON") == 0) ||
112 (wcscmp(o.second->getAs<types::String>()->get(0), L"json") == 0))
113 {
114 isJson = true;
115 }
116 }
117 }
118
119 if(in.size() > 1)
120 {
121 // get data
122 if(in[1]->isString() && in[1]->getAs<types::String>()->isScalar())
123 {
124 pcData = wide_string_to_UTF8(in[1]->getAs<types::String>()->get(0));
125 }
126 else
127 {
128 pcData = os_strdup(toJSON(in[1]).c_str());
129 isJson = true;
130 }
131
132 if(isJson)
133 {
134 headers = curl_slist_append(headers, "Accept: application/json");
135 headers = curl_slist_append(headers, "Content-Type: application/json");
136 headers = curl_slist_append(headers, "charsets: utf-8");
137 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
138 }
139
140 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, pcData);
141 }
142
143 res = curl_easy_perform(curl);
144 if (pcData)
145 {
146 FREE(pcData);
147 }
148
149 if(headers)
150 {
151 curl_slist_free_all(headers);
152 }
153
154 if(res != CURLE_OK)
155 {
156 Scierror(999, _("%s: CURL execution failed.\n%s\n"), fname, curl_easy_strerror(res));
157 sciCurlObj->clear();
158 return types::Function::Error;
159 }
160
161 out.push_back(sciCurlObj->getResult());
162
163 if(_iRetCount == 2)
164 {
165 long http_code = 0;
166 curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &http_code);
167 out.push_back(new types::Double((double)http_code));
168 }
169
170 curl_easy_cleanup(curl);
171 return types::Function::OK;
172 }
173