/*****************************************************************************/ /* DAVxml.c Uses the EXPAT XML parser to parse the request body. REFERENCES ---------- Using Expat by Clark Cooper http://en.wikipedia.org/wiki/Expat_(XML) https://libexpat.github.io http://www.xml.com/pub/a/1999/09/expat/index.html http://www.xml.com/lpt/a/47 VERSION HISTORY --------------- 09-MAY-2018 MGD DavXmlMemoryError() detect out-of-memory DavXmlParseText() detect out-of-memory 19-NOV-2017 MGD always DavWebEnd() not RequestEnd() 23-APR-2015 MGD bugfix; DavXmlStartElement() PROPFIND accumulate list of dead properties subsequently searched for in the metadata 20-AUG-2009 MGD DavXmlStartElement() begin parsing lock own immediately 31-DEC-2006 MGD initial */ /*****************************************************************************/ #ifdef WASD_VMS_V7 #undef _VMS__V6__SOURCE #define _VMS__V6__SOURCE #undef __VMS_VER #define __VMS_VER 70000000 #undef __CRTL_VER #define __CRTL_VER 70000000 #endif #define DAVXML_MEMORY 1 #ifndef DAVXML_MEMORY #define DAVXML_MEMORY 1 #endif #include #include #include #include #include "wasd.h" #include "davweb.h" #define WASD_MODULE "DAVXML" /* just reduce the amount of XML parse noise when WATCHing */ #define WATCH_XML 1 /******************/ /* global storage */ /******************/ static XML_Memory_Handling_Suite DavXmlMemorySuite; /********************/ /* external storage */ /********************/ extern int HttpdTickSecond; extern char ErrorSanityCheck[]; extern ACCOUNTING_STRUCT *AccountingPtr; extern CONFIG_STRUCT Config; extern WATCH_STRUCT Watch; /*****************************************************************************/ /* Initialise ememory management for when parsing XML. */ void DavXmlInit () { if (VmExpatInit ()) { /* initialise the EXPAT memory mnagement suite */ DavXmlMemorySuite.free_fcn = VmExpatFree; DavXmlMemorySuite.malloc_fcn = VmExpatMalloc; DavXmlMemorySuite.realloc_fcn = VmExpatRealloc; } } /*****************************************************************************/ /* Wrap XML_ParserCreateNS() to allow memory management and monitoring. Note that the request pointer is currently unused. */ XML_Parser* DavXmlParserCreate (REQUEST_STRUCT *rqptr) { static char nssep[] = " ", nsenc[] = "UTF-8"; /*********/ /* begin */ /*********/ if (WATCH_XML && WATCHMOD (rqptr, WATCH_MOD_WEBDAV)) WatchThis (WATCHITM(rqptr), WATCH_MOD_WEBDAV, "DavXmlParserCreate()"); if (DavXmlMemorySuite.free_fcn) return (XML_ParserCreate_MM (nsenc, &DavXmlMemorySuite, nssep)); else return (XML_ParserCreate_MM (nsenc, NULL, nssep)); } /*****************************************************************************/ /* */ int DavXmlParseText ( REQUEST_STRUCT *rqptr, STR_DSC *sdptr ) { int cnt, column, line, status, xmlsts; char *cptr, *eptr, *sptr; WEBDAV_LOCK *lckptr; WEBDAV_TASK *tkptr; WEBDAV_XML *xmlptr; /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD_WEBDAV)) WatchThis (WATCHITM(rqptr), WATCH_MOD_WEBDAV, "DavXmlParseText()"); /* shouldn't be calling this without content to parse! */ if (!(STR_DSC_SANITY(sdptr) && STR_DSC_LEN(sdptr))) return (SS$_BUGCHECK); status = SS$_NORMAL; tkptr = rqptr->WebDavTaskPtr; lckptr = &tkptr->LockData; xmlptr = &tkptr->XmlData; InstanceGblSecIncrLong (&AccountingPtr->WebDavXmlParseCount); xmlptr->ParserPtr = DavXmlParserCreate (rqptr); if (!xmlptr->ParserPtr) { status = vaxc$errno; rqptr->rqResponse.HttpStatus = 500; ErrorVmsStatus (rqptr, status, FI_LI); return (status); } xmlptr->ParseLockInfo = xmlptr->ParseLockOwner = xmlptr->ParseLockScope = xmlptr->ParseLockType = xmlptr->ParseProp = xmlptr->ParsePropertyBehavior = xmlptr->ParsePropertyUpdate = xmlptr->ParsePropFind = xmlptr->ParseRemove = xmlptr->ParseSet = WEBDAV_STATE_NOT_PARSING; lckptr->Type = lckptr->Scope = xmlptr->ElementDepth = 0; /* properties will be in a descriptor collection */ StrDscColIfNotBegin (rqptr, &xmlptr->PropFindDsc, 256); StrDscColIfNotBegin (rqptr, &xmlptr->PropRemoveDsc, 256); StrDscColIfNotBegin (rqptr, &xmlptr->PropSetDsc, 256); XML_SetUserData (xmlptr->ParserPtr, rqptr); XML_SetElementHandler (xmlptr->ParserPtr, DavXmlStartElement, DavXmlEndElement); XML_SetCharacterDataHandler (xmlptr->ParserPtr, DavXmlCharData); xmlsts = XML_Parse (xmlptr->ParserPtr, STR_DSC_PTR(sdptr), STR_DSC_LEN(sdptr), 1); if (xmlsts == XML_STATUS_ERROR) { DavXmlParseError (rqptr, xmlptr->ParserPtr, sdptr, &xmlptr->ParseErrorDsc); if (DavXmlMemoryError (rqptr, tkptr->XmlData.ParserPtr)) status = LIB$_INSVIRMEM; else status = SS$_ABORT; } if (xmlptr->ParserPtr) XML_ParserFree (xmlptr->ParserPtr); if (xmlsts == XML_STATUS_ERROR) { DavWebResponse (rqptr, 400, 0, "XML_STATUS_ERROR", FI_LI); return (status); } if (WATCHING (rqptr, WATCH_WEBDAV)) { if (STR_DSC_LEN(&xmlptr->PropRemoveDsc)) WatchThis (WATCHITM(rqptr), WATCH_WEBDAV, "REMOVE"); STR_DSC_ITERATE (sdptr, &xmlptr->PropRemoveDsc) if (STR_DSC_LEN(sdptr)) WatchDataFormatted ("!AZ\n", STR_DSC_PTR(sdptr)); if (STR_DSC_LEN(&xmlptr->PropSetDsc)) WatchThis (WATCHITM(rqptr), WATCH_WEBDAV, "SET"); STR_DSC_ITERATE (sdptr, &xmlptr->PropSetDsc) if (STR_DSC_LEN(sdptr)) WatchDataFormatted ("!AZ\n", STR_DSC_PTR(sdptr)); } if (WATCHING (rqptr, WATCH_WEBDAV)) DavXmlWatchProp (rqptr); return (status); } /*****************************************************************************/ /* Return true if error was "out of memory", false if not. */ BOOL DavXmlMemoryError ( REQUEST_STRUCT *rqptr, XML_Parser *XmlParserPtr ) { /*********/ /* begin */ /*********/ if (WATCH_XML && WATCHMOD (rqptr, WATCH_MOD_WEBDAV)) WatchThis (WATCHITM(rqptr), WATCH_MOD_WEBDAV, "DavXmlMemoryError()"); return (XML_GetErrorCode(XmlParserPtr) == XML_ERROR_NO_MEMORY); } /*****************************************************************************/ /* The ExPat XML parser has returned an error code. Generate a WATCH item and textual report describing that error. */ DavXmlParseError ( REQUEST_STRUCT *rqptr, XML_Parser *XmlParserPtr, STR_DSC *xdptr, STR_DSC *sdptr ) { int cnt, column, line, status, xmlsts; char *cptr, *eptr, *sptr; WEBDAV_TASK *tkptr; WEBDAV_XML *xmlptr; /*********/ /* begin */ /*********/ if (WATCH_XML && WATCHMOD (rqptr, WATCH_MOD_WEBDAV)) WatchThis (WATCHITM(rqptr), WATCH_MOD_WEBDAV, "DavXmlParseError()"); tkptr = rqptr->WebDavTaskPtr; xmlptr = &tkptr->XmlData; line = cnt = XML_GetCurrentLineNumber(XmlParserPtr); column = XML_GetCurrentColumnNumber(XmlParserPtr); eptr = (char*)XML_ErrorString(XML_GetErrorCode(XmlParserPtr)); /* delimit the problematic line */ if (cnt) cnt--; for (cptr = STR_DSC_PTR(xdptr); *cptr && cnt; cptr++) if (*cptr == '\n') cnt--; for (sptr = cptr; *sptr && *sptr != '\n'; sptr++); if (WATCHING (rqptr, WATCH_WEBDAV)) { WatchThis (WATCHITM(rqptr), WATCH_WEBDAV, "XML parse ERROR line:!UL column:!UL !AZ\n!#AZ\n!#*-^", line, column, eptr, sptr-cptr, cptr, column); WatchDataDump (cptr, sptr-cptr); } /* create an error report that is also available for interrogation */ StrDscBegin (rqptr, sdptr, -1); FaoToBuffer (sdptr, -1, NULL, "XML parse ERROR line:!UL column:!UL !AZ:\n!#AZ\n!#*-^", line, column, eptr, sptr-cptr, cptr, column); } /*****************************************************************************/ /* This function and DavXmlEndElement() set various flags to indicate the state of the current XML element. From that various flags indicating properties to be manipulated are set. This pretty-much assumes that the parsing library is ensuring document well-formedness, so the checks on element nesting are very elementary. */ void XMLCALL DavXmlStartElement ( REQUEST_STRUCT *rqptr, char *ElementPtr, char **AttrPtr ) { int idx; char *cptr, *sptr; STR_DSC *sdptr; STR_DSC_AUTO (ScratchDsc); WEBDAV_LOCK *lckptr; WEBDAV_PROP *proptr; WEBDAV_TASK *tkptr; WEBDAV_XML *xmlptr; /*********/ /* begin */ /*********/ if (WATCH_XML && WATCHMOD (rqptr, WATCH_MOD_WEBDAV)) WatchThis (WATCHITM(rqptr), WATCH_MOD_WEBDAV, "DavXmlStartElement() !UL", rqptr->WebDavTaskPtr->XmlData.ElementDepth+1); tkptr = rqptr->WebDavTaskPtr; lckptr = &tkptr->LockData; proptr = &tkptr->PropData; xmlptr = &tkptr->XmlData; xmlptr->ElementDepth++; if (WATCH_XML && WATCHMOD (rqptr, WATCH_MOD_WEBDAV)) { WatchThis (WATCHITM(rqptr), WATCH_MOD_WEBDAV, "ELEMENT !AZ", ElementPtr); for (idx = 0; AttrPtr[idx]; idx += 2) WatchDataFormatted ("!AZ=\"!AZ\"\n", AttrPtr[idx], AttrPtr[idx+1]); } sdptr = NULL; if (WEBDAV_IS_PARSING(xmlptr->ParseSet) && WEBDAV_IS_PARSING(xmlptr->ParseProp)) sdptr = &xmlptr->PropSetDsc; else if (WEBDAV_IS_PARSING(xmlptr->ParseRemove) && WEBDAV_IS_PARSING(xmlptr->ParseProp)) sdptr = &xmlptr->PropRemoveDsc; else if (WEBDAV_IS_PARSING(xmlptr->ParseLockOwner)) sdptr = &lckptr->OwnerDsc; if (WEBDAV_IS_PARSING(xmlptr->ParseLockInfo)) { /************/ /* lockinfo */ /************/ StrDscColIfNotBegin (rqptr, &lckptr->OwnerDsc, 256); /* initialise the descriptor to reallocate expanded storage */ STR_DSC_REALLOC(&lckptr->OwnerDsc, 256); if (WEBDAV_IS_PARSING(xmlptr->ParseLockType)) { if (WEBDAV_IS_DAVEL(ElementPtr, "write")) lckptr->Type = WEBDAV_LOCK_TYPE_WRITE; } else if (WEBDAV_IS_PARSING(xmlptr->ParseLockScope)) { if (WEBDAV_IS_DAVEL(ElementPtr, "exclusive")) lckptr->Scope = WEBDAV_LOCK_SCOPE_EXCLUSIVE; else if (WEBDAV_IS_DAVEL(ElementPtr, "shared")) lckptr->Scope = WEBDAV_LOCK_SCOPE_SHARED; } else if (WEBDAV_IS_DAVEL(ElementPtr, "locktype")) WEBDAV_PARSING(xmlptr->ParseLockType); else if (WEBDAV_IS_DAVEL(ElementPtr, "lockscope")) WEBDAV_PARSING(xmlptr->ParseLockScope); else if (WEBDAV_IS_DAVEL(ElementPtr, "owner")) { WEBDAV_PARSING(xmlptr->ParseLockOwner); WEBDAV_PARSING(xmlptr->ParseCharData); } } else if (WEBDAV_IS_PARSING(xmlptr->ParsePropFind)) { /************/ /* propfind */ /************/ if (WEBDAV_IS_DAVEL(ElementPtr, "allprop")) proptr->AllProp = true; else if (WEBDAV_IS_DAVEL(ElementPtr, "creationdate")) proptr->CreationDate = true; else if (WEBDAV_IS_DAVEL(ElementPtr, "displayname")) proptr->DisplayName = true; else if (WEBDAV_IS_DAVEL(ElementPtr, "resourcetype")) proptr->ResourceType = true; else if (WEBDAV_IS_DAVEL(ElementPtr, "getcontenttype")) proptr->GetContentType = true; else if (WEBDAV_IS_DAVEL(ElementPtr, "getcontentlength")) proptr->GetContentLength = true; else if (WEBDAV_IS_DAVEL(ElementPtr, "getetag")) proptr->GetEtag = true; else if (WEBDAV_IS_DAVEL(ElementPtr, "getlastmodified")) proptr->GetLastModified = true; else if (WEBDAV_IS_DAVEL(ElementPtr, "lockdiscovery")) proptr->LockDiscovery = true; else if (WEBDAV_IS_DAVEL(ElementPtr, "propname")) proptr->PropName = true; else if (WEBDAV_IS_DAVEL(ElementPtr, "supportedlock")) proptr->SupportedLock = true; else if (WEBDAV_IS_DAVEL(ElementPtr, "quota-available-bytes")) proptr->QuotaAvailableBytes = true; else if (WEBDAV_IS_DAVEL(ElementPtr, "quota-used-bytes")) proptr->QuotaUsedBytes = true; else if (!WEBDAV_IS_DAVEL(ElementPtr, "prop")) { /* stored and searched for in the dead properties */ sdptr = &xmlptr->PropFindDsc; proptr->FindProp = true; WEBDAV_PARSING(xmlptr->ParseFind); } if (WATCHING (rqptr, WATCH_WEBDAV)) DavXmlWatchProp (rqptr); } else if (WEBDAV_IS_PARSING(xmlptr->ParsePropertyBehavior)) { /********************/ /* propertybehavior */ /********************/ if (WEBDAV_IS_DAVEL(ElementPtr, "keepalive")) proptr->PropertyBehaviorKeepalive = true; else if (WEBDAV_IS_DAVEL(ElementPtr, "omit")) proptr->PropertyBehaviorOmit = true; } else if (WEBDAV_IS_PARSING(xmlptr->ParsePropertyUpdate)) { /******************/ /* propertyupdate */ /******************/ if (WEBDAV_IS_PARSING(xmlptr->ParseSet) || WEBDAV_IS_PARSING(xmlptr->ParseRemove)) { if (WEBDAV_IS_DAVEL(ElementPtr, "prop")) WEBDAV_PARSING(xmlptr->ParseProp); } else if (WEBDAV_IS_DAVEL(ElementPtr, "set")) WEBDAV_PARSING(xmlptr->ParseSet); else if (WEBDAV_IS_DAVEL(ElementPtr, "remove")) WEBDAV_PARSING(xmlptr->ParseRemove); } else if (WEBDAV_IS_DAVEL(ElementPtr, "lockinfo")) WEBDAV_PARSING(xmlptr->ParseLockInfo); else if (WEBDAV_IS_DAVEL(ElementPtr, "propfind")) WEBDAV_PARSING(xmlptr->ParsePropFind); else if (WEBDAV_IS_DAVEL(ElementPtr, "propertybehavior")) WEBDAV_PARSING(xmlptr->ParsePropertyBehavior); else if (WEBDAV_IS_DAVEL(ElementPtr, "propertyupdate")) WEBDAV_PARSING(xmlptr->ParsePropertyUpdate); if (sdptr) { for (cptr = ElementPtr; *cptr && *cptr != ' '; cptr++); sdptr = StrDscBuild (sdptr, NULL, ""); if (WEBDAV_IS_PARSING(xmlptr->ParsePropFind)) STR_DSC_SET_FROZEN (sdptr) WEBDAV_PARSING(xmlptr->ParseCharData); } } /*****************************************************************************/ /* */ void XMLCALL DavXmlEndElement ( REQUEST_STRUCT *rqptr, char *ElementPtr ) { char *cptr, *sptr; STR_DSC *sdptr; STR_DSC_AUTO (ScratchDsc); WEBDAV_LOCK *lckptr; WEBDAV_TASK *tkptr; WEBDAV_XML *xmlptr; /*********/ /* begin */ /*********/ if (WATCH_XML && WATCHMOD (rqptr, WATCH_MOD_WEBDAV)) WatchThis (WATCHITM(rqptr), WATCH_MOD_WEBDAV, "DavXmlEndElement() !UL !AZ", rqptr->WebDavTaskPtr->XmlData.ElementDepth, ElementPtr); tkptr = rqptr->WebDavTaskPtr; lckptr = &tkptr->LockData; xmlptr = &tkptr->XmlData; if (WEBDAV_IS_PARSING(xmlptr->ParseLockInfo)) { if (WEBDAV_IS_PARSING(xmlptr->ParseLockScope) && WEBDAV_IS_DAVEL(ElementPtr, "lockscope")) WEBDAV_PARSED(xmlptr->ParseLockScope); else if (WEBDAV_IS_PARSING(xmlptr->ParseLockType) && WEBDAV_IS_DAVEL(ElementPtr, "locktype")) WEBDAV_PARSED(xmlptr->ParseLockType); else if (WEBDAV_IS_PARSING(xmlptr->ParseLockOwner) && WEBDAV_IS_DAVEL(ElementPtr, "owner")) { WEBDAV_PARSED(xmlptr->ParseLockOwner); DavXmlTrimElement (&lckptr->OwnerDsc); if (WATCH_XML && WATCHMOD (rqptr, WATCH_MOD_WEBDAV)) WatchThis (WATCHITM(rqptr), WATCH_MOD_WEBDAV, "!&Z", STR_DSC_PTR(&lckptr->OwnerDsc)); } else if (WEBDAV_IS_DAVEL(ElementPtr, "lockinfo")) WEBDAV_PARSED(xmlptr->ParseLockInfo); } else if (WEBDAV_IS_PARSING(xmlptr->ParsePropFind)) { if (WEBDAV_IS_DAVEL(ElementPtr, "propfind")) WEBDAV_PARSED(xmlptr->ParsePropFind); else WEBDAV_PARSED(xmlptr->ParseFind); } else if (WEBDAV_IS_PARSING(xmlptr->ParsePropertyBehavior)) { if (WEBDAV_IS_DAVEL(ElementPtr, "propertybehavior")) WEBDAV_PARSED(xmlptr->ParsePropertyBehavior); } else if (WEBDAV_IS_PARSING(xmlptr->ParsePropertyUpdate)) { if (WEBDAV_IS_PARSING(xmlptr->ParseSet)) { if (WEBDAV_IS_PARSING(xmlptr->ParseProp)) { if (WEBDAV_IS_DAVEL(ElementPtr, "prop")) WEBDAV_PARSED(xmlptr->ParseProp); } else if (WEBDAV_IS_DAVEL(ElementPtr, "set")) WEBDAV_PARSED(xmlptr->ParseSet); } else if (WEBDAV_IS_PARSING(xmlptr->ParseRemove)) { if (WEBDAV_IS_PARSING(xmlptr->ParseProp)) { if (WEBDAV_IS_DAVEL(ElementPtr, "prop")) WEBDAV_PARSED(xmlptr->ParseProp); } else if (WEBDAV_IS_DAVEL(ElementPtr, "remove")) WEBDAV_PARSED(xmlptr->ParseRemove); } else if (WEBDAV_IS_DAVEL(ElementPtr, "propertyupdate")) WEBDAV_PARSED(xmlptr->ParsePropertyUpdate); } sdptr = NULL; if (WEBDAV_IS_PARSING(xmlptr->ParseSet) && WEBDAV_IS_PARSING(xmlptr->ParseProp)) sdptr = &xmlptr->PropSetDsc; else if (WEBDAV_IS_PARSING(xmlptr->ParseRemove) && WEBDAV_IS_PARSING(xmlptr->ParseProp)) sdptr = &xmlptr->PropRemoveDsc; else if (WEBDAV_IS_PARSING(xmlptr->ParseLockOwner)) sdptr = &lckptr->OwnerDsc; if (sdptr) { for (cptr = ElementPtr; *cptr && *cptr != ' '; cptr++); sdptr = StrDscBuild (sdptr, NULL, ""); if (WEBDAV_IS_PARSING(xmlptr->ParseProp) && xmlptr->ElementDepth == 4) { /* end of this property, freeze current content */ STR_DSC_SET_FROZEN (sdptr) WEBDAV_NOT_PARSING(xmlptr->ParseCharData); } else WEBDAV_PARSING(xmlptr->ParseCharData); } else WEBDAV_NOT_PARSING(xmlptr->ParseCharData); if (xmlptr->ElementDepth) xmlptr->ElementDepth--; } /*****************************************************************************/ /* */ void XMLCALL DavXmlCharData ( REQUEST_STRUCT *rqptr, XML_Char *DataPtr, int DataLength ) { STR_DSC *sdptr; STR_DSC_AUTO (CharDataDsc); WEBDAV_LOCK *lckptr; WEBDAV_TASK *tkptr; WEBDAV_XML *xmlptr; /*********/ /* begin */ /*********/ if (WATCH_XML && WATCHMOD (rqptr, WATCH_MOD_WEBDAV)) WatchThis (WATCHITM(rqptr), WATCH_MOD_WEBDAV, "DavXmlCharData() !&B !UL |!#AZ", rqptr->WebDavTaskPtr->XmlData.ParseCharData, DataLength, DataLength, DataPtr); tkptr = rqptr->WebDavTaskPtr; lckptr = &tkptr->LockData; xmlptr = &tkptr->XmlData; if (!WEBDAV_IS_PARSING(xmlptr->ParseCharData)) return; if (WEBDAV_IS_PARSING(xmlptr->ParseSet) && WEBDAV_IS_PARSING(xmlptr->ParseProp)) sdptr = &xmlptr->PropSetDsc; else if (WEBDAV_IS_PARSING(xmlptr->ParseRemove) && WEBDAV_IS_PARSING(xmlptr->ParseProp)) sdptr = &xmlptr->PropRemoveDsc; else if (WEBDAV_IS_PARSING(xmlptr->ParseLockOwner)) sdptr = &lckptr->OwnerDsc; else sdptr = NULL; if (sdptr) { StrDscThis (NULL, &CharDataDsc, DataPtr, DataLength); StrDscBuild (sdptr, &CharDataDsc, NULL); } } /*****************************************************************************/ /* Trim leading and trailing white-space from a string containing an XML element. */ DavXmlTrimElement (STR_DSC *sdptr) { char *cptr, *sptr; /*********/ /* begin */ /*********/ if (!STR_DSC_PTR(sdptr) || !STR_DSC_LEN(sdptr)) return; for (cptr = STR_DSC_PTR(sdptr) + STR_DSC_LEN(sdptr); cptr > STR_DSC_PTR(sdptr) && *cptr != '>'; cptr--); if (cptr > STR_DSC_PTR(sdptr)) { *++cptr = '\0'; STR_DSC_LEN(sdptr) = cptr - STR_DSC_PTR(sdptr); } for (cptr = STR_DSC_PTR(sdptr); *cptr && *cptr != '<'; cptr++); if (cptr > STR_DSC_PTR(sdptr) && cptr < STR_DSC_PTR(sdptr) + STR_DSC_LEN(sdptr)) { for (sptr = STR_DSC_PTR(sdptr); *cptr; *sptr++ = *cptr++); *sptr = '\0'; STR_DSC_LEN(sdptr) = sptr - STR_DSC_PTR(sdptr); } } /*****************************************************************************/ /* Report on the XML. */ DavXmlReport (REQUEST_STRUCT *rqptr) { static char ReportFormFao [] = "
\n\

