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

#include "TCivetweb.h"

#include "../civetweb/civetweb.h"

#include <stdlib.h>

#include "THttpServer.h"
#include "TUrl.h"

static int begin_request_handler(struct mg_connection *conn)
{
   TCivetweb *engine = (TCivetweb *) mg_get_request_info(conn)->user_data;
   if (engine == 0) return 0;
   THttpServer *serv = engine->GetServer();
   if (serv == 0) return 0;

   const struct mg_request_info *request_info = mg_get_request_info(conn);

   TString filename;

   if (serv->IsFileRequested(request_info->uri, filename)) {
      mg_send_file(conn, filename.Data());
      return 1;
   }

   THttpCallArg arg;
   arg.SetPathAndFileName(request_info->uri); // path and file name
   arg.SetQuery(request_info->query_string);  //! additional arguments
   arg.SetTopName(engine->GetTopName());

   TString hdr;

   if (!serv->ExecuteHttp(&arg) || arg.Is404()) {
      arg.FillHttpHeader(hdr);
      mg_printf(conn, "%s", hdr.Data());
      return 1;
   }

   if (arg.IsFile()) {
      mg_send_file(conn, (const char *) arg.GetContent());
      return 1;
   }

   arg.FillHttpHeader(hdr);
   mg_printf(conn, "%s", hdr.Data());

   if (arg.GetContentLength() > 0)
      mg_write(conn, arg.GetContent(), (size_t) arg.GetContentLength());

   // Returning non-zero tells civetweb that our function has replied to
   // the client, and civetweb should not send client any more data.
   return 1;
}


//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TCivetweb                                                            //
//                                                                      //
// http server implementation, based on civetweb embedded server        //
// It is default kind of engine, created for THttpServer                //
//                                                                      //
// Following additional options can be specified                        //
//    top=foldername - name of top folder, seen in the browser          //
//    thrds=N - use N threads to run civetweb server (default 5)        //
//    auth_file - global authentication file                            //
//    auth_domain - domain name, used for authentication                //
//                                                                      //
// Example:                                                             //
//    new THttpServer("http:8080/none?top=MyApp&thrds=3");              //
//                                                                      //
// Authentication:                                                      //
//    When auth_file and auth_domain parameters are specified, access   //
//    to running http server will be possible only after user           //
//    authentication, using so-call digest method. To generate          //
//    authentication file, htdigest routine should be used:             //
//                                                                      //
//        [shell] htdigest -c .htdigest domain_name user                //
//                                                                      //
//    When creating server, parameters should be:                       //
//                                                                      //
//       new THttpServer("http:8080/none?auth_file=.htdigets&auth_domain=domain_name");   //
//                                                                      //
//////////////////////////////////////////////////////////////////////////


//______________________________________________________________________________
TCivetweb::TCivetweb() :
   THttpEngine("civetweb", "compact embedded http server"),
   fCtx(0),
   fCallbacks(0),
   fTopName()
{
   // constructor
}

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

   if (fCtx != 0) mg_stop((struct mg_context *) fCtx);
   if (fCallbacks != 0) free(fCallbacks);
   fCtx = 0;
   fCallbacks = 0;
}

