Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

517 lines
12 KiB

  1. /*
  2. * X L O C K . C P P
  3. *
  4. * XML push model parsing for LOCK requests
  5. *
  6. * Copyright 1986-1997 Microsoft Corporation, All Rights Reserved
  7. */
  8. #include "_xml.h"
  9. #include <xlock.h>
  10. #include <statetok.h>
  11. // Here are our LOCK XML elements
  12. //
  13. const WCHAR gc_wszLockActive[] = L"DAV:activelock";
  14. const WCHAR gc_wszLockDepth[] = L"DAV:depth";
  15. const WCHAR gc_wszLockDiscovery[] = L"DAV:lockdiscovery";
  16. const WCHAR gc_wszLockEntry[] = L"DAV:lockentry";
  17. const WCHAR gc_wszLockInfo[] = L"DAV:lockinfo";
  18. const WCHAR gc_wszLockOwner[] = L"DAV:owner";
  19. const WCHAR gc_wszLockScope[] = L"DAV:lockscope";
  20. const WCHAR gc_wszLockScopeExclusive[] = L"DAV:exclusive";
  21. const WCHAR gc_wszLockScopeShared[] = L"DAV:shared";
  22. const WCHAR gc_wszLockSupportedlock[] = L"DAV:supportedlock";
  23. const WCHAR gc_wszLockTimeout[] = L"DAV:timeout";
  24. const WCHAR gc_wszLockToken[] = L"DAV:locktoken";
  25. const WCHAR gc_wszLockType[] = L"DAV:locktype";
  26. const WCHAR gc_wszLockTypeWrite[] = L"DAV:write";
  27. const WCHAR gc_wszLockTypeCheckout[] = L"DAV:checkout";
  28. const WCHAR gc_wszLockTypeTransaction[] = L"DAV:transaction";
  29. const WCHAR gc_wszLockTypeTransactionGOP[] = L"DAV:groupoperation";
  30. const WCHAR gc_wszLockScopeLocal[] = L"DAV:local";
  31. // And one item from the rollback draft.
  32. //
  33. const WCHAR gc_wszLockRollback[] = L"http://www.iana.org/experimental/msrollback/rollback";
  34. // UNLOCK xml elememts
  35. //
  36. const WCHAR gc_wszUnlockInfo[] = L"DAV:unlockinfo";
  37. const WCHAR gc_wszCancelCheckout[] = L"DAV:cancelcheckout";
  38. const WCHAR gc_wszComment[] = L"DAV:comment";
  39. const WCHAR gc_wszTransactionInfo[] = L"DAV:transactioninfo";
  40. const WCHAR gc_wszTransactionStatus[] = L"DAV:transactionstatus";
  41. const WCHAR gc_wszCommit[] = L"DAV:commit";
  42. const WCHAR gc_wszAbort[] = L"DAV:abort";
  43. // class CNFLock -------------------------------------------------------------
  44. //
  45. SCODE
  46. CNFLock::ScCompleteAttribute (void)
  47. {
  48. // When we have gotten here, we have started processing
  49. // owner node attributes and all cached namespaces have
  50. // been added.
  51. //
  52. if (m_state == ST_OWNER)
  53. return m_xo.ScCompleteChildren ( FALSE, XML_ATTRIBUTE, L"", 0 );
  54. return S_OK;
  55. }
  56. SCODE
  57. CNFLock::ScCompleteChildren (
  58. /* [in] */ BOOL fEmptyNode,
  59. /* [in] */ DWORD dwType,
  60. /* [in] */ const WCHAR __RPC_FAR *pwcText,
  61. /* [in] */ ULONG ulLen)
  62. {
  63. SCODE sc = S_OK;
  64. // Handle owner processing first....
  65. //
  66. if (ST_OWNER == m_state)
  67. {
  68. sc = m_xo.ScCompleteChildren (fEmptyNode,
  69. dwType,
  70. pwcText,
  71. ulLen);
  72. if (FAILED (sc))
  73. goto ret;
  74. }
  75. // Handle the rest...
  76. //
  77. switch (dwType)
  78. {
  79. case XML_ELEMENT:
  80. switch (m_state)
  81. {
  82. case ST_LOCKINFO:
  83. m_state = ST_NODOC;
  84. break;
  85. case ST_OWNER:
  86. if (0 == m_xo.LDepth())
  87. {
  88. // Complete the owner comment buffer
  89. //
  90. m_state = ST_LOCKINFO;
  91. m_sbOwner.Append (sizeof(WCHAR), L"\0");
  92. XmlTrace ("Xml: Lock: owner XML body:\n%ws\n",
  93. m_sbOwner.PContents());
  94. }
  95. break;
  96. case ST_TYPE:
  97. m_state = ST_LOCKINFO;
  98. break;
  99. case ST_INTYPE:
  100. m_state = ST_TYPE;
  101. break;
  102. case ST_INTYPE_TRANS:
  103. m_state = ST_INTYPE;
  104. break;
  105. case ST_SCOPE:
  106. m_state = ST_LOCKINFO;
  107. break;
  108. case ST_INSCOPE:
  109. m_state = ST_SCOPE;
  110. break;
  111. case ST_ROLLBACK:
  112. m_state = ST_LOCKINFO;
  113. break;
  114. }
  115. }
  116. ret:
  117. return sc;
  118. }
  119. SCODE
  120. CNFLock::ScHandleNode (
  121. /* [in] */ DWORD dwType,
  122. /* [in] */ DWORD dwSubType,
  123. /* [in] */ BOOL fTerminal,
  124. /* [in] */ const WCHAR __RPC_FAR *pwcText,
  125. /* [in] */ ULONG ulLen,
  126. /* [in] */ ULONG ulNamespaceLen,
  127. /* [in] */ const WCHAR __RPC_FAR *pwcNamespace,
  128. /* [in] */ const ULONG ulNsPrefixLen)
  129. {
  130. CStackBuffer<WCHAR> wsz;
  131. LPCWSTR pwszTag = NULL;
  132. SCODE sc = S_FALSE;
  133. UINT cch;
  134. switch (dwType)
  135. {
  136. case XML_ELEMENT:
  137. // Construct the full name of the node
  138. //
  139. cch = ulNamespaceLen + ulLen;
  140. pwszTag = wsz.resize(CbSizeWsz(cch));
  141. if (NULL == pwszTag)
  142. {
  143. sc = E_OUTOFMEMORY;
  144. break;
  145. }
  146. wcsncpy (wsz.get(), pwcNamespace, ulNamespaceLen);
  147. wcsncpy (wsz.get() + ulNamespaceLen, pwcText, ulLen);
  148. *(wsz.get() + cch) = 0;
  149. switch (m_state)
  150. {
  151. case ST_NODOC:
  152. // If this is the topmost node in a propfind request,
  153. // transition to the next state. Since there is no parent
  154. // node to provide scoping, FIsTag() cannot be used here!
  155. //
  156. if (!wcscmp (pwszTag, gc_wszLockInfo))
  157. {
  158. m_state = ST_LOCKINFO;
  159. sc = S_OK;
  160. }
  161. break;
  162. case ST_LOCKINFO:
  163. // Look for our well know node types
  164. //
  165. if (FIsTag (pwszTag, gc_wszLockOwner))
  166. {
  167. CEmitNmspc cen(m_xo);
  168. // Make the state transition and start recording
  169. //
  170. m_sbOwner.Reset();
  171. m_state = ST_OWNER;
  172. sc = m_xo.ScHandleNode (dwType,
  173. dwSubType,
  174. fTerminal,
  175. pwcText,
  176. ulLen,
  177. ulNamespaceLen,
  178. pwcNamespace,
  179. ulNsPrefixLen);
  180. // Spit out the namespaces.
  181. //
  182. // Note that this will spit out any namespaces
  183. // decl'd in the DAV:owner node itself. So we
  184. // do not really want to emit these out to the
  185. // owners comments until ScCompleteAttribute()
  186. // is called.
  187. //
  188. Assert (!m_xo.FAddNamespaceDecl());
  189. m_cache.ForEach(cen);
  190. sc = S_OK;
  191. }
  192. else if (FIsTag (pwszTag, gc_wszLockRollback))
  193. {
  194. m_dwRollback = DAV_LOCKTYPE_ROLLBACK;
  195. m_state = ST_ROLLBACK;
  196. sc = S_OK;
  197. }
  198. else if (FIsTag (pwszTag, gc_wszLockType))
  199. {
  200. m_state = ST_TYPE;
  201. sc = S_OK;
  202. }
  203. else if (FIsTag (pwszTag, gc_wszLockScope))
  204. {
  205. m_state = ST_SCOPE;
  206. sc = S_OK;
  207. }
  208. break;
  209. case ST_TYPE:
  210. if (FIsTag (pwszTag, gc_wszLockTypeWrite))
  211. {
  212. XmlTrace ("Xml: Lock: request is for a WRITE lock\n");
  213. m_dwLockType |= GENERIC_WRITE;
  214. m_state = ST_INTYPE;
  215. sc = S_OK;
  216. }
  217. else if (FIsTag (pwszTag, gc_wszLockTypeCheckout))
  218. {
  219. XmlTrace ("Xml: Lock: request is for a CHECKOUT lock\n");
  220. m_dwLockType |= DAV_LOCKTYPE_CHECKOUT;
  221. m_state = ST_INTYPE;
  222. sc = S_OK;
  223. }
  224. else if (FIsTag (pwszTag, gc_wszLockTypeTransaction))
  225. {
  226. XmlTrace ("Xml: Lock: request is for a TRANSACTION lock\n");
  227. m_state = ST_INTYPE_TRANS;
  228. sc = S_OK;
  229. }
  230. #ifdef DBG
  231. if (!_wcsicmp (pwszTag, L"read"))
  232. {
  233. XmlTrace ("Xml: Lock: request is for a READ lock\n");
  234. m_dwLockType |= GENERIC_READ;
  235. m_state = ST_INTYPE;
  236. sc = S_OK;
  237. }
  238. #endif // DBG
  239. break;
  240. case ST_SCOPE:
  241. if (FIsTag (pwszTag, gc_wszLockScopeExclusive))
  242. {
  243. XmlTrace ("Xml: Lock: request is for an EXCLUSE lock\n");
  244. m_dwScope = DAV_EXCLUSIVE_LOCK;
  245. m_state = ST_INSCOPE;
  246. sc = S_OK;
  247. }
  248. else if (FIsTag (pwszTag, gc_wszLockScopeShared))
  249. {
  250. XmlTrace ("Xml: Lock: request is for a SHARED lock\n");
  251. m_dwScope = DAV_SHARED_LOCK;
  252. m_state = ST_INSCOPE;
  253. sc = S_OK;
  254. }
  255. else if (FIsTag (pwszTag, gc_wszLockScopeLocal))
  256. {
  257. XmlTrace ("Xml: Lock: request is for a LOCAL scope lock\n");
  258. m_dwScope = DAV_LOCKSCOPE_LOCAL;
  259. m_state = ST_INSCOPE;
  260. sc = S_OK;
  261. }
  262. break;
  263. case ST_OWNER:
  264. sc = m_xo.ScHandleNode (dwType,
  265. dwSubType,
  266. fTerminal,
  267. pwcText,
  268. ulLen,
  269. ulNamespaceLen,
  270. pwcNamespace,
  271. ulNsPrefixLen);
  272. break;
  273. case ST_INTYPE_TRANS:
  274. if (FIsTag (pwszTag, gc_wszLockTypeTransactionGOP))
  275. {
  276. XmlTrace ("Xml: Lock: request is for a TRANSACTION GOP lock\n");
  277. m_dwLockType |= DAV_LOCKTYPE_TRANSACTION_GOP;
  278. m_state = ST_INTYPE_TRANS;
  279. sc = S_OK;
  280. }
  281. }
  282. break;
  283. default:
  284. // If we are processing the owner, continue
  285. // to do so...
  286. //
  287. if (ST_OWNER == m_state)
  288. {
  289. sc = m_xo.ScHandleNode (dwType,
  290. dwSubType,
  291. fTerminal,
  292. pwcText,
  293. ulLen,
  294. ulNamespaceLen,
  295. pwcNamespace,
  296. ulNsPrefixLen);
  297. }
  298. break;
  299. }
  300. return sc;
  301. }
  302. SCODE
  303. CNFLock::ScCompleteCreateNode (
  304. /* [in] */ DWORD dwType)
  305. {
  306. if (ST_OWNER == m_state)
  307. m_xo.CompleteCreateNode (dwType);
  308. return S_OK;
  309. }
  310. // class CNFUnlock -------------------------------------------------------------
  311. //
  312. SCODE
  313. CNFUnlock::ScCompleteAttribute (void)
  314. {
  315. return S_OK;
  316. }
  317. SCODE
  318. CNFUnlock::ScCompleteChildren (
  319. /* [in] */ BOOL fEmptyNode,
  320. /* [in] */ DWORD dwType,
  321. /* [in] */ const WCHAR __RPC_FAR *pwcText,
  322. /* [in] */ ULONG ulLen)
  323. {
  324. // Handle the rest...
  325. //
  326. switch (m_state)
  327. {
  328. case ST_UNLOCKINFO:
  329. m_state = ST_NODOC;
  330. break;
  331. case ST_COMMENT:
  332. case ST_CANCELCHECKOUT:
  333. m_state = ST_UNLOCKINFO;
  334. break;
  335. }
  336. return S_OK;
  337. }
  338. SCODE
  339. CNFUnlock::ScHandleNode (
  340. /* [in] */ DWORD dwType,
  341. /* [in] */ DWORD dwSubType,
  342. /* [in] */ BOOL fTerminal,
  343. /* [in] */ const WCHAR __RPC_FAR *pwcText,
  344. /* [in] */ ULONG ulLen,
  345. /* [in] */ ULONG ulNamespaceLen,
  346. /* [in] */ const WCHAR __RPC_FAR *pwcNamespace,
  347. /* [in] */ const ULONG ulNsPrefixLen)
  348. {
  349. CStackBuffer<WCHAR> wsz;
  350. LPCWSTR pwszTag = NULL;
  351. SCODE sc = S_FALSE;
  352. UINT cch;
  353. switch (dwType)
  354. {
  355. case XML_ELEMENT:
  356. // Construct the full name of the node
  357. //
  358. cch = ulNamespaceLen + ulLen;
  359. pwszTag = wsz.resize(CbSizeWsz(cch));
  360. if (NULL == pwszTag)
  361. {
  362. sc = E_OUTOFMEMORY;
  363. break;
  364. }
  365. wcsncpy (wsz.get(), pwcNamespace, ulNamespaceLen);
  366. wcsncpy (wsz.get() + ulNamespaceLen, pwcText, ulLen);
  367. *(wsz.get() + cch) = 0;
  368. switch (m_state)
  369. {
  370. case ST_NODOC:
  371. // If this is the topmost node in a propfind request,
  372. // transition to the next state. Since there is no parent
  373. // node to provide scoping, FIsTag() cannot be used here!
  374. //
  375. if (!wcscmp (pwszTag, gc_wszUnlockInfo))
  376. {
  377. m_state = ST_UNLOCKINFO;
  378. sc = S_OK;
  379. }
  380. else if (FIsTag (pwszTag, gc_wszTransactionInfo))
  381. {
  382. m_state = ST_TRANSACTIONINFO;
  383. sc = S_OK;
  384. }
  385. break;
  386. case ST_UNLOCKINFO:
  387. // Look for our well know node types
  388. //
  389. if (FIsTag (pwszTag, gc_wszComment))
  390. {
  391. m_state = ST_COMMENT;
  392. sc = S_OK;
  393. }
  394. else if (FIsTag (pwszTag, gc_wszCancelCheckout))
  395. {
  396. m_fCancelCheckout = TRUE;
  397. m_state = ST_CANCELCHECKOUT;
  398. sc = S_OK;
  399. }
  400. break;
  401. case ST_TRANSACTIONINFO:
  402. // Look for our well know node types
  403. //
  404. if (FIsTag (pwszTag, gc_wszTransactionStatus))
  405. {
  406. m_state = ST_TRANSACTIONSTATUS;
  407. sc = S_OK;
  408. }
  409. break;
  410. case ST_TRANSACTIONSTATUS:
  411. // Look for our well know node types
  412. //
  413. if (FIsTag (pwszTag, gc_wszCommit))
  414. {
  415. m_fCommitTransaction = TRUE;
  416. m_state = ST_TRANSACTIONSTATUS_COMMIT;
  417. sc = S_OK;
  418. }
  419. else if (FIsTag (pwszTag, gc_wszAbort))
  420. {
  421. m_fAbortTransaction = TRUE;
  422. m_state = ST_TRANSACTIONSTATUS_ABORT;
  423. sc = S_OK;
  424. }
  425. break;
  426. }
  427. break;
  428. case XML_PCDATA:
  429. // get unlock comment
  430. //
  431. if (m_state == ST_COMMENT)
  432. {
  433. // Keep the comment
  434. // It's a syntax error to have more than one comment
  435. //
  436. if (!m_wszComment.get())
  437. {
  438. m_wszComment = reinterpret_cast<LPWSTR>(ExAlloc((ulLen + 1) * sizeof(WCHAR)));
  439. Assert (m_wszComment.get());
  440. wcsncpy (m_wszComment.get(), pwcText, ulLen);
  441. m_wszComment[ulLen] = L'\0';
  442. sc = S_OK;
  443. }
  444. // else it's an error
  445. else
  446. sc = E_DAV_XML_PARSE_ERROR;
  447. }
  448. break;
  449. }
  450. return sc;
  451. }