// $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 "THttpEngine.h"
#include "TRootSniffer.h"
#include "TRootSnifferStore.h"

#include <string>
#include <cstdlib>

//extern "C" void R__zipMultipleAlgorithm(int cxlevel, int *srcsize, char *src, int *tgtsize, char *tgt, int *irep, int compressionAlgorithm);
//const Int_t kMAXBUF = 0xffffff;


//////////////////////////////////////////////////////////////////////////
//                                                                      //
// THttpCallArg                                                         //
//                                                                      //
// Contains arguments for single HTTP call                              //
// Must be used in THttpEngine to process icomming http requests        //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

//______________________________________________________________________________
THttpCallArg::THttpCallArg() :
   TObject(),
   fTopName(),
   fPathName(),
   fFileName(),
   fQuery(),
   fCond(),
   fContentType(),
   fContentEncoding(),
   fContent(),
   fBinData(0),
   fBinDataLength(0)
{
   // constructor
}

//______________________________________________________________________________
THttpCallArg::~THttpCallArg()
{
   // destructor

   if (fBinData) {
      free(fBinData);
      fBinData = 0;
   }
}

//______________________________________________________________________________
void THttpCallArg::SetPathAndFileName(const char *fullpath)
{
   // set complete path of requested http element
   // For instance, it could be "/folder/subfolder/get.bin"
   // Here "/folder/subfolder/" is element path and "get.bin" requested file.
   // One could set path and file name separately

   fPathName.Clear();
   fFileName.Clear();

   if (fullpath == 0) return;

   const char *rslash = strrchr(fullpath, '/');
   if (rslash == 0) {
      fFileName = fullpath;
   } else {
      while ((fullpath != rslash) && (*fullpath == '/')) fullpath++;
      fPathName.Append(fullpath, rslash - fullpath);
      if (fPathName == "/") fPathName.Clear();
      fFileName = rslash + 1;
   }
}

//______________________________________________________________________________
void THttpCallArg::FillHttpHeader(TString &hdr, Bool_t normal)
{
   const char *header = normal ? "HTTP/1.1" : "Status:";

   if ((fContentType.Length() == 0) || Is404()) {
      hdr.Form("%s 404 Not Found\r\n"
               "Content-Length: 0\r\n"
               "Connection: close\r\n\r\n", header);
      return;
   }

   hdr.Form("%s 200 OK\r\n"
            "Content-Type: %s\r\n"
            "Connection: keep-alive\r\n"
            "Content-Length: %ld\r\n",
            header,
            GetContentType(),
            GetContentLength());
   if (fContentEncoding.Length() > 0)
      hdr.Append(TString::Format("Content-Encoding: %s\r\n", fContentEncoding.Data()));

   hdr.Append("\r\n");
}


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

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// THttpTimer                                                           //
//                                                                      //
// Specialized timer for THttpServer                                    //
// Main aim - provide 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 server for arbitrary ROOT analysis                            //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

//______________________________________________________________________________
THttpServer::THttpServer(const char *engine) :
   TNamed("http", "ROOT http server"),
   fEngines(),
   fTimer(0),
   fSniffer(0),
   fMainThrdId(0),
   fHttpSys(),
   fRootSys(),
   fJSRootIOSys(),
   fTopName("ROOT"),
   fMutex(),
   fCallArgs()
{
   // constructor

   // Checks where ROOT sources (via $ROOTSYS variable)
   // Sources are required to locate files and scripts,
   // which will be provided to the web clients by request

   fMainThrdId = TThread::SelfId();

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

   const char *rootsys = gSystem->Getenv("ROOTSYS");
   if (rootsys != 0) fRootSys = rootsys;

#ifdef COMPILED_WITH_DABC

   const char *dabcsys = gSystem->Getenv("DABCSYS");
   if (dabcsys != 0) fHttpSys = TString::Format("%s/plugins/http", dabcsys);

#else
   if (fRootSys.Length() > 0)
      fHttpSys = TString::Format("%s/etc/http", fRootSys.Data());
#endif

   if (fHttpSys.IsNull()) fHttpSys = ".";

   const char *jsrootiosys = gSystem->Getenv("JSROOTIOSYS");
   if (jsrootiosys != 0)
      fJSRootIOSys = jsrootiosys;
   else
      fJSRootIOSys = fHttpSys + "/JSRootIO";

   fDefaultPage = fHttpSys + "/files/main.htm";
   fDrawPage = fHttpSys + "/files/single.htm";

   SetSniffer(new TRootSniffer("sniff"));

   // start timer
   SetTimer(100, kTRUE);

   CreateEngine(engine);
}

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

   fEngines.Delete();

   SetSniffer(0);

   SetTimer(0);
}

//______________________________________________________________________________
void THttpServer::SetSniffer(TRootSniffer *sniff)
{
   if (fSniffer) delete fSniffer;
   fSniffer = sniff;
}