//______________________________________________________________________________
Bool_t TCivetweb::Create(const char *args)
{
   // Creates embedded civetweb server
   // As argument, http port should be specified in form "8090"

   fCallbacks = malloc(sizeof(struct mg_callbacks));
   memset(fCallbacks, 0, sizeof(struct mg_callbacks));
   ((struct mg_callbacks *) fCallbacks)->begin_request = begin_request_handler;

   TString sport = "8080";
   TString num_threads = "5";
   TString auth_file, auth_domain;

   // for the moment the only argument is port number
   if ((args != 0) && (strlen(args) > 0)) {
      TUrl url(TString::Format("http://localhost:%s", args));

      if (url.IsValid()) {
         url.ParseOptions();
         if (url.GetPort() > 0) sport.Form("%d", url.GetPort());

         const char *top = url.GetValueFromOptions("top");
         if (top != 0) fTopName = top;

         Int_t thrds = url.GetIntValueFromOptions("thrds");
         if (thrds > 0) num_threads.Form("%d", thrds);

         const char *afile = url.GetValueFromOptions("auth_file");
         if (afile != 0) auth_file = afile;
         const char *adomain = url.GetValueFromOptions("auth_domain");
         if (adomain != 0) auth_domain = adomain;
      }
   }

   const char *options[100];
   int op(0);

   Info("Create", "Starting HTTP server on port %s", sport.Data());

   options[op++] = "listening_ports";
   options[op++] = sport.Data();
   options[op++] = "num_threads";
   options[op++] = num_threads.Data();

   if ((auth_file.Length() > 0) && (auth_domain.Length() > 0)) {
      options[op++] = "global_auth_file";
      options[op++] = auth_file.Data();
      options[op++] = "authentication_domain";
      options[op++] = auth_domain.Data();
   }

   options[op++] = 0;

   // Start the web server.
   fCtx = mg_start((struct mg_callbacks *) fCallbacks, this, options);

   return kTRUE;
}

 TCivetweb.cxx:1
 TCivetweb.cxx:2
 TCivetweb.cxx:3
 TCivetweb.cxx:4
 TCivetweb.cxx:5
 TCivetweb.cxx:6
 TCivetweb.cxx:7
 TCivetweb.cxx:8
 TCivetweb.cxx:9
 TCivetweb.cxx:10
 TCivetweb.cxx:11
 TCivetweb.cxx:12
 TCivetweb.cxx:13
 TCivetweb.cxx:14
 TCivetweb.cxx:15
 TCivetweb.cxx:16
 TCivetweb.cxx:17
 TCivetweb.cxx:18
 TCivetweb.cxx:19
 TCivetweb.cxx:20
 TCivetweb.cxx:21
 TCivetweb.cxx:22
 TCivetweb.cxx:23
 TCivetweb.cxx:24
 TCivetweb.cxx:25
 TCivetweb.cxx:26
 TCivetweb.cxx:27
 TCivetweb.cxx:28
 TCivetweb.cxx:29
 TCivetweb.cxx:30
 TCivetweb.cxx:31
 TCivetweb.cxx:32
 TCivetweb.cxx:33
 TCivetweb.cxx:34
 TCivetweb.cxx:35
 TCivetweb.cxx:36
 TCivetweb.cxx:37
 TCivetweb.cxx:38
 TCivetweb.cxx:39
 TCivetweb.cxx:40
 TCivetweb.cxx:41
 TCivetweb.cxx:42
 TCivetweb.cxx:43
 TCivetweb.cxx:44
 TCivetweb.cxx:45
 TCivetweb.cxx:46
 TCivetweb.cxx:47
 TCivetweb.cxx:48
 TCivetweb.cxx:49
 TCivetweb.cxx:50
 TCivetweb.cxx:51
 TCivetweb.cxx:52
 TCivetweb.cxx:53
 TCivetweb.cxx:54
 TCivetweb.cxx:55
 TCivetweb.cxx:56
 TCivetweb.cxx:57
 TCivetweb.cxx:58
 TCivetweb.cxx:59
 TCivetweb.cxx:60
 TCivetweb.cxx:61
 TCivetweb.cxx:62
 TCivetweb.cxx:63
 TCivetweb.cxx:64
 TCivetweb.cxx:65
 TCivetweb.cxx:66
 TCivetweb.cxx:67
 TCivetweb.cxx:68
 TCivetweb.cxx:69
 TCivetweb.cxx:70
 TCivetweb.cxx:71
 TCivetweb.cxx:72
 TCivetweb.cxx:73
 TCivetweb.cxx:74
 TCivetweb.cxx:75
 TCivetweb.cxx:76
 TCivetweb.cxx:77
 TCivetweb.cxx:78
 TCivetweb.cxx:79
 TCivetweb.cxx:80
 TCivetweb.cxx:81
 TCivetweb.cxx:82
 TCivetweb.cxx:83
 TCivetweb.cxx:84
 TCivetweb.cxx:85
 TCivetweb.cxx:86
 TCivetweb.cxx:87
 TCivetweb.cxx:88
 TCivetweb.cxx:89
 TCivetweb.cxx:90
 TCivetweb.cxx:91
 TCivetweb.cxx:92
 TCivetweb.cxx:93
 TCivetweb.cxx:94
 TCivetweb.cxx:95
 TCivetweb.cxx:96
 TCivetweb.cxx:97
 TCivetweb.cxx:98
 TCivetweb.cxx:99
 TCivetweb.cxx:100
 TCivetweb.cxx:101
 TCivetweb.cxx:102
 TCivetweb.cxx:103
 TCivetweb.cxx:104
 TCivetweb.cxx:105
 TCivetweb.cxx:106
 TCivetweb.cxx:107
 TCivetweb.cxx:108
 TCivetweb.cxx:109
 TCivetweb.cxx:110
 TCivetweb.cxx:111
 TCivetweb.cxx:112
 TCivetweb.cxx:113
 TCivetweb.cxx:114
 TCivetweb.cxx:115
 TCivetweb.cxx:116
 TCivetweb.cxx:117
 TCivetweb.cxx:118
 TCivetweb.cxx:119
 TCivetweb.cxx:120
 TCivetweb.cxx:121
 TCivetweb.cxx:122
 TCivetweb.cxx:123
 TCivetweb.cxx:124
 TCivetweb.cxx:125
 TCivetweb.cxx:126
 TCivetweb.cxx:127
 TCivetweb.cxx:128
 TCivetweb.cxx:129
 TCivetweb.cxx:130
 TCivetweb.cxx:131
 TCivetweb.cxx:132
 TCivetweb.cxx:133
 TCivetweb.cxx:134
 TCivetweb.cxx:135
 TCivetweb.cxx:136
 TCivetweb.cxx:137
 TCivetweb.cxx:138
 TCivetweb.cxx:139
 TCivetweb.cxx:140
 TCivetweb.cxx:141
 TCivetweb.cxx:142
 TCivetweb.cxx:143
 TCivetweb.cxx:144
 TCivetweb.cxx:145
 TCivetweb.cxx:146
 TCivetweb.cxx:147
 TCivetweb.cxx:148
 TCivetweb.cxx:149
 TCivetweb.cxx:150
 TCivetweb.cxx:151
 TCivetweb.cxx:152
 TCivetweb.cxx:153
 TCivetweb.cxx:154
 TCivetweb.cxx:155
 TCivetweb.cxx:156
 TCivetweb.cxx:157
 TCivetweb.cxx:158
 TCivetweb.cxx:159
 TCivetweb.cxx:160
 TCivetweb.cxx:161
 TCivetweb.cxx:162
 TCivetweb.cxx:163
 TCivetweb.cxx:164
 TCivetweb.cxx:165
 TCivetweb.cxx:166
 TCivetweb.cxx:167
 TCivetweb.cxx:168
 TCivetweb.cxx:169
 TCivetweb.cxx:170