otsdaq  v2_04_00
WizardSupervisor.cc
1 #include "otsdaq-core/WizardSupervisor/WizardSupervisor.h"
2 
3 #include "otsdaq-core/GatewaySupervisor/GatewaySupervisor.h"
4 
5 #include "otsdaq-core/Macros/CoutMacros.h"
6 #include "otsdaq-core/MessageFacility/MessageFacility.h"
7 
8 #include <xdaq/NamespaceURI.h>
9 #include "otsdaq-core/CgiDataUtilities/CgiDataUtilities.h"
10 #include "otsdaq-core/SOAPUtilities/SOAPCommand.h"
11 #include "otsdaq-core/SOAPUtilities/SOAPUtilities.h"
12 #include "otsdaq-core/WebUsersUtilities/WebUsers.h"
13 #include "otsdaq-core/XmlUtilities/HttpXmlDocument.h"
14 
15 #include <dirent.h> //for DIR
16 #include <sys/stat.h> // mkdir
17 #include <chrono> // std::chrono::seconds
18 #include <fstream>
19 #include <iostream>
20 #include <string>
21 #include <thread> // std::this_thread::sleep_for
22 
23 using namespace ots;
24 
25 #define SECURITY_FILE_NAME \
26  std::string(__ENV__("SERVICE_DATA_PATH")) + "/OtsWizardData/security.dat"
27 #define SEQUENCE_FILE_NAME \
28  std::string(__ENV__("SERVICE_DATA_PATH")) + "/OtsWizardData/sequence.dat"
29 #define SEQUENCE_OUT_FILE_NAME \
30  std::string(__ENV__("SERVICE_DATA_PATH")) + "/OtsWizardData/sequence.out"
31 #define USER_DATA_PATH std::string(__ENV__("SERVICE_DATA_PATH")) + std::string("/")
32 //#define LOGBOOK_PREVIEWS_PATH "uploads/"
33 
34 #define XML_STATUS "editUserData_status"
35 
36 #define XML_ADMIN_STATUS "logbook_admin_status"
37 #define XML_MOST_RECENT_DAY "most_recent_day"
38 #define XML_EXPERIMENTS_ROOT "experiments"
39 #define XML_EXPERIMENT "experiment"
40 #define XML_ACTIVE_EXPERIMENT "active_experiment"
41 #define XML_EXPERIMENT_CREATE "create_time"
42 #define XML_EXPERIMENT_CREATOR "creator"
43 
44 #define XML_LOGBOOK_ENTRY "logbook_entry"
45 #define XML_LOGBOOK_ENTRY_SUBJECT "logbook_entry_subject"
46 #define XML_LOGBOOK_ENTRY_TEXT "logbook_entry_text"
47 #define XML_LOGBOOK_ENTRY_FILE "logbook_entry_file"
48 #define XML_LOGBOOK_ENTRY_TIME "logbook_entry_time"
49 #define XML_LOGBOOK_ENTRY_CREATOR "logbook_entry_creator"
50 #define XML_LOGBOOK_ENTRY_HIDDEN "logbook_entry_hidden"
51 #define XML_LOGBOOK_ENTRY_HIDER "logbook_entry_hider"
52 #define XML_LOGBOOK_ENTRY_HIDDEN_TIME "logbook_entry_hidden_time"
53 
54 #define XML_PREVIEW_INDEX "preview_index"
55 #define LOGBOOK_PREVIEW_FILE "preview.xml"
56 
57 XDAQ_INSTANTIATOR_IMPL(WizardSupervisor)
58 
59 #undef __MF_SUBJECT__
60 #define __MF_SUBJECT__ "Wizard"
61 
62 //========================================================================================================================
63 WizardSupervisor::WizardSupervisor(xdaq::ApplicationStub* s)
64  : xdaq::Application(s)
65  , SOAPMessenger(this)
66  , supervisorClass_(getApplicationDescriptor()->getClassName())
67  , supervisorClassNoNamespace_(supervisorClass_.substr(
68  supervisorClass_.find_last_of(":") + 1,
69  supervisorClass_.length() - supervisorClass_.find_last_of(":")))
70 {
71  __COUT__ << "Constructor started." << __E__;
72 
73  INIT_MF("OtsConfigurationWizard");
74 
75  // attempt to make directory structure (just in case)
76  mkdir((std::string(__ENV__("SERVICE_DATA_PATH"))).c_str(), 0755);
77  mkdir((std::string(__ENV__("SERVICE_DATA_PATH")) + "/OtsWizardData").c_str(), 0755);
78 
79  GatewaySupervisor::indicateOtsAlive();
80 
81  generateURL();
82  xgi::bind(this, &WizardSupervisor::Default, "Default");
83  xgi::bind(this, &WizardSupervisor::verification, "Verify");
84  xgi::bind(this, &WizardSupervisor::request, "Request");
85  xgi::bind(this, &WizardSupervisor::requestIcons, "requestIcons");
86  xgi::bind(this, &WizardSupervisor::editSecurity, "editSecurity");
87  xgi::bind(this, &WizardSupervisor::UserSettings, "UserSettings");
88  xgi::bind(this, &WizardSupervisor::tooltipRequest, "TooltipRequest");
89  xgi::bind(this,
90  &WizardSupervisor::toggleSecurityCodeGeneration,
91  "ToggleSecurityCodeGeneration");
92  xoap::bind(this,
93  &WizardSupervisor::supervisorSequenceCheck,
94  "SupervisorSequenceCheck",
95  XDAQ_NS_URI);
96  xoap::bind(this,
97  &WizardSupervisor::supervisorLastConfigGroupRequest,
98  "SupervisorLastConfigGroupRequest",
99  XDAQ_NS_URI);
100  init();
101 
102  __COUT__ << "Constructor complete." << __E__;
103 }
104 
105 //========================================================================================================================
106 WizardSupervisor::~WizardSupervisor(void) { destroy(); }
107 
108 //========================================================================================================================
109 void WizardSupervisor::init(void)
110 {
111  // getApplicationContext();
112 
113  // init allowed file upload types
114  allowedFileUploadTypes_.push_back("image/png");
115  matchingFileUploadTypes_.push_back("png");
116  allowedFileUploadTypes_.push_back("image/jpeg");
117  matchingFileUploadTypes_.push_back("jpeg");
118  allowedFileUploadTypes_.push_back("image/gif");
119  matchingFileUploadTypes_.push_back("gif");
120  allowedFileUploadTypes_.push_back("image/bmp");
121  matchingFileUploadTypes_.push_back("bmp");
122  allowedFileUploadTypes_.push_back("application/pdf");
123  matchingFileUploadTypes_.push_back("pdf");
124  allowedFileUploadTypes_.push_back("application/zip");
125  matchingFileUploadTypes_.push_back("zip");
126  allowedFileUploadTypes_.push_back("text/plain");
127  matchingFileUploadTypes_.push_back("txt");
128 }
129 
130 //========================================================================================================================
131 void WizardSupervisor::requestIcons(xgi::Input* in,
132  xgi::Output* out)
133 {
134  cgicc::Cgicc cgi(in);
135 
136  std::string submittedSequence = CgiDataUtilities::postData(cgi, "sequence");
137 
138  // SECURITY CHECK START ****
139  if(securityCode_.compare(submittedSequence) != 0)
140  {
141  __COUT__ << "Unauthorized Request made, security sequence doesn't match! "
142  << time(0) << std::endl;
143  return;
144  }
145  else
146  {
147  __COUT__ << "***Successfully authenticated security sequence. " << time(0)
148  << std::endl;
149  }
150  // SECURITY CHECK END ****
151 
152  // an icon is 7 fields.. give comma-separated
153  // 0 - subtext = text below icon
154  // 1 - altText = text for icon if image set to 0
155  // 2 - uniqueWin = if true, only one window is allowed, else multiple instances of
156  // window 3 - permissions = security level needed to see icon 4 - picfn = icon image
157  // filename, 0 for no image 5 - linkurl = url of the window to open 6 - folderPath =
158  // folder and subfolder location
159 
160  *out << "Configure,CFG,0,1,icon-Configure.png,/urn:xdaq-application:lid=280/,/"
161  << ",Table "
162  "Editor,TBL,0,1,icon-IconEditor.png,/urn:xdaq-application:lid=280/"
163  "?configWindowName=tableEditor,/"
164  << ",Security "
165  "Settings,SEC,1,1,icon-SecuritySettings.png,/WebPath/html/"
166  "SecuritySettings.html,/User Settings"
167  << ",Edit User "
168  "Data,USER,1,1,icon-EditUserData.png,/WebPath/html/EditUserData.html,/User "
169  "Settings"
170  <<
171 
172  ",Console,C,1,1,icon-Console.png,/urn:xdaq-application:lid=260/,/" <<
173 
174  //",Iterate,IT,0,1,icon-Iterate.png,/urn:xdaq-application:lid=280/?configWindowName=iterate,/"
175  //<<
176  //",Configure,CFG,0,1,icon-Configure.png,/urn:xdaq-application:lid=280/,myFolder"
177  //<<
178  //",Configure,CFG,0,1,icon-Configure.png,/urn:xdaq-application:lid=280/,/myFolder/mySub.folder"
179  //<<
180  //",Configure,CFG,0,1,icon-Configure.png,/urn:xdaq-application:lid=280/,myFolder/"
181  //<<
182  ",Front-end "
183  "Wizard,CFG,0,1,icon-Configure.png,/WebPath/html/"
184  "RecordWiz_ConfigurationGUI.html?urn=280&recordAlias=Front%2Dend,Config Wizards"
185  << ",Processor "
186  "Wizard,CFG,0,1,icon-Configure.png,/WebPath/html/"
187  "RecordWiz_ConfigurationGUI.html?urn=280&recordAlias=Processor,Config Wizards"
188  << ",Block "
189  "Diagram,CFG,0,1,icon-Configure.png,/WebPath/html/"
190  "ConfigurationSubsetBlockDiagram.html?urn=280,Config Wizards"
191  <<
192  //",Consumer
193  // Wizard,CFG,0,1,icon-Configure.png,/WebPath/html/RecordWiz_ConfigurationGUI.html?urn=280&subsetBasePath=FEInterfaceConfiguration&recordAlias=Consumer,Config
194  // Wizards" <<
195 
196  //",DB Utilities,DB,1,1,0,http://127.0.0.1:8080/db/client.html" <<
197 
198  ",Code Editor,CODE,0,1,icon-CodeEditor.png,/urn:xdaq-application:lid=240/,/"
199  //",Code Editor,CODE,0,1,icon-CodeEditor.png,/WebPath/html/CodeEditor.html,/"
200  << "";
201  return;
202 } // end requestIcons()
203 
204 //========================================================================================================================
205 void WizardSupervisor::verification(xgi::Input* in,
206  xgi::Output* out)
207 {
208  cgicc::Cgicc cgi(in);
209  std::string submittedSequence = CgiDataUtilities::getData(cgi, "code");
210  __COUT__ << "submittedSequence=" << submittedSequence << " " << time(0) << std::endl;
211 
212  std::string securityWarning = "";
213 
214  if(securityCode_.compare(submittedSequence) != 0)
215  {
216  __COUT__ << "Unauthorized Request made, security sequence doesn't match!"
217  << std::endl;
218  *out << "Invalid code.";
219  return;
220  }
221  else
222  {
223  // defaultSequence_ = false;
224  __COUT__ << "*** Successfully authenticated security sequence "
225  << "@ " << time(0) << std::endl;
226 
227  if(defaultSequence_)
228  {
229  //__COUT__ << " UNSECURE!!!" << std::endl;
230  securityWarning = "&secure=False";
231  }
232  }
233 
234  *out << "<!DOCTYPE HTML><html lang='en'><head><title>ots wiz</title>" <<
235  // show ots icon
236  // from http://www.favicon-generator.org/
237  "<link rel='apple-touch-icon' sizes='57x57' href='/WebPath/images/otsdaqIcons/apple-icon-57x57.png'>\
238  <link rel='apple-touch-icon' sizes='60x60' href='/WebPath/images/otsdaqIcons/apple-icon-60x60.png'>\
239  <link rel='apple-touch-icon' sizes='72x72' href='/WebPath/images/otsdaqIcons/apple-icon-72x72.png'>\
240  <link rel='apple-touch-icon' sizes='76x76' href='/WebPath/images/otsdaqIcons/apple-icon-76x76.png'>\
241  <link rel='apple-touch-icon' sizes='114x114' href='/WebPath/images/otsdaqIcons/apple-icon-114x114.png'>\
242  <link rel='apple-touch-icon' sizes='120x120' href='/WebPath/images/otsdaqIcons/apple-icon-120x120.png'>\
243  <link rel='apple-touch-icon' sizes='144x144' href='/WebPath/images/otsdaqIcons/apple-icon-144x144.png'>\
244  <link rel='apple-touch-icon' sizes='152x152' href='/WebPath/images/otsdaqIcons/apple-icon-152x152.png'>\
245  <link rel='apple-touch-icon' sizes='180x180' href='/WebPath/images/otsdaqIcons/apple-icon-180x180.png'>\
246  <link rel='icon' type='image/png' sizes='192x192' href='/WebPath/images/otsdaqIcons/android-icon-192x192.png'>\
247  <link rel='icon' type='image/png' sizes='32x32' href='/WebPath/images/otsdaqIcons/favicon-32x32.png'>\
248  <link rel='icon' type='image/png' sizes='96x96' href='/WebPath/images/otsdaqIcons/favicon-96x96.png'>\
249  <link rel='icon' type='image/png' sizes='16x16' href='/WebPath/images/otsdaqIcons/favicon-16x16.png'>\
250  <link rel='manifest' href='/WebPath/images/otsdaqIcons/manifest.json'>\
251  <meta name='msapplication-TileColor' content='#ffffff'>\
252  <meta name='msapplication-TileImage' content='/ms-icon-144x144.png'>\
253  <meta name='theme-color' content='#ffffff'>"
254  <<
255  // end show ots icon
256  "</head>"
257  << "<frameset col='100%' row='100%'><frame src='/WebPath/html/Wizard.html?urn="
258  << this->getApplicationDescriptor()->getLocalId() << securityWarning
259  << "'></frameset></html>";
260 } // end verification()
261 
262 //========================================================================================================================
263 void WizardSupervisor::generateURL()
264 {
265  defaultSequence_ = true;
266 
267  int length = 4;
268  FILE* fp = fopen((SEQUENCE_FILE_NAME).c_str(), "r");
269  if(fp)
270  {
271  __COUT_INFO__ << "Sequence length file found: " << SEQUENCE_FILE_NAME
272  << std::endl;
273  char line[100];
274  fgets(line, 100, fp);
275  sscanf(line, "%d", &length);
276  fclose(fp);
277  if(length < 4)
278  length = 4; // don't allow shorter than 4
279  else
280  defaultSequence_ = false;
281  srand(time(0)); // randomize differently each "time"
282  }
283  else
284  {
285  __COUT_INFO__
286  << "(Reverting to default wiz security) Sequence length file NOT found: "
287  << SEQUENCE_FILE_NAME << std::endl;
288  srand(0); // use same seed for convenience if file not found
289  }
290 
291  __COUT__ << "Sequence length = " << length << std::endl;
292 
293  securityCode_ = "";
294 
295  const char alphanum[] =
296  "0123456789"
297  "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
298  "abcdefghijklmnopqrstuvwxyz";
299 
300  for(int i = 0; i < length; ++i)
301  {
302  securityCode_ += alphanum[rand() % (sizeof(alphanum) - 1)];
303  }
304 
305  __COUT__ << __ENV__("OTS_CONFIGURATION_WIZARD_SUPERVISOR_SERVER") << ":"
306  << __ENV__("PORT") << "/urn:xdaq-application:lid="
307  << this->getApplicationDescriptor()->getLocalId()
308  << "/Verify?code=" << securityCode_ << std::endl;
309 
310  // Note: print out handled by StartOTS.sh now
311  // std::thread([&](WizardSupervisor *ptr, std::string securityCode)
312  // {printURL(ptr,securityCode);},this,securityCode_).detach();
313 
314  fp = fopen((SEQUENCE_OUT_FILE_NAME).c_str(), "w");
315  if(fp)
316  {
317  fprintf(fp, "%s", securityCode_.c_str());
318  fclose(fp);
319  }
320  else
321  __COUT_ERR__ << "Sequence output file NOT found: " << SEQUENCE_OUT_FILE_NAME
322  << std::endl;
323 
324  return;
325 } // end generateURL()
326 
327 void WizardSupervisor::printURL(WizardSupervisor* ptr, std::string securityCode)
328 {
329  INIT_MF("ConfigurationWizard");
330  // child process
331  int i = 0;
332  for(; i < 5; ++i)
333  {
334  std::this_thread::sleep_for(std::chrono::seconds(2));
335  __COUT__ << __ENV__("OTS_CONFIGURATION_WIZARD_SUPERVISOR_SERVER") << ":"
336  << __ENV__("PORT") << "/urn:xdaq-application:lid="
337  << ptr->getApplicationDescriptor()->getLocalId()
338  << "/Verify?code=" << securityCode << std::endl;
339  }
340 }
341 
342 //========================================================================================================================
343 void WizardSupervisor::destroy(void)
344 {
345  // called by destructor
346 }
347 
348 //========================================================================================================================
349 void WizardSupervisor::tooltipRequest(xgi::Input* in,
350  xgi::Output* out)
351 {
352  cgicc::Cgicc cgi(in);
353 
354  std::string Command = CgiDataUtilities::getData(cgi, "RequestType");
355  //__COUT__ << "Command = " << Command << std::endl;
356 
357  std::string submittedSequence = CgiDataUtilities::postData(cgi, "sequence");
358 
359  // SECURITY CHECK START ****
360  if(securityCode_.compare(submittedSequence) != 0)
361  {
362  __COUT__ << "Unauthorized Request made, security sequence doesn't match!"
363  << std::endl;
364  return;
365  }
366  // else
367  // {
368  // __COUT__ << "***Successfully authenticated security sequence." << std::endl;
369  // }
370  // SECURITY CHECK END ****
371 
372  HttpXmlDocument xmldoc;
373 
374  if(Command == "check")
375  {
376  WebUsers::tooltipCheckForUsername(WebUsers::DEFAULT_ADMIN_USERNAME,
377  &xmldoc,
378  CgiDataUtilities::getData(cgi, "srcFile"),
379  CgiDataUtilities::getData(cgi, "srcFunc"),
380  CgiDataUtilities::getData(cgi, "srcId"));
381  }
382  else if(Command == "setNeverShow")
383  {
384  WebUsers::tooltipSetNeverShowForUsername(
385  WebUsers::DEFAULT_ADMIN_USERNAME,
386  &xmldoc,
387  CgiDataUtilities::getData(cgi, "srcFile"),
388  CgiDataUtilities::getData(cgi, "srcFunc"),
389  CgiDataUtilities::getData(cgi, "srcId"),
390  CgiDataUtilities::getData(cgi, "doNeverShow") == "1" ? true : false,
391  CgiDataUtilities::getData(cgi, "temporarySilence") == "1" ? true : false);
392  }
393  else
394  __COUT__ << "Command Request, " << Command << ", not recognized." << std::endl;
395 
396  xmldoc.outputXmlDocument((std::ostringstream*)out, false, true);
397 } // end tooltipRequest()
398 
399 //========================================================================================================================
400 void WizardSupervisor::toggleSecurityCodeGeneration(
401  xgi::Input* in, xgi::Output* out)
402 {
403  cgicc::Cgicc cgi(in);
404 
405  std::string Command = CgiDataUtilities::getData(cgi, "RequestType");
406  __COUT__ << "Got to Command = " << Command << std::endl;
407 
408  std::string submittedSequence = CgiDataUtilities::postData(cgi, "sequence");
409 
410  // SECURITY CHECK START ****
411  if(securityCode_.compare(submittedSequence) != 0)
412  {
413  __COUT__ << "Unauthorized Request made, security sequence doesn't match!"
414  << std::endl;
415  return;
416  }
417  else
418  {
419  __COUT__ << "***Successfully authenticated security sequence." << std::endl;
420  }
421  // SECURITY CHECK END ****
422 
423  HttpXmlDocument xmldoc;
424 
425  if(Command == "TurnGenerationOn")
426  {
427  __COUT__ << "Turning automatic URL Generation on with a sequence depth of 16!"
428  << std::endl;
429  std::ofstream outfile((SEQUENCE_FILE_NAME).c_str());
430  outfile << "16" << std::endl;
431  outfile.close();
432  generateURL();
433 
434  // std::stringstream url;
435  // url << __ENV__("OTS_CONFIGURATION_WIZARD_SUPERVISOR_SERVER") << ":" <<
436  // __ENV__("PORT")
437  // << "/urn:xdaq-application:lid=" <<
438  // this->getApplicationDescriptor()->getLocalId()
439  // << "/Verify?code=" << securityCode_;
440  // printURL(this, securityCode_);
441  std::thread([&](WizardSupervisor* ptr,
442  std::string securityCode) { printURL(ptr, securityCode); },
443  this,
444  securityCode_)
445  .detach();
446 
447  xmldoc.addTextElementToData("Status", "Generation_Success");
448  }
449  else
450  __COUT__ << "Command Request, " << Command << ", not recognized." << std::endl;
451 
452  xmldoc.outputXmlDocument((std::ostringstream*)out, false, true);
453 }
454 
455 //========================================================================================================================
456 // xoap::supervisorSequenceCheck
457 // verify cookie
458 xoap::MessageReference WizardSupervisor::supervisorSequenceCheck(
459  xoap::MessageReference message)
460 {
461  // SOAPUtilities::receive request parameters
462  SOAPParameters parameters;
463  parameters.addParameter("sequence");
464  SOAPUtilities::receive(message, parameters);
465 
466  std::string submittedSequence = parameters.getValue("sequence");
467 
468  // If submittedSequence matches securityCode_ then return full permissions (255)
469  // else, return permissions 0
470  std::map<std::string /*groupName*/, WebUsers::permissionLevel_t> permissionMap;
471 
472  if(securityCode_ == submittedSequence)
473  permissionMap.emplace(
474  std::pair<std::string /*groupName*/, WebUsers::permissionLevel_t>(
475  WebUsers::DEFAULT_USER_GROUP, WebUsers::PERMISSION_LEVEL_ADMIN));
476  else
477  {
478  __COUT__ << "Unauthorized Request made, security sequence doesn't match!"
479  << std::endl;
480 
481  permissionMap.emplace(
482  std::pair<std::string /*groupName*/, WebUsers::permissionLevel_t>(
483  WebUsers::DEFAULT_USER_GROUP, WebUsers::PERMISSION_LEVEL_INACTIVE));
484  }
485 
486  // fill return parameters
487  SOAPParameters retParameters;
488  retParameters.addParameter("Permissions", StringMacros::mapToString(permissionMap));
489 
490  return SOAPUtilities::makeSOAPMessageReference("SequenceResponse", retParameters);
491 }
492 
493 //===================================================================================================================
494 // xoap::supervisorLastConfigGroupRequest
495 // return the group name and key for the last state machine activity
496 //
497 // Note: same as Supervisor::supervisorLastConfigGroupRequest
498 xoap::MessageReference WizardSupervisor::supervisorLastConfigGroupRequest(
499  xoap::MessageReference message)
500 {
501  SOAPParameters parameters;
502  parameters.addParameter("ActionOfLastGroup");
503  SOAPUtilities::receive(message, parameters);
504 
505  return GatewaySupervisor::lastConfigGroupRequestHandler(parameters);
506 }
507 
508 //========================================================================================================================
509 void WizardSupervisor::Default(xgi::Input* in,
510  xgi::Output* out)
511 {
512  __COUT__ << "Unauthorized Request made, security sequence doesn't match!"
513  << std::endl;
514  *out << "Unauthorized Request.";
515 }
516 
517 //========================================================================================================================
518 void WizardSupervisor::request(xgi::Input* in,
519  xgi::Output* out)
520 {
521  cgicc::Cgicc cgiIn(in);
522 
523  std::string submittedSequence = CgiDataUtilities::postData(cgiIn, "sequence");
524 
525  // SECURITY CHECK START ****
526  if(securityCode_.compare(submittedSequence) != 0)
527  {
528  __COUT__ << "Unauthorized Request made, security sequence doesn't match! "
529  << time(0) << std::endl;
530  return;
531  }
532  else
533  {
534  __COUT__ << "***Successfully authenticated security sequence. " << time(0)
535  << std::endl;
536  }
537  // SECURITY CHECK END ****
538 
539  std::string requestType = CgiDataUtilities::getData(cgiIn, "RequestType");
540  __COUTV__(requestType);
541 
542  HttpXmlDocument xmlOut;
543 
544  try
545  {
546  if(requestType == "gatewayLaunchOTS" || requestType == "gatewayLaunchWiz")
547  {
548  // NOTE: similar to ConfigurationGUI version but DOES keep active sessions
549 
550  __COUT_WARN__ << requestType << " requestType received! " << __E__;
551  __MOUT_WARN__ << requestType << " requestType received! " << __E__;
552 
553  // now launch
554  ConfigurationManager cfgMgr;
555  if(requestType == "gatewayLaunchOTS")
556  GatewaySupervisor::launchStartOTSCommand("LAUNCH_OTS", &cfgMgr);
557  else if(requestType == "gatewayLaunchWiz")
558  GatewaySupervisor::launchStartOTSCommand("LAUNCH_WIZ", &cfgMgr);
559  }
560  else
561  {
562  __SS__ << "requestType Request, " << requestType << ", not recognized."
563  << __E__;
564  __SS_THROW__;
565  }
566  }
567  catch(const std::runtime_error& e)
568  {
569  __SS__ << "An error was encountered handling requestType '" << requestType
570  << "':" << e.what() << __E__;
571  __COUT__ << "\n" << ss.str();
572  xmlOut.addTextElementToData("Error", ss.str());
573  }
574  catch(...)
575  {
576  __SS__ << "An unknown error was encountered handling requestType '" << requestType
577  << ".' "
578  << "Please check the printouts to debug." << __E__;
579  __COUT__ << "\n" << ss.str();
580  xmlOut.addTextElementToData("Error", ss.str());
581  }
582 
583  // return xml doc holding server response
584  xmlOut.outputXmlDocument(
585  (std::ostringstream*)out,
586  false /*dispStdOut*/,
587  true /*allowWhiteSpace*/); // Note: allow white space need for error response
588 
589 } // end request()
590 
591 //========================================================================================================================
592 void WizardSupervisor::editSecurity(xgi::Input* in,
593  xgi::Output* out)
594 {
595  // if sequence doesn't match up -> return
596  cgicc::Cgicc cgi(in);
597  std::string submittedSequence = CgiDataUtilities::postData(cgi, "sequence");
598  std::string submittedSecurity = CgiDataUtilities::postData(cgi, "selection");
599  std::string securityFileName = SECURITY_FILE_NAME;
600 
601  // SECURITY CHECK START ****
602  if(securityCode_.compare(submittedSequence) != 0)
603  {
604  __COUT__ << "Unauthorized Request made, security sequence doesn't match!"
605  << std::endl;
606  return;
607  }
608  else
609  {
610  __COUT__ << "***Successfully authenticated security sequence." << std::endl;
611  }
612  // SECURITY CHECK END ****
613 
614  if(submittedSecurity != "")
615  {
616  __COUT__ << "Selection exists!" << std::endl;
617  __COUT__ << submittedSecurity << std::endl;
618 
619  if(submittedSecurity == "ResetAllUserData")
620  {
621  WebUsers::deleteUserData();
622  __COUT__ << "Turning URL Generation back to default!" << std::endl;
623  // std::remove((SEQUENCE_FILE_NAME).c_str());
624  // std::remove((SEQUENCE_OUT_FILE_NAME).c_str());
625  std::ofstream newFile((SEQUENCE_FILE_NAME).c_str());
626  newFile << "4" << std::endl;
627  newFile.close();
628 
629  generateURL();
630  std::thread([&](WizardSupervisor* ptr,
631  std::string securityCode) { printURL(ptr, securityCode); },
632  this,
633  securityCode_)
634  .detach();
635  *out << "Default_URL_Generation";
636  }
637  else if(submittedSecurity == "ResetAllUserTooltips")
638  {
639  WebUsers::resetAllUserTooltips();
640  *out << submittedSecurity;
641  return;
642  }
643  else if(submittedSecurity == "DigestAccessAuthentication" ||
644  submittedSecurity == "NoSecurity")
645  {
646  std::ofstream writeSecurityFile;
647 
648  writeSecurityFile.open(securityFileName.c_str());
649  if(writeSecurityFile.is_open())
650  writeSecurityFile << submittedSecurity;
651  else
652  __COUT__ << "Error writing file!" << std::endl;
653 
654  writeSecurityFile.close();
655  }
656  else
657  {
658  __COUT_ERR__ << "Invalid submittedSecurity string: " << submittedSecurity
659  << std::endl;
660  *out << "Error";
661  return;
662  }
663  }
664 
665  // Always return the file
666  std::ifstream securityFile;
667  std::string line;
668  std::string security = "";
669  int lineNumber = 0;
670 
671  securityFile.open(securityFileName.c_str());
672 
673  if(!securityFile)
674  {
675  //__SS__ << "Error opening file: "<< securityFileName << std::endl;
676  //__COUT_ERR__ << "\n" << ss.str();
677 
678  //__SS_THROW__;
679  // return;
680  security = "DigestAccessAuthentication"; // default security when no file exists
681  }
682  if(securityFile.is_open())
683  {
684  //__COUT__ << "Opened File: " << securityFileName << std::endl;
685  while(std::getline(securityFile, line))
686  {
687  security += line;
688  lineNumber++;
689  }
690  //__COUT__ << std::to_string(lineNumber) << ":" << iconList << std::endl;
691 
692  // Close file
693  securityFile.close();
694  }
695 
696  *out << security;
697 }
698 //========================================================================================================================
699 void WizardSupervisor::UserSettings(xgi::Input* in,
700  xgi::Output* out)
701 {
702  // if sequence doesn't match up -> return
703  cgicc::Cgicc cgi(in);
704  std::string submittedSequence = CgiDataUtilities::postData(cgi, "sequence");
705  std::string securityFileName = SECURITY_FILE_NAME;
706  std::string Command;
707  if((Command = CgiDataUtilities::postData(cgi, "RequestType")) == "")
708  Command = cgi("RequestType"); // get command from form, if PreviewEntry
709 
710  __COUT__ << Command << std::endl;
711  __COUT__ << "We are vewing Users' Settings!" << std::endl;
712 
713  // SECURITY CHECK START ****
714  if(securityCode_.compare(submittedSequence) != 0)
715  {
716  __COUT__ << "Unauthorized Request made, security sequence doesn't match!"
717  << std::endl;
718  __COUT__ << submittedSequence << std::endl;
719  // return;
720  }
721  else
722  {
723  __COUT__ << "***Successfully authenticated security sequence." << std::endl;
724  }
725  // SECURITY CHECK END ****
726 
727  HttpXmlDocument xmldoc;
728  uint64_t activeSessionIndex;
729  std::string user;
730  uint8_t userPermissions;
731 
732  if(Command != "")
733  {
734  __COUT__ << "Action exists!" << std::endl;
735  __COUT__ << Command << std::endl;
736 
737  if(Command == "Import")
738  {
739  // cleanup temporary folder
740  // NOTE: all input parameters for User Data will be attached to form
741  // so use cgi(xxx) to get values.
742  // increment number for each temporary preview, previewPostTempIndex_
743  // save entry and uploads to previewPath / previewPostTempIndex_ /.
744 
745  // cleanUpPreviews();
746  // std::string EntryText = cgi("EntryText");
747  // __COUT__ << "EntryText " << EntryText << std::endl << std::endl;
748  // std::string EntrySubject = cgi("EntrySubject");
749  // __COUT__ << "EntrySubject " << EntrySubject << std::endl <<
750  // std::endl;
751 
752  // get creator name
753  // std::string creator = user;
754  // CgiDataUtilities::postData(cgi, "file"); CgiDataUtilities::postData(cgi,
755  // "file");//
756  __COUT__ << cgi("Entry") << std::endl;
757  __COUT__ << cgi("Filename") << std::endl;
758  __COUT__ << cgi("Imported_File") << std::endl;
759 
760  const std::vector<cgicc::FormFile> files = cgi.getFiles();
761  __COUT__ << "FormFiles: " << sizeof(files) << std::endl;
762  __COUT__ << "Number of files: " << files.size() << std::endl;
763 
764  for(unsigned int i = 0; i < files.size(); ++i)
765  {
766  std::string filename = USER_DATA_PATH + files[i].getFilename();
767  __COUT__ << filename << std::endl;
768  std::ofstream myFile;
769  myFile.open(filename.c_str());
770  files[0].writeToStream(myFile);
771  }
772 
773  __COUT__ << files[0].getFilename() << std::endl;
774  __COUT__ << "********************Files Begin********************"
775  << std::endl;
776  for(unsigned int i = 0; i < files.size(); ++i)
777  {
778  __COUT__ << files[i].getDataType() << std::endl;
779  }
780  __COUT__ << "*********************Files End*********************"
781  << std::endl;
782 
783  // savePostPreview(EntrySubject, EntryText, cgi.getFiles(), creator,
784  //&xmldoc); else xmldoc.addTextElementToData(XML_STATUS,"Failed - could not
785  // get username info.");
786  }
787  else if(Command == "Export")
788  {
789  __SS__ << "This has been commented out due to problems compiling. Contact "
790  "system admins."
791  << __E__;
792  __SS_THROW__;
793  //
794  // __COUT__ << "We are exporting Users' Settings!!!" << std::endl;
795  // //system('pwd');
796  //
797  // //Check for a TMP directory; if it doesn't exist, make it
798  // std::string command = "cd " + USER_DATA_PATH;
799  // std::string pathToTmp = USER_DATA_PATH + "/tmp/";
800  // std::filesystem::path tmp = pathToTmp;
801  //
802  // exec(command.c_str());
803  // __COUT__ << exec("pwd") << std::endl;
804  //
805  //
806  // if(std::filesystem::status_known(tmpDir) ?
807  // std::filesystem::exists(tmpDir) : std::filesystem::exists(tmpDir))
808  // __COUT__ << pathToTmp << " exists!" << std::endl;
809  // else
810  // __COUT__ << pathToTmp << "does not exist! Creating it now. "
811  //<< std::endl;
812  //
813  // //Zip current files into TMP directory
814  // command = std::string("tar -cvf user_settings.tar") +
815  // std::string("ActiveTableGroups.cfg ") +
816  // std::string("ConsolePreferences ") +
817  // std::string("CoreTableInfoNames.dat ") +
818  // std::string("LoginData ") +
819  // std::string("OtsWizardData ") +
820  // std::string("ProgressBarData ");
821  //
822  //
823  // //return zip
824  // if(exec("pwd").find(USER_DATA_PATH) != std::string::npos)
825  // {
826  // __COUT__ << "Found USER_DATA directory " << std::endl;
827  // system(command.c_str());
828  // __COUT__ << system("ls") << std::endl;
829  // }
830  }
831  else
832  {
833  __COUT__ << "Command request not recognized: " << Command << std::endl;
834  *out << "Error";
835  return;
836  }
837  }
838 
839  *out << "test";
840  return;
841 }
842 //========================================================================================================================
843 // validateUploadFileType
844 // returns "" if file type is invalid, else returns file extension to use
845 std::string WizardSupervisor::validateUploadFileType(const std::string fileType)
846 {
847  for(unsigned int i = 0; i < allowedFileUploadTypes_.size(); ++i)
848  if(allowedFileUploadTypes_[i] == fileType)
849  return matchingFileUploadTypes_[i]; // found and done
850 
851  return ""; // not valid, return ""
852 }
853 //========================================================================================================================
854 // cleanUpPreviews
855 // cleanup logbook preview directory
856 // all names have time_t creation time + "_" + incremented index
857 void WizardSupervisor::cleanUpPreviews()
858 {
859  std::string userData = (std::string)USER_DATA_PATH;
860 
861  DIR* dir = opendir(userData.c_str());
862  if(!dir)
863  {
864  __COUT__ << "Error - User Data directory missing: " << userData << std::endl;
865  return;
866  }
867 
868  struct dirent* entry;
869  time_t dirCreateTime;
870  unsigned int i;
871 
872  while(
873  (entry = readdir(
874  dir))) // loop through all entries in directory and remove anything expired
875  {
876  if(strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0 &&
877  strcmp(entry->d_name, ".svn") != 0)
878  {
879  // replace _ with space so sscanf works
880  for(i = 0; i < strlen(entry->d_name); ++i)
881  if(entry->d_name[i] == '_')
882  {
883  entry->d_name[i] = ' ';
884  break;
885  }
886  sscanf(entry->d_name, "%li", &dirCreateTime);
887 
888  if((time(0) - dirCreateTime) > USER_DATA_EXPIRATION_TIME)
889  {
890  __COUT__ << "Expired" << std::endl;
891 
892  entry->d_name[i] = '_'; // put _ back
893 
894  __COUT__ << "rm -rf " << USER_DATA_PATH + (std::string)entry->d_name
895  << std::endl
896  << std::endl;
897  system(((std::string)("rm -rf " + userData + (std::string)entry->d_name))
898  .c_str());
899  }
900  }
901  }
902 
903  closedir(dir);
904 }
905 
906 //========================================================================================================================
907 // savePostPreview
908 // save post to preview directory named with time and incremented index
909 void WizardSupervisor::savePostPreview(std::string& subject,
910  std::string& text,
911  const std::vector<cgicc::FormFile>& files,
912  std::string creator,
913  HttpXmlDocument* xmldoc)
914 {
915  /*if(activeExperiment_ == "") //no active experiment!
916  {
917  if(xmldoc) xmldoc->addTextElementToData(XML_STATUS,"Failed - no active experiment
918  currently!"); return;
919  }
920 */
921  char fileIndex[40];
922  sprintf(fileIndex,
923  "%lu_%lu",
924  time(0),
925  clock()); // create unique time label for entry time(0)_clock()
926  std::string userDataPath = (std::string)USER_DATA_PATH + (std::string)fileIndex;
927 
928  __COUT__ << "userDataPath " << userDataPath << std::endl;
929  if(-1 == mkdir(userDataPath.c_str(), 0755))
930  {
931  if(xmldoc)
932  xmldoc->addTextElementToData(XML_STATUS,
933  "Failed - directory could not be generated.");
934  return;
935  }
936  /*
937  //new directory created successfully, save text and files
938  //entry structure:
939  // <XML_LOGBOOK_ENTRY>
940  // <XML_LOGBOOK_ENTRY_TIME>
941  // <XML_LOGBOOK_ENTRY_CREATOR>
942  // <XML_LOGBOOK_ENTRY_SUBJECT>
943  // <XML_LOGBOOK_ENTRY_TEXT>
944  // <XML_LOGBOOK_ENTRY_FILE value=fileType0>
945  // <XML_LOGBOOK_ENTRY_FILE value=fileType1> ...
946  // </XML_LOGBOOK_ENTRY>
947 
948  escapeLogbookEntry(text);
949  escapeLogbookEntry(subject);
950  __COUT__ << "~~subject " << subject << std::endl << "~~text " << text << std::endl <<
951  std::endl;
952 
953  HttpXmlDocument previewXml;
954 
955  previewXml.addTextElementToData(XML_LOGBOOK_ENTRY);
956  previewXml.addTextElementToParent(XML_LOGBOOK_ENTRY_TIME, fileIndex,
957  XML_LOGBOOK_ENTRY); if(xmldoc)
958  xmldoc->addTextElementToData(XML_LOGBOOK_ENTRY_TIME,fileIndex); //return time
959  previewXml.addTextElementToParent(XML_LOGBOOK_ENTRY_CREATOR, creator,
960  XML_LOGBOOK_ENTRY); if(xmldoc)
961  xmldoc->addTextElementToData(XML_LOGBOOK_ENTRY_CREATOR,creator); //return creator
962  previewXml.addTextElementToParent(XML_LOGBOOK_ENTRY_TEXT, text, XML_LOGBOOK_ENTRY);
963  if(xmldoc) xmldoc->addTextElementToData(XML_LOGBOOK_ENTRY_TEXT,text); //return text
964  previewXml.addTextElementToParent(XML_LOGBOOK_ENTRY_SUBJECT, subject,
965  XML_LOGBOOK_ENTRY); if(xmldoc)
966  xmldoc->addTextElementToData(XML_LOGBOOK_ENTRY_SUBJECT,subject); //return subject
967 
968  __COUT__ << "file size " << files.size() << std::endl;
969 
970  std::string filename;
971  std::ofstream myfile;
972  for (unsigned int i=0; i<files.size(); ++i)
973  {
974 
975  previewXml.addTextElementToParent(XML_LOGBOOK_ENTRY_FILE, files[i].getDataType(),
976  XML_LOGBOOK_ENTRY); if(xmldoc)
977  xmldoc->addTextElementToData(XML_LOGBOOK_ENTRY_FILE,files[i].getDataType()); //return
978  file type
979 
980  if((filename = validateUploadFileType(files[i].getDataType())) == "") //invalid
981  file type
982  {
983  if(xmldoc) xmldoc->addTextElementToData(XML_STATUS,"Failed - invalid file
984  type, " + files[i].getDataType() + "."); return;
985  }*/
986 
987  /*//file validated, so save upload to temp directory
988  sprintf(fileIndex,"%d",i);
989  filename = previewPath + "/" + (std::string)LOGBOOK_PREVIEW_UPLOAD_PREFACE +
990  (std::string)fileIndex + "." + filename;
991 
992  __COUT__ << "file " << i << " - " << filename << std::endl;
993  myfile.open(filename.c_str());
994  if (myfile.is_open())
995  {
996  files[i].writeToStream(myfile);
997  myfile.close();
998  }
999  }*/
1000  /*
1001  //save xml doc for preview entry
1002  previewXml.saveXmlDocument(USER_DATA_PATH + "/" + (std::string)LOGBOOK_PREVIEW_FILE);
1003 
1004  if(xmldoc) xmldoc->addTextElementToData(XML_STATUS,"1"); //1 indicates success!
1005  if(xmldoc) xmldoc->addTextElementToData(XML_PREVIEW_INDEX,"1"); //1 indicates is a
1006  preview post*/
1007 }