22#define THREADTYPE void
24#if defined( OS_WINNT )
26#define THREADTYPE DWORD WINAPI
35#include <TDirectory.h>
39#include <TServerSocket.h>
42#include <TObjString.h>
45#include <TBufferXML.h>
89 }
else if (c ==
'>') {
91 }
else if (c ==
'&') {
108 }
else if (isdigit(c)) {
112 sprintf(buf,
"%%%02x", c);
122 if (a>=
'0' && a<=
'9')
124 if (a>=
'a' && a<=
'f')
126 if (a>=
'A' && a<=
'F')
159 printf(
"Follow path [%s] in container %p\n", path, container);
166 char* s = strchr(path,
'/');
176 if (container->InheritsFrom(TDirectory::Class()))
177 obj = ((
TDirectory*)container)->FindObject(xpath.c_str());
178 else if (container->InheritsFrom(TFolder::Class()))
179 obj = ((TFolder*)container)->FindObject(xpath.c_str());
180 else if (container->InheritsFrom(TCollection::Class()))
181 obj = ((TCollection*)container)->FindObject(xpath.c_str());
184 fprintf(stderr,
"XmlServer: ERROR: Container \'%s\' of type %s is not a TDirectory, TFolder or TCollection\n", container->GetName(), container->IsA()->GetName());
204 printf(
"FindTopLevelObject [%s]\n", name);
205 if (strcmp(name,
"root") == 0)
209 obj = gROOT->GetListOfFiles()->FindObject(name);
212 obj = gROOT->FindObjectAny(name);
221 printf(
"Extract top level object from [%s]\n", path);
226 char* s = strchr(path,
'/');
242 for (
unsigned int i=0; i<
gExports.size(); i++)
244 const char* ename =
gExports[i].c_str();
246 if (strcmp(xpath.c_str(), ename) == 0)
257 fprintf(stderr,
"XmlServer: ERROR: Top level object \'%s\' not found in exports list\n", xpath.c_str());
267 printf(
"Follow path [%s]\n", path);
289 printf(
"ResetObject object %p name [%s] type [%s]\n", obj, obj->GetName(), obj->IsA()->GetName());
291 if (obj->InheritsFrom(TH1::Class()))
293 ((TH1*)obj)->Reset();
295 else if (obj->InheritsFrom(TDirectory::Class()))
303 TObject *obj = next();
316 sock->SendRaw(str, strlen(str));
319static void SendHttpReply(TSocket* sock,
const char* mimetype,
const char* message)
322 int len = strlen(message);
325 SendString(sock,
"Server: ROOTANA xmlServer\n");
326 sprintf(buf,
"Content-Length: %d\n", len);
329 sprintf(buf,
"Content-Type: %s\n", mimetype);
334 printf(
"XmlServer: Reply content-length %d, content-type %s\n", len, mimetype);
337static void SendHttpReply(TSocket* sock,
const char* mimetype,
const std::string& str)
344static std::string
HtmlTag(
const char* tag,
const char* contents)
357static std::string
HtmlTag(
const char* tag,
const std::string& contents)
374 const char* objname = obj->GetName();
375 const char* classname = obj->ClassName();
376 bool isSubdir =
false;
377 std::string xkey =
"";
379 if (obj->InheritsFrom(TKey::Class())) {
380 TKey* key = (TKey*)obj;
381 classname = key->GetClassName();
385 const TClass *xclass = TClass::GetClass(classname);
387 if (xclass->InheritsFrom(TDirectory::Class()))
390 if (xclass->InheritsFrom(TFolder::Class()))
393 if (xclass->InheritsFrom(TCollection::Class()))
406 const char* objname = obj->GetName();
407 const char* classname = obj->ClassName();
410 if (obj->InheritsFrom(TKey::Class())) {
411 TKey* key = (TKey*)obj;
412 classname = key->GetClassName();
444static void SendFile(TSocket* sock,
const char* filename,
const char* mimetype)
446 std::string f = filename;
448 FILE *fp = fopen(f.c_str(),
"r");
450 std::string home = getenv(
"HOME");
451 f = home +
"/packages/rootana/libXmlServer/" + filename;
452 fp = fopen(f.c_str(),
"r");
454 printf(
"sending file %s, fp %p\n", f.c_str(), fp);
458 int rd = fread(buf, 1,
sizeof(buf)-1, fp);
478 TSocket *sock = (TSocket *) arg;
484 int rd = sock->RecvRaw(request,
sizeof(request), kDontBlock);
488 fprintf(stderr,
"XmlServer: connection from %s closed\n", sock->GetInetAddress().GetHostName());
496 p = strchr(request,
'\n');
500 p = strchr(request,
'\r');
506 printf(
"XmlServer: Request [%s] from %s\n", request, sock->GetInetAddress().GetHostName());
509 else if (strstr(request,
"GET / "))
517 reply +=
"<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<html><head>\n";
518 reply +=
HtmlTag(
"title",
"Export list") +
"\n";
519 reply +=
"</head><body>\n";
520 reply +=
HtmlTag(
"h1",
"Export list") +
"\n";
522 for (
unsigned int i=0; i<
gExports.size(); i++) {
523 const char* ename =
gExports[i].c_str();
541 reply +=
HtmlTag(
"p", s) +
"\n";
545 s +=
" (cannot be found. maybe deleted?)\n";
546 reply +=
HtmlTag(
"p", s) +
"\n";
552 reply +=
"</body></html>\n";
559 else if (strstr(request,
"js/jquery.min.js "))
561 SendFile(sock,
"jquery.min.js",
"text/javascript");
563 else if (strstr(request,
"js/highcharts.js "))
565 SendFile(sock,
"highcharts.js",
"text/javascript");
567 else if (strstr(request,
"js/exporting.js "))
569 SendFile(sock,
"exporting.js",
"text/javascript");
571 else if (strstr(request,
"GET /favicon.ico "))
575 reply +=
"<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<html><head>\n";
576 reply +=
HtmlTag(
"title",
"No favicon") +
"\n";
577 reply +=
"</head><body>\n";
578 reply +=
HtmlTag(
"h1",
"No favicon") +
"\n";
579 reply +=
HtmlTag(
"p",
"No favicon") +
"\n";
580 reply +=
"</body></html>\n";
583 else if (strstr(request,
"GET /index.xml "))
594 for (
unsigned int i=0; i<
gExports.size(); i++)
596 const char* ename =
gExports[i].c_str();
606 const char* cname = obj->ClassName();
618 else if (strncmp(request,
"GET /", 5) == 0)
622 char* dirname = request + 5;
624 char* x = strstr(dirname,
" HTTP");
628 bool xmlOutput =
false;
630 x = strstr(dirname,
".xml");
650 reply +=
"<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<html><head>\n";
654 reply +=
HtmlTag(
"title", buf) +
"\n";
655 reply +=
"</head><body>\n";
656 reply +=
HtmlTag(
"h1", buf) +
"\n";
658 reply +=
HtmlTag(
"p",
"Object not found");
660 reply +=
"</body></html>\n";
663 }
else if (obj && obj->InheritsFrom(TDirectory::Class())) {
673 reply +=
"<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<html><head>\n";
677 reply +=
HtmlTag(
"title", buf) +
"\n";
678 reply +=
"</head><body>\n";
679 reply +=
HtmlTag(
"h1", buf) +
"\n";
684 std::map<std::string, std::string> alist;
694 TObject *obj = next();
718 TObject *obj = next();
736 std::map<std::string, std::string>::iterator iter = alist.begin();
737 for (; iter!=alist.end(); iter++) {
740 reply += iter->second;
744 reply +=
"</body></html>\n";
746 xml +=
"</dir></xml>\n";
753 }
else if (obj && obj->InheritsFrom(TFolder::Class())) {
754 TFolder* folder = (TFolder*)obj;
767 reply +=
"<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<html><head>\n";
771 reply +=
HtmlTag(
"title", buf) +
"\n";
772 reply +=
"</head><body>\n";
773 reply +=
HtmlTag(
"h1", buf) +
"\n";
775 TIterator *iterator = folder->GetListOfFolders()->MakeIterator();
791 xml +=
"</dir></xml>\n";
792 reply +=
"</body></html>\n";
799 }
else if (obj && obj->InheritsFrom(TCollection::Class())) {
800 TCollection* collection = (TCollection*)obj;
815 reply +=
"<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<html><head>\n";
819 reply +=
HtmlTag(
"title", buf) +
"\n";
820 reply +=
"</head><body>\n";
821 reply +=
HtmlTag(
"h1", buf) +
"\n";
823 TIterator *iterator = collection->MakeIterator();
839 xml +=
"</dir></xml>\n";
840 reply +=
"</body></html>\n";
850 xml +=
"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
852 xml +=
"<ROOTobject>\n";
853 TString msg = TBufferXML::ConvertToXML(obj);
855 xml +=
"</ROOTobject>\n";
860 SendFile(sock,
"plot.html",
"text/html");
865 reply +=
"<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<html><head>\n";
869 reply +=
HtmlTag(
"title", buf) +
"\n";
870 reply +=
"</head><body>\n";
871 reply +=
HtmlTag(
"h1", buf) +
"\n";
873 reply +=
HtmlTag(
"p", obj->GetName());
874 reply +=
HtmlTag(
"p", obj->ClassName());
876 reply +=
"</body></html>\n";
883 else if (strncmp(request,
"ResetTH1 ", 9) == 0)
887 char* path = request + 9;
889 if (strlen(path) > 1)
898 for (
unsigned int i=0; i<
gExports.size(); i++)
900 const char* ename =
gExports[i].c_str();
907 fprintf(stderr,
"XmlServer: ResetTH1: Exported name \'%s\' cannot be found!\n", xname);
922 const char *msg =
"Success";
923 sock->SendRaw(msg, strlen(msg) + 1);
928 fprintf(stderr,
"XmlServer: Received unknown request \"%s\"\n", request);
931 reply +=
"<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<html><head>\n";
932 reply +=
HtmlTag(
"title",
"Unknown request") +
"\n";
933 reply +=
"</head><body>\n";
934 reply +=
HtmlTag(
"h1",
"Unknown request") +
"\n";
935 reply +=
HtmlTag(
"p", request) +
"\n";
936 reply +=
"</body></html>\n";
951 int port = *(
int *) arg;
953 fprintf(stderr,
"XmlServer: Listening on port %d...\n", port);
954 TServerSocket *lsock =
new TServerSocket(port, kTRUE);
958 TSocket *sock = lsock->Accept();
962 fprintf(stderr,
"XmlServer: TSocket->Accept() error\n");
967 fprintf(stderr,
"XmlServer: connection from %s\n", sock->GetInetAddress().GetHostName());
973 LPDWORD lpThreadId = 0;
993 printf(
"Export TDirectory %p named [%s] of type [%s] as [%s]\n", dir, dir->GetName(), dir->IsA()->GetName(), exportName);
996 for (
unsigned int i=0; i<
gExports.size(); i++)
998 const char* ename =
gExports[i].c_str();
999 if (strcmp(ename, exportName) == 0)
1011 printf(
"Export TFolder %p named [%s] of type [%s] as [%s]\n", folder, folder->GetName(), folder->IsA()->GetName(), exportName);
1014 for (
unsigned int i=0; i<
gExports.size(); i++)
1016 const char* ename =
gExports[i].c_str();
1017 if (strcmp(ename, exportName) == 0)
1029 printf(
"Export TCollection %p named [%s] of type [%s] as [%s]\n", collection, collection->GetName(), collection->IsA()->GetName(), exportName);
1032 for (
unsigned int i=0; i<
gExports.size(); i++)
1034 const char* ename =
gExports[i].c_str();
1035 if (strcmp(ename, exportName) == 0)
1051 static int pport = port;
1056 LPDWORD lpThreadId = 0;
1057 CloseHandle(CreateThread(NULL, 1024, &xroot_socket_server, &pport, 0, lpThreadId));
virtual TList * GetList() const
virtual TList * GetListOfKeys() const
void Export(TDirectory *dir, const char *exportName)
void SetVerbose(bool verbose)
static std::deque< std::string > gExports
static std::map< std::string, std::string > gExportNames
static void ResetObject(TObject *obj)
static std::string HtmlDecode(const char *s)
std::string MakeHtmlEntry(const TObject *obj, const char *path)
std::string MakeXmlEntry(const TObject *obj)
static std::deque< std::string > gExports
static std::string HtmlTag(const char *tag, const char *contents)
static std::map< std::string, std::string > gExportNames
static TObject * FollowPath(TObject *container, char *path)
static std::string UrlEncode(const char *s)
static TObject * FindTopLevelObject(const char *name)
static void SendString(TSocket *sock, const char *str)
static THREADTYPE xsocket_listener(void *arg)
static TObject * TopLevel(char *path, char **opath)
static void SendHttpReply(TSocket *sock, const char *mimetype, const char *message)
static std::string HtmlEncode(const char *s)
static THREADTYPE xroot_server_thread(void *arg)
static void SendFile(TSocket *sock, const char *filename, const char *mimetype)