/*****************************************************************************/
/*
                                  DAVweb.h

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

#ifndef DAVWEB_H_LOADED
#define DAVWEB_H_LOADED 1

#include "../expat/expat.h"
#include <lkidef.h>

/**********/
/* macros */
/**********/

/* WASD'S own XML namespace */
#define WEBDAV_NS_WASDAV "WASD.VMS.WebDAV:"

/* compare this element string to the WASDAV namespace element name */
#define WEBDAV_IS_WASDAVEL(elstr,elname) \
(*(ULONGPTR)elstr == 'WASD' && \
 *(ULONGPTR)(elstr+sizeof(WEBDAV_NS_WASDAV)) == *(ULONGPTR)elname && \
 !strcmp(elstr,WEBDAV_NS_WASDAV " " elname))

/* compare this element string to the DAV namespace element name */
#define WEBDAV_IS_DAVEL(elstr,elname) \
(*(ULONGPTR)elstr == 'DAV:' && \
 *(ULONGPTR)(elstr+sizeof("DAV:")) == *(ULONGPTR)elname && \
 !strcmp(elstr,"DAV: " elname))

/* number of parents tested for lock meta-data */
#define WEBDAV_LOCK_PARENT_DEFAULT 1

/* number of volumes ODS can be cached */
#define WEBDAV_META_VOLODS 32

/* seconds representing an infinite timeout (~31 years) */
#define WEBDAV_TIMEOUT_INFINITE 999999999

#define WEBDAV_LOCK_TIMEOUT_DEFAULT   3600  /* seconds - one hour */
#define WEBDAV_LOCK_TIMEOUT_MAX     604800  /* seconds - one week */

#define WEBDAV_FLUSH_SECONDS_MAX        30  /* for PROPFIND */

#define WEBDAV_DEPTH_ZERO 0
#define WEBDAV_DEPTH_ONE  1
/* must be positive and greater than 1 */
#define WEBDAV_DEPTH_INFINITY 999

#define WEBDAV_LOCK_TYPE_WRITE      1

#define WEBDAV_LOCK_SCOPE_SHARED    1
#define WEBDAV_LOCK_SCOPE_EXCLUSIVE 2

/* phases of processing when deleting */
#define WEBDAV_DELETE_SINGLE_FILE  1
#define WEBDAV_DELETE_TREE_FILES   2
#define WEBDAV_DELETE_TREE_DIRS    3
#define WEBDAV_DELETE_TREE_PARENT  4

/* "Microsoft-WebDAV-MiniRedir/.." */
#define WEBDAV_MICROSOFT_MINIREDIR  1
/* "Microsoft Data Access Internet Publishing Provider .." */
#define WEBDAV_MICROSOFT_MDAIPP     2
/* South River Technologies WebDrive (assuming some level of IIS conformance) */
#define WEBDAV_MICROSOFT_WEBDRIVE  10
/* BARAD-DUR (assuming some level of IIS conformance) */
#define WEBDAV_MICROSOFT_BITKINEX  11
/* had "Microsoft" in the user agent field */
#define WEBDAV_MICROSOFT_UNKNOWN   99

#define WEBDAV_LOCK_TOKEN_SIZE 64

/* states when parsing XML */
#define WEBDAV_STATE_NOT_PARSING  0
#define WEBDAV_STATE_PARSING      1
#define WEBDAV_STATE_PARSED       2

/* macros for setting/testing states */
#define WEBDAV_PARSING(this)     (this = WEBDAV_STATE_PARSING)
#define WEBDAV_PARSED(this)      (this = WEBDAV_STATE_PARSED)
#define WEBDAV_NOT_PARSING(this) (this = WEBDAV_STATE_NOT_PARSING)
#define WEBDAV_IS_PARSING(this)  (this == WEBDAV_STATE_PARSING)
#define WEBDAV_IS_PARSED(this)   (this == WEBDAV_STATE_PARSED)

/*******************/
/* data structures */
/*******************/

#pragma member_alignment __save
#pragma member_alignment

/* forward reference */
typedef struct WebDavTaskStruct WEBDAV_TASK;

/******************/
/* copy structure */
/******************/

typedef struct WebDavCopyStruct WEBDAV_COPY;

typedef struct WebDavCopyStruct
{
   BOOL  CopyingDir,
         CopyingMeta,
         MoveOverwrite;

   int  BucketSize,
        DataSize,
        DirCount,
        DirFailCount,
        FileCount,
        FileFailCount,
        MetaCount,
        MetaFailCount,
        SuccessCount,
        VmsStatus;

   char  *DataPtr;

   REQUEST_STRUCT  *RequestPtr;

   STR_DSC  ReadNameDsc,
            WriteNameDsc;

   ODS_STRUCT  *ReadOdsPtr,
               *WriteOdsPtr;
};

