[0001] [0002] [0003] [0004] [0005] [0006] [0007] [0008] [0009] [0010] [0011] [0012] [0013] [0014] [0015] [0016] [0017] [0018] [0019] [0020] [0021] [0022] [0023] [0024] [0025] [0026] [0027] [0028] [0029] [0030] [0031] [0032] [0033] [0034] [0035] [0036] [0037] [0038] [0039] [0040] [0041] [0042] [0043] [0044] [0045] [0046] [0047] [0048] [0049] [0050] [0051] [0052] [0053] [0054] [0055] [0056] [0057] [0058] [0059] [0060] [0061] [0062] [0063] [0064] [0065] [0066] [0067] [0068] [0069] [0070] [0071] [0072] [0073] [0074] [0075] [0076] [0077] [0078] [0079] [0080] [0081] [0082] [0083] [0084] [0085] [0086] [0087] [0088] [0089] [0090] [0091] [0092] [0093] [0094] [0095] [0096] [0097] [0098] [0099] [0100] [0101] [0102] [0103] [0104] [0105] [0106] [0107] [0108] [0109] [0110] [0111] [0112] [0113] [0114] [0115] [0116] [0117] [0118] [0119] [0120] [0121] [0122] [0123] [0124] [0125] [0126] [0127] [0128] [0129] [0130] [0131] [0132] [0133] [0134] [0135] [0136] [0137] [0138] [0139] [0140] [0141] [0142] [0143] [0144] [0145] [0146] [0147] [0148] [0149] [0150] [0151] [0152] [0153] [0154] [0155] [0156] [0157] [0158] [0159] [0160] [0161] [0162] [0163] [0164] [0165] [0166] [0167] [0168] [0169] [0170] [0171] [0172] [0173] [0174] [0175] [0176] [0177] [0178] [0179] [0180] [0181] [0182] [0183] [0184] [0185] [0186] [0187] [0188] [0189] [0190] [0191] [0192] [0193] [0194] [0195] [0196] [0197] [0198] [0199] [0200] [0201] [0202] [0203] [0204] [0205] [0206] [0207] [0208] [0209] [0210] [0211] [0212] [0213] [0214] [0215] [0216] [0217] [0218] [0219] [0220] [0221] [0222] [0223] [0224] [0225] [0226] [0227] [0228] [0229] [0230] [0231] [0232] [0233] [0234] [0235] [0236] [0237] [0238] [0239] [0240] [0241] [0242] [0243] [0244] [0245] [0246] [0247] [0248] [0249] [0250] [0251] [0252] [0253] [0254] [0255] [0256] [0257] [0258] [0259] [0260] [0261] [0262] [0263] [0264] [0265] [0266] [0267] [0268] [0269] [0270] [0271] [0272] [0273] [0274] [0275] [0276] [0277] [0278] [0279] [0280] [0281] [0282] [0283] [0284] [0285] [0286] [0287] [0288] [0289] [0290] [0291] [0292] [0293] [0294] [0295] [0296] [0297] [0298] [0299] [0300] [0301] [0302] [0303] [0304] [0305] [0306] [0307] [0308] [0309] [0310] [0311] [0312] [0313] [0314] [0315] [0316] [0317] [0318] [0319] [0320] [0321] [0322] [0323] [0324] [0325] [0326] [0327] [0328] [0329] [0330] [0331] [0332] [0333] [0334] [0335] [0336] [0337] [0338] [0339] [0340] [0341] [0342] [0343] [0344] [0345] [0346] [0347] [0348] [0349] [0350] [0351] [0352] [0353] [0354] [0355] [0356] [0357] [0358] [0359] [0360] [0361] [0362] [0363] [0364] [0365] [0366] [0367] [0368] [0369] [0370] [0371] [0372] [0373] [0374] [0375] [0376] [0377] [0378] [0379] [0380] [0381] [0382] [0383] [0384] [0385] [0386] [0387] [0388] [0389] [0390] [0391] [0392] [0393] [0394] [0395] [0396] [0397] [0398] [0399] [0400] [0401] [0402] [0403] [0404] [0405] [0406] [0407] [0408] [0409] [0410] [0411] [0412] [0413] [0414] [0415] [0416] [0417] [0418] [0419] [0420] [0421] [0422] [0423] [0424] [0425] [0426] [0427] [0428] [0429] [0430] [0431] [0432] [0433] [0434] [0435] [0436] [0437] [0438] [0439] [0440] [0441] [0442] [0443] [0444] [0445] [0446] [0447] [0448] [0449] [0450] [0451] [0452] [0453] [0454] [0455] [0456] [0457] [0458] [0459] [0460] [0461] [0462] [0463] [0464] [0465] [0466] [0467] [0468] [0469] [0470] [0471] [0472] [0473] [0474] [0475] [0476] [0477] [0478] [0479] [0480] [0481] [0482] [0483] [0484] [0485] [0486] [0487] [0488] [0489] [0490] [0491] [0492] [0493] [0494] [0495] [0496] [0497] [0498] [0499] [0500] [0501] [0502] [0503] [0504] [0505] [0506] [0507] [0508] [0509] [0510] [0511] [0512] [0513] [0514] [0515] [0516] [0517] [0518] [0519] [0520] [0521] [0522] [0523] [0524] [0525] [0526] [0527] [0528] [0529] [0530] [0531] [0532] [0533] [0534] [0535] [0536] [0537] [0538] [0539] [0540] [0541] [0542] [0543] [0544] [0545] [0546] [0547] [0548] [0549] [0550] [0551] [0552] [0553] [0554] [0555] [0556] [0557] [0558] [0559] [0560] [0561] [0562] [0563] [0564] [0565] [0566] [0567] [0568] [0569] [0570] [0571] [0572] [0573] [0574] [0575] [0576] [0577] [0578] [0579] [0580] [0581] [0582] [0583] [0584] [0585] [0586] [0587] [0588] [0589] [0590] [0591] [0592] [0593] [0594] [0595] [0596] [0597] [0598] [0599] [0600] [0601] [0602] [0603] [0604] [0605] [0606] [0607] [0608] [0609] [0610] [0611] [0612] [0613] [0614] [0615] [0616] [0617] [0618] [0619] [0620] [0621] [0622] [0623] [0624] [0625] [0626] [0627] [0628] [0629] [0630] [0631] [0632] [0633] [0634] [0635] [0636] [0637] [0638] [0639] [0640] [0641] [0642] [0643] [0644] [0645] [0646] [0647] [0648] [0649] [0650] [0651] [0652] [0653] [0654] [0655] [0656] [0657] [0658] [0659] [0660] [0661] [0662] [0663] [0664] [0665] [0666] [0667] [0668] [0669] [0670] [0671] [0672] [0673] [0674] [0675] [0676] [0677] [0678] [0679] [0680] [0681] [0682] [0683] [0684] [0685] [0686] [0687] [0688] [0689] [0690] [0691] [0692] [0693] [0694] [0695] [0696] [0697] [0698] [0699] [0700] [0701] [0702] [0703] [0704] [0705] [0706] [0707] [0708] [0709] [0710] [0711] [0712] [0713] [0714] [0715] [0716] [0717] [0718] [0719] [0720] [0721] [0722] [0723] [0724] [0725] [0726] [0727] [0728] [0729] [0730] [0731] [0732] [0733] [0734] [0735] [0736] [0737] [0738] [0739] [0740] [0741] [0742] [0743] [0744] [0745] [0746] [0747] [0748] [0749] [0750] [0751] [0752] [0753] [0754] [0755] [0756] [0757] [0758] [0759] [0760] [0761] [0762] [0763] [0764] [0765] [0766] [0767] [0768] [0769] [0770] [0771] [0772] [0773] [0774] [0775] [0776] [0777] [0778] [0779] [0780] [0781] [0782] [0783] [0784] [0785] [0786] [0787] [0788] [0789] [0790] [0791] [0792] [0793] [0794] [0795] [0796] [0797] [0798] [0799] [0800] [0801] [0802] [0803] [0804] [0805] [0806] [0807] [0808] [0809] [0810] [0811] [0812] [0813] [0814] [0815] [0816] [0817] [0818] [0819] [0820] [0821] [0822] [0823] [0824] [0825] [0826] [0827] [0828] [0829] [0830] [0831] [0832] [0833] [0834] [0835] [0836] [0837] [0838] [0839] [0840] [0841] [0842] [0843] [0844] [0845] [0846] [0847] [0848] [0849] [0850] [0851] [0852] [0853] [0854] [0855] [0856] [0857] [0858] [0859] [0860] [0861] [0862] [0863] [0864] [0865] [0866] [0867] [0868] [0869] [0870] [0871] [0872] [0873] [0874] [0875] [0876] [0877] [0878] [0879] [0880] [0881] [0882] [0883] [0884] [0885] [0886] [0887] [0888] [0889] [0890] [0891] [0892] [0893] [0894] [0895] [0896] [0897] [0898] [0899] [0900] [0901] [0902] [0903] [0904] [0905] [0906] [0907] [0908] [0909] [0910] [0911] [0912] [0913] [0914] [0915] [0916] [0917] [0918] [0919] [0920] [0921] [0922] [0923] [0924] [0925] [0926] [0927] [0928] [0929] [0930] [0931] [0932] [0933] [0934] [0935] [0936] [0937] [0938] [0939] [0940] [0941] [0942] [0943] [0944] [0945] [0946] [0947] [0948] [0949] [0950] [0951] [0952] [0953] [0954] [0955] [0956] [0957] [0958] [0959] [0960] [0961] [0962] [0963] [0964] [0965] [0966] [0967] [0968] [0969] [0970] [0971] [0972] [0973] [0974] [0975] [0976] [0977] [0978] [0979] [0980] [0981] [0982] [0983] [0984] [0985] [0986] [0987] [0988] [0989] [0990] [0991] [0992] [0993] [0994] [0995] [0996] [0997] [0998] [0999] [1000] [1001] [1002] [1003] [1004] [1005] [1006] [1007] [1008] [1009] [1010] [1011] [1012] [1013] [1014] [1015] [1016] [1017] [1018] [1019] [1020] [1021] [1022] [1023] [1024] [1025] [1026] [1027] [1028] [1029] [1030] [1031] [1032] [1033] [1034] [1035] [1036] [1037] [1038] [1039] [1040] [1041] [1042] [1043] [1044] [1045] [1046] [1047] [1048] [1049] [1050] [1051] [1052] [1053] [1054] [1055] [1056] [1057] [1058] [1059] [1060] [1061] [1062] [1063] [1064] [1065] [1066] [1067] [1068] [1069] [1070] [1071] [1072] [1073] [1074] [1075] [1076] [1077] [1078] [1079] [1080] [1081] [1082] [1083] [1084] [1085] [1086] [1087] [1088] [1089] [1090] [1091] [1092] [1093] [1094] [1095] [1096] [1097] [1098] [1099] [1100] [1101] [1102] [1103] [1104] [1105] [1106] [1107] [1108] [1109] [1110] [1111] [1112]
/*****************************************************************************/ /* 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 <ctype.h> #include <errno.h> #include <stdio.h> #include <libdef.h> #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, "<NS:"); StrDscBuild (sdptr, NULL, cptr+1); for (idx = 0; AttrPtr[idx]; idx += 2) { StrDscBuild (sdptr, NULL, " "); StrDscBuild (sdptr, NULL, AttrPtr[idx]); StrDscBuild (sdptr, NULL, "=\""); StrDscBuild (sdptr, NULL, AttrPtr[idx+1]); StrDscBuild (sdptr, NULL, "\""); } StrDscBuild (sdptr, NULL, " xmlns:NS=\""); StrDscThis (NULL, &ScratchDsc, ElementPtr, cptr - ElementPtr); StrDscBuild (sdptr, &ScratchDsc, NULL); 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, "</NS:"); StrDscBuild (sdptr, NULL, cptr+1); 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 [] = "<form action=\"" ADMIN_REPORT_WEBDAV_XML "\" METHOD=\"POST\" \ ENCtype=\"application/x-www-form-urlencoded\">\n\ <p><table cellpadding=\"1\" cellspacing=\"0\" border=\"0\">\n\ <tr><td>\ <textarea name=\"XMLtext\" id=\"XMLtext\" \ rows=\"24\" cols=\"80\" nowrap></textarea>\n\ </td></tr>\n\ </table>\n\ <p><input type=\"submit\" name=\"submit\" value=\"Parse XML\">\ <input type=\"submit\" name=\"submit\" value=\"Display XML\">\ <input type=\"submit\" name=\"submit\" value=\"Display Plain\">\ <input type=\"reset\" value=\"Clear\">\n\ </form>\n\ </body>\n\ </html>\n"; static char ReportPage1Fao [] = "<p><table cellpadding=\"5\" cellspacing=\"0\" border=\"1\">\n\ <tr><td>"; static char ReportPage2Fao [] = "</td></tr>\n\ </table>\n\ </tr></td>\n\ </body>\n\ </html>\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, "<pre>!&;AZ</pre>", 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, "<ul>\n"); if (WEBDAV_IS_PARSED(xmlptr->ParseLockInfo)) { FaoToNet (rqptr, "<p><li><b>lockinfo</b>\n<ul>\n"); if (lckptr->Type == WEBDAV_LOCK_TYPE_WRITE) FaoToNet (rqptr, "<li>write\n"); if (lckptr->Scope == WEBDAV_LOCK_SCOPE_EXCLUSIVE) FaoToNet (rqptr, "<li>exclusive\n"); else if (lckptr->Scope == WEBDAV_LOCK_SCOPE_SHARED) FaoToNet (rqptr, "<li>shared\n"); if (STR_DSC_PTR(&lckptr->OwnerDsc)) FaoToNet (rqptr, "<li>owner:<pre>!&;AZ</pre>\n", STR_DSC_PTR(&lckptr->OwnerDsc)); FaoToNet (rqptr, "</ul>\n"); } if (WEBDAV_IS_PARSED(xmlptr->ParsePropFind)) { FaoToNet (rqptr, "<p><li><b>propfind</b>\n<ul>\n"); if (proptr->AllProp) FaoToNet (rqptr, "<li>allprop\n"); if (proptr->CreationDate) FaoToNet (rqptr, "<li>creationdate\n"); if (proptr->DisplayName) FaoToNet (rqptr, "<li>displayname\n"); if (proptr->ResourceType) FaoToNet (rqptr, "<li>resourcetype\n"); if (proptr->GetContentType) FaoToNet (rqptr, "<li>getcontenttype\n"); if (proptr->GetContentLength) FaoToNet (rqptr, "<li>getcontentlength\n"); if (proptr->GetEtag) FaoToNet (rqptr, "<li>getetag\n"); if (proptr->GetLastModified) FaoToNet (rqptr, "<li>getlastmodified\n"); if (proptr->LockDiscovery) FaoToNet (rqptr, "<li>lockdiscovery\n"); if (proptr->PropName) FaoToNet (rqptr, "<li>propname\n"); if (proptr->SupportedLock) FaoToNet (rqptr, "<li>supportedlock\n"); if (proptr->QuotaAvailableBytes) FaoToNet (rqptr, "<li>quota-available-bytes\n"); if (proptr->QuotaUsedBytes) FaoToNet (rqptr, "<li>quota-used-bytes\n"); FaoToNet (rqptr, "</ul>\n"); } if (WEBDAV_IS_PARSED(xmlptr->ParsePropertyBehavior)) { FaoToNet (rqptr, "<p><li><b>propertybehaviour</b>\n<ul>\n"); if (proptr->PropertyBehaviorKeepalive) FaoToNet (rqptr, "<li>keepalive\n"); if (proptr->PropertyBehaviorOmit) FaoToNet (rqptr, "<li>omit\n"); FaoToNet (rqptr, "</ul>\n"); } STR_DSC_ITERATE (sdptr, &xmlptr->PropSetDsc) if (STR_DSC_LEN(sdptr)) FaoToNet (rqptr, "<p><li><b>set prop</b><pre>!&;AZ</pre>\n", STR_DSC_PTR(sdptr)); STR_DSC_ITERATE (sdptr, &xmlptr->PropRemoveDsc) if (STR_DSC_LEN(sdptr)) FaoToNet (rqptr, "<p><li><b>remove prop</b><pre>!&;AZ</pre>\n", STR_DSC_PTR(sdptr)); FaoToNet (rqptr, "</ul><p>\n"); } /*****************************************************************************/ /* WATCH the XML elements. */ DavXmlWatchProp (REQUEST_STRUCT *rqptr) { 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'; 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) strcat (buf, " write"); if (lckptr->Scope == WEBDAV_LOCK_SCOPE_EXCLUSIVE) strcat (buf, " exclusive"); else if (lckptr->Scope == WEBDAV_LOCK_SCOPE_SHARED) strcat (buf, " shared"); WatchThis (WATCHITM(rqptr), WATCH_WEBDAV, "LOCKINFO!AZ", buf); } if (WEBDAV_IS_PARSED(xmlptr->ParsePropFind)) { buf[0] = '\0'; if (proptr->AllProp) strcat (buf, " allprop"); if (proptr->CreationDate) strcat (buf, " creationdate"); if (proptr->DisplayName) strcat (buf, " displayname"); if (proptr->ResourceType) strcat (buf, " resourcetype"); if (proptr->GetContentType) strcat (buf, " getcontenttype"); if (proptr->GetContentLength) strcat (buf, " getcontentlength"); if (proptr->GetEtag) strcat (buf, " getetag"); if (proptr->GetLastModified) strcat (buf, " getlastmodified"); if (proptr->LockDiscovery) strcat (buf, " lockdiscovery"); if (proptr->PropName) strcat (buf, " propname"); if (proptr->SupportedLock) strcat (buf, " supportedlock"); if (proptr->QuotaAvailableBytes) strcat (buf, " quota-available-bytes"); if (proptr->QuotaUsedBytes) strcat (buf, "quota-used-bytes "); WatchThis (WATCHITM(rqptr), WATCH_WEBDAV, "PROPFIND!AZ", buf); } if (WEBDAV_IS_PARSED(xmlptr->ParsePropertyBehavior)) { buf[0] = '\0'; if (proptr->PropertyBehaviorKeepalive) strcat (buf, " keepalive"); if (proptr->PropertyBehaviorOmit) strcat (buf, " omit"); 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)); } /*****************************************************************************/