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