/********************/
/* delete structure */
/********************/

typedef struct WebDavDeleteStruct WEBDAV_DELETE;

typedef struct WebDavDeleteStruct
{
   int  /* phase of deletion */
        DelPhase,
        /* count of directory files deleted */
        DirCount,
        /* count of directory file deletion errors */
        DirFailCount,
        /* count of files deleted */
        FileCount,
        /* count of file deletion errors */
        FileFailCount,
        /* count of meta files deleted */
        MetaCount,
        /* count of meta file deletion errors */
        MetaFailCount,
        /* count of tree directories deleted this pass */
        TreeDirCount,
        /* count of tree directories not empty this pass */
        TreeDirNotEmptyCount;
};      

/******************/
/* lock structure */
/******************/

typedef struct WebDavLockStruct WEBDAV_LOCK;

typedef struct WebDavLockStruct
{
   LIST_ENTRY  ListEntry;

   int  Depth,
        Type,
        Scope,
        Timeout;

   int64  ExpiresTime64;

   char  ExpiresString [48],
         TokenString [WEBDAV_LOCK_TOKEN_SIZE+1],
         TimeoutString [24];
         
   STR_DSC  LockDsc,
            OwnerDsc;
};

/*****************/
/* DLM structure */
/*****************/

typedef struct WebDavDlmStruct WEBDAV_DLM;

typedef struct WebDavDlmStruct
{
   unsigned long  ResourceHash [4];

   BOOL  ExMode;

   char  ResourceName [ODS_MAX_FILE_NAME_LENGTH+1];

   struct lksb  LockSb;

   REQUEST_STRUCT  *RequestPtr;
   WEBDAV_TASK  *TaskPtr;
};

/******************/
/* meta structure */
/******************/

typedef struct WebDavMetaStruct WEBDAV_META;

typedef struct WebDavMetaStruct
{
   BOOL  CopyCaseChange,
         CopyDeleteAfter,
         CopyLocked,
         LockCreated,
         MetaCreated,
         MetaDirCreate,
         MetaForDir,
         ParseData,
         ParseLock,
         ParseLockExpires,
         ParseLockOwner,
         ParseProp,
         ParseCharData,
         ResourceNamesMatch,
         UpdateLocked;

   int  ElementDepth,
        MetaDirNameLength,
        MoveDirCount,
        MoveDirFailCount,
        MoveFileCount,
        MoveFileFailCount,
        ReadMetaNameLength,
        ReadResourceNameLength,
        RabBucket,
        VmsStatus,
        WriteMetaNameLength,
        WriteResourceNameLength;

   unsigned long  CopyAstParam,
                  DeleteAstParam,
                  ReadAstParam,
                  UpdateAstParam;

   unsigned long  ReadHash [4],
                  WriteHash [4];

   char  *MetaDirNamePtr;

   char  ReadMetaName [ODS_MAX_FILE_NAME_LENGTH+1],
         ReadResourceName [ODS_MAX_FILE_NAME_LENGTH+1],
         WriteMetaName [ODS_MAX_FILE_NAME_LENGTH+1],
         WriteResourceName [ODS_MAX_FILE_NAME_LENGTH+1];

   WEBDAV_DLM  DlmData,
               DlmDest;
   WEBDAV_LOCK  *LockBuildPtr;
   WEBDAV_TASK  *TaskPtr;

   LIST_HEAD  LockList;

   STR_DSC  CopyDsc,
            FromDsc,
            LockDsc,
            ParseErrorDsc,
            PropDsc,
            ReadDsc,
            ToDsc,
            WriteDsc;

   ODS_STRUCT  ReadOds;

   REQUEST_STRUCT  *RequestPtr;

   REQUEST_AST  CopyAstFunction,
                DeleteAstFunction,
                ReadAstFunction,
                UpdateAstFunction;
};

/**********************/
/* property structure */
/**********************/

typedef struct WebDavPropStruct WEBDAV_PROP;

typedef struct WebDavPropStruct
{
   BOOL  AllProp,
         CreationDate,
         DisplayName,
         FindProp,
         GetContentLanguage,
         GetContentLength,
         GetContentType,
         GetEtag,
         GetLastModified,
         LockDiscovery,
         PropName,
         ResourceType,
         PropertyBehaviorKeepalive,
         PropertyBehaviorOmit,
         SupportedLock,
         VersionName,
         QuotaAvailableBytes,
         QuotaUsedBytes;

   STR_DSC  SetDsc;
};

