////////////////////////////////////////////////////////////////////////////
//
//  httpup.h
//
//  http upload handling
//
//                                                  - Paul Roub  12/01/97
//
/////////////////////////////////////////////////////////////////////////////

#if ! defined( HTTPUP_H )
#  define HTTPUP_H

#include  "gcomm.h"
#include  "galacth.h"

const int HOLDBACKSIZE = 10;
const int OUTBUFSIZE = 4096;

class httpUpload
{
public:
     httpUpload( acthSession *session, const char* path=NULL, GBOOL forceShort=TRUE );
     virtual ~httpUpload();

     GBOOL                         //   TRUE if file handle set ok
     setFile(                      // set the file handle to use for uploaded file
     FILE *file);                  //   file to direct data to

     GBOOL                         //   TRUE if a file has been received
     gotFile();                    // check whether a file was uploaded

     ACTHCODE                      //   ACTHDONE when all data have arrived
     proceed(                      // proceed with http upload processing
     GBOOL dumpData = FALSE);      //   toss data

     const CHAR *                  //   our file name
     getFileName();                // get upload file name
     
     const CHAR *                  //   long file name
     getLongName();                // get long name (when shortening)

     ULONG                         //   size in bytes
     getFileSize();                // get upload file size

     const CHAR *                  //   our description
     getFileDescription();         // get our file description

     const CHAR *                  //   upload path
     getPath();                    // get our upload path

     const CHAR *                  //   upload library name
     getLibName();                 // get target lib name

     GBOOL                         //   TRUE if IE 3 is in use without upload patch
     needIeAddon();                // see if IE 3 upload addon is needed

     GBOOL                         //   TRUE if path retrieved
     getFilePath(                  // get our upload path
     CHAR *path,                   //   path (returned)
     size_t bufsize);              //   path buffer size

     GBOOL                         //   TRUE if info retrieved OK
     getFileInfo(                  // get info on uploaded file
     ffblk *f);                    //   file info (returned)

     void
     setCleanText(                 // toggle retrieved description cleanup
     GBOOL shouldClean);           //   should we scrub description data?

     void           
     setShortName(                 // reset our short filename
     const CHAR *fn);              //   new short name     

protected:
     virtual
     GBOOL                         //   TRUE if file opened OK
     openFile();                   // open upload file

     virtual
     GBOOL                         //   TRUE if data written to file OK
     writeToFile(                  // write data to file
     const VOID *data,             //   data to write
     size_t bytes);                //   data size

     virtual
     GBOOL                         //   TRUE if closed OK
     closeFile();                  // close the upload file

     VOID
     initUpload(                   // initialize the httpUpload object
     const CHAR* path);            //   temporary upload path


private:
     GBOOL                         //   TRUE if data output successfully
     outputFileData(               // output a chunk of file data
     const VOID *data,             //   data to output
     size_t bytes);                //   data length in bytes

     void
     finishFile();                 // finish off the upload file

     void
     stccat(                       // add a char to a string
     CHAR *dst,                    //   string in question
     CHAR newchar,                 //   char to add
     size_t maxLen);               //   maximum string length

     GBOOL                         //   TRUE if boundary info retrieved
     getBoundaryInfo();            // establish upload boundary string

     void
     processData();                // process incoming data

     void
     lrtrim(                       // remove leading and trailing blanks
     CHAR *st);                    //   string to trim

     void
     processHeaderLine(            // process a form-encoding header line
     const CHAR *data);            //   line to process

     void
     parseDisposition(             // parse a content disposition line
     const CHAR *st,               //   line to parse
     CHAR *fieldname,              //   field name (returned)
     CHAR *filename);              //   file name (returned)

     void
     fieldAt(                      // get field data from a header string
     const CHAR *fieldSrc,         //   string to parse
     CHAR *field);                 //   field data start pos

     void
     shorten(                      // brain-dead filename shortening
     const CHAR *longname,         //   long name
     CHAR *shortname);             //   short name (returned)

     GBOOL                         //   TRUE if character match
     matchBoundChar(               // match next boundary char and advance
     UCHAR ch);                    //   char to match

     INT                           //   next char in buf, or EOF
     nextChar();                   // get next char in buffer

     void
     pushBack(                     // push a char back into the buffer
     UCHAR ch);                    //   char to push

     void
     pushBack(                     // push data back into the buffer
     const UCHAR *data,            //   data to push
     size_t len);                  //   data length

     void
     cleanupDescription();         // clean up the file description

     void
     cleanupLibname();             // clean up the library name

     void
     cleanupText(                  // remove newlines from text, and trim
     CHAR *st);                    //   text to clean

     enum uploadState
     {
          LOOKING,
          INBOUNDARY,
          HEADERWAIT,
          HEADERS,
          INFILE,
          INDESC,
          INDESCBOUNDARY,
          INLIB,
          INLIBBOUNDARY,
          INENDBOUNDARY
     };

     VOID
     setState(                     // set our processing state
     uploadState newState);        //   new state

     GBOOL     m_forceShort;
     CHAR m_longName[ GCMAXPTH ];
     int m_toSend;
     int m_sent;
     UCHAR m_buffer[ 16 * 1024 ];
     UCHAR m_echoBuffer[ 16 * 1024 ];
     int m_inBuffer;
     int m_bufSent;
     char m_boundary[ 1024 ];
     char m_line[ 1024 ];
     uploadState m_state;
     int m_lineLen;
     char m_filename[ GCMAXPTH ];
     char m_tempfilename[ GCMAXPTH ];
     char m_libname[ GCMAXPTH ];
     char m_description[ 1024 ];
     GBOOL m_fileHeader;
     GBOOL m_descHeader;
     GBOOL m_libnameHeader;
     FILE *m_outFile;
     INT m_boundMatchLen;
     int m_boundLen;
     UCHAR m_outBuf[ OUTBUFSIZE ];
     int m_inOutBuf;
     acthSession *ses;
     ULONG m_fileSize;
     ULONG m_waiting;
     ULONG m_waitSent;
     GBOOL m_ours;
     GBOOL m_cleanText;
     char m_path[ GCMAXPTH ];
};

#endif
