//---------------------------------------------------------------------------
//
// MODULE NAME:     main.cpp
//
// COPYRIGHT:       Copyright (c) 2013, GladeSoft, Inc.
//                  All Rights Reserved.
//
//                  NOTICE: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF
//                  GLADESOFT, INC., AND SHALL NOT BE REPRODUCED, COPIED
//                  IN WHOLE OR IN PART ADAPTED, MODIFIED, OR
//                  DISSEMINATED WITHOUT THE EXPRESS WRITTEN CONSENT
//                  OF GLADESOFT, INC. ANY REDISTRIBUTION OR
//                  PUBLICATION TO UNAUTHORIZED PERSONS IS STRICTLY
//                  PROHIBITED BY U.S. AND INTERNATIONAL COPYRIGHT LAW.
//
// DESCRIPTION:     Another example program using the Seminole embedded 
//                  web server.
//
// AUTHOR:          S. Conner
//
// CREATION DATE:   Jun  5, 2006
//
//---------------------------------------------------------------------------
//
// HISTORY OF CHANGE  
//
// -----+--------+------------------------------------------+------+---------
// VERS | DATE   | DESCRIPTION OF CHANGE                    | INIT | PR#
// =====+========+==========================================+======+=========
//  001 |06/05/06| File creation.                           | MYG  |
// -----+--------+------------------------------------------+------+---------
//  002 |06/12/09| Const correctness.                       | RAH  |
// -----+--------+------------------------------------------+------+---------
//---------------------------------------------------------------------------

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "seminole.h"
#include "sem_auth.h"

#include "sitedata.h"

//**********************************************************************

class DemoFileHandler : public HttpdFileHandler
{
  class Authenticator : public HttpdAuthenticator
  {
  protected:
    bool GetPassword(const char    *p_user,
                     HttpdRequest  *p_request,
                     char          *p_buf);
    void Realm(HttpdRequest *p_request, char *p_realm);
  };

  Authenticator   mAuthenticator;

protected:
  void ProcessUri(RequestState &state);
    
public:
  DemoFileHandler(HttpdFileSystem *p_filesys,
                  const char      *p_root,
                  const char      *p_prefix);
  int Create() { return (mAuthenticator.Create()); }
};

static const char  gServername[] = "localhost";
static const int   gServerport   = 8080;
static Httpd      *gpWebServer;

//**********************************************************************

//---------------------------------------------------------------------------
//
// NAME:           DemoFileHandler::DemoFileHandler
//
// DESCRIPTION:    Construct the demo file handler.
//
// AUTHOR:         S. Conner
// CREATED:        Jun  5, 2006
// LAST MODIFIED:  N/A           BY:  N/A
//
//--------------------------------------------------------------------------
DemoFileHandler::DemoFileHandler(HttpdFileSystem *p_filesys,
                                 const char      *p_root,
                                 const char      *p_prefix)
 : HttpdFileHandler(p_filesys, p_root, p_prefix)
{}

//---------------------------------------------------------------------------
//
// NAME:           DemoFileHandler::Authenticator::GetPassword
//
// DESCRIPTION:    Implementation of the abstract method for password
//                 authentication.
//
// RETURNS:        True if a password exists and is available. False
//                 otherwise.
//
// AUTHOR:         S. Conner
// CREATED:        Jun  5, 2006
// LAST MODIFIED:  N/A           BY:  N/A
//
//--------------------------------------------------------------------------
bool DemoFileHandler::Authenticator::GetPassword(const char    *p_user,
                                                 HttpdRequest  *p_request,
                                                 char          *p_buf)
{
  const char *p_password;

  if (strcmp(p_user, "sam") == 0)
    p_password = "i_am36";
  else if (strcmp(p_user, "fred") == 0)
    p_password = "inbed";
  else if (strcmp(p_user, "bob") == 0)
    p_password = "4apples";
  else if (strcmp(p_user, "david") == 0)
    p_password = "mogen";
  else if (strcmp(p_user, "moshe") == 0)
    p_password = "boker";
  else if (strcmp(p_user, "sally") == 0)
    p_password = "aqua";
  else if (strcmp(p_user, "patty") == 0)
    p_password = "yumyum";
  else
    return (false);

  if (strlen(p_password) >= HTTPD_MAX_PASSWD_LENGTH)
    return (false);

  strcpy(p_buf, p_password);
  return (true);
}

