// $Id$
// Author: Sergey Linev   21/12/2013

#include "THttpServer.h"

#include "TTimer.h"
#include "TSystem.h"
#include "TImage.h"
#include "TROOT.h"
#include "TClass.h"
#include "TFolder.h"
#include "RVersion.h"
#include "RConfigure.h"

#include "THttpEngine.h"
#include "TRootSniffer.h"
#include "TRootSnifferStore.h"

#include <string>
#include <cstdlib>
#include <stdlib.h>
#include <string.h>
#include <fstream>


//////////////////////////////////////////////////////////////////////////
//                                                                      //
// THttpTimer                                                           //
//                                                                      //
// Specialized timer for THttpServer                                    //
// Provides regular call of THttpServer::ProcessRequests() method       //
//                                                                      //
//////////////////////////////////////////////////////////////////////////


//______________________________________________________________________________
class THttpTimer : public TTimer {
public:

   THttpServer *fServer;  //!

   THttpTimer(Long_t milliSec, Bool_t mode, THttpServer *serv) :
      TTimer(milliSec, mode), fServer(serv)
   {
      // construtor
   }
   virtual ~THttpTimer()
   {
      // destructor
   }
   virtual void Timeout()
   {
      // timeout handler
      // used to process http requests in main ROOT thread

      if (fServer) fServer->ProcessRequests();
   }
};

// =======================================================

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// THttpServer                                                          //
//                                                                      //
// Online http server for arbitrary ROOT application                    //
//                                                                      //
// Idea of THttpServer - provide remote http access to running          //
// ROOT application and enable HTML/JavaScript user interface.          //
// Any registered object can be requested and displayed in the browser. //
// There are many benefits of such approach:                            //
//     * standard http interface to ROOT application                    //
//     * no any temporary ROOT files when access data                   //
//     * user interface running in all browsers                         //
//                                                                      //
// Starting HTTP server                                                 //
//                                                                      //
// To start http server, at any time  create instance                   //
// of the THttpServer class like:                                       //
//    serv = new THttpServer("http:8080");                              //
//                                                                      //
// This will starts civetweb-based http server with http port 8080.     //
// Than one should be able to open address "http://localhost:8080"      //
// in any modern browser (IE, Firefox, Chrome) and browse objects,      //
// created in application. By default, server can access files,         //
// canvases and histograms via gROOT pointer. All such objects          //
// can be displayed with JSROOT graphics.                               //
//                                                                      //
// At any time one could register other objects with the command:       //
//                                                                      //
// TGraph* gr = new TGraph(10);                                         //
// gr->SetName("gr1");                                                  //
// serv->Register("graphs/subfolder", gr);                              //
//                                                                      //
// If objects content is changing in the application, one could         //
// enable monitoring flag in the browser - than objects view            //
// will be regularly updated.                                           //
//                                                                      //
// More information: http://root.cern.ch/drupal/content/users-guide     //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

//______________________________________________________________________________
THttpServer::THttpServer(const char *engine) :
   TNamed("http", "ROOT http server"),
   fEngines(),
   fTimer(0),
   fSniffer(0),
   fMainThrdId(0),
   fJSROOTSYS(),
   fTopName("ROOT"),
   fJSROOT(),
   fLocations(),
   fDefaultPage(),
   fDefaultPageCont(),
   fDrawPage(),
   fDrawPageCont(),
   fMutex(),
   fCallArgs()
{
   // constructor

   // As argument, one specifies engine kind which should be
   // created like "http:8080". One could specify several engines
   // at once, separating them with ; like "http:8080;fastcgi:9000"
   // One also can configure readonly flag for sniffer like
   // "http:8080;readonly" or "http:8080;readwrite"
   //
   // Also searches for JavaScript ROOT sources, which are used in web clients
   // Typically JSROOT sources located in $ROOTSYS/etc/http directory,
   // but one could set JSROOTSYS variable to specify alternative location

   fLocations.SetOwner(kTRUE);

   // Info("THttpServer", "Create %p in thrd %ld", this, (long) fMainThrdId);

#ifdef COMPILED_WITH_DABC
   const char *dabcsys = gSystem->Getenv("DABCSYS");
   if (dabcsys != 0)
      fJSROOTSYS = TString::Format("%s/plugins/root/js", dabcsys);
#endif

   const char *jsrootsys = gSystem->Getenv("JSROOTSYS");
   if (jsrootsys != 0) fJSROOTSYS = jsrootsys;

   if (fJSROOTSYS.Length() == 0) {
#ifdef ROOTETCDIR
      TString jsdir = TString::Format("%s/http", ROOTETCDIR);
#else
      TString jsdir("$(ROOTSYS)/etc/http");
#endif
      if (gSystem->ExpandPathName(jsdir)) {
         Warning("THttpServer", "problems resolving '%s', use JSROOTSYS to specify $ROOTSYS/etc/http location", jsdir.Data());
         fJSROOTSYS = ".";
      } else {
         fJSROOTSYS = jsdir;
      }
   }

   AddLocation("currentdir/", ".");
   AddLocation("jsrootsys/", fJSROOTSYS);

   const char *rootsys = gSystem->Getenv("ROOTSYS");
   if (rootsys != 0) {
      AddLocation("rootsys/", rootsys);
   } else {
#ifdef ROOTPREFIX
      TString sysdir = ROOTPREFIX;
#else
      TString sysdir = "$(ROOTSYS)";
#endif
      if (!gSystem->ExpandPathName(sysdir)) AddLocation("rootsys/", sysdir);
   }

   fDefaultPage = fJSROOTSYS + "/files/online.htm";
   fDrawPage = fJSROOTSYS + "/files/draw.htm";

   SetSniffer(new TRootSniffer("sniff"));

   // start timer
   SetTimer(20, kTRUE);

   if (strchr(engine, ';') == 0) {
      CreateEngine(engine);
   } else {
      TObjArray *lst = TString(engine).Tokenize(";");

      for (Int_t n = 0; n <= lst->GetLast(); n++) {
         const char *opt = lst->At(n)->GetName();
         if ((strcmp(opt, "readonly") == 0) || (strcmp(opt, "ro") == 0)) {
            GetSniffer()->SetReadOnly(kTRUE);
         } else if ((strcmp(opt, "readwrite") == 0) || (strcmp(opt, "rw") == 0)) {
            GetSniffer()->SetReadOnly(kFALSE);
         } else
            CreateEngine(opt);
      }

      delete lst;
   }
}

//______________________________________________________________________________
THttpServer::~THttpServer()
{
   // destructor
   // delete all http engines and sniffer

   fEngines.Delete();

   SetSniffer(0);

   SetTimer(0);
}

//______________________________________________________________________________
void THttpServer::SetSniffer(TRootSniffer *sniff)
{
   // Set TRootSniffer to the server
   // Server takes ownership over sniffer

   if (fSniffer) delete fSniffer;
   fSniffer = sniff;
}

//______________________________________________________________________________
Bool_t THttpServer::IsReadOnly() const
{
   // returns read-only mode

   return fSniffer ? fSniffer->IsReadOnly() : kTRUE;
}