/***********************/
/* XML parse structure */
/***********************/

typedef struct WebDavXmlStruct WEBDAV_XML;

struct WebDavXmlStruct
{
   int  ElementDepth,
        ParseCharData,
        ParseFind,
        ParseLockInfo,
        ParseLockOwner,
        ParseLockScope,
        ParseLockType,
        ParseProp,
        ParsePropertyBehavior,
        ParsePropertyUpdate,
        ParsePropFind,
        ParseRemove,
        ParseSet;

   STR_DSC  CharDataDsc,
            ElementDsc,
            ParseErrorDsc,
            PropFindDsc,
            PropRemoveDsc,
            PropSetDsc;

   WEBDAV_PROP  *PropListPtr,
                *PropRemovePtr,
                *PropSetPtr;

   XML_Parser  *ParserPtr;
};

/******************/
/* task structure */
/******************/

struct WebDavTaskStruct
{
   BOOL  /* request is NOT begin processed by WebDAV module functions */
         NotWebDavFun,
         /* the specification is a directory */
         IsDirectory,
         /* global config locking enabled and path not 'webdav=NOlocking' */
         LockingEnabled,
         /* keeps track of parent search */
         PropParent,
         /* RFC 4331 quota properties enabled for request */
         QuotaEnabled,
         /* the searched file is a directory file (".DIR;") */
         SearchIsDirectory,
         /* the directory has been changed from ']dir' to '.dir]' */
         SlashlessDir,
         /* move required a copy (different device or meta-data involved) */
         MoveUsingCopy,
         /* overwrite was permitted and actually happened */
         OverwriteOccurred;

   int  /* subdirectory or full directory specification for meta files */
        MetaFileDirLength,
        /* "Microsoft" in the user agent field */
        MicrosoftAgent,
        /* seconds before network buffer is explicitly flushed */
        PropFindFlushAfter,
        /* U*x seconds timestamp when network buffer last flushed */
        PropFindFlushSecond,
        /* track the length of the network buffer data  */
        PropFindFlushLength,
        /* HTTP status code generated during processing */
        ResponseStatusCode,
        /* length of search specification */
        SearchSpecLength,
        /* parameter to meta-data test (for lock) AST */
        TestLockAstParam,
        /* level at which (any) lock occured */
        TestLockedAt,
        /* for checking parent meta locks */
        TestLockDepth,
        /* for checking meta locks */
        TestLockState,
        /* VMS status indicating locking test result */
        TestLockStatus,
        /* depth of collection operation */
        ToDepth;

   unsigned long  /* MD5 hash of request name */
                  RequestHash [4],
                  /* MD5 hash of destination name */
                  DestinationHash [4];

   char  /* subdirectory or full directory specification for meta files */
         *MetaFileDirPtr;

   char  /* buffer to contain multistatus href= scheme://host:port */
         HrefHost [32+128],
         /* buffer to contain multistatus href= path */
         HrefPath [ODS_MAX_FILE_NAME_LENGTH+1],
         /* */
         LockTestName [ODS_MAX_FILE_NAME_LENGTH+1],
         /* search specification */
         SearchSpec [ODS_MAX_FILE_NAME_LENGTH+1];

   /* storage for content-type, etc. */
   CONTENT_TYPE  ContentInfo;

   /* VMS DLM locks on source and destination */
   WEBDAV_DLM  DlmSource,
               DlmDestin;

   /* used for retrieving file size, dates, etc. */
   FILE_QIO  FileAcpData;

   /* "on-disk structure" supporting both ODS-2 and ODS-5 */
   ODS_STRUCT  DestOds,
               SearchOds;

   /* WebDAV functional data stuctures */
   WEBDAV_COPY  CopyData;
   WEBDAV_DELETE  DeleteData;
   WEBDAV_LOCK  LockData;
   WEBDAV_META  MetaData;
   WEBDAV_PROP  PropData;
   WEBDAV_XML  XmlData;

   /* pointer to request owning this WebDAV task structure */
   REQUEST_STRUCT  *RequestPtr;

   REQUEST_AST  /* storage of next function after AST delivery */
                AstFunction,
                /* storage of function after meta-data test (for lock) */
                TestLockAstFunction;
};

#pragma member_alignment __restore

/***********************/
/* function prototypes */
/***********************/

/* DAVWEB.C module */

void DavWebAgentDetect (REQUEST_STRUCT*);
int DavWebCreateDir (REQUEST_STRUCT*, char*, int);
int DavWebDateTimeTo3339 (char*, int64*);
int DavWebDateTimeFrom3339 (char*, int64*);
BOOL DavWebDequeue (WEBDAV_DLM*);
int DavWebDestination (REQUEST_STRUCT*);
int DavWebDirFromName (char*, char*, int);
BOOL DavWebDlmEnqueue (REQUEST_STRUCT*, WEBDAV_DLM*, char*, unsigned long*,
                       BOOL, BOOL, REQUEST_AST, unsigned long);
