otsdaq_utilities  v2_05_02_indev
ECLConnection.cpp
1 #include <openssl/md5.h>
2 #include <otsdaq-utilities/ECLWriter/ECLConnection.h>
3 #include <boost/algorithm/string.hpp>
4 #include <cstring>
5 #include <fstream>
6 #include <iomanip>
7 #include <sstream>
8 #include "otsdaq/Macros/CoutMacros.h"
9 #include "otsdaq/MessageFacility/MessageFacility.h"
10 
11 ECLConnection::ECLConnection(std::string user, std::string pwd, std::string url)
12 {
13  _user = user;
14  _pwd = pwd;
15  _url = url;
16 
17  srand(time(NULL));
18 }
19 
20 size_t ECLConnection::WriteMemoryCallback(char* data,
21  size_t size,
22  size_t nmemb,
23  std::string* buffer)
24 {
25  size_t realsize = 0;
26 
27  if(buffer != NULL)
28  {
29  buffer->append(data, size * nmemb);
30  realsize = size * nmemb;
31  }
32 
33  return realsize;
34 }
35 
36 bool ECLConnection::Get(std::string s, std::string& response)
37 {
38  response = "NULL";
39 
40  char errorBuffer[CURL_ERROR_SIZE];
41  std::string buffer;
42  CURL* curl_handle;
43 
44  curl_global_init(CURL_GLOBAL_ALL);
45 
46  /* init the curl session */
47  curl_handle = curl_easy_init();
48 
49  curl_easy_setopt(curl_handle, CURLOPT_ERRORBUFFER, errorBuffer);
50 
51  std::string fullURL = _url + s;
52 
53  /* specify URL to get */
54  curl_easy_setopt(curl_handle, CURLOPT_URL, fullURL.c_str());
55  curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1);
56 
57  /* send all data to this function */
58  curl_easy_setopt(
59  curl_handle, CURLOPT_WRITEFUNCTION, ECLConnection::WriteMemoryCallback);
60 
61  /* we pass our 'chunk' struct to the callback function */
62  curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, &buffer);
63 
64  /* some servers don't like requests that are made without a user-agent
65  field, so we provide one */
66  curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
67 
68  /* get it! */
69  CURLcode result = curl_easy_perform(curl_handle);
70 
71  /* cleanup curl stuff */
72  curl_easy_cleanup(curl_handle);
73 
74  if(result == CURLE_OK)
75  response = buffer;
76  else
77  {
78  std::cerr << "Error: [" << result << "] - " << errorBuffer << std::endl;
79  return false;
80  }
81 
82  curl_global_cleanup();
83 
84  return true;
85 }
86 
87 bool ECLConnection::Search(std::string /*s*/) { return false; }
88 
89 std::string ECLConnection::MakeSaltString()
90 {
91  std::string rndString = "";
92 
93  std::string chars(
94  "abcdefghijklmnopqrstuvwxyz"
95  // "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
96  "1234567890");
97  for(int i = 0; i < 10; ++i)
98  {
99  rndString += chars[rand() % chars.size()];
100  }
101 
102  return rndString;
103 }
104 
105 bool ECLConnection::Post(ECLEntry_t& e)
106 {
107  std::string safe_url;
108  if(!Get("/secureURL", safe_url))
109  return false;
110 
111  std::string rndString = MakeSaltString();
112 
113  std::string myURL = "/E/xml_post?";
114  std::string mySalt = "salt=" + rndString;
115  std::string fullURL = _url + myURL + mySalt;
116 
117  std::string myData = mySalt + ":" + _pwd + ":";
118 
119  // create text from xml form, but need to remove all \n's
120  std::ostringstream oss;
121  entry(oss, e);
122  std::string eclString = oss.str();
123  __COUT__ << "ECL XML is: " << eclString << std::endl;
124  // std::string eclString = e.entry();
125  eclString = eclString.substr(eclString.find_first_of(">") + 2);
126 
127  while(eclString.find('\n') != std::string::npos)
128  {
129  eclString = eclString.erase(eclString.find('\n'), 1);
130  }
131  while(eclString.find('\r') != std::string::npos)
132  {
133  eclString = eclString.erase(eclString.find('\r'), 1);
134  }
135  while(eclString.find(" <") != std::string::npos)
136  {
137  eclString = eclString.erase(eclString.find(" <"), 1);
138  }
139  boost::trim(eclString);
140  myData += eclString;
141  __COUT__ << "ECL Hash string is: " << myData << std::endl;
142  unsigned char resultMD5[MD5_DIGEST_LENGTH];
143  MD5((unsigned char*)myData.c_str(), myData.size(), resultMD5);
144 
145  std::string xSig;
146  char buf[3];
147  for(auto i = 0; i < MD5_DIGEST_LENGTH; i++)
148  {
149  sprintf(buf, "%02x", resultMD5[i]);
150  xSig.append(buf);
151  }
152  __COUT__ << "ECL MD5 Signature is: " << xSig << std::endl;
153 
154  CURL* curl_handle;
155  char errorBuffer[CURL_ERROR_SIZE];
156 
157  curl_global_init(CURL_GLOBAL_ALL);
158 
159  /* init the curl session */
160 
161  curl_handle = curl_easy_init();
162 
163  curl_easy_setopt(curl_handle, CURLOPT_ERRORBUFFER, errorBuffer);
164 
165  /* specify URL to get */
166 
167  struct curl_slist* headers = NULL;
168  std::string buff = "X-User: " + _user;
169  headers = curl_slist_append(headers, buff.c_str());
170  headers = curl_slist_append(headers, "Content-type: text/xml");
171  headers = curl_slist_append(headers, "X-Signature-Method: md5");
172  buff = "X-Signature: " + xSig;
173  headers = curl_slist_append(headers, buff.c_str());
174 
175  const char* estr = eclString.c_str();
176 
177  __COUT__ << "ECL Setting message headers" << std::endl;
178  curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, estr);
179  curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers);
180  curl_easy_setopt(curl_handle, CURLOPT_URL, fullURL.c_str());
181  // curl_easy_setopt(curl_handle, CURLOPT_VERBOSE,1);
182 
183  // post it!
184 
185  __COUT__ << "ECL Posting message" << std::endl;
186  CURLcode result = curl_easy_perform(curl_handle);
187 
188  if(result != CURLE_OK)
189  {
190  std::cerr << "Error: [" << result << "] - " << errorBuffer << std::endl;
191  return false;
192  }
193 
194  __COUT__ << "ECL Cleanup" << std::endl;
195  // cleanup curl stuff
196  curl_easy_cleanup(curl_handle);
197  curl_slist_free_all(headers);
198 
199  curl_global_cleanup();
200 
201  return true;
202 }
203 
204 std::string ECLConnection::EscapeECLString(std::string input)
205 {
206  std::string output = input;
207  size_t pos = output.find('&');
208  while(pos != std::string::npos)
209  {
210  output = output.replace(pos, 1, "&amp;");
211  pos = output.find('&', pos + 2);
212  }
213 
214  pos = output.find('"');
215  while(pos != std::string::npos)
216  {
217  output = output.replace(pos, 1, "&quot;");
218  pos = output.find('"', pos + 1);
219  }
220 
221  pos = output.find('\'');
222  while(pos != std::string::npos)
223  {
224  output = output.replace(pos, 1, "&apos;");
225  pos = output.find('\'', pos + 1);
226  }
227 
228  pos = output.find('<');
229  while(pos != std::string::npos)
230  {
231  output = output.replace(pos, 1, "&lt;");
232  pos = output.find('<', pos + 1);
233  }
234 
235  pos = output.find('>');
236  while(pos != std::string::npos)
237  {
238  output = output.replace(pos, 1, "&gt;");
239  pos = output.find('>', pos + 1);
240  }
241 
242  return output;
243 }
244 
245 Attachment_t ECLConnection::MakeAttachmentImage(std::string const& imageFileName)
246 {
247  Attachment_t attachment;
248  std::string fileNameShort = imageFileName;
249  if(fileNameShort.rfind('/') != std::string::npos)
250  {
251  fileNameShort = fileNameShort.substr(imageFileName.rfind('/'));
252  }
253  std::ifstream fin(imageFileName, std::ios::in | std::ios::binary);
254  fin.seekg(0, std::ios::end);
255  std::streamsize size = fin.tellg();
256  fin.seekg(0, std::ios::beg);
257  std::vector<char> buffer(size);
258  if(!fin.read(buffer.data(), size))
259  {
260  __COUT__ << "ECLConnection: Error reading file: " << imageFileName << std::endl;
261  attachment = Attachment_t("Image=none", fileNameShort);
262  }
263  else
264  {
265  attachment = Attachment_t(
266  ::xml_schema::base64_binary(&buffer[0], size), "image", fileNameShort);
267  }
268  return attachment;
269 }
270 
271 Attachment_t ECLConnection::MakeAttachmentFile(std::string const& fileName)
272 {
273  Attachment_t attachment;
274  std::string fileNameShort = fileName;
275  if(fileNameShort.rfind('/') != std::string::npos)
276  {
277  fileNameShort = fileNameShort.substr(fileName.rfind('/'));
278  }
279  std::ifstream fin(fileName, std::ios::in | std::ios::binary);
280  fin.seekg(0, std::ios::end);
281  std::streamsize size = fin.tellg();
282  fin.seekg(0, std::ios::beg);
283 
284  std::vector<char> buffer(size);
285  if(!fin.read(buffer.data(), size))
286  {
287  __COUT__ << "ECLConnection: Error reading file: " << fileName;
288  attachment = Attachment_t("File=none", fileNameShort);
289  }
290  else
291  {
292  attachment = Attachment_t(
293  ::xml_schema::base64_binary(&buffer[0], size), "file", fileNameShort);
294  }
295  return attachment;
296 }
Definition: ECL.hxx:547