//______________________________________________________________________________
void THttpServer::SetReadOnly(Bool_t readonly)
{
   // Set read-only mode for the server (default on)
   // In read-only server is not allowed to change any ROOT object, registered to the server
   // Server also cannot execute objects method via exe.json request

   if (fSniffer) fSniffer->SetReadOnly(readonly);
}

//______________________________________________________________________________
void THttpServer::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 like AddLocation("mydir/","/home/user/specials");
   // Than files from this directory could be addressed via server like
   // http://localhost:8080/mydir/myfile.root

   if ((prefix==0) || (*prefix==0)) return;

   TNamed *obj = dynamic_cast<TNamed*> (fLocations.FindObject(prefix));
   if (obj != 0) {
      obj->SetTitle(path);
   } else {
      fLocations.Add(new TNamed(prefix, path));
   }
}

//______________________________________________________________________________
void THttpServer::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)

   fJSROOT = location ? location : "";
}

//______________________________________________________________________________
void THttpServer::SetDefaultPage(const char* filename)
{
   // Set file name of HTML page, delivered by the server when
   // http address is opened in the browser.
   // By default, $ROOTSYS/etc/http/files/online.htm page is used
   // When empty filename is specified, default page will be used

   if ((filename!=0) && (*filename!=0))
      fDefaultPage = filename;
   else
      fDefaultPage = fJSROOTSYS + "/files/online.htm";

   // force to read page content next time again
   fDefaultPageCont.Clear();
}

//______________________________________________________________________________
void THttpServer::SetDrawPage(const char* filename)
{
   // Set file name of HTML page, delivered by the server when
   // objects drawing page is requested from the browser
   // By default, $ROOTSYS/etc/http/files/draw.htm page is used
   // When empty filename is specified, default page will be used

   if ((filename!=0) && (*filename!=0))
      fDrawPage = filename;
   else
      fDrawPage = fJSROOTSYS + "/files/draw.htm";

   // force to read page content next time again
   fDrawPageCont.Clear();
}

//______________________________________________________________________________
Bool_t THttpServer::CreateEngine(const char *engine)
{
   // factory method to create different http engines
   // At the moment two engine kinds are supported:
   //  civetweb (default) and fastcgi
   // Examples:
   //   "civetweb:8080" or "http:8080" or ":8080" - creates civetweb web server with http port 8080
   //   "fastcgi:9000" - creates fastcgi server with port 9000
   //   "dabc:1237"    - create DABC server with port 1237 (only available with DABC installed)
   //   "dabc:master_host:port" - attach to DABC master, running on master_host:port (only available with DABC installed)

   if (engine == 0) return kFALSE;

   const char *arg = strchr(engine, ':');
   if (arg == 0) return kFALSE;

   TString clname;
   if (arg != engine) clname.Append(engine, arg - engine);

   if ((clname.Length() == 0) || (clname == "http") || (clname == "civetweb"))
      clname = "TCivetweb";
   else if (clname == "fastcgi")
      clname = "TFastCgi";
   else if (clname == "dabc")
      clname = "TDabcEngine";

   // ensure that required engine class exists before we try to create it
   TClass *engine_class = gROOT->LoadClass(clname.Data());
   if (engine_class == 0) return kFALSE;

   THttpEngine *eng = (THttpEngine *) engine_class->New();
   if (eng == 0) return kFALSE;

   eng->SetServer(this);

   if (!eng->Create(arg + 1)) {
      delete eng;
      return kFALSE;
   }

   fEngines.Add(eng);

   return kTRUE;
}

//______________________________________________________________________________
void THttpServer::SetTimer(Long_t milliSec, Bool_t mode)
{
   // create timer which will invoke ProcessRequests() function periodically
   // Timer is required to perform all actions in main ROOT thread
   // Method arguments are the same as for TTimer constructor
   // By default, sync timer with 100 ms period is created
   //
   // If milliSec == 0, no timer will be created.
   // In this case application should regularly call ProcessRequests() method.

   if (fTimer) {
      fTimer->Stop();
      delete fTimer;
      fTimer = 0;
   }
   if (milliSec > 0) {
      fTimer = new THttpTimer(milliSec, mode, this);
      fTimer->TurnOn();
   }
}

//______________________________________________________________________________
Bool_t THttpServer::VerifyFilePath(const char *fname)
{
   // Checked that filename does not contains relative path below current directory
   // Used to prevent access to files below current directory

   if ((fname == 0) || (*fname == 0)) return kFALSE;

   Int_t level = 0;

   while (*fname != 0) {

      // find next slash or backslash
      const char *next = strpbrk(fname, "/\\");
      if (next == 0) return kTRUE;

      // most important - change to parent dir
      if ((next == fname + 2) && (*fname == '.') && (*(fname + 1) == '.')) {
         fname += 3;
         level--;
         if (level < 0) return kFALSE;
         continue;
      }

      // ignore current directory
      if ((next == fname + 1) && (*fname == '.'))  {
         fname += 2;
         continue;
      }

      // ignore slash at the front
      if (next == fname) {
         fname ++;
         continue;
      }

      fname = next + 1;
      level++;
   }

   return kTRUE;
}

//______________________________________________________________________________
Bool_t THttpServer::IsFileRequested(const char *uri, TString &res) const
{
   // Verifies that request is just file name
   // File names typically contains prefix like "jsrootsys/"
   // If true, method returns real name of the file,
   // which should be delivered to the client
   // Method is thread safe and can be called from any thread

   if ((uri == 0) || (strlen(uri) == 0)) return kFALSE;

   TString fname = uri;

   TIter iter(&fLocations);
   TObject *obj(0);
   while ((obj=iter()) != 0) {
      Ssiz_t pos = fname.Index(obj->GetName());
      if (pos == kNPOS) continue;
      fname.Remove(0, pos + (strlen(obj->GetName()) - 1));
      if (!VerifyFilePath(fname.Data())) return kFALSE;
      res = obj->GetTitle();
      if ((fname[0]=='/') && (res[res.Length()-1]=='/')) res.Resize(res.Length()-1);
      res.Append(fname);
      return kTRUE;
   }

   return kFALSE;
}

//______________________________________________________________________________
Bool_t THttpServer::ExecuteHttp(THttpCallArg *arg)
{
   // Executes http request, specified in THttpCallArg structure
   // Method can be called from any thread
   // Actual execution will be done in main ROOT thread, where analysis code is running.

   if ((fMainThrdId!=0) && (fMainThrdId == TThread::SelfId())) {
      // should not happen, but one could process requests directly without any signaling

      ProcessRequest(arg);

      return kTRUE;
   }

   // add call arg to the list
   fMutex.Lock();
   fCallArgs.Add(arg);
   fMutex.UnLock();

   // and now wait until request is processed
   arg->fCond.Wait();

   return kTRUE;
}

