3876984110226102005c2b627f31129e53dc5a3f
[scilab.git] / scilab / modules / webtools / sci_gateway / cpp / sci_http_put_post.cpp
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 /*--------------------------------------------------------------------------*/
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     char* pcURL = wide_string_to_UTF8(in[0]->getAs<types::String>()->get(0));
68     curl_easy_setopt(curl, CURLOPT_URL, pcURL);
69     FREE(pcURL);
70
71     sciCurlObj->getResultAsObject(curl);
72     if(strcmp(fname, "http_put") == 0)
73     {
74         curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");
75     }
76     else if(strcmp(fname, "http_patch") == 0)
77     {
78         curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PATCH");
79     }
80     else
81     {
82         curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
83     }
84
85     // common optional argument
86     if(checkCommonOpt((void*)curl, opt, fname))
87     {
88         return types::Function::Error;
89     }
90
91     // set proxy information
92     if(sciCurlObj->setProxy(curl))
93     {
94         Scierror(999, _("%s: Wrong proxy information, please check in the 'internet' Scilab preference.\n"), fname);
95         return types::Function::Error;
96     }
97
98     // specific optional argument
99     for (const auto& o : opt)
100     {
101         if(o.first == L"format")
102         {
103             if(o.second->isString() == false && o.second->getAs<types::String>()->isScalar() == false)
104             {
105                 Scierror(999, _("%s: Wrong type for input argument #%s: A scalar string expected.\n"), fname, o.first.data());
106                 return types::Function::Error;
107             }
108
109             if( (wcscmp(o.second->getAs<types::String>()->get(0), L"JSON") == 0) ||
110                 (wcscmp(o.second->getAs<types::String>()->get(0), L"json") == 0))
111             {
112                 isJson = true;
113             }
114         }
115     }
116
117     if(in.size() > 1)
118     {
119         // get data
120         if(in[1]->isString() && in[1]->getAs<types::String>()->isScalar())
121         {
122             pcData = wide_string_to_UTF8(in[1]->getAs<types::String>()->get(0));
123         }
124         else
125         {
126             pcData = os_strdup(toJSON(in[1]).c_str());
127             isJson = true;
128         }
129
130         if(isJson)
131         {
132             headers = curl_slist_append(headers, "Accept: application/json");
133             headers = curl_slist_append(headers, "Content-Type: application/json");
134             headers = curl_slist_append(headers, "charsets: utf-8");
135             curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
136         }
137
138         curl_easy_setopt(curl, CURLOPT_POSTFIELDS, pcData);
139     }
140
141     res = curl_easy_perform(curl);
142     if (pcData)
143     {
144         FREE(pcData);
145     }
146
147     if(headers)
148     {
149         curl_slist_free_all(headers);
150     }
151
152     if(res != CURLE_OK)
153     {
154         Scierror(999, _("%s: CURL execution failed.\n%s\n"), fname, curl_easy_strerror(res));
155         sciCurlObj->clear();
156         return types::Function::Error;
157     }
158
159     out.push_back(sciCurlObj->getResult());
160
161     if(_iRetCount == 2)
162     {
163         long http_code = 0;
164         curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &http_code);
165         out.push_back(new types::Double((double)http_code));
166     }
167
168     curl_easy_cleanup(curl);
169     return types::Function::OK;
170 }