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.

288 lines
8.1 KiB

  1. #include "stdinc.h"
  2. #include "debmacro.h"
  3. #include "xmlns.h"
  4. #include "fusionheap.h"
  5. #include "smartptr.h"
  6. CXMLNamespaceManager::CXMLNamespaceManager(
  7. ) : m_CurrentDepth(0),
  8. m_DefaultNamespacePrefix(NULL)
  9. {
  10. }
  11. CXMLNamespaceManager::~CXMLNamespaceManager()
  12. {
  13. CSxsPreserveLastError ple;
  14. CNamespacePrefix *pCurrent = m_DefaultNamespacePrefix;
  15. // Clean up any namespace prefixes hanging around...
  16. while (pCurrent != NULL)
  17. {
  18. CNamespacePrefix *pNext = pCurrent->m_Previous;
  19. FUSION_DELETE_SINGLETON(pCurrent);
  20. pCurrent = pNext;
  21. }
  22. m_DefaultNamespacePrefix = NULL;
  23. CStringPtrTableIter<CNamespacePrefix, CUnicodeCharTraits> iter(m_NamespacePrefixes);
  24. for (iter.Reset(); iter.More(); iter.Next())
  25. iter.Delete();
  26. ple.Restore();
  27. }
  28. BOOL
  29. CXMLNamespaceManager::Initialize()
  30. {
  31. FN_PROLOG_WIN32
  32. IFW32FALSE_EXIT(m_NamespacePrefixes.Initialize());
  33. FN_EPILOG
  34. }
  35. HRESULT
  36. CXMLNamespaceManager::OnCreateNode(
  37. IXMLNodeSource *pSource,
  38. PVOID pNodeParent,
  39. USHORT cNumRecs,
  40. XML_NODE_INFO **apNodeInfo
  41. )
  42. {
  43. FN_PROLOG_HR
  44. USHORT i;
  45. CSmartPtr<CNamespacePrefix> NamespacePrefix;
  46. if ((cNumRecs != 0) &&
  47. (apNodeInfo[0]->dwType == XML_ELEMENT))
  48. {
  49. m_CurrentDepth++;
  50. for (i=0; i<cNumRecs; i++)
  51. {
  52. XML_NODE_INFO *Node = apNodeInfo[i];
  53. if (Node->dwType == XML_ATTRIBUTE)
  54. {
  55. if (Node->ulLen >= 5)
  56. {
  57. PCWSTR pwcText = Node->pwcText;
  58. // if it's not prefixed by "xmlns", we're not interested.
  59. if ((pwcText[0] != L'x') ||
  60. (pwcText[1] != L'm') ||
  61. (pwcText[2] != L'l') ||
  62. (pwcText[3] != L'n') ||
  63. (pwcText[4] != L's'))
  64. continue;
  65. // If it's longer than 5 characters and the next character isn't
  66. // a colon, it's not interesting.
  67. if ((Node->ulLen > 5) && (pwcText[5] != L':'))
  68. continue;
  69. IFW32FALSE_EXIT(NamespacePrefix.Win32Allocate(__FILE__, __LINE__));
  70. // walk the subsequent nodes, concatenating the values...
  71. i++;
  72. while (i < cNumRecs)
  73. {
  74. if (apNodeInfo[i]->dwType != XML_PCDATA)
  75. break;
  76. IFW32FALSE_EXIT(NamespacePrefix->m_NamespaceURI.Win32Append(apNodeInfo[i]->pwcText, apNodeInfo[i]->ulLen));
  77. i++;
  78. }
  79. i--;
  80. NamespacePrefix->m_Depth = m_CurrentDepth;
  81. if (Node->ulLen == 5)
  82. {
  83. NamespacePrefix->m_Previous = m_DefaultNamespacePrefix;
  84. m_DefaultNamespacePrefix = NamespacePrefix.Detach();
  85. }
  86. else
  87. {
  88. CSmallStringBuffer TextBuffer;
  89. // Unfortunately, we need the node name in a null terminated buffer. I tried modifying the hash
  90. // table code to handle more than one parameter for a key being passed through, but it ended
  91. // up being too much work.
  92. IFW32FALSE_EXIT(TextBuffer.Win32Assign(pwcText + 6, Node->ulLen - 6));
  93. IFW32FALSE_EXIT(
  94. m_NamespacePrefixes.InsertOrUpdateIf<CXMLNamespaceManager>(
  95. TextBuffer,
  96. NamespacePrefix.Detach(),
  97. this,
  98. &CXMLNamespaceManager::InsertOrUpdateIfCallback));
  99. }
  100. }
  101. }
  102. }
  103. }
  104. FN_EPILOG
  105. }
  106. HRESULT
  107. CXMLNamespaceManager::OnBeginChildren(
  108. IXMLNodeSource *pSource,
  109. XML_NODE_INFO *pNodeInfo
  110. )
  111. {
  112. // Nothing to do today, but we'll still have people reflect it through us so that we can do something
  113. // in the future if we need to.
  114. return S_OK;
  115. }
  116. HRESULT
  117. CXMLNamespaceManager::OnEndChildren(
  118. IXMLNodeSource *pSource,
  119. BOOL fEmpty,
  120. XML_NODE_INFO *pNodeInfo
  121. )
  122. {
  123. FN_PROLOG_HR;
  124. // Pop everything relevant off for this depth...
  125. if (m_DefaultNamespacePrefix != NULL)
  126. {
  127. if (m_DefaultNamespacePrefix->m_Depth == m_CurrentDepth)
  128. {
  129. CNamespacePrefix *Previous = m_DefaultNamespacePrefix->m_Previous;
  130. FUSION_DELETE_SINGLETON(m_DefaultNamespacePrefix);
  131. m_DefaultNamespacePrefix = Previous;
  132. }
  133. }
  134. CStringPtrTableIter<CNamespacePrefix, CUnicodeCharTraits> iter(m_NamespacePrefixes);
  135. for (iter.Reset(); iter.More(); iter.Next())
  136. {
  137. CNamespacePrefix *NamespacePrefix = iter;
  138. if (NamespacePrefix->m_Depth == m_CurrentDepth)
  139. {
  140. if (NamespacePrefix->m_Previous != NULL)
  141. iter.Update(NamespacePrefix->m_Previous);
  142. else{
  143. iter.Delete();
  144. NamespacePrefix = NULL;
  145. }
  146. FUSION_DELETE_SINGLETON(NamespacePrefix);
  147. }
  148. }
  149. m_CurrentDepth--;
  150. FN_EPILOG
  151. }
  152. HRESULT
  153. CXMLNamespaceManager::Map(
  154. DWORD dwMapFlags,
  155. const XML_NODE_INFO *pNodeInfo,
  156. CBaseStringBuffer *pbuffNamespace,
  157. SIZE_T *pcchNamespacePrefix
  158. )
  159. {
  160. HRESULT hr = E_FAIL;
  161. FN_TRACE_HR(hr);
  162. SIZE_T iColon;
  163. SIZE_T ulLen;
  164. PCWSTR pwcText;
  165. CNamespacePrefix *NamespacePrefix = NULL;
  166. if (pcchNamespacePrefix != NULL)
  167. *pcchNamespacePrefix = 0;
  168. PARAMETER_CHECK((dwMapFlags & ~(CXMLNamespaceManager::eMapFlag_DoNotApplyDefaultNamespace)) == 0);
  169. PARAMETER_CHECK(pNodeInfo != NULL);
  170. PARAMETER_CHECK(pbuffNamespace != NULL);
  171. PARAMETER_CHECK(pcchNamespacePrefix != NULL);
  172. ulLen = pNodeInfo->ulLen;
  173. pwcText = pNodeInfo->pwcText;
  174. // First let's see if there's a colon in the name. We can't use wcschr() since it's not
  175. // null terminated.
  176. for (iColon=0; iColon<ulLen; iColon++)
  177. {
  178. if (pwcText[iColon] == L':')
  179. break;
  180. }
  181. // If there was no namespace prefix, apply the default, if there is one.
  182. if (iColon == ulLen)
  183. {
  184. // Unless they asked us not to, apply the default namespace...
  185. if ((dwMapFlags & CXMLNamespaceManager::eMapFlag_DoNotApplyDefaultNamespace) == 0)
  186. NamespacePrefix = m_DefaultNamespacePrefix;
  187. }
  188. else
  189. {
  190. // Ok, so there was a namespace prefix. Look it up in the table...
  191. CCountedStringHolder<CUnicodeCharTraits> key;
  192. key.m_psz = pwcText;
  193. key.m_cch = iColon;
  194. if (!m_NamespacePrefixes.Find(key, NamespacePrefix))
  195. {
  196. hr = HRESULT_FROM_WIN32(::FusionpGetLastWin32Error());
  197. goto Exit;
  198. }
  199. }
  200. if (NamespacePrefix != NULL)
  201. IFW32FALSE_EXIT(pbuffNamespace->Win32Assign(NamespacePrefix->m_NamespaceURI));
  202. if ((pcchNamespacePrefix != NULL) && (iColon != ulLen))
  203. *pcchNamespacePrefix = iColon;
  204. hr = NOERROR;
  205. Exit:
  206. return hr;
  207. }
  208. BOOL
  209. CXMLNamespaceManager::InsertOrUpdateIfCallback(
  210. CNamespacePrefix *NewNamespacePrefix,
  211. CNamespacePrefix * const &rpOldNamespacePrefix,
  212. InsertOrUpdateIfDisposition &Disposition
  213. )
  214. {
  215. BOOL fSuccess = FALSE;
  216. FN_TRACE_WIN32(fSuccess);
  217. INTERNAL_ERROR_CHECK(rpOldNamespacePrefix != NULL);
  218. INTERNAL_ERROR_CHECK(NewNamespacePrefix != NULL);
  219. NewNamespacePrefix->m_Previous = rpOldNamespacePrefix;
  220. Disposition = eUpdateValue;
  221. fSuccess = TRUE;
  222. Exit:
  223. return fSuccess;
  224. }
  225. CXMLNamespaceManager::CNamespacePrefix::CNamespacePrefix(
  226. ) :
  227. m_Depth(0),
  228. m_Previous(NULL)
  229. {
  230. }
  231. CXMLNamespaceManager::CNamespacePrefix::~CNamespacePrefix()
  232. {
  233. }