//______________________________________________________________________________
void THttpServer::ProcessRequests()
{
   // Process requests, submitted for execution
   // Regularly invoked by THttpTimer, when somewhere in the code
   // gSystem->ProcessEvents() is called.
   // User can call serv->ProcessRequests() directly, but only from main analysis thread.

   if (fMainThrdId==0) fMainThrdId = TThread::SelfId();

   if (fMainThrdId != TThread::SelfId()) {
      Error("ProcessRequests", "Should be called only from main ROOT thread");
      return;
   }

   while (true) {
      THttpCallArg *arg = 0;

      fMutex.Lock();
      if (fCallArgs.GetSize() > 0) {
         arg = (THttpCallArg *) fCallArgs.First();
         fCallArgs.RemoveFirst();
      }
      fMutex.UnLock();

      if (arg == 0) break;

      fSniffer->SetCurrentCallArg(arg);

      try {
         ProcessRequest(arg);
         fSniffer->SetCurrentCallArg(0);
      } catch (...) {
         fSniffer->SetCurrentCallArg(0);
      }

      arg->fCond.Signal();
   }

   // regularly call Process() method of engine to let perform actions in ROOT context
   TIter iter(&fEngines);
   THttpEngine *engine = 0;
   while ((engine = (THttpEngine *)iter()) != 0)
      engine->Process();
}