int DavWebDlmTest (char*);
BOOL DavWebEnqueue (WEBDAV_DLM*, BOOL, BOOL, REQUEST_AST, unsigned long);
void DavWebEnd (REQUEST_STRUCT*);
void DavWebGetHead (REQUEST_STRUCT*);
void DavWebGetHeadEnd (REQUEST_STRUCT*);
void DavWebGetHead404 (REQUEST_STRUCT*);
DavWebHref (REQUEST_STRUCT*, char*, int);
int DavWebInit ();
BOOL DavWebMicrosoftDetect (REQUEST_STRUCT*);
DavWebMkCol (REQUEST_STRUCT*);
DavWebMkCol2 (REQUEST_STRUCT*);
DavWebMultiStatus (REQUEST_STRUCT*, int, char*);
DavWebMicrosoftMunge1 (REQUEST_STRUCT*);
DavWebMicrosoftMunge2 (REQUEST_STRUCT*);
int DavWebSlashlessMunge (REQUEST_STRUCT*, BOOL);
char* DavWebPathAccess (REQUEST_STRUCT*);
void DavWebPutBegin (REQUEST_STRUCT*);
BOOL DavWebRequest (REQUEST_STRUCT*);
DavWebRequest2 (REQUEST_STRUCT*);
DavWebReport (REQUEST_STRUCT*);
DavWebReportOnParse (REQUEST_STRUCT*);
DavWebResponse (REQUEST_STRUCT*, int, int, char*, char*, int);
DavWebResponse201 (REQUEST_STRUCT*);
DavWebResponse207 (REQUEST_STRUCT*);

/* DAVCOPY.C module */

DavCopyBegin (REQUEST_STRUCT*);
DavCopyDirectory (REQUEST_STRUCT*);
DavCopyDirectory2 (REQUEST_STRUCT*);
DavCopyEnd (WEBDAV_COPY*);
DavCopyFile (REQUEST_STRUCT*);
DavCopyFile2 (WEBDAV_COPY*);
DavCopyMeta (REQUEST_STRUCT*, char*, char*);
DavCopyNext (WEBDAV_COPY*);
DavCopyNextAst (WEBDAV_COPY*);
DavCopyOpen (WEBDAV_COPY*);
DavCopyReadOpenAst (WEBDAV_COPY*);
DavCopyReadAst (struct RAB*);
DavCopyWriteAst (struct RAB*);
DavCopyWriteOpenAst (WEBDAV_COPY*);

/* DAVDELETE.C module */

DavDeleteBegin (REQUEST_STRUCT*);
DavDeleteBegin2 (REQUEST_STRUCT*);
DavDeleteEnd (REQUEST_STRUCT*);
void DavDeleteErase (REQUEST_STRUCT*);
int DavDeleteMetaErase (WEBDAV_META*);
int DavDeleteParse (REQUEST_STRUCT*, BOOL, char*);
DavDeleteSearch (REQUEST_STRUCT*);
DavDeleteSearchAst (REQUEST_STRUCT*);

/* DAVLOCK.C module */

DavLockBegin (REQUEST_STRUCT*);
int DavLockSetTimeout (REQUEST_STRUCT*, WEBDAV_LOCK*);
DavLockDlm (REQUEST_STRUCT*);
DavLockEnd (WEBDAV_META*);
WEBDAV_LOCK* DavLockFindToken (REQUEST_STRUCT*);
WEBDAV_LOCK* DavLockFindIf (REQUEST_STRUCT*, int);
DavLockTest (REQUEST_STRUCT*, char*, BOOL, REQUEST_AST, unsigned long);
BOOL DavLockIfToken (REQUEST_STRUCT*, WEBDAV_LOCK*);
DavLockPreProcess (REQUEST_STRUCT*);
DavLockSetOpaqueToken (REQUEST_STRUCT*, WEBDAV_LOCK*);
DavLockSetUrnUuidToken (REQUEST_STRUCT*, WEBDAV_LOCK*);
DavLockUpdate (WEBDAV_META*);
DavLockXml (REQUEST_STRUCT*, WEBDAV_LOCK*, STR_DSC*);
DavUnLockBegin (REQUEST_STRUCT*);
DavUnLockEnd (WEBDAV_META*);
DavUnLockUpdate (WEBDAV_META*);

/* DavMeta.C module */