//______________________________________________________________________________
Bool_t THttpServer::CreateEngine(const char *engine)
{
   // factory method to create different http engine
   // At the moment two engine kinds are supported:
   //  civetweb (default) and fastcgi
   // Examples:
   //   "civetweb:8090" or "http:8090" or ":8090" - creates civetweb web server with http port 8090
   //   "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::IsFileRequested(const char *uri, TString &res) const
{
   // verifies that request just file name
   // File names typically contains prefix like "httpsys/" or "jsrootiosys/"
   // 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;

   std::string fname = uri;
   size_t pos = fname.rfind("httpsys/");
   if (pos != std::string::npos) {
      fname.erase(0, pos + 7);
      res = fHttpSys + fname.c_str();
      return kTRUE;
   }

   if (!fRootSys.IsNull()) {
      pos = fname.rfind("rootsys/");
      if (pos != std::string::npos) {
         fname.erase(0, pos + 7);
         res = fRootSys + fname.c_str();
         return kTRUE;
      }
   }

   if (!fJSRootIOSys.IsNull()) {
      pos = fname.rfind("jsrootiosys/");
      if (pos != std::string::npos) {
         fname.erase(0, pos + 11);
         res = fJSRootIOSys + fname.c_str();
         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 == 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.

   // Info("ProcessRequests", "Server %p in main %ld curr %ld", this, (long) fMainThrdId, (long)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;

      ProcessRequest(arg);

      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

   // Info("ProcessRequest", "Path %s File %s", arg->fPathName.Data(), arg->fFileName.Data());

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

      Bool_t usedefaultpage = kTRUE;

      if (!fSniffer->CanExploreItem(arg->fPathName.Data()) &&
            fSniffer->CanDrawItem(arg->fPathName.Data())) usedefaultpage = kFALSE;

      if (usedefaultpage)
         arg->fContent = fDefaultPage;
      else
         arg->fContent = fDrawPage;

      arg->SetFile();

      return;
   }

   TString buf = arg->fFileName;

   if (IsFileRequested(arg->fFileName.Data(), buf)) {
      arg->fContent = buf;
      arg->SetFile();
      return;
   }

   if (arg->fFileName == "h.xml")  {

      arg->fContent.Form(
         "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
         "<dabc version=\"2\" xmlns:dabc=\"http://dabc.gsi.de/xhtml\" path=\"%s\">\n", arg->fPathName.Data());

      {
         TRootSnifferStoreXml store(arg->fContent);

         const char *topname = fTopName.Data();
         if (arg->fTopName.Length() > 0) topname = arg->fTopName.Data();

         fSniffer->ScanHierarchy(topname, arg->fPathName.Data(), &store);
      }

      arg->fContent.Append("</dabc>\n");
      arg->SetXml();

      return;
   }

   if (arg->fFileName == "h.json")  {

      arg->fContent.Append("{\n");

      {
         TRootSnifferStoreJson store(arg->fContent);

         const char *topname = fTopName.Data();
         if (arg->fTopName.Length() > 0) topname = arg->fTopName.Data();

         fSniffer->ScanHierarchy(topname, arg->fPathName.Data(), &store);
      }

      arg->fContent.Append("\n}\n");
      arg->SetJson();

      return;
   }

   if (fSniffer->Produce(arg->fPathName.Data(), arg->fFileName.Data(), arg->fQuery.Data(), arg->fBinData, arg->fBinDataLength)) {
      // define content type base on extension
      arg->SetContentType(GetMimeType(arg->fFileName.Data()));
      return;
   }

   /*
     if (arg->fFileName == "get.json.gz") {
        if (fSniffer->ProduceJson(arg->fPathName.Data(), arg->fQuery.Data(), arg->fContent)) {

           Int_t fObjlen = arg->fContent.Length();
           Int_t cxlevel = 5;
           Int_t cxAlgorithm = 0;

           Int_t nbuffers = 1 + (fObjlen - 1)/kMAXBUF;
           Int_t buflen = fObjlen + 9*nbuffers + 28; //add 28 bytes in case object is placed in a deleted gap
           if (buflen<512) buflen = 512;

           void* fBuffer = malloc(buflen);

           char *objbuf = (char*) arg->fContent.Data();
           char *bufcur = (char*) fBuffer;
           Int_t noutot = 0;
           Int_t nzip   = 0;
           for (Int_t i = 0; i < nbuffers; ++i) {
              Int_t bufmax = kMAXBUF, nout(0);
              if (i == nbuffers - 1) bufmax = fObjlen - nzip;
              R__zipMultipleAlgorithm(cxlevel, &bufmax, objbuf, &bufmax, bufcur, &nout, cxAlgorithm);
              if (nout == 0 || nout >= fObjlen) { //this happens when the buffer cannot be compressed
                 Error("", "Fail to compress data");
                 free(fBuffer);
                 return;
              }
              bufcur += nout;
              noutot += nout;
              objbuf += kMAXBUF;
              nzip   += kMAXBUF;
           }

           Info("Compress", "Original size %d compressed %d", fObjlen, noutot);

           arg->fBinData = fBuffer;
           arg->fBinDataLength = noutot;
           arg->fContent.Clear();

           arg->SetEncoding("gzip");
           arg->SetJson();
           return;
        }
     }
   */

   arg->Set404();
}

//______________________________________________________________________________
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);
}


//______________________________________________________________________________
const char *THttpServer::GetMimeType(const char *path)
{
   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";
}
 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