//______________________________________________________________________________
void THttpServer::ProcessRequest(THttpCallArg *arg)
{
   // Process single http request
   // Depending from requested path and filename different actions will be performed.
   // In most cases information is provided by TRootSniffer class


   if (arg->fFileName.IsNull() || (arg->fFileName == "index.htm")) {

      if (fDefaultPageCont.Length() == 0) {
         Int_t len = 0;
         char *buf = ReadFileContent(fDefaultPage.Data(), len);
         if (len > 0) fDefaultPageCont.Append(buf, len);
         delete buf;
      }

      if (fDefaultPageCont.Length() == 0) {
         arg->Set404();
      } else {
         arg->fContent = fDefaultPageCont;

         // replace all references on JSROOT
         if (fJSROOT.Length() > 0) {
            TString repl = TString("=\"") + fJSROOT;
            if (!repl.EndsWith("/")) repl+="/";
            arg->fContent.ReplaceAll("=\"jsrootsys/", repl);
         }

         const char *hjsontag = "\"$$$h.json$$$\"";

         // add h.json caching
         if (arg->fContent.Index(hjsontag) != kNPOS) {
            TString h_json;
            TRootSnifferStoreJson store(h_json, kTRUE);
            const char *topname = fTopName.Data();
            if (arg->fTopName.Length() > 0) topname = arg->fTopName.Data();
            fSniffer->ScanHierarchy(topname, arg->fPathName.Data(), &store);

            arg->fContent.ReplaceAll(hjsontag, h_json);

            arg->AddHeader("Cache-Control", "private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0");
            if (arg->fQuery.Index("nozip") == kNPOS) arg->SetZipping(2);
         }
         arg->SetContentType("text/html");
      }
      return;
   }

   if (arg->fFileName == "draw.htm") {
      if (fDrawPageCont.Length() == 0) {
         Int_t len = 0;
         char *buf = ReadFileContent(fDrawPage.Data(), len);
         if (len > 0) fDrawPageCont.Append(buf, len);
         delete buf;
      }

      if (fDrawPageCont.Length() == 0) {
         arg->Set404();
      } else {
         const char *rootjsontag = "\"$$$root.json$$$\"";
         const char *hjsontag = "\"$$$h.json$$$\"";

         arg->fContent = fDrawPageCont;

         // replace all references on JSROOT
         if (fJSROOT.Length() > 0) {
            TString repl = TString("=\"") + fJSROOT;
            if (!repl.EndsWith("/")) repl+="/";
            arg->fContent.ReplaceAll("=\"jsrootsys/", repl);
         }

         if (arg->fContent.Index(hjsontag) != kNPOS) {
            TString h_json;
            TRootSnifferStoreJson store(h_json, kTRUE);
            const char *topname = fTopName.Data();
            if (arg->fTopName.Length() > 0) topname = arg->fTopName.Data();
            fSniffer->ScanHierarchy(topname, arg->fPathName.Data(), &store, kTRUE);

            arg->fContent.ReplaceAll(hjsontag, h_json);
         }

         if (arg->fContent.Index(rootjsontag) != kNPOS) {
            TString str;
            void *bindata = 0;
            Long_t bindatalen = 0;
            if (fSniffer->Produce(arg->fPathName.Data(), "root.json", "compact=3", bindata, bindatalen, str)) {
               arg->fContent.ReplaceAll(rootjsontag, str);
            }
         }
         arg->AddHeader("Cache-Control", "private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0");
         if (arg->fQuery.Index("nozip") == kNPOS) arg->SetZipping(2);
         arg->SetContentType("text/html");
      }
      return;
   }

   TString filename;
   if (IsFileRequested(arg->fFileName.Data(), filename)) {
      arg->SetFile(filename);
      return;
   }

   filename = arg->fFileName;
   Bool_t iszip = kFALSE;
   if (filename.EndsWith(".gz")) {
      filename.Resize(filename.Length() - 3);
      iszip = kTRUE;
   }

   void* bindata(0);
   Long_t bindatalen(0);

   if ((filename == "h.xml") || (filename == "get.xml"))  {

      Bool_t compact = arg->fQuery.Index("compact") != kNPOS;

      arg->fContent.Form("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
      if (!compact) arg->fContent.Append("\n");
      arg->fContent.Append("<root>");
      if (!compact) arg->fContent.Append("\n");
      {
         TRootSnifferStoreXml store(arg->fContent, compact);

         const char *topname = fTopName.Data();
         if (arg->fTopName.Length() > 0) topname = arg->fTopName.Data();
         fSniffer->ScanHierarchy(topname, arg->fPathName.Data(), &store, filename == "get.xml");
      }

      arg->fContent.Append("</root>");
      if (!compact) arg->fContent.Append("\n");

      arg->SetXml();
   } else

   if (filename == "h.json")  {
      TRootSnifferStoreJson store(arg->fContent, arg->fQuery.Index("compact") != kNPOS);
      const char *topname = fTopName.Data();
      if (arg->fTopName.Length() > 0) topname = arg->fTopName.Data();
      fSniffer->ScanHierarchy(topname, arg->fPathName.Data(), &store);
      arg->SetJson();
   } else

   if (fSniffer->Produce(arg->fPathName.Data(), filename.Data(), arg->fQuery.Data(), bindata, bindatalen, arg->fContent)) {
      if (bindata != 0) arg->SetBinData(bindata, bindatalen);

      // define content type base on extension
      arg->SetContentType(GetMimeType(filename.Data()));
   } else {
      // request is not processed
      arg->Set404();
   }

   if (arg->Is404()) return;

   if (iszip) arg->SetZipping(3);

   if (filename == "root.bin") {
      // only for binary data master version is important
      // it allows to detect if streamer info was modified
      const char *parname = fSniffer->IsStreamerInfoItem(arg->fPathName.Data()) ? "BVersion" : "MVersion";
      arg->AddHeader(parname, Form("%u", (unsigned) fSniffer->GetStreamerInfoHash()));
   }

   // try to avoid caching on the browser
   arg->AddHeader("Cache-Control", "private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0");
}

//______________________________________________________________________________
Bool_t THttpServer::Register(const char *subfolder, TObject *obj)
{
   // Register object in folders hierarchy
   //
   // See TRootSniffer::RegisterObject() for more details

   return fSniffer->RegisterObject(subfolder, obj);
}

//______________________________________________________________________________
Bool_t THttpServer::Unregister(TObject *obj)
{
   // Unregister object in folders hierarchy
   //
   // See TRootSniffer::UnregisterObject() for more details

   return fSniffer->UnregisterObject(obj);
}

//______________________________________________________________________________
void THttpServer::Restrict(const char *path, const char* options)
{
   // Restrict access to specified object
   //
   // See TRootSniffer::Restrict() for more details

   fSniffer->Restrict(path, options);
}

//______________________________________________________________________________
Bool_t THttpServer::RegisterCommand(const char *cmdname, const char *method, const char *icon)
{
   // Register command which can be executed from web interface
   //
   // As method one typically specifies string, which is executed with
   // gROOT->ProcessLine() method. For instance
   //    serv->RegisterCommand("Invoke","InvokeFunction()");
   //
   // Or one could specify any method of the object which is already registered
   // to the server. For instance:
   //     serv->Register("/", hpx);
   //     serv->RegisterCommand("/ResetHPX", "/hpx/->Reset()");
   // Here symbols '/->' separates item name from method to be executed
   //
   // One could specify additional arguments in the command with
   // syntax like %arg1%, %arg2% and so on. For example:
   //     serv->RegisterCommand("/ResetHPX", "/hpx/->SetTitle(\"%arg1%\")");
   //     serv->RegisterCommand("/RebinHPXPY", "/hpxpy/->Rebin2D(%arg1%,%arg2%)");
   // Such parameter(s) will be requested when command clicked in the browser.
   //
   // Once command is registered, one could specify icon which will appear in the browser:
   //     serv->SetIcon("/ResetHPX", "rootsys/icons/ed_execute.png");
   //
   // One also can set extra property '_fastcmd', that command appear as
   // tool button on the top of the browser tree:
   //     serv->SetItemField("/ResetHPX", "_fastcmd", "true");
   // Or it is equivalent to specifying extra argument when register command:
   //     serv->RegisterCommand("/ResetHPX", "/hpx/->Reset()", "button;rootsys/icons/ed_delete.png");

   return fSniffer->RegisterCommand(cmdname, method, icon);
}

//______________________________________________________________________________
Bool_t THttpServer::Hide(const char *foldername, Bool_t hide)
{
   // hides folder or element from web gui

   return SetItemField(foldername, "_hidden", hide ? "true" : (const char *) 0);
}

//______________________________________________________________________________
Bool_t THttpServer::SetIcon(const char *fullname, const char *iconname)
{
   // set name of icon, used in browser together with the item
   //
   // One could use images from $ROOTSYS directory like:
   //    serv->SetIcon("/ResetHPX","/rootsys/icons/ed_execute.png");

   return SetItemField(fullname, "_icon", iconname);
}

//______________________________________________________________________________
Bool_t THttpServer::CreateItem(const char *fullname, const char *title)
{
   return fSniffer->CreateItem(fullname, title);
}

//______________________________________________________________________________
Bool_t THttpServer::SetItemField(const char *fullname, const char *name, const char *value)
{
   return fSniffer->SetItemField(fullname, name, value);
}

//______________________________________________________________________________
const char *THttpServer::GetItemField(const char *fullname, const char *name)
{
   return fSniffer->GetItemField(fullname, name);
}

//______________________________________________________________________________
const char *THttpServer::GetMimeType(const char *path)
{
   // Returns MIME type base on file extension

   static const struct {
      const char *extension;
      int ext_len;
      const char *mime_type;
   } builtin_mime_types[] = {
      {".xml", 4, "text/xml"},
      {".json", 5, "application/json"},
      {".bin", 4, "application/x-binary"},
      {".gif", 4, "image/gif"},
      {".jpg", 4, "image/jpeg"},
      {".png", 4, "image/png"},
      {".html", 5, "text/html"},
      {".htm", 4, "text/html"},
      {".shtm", 5, "text/html"},
      {".shtml", 6, "text/html"},
      {".css", 4, "text/css"},
      {".js",  3, "application/x-javascript"},
      {".ico", 4, "image/x-icon"},
      {".jpeg", 5, "image/jpeg"},
      {".svg", 4, "image/svg+xml"},
      {".txt", 4, "text/plain"},
      {".torrent", 8, "application/x-bittorrent"},
      {".wav", 4, "audio/x-wav"},
      {".mp3", 4, "audio/x-mp3"},
      {".mid", 4, "audio/mid"},
      {".m3u", 4, "audio/x-mpegurl"},
      {".ogg", 4, "application/ogg"},
      {".ram", 4, "audio/x-pn-realaudio"},
      {".xslt", 5, "application/xml"},
      {".xsl", 4, "application/xml"},
      {".ra",  3, "audio/x-pn-realaudio"},
      {".doc", 4, "application/msword"},
      {".exe", 4, "application/octet-stream"},
      {".zip", 4, "application/x-zip-compressed"},
      {".xls", 4, "application/excel"},
      {".tgz", 4, "application/x-tar-gz"},
      {".tar", 4, "application/x-tar"},
      {".gz",  3, "application/x-gunzip"},
      {".arj", 4, "application/x-arj-compressed"},
      {".rar", 4, "application/x-arj-compressed"},
      {".rtf", 4, "application/rtf"},
      {".pdf", 4, "application/pdf"},
      {".swf", 4, "application/x-shockwave-flash"},
      {".mpg", 4, "video/mpeg"},
      {".webm", 5, "video/webm"},
      {".mpeg", 5, "video/mpeg"},
      {".mov", 4, "video/quicktime"},
      {".mp4", 4, "video/mp4"},
      {".m4v", 4, "video/x-m4v"},
      {".asf", 4, "video/x-ms-asf"},
      {".avi", 4, "video/x-msvideo"},
      {".bmp", 4, "image/bmp"},
      {".ttf", 4, "application/x-font-ttf"},
      {NULL,  0, NULL}
   };

   int path_len = strlen(path);

   for (int i = 0; builtin_mime_types[i].extension != NULL; i++) {
      if (path_len <= builtin_mime_types[i].ext_len) continue;
      const char *ext = path + (path_len - builtin_mime_types[i].ext_len);
      if (strcmp(ext, builtin_mime_types[i].extension) == 0) {
         return builtin_mime_types[i].mime_type;
      }
   }

   return "text/plain";
}

//______________________________________________________________________________
char *THttpServer::ReadFileContent(const char *filename, Int_t &len)
{
   // reads file content

   len = 0;

   std::ifstream is(filename);
   if (!is) return 0;

   is.seekg(0, is.end);
   len = is.tellg();
   is.seekg(0, is.beg);

   char *buf = (char *) malloc(len);
   is.read(buf, len);
   if (!is) {
      free(buf);
      len = 0;
      return 0;
   }

   return buf;
}
 THttpServer.cxx:1
 THttpServer.cxx:2
 THttpServer.cxx:3
 THttpServer.cxx:4
 THttpServer.cxx:5
 THttpServer.cxx:6
 THttpServer.cxx:7
 THttpServer.cxx:8
 THttpServer.cxx:9
 THttpServer.cxx:10
 THttpServer.cxx:11
 THttpServer.cxx:12
 THttpServer.cxx:13
 THttpServer.cxx:14
 THttpServer.cxx:15
 THttpServer.cxx:16
 THttpServer.cxx:17
 THttpServer.cxx:18
 THttpServer.cxx:19
 THttpServer.cxx:20
 THttpServer.cxx:21
 THttpServer.cxx:22
 THttpServer.cxx:23
 THttpServer.cxx:24
 THttpServer.cxx:25
 THttpServer.cxx:26
 THttpServer.cxx:27
 THttpServer.cxx:28
 THttpServer.cxx:29
 THttpServer.cxx:30
 THttpServer.cxx:31
 THttpServer.cxx:32
 THttpServer.cxx:33
 THttpServer.cxx:34
 THttpServer.cxx:35
 THttpServer.cxx:36
 THttpServer.cxx:37
 THttpServer.cxx:38
 THttpServer.cxx:39
 THttpServer.cxx:40
 THttpServer.cxx:41
 THttpServer.cxx:42
 THttpServer.cxx:43
 THttpServer.cxx:44
 THttpServer.cxx:45
 THttpServer.cxx:46
 THttpServer.cxx:47
 THttpServer.cxx:48
 THttpServer.cxx:49
 THttpServer.cxx:50
 THttpServer.cxx:51
 THttpServer.cxx:52
 THttpServer.cxx:53
 THttpServer.cxx:54
 THttpServer.cxx:55
 THttpServer.cxx:56
 THttpServer.cxx:57
 THttpServer.cxx:58
 THttpServer.cxx:59
 THttpServer.cxx:60
 THttpServer.cxx:61
 THttpServer.cxx:62
 THttpServer.cxx:63
 THttpServer.cxx:64
 THttpServer.cxx:65
 THttpServer.cxx:66
 THttpServer.cxx:67
 THttpServer.cxx:68
 THttpServer.cxx:69
 THttpServer.cxx:70
 THttpServer.cxx:71
 THttpServer.cxx:72
 THttpServer.cxx:73
 THttpServer.cxx:74
 THttpServer.cxx:75
 THttpServer.cxx:76
 THttpServer.cxx:77
 THttpServer.cxx:78
 THttpServer.cxx:79
 THttpServer.cxx:80
 THttpServer.cxx:81
 THttpServer.cxx:82
 THttpServer.cxx:83
 THttpServer.cxx:84
 THttpServer.cxx:85
 THttpServer.cxx:86
 THttpServer.cxx:87
 THttpServer.cxx:88
 THttpServer.cxx:89
 THttpServer.cxx:90
 THttpServer.cxx:91
 THttpServer.cxx:92
 THttpServer.cxx:93
 THttpServer.cxx:94
 THttpServer.cxx:95
 THttpServer.cxx:96
 THttpServer.cxx:97
 THttpServer.cxx:98
 THttpServer.cxx:99
 THttpServer.cxx:100
 THttpServer.cxx:101
 THttpServer.cxx:102
 THttpServer.cxx:103
 THttpServer.cxx:104
 THttpServer.cxx:105
 THttpServer.cxx:106
 THttpServer.cxx:107
 THttpServer.cxx:108
 THttpServer.cxx:109
 THttpServer.cxx:110
 THttpServer.cxx:111
 THttpServer.cxx:112
 THttpServer.cxx:113
 THttpServer.cxx:114
 THttpServer.cxx:115
 THttpServer.cxx:116
 THttpServer.cxx:117
 THttpServer.cxx:118
 THttpServer.cxx:119
 THttpServer.cxx:120
 THttpServer.cxx:121
 THttpServer.cxx:122
 THttpServer.cxx:123
 THttpServer.cxx:124
 THttpServer.cxx:125
 THttpServer.cxx:126
 THttpServer.cxx:127
 THttpServer.cxx:128
 THttpServer.cxx:129
 THttpServer.cxx:130
 THttpServer.cxx:131
 THttpServer.cxx:132
 THttpServer.cxx:133
 THttpServer.cxx:134
 THttpServer.cxx:135
 THttpServer.cxx:136
 THttpServer.cxx:137
 THttpServer.cxx:138
 THttpServer.cxx:139
 THttpServer.cxx:140
 THttpServer.cxx:141
 THttpServer.cxx:142
 THttpServer.cxx:143
 THttpServer.cxx:144
 THttpServer.cxx:145
 THttpServer.cxx:146
 THttpServer.cxx:147
 THttpServer.cxx:148
 THttpServer.cxx:149
 THttpServer.cxx:150
 THttpServer.cxx:151
 THttpServer.cxx:152
 THttpServer.cxx:153
 THttpServer.cxx:154
 THttpServer.cxx:155
 THttpServer.cxx:156
 THttpServer.cxx:157
 THttpServer.cxx:158
 THttpServer.cxx:159
 THttpServer.cxx:160
 THttpServer.cxx:161
 THttpServer.cxx:162
 THttpServer.cxx:163
 THttpServer.cxx:164
 THttpServer.cxx:165
 THttpServer.cxx:166
 THttpServer.cxx:167
 THttpServer.cxx:168
 THttpServer.cxx:169
 THttpServer.cxx:170
 THttpServer.cxx:171
 THttpServer.cxx:172
 THttpServer.cxx:173
 THttpServer.cxx:174
 THttpServer.cxx:175
 THttpServer.cxx:176
 THttpServer.cxx:177
 THttpServer.cxx:178
 THttpServer.cxx:179
 THttpServer.cxx:180
 THttpServer.cxx:181
 THttpServer.cxx:182
 THttpServer.cxx:183
 THttpServer.cxx:184
 THttpServer.cxx:185
 THttpServer.cxx:186
 THttpServer.cxx:187
 THttpServer.cxx:188
 THttpServer.cxx:189
 THttpServer.cxx:190
 THttpServer.cxx:191
 THttpServer.cxx:192
 THttpServer.cxx:193
 THttpServer.cxx:194
 THttpServer.cxx:195
 THttpServer.cxx:196
 THttpServer.cxx:197
 THttpServer.cxx:198
 THttpServer.cxx:199
 THttpServer.cxx:200
 THttpServer.cxx:201
 THttpServer.cxx:202
 THttpServer.cxx:203
 THttpServer.cxx:204
 THttpServer.cxx:205
 THttpServer.cxx:206
 THttpServer.cxx:207
 THttpServer.cxx:208
 THttpServer.cxx:209
 THttpServer.cxx:210
 THttpServer.cxx:211
 THttpServer.cxx:212
 THttpServer.cxx:213
 THttpServer.cxx:214
 THttpServer.cxx:215
 THttpServer.cxx:216
 THttpServer.cxx:217
 THttpServer.cxx:218
 THttpServer.cxx:219
 THttpServer.cxx:220
 THttpServer.cxx:221
 THttpServer.cxx:222
 THttpServer.cxx:223
 THttpServer.cxx:224
 THttpServer.cxx:225
 THttpServer.cxx:226
 THttpServer.cxx:227
 THttpServer.cxx:228
 THttpServer.cxx:229
 THttpServer.cxx:230
 THttpServer.cxx:231
 THttpServer.cxx:232
 THttpServer.cxx:233
 THttpServer.cxx:234
 THttpServer.cxx:235
 THttpServer.cxx:236
 THttpServer.cxx:237
 THttpServer.cxx:238
 THttpServer.cxx:239
 THttpServer.cxx:240
 THttpServer.cxx:241
 THttpServer.cxx:242
 THttpServer.cxx:243
 THttpServer.cxx:244
 THttpServer.cxx:245
 THttpServer.cxx:246
 THttpServer.cxx:247
 THttpServer.cxx:248
 THttpServer.cxx:249
 THttpServer.cxx:250
 THttpServer.cxx:251
 THttpServer.cxx:252
 THttpServer.cxx:253
 THttpServer.cxx:254
 THttpServer.cxx:255
 THttpServer.cxx:256
 THttpServer.cxx:257
 THttpServer.cxx:258
 THttpServer.cxx:259
 THttpServer.cxx:260
 THttpServer.cxx:261
 THttpServer.cxx:262
 THttpServer.cxx:263
 THttpServer.cxx:264
 THttpServer.cxx:265
 THttpServer.cxx:266
 THttpServer.cxx:267
 THttpServer.cxx:268
 THttpServer.cxx:269
 THttpServer.cxx:270
 THttpServer.cxx:271
 THttpServer.cxx:272
 THttpServer.cxx:273
 THttpServer.cxx:274
 THttpServer.cxx:275
 THttpServer.cxx:276
 THttpServer.cxx:277
 THttpServer.cxx:278
 THttpServer.cxx:279
 THttpServer.cxx:280
 THttpServer.cxx:281
 THttpServer.cxx:282
 THttpServer.cxx:283
 THttpServer.cxx:284
 THttpServer.cxx:285
 THttpServer.cxx:286
 THttpServer.cxx:287
 THttpServer.cxx:288
 THttpServer.cxx:289
 THttpServer.cxx:290
 THttpServer.cxx:291
 THttpServer.cxx:292
 THttpServer.cxx:293
 THttpServer.cxx:294
 THttpServer.cxx:295
 THttpServer.cxx:296
 THttpServer.cxx:297
 THttpServer.cxx:298
 THttpServer.cxx:299
 THttpServer.cxx:300
 THttpServer.cxx:301
 THttpServer.cxx:302
 THttpServer.cxx:303
 THttpServer.cxx:304
 THttpServer.cxx:305
 THttpServer.cxx:306
 THttpServer.cxx:307
 THttpServer.cxx:308
 THttpServer.cxx:309
 THttpServer.cxx:310
 THttpServer.cxx:311
 THttpServer.cxx:312
 THttpServer.cxx:313
 THttpServer.cxx:314
 THttpServer.cxx:315
 THttpServer.cxx:316
 THttpServer.cxx:317
 THttpServer.cxx:318
 THttpServer.cxx:319
 THttpServer.cxx:320
 THttpServer.cxx:321
 THttpServer.cxx:322
 THttpServer.cxx:323
 THttpServer.cxx:324
 THttpServer.cxx:325
 THttpServer.cxx:326
 THttpServer.cxx:327
 THttpServer.cxx:328
 THttpServer.cxx:329
 THttpServer.cxx:330
 THttpServer.cxx:331
 THttpServer.cxx:332
 THttpServer.cxx:333
 THttpServer.cxx:334
 THttpServer.cxx:335
 THttpServer.cxx:336
 THttpServer.cxx:337
 THttpServer.cxx:338
 THttpServer.cxx:339
 THttpServer.cxx:340
 THttpServer.cxx:341
 THttpServer.cxx:342
 THttpServer.cxx:343
 THttpServer.cxx:344
 THttpServer.cxx:345
 THttpServer.cxx:346
 THttpServer.cxx:347
 THttpServer.cxx:348
 THttpServer.cxx:349
 THttpServer.cxx:350
 THttpServer.cxx:351
 THttpServer.cxx:352
 THttpServer.cxx:353
 THttpServer.cxx:354
 THttpServer.cxx:355
 THttpServer.cxx:356
 THttpServer.cxx:357
 THttpServer.cxx:358
 THttpServer.cxx:359
 THttpServer.cxx:360
 THttpServer.cxx:361
 THttpServer.cxx:362
 THttpServer.cxx:363
 THttpServer.cxx:364
 THttpServer.cxx:365
 THttpServer.cxx:366
 THttpServer.cxx:367
 THttpServer.cxx:368
 THttpServer.cxx:369
 THttpServer.cxx:370
 THttpServer.cxx:371
 THttpServer.cxx:372
 THttpServer.cxx:373
 THttpServer.cxx:374
 THttpServer.cxx:375
 THttpServer.cxx:376
 THttpServer.cxx:377
 THttpServer.cxx:378
 THttpServer.cxx:379
 THttpServer.cxx:380
 THttpServer.cxx:381
 THttpServer.cxx:382
 THttpServer.cxx:383
 THttpServer.cxx:384
 THttpServer.cxx:385
 THttpServer.cxx:386
 THttpServer.cxx:387
 THttpServer.cxx:388
 THttpServer.cxx:389
 THttpServer.cxx:390
 THttpServer.cxx:391
 THttpServer.cxx:392
 THttpServer.cxx:393
 THttpServer.cxx:394
 THttpServer.cxx:395
 THttpServer.cxx:396
 THttpServer.cxx:397
 THttpServer.cxx:398
 THttpServer.cxx:399
 THttpServer.cxx:400
 THttpServer.cxx:401
 THttpServer.cxx:402
 THttpServer.cxx:403
 THttpServer.cxx:404
 THttpServer.cxx:405
 THttpServer.cxx:406
 THttpServer.cxx:407
 THttpServer.cxx:408
 THttpServer.cxx:409
 THttpServer.cxx:410
 THttpServer.cxx:411
 THttpServer.cxx:412
 THttpServer.cxx:413
 THttpServer.cxx:414
 THttpServer.cxx:415
 THttpServer.cxx:416
 THttpServer.cxx:417
 THttpServer.cxx:418
 THttpServer.cxx:419
 THttpServer.cxx:420
 THttpServer.cxx:421
 THttpServer.cxx:422
 THttpServer.cxx:423
 THttpServer.cxx:424
 THttpServer.cxx:425
 THttpServer.cxx:426
 THttpServer.cxx:427
 THttpServer.cxx:428
 THttpServer.cxx:429
 THttpServer.cxx:430
 THttpServer.cxx:431
 THttpServer.cxx:432
 THttpServer.cxx:433
 THttpServer.cxx:434
 THttpServer.cxx:435
 THttpServer.cxx:436
 THttpServer.cxx:437
 THttpServer.cxx:438
 THttpServer.cxx:439
 THttpServer.cxx:440
 THttpServer.cxx:441
 THttpServer.cxx:442
 THttpServer.cxx:443
 THttpServer.cxx:444
 THttpServer.cxx:445
 THttpServer.cxx:446
 THttpServer.cxx:447
 THttpServer.cxx:448
 THttpServer.cxx:449
 THttpServer.cxx:450
 THttpServer.cxx:451
 THttpServer.cxx:452
 THttpServer.cxx:453
 THttpServer.cxx:454
 THttpServer.cxx:455
 THttpServer.cxx:456
 THttpServer.cxx:457
 THttpServer.cxx:458
 THttpServer.cxx:459
 THttpServer.cxx:460
 THttpServer.cxx:461
 THttpServer.cxx:462
 THttpServer.cxx:463
 THttpServer.cxx:464
 THttpServer.cxx:465
 THttpServer.cxx:466
 THttpServer.cxx:467
 THttpServer.cxx:468
 THttpServer.cxx:469
 THttpServer.cxx:470
 THttpServer.cxx:471
 THttpServer.cxx:472
 THttpServer.cxx:473
 THttpServer.cxx:474
 THttpServer.cxx:475
 THttpServer.cxx:476
 THttpServer.cxx:477
 THttpServer.cxx:478
 THttpServer.cxx:479
 THttpServer.cxx:480
 THttpServer.cxx:481
 THttpServer.cxx:482
 THttpServer.cxx:483
 THttpServer.cxx:484
 THttpServer.cxx:485
 THttpServer.cxx:486
 THttpServer.cxx:487
 THttpServer.cxx:488
 THttpServer.cxx:489
 THttpServer.cxx:490
 THttpServer.cxx:491
 THttpServer.cxx:492
 THttpServer.cxx:493
 THttpServer.cxx:494
 THttpServer.cxx:495
 THttpServer.cxx:496
 THttpServer.cxx:497
 THttpServer.cxx:498
 THttpServer.cxx:499
 THttpServer.cxx:500
 THttpServer.cxx:501
 THttpServer.cxx:502
 THttpServer.cxx:503
 THttpServer.cxx:504
 THttpServer.cxx:505
 THttpServer.cxx:506
 THttpServer.cxx:507
 THttpServer.cxx:508
 THttpServer.cxx:509
 THttpServer.cxx:510
 THttpServer.cxx:511
 THttpServer.cxx:512
 THttpServer.cxx:513
 THttpServer.cxx:514
 THttpServer.cxx:515
 THttpServer.cxx:516
 THttpServer.cxx:517
 THttpServer.cxx:518
 THttpServer.cxx:519
 THttpServer.cxx:520
 THttpServer.cxx:521
 THttpServer.cxx:522
 THttpServer.cxx:523
 THttpServer.cxx:524
 THttpServer.cxx:525
 THttpServer.cxx:526
 THttpServer.cxx:527
 THttpServer.cxx:528
 THttpServer.cxx:529
 THttpServer.cxx:530
 THttpServer.cxx:531
 THttpServer.cxx:532
 THttpServer.cxx:533
 THttpServer.cxx:534
 THttpServer.cxx:535
 THttpServer.cxx:536
 THttpServer.cxx:537
 THttpServer.cxx:538
 THttpServer.cxx:539
 THttpServer.cxx:540
 THttpServer.cxx:541
 THttpServer.cxx:542
 THttpServer.cxx:543
 THttpServer.cxx:544
 THttpServer.cxx:545
 THttpServer.cxx:546
 THttpServer.cxx:547
 THttpServer.cxx:548
 THttpServer.cxx:549
 THttpServer.cxx:550
 THttpServer.cxx:551
 THttpServer.cxx:552
 THttpServer.cxx:553
 THttpServer.cxx:554
 THttpServer.cxx:555
 THttpServer.cxx:556
 THttpServer.cxx:557
 THttpServer.cxx:558
 THttpServer.cxx:559
 THttpServer.cxx:560
 THttpServer.cxx:561
 THttpServer.cxx:562
 THttpServer.cxx:563
 THttpServer.cxx:564
 THttpServer.cxx:565
 THttpServer.cxx:566
 THttpServer.cxx:567
 THttpServer.cxx:568
 THttpServer.cxx:569
 THttpServer.cxx:570
 THttpServer.cxx:571
 THttpServer.cxx:572
 THttpServer.cxx:573
 THttpServer.cxx:574
 THttpServer.cxx:575
 THttpServer.cxx:576
 THttpServer.cxx:577
 THttpServer.cxx:578
 THttpServer.cxx:579
 THttpServer.cxx:580
 THttpServer.cxx:581
 THttpServer.cxx:582
 THttpServer.cxx:583
 THttpServer.cxx:584
 THttpServer.cxx:585
 THttpServer.cxx:586
 THttpServer.cxx:587
 THttpServer.cxx:588
 THttpServer.cxx:589
 THttpServer.cxx:590
 THttpServer.cxx:591
 THttpServer.cxx:592
 THttpServer.cxx:593
 THttpServer.cxx:594
 THttpServer.cxx:595
 THttpServer.cxx:596
 THttpServer.cxx:597
 THttpServer.cxx:598
 THttpServer.cxx:599
 THttpServer.cxx:600
 THttpServer.cxx:601
 THttpServer.cxx:602
 THttpServer.cxx:603
 THttpServer.cxx:604
 THttpServer.cxx:605
 THttpServer.cxx:606
 THttpServer.cxx:607
 THttpServer.cxx:608
 THttpServer.cxx:609
 THttpServer.cxx:610
 THttpServer.cxx:611
 THttpServer.cxx:612
 THttpServer.cxx:613
 THttpServer.cxx:614
 THttpServer.cxx:615
 THttpServer.cxx:616
 THttpServer.cxx:617
 THttpServer.cxx:618
 THttpServer.cxx:619
 THttpServer.cxx:620
 THttpServer.cxx:621
 THttpServer.cxx:622
 THttpServer.cxx:623
 THttpServer.cxx:624
 THttpServer.cxx:625
 THttpServer.cxx:626
 THttpServer.cxx:627
 THttpServer.cxx:628
 THttpServer.cxx:629
 THttpServer.cxx:630
 THttpServer.cxx:631
 THttpServer.cxx:632
 THttpServer.cxx:633
 THttpServer.cxx:634
 THttpServer.cxx:635
 THttpServer.cxx:636
 THttpServer.cxx:637
 THttpServer.cxx:638
 THttpServer.cxx:639
 THttpServer.cxx:640
 THttpServer.cxx:641
 THttpServer.cxx:642
 THttpServer.cxx:643
 THttpServer.cxx:644
 THttpServer.cxx:645
 THttpServer.cxx:646
 THttpServer.cxx:647
 THttpServer.cxx:648
 THttpServer.cxx:649
 THttpServer.cxx:650
 THttpServer.cxx:651
 THttpServer.cxx:652
 THttpServer.cxx:653
 THttpServer.cxx:654
 THttpServer.cxx:655
 THttpServer.cxx:656
 THttpServer.cxx:657
 THttpServer.cxx:658
 THttpServer.cxx:659
 THttpServer.cxx:660
 THttpServer.cxx:661
 THttpServer.cxx:662
 THttpServer.cxx:663
 THttpServer.cxx:664
 THttpServer.cxx:665
 THttpServer.cxx:666
 THttpServer.cxx:667
 THttpServer.cxx:668
 THttpServer.cxx:669
 THttpServer.cxx:670
 THttpServer.cxx:671
 THttpServer.cxx:672
 THttpServer.cxx:673
 THttpServer.cxx:674
 THttpServer.cxx:675
 THttpServer.cxx:676
 THttpServer.cxx:677
 THttpServer.cxx:678
 THttpServer.cxx:679
 THttpServer.cxx:680
 THttpServer.cxx:681
 THttpServer.cxx:682
 THttpServer.cxx:683
 THttpServer.cxx:684
 THttpServer.cxx:685
 THttpServer.cxx:686
 THttpServer.cxx:687
 THttpServer.cxx:688
 THttpServer.cxx:689
 THttpServer.cxx:690
 THttpServer.cxx:691
 THttpServer.cxx:692
 THttpServer.cxx:693
 THttpServer.cxx:694
 THttpServer.cxx:695
 THttpServer.cxx:696
 THttpServer.cxx:697
 THttpServer.cxx:698
 THttpServer.cxx:699
 THttpServer.cxx:700
 THttpServer.cxx:701
 THttpServer.cxx:702
 THttpServer.cxx:703
 THttpServer.cxx:704
 THttpServer.cxx:705
 THttpServer.cxx:706
 THttpServer.cxx:707
 THttpServer.cxx:708
 THttpServer.cxx:709
 THttpServer.cxx:710
 THttpServer.cxx:711
 THttpServer.cxx:712
 THttpServer.cxx:713
 THttpServer.cxx:714
 THttpServer.cxx:715
 THttpServer.cxx:716
 THttpServer.cxx:717
 THttpServer.cxx:718
 THttpServer.cxx:719
 THttpServer.cxx:720
 THttpServer.cxx:721
 THttpServer.cxx:722
 THttpServer.cxx:723
 THttpServer.cxx:724
 THttpServer.cxx:725
 THttpServer.cxx:726
 THttpServer.cxx:727
 THttpServer.cxx:728
 THttpServer.cxx:729
 THttpServer.cxx:730
 THttpServer.cxx:731
 THttpServer.cxx:732
 THttpServer.cxx:733
 THttpServer.cxx:734
 THttpServer.cxx:735
 THttpServer.cxx:736
 THttpServer.cxx:737
 THttpServer.cxx:738
 THttpServer.cxx:739
 THttpServer.cxx:740
 THttpServer.cxx:741
 THttpServer.cxx:742
 THttpServer.cxx:743
 THttpServer.cxx:744
 THttpServer.cxx:745
 THttpServer.cxx:746
 THttpServer.cxx:747
 THttpServer.cxx:748
 THttpServer.cxx:749
 THttpServer.cxx:750
 THttpServer.cxx:751
 THttpServer.cxx:752
 THttpServer.cxx:753
 THttpServer.cxx:754
 THttpServer.cxx:755
 THttpServer.cxx:756
 THttpServer.cxx:757
 THttpServer.cxx:758
 THttpServer.cxx:759
 THttpServer.cxx:760
 THttpServer.cxx:761
 THttpServer.cxx:762
 THttpServer.cxx:763
 THttpServer.cxx:764
 THttpServer.cxx:765
 THttpServer.cxx:766
 THttpServer.cxx:767
 THttpServer.cxx:768
 THttpServer.cxx:769
 THttpServer.cxx:770
 THttpServer.cxx:771
 THttpServer.cxx:772
 THttpServer.cxx:773
 THttpServer.cxx:774
 THttpServer.cxx:775
 THttpServer.cxx:776
 THttpServer.cxx:777
 THttpServer.cxx:778
 THttpServer.cxx:779
 THttpServer.cxx:780
 THttpServer.cxx:781
 THttpServer.cxx:782
 THttpServer.cxx:783
 THttpServer.cxx:784
 THttpServer.cxx:785
 THttpServer.cxx:786
 THttpServer.cxx:787
 THttpServer.cxx:788
 THttpServer.cxx:789
 THttpServer.cxx:790
 THttpServer.cxx:791
 THttpServer.cxx:792
 THttpServer.cxx:793
 THttpServer.cxx:794
 THttpServer.cxx:795
 THttpServer.cxx:796
 THttpServer.cxx:797
 THttpServer.cxx:798
 THttpServer.cxx:799
 THttpServer.cxx:800
 THttpServer.cxx:801
 THttpServer.cxx:802
 THttpServer.cxx:803
 THttpServer.cxx:804
 THttpServer.cxx:805
 THttpServer.cxx:806
 THttpServer.cxx:807
 THttpServer.cxx:808
 THttpServer.cxx:809
 THttpServer.cxx:810
 THttpServer.cxx:811
 THttpServer.cxx:812
 THttpServer.cxx:813
 THttpServer.cxx:814
 THttpServer.cxx:815
 THttpServer.cxx:816
 THttpServer.cxx:817
 THttpServer.cxx:818
 THttpServer.cxx:819
 THttpServer.cxx:820
 THttpServer.cxx:821
 THttpServer.cxx:822
 THttpServer.cxx:823
 THttpServer.cxx:824
 THttpServer.cxx:825
 THttpServer.cxx:826
 THttpServer.cxx:827
 THttpServer.cxx:828
 THttpServer.cxx:829
 THttpServer.cxx:830
 THttpServer.cxx:831
 THttpServer.cxx:832
 THttpServer.cxx:833
 THttpServer.cxx:834
 THttpServer.cxx:835
 THttpServer.cxx:836
 THttpServer.cxx:837
 THttpServer.cxx:838
 THttpServer.cxx:839
 THttpServer.cxx:840
 THttpServer.cxx:841
 THttpServer.cxx:842
 THttpServer.cxx:843
 THttpServer.cxx:844
 THttpServer.cxx:845
 THttpServer.cxx:846
 THttpServer.cxx:847
 THttpServer.cxx:848
 THttpServer.cxx:849
 THttpServer.cxx:850
 THttpServer.cxx:851
 THttpServer.cxx:852
 THttpServer.cxx:853
 THttpServer.cxx:854
 THttpServer.cxx:855
 THttpServer.cxx:856
 THttpServer.cxx:857
 THttpServer.cxx:858
 THttpServer.cxx:859
 THttpServer.cxx:860
 THttpServer.cxx:861
 THttpServer.cxx:862
 THttpServer.cxx:863
 THttpServer.cxx:864
 THttpServer.cxx:865
 THttpServer.cxx:866
 THttpServer.cxx:867
 THttpServer.cxx:868
 THttpServer.cxx:869
 THttpServer.cxx:870
 THttpServer.cxx:871
 THttpServer.cxx:872
 THttpServer.cxx:873
 THttpServer.cxx:874
 THttpServer.cxx:875
 THttpServer.cxx:876
 THttpServer.cxx:877
 THttpServer.cxx:878
 THttpServer.cxx:879
 THttpServer.cxx:880
 THttpServer.cxx:881
 THttpServer.cxx:882
 THttpServer.cxx:883
 THttpServer.cxx:884
 THttpServer.cxx:885
 THttpServer.cxx:886