GSI Object Oriented Online Offline (Go4)  GO4-6.3.0
TGo4HttpProxy.cpp
Go to the documentation of this file.
1 // $Id$
2 //-----------------------------------------------------------------------
3 // The GSI Online Offline Object Oriented (Go4) Project
4 // Experiment Data Processing at EE department, GSI
5 //-----------------------------------------------------------------------
6 // Copyright (C) 2000- GSI Helmholtzzentrum fuer Schwerionenforschung GmbH
7 // Planckstr. 1, 64291 Darmstadt, Germany
8 // Contact: http://go4.gsi.de
9 //-----------------------------------------------------------------------
10 // This software can be used under the license agreements as stated
11 // in Go4License.txt file which is part of the distribution.
12 //-----------------------------------------------------------------------
13 
14 #include "TGo4HttpProxy.h"
15 
16 #include "TROOT.h"
17 #include "TClass.h"
18 #include "TList.h"
19 #include "TH1.h"
20 #include "TH2.h"
21 #include "TGraph.h"
22 #include "TBufferFile.h"
23 
24 #include "TGo4Condition.h"
25 #include "TGo4Slot.h"
26 #include "TGo4Iter.h"
27 #include "TGo4ObjectProxy.h"
28 #include "TGo4Ratemeter.h"
29 #include "TGo4AnalysisStatus.h"
30 
31 #include <QtNetwork>
32 #include <QTimer>
33 #include <QElapsedTimer>
34 #include <QApplication>
35 #include <QEventLoop>
36 #include <QInputDialog>
37 
39  QObject(),
40  qnam(),
41  fHReply(nullptr),
42  fProxy(p)
43 {
44  QObject::connect(&qnam, &QNetworkAccessManager::authenticationRequired, this, &QHttpProxy::authenticationRequiredSlot);
45 }
46 
48 {
49 }
50 
52 {
53  if (!fHReply) return;
54 
55  QByteArray res = fHReply->readAll();
56  fHReply->deleteLater();
57  fHReply = nullptr;
58  fProxy->GetHReply(res);
59 }
60 
61 void QHttpProxy::httpHReqError(QNetworkReply::NetworkError code)
62 {
63  if (gDebug > 0)
64  printf("QHttpProxy::httpHReqError %d %s\n", code, fHReply ? fHReply->errorString().toLatin1().constData() : "---");
65  if (fHReply) {
66  fHReply->deleteLater();
67  fHReply = nullptr;
68  }
69 }
70 
72 {
74  QTimer::singleShot(2000, this, &QHttpProxy::updateRatemeter);
75 }
76 
78 {
79  if (fProxy) fProxy->UpdateHierarchy(kFALSE);
80 }
81 
83 {
85 }
86 
87 void QHttpProxy::StartRequest(const char *url)
88 {
89  fHReply = qnam.get(QNetworkRequest(QUrl(url)));
90 
91  QObject::connect(fHReply, &QNetworkReply::finished, this, &QHttpProxy::httpFinished);
92 
93 #if QT_VERSION < QT_VERSION_CHECK(5,15,0)
94  QObject::connect(fHReply, (void (QNetworkReply::*)(QNetworkReply::NetworkError)) &QNetworkReply::error, this, &QHttpProxy::httpHReqError);
95 #else
96  QObject::connect(fHReply, &QNetworkReply::errorOccurred, this, &QHttpProxy::httpHReqError);
97 #endif
98 
99  QObject::connect(fHReply, &QNetworkReply::sslErrors, [this](const QList<QSslError> &errors) { fHReply->ignoreSslErrors(errors); });
100 
101  QSslConfiguration cfg = fHReply->sslConfiguration();
102  cfg.setProtocol(QSsl::AnyProtocol/*QSsl::TlsV1SslV3*/);
103  fHReply->setSslConfiguration(cfg);
104 }
105 
106 void QHttpProxy::authenticationRequiredSlot(QNetworkReply* repl, QAuthenticator* auth)
107 {
108  if (fProxy->fUserName.Length()>0) {
109  auth->setUser(fProxy->fUserName.Data());
110  auth->setPassword(fProxy->fPassword.Data());
111  return;
112  }
113 
114  bool ok = false;
115  QString user_name =
116  QInputDialog::getText(nullptr, tr("Authentication required"),
117  tr("User name:"), QLineEdit::Normal,
118  "", &ok);
119  if (!ok) return;
120  QString passwd =
121  QInputDialog::getText(nullptr, tr("Authentication required"),
122  tr("User password:"), QLineEdit::Password,
123  "", &ok);
124  if (!ok) return;
125 
126  fProxy->fUserName = user_name.toLatin1().constData();
127  fProxy->fPassword = passwd.toLatin1().constData();
128 
129  auth->setUser(user_name);
130  auth->setPassword(passwd);
131 }
132 
133 const char *GetHttpRootClassName(const char *kind)
134 {
135  if (!kind || (*kind == 0)) return nullptr;
136  if (strncmp(kind,"ROOT.", 5) != 0) return nullptr;
137  if (strcmp(kind+5,"TGo4AnalysisWebStatus") == 0)
138  return "TGo4AnalysisStatus";
139  return kind+5;
140 }
141 
142 // ============================================================================================
143 
144 TGo4HttpAccess::TGo4HttpAccess(TGo4HttpProxy *proxy, XMLNodePointer_t node, Int_t kind, const char *extra_arg) :
145  TGo4Access(),
146  fProxy(proxy),
147  fNode(node),
148  fUrlPath(),
149  fKind(kind),
150  fNameAttr(),
151  fKindAttr(),
152  fExtraArg(),
153  fReceiver(nullptr),
154  fRecvPath(),
155  fReply(nullptr)
156 {
157  const char *_name = fProxy->fXML->GetAttr(fNode,"_realname");
158  if (!_name) _name = fProxy->fXML->GetAttr(fNode,"_name");
159  if (_name) fNameAttr = _name;
160 
161  fUrlPath = fProxy->MakeUrlPath(node);
162 
163  const char *_kind = fProxy->fXML->GetAttr(fNode,"_kind");
164  if (_kind) fKindAttr = _kind;
165  if (extra_arg) fExtraArg = extra_arg;
166 }
167 
169 {
170  if (fKind==3) return TGraph::Class();
171  if (fKind==4) return gROOT->GetClass("TGo4ParameterStatus");
172  if (fKind==5) return gROOT->GetClass("TTree");
173  if (fKind==6) return gROOT->GetClass("TGo4AnalysisStatus");
174  if (fKind==7) return gROOT->GetClass("TList");
175  if (fKind==8) return gROOT->GetClass("TGo4HistogramStatus");
177 }
178 
179 const char *TGo4HttpAccess::GetObjectName() const
180 {
181  return fNameAttr.Data();
182 }
183 
185 {
186  if (fKind==3) return "TGraph";
187  if (fKind==4) return "TGo4ParameterStatus";
188  if (fKind==6) return "TGo4AnalysisStatus";
189  if (fKind==7) return "TList";
190  if (fKind==8) return "TGo4HistogramStatus";
191 
192  const char *clname = GetHttpRootClassName(fKindAttr.Data());
193 
194  return clname ? clname : "TObject";
195 }
196 
198 {
199  if (!rcv) return 0;
200 
201  TClass *obj_cl = GetObjectClass();
202  if (!obj_cl) {
203  printf("TGo4HttpAccess fail to get class %s for object %s\n", GetObjectClassName(), path);
204  return 0;
205  }
206 
207  if (obj_cl->GetBaseClassOffset(TObject::Class()) != 0) {
208  printf("TGo4HttpAccess cannot used class %s not derived from TObject\n", GetObjectClassName());
209  return 0;
210  }
211 
212  fReceiver = rcv;
213  fRecvPath = path;
214 
215  TString url = fProxy->fNodeName;
216  if (fUrlPath.Length()>0) { url.Append("/"); url.Append(fUrlPath); }
217 
218  switch (fKind) {
219  case 0: url.Append("/h.xml?compact"); break;
220  case 1: url.Append("/root.bin.gz"); break;
221  case 2: url.Append("/get.xml"); break;
222  case 3: url.Append("/get.xml.gz?history=100&compact"); break;
223  case 4: url.Append("/exe.bin.gz?method=CreateStatus&_destroy_result_"); break;
224  case 5: url.Append("/exe.bin.gz?method=CreateSampleTree&sample=0&_destroy_result_"); break;
225  case 6: url.Append("/exe.bin.gz?method=CreateStatus&_destroy_result_"); break;
226  case 7: url.Append("/exe.bin.gz?method=Select&max=10000"); break;
227  case 8: url.Form("%s/Control/go4_sniffer/exe.bin.gz?method=CreateItemStatus&_destroy_result_&itemname=\"%s\"", fProxy->fNodeName.Data(), fUrlPath.Data()); break;
228  default: url.Append("/root.bin.gz"); break;
229  }
230 
231  if (fExtraArg.Length()>0) {
232  if (url.Index("?") != kNPOS) url.Append("&"); else url.Append("?");
233  url.Append(fExtraArg);
234  }
235 
236  fReply = fProxy->fComm.qnam.get(QNetworkRequest(QUrl(url.Data())));
237  QObject::connect(fReply, &QNetworkReply::finished, this, &TGo4HttpAccess::httpFinished);
238 
239 #if QT_VERSION < QT_VERSION_CHECK(5,15,0)
240  QObject::connect(fReply, (void (QNetworkReply::*)(QNetworkReply::NetworkError)) &QNetworkReply::error, this, &TGo4HttpAccess::httpError);
241 #else
242  QObject::connect(fReply, &QNetworkReply::errorOccurred, this, &TGo4HttpAccess::httpError);
243 #endif
244 
245  if (gDebug > 2)
246  printf("TGo4HttpAccess::AssignObjectTo Request URL %s\n", url.Data());
247 
248  return 2;
249 }
250 
251 void TGo4HttpAccess::httpError(QNetworkReply::NetworkError)
252 {
253  // may do special handling for http errors
254 }
255 
256 
258 {
259  QByteArray res = fReply->readAll();
260  fReply->deleteLater();
261  fReply = nullptr;
262 
263  if (gDebug > 2)
264  printf("TGo4HttpAccess::httpFinished Get reply size %ld\n", (long) res.size());
265 
266  // regular ratemeter update used to check connection status
267  if (fUrlPath == "Status/Ratemeter") {
268  Bool_t conn = res.size() > 0;
269 
270  // if proxy in shutdown state - cancel all action in case of communication error
271  if (!conn && fProxy->CheckShutdown()) return;
272 
273  if (!conn) DoObjectAssignement(fReceiver, fRecvPath.Data(), new TNamed("disconnected","title"), kTRUE); else
274  if (fProxy->fConnected != conn) fProxy->UpdateHierarchy(kFALSE);
275 
276  fProxy->fConnected = conn;
277  }
278 
279  // do nothing when nothing received
280  if (res.size() == 0) {
281  if (gDebug > 0)
282  printf("TGo4HttpAccess::httpFinished error with %s\n", fUrlPath.Data());
283  return;
284  }
285 
286  if (fKind == 0) {
287 
288  TXMLEngine *xml = fProxy->fXML;
289 
290  XMLDocPointer_t doc = xml->ParseString(res.data());
291 
292  if (!doc) return;
293 
294  XMLNodePointer_t top = xml->GetChild(xml->DocGetRootElement(doc));
295 
296  xml->FreeAllAttr(fNode);
297 
298  XMLAttrPointer_t attr = xml->GetFirstAttr(top);
299  while (attr) {
300  xml->NewAttr(fNode, nullptr, xml->GetAttrName(attr), xml->GetAttrValue(attr));
301  attr = xml->GetNextAttr(attr);
302  }
303 
304  XMLNodePointer_t chld;
305  while ((chld = xml->GetChild(top)) != nullptr) {
306  xml->UnlinkNode(chld);
307  xml->AddChild(fNode, chld);
308  }
309 
310  xml->FreeDoc(doc);
311 
312  if (fProxy->fxParentSlot)
314  }
315 
316  TObject *obj = nullptr;
317 
318  if (fKind == 2) {
319  TXMLEngine* xml = fProxy->fXML;
320 
321  XMLDocPointer_t doc = xml->ParseString(res.data());
322  if (!doc) return;
323 
324  XMLNodePointer_t top = xml->DocGetRootElement(doc);
325 
326  const char *_kind = xml->GetAttr(top, "_kind");
327  const char *_name = xml->GetAttr(top, "_name");
328  const char *_title = xml->GetAttr(top, "_title");
329  const char *xtitle = xml->GetAttr(top, "xtitle");
330  const char *ytitle = xml->GetAttr(top, "ytitle");
331  const char *xlabels = xml->GetAttr(top, "xlabels");
332  const char *ylabels = xml->GetAttr(top, "ylabels");
333 
334  if (strcmp(_kind,"ROOT.TH1D") == 0) {
335  Int_t nbins = xml->GetIntAttr(top, "nbins");
336  Int_t left = TString(xml->GetAttr(top, "left")).Atof();
337  Int_t right = TString(xml->GetAttr(top, "right")).Atof();
338  TH1D* h1 = new TH1D(_name, _title, nbins, left, right);
339  h1->SetDirectory(nullptr);
340  const char *bins = xml->GetAttr(top, "bins") + 1;
341  for (int n =-3; n<nbins+2; n++) {
342  const char *separ = strpbrk(bins,",]");
343  if (!separ) { printf("Error parsing histogram bins\n"); break; }
344  if (n >= 0) {
345  Double_t v = TString(bins, separ-bins).Atof();
346  h1->SetBinContent(n, v);
347  }
348  bins = separ+1;
349  }
350  h1->ResetStats();
351  obj = h1;
352  } else {
353  Int_t nbins1 = xml->GetIntAttr(top, "nbins1");
354  Int_t left1 = TString(xml->GetAttr(top, "left1")).Atof();
355  Int_t right1 = TString(xml->GetAttr(top, "right1")).Atof();
356  Int_t nbins2 = xml->GetIntAttr(top, "nbins2");
357  Int_t left2 = TString(xml->GetAttr(top, "left2")).Atof();
358  Int_t right2 = TString(xml->GetAttr(top, "right2")).Atof();
359  TH2D* h2 = new TH2D(_name, _title, nbins1, left1, right1, nbins2, left2, right2);
360  h2->SetDirectory(nullptr);
361  const char *bins = xml->GetAttr(top, "bins") + 1;
362  for (int n =-6; n<(nbins1+2)*(nbins2+2); n++) {
363  const char *separ = strpbrk(bins,",]");
364  if (!separ) { printf("Error parsing histogram bins\n"); break; }
365  if (n >= 0) {
366  Double_t v = TString(bins, separ-bins).Atof();
367  h2->SetBinContent(n % (nbins1 + 2), n / (nbins1 + 2), v);
368  }
369  bins = separ+1;
370  }
371  h2->ResetStats();
372  obj = h2;
373  }
374 
375  if (obj) {
376  if (xtitle)
377  ((TH1 *)obj)->GetXaxis()->SetTitle(xtitle);
378  if (ytitle)
379  ((TH1 *)obj)->GetYaxis()->SetTitle(ytitle);
380  if (xlabels) {
381  TObjArray *arr = TString(xlabels).Tokenize(",");
382  for (int n = 0; n <= (arr ? arr->GetLast() : -1); n++)
383  ((TH1 *)obj)->GetXaxis()->SetBinLabel(1 + n, arr->At(n)->GetName());
384  delete arr;
385  }
386  if (ylabels) {
387  TObjArray *arr = TString(ylabels).Tokenize(",");
388  for (int n = 0; n <= (arr ? arr->GetLast() : -1); n++)
389  ((TH1 *)obj)->GetYaxis()->SetBinLabel(1 + n, arr->At(n)->GetName());
390  delete arr;
391  }
392  }
393 
394  xml->FreeDoc(doc);
395 
396  } else
397 
398  if (fKind == 3) {
399  TXMLEngine* xml = fProxy->fXML;
400 
401  XMLDocPointer_t doc = xml->ParseString(res.data());
402  if (!doc) return;
403 
404  XMLNodePointer_t top = xml->DocGetRootElement(doc);
405 
406  XMLNodePointer_t chld = top;
407  Int_t cnt = 0;
408  while (chld) {
409  if (xml->GetAttr(chld, "value") && xml->GetAttr(chld, "time")) cnt++;
410  chld = (chld==top) ? xml->GetChild(top) : xml->GetNext(chld);
411  }
412 
413  TGraph *gr = new TGraph(cnt);
414  gr->SetName(xml->GetAttr(top, "_name"));
415  gr->SetTitle(TString::Format("%s ratemeter", xml->GetAttr(top, "_name")).Data());
416 
417  chld = top;
418  Int_t i = cnt-1;
419  while (chld) {
420  const char *time = xml->GetAttr(chld, "time");
421  const char *value = xml->GetAttr(chld, "value");
422  if (time && value) {
423  QDateTime tm = QDateTime::fromString(time, Qt::ISODate);
424  gr->SetPoint(i, tm.toMSecsSinceEpoch()/1000, TString(value).Atof());
425  i = (i+1) % cnt;
426  }
427  chld = (chld==top) ? xml->GetChild(top) : xml->GetNext(chld);
428  }
429 
430  xml->FreeDoc(doc);
431  obj = gr;
432 
433  gr->GetXaxis()->SetTimeDisplay(1);
434  gr->GetXaxis()->SetTimeFormat("%H:%M:%S%F1970-01-01 00:00:00");
435  } else {
436 
437  TClass *obj_cl = GetObjectClass();
438 
439  if (gDebug > 2) printf("TGo4HttpAccess::httpFinished Reconstruct object class %s\n", obj_cl ? obj_cl->GetName() : "---");
440 
441  if (!obj_cl || (obj_cl->GetBaseClassOffset(TObject::Class()) != 0)) return;
442 
443  obj = (TObject *) obj_cl->New();
444  if (!obj) {
445  printf("TGo4HttpAccess fail to create object of class %s\n", GetObjectClassName());
446  return;
447  }
448 
449  TBufferFile buf(TBuffer::kRead, res.size(), res.data(), kFALSE);
450  buf.MapObject(obj, obj_cl);
451 
452  obj->Streamer(buf);
453 
454  // workaround - when ratemeter received, check running state
455  if (obj->IsA() == TGo4Ratemeter::Class())
456  fProxy->fbAnalysisRunning = ((TGo4Ratemeter*) obj)->IsRunning();
457 
458  if (fKind == 6)
459  fProxy->SetAnalysisReady(kTRUE);
460 
461  }
462 
463  DoObjectAssignement(fReceiver, fRecvPath.Data(), obj, kTRUE);
464 }
465 
466 // =========================================================================
467 
469  protected:
470  TXMLEngine *fXML;
471  XMLNodePointer_t fParent;
472  XMLNodePointer_t fChild;
473 
474  public:
475  TGo4HttpLevelIter(TXMLEngine* xml, XMLNodePointer_t item) :
476  TGo4LevelIter(),
477  fXML(xml),
478  fParent(item),
479  fChild()
480  {
481  }
482 
483  virtual ~TGo4HttpLevelIter() {}
484 
485  Bool_t next() override
486  {
487  if (!fParent) return kFALSE;
488 
489  while (true) {
490 
491  if (!fChild) {
492  fChild = fXML->GetChild(fParent);
493  } else {
494  fChild = fXML->GetNext(fChild);
495  }
496 
497  if (!fChild) return kFALSE;
498 
499  if (fXML->HasAttr(fChild,"_hidden")) continue;
500 
501  break;
502  }
503 
504  return fChild != nullptr;
505  }
506 
507  Bool_t isfolder() override
508  {
509  return fXML->GetChild(fChild) != nullptr;
510  }
511 
512  Int_t getflag(const char *flagname) override
513  {
514  if (strcmp(flagname,"IsRemote") == 0) return 1;
515 
516  if (strcmp(flagname,"IsDeleteProtect") == 0)
517  return fXML->HasAttr(fChild, "_can_delete") ? 0 : 1;
518 
519  if (strcmp(flagname,"IsResetProtect") == 0)
520  return fXML->HasAttr(fChild, "_no_reset") ? 1 : 0;
521 
522  if (strcmp(flagname,"_numargs") == 0) {
523  const char *_numargs = fXML->GetAttr(fChild,"_numargs");
524  return !_numargs ? -1 : TString(_numargs).Atoi();
525  }
526 
527  return -1;
528  }
529 
531  {
532  if (!isfolder()) return nullptr;
533  return new TGo4HttpLevelIter(fXML,fChild);
534  }
535 
536  TGo4Slot *getslot() override { return nullptr; }
537 
538  const char *name() override
539  {
540  const char *real = fXML->GetAttr(fChild,"_realname");
541  return real? real : fXML->GetAttr(fChild,"_name");
542  }
543 
544  const char *info() override { return fXML->GetAttr(fChild,"_title"); }
545  Int_t sizeinfo() override { return 0; }
546 
547  Int_t GetKind() override
548  {
549  if (isfolder()) return TGo4Access::kndFolder;
550 
551  if (fXML->HasAttr(fChild,"_go4event")) return TGo4Access::kndEventElement;
552 
553  if (fXML->HasAttr(fChild,"_more")) return TGo4Access::kndMoreFolder;
554 
555  const char *_kind = fXML->GetAttr(fChild,"_kind");
556  if (_kind && strcmp(_kind,"Command") == 0) return TGo4Access::kndRootCommand;
557 
558  const char *drawfunc = fXML->GetAttr(fChild,"_drawfunc");
559  if (drawfunc && !strcmp(drawfunc, "GO4.drawParameter")) return TGo4Access::kndGo4Param;
560 
561  const char *classname = GetClassName();
562 
563  if (!classname) return TGo4Access::kndNone;
564 
565  if (strcmp(classname,"TLeafElement") == 0) return TGo4Access::kndTreeLeaf;
566 
567  return TGo4Access::kndObject;
568  }
569 
570  const char *GetClassName() override
571  {
572  const char *_kind = fXML->GetAttr(fChild,"_kind");
573  const char *res = GetHttpRootClassName(_kind);
574  if (res) return res;
575  if (_kind && !strcmp(_kind,"rate") && fXML->HasAttr(fChild,"_history")) return "TGraph";
576  return isfolder() ? "TFolder" : nullptr;
577  }
578 };
579 
580 // =====================================================================
581 
583  TGo4ServerProxy(),
584  fXML(nullptr),
585  fxHierarchy(nullptr),
586  fComm(this),
587  fRateCnt(0),
588  fStatusCnt(0),
589  fDebugCnt(0),
590  fbAnalysisRunning(kFALSE),
591  fUserName(),
592  fPassword(),
593  fConnected(kTRUE),
594  fRegularReq(nullptr)
595 {
596  fXML = new TXMLEngine;
597  fUserName = "anonymous";
598  // SetAccount("observer","go4view");
599  // SetAccount("controller","go4ctrl");
600 }
601 
603 {
604  fXML->FreeDoc(fxHierarchy);
605  fxHierarchy = nullptr;
606 
607  delete fXML; fXML = nullptr;
608 }
609 
610 void TGo4HttpProxy::SetAccount(const char *username, const char *passwd)
611 {
612  fUserName = username ? username : "";
613  fPassword = passwd ? passwd : "";
614 }
615 
617 {
619 
620  if (!IsGo4Analysis()) return;
621 
622  TGo4Slot *subslot = new TGo4Slot(fxParentSlot, "Settings", "Analysis configuration");
623  subslot->SetProxy(new TGo4ObjectProxy());
624 
625  subslot = new TGo4Slot(fxParentSlot, "Ratemeter", "Analysis ratemeter");
626  subslot->SetProxy(new TGo4ObjectProxy());
627 
628  subslot = new TGo4Slot(fxParentSlot, "Loginfo", "Latest status messages");
629  subslot->SetProxy(new TGo4ObjectProxy());
630 
631  subslot = new TGo4Slot(fxParentSlot, "Debugoutput", "Debug output of go4 analysis");
632  subslot->SetProxy(new TGo4ObjectProxy());
633 
634  QTimer::singleShot(2000, &fComm, &QHttpProxy::updateRatemeter);
635 }
636 
637 
638 XMLNodePointer_t TGo4HttpProxy::FindItem(const char *name, XMLNodePointer_t curr) const
639 {
640  if (!curr) curr = fXML->GetChild(fXML->DocGetRootElement(fxHierarchy));
641 
642  if (!curr || !name || !*name) return curr;
643 
644  const char *slash = strchr(name,'/');
645  bool doagain = false;
646 
647  do {
648  size_t len = !slash ? strlen(name) : (slash - name);
649 
650  XMLNodePointer_t chld = fXML->GetChild(curr);
651  while (chld) {
652  const char *_name = fXML->GetAttr(chld,"_realname");
653  if (!_name) _name = fXML->GetAttr(chld,"_name");
654 
655  if (_name && (strlen(_name) == len) && (strncmp(_name, name, len) == 0))
656  return FindItem(slash ? slash+1 : nullptr, chld);
657 
658  chld = fXML->GetNext(chld);
659  }
660 
661  // we try to process situation when item name contains slashes
662  doagain = slash != nullptr;
663  if (slash) slash = strchr(slash+1,'/');
664 
665  } while (doagain);
666 
667  return nullptr;
668 }
669 
670 TString TGo4HttpProxy::MakeUrlPath(XMLNodePointer_t item)
671 {
672  if (!item) return TString("");
673 
674  XMLNodePointer_t root = fXML->GetChild(fXML->DocGetRootElement(fxHierarchy));
675 
676  TString res;
677 
678  while (item != root) {
679  const char *_name = fXML->GetAttr(item,"_name");
680  if (!_name) return TString("");
681  if (res.Length()>0)
682  res = TString(_name) + "/" + res;
683  else
684  res = _name;
685 
686  item = fXML->GetParent(item);
687  if (!item) return TString("");
688  }
689 
690  return res;
691 }
692 
693 
694 void TGo4HttpProxy::GetHReply(QByteArray& res)
695 {
696  if (res.size() == 0) return;
697  XMLDocPointer_t doc = fXML->ParseString(res.data());
698 
699  if (doc) {
700  fXML->FreeDoc(fxHierarchy);
701  fxHierarchy = doc;
702  }
703 
704  if (fxParentSlot)
706 }
707 
709 {
710  TGo4ServerProxy::GetContainedObjectInfo(); // evaluate roles
711  fInfoStr +="(";
712  fInfoStr +=GetUserName();
713  fInfoStr +="@";
715  fInfoStr +=")";
716  const char *analname = fXML->GetAttr(FindItem(""), "_analysis_name");
717  if (analname) {
718  fInfoStr += " name:";
719  fInfoStr += analname;
720  }
721 
722  return fInfoStr.Data();
723 }
724 
725 Bool_t TGo4HttpProxy::Connect(const char *nodename)
726 {
727  fNodeName = nodename;
728 
729  if ((fNodeName.Index("http://") != 0) && (fNodeName.Index("https://") != 0))
730  fNodeName = TString("http://") + fNodeName;
731 
732  return UpdateHierarchy(kTRUE);
733 }
734 
736 {
737  return fxHierarchy && !fComm.fHReply;
738 }
739 
741 {
742  if (fComm.fHReply) return kTRUE;
743 
744  TString req = fNodeName + "/h.xml?compact";
745 
746  fComm.StartRequest(req.Data());
747 
748  if (!sync) return kTRUE;
749 
750  QElapsedTimer t;
751  t.start();
752 
753  // wait several seconds
754  while (t.elapsed() < 5000) {
755  if (!fComm.fHReply) break;
756  QApplication::processEvents();
757  }
758 
759  return fxHierarchy != nullptr;
760 }
761 
763 {
764  return fxHierarchy != nullptr;
765 }
766 
767 std::unique_ptr<TGo4Access> TGo4HttpProxy::ProvideAccess(const char *name)
768 {
769  XMLNodePointer_t item = FindItem(name);
770 
771  if (!item) return nullptr;
772 
773  const char *_kind = fXML->GetAttr(item,"_kind");
774 
775  Int_t kind = 1;
776 
777  if (!strcmp(_kind, "rate") && fXML->HasAttr(item, "_history"))
778  kind = 3;
779  else if (fXML->HasAttr(item, "_dabc_hist"))
780  kind = 2;
781  else if (fXML->HasAttr(item, "_more"))
782  kind = 0;
783 
784  return std::make_unique<TGo4HttpAccess>(this, item, kind);
785 }
786 
788 {
789  if (!fxHierarchy) return nullptr;
790  XMLNodePointer_t top = fXML->GetChild(fXML->DocGetRootElement(fxHierarchy));
791 
792  return !top ? nullptr : new TGo4HttpLevelIter(fXML, top);
793 }
794 
795 void TGo4HttpProxy::WriteData(TGo4Slot *slot, TDirectory *dir, Bool_t onlyobjs)
796 {
797 }
798 
799 void TGo4HttpProxy::ReadData(TGo4Slot *slot, TDirectory *dir)
800 {
801 }
802 
803 void TGo4HttpProxy::Update(TGo4Slot *slot, Bool_t strong)
804 {
805  if (strong)
806  UpdateHierarchy(kFALSE);
807 }
808 
810 {
811  // return kTRUE when server has Restrict methods
812  // It is indication of new functionality like commands with arguments or support of POST requests
813 
814  return fXML->HasAttr(FindItem(""),"_has_restrict");
815 }
816 
818 {
819  // return kTRUE when server has ProduceMulti method
820  // One could use it to submit many requests at once
821 
822  return fXML->HasAttr(FindItem(""),"_has_produce_multi");
823 }
824 
825 
827 {
828  XMLNodePointer_t item = FindItem("");
829  if (!item) return kFALSE;
830 
831  const char *_kind = fXML->GetAttr(item,"_kind");
832  const char *_title = fXML->GetAttr(item,"_title");
833 
834  if (!_kind || !_title) return kFALSE;
835 
836  return !strcmp(_kind,"ROOT.Session") && !strcmp(_title,"GO4 analysis");
837 }
838 
839 Bool_t TGo4HttpProxy::CheckUserName(const char *expects, Bool_t dflt) const
840 {
841  XMLNodePointer_t item = FindItem("");
842  if (!item) return dflt;
843 
844  const char *username = fXML->GetAttr(item,"_username");
845  if (!username) return dflt;
846 
847  return strcmp(username, expects) == 0;
848 }
849 
850 
852 {
853  return UpdateHierarchy(kFALSE);
854 }
855 
857 {
858  QTimer::singleShot(delay_sec*1000, &fComm, &QHttpProxy::updateHierarchy);
859 
860  return kTRUE;
861 }
862 
864 {
865  if (!IsGo4Analysis() || IsViewer()) return kFALSE;
866 
867  return ServerHasRestrict();
868 }
869 
870 
872 {
873  if (SubmitRequest("Control/Analysis", 6, SettingsSlot()))
874  SetAnalysisSettingsReady(kTRUE); // workaround - mark as we finished with settings
875 }
876 
878 {
879  TGo4AnalysisStatus *status = nullptr;
880  if (SettingsSlot())
881  status = dynamic_cast<TGo4AnalysisStatus*>(SettingsSlot()->GetAssignedObject());
882 
883  if (status)
884  PostObject("Control/Analysis/exe.bin?method=ApplyStatus&status", status, 2);
885 }
886 
888 {
889  SetAnalysisSettingsReady(kFALSE);
890 
891  SubmitCommand("Control/CmdClose");
892 }
893 
895 {
896  // when command submitted without arguments, histograms and conditions folder will be cleared
897  SubmitCommand("Control/CmdClear");
898 }
899 
900 void TGo4HttpProxy::ClearAnalysisObject(const char *fullpath)
901 {
902  TString foldername, objectname;
903  TGo4Slot::ProduceFolderAndName(fullpath, foldername, objectname);
904 
905  objectname = TString("\"") + objectname + TString("\"");
906 
907  SubmitCommand("Control/CmdClearObject", -1, objectname.Data());
908 }
909 
910 void TGo4HttpProxy::RemoveObjectFromAnalysis(const char *fullpath)
911 {
912  TString foldername, objectname;
913  TGo4Slot::ProduceFolderAndName(fullpath, foldername, objectname);
914 
915  objectname = TString("\"") + objectname + TString("\"");
916 
917  SubmitCommand("Control/CmdDeleteObject", -1, objectname.Data());
918 }
919 
920 void TGo4HttpProxy::ExecuteLine(const char *line)
921 {
922  // use method of TGo4AnalysisWebStatus - this works with all THttpServer versions
923  if (FindItem("Control/Analysis"))
924  SubmitURL(TString::Format("Control/Analysis/exe.json?method=ExecuteLine&cmd=\"%s\"", line));
925 }
926 
928 {
929  SubmitCommand("Control/CmdStart");
930  fbAnalysisRunning = kTRUE;
931 }
932 
934 {
935  SubmitCommand("Control/CmdStop");
936  fbAnalysisRunning = kFALSE;
937 }
938 
939 Bool_t TGo4HttpProxy::RequestObjectStatus(const char *objectname, TGo4Slot *tgtslot)
940 {
941  return SubmitRequest(objectname, 4, tgtslot) != nullptr;
942 }
943 
944 Bool_t TGo4HttpProxy::SubmitURL(const char *path, Int_t waitres)
945 {
946  TString url = fNodeName;
947  url.Append("/");
948  url.Append(path);
949 
950  if (gDebug > 1) printf("Submit URL %s\n", url.Data());
951 
952  QNetworkReply *netReply = fComm.qnam.get(QNetworkRequest(QUrl(url.Data())));
953 
954  QSslConfiguration cfg = netReply->sslConfiguration();
955  cfg.setProtocol(QSsl::AnyProtocol/*QSsl::TlsV1SslV3*/);
956  netReply->setSslConfiguration(cfg);
957 
958  if (waitres <= 0) {
959  QObject::connect(netReply, &QNetworkReply::finished, netReply, &QNetworkReply::deleteLater);
960  return kTRUE;
961  }
962 
963  QEventLoop loop;
964  QElapsedTimer myTimer;
965  myTimer.start();
966  while (!netReply->isFinished()) {
967  loop.processEvents(QEventLoop::AllEvents,100);
968  if (myTimer.elapsed() > waitres*1000) break;
969  }
970 
971  netReply->deleteLater();
972  return netReply->isFinished();
973 }
974 
975 TString TGo4HttpProxy::FindCommand(const char *name)
976 {
977  if (!name || !*name)
978  return "";
979  if (NumCommandArgs(name) >= 0)
980  return name;
981 
982  TGo4Iter iter(fxParentSlot);
983 
984  while (iter.next()) {
985  if (iter.getflag("_numargs") < 0) continue;
986  if (strcmp(iter.getname(),name) == 0) return iter.getfullname();
987  }
988 
989  return "";
990 }
991 
992 Int_t TGo4HttpProxy::NumCommandArgs(const char *name)
993 {
994  XMLNodePointer_t item = FindItem(name);
995  if (!item) return -1;
996 
997  const char *_numargs = fXML->GetAttr(item,"_numargs");
998  if (!_numargs) return 0;
999 
1000  return TString(_numargs).Atoi();
1001 }
1002 
1003 Bool_t TGo4HttpProxy::SubmitCommand(const char *name, Int_t waitres, const char *arg1, const char *arg2, const char *arg3)
1004 {
1005  TString url(name);
1006  url.Append("/cmd.json");
1007  if (arg1 && *arg1) {
1008  url.Append("?arg1=");
1009  url.Append(arg1);
1010  if (arg2 && *arg2) {
1011  url.Append("&arg2=");
1012  url.Append(arg2);
1013  if (arg3 && *arg3) {
1014  url.Append("&arg3=");
1015  url.Append(arg3);
1016  }
1017  }
1018  }
1019 
1020  return SubmitURL(url.Data(), waitres);
1021 }
1022 
1023 Bool_t TGo4HttpProxy::PostObject(const char *prefix, TObject *obj, Int_t waitres, Bool_t destroy_after)
1024 {
1025  if (!ServerHasRestrict()) return kFALSE;
1026 
1027  TBufferFile *sbuf = new TBufferFile(TBuffer::kWrite, 100000);
1028  sbuf->MapObject(obj);
1029  obj->Streamer(*sbuf);
1030 
1031  QByteArray postData;
1032  postData.append(sbuf->Buffer(), sbuf->Length());
1033 
1034  delete sbuf;
1035 
1036  TString url = fNodeName;
1037  url.Append("/");
1038  url.Append(prefix);
1039  url.Append("=_post_object_&");
1040  if (destroy_after) url.Append("_destroy_post_&");
1041  url.Append("_post_class_=");
1042  url.Append(obj->ClassName());
1043 
1044  // printf("URL %s datalen %d\n", url.Data(), postData.length());
1045 
1046  QNetworkRequest req(QUrl(url.Data()));
1047 
1048  QNetworkReply *netReply = fComm.qnam.post(req, postData);
1049 
1050  QSslConfiguration cfg = netReply->sslConfiguration();
1051  cfg.setProtocol(QSsl::AnyProtocol/*QSsl::TlsV1SslV3*/);
1052  netReply->setSslConfiguration(cfg);
1053 
1054  if (waitres <= 0) {
1055  QObject::connect(netReply, &QNetworkReply::finished, netReply, &QNetworkReply::deleteLater);
1056  return kTRUE;
1057  }
1058 
1059  QEventLoop loop;
1060  QElapsedTimer myTimer;
1061  myTimer.start();
1062  while (!netReply->isFinished()) {
1063  loop.processEvents(QEventLoop::AllEvents,100);
1064  if (myTimer.elapsed() > waitres*1000) break;
1065  }
1066 
1067  netReply->deleteLater();
1068  return netReply->isFinished();
1069 }
1070 
1071 
1072 Bool_t TGo4HttpProxy::UpdateAnalysisObject(const char *objectname, TObject *obj)
1073 {
1074  TString url;
1075 
1076  Bool_t destr = kTRUE;
1077 
1078  if (*objectname == 0) {
1079  url.Append("Control/go4_sniffer/exe.bin?method=AddAnalysisObject&obj");
1080  destr = kFALSE; // object will be owned by analysis
1081  } else {
1082  url.Append(objectname);
1083  url.Append("/exe.bin?method=");
1084 
1085  if (obj->InheritsFrom(TGo4Condition::Class())) {
1086  url.Append("UpdateFrom&counts=kFALSE&cond");
1087  } else {
1088  url.Append("SetStatus&status");
1089  }
1090  }
1091 
1092  return PostObject(url.Data(), obj, 2, destr);
1093 }
1094 
1096 {
1097  TGo4Slot *subslot = DebugOutputSlot();
1098  if (subslot) subslot->AssignObject(nullptr, kFALSE);
1099 }
1100 
1102 {
1103  if (finished) {
1104  if (!fRegularReq) return;
1105 
1106  QByteArray res = fRegularReq->readAll();
1107  fRegularReq->deleteLater();
1108  fRegularReq = nullptr;
1109 
1110  if (res.size() <= 0) {
1111  fConnected = false;
1112 
1113  // check if proxy is in shutdown phase
1114  if (CheckShutdown()) return;
1115 
1116  RatemeterSlot()->AssignObject(new TNamed("disconnected","title"),kTRUE);
1117 
1118  return;
1119  }
1120 
1121  if (!fConnected) {
1122  UpdateHierarchy(kFALSE);
1123  fConnected = true;
1124  }
1125 
1126  if (gDebug > 2)
1127  printf("TGo4HttpProxy:: get reply on multi.bin request with %ld bytes\n", (long) res.size());
1128 
1129  int pos = 0;
1130 
1131  for (int n = 0; n < 3; n++) {
1132  unsigned char *ptr = (unsigned char *)res.data() + pos;
1133  unsigned len = ((unsigned) ptr[0]) |
1134  (((unsigned) ptr[1]) << 8) |
1135  (((unsigned) ptr[2]) << 16) |
1136  (((unsigned) ptr[3]) << 24);
1137 
1138  ptr += 4;
1139  pos += 4 + len;
1140  if (len > (unsigned) res.size()) {
1141  printf("Error decoding multi.bin buffer\n");
1142  return;
1143  }
1144 
1145  if (gDebug>2) printf("Decoding portion of %d bytes\n", len);
1146 
1147  TClass *obj_cl = n == 0 ? TGo4Ratemeter::Class() : TList::Class();
1148  TObject *obj = (TObject*) obj_cl->New();
1149 
1150  TBufferFile buf(TBuffer::kRead, len, ptr, kFALSE);
1151  buf.MapObject(obj, obj_cl);
1152 
1153  obj->Streamer(buf);
1154 
1155  if (n > 0) {
1156  TGo4Slot *subslot = n==1 ? LoginfoSlot() : DebugOutputSlot();
1157  TList *curr = subslot ? dynamic_cast<TList *> (subslot->GetAssignedObject()) : nullptr;
1158  TList *next = dynamic_cast<TList *> (obj);
1159  if (curr && curr->First() && next && next->First()) {
1160  if (strcmp(curr->First()->GetName(), next->First()->GetName()) == 0) {
1161  // this is protection against sending same info many times
1162  // happend with sever snapshot
1163  delete obj;
1164  obj = nullptr;
1165  }
1166  }
1167  }
1168 
1169  switch(n) {
1170  case 0:
1171  fbAnalysisRunning = ((TGo4Ratemeter*) obj)->IsRunning();
1172  RatemeterSlot()->AssignObject(obj,kTRUE);
1173  break;
1174  case 1:
1175  if (obj) LoginfoSlot()->AssignObject(obj,kTRUE);
1176  break;
1177  case 2:
1178  if (obj) DebugOutputSlot()->AssignObject(obj,kTRUE);
1179  break;
1180  }
1181  }
1182 
1183  if (pos != res.size())
1184  printf("Decoding fails %d != %ld bytes\n", pos, (long) res.size());
1185 
1186  return;
1187  }
1188 
1189 
1190  if (fRegularReq) return;
1191 
1192  TString req;
1193 
1194  req.Append("Ratemeter/root.bin\n");
1195 
1196  req.Append("Msg/exe.bin?method=Select&max=10000");
1197  TGo4Slot *subslot = LoginfoSlot();
1198  TList *curr = subslot ? dynamic_cast<TList *> (subslot->GetAssignedObject()) : nullptr;
1199  if (curr && curr->First()) {
1200  req.Append("&id=");
1201  req.Append(curr->First()->GetName());
1202 
1203  }
1204  req.Append("\n");
1205 
1206  req.Append("Log/exe.bin?method=Select&max=10000");
1207  subslot = DebugOutputSlot();
1208  curr = subslot ? dynamic_cast<TList *> (subslot->GetAssignedObject()) : nullptr;
1209  if (curr && curr->First()) {
1210  req.Append("&id=");
1211  req.Append(curr->First()->GetName());
1212 
1213  }
1214  req.Append("\n");
1215 
1216  QByteArray postData;
1217  postData.append(req.Data(), req.Length());
1218  if (gDebug>2) printf("Sending multi.bin request\n%s", req.Data());
1219 
1220  TString url = fNodeName;
1221  url.Append("/Status/multi.bin.gz?number=3");
1222 
1223  fRegularReq = fComm.qnam.post(QNetworkRequest(QUrl(url.Data())), postData);
1224 
1225  QSslConfiguration cfg = fRegularReq->sslConfiguration();
1226  cfg.setProtocol(QSsl::AnyProtocol/*QSsl::TlsV1SslV3*/);
1227  fRegularReq->setSslConfiguration(cfg);
1228 
1229  QObject::connect(fRegularReq, &QNetworkReply::finished, &fComm, &QHttpProxy::regularRequestFinished);
1230 }
1231 
1232 Bool_t TGo4HttpProxy::CheckShutdown(Bool_t force)
1233 {
1234  if (force || (fShutdownCnt>0)) {
1236  fxParentSlot = nullptr;
1237  return kTRUE;
1238  }
1239  return kFALSE;
1240 }
1241 
1243 {
1244  if ((fShutdownCnt > 0) && (--fShutdownCnt == 0)) {
1245  CheckShutdown(kTRUE);
1246  return;
1247  }
1248 
1249  if (ServerHasMulti() || fRegularReq) {
1251  return;
1252  }
1253 
1254  TGo4Slot *subslot = RatemeterSlot();
1255  if (subslot) {
1256  // no new update since last call
1257  if (!subslot->GetAssignedObject() || (fRateCnt != subslot->GetAssignCnt())) {
1258  fRateCnt = subslot->GetAssignCnt();
1259  SubmitRequest("Status/Ratemeter", 1, subslot);
1260  }
1261  }
1262 
1263  subslot = LoginfoSlot();
1264  if (subslot && IsConnected()) {
1265  TList *curr = dynamic_cast<TList *> (subslot->GetAssignedObject());
1266  if (!curr || (fStatusCnt != subslot->GetAssignCnt())) {
1267  TString arg;
1268  if (curr && curr->First()) {
1269  arg = "id=";
1270  arg += curr->First()->GetName();
1271  }
1272  fStatusCnt = subslot->GetAssignCnt();
1273  SubmitRequest("Status/Msg", 7, subslot, arg);
1274  }
1275  }
1276 
1277  subslot = DebugOutputSlot();
1278  if (subslot && IsConnected()) {
1279  TList *curr = dynamic_cast<TList *> (subslot->GetAssignedObject());
1280  if (!curr || (fDebugCnt != subslot->GetAssignCnt())) {
1281  TString arg;
1282  if (curr && curr->First()) {
1283  arg = "id=";
1284  arg += curr->First()->GetName();
1285  }
1286  fDebugCnt = subslot->GetAssignCnt();
1287  SubmitRequest("Status/Log", 7, subslot, arg);
1288  }
1289  }
1290 }
1291 
1292 void TGo4HttpProxy::RemoteTreeDraw(const char *treename,
1293  const char *varexp,
1294  const char *cutcond,
1295  const char *hname)
1296 {
1297  TString tfoldername, tobjectname;
1298  TGo4Slot::ProduceFolderAndName(treename, tfoldername, tobjectname);
1299 
1300  TString hfoldername, hobjectname;
1301  TGo4Slot::ProduceFolderAndName(hname, hfoldername, hobjectname);
1302 
1303  TString path;
1304  path.Form("Control/go4_sniffer/exe.json?method=RemoteTreeDraw&histoname=\"%s\"&treename=\"%s\"&varexpr=\"%s\"&cutexpr=\"%s\"",
1305  hobjectname.Data(), tobjectname.Data(), varexp, cutcond);
1306 
1307  SubmitURL(path, 2);
1308 }
1309 
1310 TGo4HttpAccess* TGo4HttpProxy::SubmitRequest(const char *itemname, Int_t kind, TGo4Slot *tgtslot, const char *extra_arg)
1311 {
1312  if (!itemname || !tgtslot) return nullptr;
1313 
1314  XMLNodePointer_t item = FindItem(itemname);
1315  if (!item) return nullptr;
1316 
1317  if (kind == 4) {
1318  // when status for histogram is requested, redirect request to the sniffer
1319  const char *_objkind = fXML->GetAttr(item, "_kind");
1320  if (_objkind && ((strstr(_objkind, "ROOT.TH1") == _objkind) || (strstr(_objkind, "ROOT.TH2") == _objkind) ||
1321  (strstr(_objkind, "ROOT.TH3") == _objkind)))
1322  kind = 8;
1323  }
1324 
1325  TGo4HttpAccess* access = new TGo4HttpAccess(this, item, kind, extra_arg);
1326  access->AssignObjectToSlot(tgtslot); // request event itself
1327 
1328  return access;
1329 }
1330 
1331 void TGo4HttpProxy::RequestEventStatus(const char *evname, Bool_t astree, TGo4Slot *tgtslot)
1332 {
1333  if (!tgtslot) {
1334  // this is remote printing of event
1335 
1336  TString url = evname;
1337  url.Append("/exe.bin?method=");
1338  url.Append(astree ? "ShowSampleTree" : "PrintEvent");
1339 
1340  SubmitURL(url);
1341  return;
1342  }
1343 
1344  SubmitRequest(evname, astree ? 5 : 1, tgtslot);
1345 }
1346 
1347 void TGo4HttpProxy::RemotePrintEvent(const char *evname,
1348  Int_t evnumber,
1349  Int_t subid,
1350  Bool_t ishex,
1351  Bool_t islong)
1352 {
1353  TString url;
1354  url.Form("Events/%s/exe.bin?method=SetPrintEvent&num=%d&sid=%d&longw=%d&hexw=%d&dataw=%d",
1355  evname, evnumber, subid, islong ? 1 : 0, ishex ? 1 : 0, ishex ? 0 : 1);
1356  SubmitURL(url);
1357 }
1358 
1359 void TGo4HttpProxy::ChageObjectProtection(const char *fullpath, const char *flags)
1360 {
1361  unsigned reset_bits = 0, set_bits = 0;
1362 
1363  TString opt = flags;
1364  if(opt.Contains("+D")) reset_bits |= TGo4Status::kGo4CanDelete;
1365  if(opt.Contains("-D")) set_bits |= TGo4Status::kGo4CanDelete;
1366  if(opt.Contains("+C")) set_bits |= TGo4Status::kGo4NoReset;
1367  if(opt.Contains("-C")) reset_bits |= TGo4Status::kGo4NoReset;
1368 
1369  TString url(fullpath);
1370  url.Append("/exe.bin?method=");
1371 
1372  if (reset_bits != 0) SubmitURL(url + TString::Format("ResetBit&f=%u",reset_bits));
1373  if (set_bits != 0) SubmitURL(url + TString::Format("SetBit&f=%u&prototype=UInt_t",set_bits));
1374 }
1375 
1376 void TGo4HttpProxy::PrintDynListEntry(const char *fullpath)
1377 {
1378  SubmitURL(TString(fullpath)+"/exe.bin?method=Print");
1379 }
1380 
1381 void TGo4HttpProxy::LoadConfigFile(const char *fname)
1382 {
1383  SubmitURL(TString::Format("Control/Analysis/exe.bin?method=LoadStatus&fname=%s", fname));
1384 }
1385 
1386 void TGo4HttpProxy::SaveConfigFile(const char *fname)
1387 {
1388  SubmitURL(TString::Format("Control/Analysis/exe.bin?method=SaveStatus&fname=%s", fname));
1389 }
1390 
1391 void TGo4HttpProxy::WriteAutoSave(const char *fname,
1392  Int_t complevel,
1393  Bool_t overwrite)
1394 {
1395  SubmitURL(TString::Format("Control/Analysis/exe.bin?method=WriteAutoSave&fname=%s&overwrite=%s&complevel=%d", fname, overwrite ? "kTRUE" : "kFALSE", complevel));
1396 }
1397 
1398 void TGo4HttpProxy::DisconnectAnalysis(Int_t waittime, Bool_t servershutdown)
1399 {
1400  if (servershutdown && IsGo4Analysis() && IsAdministrator()) {
1401  SubmitCommand("Control/CmdExit");
1402  fShutdownCnt = waittime;
1403  } else {
1404  CheckShutdown(kTRUE);
1405  }
1406 }
TGo4HttpProxy * fProxy
used only to receive hierarchy
Definition: TGo4HttpProxy.h:38
TString fPassword
user name and password -
void ClearAllAnalysisObjects() override
const char * name() override
static TClass * GetClass(const char *classname, Bool_t load=kFALSE)
Definition: TGo4Proxy.cxx:73
Int_t fStatusCnt
counter for ratemeter updates
void RemotePrintEvent(const char *evname, Int_t evnumber, Int_t subid, Bool_t ishex, Bool_t islong) override
void ResetDebugOutputRequests() override
void ClearAnalysisObject(const char *fullpath) override
QNetworkReply * fReply
Definition: TGo4HttpProxy.h:82
Bool_t fbAnalysisRunning
counter for debug output updates
QNetworkAccessManager qnam
Definition: TGo4HttpProxy.h:36
void SetProxy(TGo4Proxy *cont)
Definition: TGo4Slot.cxx:296
TGo4Slot * LoginfoSlot()
Int_t AssignObjectTo(TGo4ObjectManager *rcv, const char *path) override
Bool_t DelayedRefreshNamesList(Int_t delay_sec) override
Int_t fDebugCnt
counter for status messages updates
Bool_t ServerHasRestrict() const
friend class TGo4HttpAccess
const char * GetHttpRootClassName(const char *kind)
Bool_t PostObject(const char *prefix, TObject *obj, Int_t waitres=-1, Bool_t destroy_after=kTRUE)
Bool_t ServerHasMulti()
Bool_t UpdateAnalysisObject(const char *objectname, TObject *obj) override
TXMLEngine * fXML
TString FindCommand(const char *name) override
void RemoteTreeDraw(const char *treename, const char *varexp, const char *cutcond, const char *hname) override
const char * GetContainedObjectInfo() override
TString fRecvPath
Definition: TGo4HttpProxy.h:81
TString fNameAttr
Definition: TGo4HttpProxy.h:77
void ProcessUpdateTimer()
void ChageObjectProtection(const char *fullpath, const char *flags) override
Bool_t IsGo4Analysis() const override
void DoObjectAssignement(TGo4ObjectManager *rcv, const char *path, TObject *obj, Bool_t owner)
Definition: TGo4Proxy.cxx:63
Bool_t SubmitURL(const char *path, Int_t waitres=-1)
const char * GetObjectClassName() const override
void WriteData(TGo4Slot *slot, TDirectory *dir, Bool_t onlyobjs) override
void RemoveObjectFromAnalysis(const char *fullpath) override
void DisconnectAnalysis(Int_t waittime=30, Bool_t servershutdown=kFALSE) override
void SubmitAnalysisSettings() override
TGo4HttpAccess(TGo4HttpProxy *proxy, XMLNodePointer_t node, Int_t kind=1, const char *extra_arg=nullptr)
Bool_t NamesListReceived() const override
void authenticationRequiredSlot(QNetworkReply *, QAuthenticator *)
TGo4HttpAccess * SubmitRequest(const char *itemname, Int_t kind, TGo4Slot *tgtslot, const char *extra_arg=nullptr)
virtual ~QHttpProxy()
const char * GetClassName() override
QHttpProxy(TGo4HttpProxy *p)
QNetworkReply * fRegularReq
true if connected
void updateRatemeter()
Int_t getflag(const char *flagname)
Definition: TGo4Iter.cxx:133
const char * GetObjectName() const override
Bool_t SubmitCommand(const char *name, Int_t waitres=-1, const char *arg1=nullptr, const char *arg2=nullptr, const char *arg3=nullptr) override
Bool_t Connect(const char *nodename)
void httpFinished()
virtual ~TGo4HttpLevelIter()
Int_t GetAssignCnt() const
Definition: TGo4Slot.h:104
virtual const char * GetServerName() const
std::unique_ptr< TGo4Access > ProvideAccess(const char *name) override
TGo4Slot * getslot() override
TGo4Slot * RatemeterSlot()
TObject * GetAssignedObject()
Definition: TGo4Slot.cxx:356
XMLNodePointer_t fParent
void SetAnalysisReady(Bool_t on=kTRUE)
void LoadConfigFile(const char *fname) override
void SaveConfigFile(const char *fname) override
const char * getfullname()
Definition: TGo4Iter.cxx:151
void CloseAnalysisSettings() override
TGo4LevelIter * MakeIter() override
TGo4HttpLevelIter(TXMLEngine *xml, XMLNodePointer_t item)
const char * info() override
TGo4Slot * DebugOutputSlot()
Bool_t IsConnected() const override
Bool_t next() override
void ProcessRegularMultiRequest(Bool_t finished=kFALSE)
void StartRequest(const char *url)
TGo4Slot * SettingsSlot()
TGo4LevelIter * subiterator() override
void GetHReply(QByteArray &res)
counter during shutdown
void SetAccount(const char *username, const char *passwd)
void SetAnalysisSettingsReady(Bool_t on=kTRUE)
void Initialize(TGo4Slot *slot) override
void StartAnalysis() override
Bool_t RefreshNamesList() override
Int_t GetKind() override
void RequestEventStatus(const char *evname, Bool_t astree, TGo4Slot *tgtslot) override
TGo4Slot * fxParentSlot
TGo4HttpProxy * fProxy
Definition: TGo4HttpProxy.h:65
TString fExtraArg
Definition: TGo4HttpProxy.h:79
Int_t getflag(const char *flagname) override
TGo4ObjectManager * fReceiver
Definition: TGo4HttpProxy.h:80
Int_t NumCommandArgs(const char *name) override
TClass * GetObjectClass() const override
QHttpProxy fComm
pointer on dabc::Hierarchy class
const char * getname()
Definition: TGo4Iter.cxx:115
void httpError(QNetworkReply::NetworkError)
Int_t sizeinfo() override
XMLDocPointer_t fxHierarchy
XMLNodePointer_t fChild
Bool_t RequestObjectStatus(const char *objectname, TGo4Slot *tgtslot) override
Bool_t HasSublevels() const override
void httpHReqError(QNetworkReply::NetworkError)
XMLNodePointer_t FindItem(const char *name, XMLNodePointer_t curr=nullptr) const
void regularRequestFinished()
void Update(TGo4Slot *slot, Bool_t strong) override
TString fKindAttr
Definition: TGo4HttpProxy.h:78
QNetworkReply * fHReply
central manager of network requests
Definition: TGo4HttpProxy.h:37
virtual ~TGo4HttpProxy()
void RequestAnalysisSettings() override
TString fUserName
static void ProduceFolderAndName(const char *fullname, TString &foldername, TString &objectname)
Definition: TGo4Slot.cxx:646
const char * GetContainedObjectInfo() override
void ExecuteLine(const char *line) override
Int_t AssignObjectToSlot(TGo4Slot *slot)
Definition: TGo4Proxy.cxx:54
TString fNodeName
0 - not launched, 1 - external shell, 2 - in qt shell
Bool_t IsAdministrator() const override
XMLNodePointer_t fNode
Definition: TGo4HttpProxy.h:66
Bool_t AssignObject(TObject *obj, Bool_t owner)
Definition: TGo4Slot.cxx:344
void updateHierarchy()
TString MakeUrlPath(XMLNodePointer_t item)
void ForwardEvent(TGo4Slot *source, Int_t id, void *param=nullptr)
Definition: TGo4Slot.cxx:565
Bool_t UpdateHierarchy(Bool_t sync=kTRUE)
void WriteAutoSave(const char *fname, Int_t complevel, Bool_t overwrite) override
void PrintDynListEntry(const char *fullpath) override
Bool_t CheckUserName(const char *expects, Bool_t dflt=kFALSE) const
void Delete(Option_t *opt="") override
Definition: TGo4Slot.cxx:171
Bool_t CanSubmitObjects() const override
Bool_t IsViewer() const override
Bool_t CheckShutdown(Bool_t force=kFALSE)
const char * GetUserName() const override
void StopAnalysis() override
Bool_t isfolder() override
void Initialize(TGo4Slot *slot) override
void ReadData(TGo4Slot *slot, TDirectory *dir) override
Int_t fShutdownCnt
multiple request for rate, log and messages
Bool_t next(Bool_t goesinto=kTRUE)
Definition: TGo4Iter.cxx:44
TString fUrlPath
Definition: TGo4HttpProxy.h:67