15 #include "RConfigure.h" 40 class THttpTimer :
public TTimer {
46 TTimer(milliSec, mode), fServer(serv)
137 fLocations.SetOwner(
kTRUE);
141 #ifdef COMPILED_WITH_DABC 148 if (jsrootsys != 0) fJSROOTSYS = jsrootsys;
150 if (fJSROOTSYS.Length() == 0) {
154 TString jsdir(
"$(ROOTSYS)/etc/http");
157 Warning(
"THttpServer",
"problems resolving '%s', use JSROOTSYS to specify $ROOTSYS/etc/http location", jsdir.
Data());
164 AddLocation(
"currentdir/",
".");
165 AddLocation(
"jsrootsys/", fJSROOTSYS);
169 AddLocation(
"rootsys/", rootsys);
179 fDefaultPage = fJSROOTSYS +
"/files/online.htm";
180 fDrawPage = fJSROOTSYS +
"/files/draw.htm";
187 if (strchr(engine,
';') == 0) {
188 CreateEngine(engine);
194 if ((strcmp(opt,
"readonly") == 0) || (strcmp(opt,
"ro") == 0)) {
195 GetSniffer()->SetReadOnly(
kTRUE);
196 }
else if ((strcmp(opt,
"readwrite") == 0) || (strcmp(opt,
"rw") == 0)) {
197 GetSniffer()->SetReadOnly(
kFALSE);
225 if (fSniffer)
delete fSniffer;
234 return fSniffer ? fSniffer->IsReadOnly() :
kTRUE;
244 if (fSniffer) fSniffer->SetReadOnly(readonly);
255 if ((prefix==0) || (*prefix==0))
return;
257 TNamed *obj =
dynamic_cast<TNamed*
> (fLocations.FindObject(prefix));
261 fLocations.Add(
new TNamed(prefix, path));
276 fJSROOT = location ? location :
"";
287 if ((filename!=0) && (*filename!=0))
288 fDefaultPage = filename;
290 fDefaultPage = fJSROOTSYS +
"/files/online.htm";
293 fDefaultPageCont.Clear();
304 if ((filename!=0) && (*filename!=0))
305 fDrawPage = filename;
307 fDrawPage = fJSROOTSYS +
"/files/draw.htm";
310 fDrawPageCont.Clear();
325 if (engine == 0)
return kFALSE;
327 const char *arg = strchr(engine,
':');
328 if (arg == 0)
return kFALSE;
331 if (arg != engine) clname.
Append(engine, arg - engine);
333 if ((clname.
Length() == 0) || (clname ==
"http") || (clname ==
"civetweb"))
334 clname =
"TCivetweb";
335 else if (clname ==
"fastcgi")
337 else if (clname ==
"dabc")
338 clname =
"TDabcEngine";
342 if (engine_class == 0)
return kFALSE;
345 if (eng == 0)
return kFALSE;
349 if (!eng->
Create(arg + 1)) {
376 fTimer =
new THttpTimer(milliSec, mode,
this);
387 if ((fname == 0) || (*fname == 0))
return kFALSE;
391 while (*fname != 0) {
394 const char *next = strpbrk(fname,
"/\\");
395 if (next == 0)
return kTRUE;
398 if ((next == fname + 2) && (*fname ==
'.') && (*(fname + 1) ==
'.')) {
401 if (level < 0)
return kFALSE;
406 if ((next == fname + 1) && (*fname ==
'.')) {
433 if ((uri == 0) || (strlen(uri) == 0))
return kFALSE;
437 TIter iter(&fLocations);
439 while ((obj=iter()) != 0) {
441 if (pos ==
kNPOS)
continue;
443 if (!VerifyFilePath(fname.
Data()))
return kFALSE;
469 std::unique_lock<std::mutex> lk(fMutex);
488 Error(
"ProcessRequests",
"Should be called only from main ROOT thread");
492 std::unique_lock<std::mutex> lk(fMutex, std::defer_lock);
497 if (fCallArgs.GetSize() > 0) {
499 fCallArgs.RemoveFirst();
505 fSniffer->SetCurrentCallArg(arg);
509 fSniffer->SetCurrentCallArg(0);
511 fSniffer->SetCurrentCallArg(0);
514 arg->
fCond.notify_one();
518 TIter iter(&fEngines);
534 if (fDefaultPageCont.Length() == 0) {
536 char *buf = ReadFileContent(fDefaultPage.Data(), len);
537 if (len > 0) fDefaultPageCont.Append(buf, len);
541 if (fDefaultPageCont.Length() == 0) {
547 if (fJSROOT.Length() > 0) {
553 const char *hjsontag =
"\"$$$h.json$$$\"";
559 const char *topname = fTopName.Data();
561 fSniffer->ScanHierarchy(topname, arg->
fPathName.
Data(), &store);
565 arg->
AddHeader(
"Cache-Control",
"private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0");
574 if (fDrawPageCont.Length() == 0) {
576 char *buf = ReadFileContent(fDrawPage.Data(), len);
577 if (len > 0) fDrawPageCont.Append(buf, len);
581 if (fDrawPageCont.Length() == 0) {
584 const char *rootjsontag =
"\"$$$root.json$$$\"";
585 const char *hjsontag =
"\"$$$h.json$$$\"";
590 if (fJSROOT.Length() > 0) {
599 const char *topname = fTopName.Data();
610 if (fSniffer->Produce(arg->
fPathName.
Data(),
"root.json",
"compact=3", bindata, bindatalen, str)) {
614 arg->
AddHeader(
"Cache-Control",
"private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0");
637 if ((filename ==
"h.xml") || (filename ==
"get.xml")) {
641 arg->
fContent.
Form(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
648 const char *topname = fTopName.Data();
650 fSniffer->ScanHierarchy(topname, arg->
fPathName.
Data(), &store, filename ==
"get.xml");
659 if (filename ==
"h.json") {
661 const char *topname = fTopName.Data();
663 fSniffer->ScanHierarchy(topname, arg->
fPathName.
Data(), &store);
667 if (filename ==
"root.websocket") {
676 if (strcmp(arg->
GetMethod(),
"WS_CONNECT")==0) {
683 if (strcmp(arg->
GetMethod(),
"WS_READY")==0) {
686 if (
gDebug>0)
Info(
"ProcessRequest",
"Set WebSocket handle %p", wshandle);
692 if (strcmp(arg->
GetMethod(),
"WS_DATA")==0) {
699 if (strcmp(arg->
GetMethod(),
"WS_CLOSE")==0) {
705 if (
gDebug>0)
Info(
"ProcessRequest",
"Clear WebSocket handle");
719 if (bindata != 0) arg->
SetBinData(bindata, bindatalen);
728 if (arg->
Is404())
return;
732 if (filename ==
"root.bin") {
735 const char *parname = fSniffer->IsStreamerInfoItem(arg->
fPathName.
Data()) ?
"BVersion" :
"MVersion";
736 arg->
AddHeader(parname,
Form(
"%u", (
unsigned) fSniffer->GetStreamerInfoHash()));
740 arg->
AddHeader(
"Cache-Control",
"private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0");
750 return fSniffer->RegisterObject(subfolder, obj);
760 return fSniffer->UnregisterObject(obj);
770 fSniffer->Restrict(path, options);
803 return fSniffer->RegisterCommand(cmdname, method, icon);
811 return SetItemField(foldername,
"_hidden", hide ?
"true" : (
const char *) 0);
822 return SetItemField(fullname,
"_icon", iconname);
829 return fSniffer->CreateItem(fullname, title);
836 return fSniffer->SetItemField(fullname, name, value);
843 return fSniffer->GetItemField(fullname, name);
851 static const struct {
856 {
".xml", 4,
"text/xml"},
857 {
".json", 5,
"application/json"},
858 {
".bin", 4,
"application/x-binary"},
859 {
".gif", 4,
"image/gif"},
860 {
".jpg", 4,
"image/jpeg"},
861 {
".png", 4,
"image/png"},
862 {
".html", 5,
"text/html"},
863 {
".htm", 4,
"text/html"},
864 {
".shtm", 5,
"text/html"},
865 {
".shtml", 6,
"text/html"},
866 {
".css", 4,
"text/css"},
867 {
".js", 3,
"application/x-javascript"},
868 {
".ico", 4,
"image/x-icon"},
869 {
".jpeg", 5,
"image/jpeg"},
870 {
".svg", 4,
"image/svg+xml"},
871 {
".txt", 4,
"text/plain"},
872 {
".torrent", 8,
"application/x-bittorrent"},
873 {
".wav", 4,
"audio/x-wav"},
874 {
".mp3", 4,
"audio/x-mp3"},
875 {
".mid", 4,
"audio/mid"},
876 {
".m3u", 4,
"audio/x-mpegurl"},
877 {
".ogg", 4,
"application/ogg"},
878 {
".ram", 4,
"audio/x-pn-realaudio"},
879 {
".xslt", 5,
"application/xml"},
880 {
".xsl", 4,
"application/xml"},
881 {
".ra", 3,
"audio/x-pn-realaudio"},
882 {
".doc", 4,
"application/msword"},
883 {
".exe", 4,
"application/octet-stream"},
884 {
".zip", 4,
"application/x-zip-compressed"},
885 {
".xls", 4,
"application/excel"},
886 {
".tgz", 4,
"application/x-tar-gz"},
887 {
".tar", 4,
"application/x-tar"},
888 {
".gz", 3,
"application/x-gunzip"},
889 {
".arj", 4,
"application/x-arj-compressed"},
890 {
".rar", 4,
"application/x-arj-compressed"},
891 {
".rtf", 4,
"application/rtf"},
892 {
".pdf", 4,
"application/pdf"},
893 {
".swf", 4,
"application/x-shockwave-flash"},
894 {
".mpg", 4,
"video/mpeg"},
895 {
".webm", 5,
"video/webm"},
896 {
".mpeg", 5,
"video/mpeg"},
897 {
".mov", 4,
"video/quicktime"},
898 {
".mp4", 4,
"video/mp4"},
899 {
".m4v", 4,
"video/x-m4v"},
900 {
".asf", 4,
"video/x-ms-asf"},
901 {
".avi", 4,
"video/x-msvideo"},
902 {
".bmp", 4,
"image/bmp"},
903 {
".ttf", 4,
"application/x-font-ttf"},
907 int path_len = strlen(path);
927 std::ifstream is(filename);
934 char *buf = (
char *)
malloc(len);
void SetZipping(Int_t kind)
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
virtual void Process()
Method regularly called in main ROOT context.
This namespace contains pre-defined functions to be used in conjuction with TExecutor::Map and TExecu...
Storage of hierarchy scan in TRootSniffer in JSON format.
TString & ReplaceAll(const TString &s1, const TString &s2)
const char * GetItemField(const char *fullname, const char *name)
Bool_t IsReadOnly() const
returns read-only mode
virtual void ProcessData(THttpCallArg *arg)
process data received from the client
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
TString fQuery
authenticated user name (if any)
TObject * At(Int_t idx) const
void SetServer(THttpServer *serv)
virtual void AssignCanvas(TCanvas *canv)
assign canvas to the web socket connects with CanvasModified signal
void SetContentType(const char *typ)
void ProcessRequests()
Process submitted requests, must be called from main thread.
Bool_t CreateItem(const char *fullname, const char *title)
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString...
The TNamed class is the base class for all named ROOT classes.
virtual const char * Getenv(const char *env)
Get environment variable.
TString fPathName
request method like GET or POST
TString & Append(const char *cs)
Bool_t EndsWith(const char *pat, ECaseCompare cmp=kExact) const
Return true if string ends with the specified string.
static Long_t SelfId()
Static method returning the id for the current thread.
void SetTimer(Long_t milliSec=100, Bool_t mode=kTRUE)
create timer which will invoke ProcessRequests() function periodically Timer is required to perform a...
Storage of hierarchy scan in TRootSniffer in XML format.
Bool_t Register(const char *subfolder, TObject *obj)
Register object in subfolder.
void SetReadOnly(Bool_t readonly)
Set read-only mode for the server (default on) In read-only server is not allowed to change any ROOT ...
Int_t GetLast() const
Return index of last object in array.
void SetBinData(void *data, Long_t length)
set binary data, which will be returned as reply body
Bool_t CreateEngine(const char *engine)
factory method to create different http engines At the moment two engine kinds are supported: civetwe...
R__EXTERN TSystem * gSystem
virtual TObject * GetPrimitive(const char *name) const
Get primitive.
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
virtual ~THttpServer()
destructor delete all http engines and sniffer
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
char * Form(const char *fmt,...)
virtual Bool_t Create(const char *)
Method to create all components of engine.
Handles synchronous and a-synchronous timer events.
The ROOT global object gROOT contains a list of all defined classes.
void SetSniffer(TRootSniffer *sniff)
Set TRootSniffer to the server Server takes ownership over sniffer.
static const struct @165 builtin_mime_types[]
Bool_t ExecuteHttp(THttpCallArg *arg)
Execute HTTP request.
TString & Remove(Ssiz_t pos)
std::condition_variable fCond
web-socket handle, derived from TNamed class
void AddLocation(const char *prefix, const char *path)
add files location, which could be used in the server one could map some system folder to the server ...
TObjArray * Tokenize(const TString &delim) const
This function is used to isolate sequential tokens in a TString.
Bool_t Hide(const char *fullname, Bool_t hide=kTRUE)
hides folder or element from web gui
virtual void ProcessRequest(THttpCallArg *arg)
submitted arguments
TNamed * TakeWSHandle()
takeout websocket handle with HTTP call can be done only once
Bool_t RegisterCommand(const char *cmdname, const char *method, const char *icon=0)
Register command which can be executed from web interface.
Mother of all ROOT objects.
static const char * GetMimeType(const char *path)
Guess mime type base on file extension.
Bool_t Unregister(TObject *obj)
Unregister object.
TString fContent
response header like ContentEncoding, Cache-Control and so on
virtual const char * GetTitle() const
Returns title of object.
void AddHeader(const char *name, const char *value)
Set name: value pair to reply header Content-Type field handled separately - one should use SetConten...
static char * ReadFileContent(const char *filename, Int_t &len)
Reads content of file from the disk.
void SetFile(const char *filename=0)
Bool_t SetIcon(const char *fullname, const char *iconname)
set name of icon, used in browser together with the item
virtual void ClearHandle()=0
static Bool_t VerifyFilePath(const char *fname)
Checked that filename does not contains relative path below current directory Used to prevent access ...
virtual Bool_t ExpandPathName(TString &path)
Expand a pathname getting rid of special shell characters like ~.
virtual const char * GetName() const
Returns name of object.
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
void SetDrawPage(const char *filename)
Set file name of HTML page, delivered by the server when objects drawing page is requested from the b...
TString fFileName
item path
const char * GetMethod() const
Bool_t SetItemField(const char *fullname, const char *name, const char *value)
Bool_t IsFileRequested(const char *uri, TString &res) const
Check if file is requested, thread safe.
void Restrict(const char *path, const char *options)
Restrict access to specified object.
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
void Resize(Ssiz_t n)
Resize the string. Truncate or add blanks as necessary.
void SetDefaultPage(const char *filename)
Set file name of HTML page, delivered by the server when http address is opened in the browser...
void SetJSROOT(const char *location)
Set location of JSROOT to use with the server One could specify address like: https://root.cern.ch/js/3.3/ http://web-docs.gsi.de/~linev/js/3.3/ This allows to get new JSROOT features with old server, reduce load on THttpServer instance, also startup time can be improved When empty string specified (default), local copy of JSROOT is used (distributed with ROOT)
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
const char * Data() const