/***************************************************************************
 *                                                                         *
 *   SESAGENT.CPP                                                          *
 *                                                                         *
 *   Copyright (c) 1997 Galacticomm, Inc.         All Rights Reserved.     *
 *                                                                         *
 *   Active HTML Session Module agent and other global resources.          *
 *                                                                         *
 *                                            - J. Alvrus   02/03/1999     *
 *                                                                         *
 ***************************************************************************/

#include "gcomm.h"
#include "majorbbs.h"
#include "gme.h"
#include "galacth.h"
#include "dnf.h"
#include "dnfmgr.h"
#include "tvb.h"
#include "cyctimer.h"
#include "tvbutil.h"
#include "encutil.h"
#include "synbadrq.h"
#include "synlogon.h"
#include "synlogof.h"
#include "synemail.h"
#include "synhint.h"
#include "synlook.h"
#include "galsesah.h"

#define FILREV "$Revision: 1 $"
MARKSOURCE(sesagent)

/* Session manager agent */

class sesAgent : public acthAgent { // Session Manager agent
public:
     sesAgent(                     // constructor/module initializor
     const CHAR *apnam,            //   description (eg "File Libraries")
     const CHAR *upfx);            //   URL prefix (eg "library")

     ~sesAgent();

     acthSynthesis *               //   session info
     newSynthesis(                 // instantiate Synthesis class
     acthSession *ses);            //   for passing to acthSynthesis's ctor

private:                           // private member functions

     bool
     AllowCookieAuth();            // is cookie authentication allowed?

     bool
     atLevel(                      // check if URL is at specified arg level
     acthSession *ses,             //   session object in use
     INT level);                   //   arg level (/blah/ or /blah/foo.htm)
};

/* Global variables */

sesAgent TheMan("Log On/Off Module","session"); // Secret Agent Man
HMCVFILE g_hmcvSes;                // option file handle
tvbBase tvbErrMsg("SES_ERRORMSG"); // error message text variable

/* Agent functions */

sesAgent::sesAgent(                // constructor/module initializor
const CHAR *apnam,                 //   description (eg "File Libraries")
const CHAR *upfx) :                //   URL prefix (eg "library")
     acthAgent(apnam,upfx)
{
     registerAgent(acthVersion);
     g_hmcvSes=::opnmsg("GALSESAH.MCV");
}

acthSynthesis *                    //   new session-specific structure
sesAgent::newSynthesis(            // instantiate Synthesis class
acthSession *ses)                  //   passed to acthSynthesis's constructor
{
     if (AllowCookieAuth()) {
          if (atLevel(ses,1)) {
               if (sameas("login",ses->urlargv(0))
                || sameas("logon",ses->urlargv(0))) {
                    return(new synLogOn(ses,1,false));
               }
               if (sameas("logout",ses->urlargv(0))
                || sameas("logoff",ses->urlargv(0))) {
                    return(new synLogOff(ses));
               }
               if (sameas("email",ses->urlargv(0))) {
                    return(new synEmail(ses));
               }
               if (sameas("hint",ses->urlargv(0))) {
                    return(new synHint(ses));
               }
               if (sameas("lookup",ses->urlargv(0))) {
                    return(new synLook(ses));
               }
          }
          if (atLevel(ses,0)) {
               return(new synLogOn(ses,0,true));
          }
     }
     return(new synBadRequest(ses,ACTHNOTFND));
}

bool
sesAgent::AllowCookieAuth()        // is cookie authentication allowed?
{
     size_t len=0;
     acthGetOption("Authentication Allowed Types",&len,NULL);
     CHAR * buf=new CHAR [len];
     acthGetOption("Authentication Allowed Types",&len,buf);
     bool rc=false;
     for (CHAR * wd=::firstwd(buf) ; !NULSTR(wd) ; wd=::nextwd()) {
          if (::sameas("Cookie",wd)) {
               rc=true;
               break;
          }
     }
     delete [] buf;
     return(rc);
}

bool
sesAgent::atLevel(                 // check if URL is at specified arg level
acthSession *ses,                  //   session object in use
INT level)                         //   arg level (/.../ or /.../foo.htm)
{
     INT n=ses->urlargc();
     if (level > 0 && n >= level
      && ::strchr(ses->urlargv(level-1),'.') != NULL) {
          return(false);
     }
     return(n == level
         || (n == level+1 && ::strchr(ses->urlargv(level),'.') != NULL));
}

sesAgent::~sesAgent()                // destructor
{
}

/* Miscellaneous global functions */

bool
isRedirectLocation(                // is this a valid redirection location?
CHAR const * loc)                  //   location to test
{
     if (*loc == '/') {
          return(true);
     }
     while (isalnum(*loc)) {
          ++loc;
     }
     return(*loc == ':');
}

void
SendPwdEmail(                      // send the password info email
CHAR const * pEmail,               //   to this address
CHAR const * pUserid,              //   send this User-ID
CHAR const * pPassword)            //   send this password
{
     struct message msg;

     ::setmbk(g_hmcvSes);
     ::memset(&msg,0,sizeof(struct message));
     msg.forum=EMLID;
     ::stlcpy(msg.from,rawmsg(PASSFROM),MAXADR);
     ::stlcpy(msg.to,"IN:",MAXADR);
     ::stlcat(msg.to,pEmail,MAXADR);
     ::stlcpy(msg.topic,rawmsg(PASSTPC),TPCSIZ);
     ::prfmsg(PASSTEXT,pUserid,pPassword);
     ::simpsnd(&msg,::stpans(::prfbuf),NULL);
     ::rstmbk();
}
