otsdaq_utilities  v2_03_00
VisualSupervisor.cc
1 #include "otsdaq-utilities/Visualization/VisualSupervisor.h"
2 //#include "otsdaq-core/RootUtilities/DQMHistos.h"
3 #include "otsdaq-core/DataManager/DataManagerSingleton.h"
4 #include "otsdaq-core/Macros/BinaryStringMacros.h"
5 
6 // ROOT documentation
7 // http://root.cern.ch/root/html/index.html
8 
9 #include <TBuffer.h>
10 #include <TBufferJSON.h>
11 #include <TCanvas.h>
12 #include <TClass.h>
13 #include <TDirectory.h>
14 #include <TFile.h>
15 #include <TH1.h>
16 #include <TH2.h>
17 #include <TIterator.h>
18 #include <TKey.h>
19 #include <TProfile.h>
20 #include <TROOT.h>
21 #include <TRegexp.h>
22 #include <TString.h>
23 #include "TBufferFile.h"
24 #include "TObject.h"
25 
26 #include <dirent.h> /*DIR and dirent*/
27 #include <sys/stat.h> /*mkdir*/
28 
29 #include <xdaq/NamespaceURI.h>
30 
31 #include <iostream>
32 
33 #define ROOT_BROWSER_PATH getenv("ROOT_BROWSER_PATH")
34 #define ROOT_DISPLAY_CONFIG_PATH getenv("ROOT_DISPLAY_CONFIG_PATH")
35 
36 #define LIVEDQM_DIR std::string("LIVE_DQM")
37 #define PRE_MADE_ROOT_CFG_DIR std::string("Pre-made Views")
38 
39 #define PRE_MADE_ROOT_CFG_FILE_EXT std::string(".rcfg")
40 
41 #define PREFERENCES_PATH std::string(getenv("SERVICE_DATA_PATH")) + "/VisualizerData/"
42 #define PREFERENCES_FILE_EXT ".pref"
43 
44 #define ROOT_VIEWER_PERMISSIONS_THRESHOLD 100
45 
46 using namespace ots;
47 
48 #undef __MF_SUBJECT__
49 #define __MF_SUBJECT__ "Visualizer"
50 
51 XDAQ_INSTANTIATOR_IMPL(VisualSupervisor)
52 
53 //========================================================================================================================
54 VisualSupervisor::VisualSupervisor(xdaq::ApplicationStub* stub)
55  : CoreSupervisorBase(stub), theDataManager_(0), loadedRunNumber_(-1)
56 {
57  __SUP_COUT__ << "Constructor." << __E__;
58  INIT_MF("VisualSupervisor");
59 
60  theDataManager_ = DataManagerSingleton::getInstance<VisualDataManager>(
61  theConfigurationManager_->getNode(
62  theConfigurationManager_->__GET_CONFIG__(XDAQContextTable)->getTableName()),
63  CorePropertySupervisorBase::getSupervisorConfigurationPath(),
64  CorePropertySupervisorBase::getSupervisorUID());
65 
66  CoreSupervisorBase::theStateMachineImplementation_.push_back(theDataManager_);
67 
68  __SUP_COUT__ << "Done instantiating Visual data manager." << __E__;
69 
70  // xgi::bind(this, &VisualSupervisor::safariDefaultPage, "safari" );
71 
72  // make preferences directory in case they don't exist
73  mkdir(((std::string)PREFERENCES_PATH).c_str(), 0755);
74 
75  __SUP_COUT__ << "Constructed." << __E__;
76 } //end constructor
77 
78 //========================================================================================================================
79 VisualSupervisor::~VisualSupervisor(void)
80 {
81  __SUP_COUT__ << "Destructor." << __E__;
82  destroy();
83  __SUP_COUT__ << "Destructed." << __E__;
84 } // end destructor()
85 
86 //========================================================================================================================
87 void VisualSupervisor::destroy(void)
88 {
89  __SUP_COUT__ << "Destroying..." << __E__;
90 
91  // called by destructor
92  // delete theConfigurationManager_;
93 
94  DataManagerSingleton::deleteInstance(
95  CorePropertySupervisorBase::getSupervisorUID());
96  theStateMachineImplementation_.pop_back();
97 } //end destroy()
98 //
100 // void VisualSupervisor::defaultPage(xgi::Input * in, xgi::Output * out )
101 //{
102 // //__SUP_COUT__ << this->getApplicationContext()->getURL() << __E__;
103 //
104 // *out << "<!DOCTYPE HTML><html lang='en'><frameset col='100%' row='100%'><frame
105 // src='/WebPath/html/Visualization.html?urn=" <<
106 // this->getApplicationDescriptor()->getLocalId() <<"'></frameset></html>";
107 //
108 //}
109 //
111 // void VisualSupervisor::safariDefaultPage(xgi::Input * in, xgi::Output * out )
112 //{
113 // *out << "<!DOCTYPE HTML><html lang='en'><iframe
114 // style='width:100%;height:100%;position:absolute;left:0;top:0;border:0;padding:0;margin:0;'
115 // src='/WebPath/html/Visualization.html?urn=" <<
116 // this->getApplicationDescriptor()->getLocalId() <<"'></iframe></html>";
117 //}
118 
119 //========================================================================================================================
120 // setSupervisorPropertyDefaults
121 // override to set defaults for supervisor property values (before user settings
122 // override)
123 void VisualSupervisor::setSupervisorPropertyDefaults()
124 {
125  CorePropertySupervisorBase::setSupervisorProperty(
126  CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.AllowNoLoginRequestTypes,
127  "setUserPreferences | getUserPreferences | getDirectoryContents | getRoot | "
128  "getEvents");
129 
130  CorePropertySupervisorBase::setSupervisorProperty(
131  CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.UserPermissionsThreshold,
132  "*=1 | rootAdminControls=100");
133 }
134 
135 //========================================================================================================================
136 // forceSupervisorPropertyValues
137 // override to force supervisor property values (and ignore user settings)
138 void VisualSupervisor::forceSupervisorPropertyValues()
139 {
140  CorePropertySupervisorBase::setSupervisorProperty(
141  CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.AutomatedRequestTypes,
142  "getRoot | getEvents");
143  CorePropertySupervisorBase::setSupervisorProperty(
144  CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.NoXmlWhiteSpaceRequestTypes,
145  "getRoot | getEvents"); // json data in ROOTJS library expects no funny
146  // characters
147  // CorePropertySupervisorBase::setSupervisorProperty(CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.NeedUsernameRequestTypes,
148  // "setUserPreferences | getUserPreferences");
149 }
150 
151 //========================================================================================================================
152 void VisualSupervisor::request(const std::string& requestType,
153  cgicc::Cgicc& cgiIn,
154  HttpXmlDocument& xmlOut,
155  const WebUsers::RequestUserInfo& userInfo)
156 {
157  // Commands
158  // getRawData
159  // getGeometry
160  // getEvents
161  // getRoot
162  // getDirectoryContents
163  // setUserPreferences
164  // getUserPreference
165 
166  // if (requestType == "getHisto" && theDataManager_->getLiveDQMHistos() != 0)
167  // {
168  // // TH1I* histo =
169  // (TH1I*)theDataManager_->getLiveDQMHistos()->get("Planes/Plane_0_Occupancy");
170  //
171  // // theDataManager_->load("Run185_Histo.root","Histograms");
172  // //TH1F* histo1d = theDataManager_->getFileDQMHistos().getHisto1D();
173  // //TCanvas* canvas = theDataManager_->getFileDQMHistos().getCanvas ();
174  // //TH2F* histo2d = theDataManager_->getFileDQMHistos().getHisto2D();
175  // //TProfile* profile = theDataManager_->getFileDQMHistos().getProfile();
176  //
177  // }
178  if(requestType == "getRawData")
179  {
180  __SUP_COUT__ << __E__;
181  try
182  {
183  // TODO -- add timestamp, so we know if data is new
184  __SUP_COUT__ << "Getting Raw data and converting to binary string" << __E__;
185  xmlOut.addBinaryStringToData("rawData", theDataManager_->getRawData());
186  __SUP_COUT__ << __E__;
187  }
188  catch(std::exception const& e)
189  {
190  __SUP_COUT__
191  << "ERROR! Exception while getting raw data. Incoming exception data..."
192  << __E__;
193  __SUP_COUT__ << e.what() << __E__;
194  __SUP_COUT__ << "End Exception Data" << __E__;
195  }
196  catch(...)
197  {
198  __SUP_COUT__ << "ERROR! Something went wrong trying to get raw data."
199  << __E__;
200  __SUP_COUT_INFO__ << "ERROR! Something went wrong trying to get raw data."
201  << __E__;
202  }
203  }
204  else if(requestType == "setUserPreferences" &&
205  userInfo.username_ != "" /*from allow no user*/)
206  {
207  __SUP_COUT__ << "userInfo.username_: " << userInfo.username_ << __E__;
208  std::string fullPath =
209  (std::string)PREFERENCES_PATH + userInfo.username_ + PREFERENCES_FILE_EXT;
210  __SUP_COUT__ << "fullPath: " << fullPath << __E__;
211 
212  std::string radioSelect = CgiDataUtilities::getData(cgiIn, "radioSelect");
213  std::string autoRefresh = CgiDataUtilities::getData(cgiIn, "autoRefresh");
214  std::string autoHide = CgiDataUtilities::getData(cgiIn, "autoHide");
215  std::string hardRefresh = CgiDataUtilities::getData(cgiIn, "hardRefresh");
216  std::string autoRefreshPeriod =
217  CgiDataUtilities::getData(cgiIn, "autoRefreshPeriod");
218 
219  __SUP_COUT__ << "radioSelect: " << radioSelect << __E__;
220  __SUP_COUT__ << "autoRefresh: " << autoRefresh << __E__;
221  __SUP_COUT__ << "autoHide: " << autoHide << __E__;
222  __SUP_COUT__ << "hardRefresh: " << hardRefresh << __E__;
223  __SUP_COUT__ << "autoRefreshPeriod: " << autoRefreshPeriod << __E__;
224 
225  // read existing
226  FILE* fp = fopen(fullPath.c_str(), "r");
227  if(fp)
228  {
229  char line[100];
230  char val[100];
231 
232  fgets(line, 100, fp);
233  sscanf(line, "%*s %s", val);
234  if(radioSelect == "")
235  radioSelect = val;
236 
237  fgets(line, 100, fp);
238  sscanf(line, "%*s %s", val);
239  if(autoRefresh == "")
240  autoRefresh = val;
241 
242  fgets(line, 100, fp);
243  sscanf(line, "%*s %s", val);
244  if(autoHide == "")
245  autoHide = val;
246 
247  fgets(line, 100, fp);
248  sscanf(line, "%*s %s", val);
249  if(hardRefresh == "")
250  hardRefresh = val;
251 
252  fgets(line, 100, fp);
253  sscanf(line, "%*s %s", val);
254  if(autoRefreshPeriod == "")
255  autoRefreshPeriod = val;
256 
257  fclose(fp);
258  }
259 
260  // write new
261  fp = fopen(fullPath.c_str(), "w");
262  if(fp)
263  {
264  fprintf(fp, "radioSelect %s\n", radioSelect.c_str());
265  fprintf(fp, "autoRefresh %s\n", autoRefresh.c_str());
266  fprintf(fp, "autoHide %s\n", autoHide.c_str());
267  fprintf(fp, "hardRefresh %s\n", hardRefresh.c_str());
268  fprintf(fp, "autoRefreshPeriod %s\n", autoRefreshPeriod.c_str());
269  fclose(fp);
270  }
271  else
272  __SUP_COUT_ERR__ << "Failure writing preferences to file: " << fullPath
273  << __E__;
274  }
275  else if(requestType == "getUserPreferences")
276  {
277  __SUP_COUT__ << "userInfo.username_: " << userInfo.username_ << __E__;
278  std::string fullPath =
279  (std::string)PREFERENCES_PATH + userInfo.username_ + PREFERENCES_FILE_EXT;
280  __SUP_COUT__ << "fullPath: " << fullPath << __E__;
281 
282  FILE* fp = fopen(fullPath.c_str(), "r");
283  if(fp)
284  {
285  char line[100];
286  // char val[100];
287  int val;
288 
289  fgets(line, 100, fp);
290  sscanf(line, "%*s %d", &val);
291  if(val < 0 || val > 3)
292  val = 0; // FIXME.. value can get corrupt...
293  xmlOut.addTextElementToData("radioSelect", std::to_string(val));
294  fgets(line, 100, fp);
295  sscanf(line, "%*s %d", &val);
296  xmlOut.addTextElementToData("autoRefresh", std::to_string(val));
297  fgets(line, 100, fp);
298  sscanf(line, "%*s %d", &val);
299  xmlOut.addTextElementToData("autoHide", std::to_string(val));
300  fgets(line, 100, fp);
301  sscanf(line, "%*s %d", &val);
302  xmlOut.addTextElementToData("hardRefresh", std::to_string(val));
303  fgets(line, 100, fp);
304  sscanf(line, "%*s %d", &val);
305  xmlOut.addTextElementToData("autoRefreshPeriod", std::to_string(val));
306  fclose(fp);
307  }
308  else
309  {
310  // else assume user has no preferences yet
311  xmlOut.addTextElementToData("radioSelect", "");
312  xmlOut.addTextElementToData("autoRefresh", "");
313  xmlOut.addTextElementToData("autoHide", "");
314  xmlOut.addTextElementToData("hardRefresh", "");
315  xmlOut.addTextElementToData("autoRefreshPeriod", "");
316  }
317  }
318  else if(requestType == "getDirectoryContents")
319  {
320  // return directory structure for requested path, types are "dir" and "file"
321 
322  std::string rootpath = std::string(ROOT_BROWSER_PATH) + "/";
323  std::string path = CgiDataUtilities::postData(cgiIn, "Path");
324  __SUP_COUT__ << path << __E__;
325 
326  // return 1 if user has access to admin controls, else 0
327  char permStr[10];
328  sprintf(permStr,
329  "%d",
330  userInfo.permissionLevel_ >=
331  CoreSupervisorBase::getSupervisorPropertyUserPermissionsThreshold(
332  "rootAdminControls"));
333  xmlOut.addTextElementToData("permissions", permStr); // add permissions
334 
335  std::string dirpath = rootpath + path;
336  if(path == "/" + PRE_MADE_ROOT_CFG_DIR + "/")
337  dirpath = ROOT_DISPLAY_CONFIG_PATH;
338 
339  if(path.find("/" + PRE_MADE_ROOT_CFG_DIR + "/") ==
340  0) // ROOT config path must start the path
341  dirpath = std::string(ROOT_DISPLAY_CONFIG_PATH) + "/" +
342  path.substr(PRE_MADE_ROOT_CFG_DIR.length() + 2);
343 
344  __SUP_COUT__ << "full path: " << dirpath << __E__;
345 
346  DIR* pDIR;
347  struct dirent* entry;
348  bool isNotRtCfg;
349  bool isDir;
350  if((pDIR = opendir(dirpath.c_str())))
351  {
352  xmlOut.addTextElementToData("path", path);
353 
354  // add LIVE if path is / and DQM is active
355  // add Pre-made Views if path is / and ROOT_DISPLAY_CONFIG_PATH isnt already
356  // there
357  if(path == "/")
358  {
359  if(theDataManager_->getLiveDQMHistos() != 0)
360  xmlOut.addTextElementToData("dir",
361  LIVEDQM_DIR + ".root"); // add to xml
362 
363  // check for ROOT_DISPLAY_CONFIG_PATH
364  DIR* pRtDIR = opendir(ROOT_DISPLAY_CONFIG_PATH);
365  bool recheck = false;
366  if(!pRtDIR) // if doesn't exist, make it
367  {
368  recheck = true;
369  if(mkdir(ROOT_DISPLAY_CONFIG_PATH,
370  S_IRWXU | (S_IRGRP | S_IXGRP) |
371  (S_IROTH | S_IXOTH))) // mode = drwx r-x r-x
372  __SUP_COUT__ << "Failed to make directory for pre made views: "
373  << ROOT_DISPLAY_CONFIG_PATH << __E__;
374  }
375  else
376  closedir(pRtDIR); // else close and display
377 
378  if(!recheck || (pRtDIR = opendir(ROOT_DISPLAY_CONFIG_PATH)))
379  {
380  xmlOut.addTextElementToData("dir",
381  PRE_MADE_ROOT_CFG_DIR); // add to xml
382  if(recheck)
383  closedir(pRtDIR);
384  }
385  }
386 
387  while((entry = readdir(pDIR)))
388  {
389  //__SUP_COUT__ << int(entry->d_type) << " " << entry->d_name << "\n" <<
390  // __E__;
391  if(entry->d_name[0] != '.' &&
392  (entry->d_type ==
393  0 || // 0 == UNKNOWN (which can happen - seen in SL7 VM)
394  entry->d_type == 4 ||
395  entry->d_type == 8))
396  {
397  //__SUP_COUT__ << int(entry->d_type) << " " << entry->d_name << "\n"
398  //<< __E__;
399  isNotRtCfg =
400  std::string(entry->d_name).find(".rcfg") == std::string::npos;
401  isDir = false;
402 
403  if(entry->d_type == 0)
404  {
405  // unknown type .. determine if directory
406  DIR* pTmpDIR = opendir((dirpath + entry->d_name).c_str());
407  if(pTmpDIR)
408  {
409  isDir = true;
410  closedir(pTmpDIR);
411  }
412  // else //assume file
413  }
414 
415  if((entry->d_type == 8 ||
416  (!isDir && entry->d_type == 0)) // file type
417  && std::string(entry->d_name).find(".root") == std::string::npos &&
418  isNotRtCfg)
419  continue; // skip if not a root file or a config file
420  else if(entry->d_type == 4)
421  isDir = true; // flag directory types
422 
423  xmlOut.addTextElementToData(
424  isDir ? "dir" : (isNotRtCfg ? "dir" : "file"), entry->d_name);
425  }
426  }
427  closedir(pDIR);
428  }
429  else
430  __SUP_COUT__ << "Failed to access directory contents!" << __E__;
431  }
432  else if(requestType == "getRoot")
433  {
434  // return directory structure for requested ROOT path, types are "dir" and "file"
435 
436  std::string path = CgiDataUtilities::postData(cgiIn, "RootPath");
437  std::string fullPath = std::string(getenv("ROOT_BROWSER_PATH")) + path;
438 
439  //__SUP_COUT__ << "Full path:-" << fullPath << "-" << __E__;
440 
441  std::string rootFileName = fullPath.substr(0, fullPath.find(".root") + 5);
442  std::string rootDirectoryName =
443  rootFileName + ":" +
444  fullPath.substr(fullPath.find(".root") + 5,
445  fullPath.size() - fullPath.find(".root") + 5 + 1);
446 
447  std::string::size_type LDQM_pos = path.find("/" + LIVEDQM_DIR + ".root/");
448  TFile* rootFile;
449 
450  if(theDataManager_->getLiveDQMHistos() != nullptr && LDQM_pos == 0)
451  {
452  //__SUP_COUT__ << "Attempting to get LIVE file." << __E__;
453  rootFile = theDataManager_->getLiveDQMHistos()->getFile();
454  if(!rootFile)
455  __SUP_COUT__ << "File was closed." << __E__;
456  else
457  {
458  //__SUP_COUT__ << "LIVE file name: " << rootFile->GetName() << __E__;
459  rootDirectoryName = path.substr(("/" + LIVEDQM_DIR + ".root").length());
460  }
461  }
462  else
463  rootFile = TFile::Open(rootFileName.c_str());
464 
465  //__SUP_COUT__ << "FileName : " << rootFileName << " Object: " <<
466  // rootDirectoryName << __E__;
467 
468  if(!rootFile || !rootFile->IsOpen())
469  {
470  __SUP_COUT__ << "Failed to access root file: " << rootFileName << __E__;
471  }
472  else
473  {
474  xmlOut.addTextElementToData("path", path);
475 
476  TDirectory* directory;
477  if((directory = rootFile->GetDirectory(rootDirectoryName.c_str())) == 0)
478  {
479  //__SUP_COUT__ << "This is not a directory!" << __E__;
480  directory = rootFile;
481 
482  // failed directory so assume it's file
483  //__SUP_COUT__ << "Getting object name: " << rootDirectoryName <<
484  // __E__;
485  TObject* histoClone = nullptr;
486  TObject* histo = (TObject*)rootFile->Get(rootDirectoryName.c_str());
487 
488  if(histo != nullptr) // turns out was a root object path
489  {
490  // Clone histo to avoid conflict when it is filled by other threads
491  histoClone = histo->Clone();
492  TString json = TBufferJSON::ConvertToJSON(histoClone);
493  TBufferFile tBuffer(TBuffer::kWrite);
494  histoClone->Streamer(tBuffer);
495 
496  //__SUP_COUT__ << "histo length " << tbuff.Length() << __E__;
497 
498  std::string destination = BinaryStringMacros::binaryToHexString(
499  tBuffer.Buffer(), tBuffer.Length());
500 
501  xmlOut.addTextElementToData("rootType", histoClone->ClassName());
502  xmlOut.addTextElementToData("rootData", destination);
503  xmlOut.addTextElementToData("rootJSON", json.Data());
504  delete histoClone;
505  }
506  else
507  __SUP_COUT_ERR__ << "Failed to access:-" << rootDirectoryName << "-"
508  << __E__;
509  }
510  else
511  {
512  __SUP_COUT__ << "directory found getting the content!" << __E__;
513  TRegexp re("*", kTRUE);
514  if(LDQM_pos == 0)
515  {
516  TObject* obj;
517  TIter nextobj(directory->GetList());
518  while((obj = (TObject*)nextobj()))
519  {
520  TString s = obj->GetName();
521  if(s.Index(re) == kNPOS)
522  continue;
523  __SUP_COUT__ << "Class Name: " << obj->IsA()->GetName()
524  << __E__;
525  xmlOut.addTextElementToData(
526  (std::string(obj->IsA()->GetName()).find("Directory") !=
527  std::string::npos)
528  ? "dir"
529  : "file",
530  obj->GetName());
531  }
532  }
533  else
534  {
535  TKey* key;
536  TIter next(directory->GetListOfKeys());
537  while((key = (TKey*)next()))
538  {
539  TString s = key->GetName();
540  if(s.Index(re) == kNPOS)
541  continue;
542  __SUP_COUT__ << "Class Name: " << key->GetClassName()
543  << __E__;
544  xmlOut.addTextElementToData(
545  (std::string(key->GetClassName()).find("Directory") !=
546  std::string::npos)
547  ? "dir"
548  : "file",
549  key->GetName());
550  }
551  }
552  }
553  if(LDQM_pos == std::string::npos)
554  rootFile->Close();
555  }
556  }
557  else if(requestType == "getEvents")
558  {
559  int Run = atoi(cgiIn("run").c_str());
560 
561  __SUP_COUT__ << "getEvents for run " << Run << __E__;
562 
563  if(Run != (int)loadedRunNumber_ || loadedRunNumber_ == (unsigned int)-1)
564  {
565  theDataManager_->load("Run1684.root", "Monicelli");
566  loadedRunNumber_ = Run;
567  }
568 
569  DOMElement* eventsParent = xmlOut.addTextElementToData("events", "");
570  DOMElement* eventParent;
571  char str[40];
572 
573  // const Visual3DEvents& events = theDataManager_->getVisual3DEvents();
574  // __SUP_COUT__ << "Preparing hits xml" << __E__;
575  // int numberOfEvents = 0;
576  // for(Visual3DEvents::const_iterator it=events.begin(); it!=events.end() &&
577  // numberOfEvents < 10000; it++, numberOfEvents++)
578  // {
579  // //__SUP_COUT__ << "Event: " << numberOfEvents << __E__;
580  // eventParent = xmlOut.addTextElementToParent("event", str,
581  // eventsParent); const VisualHits& hits = it->getHits();
582  // for(VisualHits::const_iterator itHits=hits.begin();
583  // itHits!=hits.end(); itHits++)
584  // {
585  // sprintf(str,"%f",itHits->x);
586  // xmlOut.addTextElementToParent("xyz_point", str, eventParent);
587  // sprintf(str,"%f",itHits->y);
588  // xmlOut.addTextElementToParent("xyz_point", str, eventParent);
589  // sprintf(str,"%f",itHits->z);
590  // xmlOut.addTextElementToParent("xyz_point", str, eventParent);
591  // //__SUP_COUT__ << "X: " << itHits->x << " Y: " << itHits->y << "
592  // Z:
593  //"
594  //<< itHits->z << __E__;
595  // }
596  // const VisualTracks& tracks = it->getTracks();
597  // for(VisualTracks::const_iterator itTrks=tracks.begin();
598  // itTrks!=tracks.end(); itTrks++)
599  // {
600  // sprintf(str,"%f",itTrks->slopeX);
601  // xmlOut.addTextElementToParent("slope", str, eventParent);
602  // sprintf(str,"%f",itTrks->slopeY);
603  // xmlOut.addTextElementToParent("slope", str, eventParent);
604  // sprintf(str,"%f",itTrks->interceptX);
605  // xmlOut.addTextElementToParent("intcpt", str, eventParent);
606  // sprintf(str,"%f",itTrks->interceptY);
607  // xmlOut.addTextElementToParent("intcpt", str, eventParent);
608  //
609  // }
610  //
611  // }
612  __SUP_COUT__ << "Done hits xml" << __E__;
613  }
614  else if(requestType == "getGeometry")
615  {
616  __SUP_COUT__ << "getGeometry" << __E__;
617 
618  // FIXME -- this crashes when the file doesn't exist!
619  theDataManager_->load("Run1684.geo", "Geometry");
620 
621  __SUP_COUT__ << "getGeometry" << __E__;
622 
623  DOMElement* geometryParent = xmlOut.addTextElementToData("geometry", "");
624  // const Visual3DShapes& shapes =
625  // theDataManager_->getVisual3DGeometry().getShapes();
626  //
627  // __SUP_COUT__ << "getGeometry" << __E__;
628  //
629  //
630  // DOMElement* objectParent;
631  // char str[40];
632  // for(Visual3DShapes::const_iterator itShapes=shapes.begin();
633  // itShapes!=shapes.end(); itShapes++)
634  // {
635  // objectParent = xmlOut.addTextElementToParent("object", str,
636  // geometryParent);
637  // xmlOut.addTextElementToParent("object_type", "LINE_LOOP",
638  // objectParent); sprintf(str,"%d",itShapes->numberOfRows);
639  // xmlOut.addTextElementToParent("object_rows", str, objectParent);
640  // sprintf(str,"%d",itShapes->numberOfColumns);
641  // xmlOut.addTextElementToParent("object_columns", str, objectParent);
642  // for(Points::const_iterator itCorners=itShapes->corners.begin();
643  // itCorners!=itShapes->corners.end(); itCorners++)
644  // {
645  // sprintf(str,"%f",itCorners->x);
646  // xmlOut.addTextElementToParent("xyz_point", str, objectParent);
647  // sprintf(str,"%f",itCorners->y);
648  // xmlOut.addTextElementToParent("xyz_point", str, objectParent);
649  // sprintf(str,"%f",itCorners->z);
650  // xmlOut.addTextElementToParent("xyz_point", str, objectParent);
651  // }
652  // }
653  }
654  else if(requestType == "getRootConfig")
655  {
656  std::string path = CgiDataUtilities::postData(cgiIn, "RootConfigPath");
657  __SUP_COUT__ << "path " << path << __E__;
658 
659  if(path.find("/" + PRE_MADE_ROOT_CFG_DIR + "/") ==
660  0) // ROOT config path must start the path
661  {
662  path = std::string(ROOT_DISPLAY_CONFIG_PATH) + "/" +
663  path.substr(PRE_MADE_ROOT_CFG_DIR.length() + 2);
664  __SUP_COUT__ << "mod path " << path << __E__;
665  }
666 
667  HttpXmlDocument cfgXml;
668  if(cfgXml.loadXmlDocument(path))
669  {
670  xmlOut.addTextElementToData("status", "1");
671  xmlOut.copyDataChildren(cfgXml); // copy file to output xml
672  cfgXml.saveXmlDocument(path);
673  }
674  else
675  xmlOut.addTextElementToData("status",
676  "Failed. File to properly load config file.");
677  }
678  else if(requestType == "rootAdminControls")
679  {
680  // if(userPermissions < ROOT_VIEWER_PERMISSIONS_THRESHOLD)
681  // {
682  // __SUP_COUT__ << "Insufficient permissions for Root Viewer Admin
683  // Controls: " << userPermissions << " < " << ROOT_VIEWER_PERMISSIONS_THRESHOLD <<
684  // __E__;
685  // xmlOut.addTextElementToData("status", "Failed. Insufficient user
686  // permissions.");
687  // }
688  // else
689  // {
690  std::string cmd = cgiIn("cmd"); // possible commands are
691  // mkdir
692  // save
693  // delete
694 
695  std::string path = CgiDataUtilities::postData(cgiIn, "path");
696  std::string name = CgiDataUtilities::postData(cgiIn, "name");
697  __SUP_COUT__ << "cmd " << cmd << __E__;
698  __SUP_COUT__ << "path " << path << __E__;
699  __SUP_COUT__ << "name " << name << __E__;
700 
701  if(path.find("/" + PRE_MADE_ROOT_CFG_DIR + "/") ==
702  0) // ROOT config path must start the path
703  {
704  path = std::string(ROOT_DISPLAY_CONFIG_PATH) + "/" +
705  path.substr(PRE_MADE_ROOT_CFG_DIR.length() + 2) + name;
706  __SUP_COUT__ << "mod path " << path << __E__;
707 
708  if(cmd == "mkdir")
709  {
710  if(mkdir(path.c_str(),
711  S_IRWXU | (S_IRGRP | S_IXGRP) |
712  (S_IROTH | S_IXOTH))) // mode = drwx r-x r-x
713  xmlOut.addTextElementToData("status",
714  "Failed. Directory create rejected.");
715  else
716  xmlOut.addTextElementToData("status", "1"); // success
717  }
718  else if(cmd == "save")
719  {
720  path += PRE_MADE_ROOT_CFG_FILE_EXT; // add file extension
721 
722  bool useRunWildCard =
723  atoi(CgiDataUtilities::postData(cgiIn, "useRunWildCard")
724  .c_str()); // 0 or 1
725  std::string config = CgiDataUtilities::postData(cgiIn, "config");
726  __SUP_COUT__ << "config " << config << __E__;
727  __SUP_COUT__ << "useRunWildCard " << useRunWildCard << __E__;
728 
729  // check if file already exists
730  FILE* fp = fopen(path.c_str(), "r");
731  if(fp)
732  {
733  fclose(fp);
734  xmlOut.addTextElementToData("status", "Failed. File already exists.");
735  __SUP_COUT__ << " Failed. File already exists." << __E__;
736  }
737  else
738  {
739  // dump to file
740  // verify proper format through read back
741  // if successfully loaded, re-save for formatting
742 
743  // dump to file
744  fp = fopen(path.c_str(), "w");
745  fputs(config.c_str(), fp);
746  fclose(fp);
747 
748  // verify proper format through read back
749  HttpXmlDocument cfgXml;
750  if(cfgXml.loadXmlDocument(path))
751  {
752  // successfully loaded, re-save for formatting
753  cfgXml.saveXmlDocument(path);
754  xmlOut.addTextElementToData("status", "1"); // success
755  }
756  else // failed to load properly
757  {
758  xmlOut.addTextElementToData(
759  "status", "Failed. Fatal. Improper file format.");
760  if(remove(path.c_str()) != 0)
761  __SUP_COUT__ << "Failed. Could not remove poorly formed Root "
762  "config file!"
763  << __E__;
764  }
765  }
766  }
767  else if(cmd == "delete")
768  {
769  // guess first directory and then file
770  if(rmdir(path.c_str()) == 0 ||
771  remove((path + PRE_MADE_ROOT_CFG_FILE_EXT).c_str()) == 0)
772  xmlOut.addTextElementToData("status", "1"); // success
773  else
774  xmlOut.addTextElementToData("status",
775  "Failed. Target could not be deleted.");
776  }
777  else
778  xmlOut.addTextElementToData("status", "Failed. Unrecognized command.");
779  }
780  else
781  xmlOut.addTextElementToData("status", "Failed. Invalid path.");
782 
783  //}
784  }
785  else
786  __SUP_COUT__ << "requestType request, " << requestType << ", not recognized."
787  << __E__;
788  // return xml doc holding server response
789  // xmlOut.outputXmlDocument((std::ostringstream*) out, false);
790 }