diff options
author | Rob Mensching <rob@firegiant.com> | 2017-09-03 11:22:38 -0700 |
---|---|---|
committer | Rob Mensching <rob@firegiant.com> | 2017-09-03 13:33:33 -0700 |
commit | 5d8375007754101ff2889d0e79486c8f9b7cf5ab (patch) | |
tree | a76d6fb6a38dd9f04a93ffcfd9d64e76779b3414 /src/dutil/rssutil.cpp | |
parent | 8e8da6dbc051ec884b5d439bb4f44dc027d05bbf (diff) | |
download | wix-5d8375007754101ff2889d0e79486c8f9b7cf5ab.tar.gz wix-5d8375007754101ff2889d0e79486c8f9b7cf5ab.tar.bz2 wix-5d8375007754101ff2889d0e79486c8f9b7cf5ab.zip |
Initial commit
Diffstat (limited to 'src/dutil/rssutil.cpp')
-rw-r--r-- | src/dutil/rssutil.cpp | 632 |
1 files changed, 632 insertions, 0 deletions
diff --git a/src/dutil/rssutil.cpp b/src/dutil/rssutil.cpp new file mode 100644 index 00000000..db49d954 --- /dev/null +++ b/src/dutil/rssutil.cpp | |||
@@ -0,0 +1,632 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
2 | |||
3 | #include "precomp.h" | ||
4 | |||
5 | static HRESULT ParseRssDocument( | ||
6 | __in IXMLDOMDocument *pixd, | ||
7 | __out RSS_CHANNEL **ppChannel | ||
8 | ); | ||
9 | static HRESULT ParseRssChannel( | ||
10 | __in IXMLDOMNode *pixnChannel, | ||
11 | __out RSS_CHANNEL **ppChannel | ||
12 | ); | ||
13 | static HRESULT ParseRssItem( | ||
14 | __in IXMLDOMNode *pixnItem, | ||
15 | __in DWORD cItem, | ||
16 | __in_xcount(pChannel->cItems) RSS_CHANNEL *pChannel | ||
17 | ); | ||
18 | static HRESULT ParseRssUnknownElement( | ||
19 | __in IXMLDOMNode *pNode, | ||
20 | __inout RSS_UNKNOWN_ELEMENT** ppUnknownElement | ||
21 | ); | ||
22 | static HRESULT ParseRssUnknownAttribute( | ||
23 | __in IXMLDOMNode *pNode, | ||
24 | __inout RSS_UNKNOWN_ATTRIBUTE** ppUnknownAttribute | ||
25 | ); | ||
26 | static void FreeRssUnknownElementList( | ||
27 | __in_opt RSS_UNKNOWN_ELEMENT* pUnknownElement | ||
28 | ); | ||
29 | static void FreeRssUnknownAttributeList( | ||
30 | __in_opt RSS_UNKNOWN_ATTRIBUTE* pUnknownAttribute | ||
31 | ); | ||
32 | |||
33 | |||
34 | /******************************************************************** | ||
35 | RssInitialize - Initialize RSS utilities. | ||
36 | |||
37 | *********************************************************************/ | ||
38 | extern "C" HRESULT DAPI RssInitialize() | ||
39 | { | ||
40 | return XmlInitialize(); | ||
41 | } | ||
42 | |||
43 | |||
44 | /******************************************************************** | ||
45 | RssUninitialize - Uninitialize RSS utilities. | ||
46 | |||
47 | *********************************************************************/ | ||
48 | extern "C" void DAPI RssUninitialize() | ||
49 | { | ||
50 | XmlUninitialize(); | ||
51 | } | ||
52 | |||
53 | |||
54 | /******************************************************************** | ||
55 | RssParseFromString - parses out an RSS channel from a string. | ||
56 | |||
57 | *********************************************************************/ | ||
58 | extern "C" HRESULT DAPI RssParseFromString( | ||
59 | __in_z LPCWSTR wzRssString, | ||
60 | __out RSS_CHANNEL **ppChannel | ||
61 | ) | ||
62 | { | ||
63 | Assert(wzRssString); | ||
64 | Assert(ppChannel); | ||
65 | |||
66 | HRESULT hr = S_OK; | ||
67 | RSS_CHANNEL *pNewChannel = NULL; | ||
68 | IXMLDOMDocument *pixdRss = NULL; | ||
69 | |||
70 | hr = XmlLoadDocument(wzRssString, &pixdRss); | ||
71 | ExitOnFailure(hr, "Failed to load RSS string as XML document."); | ||
72 | |||
73 | hr = ParseRssDocument(pixdRss, &pNewChannel); | ||
74 | ExitOnFailure(hr, "Failed to parse RSS document."); | ||
75 | |||
76 | *ppChannel = pNewChannel; | ||
77 | pNewChannel = NULL; | ||
78 | |||
79 | LExit: | ||
80 | ReleaseObject(pixdRss); | ||
81 | |||
82 | ReleaseRssChannel(pNewChannel); | ||
83 | |||
84 | return hr; | ||
85 | } | ||
86 | |||
87 | |||
88 | /******************************************************************** | ||
89 | RssParseFromFile - parses out an RSS channel from a file path. | ||
90 | |||
91 | *********************************************************************/ | ||
92 | extern "C" HRESULT DAPI RssParseFromFile( | ||
93 | __in_z LPCWSTR wzRssFile, | ||
94 | __out RSS_CHANNEL **ppChannel | ||
95 | ) | ||
96 | { | ||
97 | Assert(wzRssFile); | ||
98 | Assert(ppChannel); | ||
99 | |||
100 | HRESULT hr = S_OK; | ||
101 | RSS_CHANNEL *pNewChannel = NULL; | ||
102 | IXMLDOMDocument *pixdRss = NULL; | ||
103 | |||
104 | hr = XmlLoadDocumentFromFile(wzRssFile, &pixdRss); | ||
105 | ExitOnFailure(hr, "Failed to load RSS string as XML document."); | ||
106 | |||
107 | hr = ParseRssDocument(pixdRss, &pNewChannel); | ||
108 | ExitOnFailure(hr, "Failed to parse RSS document."); | ||
109 | |||
110 | *ppChannel = pNewChannel; | ||
111 | pNewChannel = NULL; | ||
112 | |||
113 | LExit: | ||
114 | ReleaseObject(pixdRss); | ||
115 | |||
116 | ReleaseRssChannel(pNewChannel); | ||
117 | |||
118 | return hr; | ||
119 | } | ||
120 | |||
121 | |||
122 | /******************************************************************** | ||
123 | RssFreeChannel - parses out an RSS channel from a string. | ||
124 | |||
125 | *********************************************************************/ | ||
126 | extern "C" void DAPI RssFreeChannel( | ||
127 | __in_xcount(pChannel->cItems) RSS_CHANNEL *pChannel | ||
128 | ) | ||
129 | { | ||
130 | if (pChannel) | ||
131 | { | ||
132 | for (DWORD i = 0; i < pChannel->cItems; ++i) | ||
133 | { | ||
134 | ReleaseStr(pChannel->rgItems[i].wzTitle); | ||
135 | ReleaseStr(pChannel->rgItems[i].wzLink); | ||
136 | ReleaseStr(pChannel->rgItems[i].wzDescription); | ||
137 | ReleaseStr(pChannel->rgItems[i].wzGuid); | ||
138 | ReleaseStr(pChannel->rgItems[i].wzEnclosureUrl); | ||
139 | ReleaseStr(pChannel->rgItems[i].wzEnclosureType); | ||
140 | |||
141 | FreeRssUnknownElementList(pChannel->rgItems[i].pUnknownElements); | ||
142 | } | ||
143 | |||
144 | ReleaseStr(pChannel->wzTitle); | ||
145 | ReleaseStr(pChannel->wzLink); | ||
146 | ReleaseStr(pChannel->wzDescription); | ||
147 | FreeRssUnknownElementList(pChannel->pUnknownElements); | ||
148 | |||
149 | MemFree(pChannel); | ||
150 | } | ||
151 | } | ||
152 | |||
153 | |||
154 | /******************************************************************** | ||
155 | ParseRssDocument - parses out an RSS channel from a loaded XML DOM document. | ||
156 | |||
157 | *********************************************************************/ | ||
158 | static HRESULT ParseRssDocument( | ||
159 | __in IXMLDOMDocument *pixd, | ||
160 | __out RSS_CHANNEL **ppChannel | ||
161 | ) | ||
162 | { | ||
163 | Assert(pixd); | ||
164 | Assert(ppChannel); | ||
165 | |||
166 | HRESULT hr = S_OK; | ||
167 | IXMLDOMElement *pRssElement = NULL; | ||
168 | IXMLDOMNodeList *pChannelNodes = NULL; | ||
169 | IXMLDOMNode *pNode = NULL; | ||
170 | BSTR bstrNodeName = NULL; | ||
171 | |||
172 | RSS_CHANNEL *pNewChannel = NULL; | ||
173 | |||
174 | // | ||
175 | // Get the document element and start processing channels. | ||
176 | // | ||
177 | hr = pixd ->get_documentElement(&pRssElement); | ||
178 | ExitOnFailure(hr, "failed get_documentElement in ParseRssDocument"); | ||
179 | |||
180 | hr = pRssElement->get_childNodes(&pChannelNodes); | ||
181 | ExitOnFailure(hr, "Failed to get child nodes of Rss Document element."); | ||
182 | |||
183 | while (S_OK == (hr = XmlNextElement(pChannelNodes, &pNode, &bstrNodeName))) | ||
184 | { | ||
185 | if (0 == lstrcmpW(bstrNodeName, L"channel")) | ||
186 | { | ||
187 | hr = ParseRssChannel(pNode, &pNewChannel); | ||
188 | ExitOnFailure(hr, "Failed to parse RSS channel."); | ||
189 | } | ||
190 | else if (0 == lstrcmpW(bstrNodeName, L"link")) | ||
191 | { | ||
192 | } | ||
193 | |||
194 | ReleaseNullBSTR(bstrNodeName); | ||
195 | ReleaseNullObject(pNode); | ||
196 | } | ||
197 | |||
198 | if (S_FALSE == hr) | ||
199 | { | ||
200 | hr = S_OK; | ||
201 | } | ||
202 | |||
203 | *ppChannel = pNewChannel; | ||
204 | pNewChannel = NULL; | ||
205 | |||
206 | LExit: | ||
207 | ReleaseBSTR(bstrNodeName); | ||
208 | ReleaseObject(pNode); | ||
209 | ReleaseObject(pChannelNodes); | ||
210 | ReleaseObject(pRssElement); | ||
211 | |||
212 | ReleaseRssChannel(pNewChannel); | ||
213 | |||
214 | return hr; | ||
215 | } | ||
216 | |||
217 | |||
218 | /******************************************************************** | ||
219 | ParseRssChannel - parses out an RSS channel from a loaded XML DOM element. | ||
220 | |||
221 | *********************************************************************/ | ||
222 | static HRESULT ParseRssChannel( | ||
223 | __in IXMLDOMNode *pixnChannel, | ||
224 | __out RSS_CHANNEL **ppChannel | ||
225 | ) | ||
226 | { | ||
227 | Assert(pixnChannel); | ||
228 | Assert(ppChannel); | ||
229 | |||
230 | HRESULT hr = S_OK; | ||
231 | IXMLDOMNodeList *pNodeList = NULL; | ||
232 | |||
233 | RSS_CHANNEL *pNewChannel = NULL; | ||
234 | long cItems = 0; | ||
235 | |||
236 | IXMLDOMNode *pNode = NULL; | ||
237 | BSTR bstrNodeName = NULL; | ||
238 | BSTR bstrNodeValue = NULL; | ||
239 | |||
240 | // | ||
241 | // First, calculate how many RSS items we're going to have and allocate | ||
242 | // the RSS_CHANNEL structure | ||
243 | // | ||
244 | hr = XmlSelectNodes(pixnChannel, L"item", &pNodeList); | ||
245 | ExitOnFailure(hr, "Failed to select all RSS items in an RSS channel."); | ||
246 | |||
247 | hr = pNodeList->get_length(&cItems); | ||
248 | ExitOnFailure(hr, "Failed to count the number of RSS items in RSS channel."); | ||
249 | |||
250 | pNewChannel = static_cast<RSS_CHANNEL*>(MemAlloc(sizeof(RSS_CHANNEL) + sizeof(RSS_ITEM) * cItems, TRUE)); | ||
251 | ExitOnNull(pNewChannel, hr, E_OUTOFMEMORY, "Failed to allocate RSS channel structure."); | ||
252 | |||
253 | pNewChannel->cItems = cItems; | ||
254 | |||
255 | // | ||
256 | // Process the elements under a channel now. | ||
257 | // | ||
258 | hr = pixnChannel->get_childNodes(&pNodeList); | ||
259 | ExitOnFailure(hr, "Failed to get child nodes of RSS channel element."); | ||
260 | |||
261 | cItems = 0; // reset the counter and use this to walk through the channel items | ||
262 | while (S_OK == (hr = XmlNextElement(pNodeList, &pNode, &bstrNodeName))) | ||
263 | { | ||
264 | if (0 == lstrcmpW(bstrNodeName, L"title")) | ||
265 | { | ||
266 | hr = XmlGetText(pNode, &bstrNodeValue); | ||
267 | ExitOnFailure(hr, "Failed to get RSS channel title."); | ||
268 | |||
269 | hr = StrAllocString(&pNewChannel->wzTitle, bstrNodeValue, 0); | ||
270 | ExitOnFailure(hr, "Failed to allocate RSS channel title."); | ||
271 | } | ||
272 | else if (0 == lstrcmpW(bstrNodeName, L"link")) | ||
273 | { | ||
274 | hr = XmlGetText(pNode, &bstrNodeValue); | ||
275 | ExitOnFailure(hr, "Failed to get RSS channel link."); | ||
276 | |||
277 | hr = StrAllocString(&pNewChannel->wzLink, bstrNodeValue, 0); | ||
278 | ExitOnFailure(hr, "Failed to allocate RSS channel link."); | ||
279 | } | ||
280 | else if (0 == lstrcmpW(bstrNodeName, L"description")) | ||
281 | { | ||
282 | hr = XmlGetText(pNode, &bstrNodeValue); | ||
283 | ExitOnFailure(hr, "Failed to get RSS channel description."); | ||
284 | |||
285 | hr = StrAllocString(&pNewChannel->wzDescription, bstrNodeValue, 0); | ||
286 | ExitOnFailure(hr, "Failed to allocate RSS channel description."); | ||
287 | } | ||
288 | else if (0 == lstrcmpW(bstrNodeName, L"ttl")) | ||
289 | { | ||
290 | hr = XmlGetText(pNode, &bstrNodeValue); | ||
291 | ExitOnFailure(hr, "Failed to get RSS channel description."); | ||
292 | |||
293 | pNewChannel->dwTimeToLive = (DWORD)wcstoul(bstrNodeValue, NULL, 10); | ||
294 | } | ||
295 | else if (0 == lstrcmpW(bstrNodeName, L"item")) | ||
296 | { | ||
297 | hr = ParseRssItem(pNode, cItems, pNewChannel); | ||
298 | ExitOnFailure(hr, "Failed to parse RSS item."); | ||
299 | |||
300 | ++cItems; | ||
301 | } | ||
302 | else | ||
303 | { | ||
304 | hr = ParseRssUnknownElement(pNode, &pNewChannel->pUnknownElements); | ||
305 | ExitOnFailure(hr, "Failed to parse unknown RSS channel element: %ls", bstrNodeName); | ||
306 | } | ||
307 | |||
308 | ReleaseNullBSTR(bstrNodeValue); | ||
309 | ReleaseNullBSTR(bstrNodeName); | ||
310 | ReleaseNullObject(pNode); | ||
311 | } | ||
312 | |||
313 | *ppChannel = pNewChannel; | ||
314 | pNewChannel = NULL; | ||
315 | |||
316 | LExit: | ||
317 | ReleaseBSTR(bstrNodeName); | ||
318 | ReleaseObject(pNode); | ||
319 | ReleaseObject(pNodeList); | ||
320 | |||
321 | ReleaseRssChannel(pNewChannel); | ||
322 | |||
323 | return hr; | ||
324 | } | ||
325 | |||
326 | |||
327 | /******************************************************************** | ||
328 | ParseRssItem - parses out an RSS item from a loaded XML DOM node. | ||
329 | |||
330 | *********************************************************************/ | ||
331 | static HRESULT ParseRssItem( | ||
332 | __in IXMLDOMNode *pixnItem, | ||
333 | __in DWORD cItem, | ||
334 | __in_xcount(pChannel->cItems) RSS_CHANNEL *pChannel | ||
335 | ) | ||
336 | { | ||
337 | HRESULT hr = S_OK; | ||
338 | |||
339 | RSS_ITEM *pItem = NULL; | ||
340 | IXMLDOMNodeList *pNodeList = NULL; | ||
341 | |||
342 | IXMLDOMNode *pNode = NULL; | ||
343 | BSTR bstrNodeName = NULL; | ||
344 | BSTR bstrNodeValue = NULL; | ||
345 | |||
346 | // | ||
347 | // First make sure we're dealing with a valid item. | ||
348 | // | ||
349 | if (pChannel->cItems <= cItem) | ||
350 | { | ||
351 | hr = E_UNEXPECTED; | ||
352 | ExitOnFailure(hr, "Unexpected number of items parsed."); | ||
353 | } | ||
354 | |||
355 | pItem = pChannel->rgItems + cItem; | ||
356 | |||
357 | // | ||
358 | // Process the elements under an item now. | ||
359 | // | ||
360 | hr = pixnItem->get_childNodes(&pNodeList); | ||
361 | ExitOnFailure(hr, "Failed to get child nodes of RSS item element."); | ||
362 | while (S_OK == (hr = XmlNextElement(pNodeList, &pNode, &bstrNodeName))) | ||
363 | { | ||
364 | if (0 == lstrcmpW(bstrNodeName, L"title")) | ||
365 | { | ||
366 | hr = XmlGetText(pNode, &bstrNodeValue); | ||
367 | ExitOnFailure(hr, "Failed to get RSS channel title."); | ||
368 | |||
369 | hr = StrAllocString(&pItem->wzTitle, bstrNodeValue, 0); | ||
370 | ExitOnFailure(hr, "Failed to allocate RSS item title."); | ||
371 | } | ||
372 | else if (0 == lstrcmpW(bstrNodeName, L"link")) | ||
373 | { | ||
374 | hr = XmlGetText(pNode, &bstrNodeValue); | ||
375 | ExitOnFailure(hr, "Failed to get RSS channel link."); | ||
376 | |||
377 | hr = StrAllocString(&pItem->wzLink, bstrNodeValue, 0); | ||
378 | ExitOnFailure(hr, "Failed to allocate RSS item link."); | ||
379 | } | ||
380 | else if (0 == lstrcmpW(bstrNodeName, L"description")) | ||
381 | { | ||
382 | hr = XmlGetText(pNode, &bstrNodeValue); | ||
383 | ExitOnFailure(hr, "Failed to get RSS item description."); | ||
384 | |||
385 | hr = StrAllocString(&pItem->wzDescription, bstrNodeValue, 0); | ||
386 | ExitOnFailure(hr, "Failed to allocate RSS item description."); | ||
387 | } | ||
388 | else if (0 == lstrcmpW(bstrNodeName, L"guid")) | ||
389 | { | ||
390 | hr = XmlGetText(pNode, &bstrNodeValue); | ||
391 | ExitOnFailure(hr, "Failed to get RSS item guid."); | ||
392 | |||
393 | hr = StrAllocString(&pItem->wzGuid, bstrNodeValue, 0); | ||
394 | ExitOnFailure(hr, "Failed to allocate RSS item guid."); | ||
395 | } | ||
396 | else if (0 == lstrcmpW(bstrNodeName, L"pubDate")) | ||
397 | { | ||
398 | hr = XmlGetText(pNode, &bstrNodeValue); | ||
399 | ExitOnFailure(hr, "Failed to get RSS item guid."); | ||
400 | |||
401 | hr = TimeFromString(bstrNodeValue, &pItem->ftPublished); | ||
402 | ExitOnFailure(hr, "Failed to convert RSS item time."); | ||
403 | } | ||
404 | else if (0 == lstrcmpW(bstrNodeName, L"enclosure")) | ||
405 | { | ||
406 | hr = XmlGetAttribute(pNode, L"url", &bstrNodeValue); | ||
407 | ExitOnFailure(hr, "Failed to get RSS item enclosure url."); | ||
408 | |||
409 | hr = StrAllocString(&pItem->wzEnclosureUrl, bstrNodeValue, 0); | ||
410 | ExitOnFailure(hr, "Failed to allocate RSS item enclosure url."); | ||
411 | ReleaseNullBSTR(bstrNodeValue); | ||
412 | |||
413 | hr = XmlGetAttributeNumber(pNode, L"length", &pItem->dwEnclosureSize); | ||
414 | ExitOnFailure(hr, "Failed to get RSS item enclosure length."); | ||
415 | |||
416 | hr = XmlGetAttribute(pNode, L"type", &bstrNodeValue); | ||
417 | ExitOnFailure(hr, "Failed to get RSS item enclosure type."); | ||
418 | |||
419 | hr = StrAllocString(&pItem->wzEnclosureType, bstrNodeValue, 0); | ||
420 | ExitOnFailure(hr, "Failed to allocate RSS item enclosure type."); | ||
421 | } | ||
422 | else | ||
423 | { | ||
424 | hr = ParseRssUnknownElement(pNode, &pItem->pUnknownElements); | ||
425 | ExitOnFailure(hr, "Failed to parse unknown RSS item element: %ls", bstrNodeName); | ||
426 | } | ||
427 | |||
428 | ReleaseNullBSTR(bstrNodeValue); | ||
429 | ReleaseNullBSTR(bstrNodeName); | ||
430 | ReleaseNullObject(pNode); | ||
431 | } | ||
432 | |||
433 | LExit: | ||
434 | ReleaseBSTR(bstrNodeValue); | ||
435 | ReleaseBSTR(bstrNodeName); | ||
436 | ReleaseObject(pNode); | ||
437 | ReleaseObject(pNodeList); | ||
438 | |||
439 | return hr; | ||
440 | } | ||
441 | |||
442 | |||
443 | /******************************************************************** | ||
444 | ParseRssUnknownElement - parses out an unknown item from the RSS feed from a loaded XML DOM node. | ||
445 | |||
446 | *********************************************************************/ | ||
447 | static HRESULT ParseRssUnknownElement( | ||
448 | __in IXMLDOMNode *pNode, | ||
449 | __inout RSS_UNKNOWN_ELEMENT** ppUnknownElement | ||
450 | ) | ||
451 | { | ||
452 | Assert(ppUnknownElement); | ||
453 | |||
454 | HRESULT hr = S_OK; | ||
455 | BSTR bstrNodeNamespace = NULL; | ||
456 | BSTR bstrNodeName = NULL; | ||
457 | BSTR bstrNodeValue = NULL; | ||
458 | IXMLDOMNamedNodeMap* pixnnmAttributes = NULL; | ||
459 | IXMLDOMNode* pixnAttribute = NULL; | ||
460 | RSS_UNKNOWN_ELEMENT* pNewUnknownElement; | ||
461 | |||
462 | pNewUnknownElement = static_cast<RSS_UNKNOWN_ELEMENT*>(MemAlloc(sizeof(RSS_UNKNOWN_ELEMENT), TRUE)); | ||
463 | ExitOnNull(pNewUnknownElement, hr, E_OUTOFMEMORY, "Failed to allocate unknown element."); | ||
464 | |||
465 | hr = pNode->get_namespaceURI(&bstrNodeNamespace); | ||
466 | if (S_OK == hr) | ||
467 | { | ||
468 | hr = StrAllocString(&pNewUnknownElement->wzNamespace, bstrNodeNamespace, 0); | ||
469 | ExitOnFailure(hr, "Failed to allocate RSS unknown element namespace."); | ||
470 | } | ||
471 | else if (S_FALSE == hr) | ||
472 | { | ||
473 | hr = S_OK; | ||
474 | } | ||
475 | ExitOnFailure(hr, "Failed to get unknown element namespace."); | ||
476 | |||
477 | hr = pNode->get_baseName(&bstrNodeName); | ||
478 | ExitOnFailure(hr, "Failed to get unknown element name."); | ||
479 | |||
480 | hr = StrAllocString(&pNewUnknownElement->wzElement, bstrNodeName, 0); | ||
481 | ExitOnFailure(hr, "Failed to allocate RSS unknown element name."); | ||
482 | |||
483 | hr = XmlGetText(pNode, &bstrNodeValue); | ||
484 | ExitOnFailure(hr, "Failed to get unknown element value."); | ||
485 | |||
486 | hr = StrAllocString(&pNewUnknownElement->wzValue, bstrNodeValue, 0); | ||
487 | ExitOnFailure(hr, "Failed to allocate RSS unknown element value."); | ||
488 | |||
489 | hr = pNode->get_attributes(&pixnnmAttributes); | ||
490 | ExitOnFailure(hr, "Failed get attributes on RSS unknown element."); | ||
491 | |||
492 | while (S_OK == (hr = pixnnmAttributes->nextNode(&pixnAttribute))) | ||
493 | { | ||
494 | hr = ParseRssUnknownAttribute(pixnAttribute, &pNewUnknownElement->pAttributes); | ||
495 | ExitOnFailure(hr, "Failed to parse attribute on RSS unknown element."); | ||
496 | |||
497 | ReleaseNullObject(pixnAttribute); | ||
498 | } | ||
499 | |||
500 | if (S_FALSE == hr) | ||
501 | { | ||
502 | hr = S_OK; | ||
503 | } | ||
504 | ExitOnFailure(hr, "Failed to enumerate all attributes on RSS unknown element."); | ||
505 | |||
506 | RSS_UNKNOWN_ELEMENT** ppTail = ppUnknownElement; | ||
507 | while (*ppTail) | ||
508 | { | ||
509 | ppTail = &(*ppTail)->pNext; | ||
510 | } | ||
511 | |||
512 | *ppTail = pNewUnknownElement; | ||
513 | pNewUnknownElement = NULL; | ||
514 | |||
515 | LExit: | ||
516 | FreeRssUnknownElementList(pNewUnknownElement); | ||
517 | |||
518 | ReleaseBSTR(bstrNodeNamespace); | ||
519 | ReleaseBSTR(bstrNodeName); | ||
520 | ReleaseBSTR(bstrNodeValue); | ||
521 | ReleaseObject(pixnnmAttributes); | ||
522 | ReleaseObject(pixnAttribute); | ||
523 | |||
524 | return hr; | ||
525 | } | ||
526 | |||
527 | |||
528 | /******************************************************************** | ||
529 | ParseRssUnknownAttribute - parses out attribute from an unknown element | ||
530 | |||
531 | *********************************************************************/ | ||
532 | static HRESULT ParseRssUnknownAttribute( | ||
533 | __in IXMLDOMNode *pNode, | ||
534 | __inout RSS_UNKNOWN_ATTRIBUTE** ppUnknownAttribute | ||
535 | ) | ||
536 | { | ||
537 | Assert(ppUnknownAttribute); | ||
538 | |||
539 | HRESULT hr = S_OK; | ||
540 | BSTR bstrNodeNamespace = NULL; | ||
541 | BSTR bstrNodeName = NULL; | ||
542 | BSTR bstrNodeValue = NULL; | ||
543 | RSS_UNKNOWN_ATTRIBUTE* pNewUnknownAttribute; | ||
544 | |||
545 | pNewUnknownAttribute = static_cast<RSS_UNKNOWN_ATTRIBUTE*>(MemAlloc(sizeof(RSS_UNKNOWN_ATTRIBUTE), TRUE)); | ||
546 | ExitOnNull(pNewUnknownAttribute, hr, E_OUTOFMEMORY, "Failed to allocate unknown attribute."); | ||
547 | |||
548 | hr = pNode->get_namespaceURI(&bstrNodeNamespace); | ||
549 | if (S_OK == hr) | ||
550 | { | ||
551 | hr = StrAllocString(&pNewUnknownAttribute->wzNamespace, bstrNodeNamespace, 0); | ||
552 | ExitOnFailure(hr, "Failed to allocate RSS unknown attribute namespace."); | ||
553 | } | ||
554 | else if (S_FALSE == hr) | ||
555 | { | ||
556 | hr = S_OK; | ||
557 | } | ||
558 | ExitOnFailure(hr, "Failed to get unknown attribute namespace."); | ||
559 | |||
560 | hr = pNode->get_baseName(&bstrNodeName); | ||
561 | ExitOnFailure(hr, "Failed to get unknown attribute name."); | ||
562 | |||
563 | hr = StrAllocString(&pNewUnknownAttribute->wzAttribute, bstrNodeName, 0); | ||
564 | ExitOnFailure(hr, "Failed to allocate RSS unknown attribute name."); | ||
565 | |||
566 | hr = XmlGetText(pNode, &bstrNodeValue); | ||
567 | ExitOnFailure(hr, "Failed to get unknown attribute value."); | ||
568 | |||
569 | hr = StrAllocString(&pNewUnknownAttribute->wzValue, bstrNodeValue, 0); | ||
570 | ExitOnFailure(hr, "Failed to allocate RSS unknown attribute value."); | ||
571 | |||
572 | RSS_UNKNOWN_ATTRIBUTE** ppTail = ppUnknownAttribute; | ||
573 | while (*ppTail) | ||
574 | { | ||
575 | ppTail = &(*ppTail)->pNext; | ||
576 | } | ||
577 | |||
578 | *ppTail = pNewUnknownAttribute; | ||
579 | pNewUnknownAttribute = NULL; | ||
580 | |||
581 | LExit: | ||
582 | FreeRssUnknownAttributeList(pNewUnknownAttribute); | ||
583 | |||
584 | ReleaseBSTR(bstrNodeNamespace); | ||
585 | ReleaseBSTR(bstrNodeName); | ||
586 | ReleaseBSTR(bstrNodeValue); | ||
587 | |||
588 | return hr; | ||
589 | } | ||
590 | |||
591 | |||
592 | /******************************************************************** | ||
593 | FreeRssUnknownElement - releases all of the memory used by a list of unknown elements | ||
594 | |||
595 | *********************************************************************/ | ||
596 | static void FreeRssUnknownElementList( | ||
597 | __in_opt RSS_UNKNOWN_ELEMENT* pUnknownElement | ||
598 | ) | ||
599 | { | ||
600 | while (pUnknownElement) | ||
601 | { | ||
602 | RSS_UNKNOWN_ELEMENT* pFree = pUnknownElement; | ||
603 | pUnknownElement = pUnknownElement->pNext; | ||
604 | |||
605 | FreeRssUnknownAttributeList(pFree->pAttributes); | ||
606 | ReleaseStr(pFree->wzNamespace); | ||
607 | ReleaseStr(pFree->wzElement); | ||
608 | ReleaseStr(pFree->wzValue); | ||
609 | MemFree(pFree); | ||
610 | } | ||
611 | } | ||
612 | |||
613 | |||
614 | /******************************************************************** | ||
615 | FreeRssUnknownAttribute - releases all of the memory used by a list of unknown attributes | ||
616 | |||
617 | *********************************************************************/ | ||
618 | static void FreeRssUnknownAttributeList( | ||
619 | __in_opt RSS_UNKNOWN_ATTRIBUTE* pUnknownAttribute | ||
620 | ) | ||
621 | { | ||
622 | while (pUnknownAttribute) | ||
623 | { | ||
624 | RSS_UNKNOWN_ATTRIBUTE* pFree = pUnknownAttribute; | ||
625 | pUnknownAttribute = pUnknownAttribute->pNext; | ||
626 | |||
627 | ReleaseStr(pFree->wzNamespace); | ||
628 | ReleaseStr(pFree->wzAttribute); | ||
629 | ReleaseStr(pFree->wzValue); | ||
630 | MemFree(pFree); | ||
631 | } | ||
632 | } | ||