36 const char *item_prop_kind =
"_kind";
37 const char *item_prop_more =
"_more";
38 const char *item_prop_title =
"_title";
39 const char *item_prop_hidden =
"_hidden";
40 const char *item_prop_typename =
"_typename";
41 const char *item_prop_arraydim =
"_arraydim";
42 const char *item_prop_realname =
"_realname";
43 const char *item_prop_user =
"_username";
44 const char *item_prop_autoload =
"_autoload";
45 const char *item_prop_rootversion =
"_root_version";
59 TRootSnifferScanRec::TRootSnifferScanRec()
61 fItemsNames.SetOwner(kTRUE);
67 TRootSnifferScanRec::~TRootSnifferScanRec()
75 void TRootSnifferScanRec::SetField(
const char *name,
const char *value, Bool_t with_quotes)
78 fStore->SetField(fLevel, name, value, with_quotes);
85 void TRootSnifferScanRec::BeforeNextChild()
88 fStore->BeforeNextChild(fLevel, fNumChilds, fNumFields);
98 void TRootSnifferScanRec::MakeItemName(
const char *objname, TString &itemname)
100 std::string nnn = objname;
105 while ((pos = nnn.find_first_of(
"- []<>#:&?/\'\"\\")) != std::string::npos)
106 nnn.replace(pos, 1,
"_");
108 itemname = nnn.c_str();
111 while (fItemsNames.FindObject(itemname.Data())) {
112 itemname.Form(
"%s_%d", nnn.c_str(), cnt++);
115 fItemsNames.Add(
new TObjString(itemname.Data()));
121 void TRootSnifferScanRec::BuildFullName(TString &buf, TRootSnifferScanRec *prnt)
127 prnt->BuildFullName(buf);
130 buf.Append(fItemName);
141 void TRootSnifferScanRec::CreateNode(
const char *_node_name)
146 fNodeStarted = kTRUE;
149 fParent->BeforeNextChild();
152 fStore->CreateNode(fLevel, _node_name);
158 void TRootSnifferScanRec::CloseNode()
160 if (fStore && fNodeStarted) {
161 fStore->CloseNode(fLevel, fNumChilds);
162 fNodeStarted = kFALSE;
171 void TRootSnifferScanRec::SetRootClass(TClass *cl)
173 if (cl && CanSetFields())
174 SetField(item_prop_kind, TString::Format(
"ROOT.%s", cl->GetName()));
181 Bool_t TRootSnifferScanRec::Done()
const
186 if ((fMask & kSearch) && fStore->GetResPtr())
189 if ((fMask & kCheckChilds) && fStore->GetResPtr() && (fStore->GetResNumChilds() >= 0))
199 Bool_t TRootSnifferScanRec::IsReadyForResult()
const
205 if ((fMask & (kSearch | kCheckChilds)) == 0)
222 Bool_t TRootSnifferScanRec::SetResult(
void *obj, TClass *cl, TDataMember *member)
225 return SetFoundResult(obj, cl);
227 fStore->Error(
"SetResult",
228 "When member specified, pointer on object (not member) should be provided; use SetFoundResult");
236 Bool_t TRootSnifferScanRec::SetFoundResult(
void *obj, TClass *cl, TDataMember *member)
241 if (!IsReadyForResult())
244 fStore->SetResult(obj, cl, member, fNumChilds, fRestriction);
252 Int_t TRootSnifferScanRec::Depth()
const
255 const TRootSnifferScanRec *rec =
this;
256 while (rec->fParent) {
268 Bool_t TRootSnifferScanRec::CanExpandItem()
270 if (fMask & (kExpand | kSearch | kCheckChilds))
277 if (fParent && (fParent->fMask & kExpand))
287 Bool_t TRootSnifferScanRec::IsReadOnly(Bool_t dflt)
289 if (fRestriction == 0)
292 return fRestriction != 2;
302 TRootSnifferScanRec::GoInside(TRootSnifferScanRec &super, TObject *obj,
const char *obj_name, TRootSniffer *sniffer)
307 if (obj && !obj_name)
308 obj_name = obj->GetName();
311 if (!obj_name || (*obj_name == 0))
314 const char *full_name =
nullptr;
317 if (obj && obj->InheritsFrom(TDirectoryFile::Class())) {
318 const char *slash = strrchr(obj_name,
'/');
320 full_name = obj_name;
321 obj_name = slash + 1;
327 super.MakeItemName(obj_name, fItemName);
329 if (sniffer && sniffer->HasRestriction(fItemName.Data())) {
332 BuildFullName(fullname, &super);
333 fRestriction = sniffer->CheckRestriction(fullname.Data());
334 if (fRestriction < 0)
339 fLevel = super.fLevel;
340 fStore = super.fStore;
341 fSearchPath = super.fSearchPath;
342 fMask = super.fMask & kActions;
343 if (fRestriction == 0)
344 fRestriction = super.fRestriction;
345 Bool_t topelement(kFALSE);
349 if (super.ScanOnlyFields())
357 if (strncmp(fSearchPath, fItemName.Data(), fItemName.Length()) != 0)
360 const char *separ = fSearchPath + fItemName.Length();
362 Bool_t isslash = kFALSE;
363 while (*separ ==
'/') {
369 fSearchPath =
nullptr;
370 if (fMask & kExpand) {
372 fMask = (fMask & kOnlyFields) | kScan;
373 fHasMore = (fMask & kOnlyFields) == 0;
382 CreateNode(fItemName.Data());
384 if (obj_name && (fItemName != obj_name))
385 SetField(item_prop_realname, obj_name);
388 SetField(
"_fullname", full_name);
391 SetField(item_prop_rootversion, TString::Format(
"%d", gROOT->GetVersionCode()), kFALSE);
393 if (topelement && sniffer->GetAutoLoad())
394 SetField(item_prop_autoload, sniffer->GetAutoLoad());
413 ClassImp(TRootSniffer);
418 TRootSniffer::TRootSniffer(
const char *name,
const char *objpath)
419 : TNamed(name,
"sniffer of root objects"), fObjectsPath(objpath)
421 fRestrictions.SetOwner(kTRUE);
427 TRootSniffer::~TRootSniffer()
437 void TRootSniffer::SetCurrentCallArg(THttpCallArg *arg)
440 fCurrentRestrict = 0;
441 fCurrentAllowedMethods =
"";
461 void TRootSniffer::Restrict(
const char *path,
const char *options)
463 const char *rslash = strrchr(path,
'/');
466 if (!rslash || (*rslash == 0))
469 fRestrictions.Add(
new TNamed(rslash, TString::Format(
"%s%s%s", path,
"%%%", options).Data()));
477 void TRootSniffer::SetAutoLoad(
const char *scripts)
479 fAutoLoad = scripts ? scripts :
"";
485 const char *TRootSniffer::GetAutoLoad()
const
487 return fAutoLoad.Length() > 0 ? fAutoLoad.Data() :
nullptr;
494 Bool_t TRootSniffer::HasRestriction(
const char *item_name)
496 if (!item_name || (*item_name == 0) || !fCurrentArg)
499 return fRestrictions.FindObject(item_name) !=
nullptr;
507 Int_t TRootSniffer::WithCurrentUserName(
const char *option)
509 const char *username = fCurrentArg ? fCurrentArg->GetUserName() :
nullptr;
511 if (!username || !option || (*option == 0))
514 if (strcmp(option,
"all") == 0)
517 if (strcmp(username, option) == 0)
520 if (strstr(option, username) == 0)
523 TObjArray *arr = TString(option).Tokenize(
",");
525 Bool_t find = arr->FindObject(username) !=
nullptr;
529 return find ? 2 : -1;
541 Int_t TRootSniffer::CheckRestriction(
const char *full_item_name)
543 if (!full_item_name || (*full_item_name == 0))
546 const char *item_name = strrchr(full_item_name,
'/');
549 if (!item_name || (*item_name == 0))
550 item_name = full_item_name;
552 TString pattern1 = TString(
"*/") + item_name +
"%%%";
553 TString pattern2 = TString(full_item_name) +
"%%%";
555 const char *options =
nullptr;
556 TIter iter(&fRestrictions);
559 while ((obj = iter()) !=
nullptr) {
560 const char *title = obj->GetTitle();
562 if (strstr(title, pattern1.Data()) == title) {
563 options = title + pattern1.Length();
566 if (strstr(title, pattern2.Data()) == title) {
567 options = title + pattern2.Length();
576 url.SetOptions(options);
580 WithCurrentUserName(url.GetValueFromOptions(
"visible")) - WithCurrentUserName(url.GetValueFromOptions(
"hidden"));
583 WithCurrentUserName(url.GetValueFromOptions(
"allow")) - WithCurrentUserName(url.GetValueFromOptions(
"readonly"));
590 const char *methods = url.GetValueFromOptions(
"allow_method");
592 fCurrentAllowedMethods = methods;
604 void TRootSniffer::ScanObjectMembers(TRootSnifferScanRec &rec, TClass *cl,
char *ptr)
606 if (!cl || !ptr || rec.Done())
610 if (!(cl->Property() & kIsAbstract))
614 TObject *obj =
nullptr;
615 TIter iter(cl->GetListOfRealData());
616 while ((obj = iter()) !=
nullptr) {
617 TRealData *rdata =
dynamic_cast<TRealData *
>(obj);
618 if (!rdata || strchr(rdata->GetName(),
'.'))
621 TDataMember *member = rdata->GetDataMember();
623 if (!member || (member->Property() & (kIsStatic | kIsEnum | kIsUnion)))
625 char *member_ptr = ptr + rdata->GetThisOffset();
627 if (member->IsaPointer())
628 member_ptr = *((
char **)member_ptr);
630 TRootSnifferScanRec chld;
632 if (chld.GoInside(rec, member, 0,
this)) {
634 TClass *mcl = (member->IsBasic() || member->IsSTLContainer()) ?
nullptr : gROOT->GetClass(member->GetTypeName());
636 Int_t coll_offset = mcl ? mcl->GetBaseClassOffset(TCollection::Class()) : -1;
637 if (coll_offset >= 0) {
638 chld.SetField(item_prop_more,
"true", kFALSE);
639 chld.fHasMore = kTRUE;
642 if (chld.SetFoundResult(ptr, cl, member))
645 const char *title = member->GetTitle();
646 if (title && (strlen(title) != 0))
647 chld.SetField(item_prop_title, title);
649 if (member->GetTypeName())
650 chld.SetField(item_prop_typename, member->GetTypeName());
652 if (member->GetArrayDim() > 0) {
655 for (Int_t n = 0; n < member->GetArrayDim(); n++) {
658 dim.Append(TString::Format(
"%d", member->GetMaxIndex(n)));
661 chld.SetField(item_prop_arraydim, dim, kFALSE);
662 }
else if (member->GetArrayIndex() != 0) {
663 TRealData *idata = cl->GetRealData(member->GetArrayIndex());
664 TDataMember *imember = idata ? idata->GetDataMember() :
nullptr;
665 if (imember && (strcmp(imember->GetTrueTypeName(),
"int") == 0)) {
666 Int_t arraylen = *((
int *)(ptr + idata->GetThisOffset()));
667 chld.SetField(item_prop_arraydim, TString::Format(
"[%d]", arraylen), kFALSE);
671 chld.SetRootClass(mcl);
673 if (chld.CanExpandItem()) {
674 if (coll_offset >= 0) {
676 ScanCollection(chld, (TCollection *)(member_ptr + coll_offset));
680 if (chld.SetFoundResult(ptr, cl, member))
695 void TRootSniffer::ScanObjectProperties(TRootSnifferScanRec &rec, TObject *obj)
697 TClass *cl = obj ? obj->IsA() :
nullptr;
699 const char *pos = strstr(cl ? cl->GetTitle() :
"",
"*SNIFF*");
710 const char *pos0 = pos;
711 while ((*pos != 0) && (*pos !=
'='))
715 TString name(pos0, pos - pos0);
717 Bool_t quotes = (*pos ==
'\"');
722 while ((*pos != 0) && (*pos != (quotes ?
'\"' :
' ')))
724 TString value(pos0, pos - pos0);
725 rec.SetField(name, value);
736 void TRootSniffer::ScanKeyProperties(TRootSnifferScanRec &rec, TKey *key, TObject *&obj, TClass *&obj_class)
738 if (strcmp(key->GetClassName(),
"TDirectoryFile") == 0) {
739 if (rec.fLevel == 0) {
740 TDirectory *dir =
dynamic_cast<TDirectory *
>(key->ReadObj());
743 obj_class = dir->IsA();
746 rec.SetField(item_prop_more,
"true", kFALSE);
747 rec.fHasMore = kTRUE;
756 void TRootSniffer::ScanObjectChilds(TRootSnifferScanRec &rec, TObject *obj)
758 if (obj->InheritsFrom(TFolder::Class())) {
759 ScanCollection(rec, ((TFolder *)obj)->GetListOfFolders());
760 }
else if (obj->InheritsFrom(TDirectory::Class())) {
761 TDirectory *dir = (TDirectory *)obj;
762 ScanCollection(rec, dir->GetList(),
nullptr, dir->GetListOfKeys());
764 if (rec.CanExpandItem()) {
765 ScanObjectMembers(rec, obj->IsA(), (
char *)obj);
772 void TRootSniffer::ScanCollection(TRootSnifferScanRec &rec, TCollection *lst,
const char *foldername,
773 TCollection *keys_lst)
775 if ((!lst || (lst->GetSize() == 0)) && (!keys_lst || (keys_lst->GetSize() == 0)))
778 TRootSnifferScanRec folderrec;
780 if (!folderrec.GoInside(rec,
nullptr, foldername,
this))
784 TRootSnifferScanRec &master = foldername ? folderrec : rec;
788 TObject *next = iter();
789 Bool_t isany = kFALSE;
792 if (IsItemField(next)) {
794 if (!isany && (next->GetName() !=
nullptr) && ((*(next->GetName()) ==
'_') || master.ScanOnlyFields()))
795 master.SetField(next->GetName(), next->GetTitle());
803 TRootSnifferScanRec chld;
804 if (!chld.GoInside(master, obj,
nullptr,
this)) {
809 if (chld.SetResult(obj, obj->IsA()))
812 Bool_t has_kind(kFALSE), has_title(kFALSE);
814 ScanObjectProperties(chld, obj);
816 while ((next = iter()) !=
nullptr) {
817 if (!IsItemField(next))
819 if ((next->GetName() !=
nullptr) && ((*(next->GetName()) ==
'_') || chld.ScanOnlyFields())) {
821 chld.SetField(next->GetName(), next->GetTitle());
822 if (strcmp(next->GetName(), item_prop_kind) == 0)
824 if (strcmp(next->GetName(), item_prop_title) == 0)
830 chld.SetRootClass(obj->IsA());
831 if (!has_title && obj->GetTitle())
832 chld.SetField(item_prop_title, obj->GetTitle());
834 ScanObjectChilds(chld, obj);
836 if (chld.SetResult(obj, obj->IsA()))
842 TIter iter(keys_lst);
843 TObject *kobj =
nullptr;
845 while ((kobj = iter()) !=
nullptr) {
846 TKey *key =
dynamic_cast<TKey *
>(kobj);
849 TObject *obj = lst ? lst->FindObject(key->GetName()) :
nullptr;
852 if (obj && (strcmp(obj->ClassName(), key->GetClassName()) != 0))
856 if (obj && (master.fMask & TRootSnifferScanRec::kScan))
859 Bool_t iskey = kFALSE;
866 TRootSnifferScanRec chld;
867 TString fullname = TString::Format(
"%s;%d", key->GetName(), key->GetCycle());
869 if (chld.GoInside(master, obj, fullname.Data(),
this)) {
871 if (!chld.IsReadOnly(fReadOnly) && iskey && chld.IsReadyForResult()) {
872 TObject *keyobj = key->ReadObj();
874 if (chld.SetResult(keyobj, keyobj->IsA()))
878 if (chld.SetResult(obj, obj->IsA()))
881 TClass *obj_class = obj->IsA();
883 ScanObjectProperties(chld, obj);
886 chld.SetField(item_prop_title, obj->GetTitle());
890 if (!chld.IsReadOnly(fReadOnly) && iskey)
891 ScanKeyProperties(chld, key, obj, obj_class);
893 rec.SetRootClass(obj_class);
895 ScanObjectChilds(chld, obj);
898 if (chld.SetResult(obj, obj_class))
910 void TRootSniffer::CreateOwnTopFolder()
912 if (fTopFolder)
return;
914 SetScanGlobalDir(kFALSE);
917 fTopFolder = std::make_unique<TFolder>(
"http",
"Dedicated instance");
929 TFolder *TRootSniffer::GetTopFolder(Bool_t force)
931 if (fTopFolder)
return fTopFolder.get();
933 TFolder *topf = gROOT->GetRootFolder();
936 Error(
"RegisterObject",
"Not found top ROOT folder!!!");
940 TFolder *httpfold =
dynamic_cast<TFolder *
>(topf->FindObject(
"http"));
944 httpfold = topf->AddFolder(
"http",
"ROOT http server");
945 httpfold->SetBit(kCanDelete);
947 R__LOCKGUARD(gROOTMutex);
948 gROOT->GetListOfCleanups()->Add(httpfold);
962 void TRootSniffer::ScanRoot(TRootSnifferScanRec &rec)
964 rec.SetField(item_prop_kind,
"ROOT.Session");
965 if (fCurrentArg && fCurrentArg->GetUserName())
966 rec.SetField(item_prop_user, fCurrentArg->GetUserName());
969 TFolder *topf = GetTopFolder();
971 rec.SetField(item_prop_title, topf->GetTitle());
972 ScanCollection(rec, topf->GetListOfFolders());
975 if (HasStreamerInfo()) {
976 TRootSnifferScanRec chld;
977 if (chld.GoInside(rec,
nullptr,
"StreamerInfo",
this)) {
978 chld.SetField(item_prop_kind,
"ROOT.TStreamerInfoList");
979 chld.SetField(item_prop_title,
"List of streamer infos for binary I/O");
980 chld.SetField(item_prop_hidden,
"true", kFALSE);
981 chld.SetField(
"_after_request",
"JSROOT.MarkAsStreamerInfo");
985 if (IsScanGlobalDir()) {
986 ScanCollection(rec, gROOT->GetList());
988 ScanCollection(rec, gROOT->GetListOfCanvases(),
"Canvases");
990 ScanCollection(rec, gROOT->GetListOfFiles(),
"Files");
997 void TRootSniffer::ScanHierarchy(
const char *topname,
const char *path, TRootSnifferStore *store,
1000 TRootSnifferScanRec rec;
1001 rec.fSearchPath = path;
1002 if (rec.fSearchPath) {
1003 while (*rec.fSearchPath ==
'/')
1005 if (*rec.fSearchPath == 0)
1006 rec.fSearchPath =
nullptr;
1010 rec.fMask = !rec.fSearchPath ? TRootSnifferScanRec::kScan : TRootSnifferScanRec::kExpand;
1012 rec.fMask |= TRootSnifferScanRec::kOnlyFields;
1016 rec.CreateNode(topname);
1018 if (!rec.fSearchPath)
1019 rec.SetField(item_prop_rootversion, TString::Format(
"%d", ROOT_VERSION_CODE), kFALSE);
1021 if (!rec.fSearchPath && GetAutoLoad())
1022 rec.SetField(item_prop_autoload, GetAutoLoad());
1037 void *TRootSniffer::FindInHierarchy(
const char *path, TClass **cl, TDataMember **member, Int_t *chld)
1039 TRootSnifferStore store;
1041 TRootSnifferScanRec rec;
1042 rec.fSearchPath = path;
1043 rec.fMask = chld ? TRootSnifferScanRec::kCheckChilds : TRootSnifferScanRec::kSearch;
1044 if (*rec.fSearchPath ==
'/')
1046 rec.fStore = &store;
1050 TDataMember *res_member = store.GetResMember();
1051 TClass *res_cl = store.GetResClass();
1052 void *res = store.GetResPtr();
1054 if (res_member && res_cl && !member) {
1055 res_cl = (res_member->IsBasic() || res_member->IsSTLContainer()) ?
nullptr : gROOT->GetClass(res_member->GetTypeName());
1056 TRealData *rdata = res_cl ? res_cl->GetRealData(res_member->GetName()) :
nullptr;
1058 res = (
char *)res + rdata->GetThisOffset();
1059 if (res_member->IsaPointer())
1060 res = *((
char **)res);
1069 *member = res_member;
1071 *chld = store.GetResNumChilds();
1074 fCurrentRestrict = store.GetResRestrict();
1082 TObject *TRootSniffer::FindTObjectInHierarchy(
const char *path)
1084 TClass *cl =
nullptr;
1086 void *obj = FindInHierarchy(path, &cl);
1088 return cl && (cl->GetBaseClassOffset(TObject::Class()) == 0) ? (TObject *)obj :
nullptr;
1095 ULong_t TRootSniffer::GetItemHash(const
char *itemname)
1097 TObject *obj = FindTObjectInHierarchy(itemname);
1099 return !obj ? 0 : TString::Hash(obj, obj->IsA()->Size());
1105 Bool_t TRootSniffer::CanDrawItem(
const char *path)
1107 TClass *obj_cl =
nullptr;
1108 void *res = FindInHierarchy(path, &obj_cl);
1109 return (res !=
nullptr) && CanDrawClass(obj_cl);
1116 Bool_t TRootSniffer::CanExploreItem(
const char *path)
1118 TClass *obj_cl =
nullptr;
1120 void *res = FindInHierarchy(path, &obj_cl,
nullptr, &obj_chld);
1121 return res && (obj_chld > 0);
1128 Bool_t TRootSniffer::ProduceJson(
const std::string &path,
const std::string &options, std::string &res)
1133 const char *path_ = path.c_str();
1138 url.SetOptions(options.c_str());
1141 if (url.GetValueFromOptions(
"compact"))
1142 compact = url.GetIntValueFromOptions(
"compact");
1144 TClass *obj_cl =
nullptr;
1145 TDataMember *member =
nullptr;
1146 void *obj_ptr = FindInHierarchy(path_, &obj_cl, &member);
1147 if (!obj_ptr || (!obj_cl && !member))
1151 TString buf = TBufferJSON::ConvertToJSON(obj_ptr, obj_cl, compact >= 0 ? compact : 0, member ? member->GetName() :
nullptr);
1154 return !res.empty();
1160 Bool_t TRootSniffer::ExecuteCmd(
const std::string &path,
const std::string &options, std::string &res)
1162 TFolder *parent =
nullptr;
1163 TObject *obj = GetItem(path.c_str(), parent, kFALSE, kFALSE);
1165 const char *kind = GetItemField(parent, obj, item_prop_kind);
1166 if ((kind == 0) || (strcmp(kind,
"Command") != 0)) {
1168 Info(
"ExecuteCmd",
"Entry %s is not a command", path.c_str());
1173 const char *cmethod = GetItemField(parent, obj,
"method");
1174 if (!cmethod || (strlen(cmethod) == 0)) {
1176 Info(
"ExecuteCmd",
"Entry %s do not defines method for execution", path.c_str());
1182 if (fRestrictions.GetLast() >= 0) {
1183 FindInHierarchy(path.c_str());
1184 if (fCurrentRestrict == 1) {
1186 Info(
"ExecuteCmd",
"Entry %s not allowed for specified user", path.c_str());
1192 TString method = cmethod;
1194 const char *cnumargs = GetItemField(parent, obj,
"_numargs");
1195 Int_t numargs = cnumargs ? TString(cnumargs).Atoi() : 0;
1198 url.SetOptions(options.c_str());
1201 for (Int_t n = 0; n < numargs; n++) {
1202 TString argname = TString::Format(
"arg%d", n + 1);
1203 const char *argvalue = url.GetValueFromOptions(argname);
1206 Info(
"ExecuteCmd",
"For command %s argument %s not specified in options %s", path.c_str(), argname.Data(),
1212 TString svalue = DecodeUrlOptionValue(argvalue, kTRUE);
1213 argname = TString(
"%") + argname + TString(
"%");
1214 method.ReplaceAll(argname, svalue);
1219 Info(
"ExecuteCmd",
"Executing command %s method:%s", path.c_str(), method.Data());
1221 TObject *item_obj =
nullptr;
1222 Ssiz_t separ = method.Index(
"/->");
1224 if (method.Index(
"this->") == 0) {
1228 }
else if (separ != kNPOS) {
1229 item_obj = FindTObjectInHierarchy(TString(method.Data(), separ).Data());
1234 TString::Format(
"((%s*)%lu)->%s", item_obj->ClassName(), (
long unsigned)item_obj, method.Data() + separ + 3);
1236 Info(
"ExecuteCmd",
"Executing %s", method.Data());
1239 Long_t v = gROOT->ProcessLineSync(method.Data());
1241 res = std::to_string(v);
1250 Bool_t TRootSniffer::ProduceItem(
const std::string &path,
const std::string &options, std::string &res, Bool_t asjson)
1254 TRootSnifferStoreJson store(buf, options.find(
"compact") != std::string::npos);
1255 ScanHierarchy(
"top", path.c_str(), &store, kTRUE);
1257 TRootSnifferStoreXml store(buf, options.find(
"compact") != std::string::npos);
1258 ScanHierarchy(
"top", path.c_str(), &store, kTRUE);
1261 return !res.empty();
1270 Bool_t TRootSniffer::ProduceXml(
const std::string &,
const std::string & , std::string & )
1278 TString TRootSniffer::DecodeUrlOptionValue(
const char *value, Bool_t remove_quotes)
1280 if (!value || (strlen(value) == 0))
1283 TString res = value;
1285 res.ReplaceAll(
"%27",
"\'");
1286 res.ReplaceAll(
"%22",
"\"");
1287 res.ReplaceAll(
"%3E",
">");
1288 res.ReplaceAll(
"%3C",
"<");
1289 res.ReplaceAll(
"%20",
" ");
1290 res.ReplaceAll(
"%5B",
"[");
1291 res.ReplaceAll(
"%5D",
"]");
1292 res.ReplaceAll(
"%3D",
"=");
1294 if (remove_quotes && (res.Length() > 1) && ((res[0] ==
'\'') || (res[0] ==
'\"')) &&
1295 (res[0] == res[res.Length() - 1])) {
1296 res.Remove(res.Length() - 1);
1311 Bool_t TRootSniffer::ProduceExe(
const std::string & ,
const std::string & , Int_t ,
1331 Bool_t TRootSniffer::ProduceMulti(
const std::string &path,
const std::string &options, std::string &str, Bool_t asjson)
1333 if (!fCurrentArg || (fCurrentArg->GetPostDataLength() <= 0) || !fCurrentArg->GetPostData())
1336 const char *args = (
const char *)fCurrentArg->GetPostData();
1337 const char *ends = args + fCurrentArg->GetPostDataLength();
1340 url.SetOptions(options.c_str());
1343 if (url.GetValueFromOptions(
"number"))
1344 number = url.GetIntValueFromOptions(
"number");
1347 std::vector<std::string> mem;
1352 for (Int_t n = 0; n < number; n++) {
1353 const char *next = args;
1354 while ((next < ends) && (*next !=
'\n'))
1357 Error(
"ProduceMulti",
"Not enough arguments in POST block");
1361 std::string file1(args, next - args);
1364 std::string path1, opt1;
1367 std::size_t pos = file1.find_first_of(
'?');
1368 if (pos != std::string::npos) {
1369 opt1 = file1.substr(pos + 1, file1.length() - pos);
1374 pos = file1.find_last_of(
'/');
1375 if (pos != std::string::npos) {
1376 path1 = file1.substr(0, pos);
1377 file1.erase(0, pos + 1);
1381 path1 = path +
"/" + path1;
1386 Produce(path1, file1, opt1, res1);
1396 mem.emplace_back(std::move(res1));
1404 for (
unsigned n = 0; n < mem.size(); n++)
1405 length += 4 + mem[n].length();
1407 char *curr = (
char *)str.data();
1408 for (
unsigned n = 0; n < mem.size(); n++) {
1409 Long_t l = mem[n].length();
1410 *curr++ = (char)(l & 0xff);
1412 *curr++ = (char)(l & 0xff);
1414 *curr++ = (char)(l & 0xff);
1416 *curr++ = (char)(l & 0xff);
1417 if (!mem[n].empty())
1418 memcpy(curr, mem[n].data(), mem[n].length());
1419 curr += mem[n].length();
1432 Bool_t TRootSniffer::ProduceBinary(
const std::string & ,
const std::string & , std::string & )
1458 Bool_t TRootSniffer::ProduceImage(Int_t ,
const std::string & ,
const std::string & , std::string & )
1479 Bool_t TRootSniffer::Produce(
const std::string &path,
const std::string &file,
const std::string &options, std::string &res)
1484 if (file ==
"root.bin")
1485 return ProduceBinary(path, options, res);
1487 if (file ==
"root.png")
1488 return ProduceImage(TImage::kPng, path, options, res);
1490 if (file ==
"root.jpeg")
1491 return ProduceImage(TImage::kJpeg, path, options, res);
1493 if (file ==
"root.gif")
1494 return ProduceImage(TImage::kGif, path, options, res);
1496 if (file ==
"exe.bin")
1497 return ProduceExe(path, options, 2, res);
1499 if (file ==
"root.xml")
1500 return ProduceXml(path, options, res);
1502 if (file ==
"root.json")
1503 return ProduceJson(path, options, res);
1506 if (file ==
"exe.txt")
1507 return ProduceExe(path, options, 0, res);
1509 if (file ==
"exe.json")
1510 return ProduceExe(path, options, 1, res);
1512 if (file ==
"cmd.json")
1513 return ExecuteCmd(path, options, res);
1515 if (file ==
"item.json")
1516 return ProduceItem(path, options, res, kTRUE);
1518 if (file ==
"item.xml")
1519 return ProduceItem(path, options, res, kFALSE);
1521 if (file ==
"multi.bin")
1522 return ProduceMulti(path, options, res, kFALSE);
1524 if (file ==
"multi.json")
1525 return ProduceMulti(path, options, res, kTRUE);
1533 TObject *TRootSniffer::GetItem(
const char *fullname, TFolder *&parent, Bool_t force, Bool_t within_objects)
1535 TFolder *httpfold = GetTopFolder(force);
1536 if (!httpfold)
return nullptr;
1539 TObject *obj = httpfold;
1545 TString path = fullname;
1546 if (within_objects && ((path.Length() == 0) || (path[0] !=
'/')))
1547 path = fObjectsPath +
"/" + path;
1552 while (path.Tokenize(tok, from,
"/")) {
1553 if (tok.Length() == 0)
1556 TFolder *fold =
dynamic_cast<TFolder *
>(obj);
1560 TIter iter(fold->GetListOfFolders());
1561 while ((obj = iter()) !=
nullptr) {
1562 if (IsItemField(obj))
1564 if (tok.CompareTo(obj->GetName()) == 0)
1571 obj = fold->AddFolder(tok,
"sub-folder");
1572 obj->SetBit(kCanDelete);
1584 TFolder *TRootSniffer::GetSubFolder(
const char *subfolder, Bool_t force)
1586 TFolder *parent =
nullptr;
1588 return dynamic_cast<TFolder *
>(GetItem(subfolder, parent, force));
1612 Bool_t TRootSniffer::RegisterObject(
const char *subfolder, TObject *obj)
1614 TFolder *f = GetSubFolder(subfolder, kTRUE);
1619 obj->SetBit(kMustCleanup);
1630 Bool_t TRootSniffer::UnregisterObject(TObject *obj)
1635 TFolder *topf = GetTopFolder();
1638 Error(
"UnregisterObject",
"Not found top folder");
1643 topf->RecursiveRemove(obj);
1651 Bool_t TRootSniffer::CreateItem(
const char *fullname,
const char *title)
1653 TFolder *f = GetSubFolder(fullname, kTRUE);
1667 Bool_t TRootSniffer::IsItemField(TObject *obj)
const
1669 return (obj !=
nullptr) && (obj->IsA() == TNamed::Class()) && obj->TestBit(kItemField);
1676 Bool_t TRootSniffer::AccessField(TFolder *parent, TObject *chld,
const char *name,
const char *value, TNamed **only_get)
1682 Info(
"AccessField",
"Should be special case for top folder, support later");
1686 TIter iter(parent->GetListOfFolders());
1688 TObject *obj =
nullptr;
1689 Bool_t find(kFALSE), last_find(kFALSE);
1691 if (parent == chld) {
1692 last_find = find = kTRUE;
1694 TNamed *curr =
nullptr;
1695 while ((obj = iter()) !=
nullptr) {
1696 if (IsItemField(obj)) {
1697 if (last_find && obj->GetName() && !strcmp(name, obj->GetName()))
1698 curr = (TNamed *)obj;
1700 last_find = (obj == chld);
1703 if (find && !last_find)
1714 return curr !=
nullptr;
1719 curr->SetTitle(value);
1721 parent->Remove(curr);
1727 curr =
new TNamed(name, value);
1728 curr->SetBit(kItemField);
1737 TList *lst =
dynamic_cast<TList *
>(parent->GetListOfFolders());
1739 Error(
"AccessField",
"Fail cast to TList");
1744 lst->AddFirst(curr);
1746 lst->AddAfter(chld, curr);
1754 Bool_t TRootSniffer::SetItemField(
const char *fullname,
const char *name,
const char *value)
1756 if (!fullname || !name)
1759 TFolder *parent =
nullptr;
1760 TObject *obj = GetItem(fullname, parent);
1762 if (!parent || !obj)
1765 if (strcmp(name, item_prop_title) == 0) {
1766 TNamed *n =
dynamic_cast<TNamed *
>(obj);
1773 return AccessField(parent, obj, name, value);
1779 const char *TRootSniffer::GetItemField(TFolder *parent, TObject *obj,
const char *name)
1781 if (!parent || !obj || !name)
1784 TNamed *field =
nullptr;
1786 if (!AccessField(parent, obj, name,
nullptr, &field))
1789 return field ? field->GetTitle() :
nullptr;
1795 const char *TRootSniffer::GetItemField(
const char *fullname,
const char *name)
1800 TFolder *parent =
nullptr;
1801 TObject *obj = GetItem(fullname, parent);
1803 return GetItemField(parent, obj, name);
1834 Bool_t TRootSniffer::RegisterCommand(
const char *cmdname,
const char *method,
const char *icon)
1836 CreateItem(cmdname, Form(
"command %s", method));
1837 SetItemField(cmdname,
"_kind",
"Command");
1839 if (strncmp(icon,
"button;", 7) == 0) {
1840 SetItemField(cmdname,
"_fastcmd",
"true");
1844 SetItemField(cmdname,
"_icon", icon);
1846 SetItemField(cmdname,
"method", method);
1849 TString nextname = TString::Format(
"%sarg%d%s",
"%", numargs + 1,
"%");
1850 if (strstr(method, nextname.Data()) ==
nullptr)
1853 }
while (numargs < 100);
1855 SetItemField(cmdname,
"_numargs", TString::Format(
"%d", numargs));