/***************************************************************************
 *                                                                         *
 *   PARMPURL.CPP                                                          *
 *                                                                         *
 *   Copyright (c) 1998 Galacticomm, Inc.         All rights reserved.     *
 *                                                                         *
 *   Active HTML URL encoded parameter parsing class implementation.       *
 *                                                                         *
 *                                           - J. Alvrus    06/16/1998     *
 *                                                                         *
 ***************************************************************************/

#pragma warn -par
#include "stepfind.h"
#include "acthutl.h"
#include "parmmgr.h"
#include "parmurl.h"
#include "parmpurl.h"

#define FILREV "$Revision: 1 $"

MARKSOURCE(parmpurl)

acthParamParseURL::acthParamParseURL( // standard constructor
acthRequest * req,                 //   associated request object
acthParamMgr * mgr) :              //   associated manager object
     acthParamParser(req,mgr),
     m_pstParam(NULL),
     m_pitBeg(NULL),
     m_pitVal(NULL),
     m_pitEnd(NULL),
     m_pitEOF(NULL),
     m_state(FINDEND)
{
     if (sameas(m_req->method(),"GET")
      || sameas(m_req->method(),"HEAD")) {
          CHAR const * qpos=strchr(m_req->url(),'?');
          if (qpos != NULL) {
               // istrstream writer needs a lesson in const
               m_pstParam=new istrstream(const_cast<CHAR *>(qpos+1));
               m_mgr->TrackStream(m_pstParam);
          }
     }
     else if (sameas(m_req->method(),"POST")) {
          m_pstParam=&m_req->bodyin();
     }
     if (m_pstParam != NULL) {
          m_pstParam->unsetf(ios::skipws);
          m_pitBeg=new istream_iterand<CHAR,streamoff>(*m_pstParam);
          m_pitVal=new istream_iterand<CHAR,streamoff>(*m_pstParam);
          m_pitEnd=new istream_iterand<CHAR,streamoff>(*m_pstParam);
          m_pitEOF=new istream_iterand<CHAR,streamoff>(*m_pstParam,EOF);
     }
}

acthParamParseURL::~acthParamParseURL() // destructor
{
     if (m_pitBeg != NULL) {
          delete m_pitBeg;
          m_pitBeg=NULL;
     }
     if (m_pitVal != NULL) {
          delete m_pitVal;
          m_pitVal=NULL;
     }
     if (m_pitEnd != NULL) {
          delete m_pitEnd;
          m_pitEnd=NULL;
     }
     if (m_pitEOF != NULL) {
          delete m_pitEOF;
          m_pitEOF=NULL;
     }
}

bool                               //   returns true when done
acthParamParseURL::process(VOID)   // parse x-www-form-urlencoded parameters
{
     if (m_pstParam == NULL || *m_pitBeg == *m_pitEOF) {
          return(true);
     }
     switch (m_state) {
     case FINDEND:
          if (step_find(*m_pitEnd,*m_pitEOF,'&',PARSECHUNKSIZE)
           || *m_pitEnd == *m_pitEOF) {
               m_state=FINDVALUE;
          }
          break;
     case FINDVALUE:
          if (step_find(*m_pitVal,*m_pitEnd,'=',PARSECHUNKSIZE)
           || *m_pitVal == *m_pitEnd) {
               CHAR pname[PNAMESIZ];
               ::urlDecode(*m_pitBeg,*m_pitVal,pname,PNAMESIZ);
               if (*m_pitVal != *m_pitEnd) {
                    ++(*m_pitVal);           // m_pitVal now points to value
               }
               m_mgr->AddParam(new acthParamURL(pname,m_pitVal
                                               ,m_pitEnd,m_pitBeg));
               if (*m_pitEnd != *m_pitEOF) {
                    ++(*m_pitEnd);           // m_pitEnd now pts to next name
               }
               *m_pitVal=*m_pitBeg=*m_pitEnd;
               m_state=FINDEND;
          }
          break;
     }
     return(*m_pitBeg == *m_pitEOF);
}
