1 #include <openssl/md5.h>
2 #include <otsdaq-utilities/ECLWriter/ECLConnection.h>
3 #include <boost/algorithm/string.hpp>
8 #include "otsdaq/Macros/CoutMacros.h"
9 #include "otsdaq/Macros/StringMacros.h"
10 #include "otsdaq/MessageFacility/MessageFacility.h"
13 ECLConnection::ECLConnection(std::string user, std::string pwd, std::string url)
19 if(!
Get(
"/secureURL", _safe_url))
21 __SS__ <<
"Could not retrieve safe URL from input url '" << _url <<
"'" << __E__;
24 __COUTTV__(_safe_url);
30 size_t ECLConnection::WriteMemoryCallback(
char* data,
39 buffer->append(data, size * nmemb);
40 realsize = size * nmemb;
52 std::string rndString = MakeSaltString();
53 std::string mySalt =
"salt=" + rndString;
55 bool needSignature =
false;
61 if(time(0) - _lastOperationTime > 5 * 60 )
63 __COUTT__ <<
"Clearing safe URL and re-requesting..." << __E__;
67 __COUTTV__(_safe_url);
68 if(_safe_url ==
"" && !
Get(
"/secureURL", _safe_url))
70 __SS__ <<
"Could not retrieve safe URL from input url '" << _url <<
"'"
74 __COUTTV__(_safe_url);
76 fullURL = _safe_url + s;
77 if(s.size() && s[s.size() - 1] ==
'?')
79 else if(fullURL.find(
'?') != std::string::npos)
88 __COUT__ <<
"ECL GET request to " << fullURL << std::endl;
89 __COUTVS__(20, needSignature);
94 std::string myData = fullURL.substr(fullURL.find(
'?') + 1);
96 myData +=
":" + _pwd +
":";
99 unsigned char resultMD5[MD5_DIGEST_LENGTH];
100 MD5((
unsigned char*)myData.c_str(), myData.size(), resultMD5);
103 for(
auto i = 0; i < MD5_DIGEST_LENGTH; i++)
105 sprintf(buf,
"%02x", resultMD5[i]);
108 __COUT_TYPE__(TLVL_DEBUG + 20)
109 << __COUT_HDR__ <<
"ECL MD5 Signature is: " << xSig << std::endl;
112 char errorBuffer[CURL_ERROR_SIZE];
113 std::string responseBuffer;
116 curl_global_init(CURL_GLOBAL_ALL);
119 curl_handle = curl_easy_init();
121 curl_easy_setopt(curl_handle, CURLOPT_ERRORBUFFER, errorBuffer);
127 struct curl_slist* headers = NULL;
128 std::string buff =
"X-User: " + _user;
129 headers = curl_slist_append(headers, buff.c_str());
130 headers = curl_slist_append(headers,
"Content-type: text/xml");
131 headers = curl_slist_append(headers,
"X-Signature-Method: md5");
132 buff =
"X-Signature: " + xSig;
133 headers = curl_slist_append(headers, buff.c_str());
135 curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers);
137 curl_easy_setopt(curl_handle, CURLOPT_URL, fullURL.c_str());
138 curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1);
142 curl_handle, CURLOPT_WRITEFUNCTION, ECLConnection::WriteMemoryCallback);
145 curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, &responseBuffer);
149 curl_easy_setopt(curl_handle, CURLOPT_USERAGENT,
"libcurl-agent/1.0");
152 CURLcode result = curl_easy_perform(curl_handle);
154 if(result != CURLE_OK)
157 __SS__ <<
"Error: [" << result <<
"] - " << errorBuffer << std::endl;
159 __COUT_TYPE__(TLVL_DEBUG + 20) << __COUT_HDR__ <<
"ECL Cleanup" << std::endl;
161 curl_easy_cleanup(curl_handle);
163 curl_global_cleanup();
167 __COUT_TYPE__(TLVL_DEBUG + 20) << __COUT_HDR__ <<
"ECL Cleanup" << std::endl;
169 curl_easy_cleanup(curl_handle);
171 curl_global_cleanup();
173 if(responseBuffer.find(
"Error") != std::string::npos ||
174 responseBuffer.find(
"301 Moved Permanently") != std::string::npos)
177 __SS__ <<
"Error found in request: " << responseBuffer << __E__;
181 __COUTVS__(2, responseBuffer);
182 response = responseBuffer;
184 _lastOperationTime = time(0);
189 bool ECLConnection::Search(std::string ) {
return false; }
192 std::string ECLConnection::MakeSaltString()
194 std::string rndString =
"";
197 "abcdefghijklmnopqrstuvwxyz"
200 for(
int i = 0; i < 10; ++i)
202 rndString += chars[rand() % chars.size()];
212 if(!
Get(
"/secureURL", _safe_url))
214 __SS__ <<
"Could not retrieve safe URL from input url '" << _url <<
"'" << __E__;
217 __COUTTV__(_safe_url);
219 std::string rndString = MakeSaltString();
221 std::string myURL =
"/E/xml_post?";
222 std::string mySalt =
"salt=" + rndString;
223 std::string fullURL = _safe_url + myURL + mySalt;
225 std::string myData = mySalt +
":" + _pwd +
":";
228 std::ostringstream oss;
230 std::string eclString = oss.str();
231 __COUT__ <<
"ECL XML is: " << eclString << std::endl;
233 eclString = eclString.substr(eclString.find_first_of(
">") + 2);
235 while(eclString.find(
'\n') != std::string::npos)
237 eclString = eclString.erase(eclString.find(
'\n'), 1);
239 while(eclString.find(
'\r') != std::string::npos)
241 eclString = eclString.erase(eclString.find(
'\r'), 1);
243 while(eclString.find(
" <") != std::string::npos)
245 eclString = eclString.erase(eclString.find(
" <"), 1);
247 boost::trim(eclString);
252 unsigned char resultMD5[MD5_DIGEST_LENGTH];
253 MD5((
unsigned char*)myData.c_str(), myData.size(), resultMD5);
257 for(
auto i = 0; i < MD5_DIGEST_LENGTH; i++)
259 sprintf(buf,
"%02x", resultMD5[i]);
262 __COUT__ <<
"ECL MD5 Signature is: " << xSig << std::endl;
265 char errorBuffer[CURL_ERROR_SIZE];
267 curl_global_init(CURL_GLOBAL_ALL);
271 curl_handle = curl_easy_init();
273 curl_easy_setopt(curl_handle, CURLOPT_ERRORBUFFER, errorBuffer);
277 struct curl_slist* headers = NULL;
278 std::string buff =
"X-User: " + _user;
279 headers = curl_slist_append(headers, buff.c_str());
280 headers = curl_slist_append(headers,
"Content-type: text/xml");
281 headers = curl_slist_append(headers,
"X-Signature-Method: md5");
282 buff =
"X-Signature: " + xSig;
283 headers = curl_slist_append(headers, buff.c_str());
285 const char* estr = eclString.c_str();
287 __COUT__ <<
"ECL Setting message headers" << std::endl;
288 curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, estr);
289 curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers);
290 curl_easy_setopt(curl_handle, CURLOPT_URL, fullURL.c_str());
291 curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1);
295 std::string responseBuffer;
297 curl_handle, CURLOPT_WRITEFUNCTION, ECLConnection::WriteMemoryCallback);
299 curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (
void*)&responseBuffer);
303 __COUT__ <<
"ECL Posting message to " << fullURL << std::endl;
304 CURLcode result = curl_easy_perform(curl_handle);
306 if(result != CURLE_OK)
309 __SS__ <<
"Error: [" << result <<
"] - " << errorBuffer << std::endl;
311 __COUTT__ <<
"ECL Cleanup" << std::endl;
313 curl_easy_cleanup(curl_handle);
314 curl_slist_free_all(headers);
315 curl_global_cleanup();
319 __COUTT__ <<
"ECL Cleanup" << std::endl;
321 curl_easy_cleanup(curl_handle);
322 curl_slist_free_all(headers);
323 curl_global_cleanup();
325 if(responseBuffer.find(
"Error") != std::string::npos ||
326 responseBuffer.find(
"301 Moved Permanently") != std::string::npos)
329 __SS__ <<
"Error found in request: " << responseBuffer << __E__;
333 __COUTTV__(responseBuffer);
339 std::string ECLConnection::EscapeECLString(std::string input)
341 std::string output = input;
342 size_t pos = output.find(
'&');
343 while(pos != std::string::npos)
345 output = output.replace(pos, 1,
"&");
346 pos = output.find(
'&', pos + 2);
349 pos = output.find(
'"');
350 while(pos != std::string::npos)
352 output = output.replace(pos, 1,
""");
353 pos = output.find(
'"', pos + 1);
356 pos = output.find(
'\'');
357 while(pos != std::string::npos)
359 output = output.replace(pos, 1,
"'");
360 pos = output.find(
'\'', pos + 1);
363 pos = output.find(
'<');
364 while(pos != std::string::npos)
366 output = output.replace(pos, 1,
"<");
367 pos = output.find(
'<', pos + 1);
370 pos = output.find(
'>');
371 while(pos != std::string::npos)
373 output = output.replace(pos, 1,
">");
374 pos = output.find(
'>', pos + 1);
381 Attachment_t ECLConnection::MakeAttachmentImage(std::string
const& imageFileName)
384 std::string fileNameShort = imageFileName;
385 if(fileNameShort.rfind(
'/') != std::string::npos)
387 fileNameShort = fileNameShort.substr(imageFileName.rfind(
'/'));
389 std::ifstream fin(imageFileName, std::ios::in | std::ios::binary);
390 fin.seekg(0, std::ios::end);
391 std::streamsize size = fin.tellg();
392 fin.seekg(0, std::ios::beg);
393 std::vector<char> buffer(size);
394 if(!fin.read(buffer.data(), size))
396 __COUT__ <<
"ECLConnection: Error reading file: " << imageFileName << std::endl;
402 ::xml_schema::base64_binary(&buffer[0], size),
"image", fileNameShort);
408 Attachment_t ECLConnection::MakeAttachmentFile(std::string
const& fileName)
411 std::string fileNameShort = fileName;
412 if(fileNameShort.rfind(
'/') != std::string::npos)
414 fileNameShort = fileNameShort.substr(fileName.rfind(
'/'));
416 std::ifstream fin(fileName, std::ios::in | std::ios::binary);
417 fin.seekg(0, std::ios::end);
418 std::streamsize size = fin.tellg();
419 fin.seekg(0, std::ios::beg);
421 std::vector<char> buffer(size);
422 if(!fin.read(buffer.data(), size))
424 __COUT__ <<
"ECLConnection: Error reading file: " << fileName;
430 ::xml_schema::base64_binary(&buffer[0], size),
"file", fileNameShort);
bool Get(std::string, std::string &)
Note: make sure GET url parameter 's' is URI encoded.