\n\ \n\
\ \n\
\n\

\   \   \    \n\

\n\ \n\ \n"; static char ReportPage1Fao [] = "

\n\ \n\
"; static char ReportPage2Fao [] = "
\n\ \n\ \n\ \n"; BOOL DisplayPlain, DisplayXML, ParseXML; int qlen, status, FieldValueSize, XmlTextLength; unsigned long FaoVector [16]; unsigned long *vecptr; char *qptr, *FieldValuePtr, *XmlTextPtr; char FieldName [256], FieldValue [256]; BODY_PROCESS *prptr; STR_DSC_AUTO (XmlTextDsc); WEBDAV_TASK *tkptr; WEBDAV_XML *xmlptr; /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD_WEBDAV)) WatchThis (WATCHITM(rqptr), WATCH_MOD_WEBDAV, "DavXmlReport()"); if (rqptr->rqHeader.ContentLength64) { if (!rqptr->rqBody.DataPtr) { /* read all of request body and then AST back to this function */ BodyReadBegin (rqptr, &DavXmlReport, &BodyProcessReadAll); return; } if (rqptr->rqBody.DataStatus != SS$_ENDOFFILE) { DavWebEnd (rqptr); return; } if (!(prptr = rqptr->rqBody.ProcessPtr)) { ErrorNoticed (rqptr, SS$_BUGCHECK, ErrorSanityCheck, FI_LI); rqptr->rqResponse.ErrorTextPtr = ErrorSanityCheck; ErrorVmsStatus (rqptr, SS$_BUGCHECK, FI_LI); DavWebEnd (rqptr); return; } FieldValueSize = prptr->BlockBufferCount; } else FieldValueSize = 256; FieldValuePtr = (char*)VmGetHeap (rqptr, FieldValueSize); DisplayPlain = DisplayXML = ParseXML = false; XmlTextPtr = ""; if (rqptr->rqHeader.Method == HTTP_METHOD_POST) { if (WATCHMOD (rqptr, WATCH_MOD_WEBDAV)) WatchThis (WATCHITM(rqptr), WATCH_MOD_WEBDAV, "!UL bytes", prptr->BlockBufferCount); qptr = prptr->BlockBufferPtr; qlen = prptr->BlockBufferCount; } else if (rqptr->rqHeader.QueryStringLength) { qptr = rqptr->rqHeader.QueryStringPtr; qlen = rqptr->rqHeader.QueryStringLength; } else { qptr = ""; qlen = 0; } while (*qptr) { status = StringParseQuery (&qptr, FieldName, sizeof(FieldName), FieldValuePtr, FieldValueSize); if (VMSnok (status)) { /* error occured */ if (status == SS$_IVCHAR) rqptr->rqResponse.HttpStatus = 400; rqptr->rqResponse.ErrorTextPtr = "parsing query string"; ErrorVmsStatus (rqptr, status, FI_LI); DavWebEnd (rqptr); return; } if (strsame (FieldName, "XMLtext", -1)) { XmlTextPtr = FieldValuePtr; /* subsequent fields into fixed storage */ FieldValuePtr = FieldValue; FieldValueSize = sizeof(FieldValue); } if (strsame (FieldName, "submit", -1)) { if (strsame (FieldValue, "Display XML", -1)) DisplayXML = true; else if (strsame (FieldValue, "Display Plain", -1)) DisplayPlain = true; else if (strsame (FieldValue, "Parse XML", -1)) ParseXML = true; } } if (DisplayXML) { StrDscBegin (rqptr, &rqptr->NetWriteBufferDsc, rqptr->rqHeader.ContentLength64); StrDscBuild (&rqptr->NetWriteBufferDsc, NULL, XmlTextPtr); XmlTextLength = StrDscLength (&rqptr->NetWriteBufferDsc); ResponseHeader (rqptr, 200, "text/xml; charset=\"utf-8\"", XmlTextLength, NULL, NULL); DavWebEnd (rqptr); return; } if (DisplayPlain) { StrDscBegin (rqptr, &rqptr->NetWriteBufferDsc, rqptr->rqHeader.ContentLength64); StrDscBuild (&rqptr->NetWriteBufferDsc, NULL, XmlTextPtr); XmlTextLength = StrDscLength (&rqptr->NetWriteBufferDsc); ResponseHeader (rqptr, 200, "text/plain", XmlTextLength, NULL, NULL); DavWebEnd (rqptr); return; } StrDscThis (NULL, &XmlTextDsc, XmlTextPtr, strlen(XmlTextPtr)); AdminPageTitle (rqptr, "WebDAV XML Parse Test Tool"); if (rqptr->rqHeader.Method == HTTP_METHOD_POST) { /* set up the task structure for the duration of the parse */ tkptr = rqptr->WebDavTaskPtr = VmGetHeap (rqptr, sizeof(WEBDAV_TASK)); xmlptr = &tkptr->XmlData; DavXmlParseText (rqptr, &XmlTextDsc); NetWriteBuffered (rqptr, NULL, ReportPage1Fao, sizeof(ReportPage1Fao)-1); if (STR_DSC_PTR(&xmlptr->ParseErrorDsc)) FaoToNet (rqptr, "

!&;AZ
", STR_DSC_PTR(&xmlptr->ParseErrorDsc)); else DavXmlReportOnParse (rqptr); NetWriteBuffered (rqptr, NULL, ReportPage2Fao, sizeof(ReportPage2Fao)-1); rqptr->rqResponse.PreExpired = PRE_EXPIRE_ADMIN; VmFreeFromHeap (rqptr, rqptr->WebDavTaskPtr, FI_LI); rqptr->WebDavTaskPtr = NULL; } else { FaolToNet (rqptr, ReportFormFao, &FaoVector); rqptr->rqResponse.PreExpired = 0; } ResponseHeader200 (rqptr, "text/html", &rqptr->NetWriteBufferDsc); AdminEnd (rqptr); } /*****************************************************************************/ /* Report on the XML elements. */ DavXmlReportOnParse (REQUEST_STRUCT *rqptr) { STR_DSC *sdptr; WEBDAV_LOCK *lckptr; WEBDAV_PROP *proptr; WEBDAV_TASK *tkptr; WEBDAV_XML *xmlptr; /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD_WEBDAV)) WatchThis (WATCHITM(rqptr), WATCH_MOD_WEBDAV, "DavXmlReportOnParse()"); tkptr = rqptr->WebDavTaskPtr; lckptr = &tkptr->LockData; proptr = &tkptr->PropData; xmlptr = &tkptr->XmlData; FaoToNet (rqptr, "
    \n"); if (WEBDAV_IS_PARSED(xmlptr->ParseLockInfo)) { FaoToNet (rqptr, "

  • lockinfo\n
      \n"); if (lckptr->Type == WEBDAV_LOCK_TYPE_WRITE) FaoToNet (rqptr, "
    • write\n"); if (lckptr->Scope == WEBDAV_LOCK_SCOPE_EXCLUSIVE) FaoToNet (rqptr, "
    • exclusive\n"); else if (lckptr->Scope == WEBDAV_LOCK_SCOPE_SHARED) FaoToNet (rqptr, "
    • shared\n"); if (STR_DSC_PTR(&lckptr->OwnerDsc)) FaoToNet (rqptr, "
    • owner:
      !&;AZ
      \n", STR_DSC_PTR(&lckptr->OwnerDsc)); FaoToNet (rqptr, "
    \n"); } if (WEBDAV_IS_PARSED(xmlptr->ParsePropFind)) { FaoToNet (rqptr, "

  • propfind\n
      \n"); if (proptr->AllProp) FaoToNet (rqptr, "
    • allprop\n"); if (proptr->CreationDate) FaoToNet (rqptr, "
    • creationdate\n"); if (proptr->DisplayName) FaoToNet (rqptr, "
    • displayname\n"); if (proptr->ResourceType) FaoToNet (rqptr, "
    • resourcetype\n"); if (proptr->GetContentType) FaoToNet (rqptr, "
    • getcontenttype\n"); if (proptr->GetContentLength) FaoToNet (rqptr, "
    • getcontentlength\n"); if (proptr->GetEtag) FaoToNet (rqptr, "
    • getetag\n"); if (proptr->GetLastModified) FaoToNet (rqptr, "
    • getlastmodified\n"); if (proptr->LockDiscovery) FaoToNet (rqptr, "
    • lockdiscovery\n"); if (proptr->PropName) FaoToNet (rqptr, "
    • propname\n"); if (proptr->SupportedLock) FaoToNet (rqptr, "
    • supportedlock\n"); if (proptr->QuotaAvailableBytes) FaoToNet (rqptr, "
    • quota-available-bytes\n"); if (proptr->QuotaUsedBytes) FaoToNet (rqptr, "
    • quota-used-bytes\n"); FaoToNet (rqptr, "
    \n"); } if (WEBDAV_IS_PARSED(xmlptr->ParsePropertyBehavior)) { FaoToNet (rqptr, "

  • propertybehaviour\n
      \n"); if (proptr->PropertyBehaviorKeepalive) FaoToNet (rqptr, "
    • keepalive\n"); if (proptr->PropertyBehaviorOmit) FaoToNet (rqptr, "
    • omit\n"); FaoToNet (rqptr, "
    \n"); } STR_DSC_ITERATE (sdptr, &xmlptr->PropSetDsc) if (STR_DSC_LEN(sdptr)) FaoToNet (rqptr, "

  • set prop
    !&;AZ
    \n", STR_DSC_PTR(sdptr)); STR_DSC_ITERATE (sdptr, &xmlptr->PropRemoveDsc) if (STR_DSC_LEN(sdptr)) FaoToNet (rqptr, "

  • remove prop
    !&;AZ
    \n", STR_DSC_PTR(sdptr)); FaoToNet (rqptr, "

\n"); } /*****************************************************************************/ /* WATCH the XML elements. */ DavXmlWatchProp (REQUEST_STRUCT *rqptr) { int size; char buf [1024]; STR_DSC *sdptr; WEBDAV_LOCK *lckptr; WEBDAV_PROP *proptr; WEBDAV_TASK *tkptr; WEBDAV_XML *xmlptr; /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD_WEBDAV)) WatchThis (WATCHITM(rqptr), WATCH_MOD_WEBDAV, "DavXmlWatchProp()"); tkptr = rqptr->WebDavTaskPtr; lckptr = &tkptr->LockData; proptr = &tkptr->PropData; xmlptr = &tkptr->XmlData; if (WEBDAV_IS_PARSED(xmlptr->ParseLockInfo)) { buf[0] = '\0'; size = sizeof(buf); if (STR_DSC_LEN(&lckptr->OwnerDsc)) FaoToBuffer (buf, sizeof(buf)/2, NULL, " owner:\"!AZ\"", STR_DSC_PTR(&lckptr->OwnerDsc)); if (lckptr->Type == WEBDAV_LOCK_TYPE_WRITE) strzcat (buf, " write", size); if (lckptr->Scope == WEBDAV_LOCK_SCOPE_EXCLUSIVE) strzcat (buf, " exclusive", size); else if (lckptr->Scope == WEBDAV_LOCK_SCOPE_SHARED) strzcat (buf, " shared", size); WatchThis (WATCHITM(rqptr), WATCH_WEBDAV, "LOCKINFO!AZ", buf); } if (WEBDAV_IS_PARSED(xmlptr->ParsePropFind)) { buf[0] = '\0'; size = sizeof(buf); if (proptr->AllProp) strzcat (buf, " allprop", size); if (proptr->CreationDate) strzcat (buf, " creationdate", size); if (proptr->DisplayName) strzcat (buf, " displayname", size); if (proptr->ResourceType) strzcat (buf, " resourcetype", size); if (proptr->GetContentType) strzcat (buf, " getcontenttype", size); if (proptr->GetContentLength) strzcat (buf, " getcontentlength", size); if (proptr->GetEtag) strzcat (buf, " getetag", size); if (proptr->GetLastModified) strzcat (buf, " getlastmodified", size); if (proptr->LockDiscovery) strzcat (buf, " lockdiscovery", size); if (proptr->PropName) strzcat (buf, " propname", size); if (proptr->SupportedLock) strzcat (buf, " supportedlock", size); if (proptr->QuotaAvailableBytes) strzcat (buf, " quota-available-bytes", size); if (proptr->QuotaUsedBytes) strzcat (buf, "quota-used-bytes ", size); WatchThis (WATCHITM(rqptr), WATCH_WEBDAV, "PROPFIND!AZ", buf); } if (WEBDAV_IS_PARSED(xmlptr->ParsePropertyBehavior)) { buf[0] = '\0'; size = sizeof(buf); if (proptr->PropertyBehaviorKeepalive) strzcat (buf, " keepalive", size); if (proptr->PropertyBehaviorOmit) strzcat (buf, " omit", size); WatchThis (WATCHITM(rqptr), WATCH_WEBDAV, "PROPERTYBEHAVIOUR!AZ", buf); } STR_DSC_ITERATE (sdptr, &xmlptr->PropSetDsc) if (STR_DSC_LEN(sdptr)) WatchThis (WATCHITM(rqptr), WATCH_WEBDAV, "SET !AZ", STR_DSC_PTR(sdptr)); STR_DSC_ITERATE (sdptr, &xmlptr->PropRemoveDsc) if (STR_DSC_LEN(sdptr)) WatchThis (WATCHITM(rqptr), WATCH_WEBDAV, "REMOVE !AZ", STR_DSC_PTR(sdptr)); } /*****************************************************************************/