int DavMetaBuild (WEBDAV_META*);
int DavMetaCreateDir (WEBDAV_META*);
int DavMetaDeleteDir (WEBDAV_META*);
BOOL DavMetaDir (REQUEST_STRUCT*, ODS_STRUCT*);
BOOL DavMetaFile (ODS_STRUCT*);
int DavMetaFileName (char*, char*, int);
int DavMetaOds (char*);
DavMetaLock (REQUEST_STRUCT*, WEBDAV_META*, char*, REQUEST_AST, unsigned long);
DavMetaLockAst (WEBDAV_META*);
DavMetaName (WEBDAV_META*, char*, int);
DavMetaRead (REQUEST_STRUCT*, WEBDAV_META*, char*, REQUEST_AST, unsigned long);
DavMetaReadOpen (WEBDAV_META*);
DavMetaReadAst (struct RAB*);
DavMetaOpenAst (WEBDAV_META*);
BOOL DavMetaRemove (REQUEST_STRUCT*, STR_DSC*, STR_DSC*);
STR_DSC* DavMetaSet (REQUEST_STRUCT*, STR_DSC*, STR_DSC*);
STR_DSC* DavMetaSearch (REQUEST_STRUCT*, STR_DSC*, STR_DSC*);
DavMetaUpdate (WEBDAV_META*, REQUEST_AST, unsigned long);
DavMetaUpdateWrite (struct RAB*);

int DavMetaParseXml (WEBDAV_META*);
void XMLCALL DavMetaCharData (WEBDAV_META*, XML_Char*, int);
void XMLCALL DavMetaEndElement (WEBDAV_META*, char*);
void XMLCALL DavMetaStartElement (WEBDAV_META*, char*, char**);

/* DAVMOVE.C module */

int DavMoveBegin (REQUEST_STRUCT*);
int DavMoveEnd (REQUEST_STRUCT*);
int DavMoveFile (REQUEST_STRUCT*);
int DavMoveDirectory (REQUEST_STRUCT*);
int DavMoveMeta (REQUEST_STRUCT*, char*, char*);
int DavMoveRename (REQUEST_STRUCT*, struct dsc$descriptor*,
                                    struct dsc$descriptor*);

/* DAVPROP.C module */

int DavPropFind ();
DavPropBegin (REQUEST_STRUCT*);
DavPropBegin2 (REQUEST_STRUCT*);
DavPropDead (REQUEST_STRUCT*);
DavPropEnd (REQUEST_STRUCT*);
DavPropLive (REQUEST_STRUCT*);
DavPropLiveAcp (REQUEST_STRUCT*);
DavPropName (REQUEST_STRUCT*);
DavPropParent (REQUEST_STRUCT*);
int DavPropParse (REQUEST_STRUCT*);
DavPropPatchBegin (REQUEST_STRUCT*);
DavPropPatchBegin2 (REQUEST_STRUCT*);
DavPropPatchEnd (REQUEST_STRUCT*);
DavPropPatchUpdate (WEBDAV_META*);
DavPropQuota (REQUEST_STRUCT*);
DavPropReadAst (REQUEST_STRUCT*);
DavPropSearch (REQUEST_STRUCT*);
DavPropSearchAst (REQUEST_STRUCT*);

DavPropPatchBegin (REQUEST_STRUCT*);
void XMLCALL DavPropPatchStartElement (REQUEST_STRUCT*, char*, const char**);
void XMLCALL DavPropPatchEndElement (REQUEST_STRUCT*, char*);

/* DAVXML.C module */

void XMLCALL DavXmlCharData (REQUEST_STRUCT*, XML_Char*, int);
void DavXmlInit ();
int DavXmlParseText (REQUEST_STRUCT*, STR_DSC*);
BOOL DavXmlMemoryError (REQUEST_STRUCT*, XML_Parser*);
DavXmlParseError (REQUEST_STRUCT*, XML_Parser*, STR_DSC*, STR_DSC*);
DavXmlTrimElement (STR_DSC*);
void XMLCALL DavXmlEndElement (REQUEST_STRUCT*, char*);
void XMLCALL DavXmlStartElement (REQUEST_STRUCT*, char*, char**);
DavXmlReport (REQUEST_STRUCT*);
DavXmlWatchProp (REQUEST_STRUCT*);

#if DAVXML_MEMORY
void DavXmlMemoryFree (void*);
void DavXmlMemoryInit ();
void* DavXmlMemoryMalloc (size_t);
void* DavXmlMemoryRealloc (void*, size_t);
#endif /* DAVXML_MEMORY */
char* DavXmlMemoryReport ();

#endif /* DAVWEB_H_LOADED */

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