//---------------------------------------------------------------------------
//
// NAME:           DemoFileHandler::Authenticator::Realm
//
// DESCRIPTION:    Get the authentication realm.
//
// AUTHOR:         S. Conner
// CREATED:        Jun  5, 2006
// LAST MODIFIED:  N/A           BY:  N/A
//
//--------------------------------------------------------------------------
void DemoFileHandler::Authenticator::Realm(HttpdRequest *p_request,
                                           char         *p_realm)
{
  strncpy(p_realm,
          "Yoyodyne Electric Banjo 2000",
          HTTPD_MAX_REALM_LENGTH - 1);
  p_realm[HTTPD_MAX_REALM_LENGTH - 1] = '\0';
}

//---------------------------------------------------------------------------
//
// NAME:           DemoFileHandler::ProcessUri
//
// DESCRIPTION:    Validate the URI against the authenticator object.
//
// AUTHOR:         S. Conner
// CREATED:        Jun  5, 2006
// LAST MODIFIED:  Apr 16, 2008  BY:  MYG (M1164: Use helper)
//
//--------------------------------------------------------------------------
void DemoFileHandler::ProcessUri(RequestState &state)
{
 if (HttpdUtilities::IsUriPathPrefix(state.mpFilePath, "/secure"))
 { 
   if (mAuthenticator.Authenticate(state.mpRequest))
     HttpdFileHandler::ProcessUri(state);
 }
 else
   HttpdFileHandler::ProcessUri(state);
}

//*************************************************************************

//---------------------------------------------------------------------------
//
// NAME:           failure
//
// DESCRIPTION:    Handle a fatal error.
//
// AUTHOR:         S. Conner
// CREATED:        Mar  6, 2004
// LAST MODIFIED:  N/A           BY:  N/A
//
//--------------------------------------------------------------------------
static void failure(const char *p_file, int line, const char *p_msg)
{
  assert(p_file != NULL);
  assert(line   >  0);
  assert(p_msg  != NULL);
  
  fprintf(stderr, "%s:%d Call to %s failed\n", p_file, line, p_msg);
  exit(EXIT_FAILURE);
}

//---------------------------------------------------------------------------
//
// NAME:           Initialize_The_Web_Server
//
// DESCRIPTION:    Start and configure Seminole.
//
// AUTHOR:         M. Grosberg
// CREATED:        Jun  5, 2006
// LAST MODIFIED:  N/A           BY:  N/A
//
//--------------------------------------------------------------------------
static void Initialize_The_Web_Server()
{
  //-------------------------------------------------------
  // Initialize the environment.
  //-------------------------------------------------------
  
  if (Httpd::Init() != 0)
    failure(__FILE__, __LINE__, "Httpd::Init()");
  
  //--------------------------------------------------------
  // Create the webserver instance.  This just initializes
  // the object --- it doesn't start it up.
  //--------------------------------------------------------
    
  gpWebServer = new Httpd(gServername, gServerport);
  if (gpWebServer == NULL)
    failure(__FILE__, __LINE__, "Httpd::Httpd()");

  static HttpdMemoryDataSource builtin(SemWeb, sizeof(SemWeb));
  static HttpdRomFileSystem    romfs;
  if (romfs.Mount(&builtin) != 0)
    failure(__FILE__, __LINE__, "HttpdRomFileSystem::Mount()");
    
  static DemoFileHandler hand(&romfs, "/", "/");

  if (hand.Create() != 0)
    failure(__FILE__, __LINE__, "DemoFileHandler::Create()");

  gpWebServer->Install(&hand);

  printf("Server started on host %s port %d\n", gServername, gServerport);
}

//*************************************************************************

//---------------------------------------------------------------------------
//
// NAME:           main
//
// DESCRIPTION:    Entry point for the demo.
//
// AUTHOR:         S. Conner
// CREATED:        Mar  6, 2004
// LAST MODIFIED:  N/A           BY:  N/A
//
//--------------------------------------------------------------------------
int main(int argc, const char *const *argv)
{
  char buf[4];

  Initialize_The_Web_Server();
  gpWebServer->Start();
  
  printf("Press <ENTER> to stop.\n");
  fgets(buf, sizeof(buf), stdin);
  
#if HTTPD_INC_SHUTDOWN
  gpWebServer->Stop(HARD);
#endif

  return (EXIT_SUCCESS);
}
