2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2017 - ESI-Group - Cedric DELAMARRE
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.
14 /*--------------------------------------------------------------------------*/
16 #include <curl/curl.h>
17 #include "webtools_gw.hxx"
18 #include "function.hxx"
22 #include "sciCurl.hxx"
27 #include "localization.h"
30 #include "sci_malloc.h"
31 #include "getFullFilename.h"
34 /*--------------------------------------------------------------------------*/
35 static const char fname[] = "http_upload";
36 types::Function::ReturnValue sci_http_upload(types::typed_list &in, types::optional_list &opt, int _iRetCount, types::typed_list &out)
38 SciCurl* sciCurlObj = SciCurl::getInstance();
39 CURLcode res = CURLE_OK;
41 if (in.size() < 3 || in.size() > 4)
43 Scierror(77, _("%s: Wrong number of input argument(s): %d to %d expected.\n"), fname, 3, 4);
44 return types::Function::Error;
49 Scierror(78, _("%s: Wrong number of output argument(s): %d to %d expected.\n"), fname, 1, 2);
50 return types::Function::Error;
54 if(in[0]->isString() == false && in[0]->getAs<types::String>()->isScalar() == false)
56 Scierror(999, _("%s: Wrong type for input argument #%d: A scalar string expected.\n"), fname, 1);
57 return types::Function::Error;
60 CURL* curl = curl_easy_init();
63 Scierror(999, _("%s: CURL initialization failed.\n"), fname);
64 return types::Function::Error;
67 char* pcURL = wide_string_to_UTF8(in[0]->getAs<types::String>()->get(0));
68 curl_easy_setopt(curl, CURLOPT_URL, pcURL);
71 // get input file name
72 if(in[1]->isString() == false)
74 Scierror(999, _("%s: Wrong type for input argument #%d: A matrix string expected.\n"), fname, 2);
75 return types::Function::Error;
78 types::String* pStrFiles = in[1]->getAs<types::String>();
79 std::vector<char*> files;
80 for(int i = 0; i < pStrFiles->getSize(); i++)
82 wchar_t* pwcFileName = getFullFilenameW(pStrFiles->get(i));
83 files.push_back(wide_string_to_UTF8(pwcFileName));
87 // get variable name server side
88 if(in[2]->isString() == false && in[2]->getAs<types::String>()->isScalar() == false)
90 Scierror(999, _("%s: Wrong type for input argument #%d: A scalar string expected.\n"), fname, 3);
91 return types::Function::Error;
94 char* pcVarName = wide_string_to_UTF8(in[2]->getAs<types::String>()->get(0));
96 struct curl_httppost *formpost = NULL;
97 struct curl_httppost *lastptr = NULL;
99 // /!\ This doesn't work with nodejs multer array /!\
100 // struct curl_forms form[files.size()+1];
102 // for(auto f : files)
104 // form[iter].option = CURLFORM_FILE;
105 // form[iter++].value = f;
108 // form[iter].option = CURLFORM_END;
110 // curl_formadd(&formpost,
112 // CURLFORM_COPYNAME, pcVarName,
113 // CURLFORM_ARRAY, form,
118 curl_formadd(&formpost,
120 CURLFORM_COPYNAME, pcVarName,
130 if(in[3]->isStruct() == false && in[3]->getAs<types::Struct>()->isScalar() == false)
132 Scierror(999, _("%s: Wrong type for input argument #%d: A structure of size %d expected.\n"), fname, 3, 1);
133 return types::Function::Error;
136 types::Struct* pStruct = in[3]->getAs<types::Struct>();
137 std::unordered_map<std::wstring, int> fieldsMap = pStruct->get(0)->getFields();
138 std::vector<types::InternalType*> pITData = pStruct->get(0)->getData();
139 for (const auto & field : fieldsMap)
141 char* pcFieldName = wide_string_to_UTF8(field.first.data());
142 std::string strData(toJSON(pITData[field.second]));
143 //remove " @start and @end of string
144 if (strData.front() == '\"' && strData.back() == '\"')
146 strData = strData.substr(1);
149 sciprint("|%s|: |%s|\n", pcFieldName, strData.data());
150 curl_formadd(&formpost,
152 CURLFORM_COPYNAME, pcFieldName,
153 CURLFORM_COPYCONTENTS, strData.data(),
160 curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
162 // set proxy information
163 if(sciCurlObj->setProxy(curl))
165 Scierror(999, _("%s: Wrong proxy information, please check in the 'internet' Scilab preference.\n"), fname);
166 return types::Function::Error;
169 // common optional argument
170 if(checkCommonOpt((void*)curl, opt, fname))
172 return types::Function::Error;
175 // specific optional argument
176 for (const auto& o : opt)
178 if (o.first == L"method")
180 if(o.second->isString() == false && o.second->getAs<types::String>()->isScalar() == false)
182 Scierror(999, _("%s: Wrong type for input argument #%s: A scalar string expected.\n"), fname, o.first.data());
183 return types::Function::Error;
186 wchar_t* pMeth = o.second->getAs<types::String>()->get(0);
187 if(wcscmp(pMeth, L"PUT") == 0)
189 curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");
191 else if(wcscmp(pMeth, L"POST") != 0)
193 Scierror(999, _("%s: Wrong value for input argument #%s: 'PUT' or 'POST' expected.\n"), fname, o.first.data());
194 return types::Function::Error;
199 sciCurlObj->getResultAsObject(curl);
200 res = curl_easy_perform(curl);
206 curl_formfree(formpost);
210 Scierror(999, _("%s: CURL execution failed.\n%s\n"), fname, curl_easy_strerror(res));
212 return types::Function::Error;
215 out.push_back(sciCurlObj->getResult());
220 curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &http_code);
221 out.push_back(new types::Double((double)http_code));
224 curl_easy_cleanup(curl);
225 return types::Function::OK;