Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(158)

Side by Side Diff: base/xml_utils.cc

Issue 624713003: Keep only base/extractor.[cc|h]. (Closed) Base URL: https://chromium.googlesource.com/external/omaha.git@master
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/xml_utils.h ('k') | base/xml_utils_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2005-2009 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 // ========================================================================
15 //
16 // xml_utils.cpp
17 //
18 // Utilities for working with XML files via MSXML.
19
20 #include "omaha/base/xml_utils.h"
21
22 #include <msxml2.h>
23 #include <atlsafe.h>
24 #include <vector>
25 #include "omaha/base/debug.h"
26 #include "omaha/base/error.h"
27 #include "omaha/base/logging.h"
28 #include "omaha/base/string.h"
29 #include "omaha/base/utils.h"
30
31 namespace omaha {
32
33 XMLFQName::XMLFQName() {}
34
35 XMLFQName::XMLFQName(const TCHAR* u, const TCHAR* b)
36 : uri(u && ::_tcslen(u) ? u : 0),
37 base(b && ::_tcslen(b) ? b : 0) {}
38
39 XMLFQName::~XMLFQName() {}
40
41 HRESULT CoCreateSafeDOMDocument(IXMLDOMDocument** my_xmldoc) {
42 ASSERT1(my_xmldoc && !*my_xmldoc);
43 if (!my_xmldoc) {
44 UTIL_LOG(LE, (L"[CoCreateSafeDOMDocument E_INVALIDARG]"));
45 return E_INVALIDARG;
46 }
47 *my_xmldoc = NULL;
48 CComPtr<IXMLDOMDocument> xml_doc;
49 HRESULT hr = xml_doc.CoCreateInstance(__uuidof(DOMDocument2));
50 if (FAILED(hr)) {
51 UTIL_LOG(LE, (_T("[xml_doc.CoCreateInstance failed][0x%x]"), hr));
52 return hr;
53 }
54 ASSERT1(xml_doc);
55 hr = xml_doc->put_resolveExternals(VARIANT_FALSE);
56 if (FAILED(hr)) {
57 UTIL_LOG(LE, (_T("[put_resolveExternals failed][0x%x]"), hr));
58 return hr;
59 }
60 *my_xmldoc = xml_doc.Detach();
61 return S_OK;
62 }
63
64 HRESULT LoadXMLFromFile(const TCHAR* xmlfile,
65 bool preserve_whitespace,
66 IXMLDOMDocument** xmldoc) {
67 ASSERT1(xmlfile);
68 ASSERT1(xmldoc);
69 ASSERT1(!*xmldoc);
70
71 *xmldoc = NULL;
72 CComPtr<IXMLDOMDocument> my_xmldoc;
73 HRESULT hr = CoCreateSafeDOMDocument(&my_xmldoc);
74 if (FAILED(hr)) {
75 UTIL_LOG(LE, (_T("[CoCreateSafeDOMDocument failed][0x%x]"), hr));
76 return hr;
77 }
78 hr = my_xmldoc->put_preserveWhiteSpace(VARIANT_BOOL(preserve_whitespace));
79 if (FAILED(hr)) {
80 UTIL_LOG(LE, (_T("[put_preserveWhiteSpace failed][0x%x]"), hr));
81 return hr;
82 }
83 CComBSTR my_xmlfile(xmlfile);
84 VARIANT_BOOL is_successful(VARIANT_FALSE);
85 hr = my_xmldoc->load(CComVariant(my_xmlfile), &is_successful);
86 if (FAILED(hr)) {
87 UTIL_LOG(LE, (_T("[my_xmldoc->load failed][0x%x]"), hr));
88 return hr;
89 }
90 if (!is_successful) {
91 CComPtr<IXMLDOMParseError> error;
92 CString error_message;
93 hr = GetXMLParseError(my_xmldoc, &error);
94 if (FAILED(hr)) {
95 UTIL_LOG(LE, (_T("[GetXMLParseError failed][0x%x]"), hr));
96 return hr;
97 }
98 ASSERT1(error);
99 HRESULT error_code = 0;
100 hr = InterpretXMLParseError(error, &error_code, &error_message);
101 if (FAILED(hr)) {
102 UTIL_LOG(LE, (_T("[InterpretXMLParseError failed][0x%x]"), hr));
103 return hr;
104 }
105 UTIL_LOG(LE, (L"[LoadXMLFromFile '%s'][parse error: %s]",
106 xmlfile, error_message));
107 ASSERT1(FAILED(error_code));
108 return FAILED(error_code) ? error_code : CI_E_XML_LOAD_ERROR;
109 }
110 *xmldoc = my_xmldoc.Detach();
111 return S_OK;
112 }
113
114 HRESULT LoadXMLFromMemory(const TCHAR* xmlstring,
115 bool preserve_whitespace,
116 IXMLDOMDocument** xmldoc) {
117 ASSERT1(xmlstring);
118 ASSERT1(xmldoc);
119 ASSERT1(!*xmldoc);
120
121 *xmldoc = NULL;
122 CComPtr<IXMLDOMDocument> my_xmldoc;
123 RET_IF_FAILED(CoCreateSafeDOMDocument(&my_xmldoc));
124 RET_IF_FAILED(my_xmldoc->put_preserveWhiteSpace(
125 VARIANT_BOOL(preserve_whitespace)));
126 CComBSTR xmlmemory(xmlstring);
127 VARIANT_BOOL is_successful(VARIANT_FALSE);
128 RET_IF_FAILED(my_xmldoc->loadXML(xmlmemory, &is_successful));
129 if (!is_successful) {
130 CComPtr<IXMLDOMParseError> error;
131 CString error_message;
132 RET_IF_FAILED(GetXMLParseError(my_xmldoc, &error));
133 ASSERT1(error);
134 HRESULT error_code = 0;
135 RET_IF_FAILED(InterpretXMLParseError(error, &error_code, &error_message));
136 UTIL_LOG(LE, (L"[LoadXMLFromMemory][parse error: %s]", error_message));
137 ASSERT1(FAILED(error_code));
138 return FAILED(error_code) ? error_code : CI_E_XML_LOAD_ERROR;
139 }
140 *xmldoc = my_xmldoc.Detach();
141 return S_OK;
142 }
143
144 HRESULT LoadXMLFromRawData(const std::vector<byte>& xmldata,
145 bool preserve_whitespace,
146 IXMLDOMDocument** xmldoc) {
147 ASSERT1(xmldoc);
148 ASSERT1(!*xmldoc);
149
150 *xmldoc = NULL;
151 if (!xmldata.size()) {
152 return E_INVALIDARG;
153 }
154
155 CComPtr<IXMLDOMDocument> my_xmldoc;
156 RET_IF_FAILED(CoCreateSafeDOMDocument(&my_xmldoc));
157 RET_IF_FAILED(my_xmldoc->put_preserveWhiteSpace(
158 VARIANT_BOOL(preserve_whitespace)));
159
160 CComSafeArray<byte> xmlsa;
161 xmlsa.Add(xmldata.size(), &xmldata.front());
162 CComVariant xmlvar(xmlsa);
163
164 VARIANT_BOOL is_successful(VARIANT_FALSE);
165 RET_IF_FAILED(my_xmldoc->load(xmlvar, &is_successful));
166 if (!is_successful) {
167 CComPtr<IXMLDOMParseError> error;
168 CString error_message;
169 RET_IF_FAILED(GetXMLParseError(my_xmldoc, &error));
170 ASSERT1(error);
171 HRESULT error_code = 0;
172 RET_IF_FAILED(InterpretXMLParseError(error, &error_code, &error_message));
173 UTIL_LOG(LE, (_T("[LoadXMLFromRawData][parse error: %s]"), error_message));
174 ASSERT1(FAILED(error_code));
175 return FAILED(error_code) ? error_code : CI_E_XML_LOAD_ERROR;
176 }
177 *xmldoc = my_xmldoc.Detach();
178 return S_OK;
179 }
180
181 HRESULT SaveXMLToFile(IXMLDOMDocument* xmldoc, const TCHAR* xmlfile) {
182 ASSERT1(xmldoc);
183 ASSERT1(xmlfile);
184
185 CComBSTR my_xmlfile(xmlfile);
186 RET_IF_FAILED(xmldoc->save(CComVariant(my_xmlfile)));
187 return S_OK;
188 }
189
190 HRESULT SaveXMLToMemory(IXMLDOMDocument* xmldoc, CString* xmlstring) {
191 ASSERT1(xmldoc);
192 ASSERT1(xmlstring);
193
194 CComBSTR xmlmemory;
195 RET_IF_FAILED(xmldoc->get_xml(&xmlmemory));
196 *xmlstring = xmlmemory;
197
198 return S_OK;
199 }
200
201 HRESULT SaveXMLToRawData(IXMLDOMDocument* xmldoc, std::vector<byte>* buffer) {
202 ASSERT1(xmldoc);
203 ASSERT1(buffer);
204
205 CComPtr<IStream> stream;
206 HRESULT hr = ::CreateStreamOnHGlobal(NULL, TRUE, &stream);
207 if (FAILED(hr)) {
208 return hr;
209 }
210
211 ASSERT1(stream);
212
213 hr = xmldoc->save(CComVariant(stream));
214 if (FAILED(hr)) {
215 return hr;
216 }
217
218 // To get the exact size of the stream, we have to use the seek function.
219 LARGE_INTEGER li = {0, 0};
220 ULARGE_INTEGER uli = {0, 0};
221 hr = stream->Seek(li, STREAM_SEEK_END, &uli);
222 if (FAILED(hr)) {
223 return hr;
224 }
225
226 buffer->resize(static_cast<size_t>(uli.QuadPart));
227
228 HGLOBAL hglobal = NULL;
229 hr = ::GetHGlobalFromStream(stream, &hglobal);
230 if (FAILED(hr)) {
231 return hr;
232 }
233
234 memcpy_s(&buffer->front(),
235 buffer->size(),
236 ::GlobalLock(hglobal),
237 buffer->size());
238 ::GlobalUnlock(hglobal);
239
240 return S_OK;
241 }
242
243 HRESULT CanonicalizeXML(const TCHAR* xmlstring, CString* canonical_xmlstring) {
244 ASSERT1(xmlstring);
245 ASSERT1(canonical_xmlstring);
246
247 // Round-trip through MSXML, having it strip whitespace.
248
249 CComPtr<IXMLDOMDocument> xmldoc;
250 RET_IF_FAILED(CoCreateSafeDOMDocument(&xmldoc));
251 RET_IF_FAILED(xmldoc->put_preserveWhiteSpace(VARIANT_FALSE));
252 {
253 CComBSTR xmlmemory(StringAfterBOM(xmlstring));
254 VARIANT_BOOL is_successful(VARIANT_FALSE);
255 RET_IF_FAILED(xmldoc->loadXML(xmlmemory, &is_successful));
256 if (!is_successful) {
257 CComPtr<IXMLDOMParseError> error;
258 CString error_message;
259 RET_IF_FAILED(GetXMLParseError(xmldoc, &error));
260 ASSERT1(error);
261 HRESULT error_code = 0;
262 RET_IF_FAILED(InterpretXMLParseError(error, &error_code, &error_message));
263 UTIL_LOG(LE, (L"[CanonicalizeXML][parse error: %s]", error_message));
264 ASSERT1(FAILED(error_code));
265 return FAILED(error_code) ? error_code : CI_E_XML_LOAD_ERROR;
266 }
267 }
268 std::vector<CString> lines;
269 {
270 CComBSTR xmlmemory2;
271 RET_IF_FAILED(xmldoc->get_xml(&xmlmemory2));
272 TextToLines(CString(xmlmemory2), L"\r\n", &lines);
273 }
274 {
275 for (size_t i = 0; i < lines.size(); ++i) {
276 TrimString(lines[i], L" \t");
277 }
278 LinesToText(lines, L"", canonical_xmlstring);
279 }
280
281 return S_OK;
282 }
283
284 bool operator==(const XMLFQName& u, const XMLFQName& v) {
285 if (u.uri && v.uri) {
286 // Both uris are non-null -> compare all the components.
287 return !_tcscmp(u.uri, v.uri) && !_tcscmp(u.base, v.base);
288 } else if (!u.uri && !v.uri) {
289 // Both uris are null -> only compare the base names.
290 return !_tcscmp(u.base ? u.base : __T(""), v.base ? v.base : __T(""));
291 } else {
292 // Either uri is null -> the names are in different namespaces.
293 return false;
294 }
295 }
296
297 bool operator!=(const XMLFQName& u, const XMLFQName& v) {
298 return !(u == v);
299 }
300
301 bool operator<(const XMLFQName& u, const XMLFQName &v) {
302 if (u.uri && v.uri) {
303 return (_tcscmp(u.uri, v.uri) < 0) ||
304 ((_tcscmp(u.uri, v.uri) == 0) && (_tcscmp(u.base, v.base) < 0));
305 } else if (!u.uri && !v.uri) {
306 return _tcscmp(u.base, v.base) < 0;
307 } else {
308 return false;
309 }
310 }
311
312 bool operator>(const XMLFQName& u, const XMLFQName& v) {
313 return v < u;
314 }
315
316 bool operator<=(const XMLFQName& u, const XMLFQName& v) {
317 return !(v < u);
318 }
319
320 bool operator>=(const XMLFQName& u, const XMLFQName& v) {
321 return !(u < v);
322 }
323
324 bool EqualXMLName(const XMLFQName& u, const XMLFQName& v) {
325 return u == v;
326 }
327
328 // msxml returns a null uri for nodes that don't belong to a namespace.
329 bool EqualXMLName(IXMLDOMNode* pnode, const XMLFQName& u) {
330 CComBSTR name;
331 CComBSTR uri;
332 if (FAILED(pnode->get_baseName(&name)) ||
333 FAILED(pnode->get_namespaceURI(&uri))) {
334 return false;
335 }
336 return EqualXMLName(XMLFQName(uri, name), u);
337 }
338
339 inline bool EqualXMLName(const XMLFQName& u, IXMLDOMNode* pnode) {
340 return EqualXMLName(pnode, u);
341 }
342
343 HRESULT GetXMLFQName(IXMLDOMNode* node, XMLFQName* name) {
344 ASSERT1(node);
345 ASSERT1(name);
346
347 CComBSTR basename, uri;
348 RET_IF_FAILED(node->get_baseName(&basename));
349 RET_IF_FAILED(node->get_namespaceURI(&uri));
350 *name = XMLFQName(uri, basename);
351 return S_OK;
352 }
353
354 CString XMLFQNameToString(const XMLFQName& fqname) {
355 CString name;
356 if (fqname.uri) {
357 name += fqname.uri;
358 name += L":";
359 }
360 if (fqname.base) {
361 name += fqname.base;
362 }
363 return name;
364 }
365
366 CString NodeToString(IXMLDOMNode* pnode) {
367 ASSERT1(pnode);
368
369 XMLFQName node_name;
370 if (SUCCEEDED(GetXMLFQName(pnode, &node_name))) {
371 return XMLFQNameToString(node_name);
372 }
373 return L"";
374 }
375
376 HRESULT CreateXMLNode(IXMLDOMDocument* xmldoc,
377 int node_type,
378 const TCHAR* node_name,
379 const TCHAR* namespace_uri,
380 const TCHAR* text,
381 IXMLDOMNode** node_out) {
382 ASSERT1(xmldoc);
383 ASSERT1(node_name);
384 // namespace_uri can be NULL
385 // text can be NULL
386 ASSERT1(node_out);
387 ASSERT1(!*node_out);
388
389 *node_out = NULL;
390 CComPtr<IXMLDOMNode> new_node;
391 CComBSTR node_name_string, namespace_uri_string;
392 RET_IF_FAILED(node_name_string.Append(node_name));
393 RET_IF_FAILED(namespace_uri_string.Append(namespace_uri));
394 RET_IF_FAILED(xmldoc->createNode(CComVariant(node_type),
395 node_name_string,
396 namespace_uri_string,
397 &new_node));
398 ASSERT1(new_node);
399
400 // If any text was supplied, put it in the node
401 if (text && text[0]) {
402 RET_IF_FAILED(new_node->put_text(CComBSTR(text)));
403 }
404
405 *node_out = new_node.Detach();
406 return S_OK;
407 }
408
409 HRESULT AppendXMLNode(IXMLDOMNode* xmlnode, IXMLDOMNode* new_child) {
410 ASSERT1(xmlnode);
411 ASSERT1(new_child);
412
413 CComPtr<IXMLDOMNode> useless;
414 RET_IF_FAILED(xmlnode->appendChild(new_child, &useless));
415 return S_OK;
416 }
417
418 HRESULT AppendXMLNode(IXMLDOMNode* xmlnode, const TCHAR* text) {
419 ASSERT1(xmlnode);
420 // text can be NULL
421
422 if (text && text[0]) {
423 CComPtr<IXMLDOMDocument> xml_doc;
424 CComPtr<IXMLDOMText> text_node;
425 RET_IF_FAILED(xmlnode->get_ownerDocument(&xml_doc));
426 ASSERT1(xml_doc);
427 RET_IF_FAILED(xml_doc->createTextNode(CComBSTR(text), &text_node));
428 RET_IF_FAILED(AppendXMLNode(xmlnode, text_node));
429 }
430 return S_OK;
431 }
432
433 HRESULT AddXMLAttributeNode(IXMLDOMNode* xmlnode, IXMLDOMAttribute* new_child) {
434 ASSERT1(xmlnode);
435 ASSERT1(new_child);
436
437 CComPtr<IXMLDOMNamedNodeMap> attributes;
438 CComPtr<IXMLDOMNode> useless;
439 RET_IF_FAILED(xmlnode->get_attributes(&attributes));
440 RET_IF_FAILED(attributes->setNamedItem(new_child, &useless));
441 return S_OK;
442 }
443
444 HRESULT AddXMLAttributeNode(IXMLDOMElement* xmlelement,
445 const TCHAR* attribute_name,
446 const TCHAR* attribute_value) {
447 ASSERT1(xmlelement);
448 ASSERT1(attribute_name);
449 // attribute_value can be NULL
450
451 RET_IF_FAILED(xmlelement->setAttribute(CComBSTR(attribute_name),
452 CComVariant(attribute_value)));
453 return S_OK;
454 }
455
456 HRESULT AddXMLAttributeNode(IXMLDOMNode* xmlnode,
457 const TCHAR* attribute_namespace,
458 const TCHAR* attribute_name,
459 const TCHAR* attribute_value) {
460 ASSERT1(xmlnode);
461 ASSERT1(attribute_name);
462 // attribute_namespace can be NULL
463 // attribute_value can be NULL
464
465 CComPtr<IXMLDOMDocument> xmldoc;
466 RET_IF_FAILED(xmlnode->get_ownerDocument(&xmldoc));
467 ASSERT1(xmldoc);
468
469 CComPtr<IXMLDOMNode> attribute_node;
470 RET_IF_FAILED(CreateXMLNode(xmldoc,
471 NODE_ATTRIBUTE,
472 attribute_name,
473 attribute_namespace,
474 attribute_value,
475 &attribute_node));
476 CComQIPtr<IXMLDOMAttribute> attribute(attribute_node);
477 ASSERT1(attribute);
478 RET_IF_FAILED(AddXMLAttributeNode(xmlnode, attribute));
479 return S_OK;
480 }
481
482 HRESULT RemoveXMLChildrenByName(IXMLDOMNode* xmlnode, const XMLFQName& name) {
483 ASSERT1(xmlnode);
484
485 CComPtr<IXMLDOMNodeList> node_list;
486 RET_IF_FAILED(xmlnode->get_childNodes(&node_list));
487 ASSERT1(node_list);
488
489 bool found = false;
490 do {
491 found = false;
492 long count = 0; // NOLINT
493 RET_IF_FAILED(node_list->get_length(&count));
494 RET_IF_FAILED(node_list->reset());
495
496 for (int i = 0; i < count; ++i) {
497 CComPtr<IXMLDOMNode> child_node, useless;
498 RET_IF_FAILED(node_list->get_item(i, &child_node));
499 ASSERT1(child_node);
500 if (EqualXMLName(child_node, name)) {
501 RET_IF_FAILED(xmlnode->removeChild(child_node, &useless));
502 // Start loop over: the list is "alive" and changes when you remove a
503 // node from it. Yes this seems to be n^2 but in fact we expect at
504 // most one each of <Hash> and/or <Size> nodes.
505 found = true;
506 break;
507 }
508 }
509 } while (found);
510
511 return S_OK;
512 }
513
514 HRESULT GetXMLChildByName(IXMLDOMElement* xmlnode,
515 const TCHAR* child_name,
516 IXMLDOMNode** xmlchild) {
517 ASSERT1(xmlnode);
518 ASSERT1(child_name);
519 ASSERT1(xmlchild);
520 ASSERT1(!*xmlchild);
521
522 *xmlchild = NULL;
523 CComPtr<IXMLDOMNodeList> node_list;
524 long node_list_length = 0; // NOLINT
525 RET_IF_FAILED(xmlnode->getElementsByTagName(CComBSTR(child_name),
526 &node_list));
527 ASSERT1(node_list);
528 RET_IF_FAILED(node_list->get_length(&node_list_length));
529 if (node_list_length <= 0) {
530 return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
531 }
532 // Should only be one child node with name we're looking for.
533 if (node_list_length > 1) {
534 return CI_E_INVALID_MANIFEST;
535 }
536 RET_IF_FAILED(node_list->reset());
537 RET_IF_FAILED(node_list->get_item(0, xmlchild));
538 ASSERT1(*xmlchild);
539 return S_OK;
540 }
541
542 HRESULT InsertXMLBeforeItem(IXMLDOMNode* xmlnode,
543 IXMLDOMNode* new_child,
544 size_t item_number) {
545 ASSERT1(xmlnode);
546 ASSERT1(new_child);
547
548 CComPtr<IXMLDOMNodeList> child_list;
549 CComPtr<IXMLDOMNode> refchild, useless;
550
551 RET_IF_FAILED(xmlnode->get_childNodes(&child_list));
552 ASSERT1(child_list);
553 RET_IF_FAILED(child_list->get_item(item_number, &refchild));
554 ASSERT1(refchild);
555 RET_IF_FAILED(xmlnode->insertBefore(new_child,
556 CComVariant(refchild),
557 &useless));
558 return S_OK;
559 }
560
561 HRESULT GetXMLParseError(IXMLDOMDocument* xmldoc,
562 IXMLDOMParseError** parse_error) {
563 ASSERT1(xmldoc);
564 ASSERT1(parse_error);
565 ASSERT1(!*parse_error);
566
567 *parse_error = NULL;
568 CComPtr<IXMLDOMParseError> error;
569 RET_IF_FAILED(xmldoc->get_parseError(&error));
570 HRESULT error_code = 0;
571 HRESULT hr = error->get_errorCode(&error_code);
572 if (hr == S_OK) {
573 *parse_error = error.Detach();
574 return S_OK;
575 } else if (hr == S_FALSE) {
576 // No parse error
577 return S_FALSE;
578 } else {
579 return hr;
580 }
581 }
582
583 HRESULT InterpretXMLParseError(IXMLDOMParseError* parse_error,
584 HRESULT* error_code,
585 CString* message) {
586 ASSERT1(parse_error);
587 ASSERT1(error_code);
588 ASSERT1(message);
589
590 long line = 0; // NOLINT
591 long char_pos = 0; // NOLINT
592 CComBSTR src_text, reason;
593 RET_IF_FAILED(parse_error->get_errorCode(error_code));
594 RET_IF_FAILED(parse_error->get_line(&line));
595 RET_IF_FAILED(parse_error->get_linepos(&char_pos));
596 RET_IF_FAILED(parse_error->get_srcText(&src_text));
597 RET_IF_FAILED(parse_error->get_reason(&reason));
598
599 // Wild guess.
600 size_t size_estimate = src_text.Length() + reason.Length() + 100;
601
602 // TODO(omaha): think about replacing this call to _snwprintf with a
603 // safestring function.
604 std::vector<TCHAR> s(size_estimate);
605 _snwprintf_s(&s.front(), size_estimate, _TRUNCATE,
606 L"%d(%d) : error 0x%08lx: %s\n %s",
607 line, char_pos, *error_code,
608 reason ? reason : L"",
609 src_text ? src_text : L"<no source text>");
610 // _snwprintf doesn't terminate the string with a null if
611 // the formatted string fills the entire buffer.
612 s[s.size()- 1] = L'\0';
613 *message = &s.front();
614 return S_OK;
615 }
616
617 HRESULT GetNumChildren(IXMLDOMNode* node, int* num_children) {
618 ASSERT1(node);
619 ASSERT1(num_children);
620
621 *num_children = 0;
622 CComPtr<IXMLDOMNodeList> children;
623 RET_IF_FAILED(node->get_childNodes(&children));
624 ASSERT1(children);
625
626 long len = 0; // NOLINT
627 RET_IF_FAILED(children->get_length(&len));
628 *num_children = len;
629 return S_OK;
630 }
631
632 int GetNumAttributes(IXMLDOMNode* node) {
633 ASSERT1(node);
634
635 CComPtr<IXMLDOMNamedNodeMap> attr_map;
636 if (FAILED(node->get_attributes(&attr_map))) {
637 return 0;
638 }
639 ASSERT1(attr_map);
640 long len = 0; // NOLINT
641 if (FAILED(attr_map->get_length(&len))) {
642 return 0;
643 }
644 return len;
645 }
646
647 bool HasAttribute(IXMLDOMNode* node, const TCHAR* attr_name) {
648 ASSERT1(node);
649 ASSERT1(attr_name);
650
651 CComPtr<IXMLDOMNamedNodeMap> attr_map;
652 if (FAILED(node->get_attributes(&attr_map))) {
653 return false;
654 }
655 if (!attr_map) {
656 return false;
657 }
658
659 CComBSTR temp_attr_name(attr_name);
660 CComPtr<IXMLDOMNode> attribute_node;
661 if (FAILED(attr_map->getNamedItem(static_cast<BSTR>(temp_attr_name),
662 &attribute_node))) {
663 return false;
664 }
665
666 return attribute_node != NULL;
667 }
668
669 HRESULT ReadBooleanAttribute(IXMLDOMNode* node,
670 const TCHAR* attr_name,
671 bool* value) {
672 CORE_LOG(L4, (_T("[ReadBooleanAttribute][%s]"), attr_name));
673 ASSERT1(node);
674 ASSERT1(attr_name);
675 ASSERT1(value);
676
677 CComBSTR node_value;
678 HRESULT hr = ReadAttribute(node, attr_name, &node_value);
679 if (FAILED(hr)) {
680 CORE_LOG(LE, (_T("[ReadAttribute failed][%s][0x%x]"), attr_name, hr));
681 return hr;
682 }
683
684 hr = String_StringToBool(static_cast<TCHAR*>(node_value),
685 value);
686 if (FAILED(hr)) {
687 CORE_LOG(LE, (_T("[String_StringToBool failed][0x%x]"), hr));
688 return hr;
689 }
690
691 return S_OK;
692 }
693
694 HRESULT ReadIntAttribute(IXMLDOMNode* node,
695 const TCHAR* attr_name,
696 int* value) {
697 CORE_LOG(L4, (_T("[ReadIntAttribute][%s]"), attr_name));
698 ASSERT1(node);
699 ASSERT1(attr_name);
700 ASSERT1(value);
701
702 CComBSTR node_value;
703 HRESULT hr = ReadAttribute(node, attr_name, &node_value);
704 if (FAILED(hr)) {
705 CORE_LOG(LE, (_T("[ReadAttribute failed][%s][0x%x]"), attr_name, hr));
706 return hr;
707 }
708
709 if (!String_StringToDecimalIntChecked(
710 static_cast<const TCHAR*>(node_value), value)) {
711 return GOOPDATEXML_E_STRTOUINT;
712 }
713 return S_OK;
714 }
715
716 HRESULT ReadGuidAttribute(IXMLDOMNode* node,
717 const TCHAR* attr_name,
718 GUID* value) {
719 CORE_LOG(L4, (_T("[ReadGuidAttribute][%s]"), attr_name));
720 ASSERT1(node);
721 ASSERT1(attr_name);
722 ASSERT1(value);
723
724 CComBSTR node_value;
725 HRESULT hr = ReadAttribute(node, attr_name, &node_value);
726 if (FAILED(hr)) {
727 CORE_LOG(LE, (_T("[ReadAttribute failed][%s][0x%x]"), attr_name, hr));
728 return hr;
729 }
730
731 hr = StringToGuidSafe(static_cast<TCHAR*>(node_value), value);
732 if (FAILED(hr)) {
733 CORE_LOG(LE, (_T("[StringToGuidSafe failed][0x%x]"), hr));
734 return hr;
735 }
736
737 return S_OK;
738 }
739
740 HRESULT ReadStringAttribute(IXMLDOMNode* node,
741 const TCHAR* attr_name,
742 CString* value) {
743 CORE_LOG(L4, (_T("[ReadStringAttribute][%s]"), attr_name));
744 ASSERT1(node);
745 ASSERT1(attr_name);
746 ASSERT1(value);
747
748 CComBSTR node_value;
749 HRESULT hr = ReadAttribute(node, attr_name, &node_value);
750 if (FAILED(hr)) {
751 CORE_LOG(LE, (_T("[ReadAttribute failed][%s][0x%x]"), attr_name, hr));
752 return hr;
753 }
754
755 // Will extract the underlying string.
756 *value = static_cast<TCHAR*>(node_value);
757
758 return S_OK;
759 }
760
761 HRESULT ReadAttribute(IXMLDOMNode* node,
762 const TCHAR* attr_name,
763 BSTR* value) {
764 CORE_LOG(L4, (_T("[ReadAttribute][%s]"), attr_name));
765 ASSERT1(node);
766 ASSERT1(attr_name);
767 ASSERT1(value);
768
769 // First read the attributes.
770 CComPtr<IXMLDOMNamedNodeMap> attributes;
771 HRESULT hr = node->get_attributes(&attributes);
772 if (FAILED(hr)) {
773 CORE_LOG(LE, (_T("[get_attributes failed][0x%x]"), hr));
774 return hr;
775 }
776
777 if (!attributes) {
778 CORE_LOG(LE, (_T("[Msxml S_FALSE return]")));
779 return E_FAIL; // Protect against msxml S_FALSE return.
780 }
781
782 CComPtr<IXMLDOMNode> attribute_node;
783 CComVariant node_value;
784 CComBSTR temp_attr_name(attr_name);
785
786 // Get the attribute using a named node.
787 hr = attributes->getNamedItem(static_cast<BSTR>(temp_attr_name),
788 &attribute_node);
789 if (FAILED(hr)) {
790 CORE_LOG(LE, (_T("[getNamedItem failed][0x%x]"), hr));
791 return hr;
792 }
793
794 if (!attribute_node) {
795 CORE_LOG(LE, (_T("[Msxml S_FALSE return]")));
796 return E_FAIL; // Protect against msxml S_FALSE return.
797 }
798
799 hr = attribute_node->get_nodeValue(&node_value);
800 if (FAILED(hr)) {
801 CORE_LOG(LE, (_T("[get_nodeValue failed][0x%x]"), hr));
802 return hr;
803 }
804
805 if (node_value.vt == VT_EMPTY) {
806 CORE_LOG(LE, (_T("[node_value.vt == VT_EMPTY]")));
807 return E_FAIL;
808 }
809
810 // Extract the variant into a BSTR.
811 node_value.CopyTo(value);
812
813 return S_OK;
814 }
815
816 HRESULT ReadStringValue(IXMLDOMNode* node, CString* value) {
817 CORE_LOG(L4, (_T("[ReadStringValue]")));
818 ASSERT1(node);
819 ASSERT1(value);
820
821 CComPtr<IXMLDOMNodeList> child_nodes;
822 HRESULT hr = node->get_childNodes(&child_nodes);
823 if (FAILED(hr)) {
824 CORE_LOG(LE, (_T("[get_childNodes failed][0x%x]"), hr));
825 return hr;
826 }
827 if (!child_nodes) {
828 CORE_LOG(LE, (_T("[Msxml S_FALSE return]")));
829 return E_FAIL; // Protect against msxml S_FALSE return.
830 }
831
832 long count = 0; // NOLINT
833 hr = child_nodes->get_length(&count);
834 if (FAILED(hr)) {
835 return hr;
836 }
837
838 ASSERT(count == 1, (_T("count: %u"), count));
839 CComPtr<IXMLDOMNode> child_node;
840 hr = child_nodes->nextNode(&child_node);
841 if (FAILED(hr)) {
842 return hr;
843 }
844
845 DOMNodeType type = NODE_INVALID;
846 hr = child_node->get_nodeType(&type);
847 if (FAILED(hr)) {
848 CORE_LOG(LE, (_T("[get_nodeType failed][0x%x]"), hr));
849 return hr;
850 }
851
852 if (type != NODE_TEXT) {
853 CORE_LOG(LE, (_T("[Invalid nodeType][%d]"), type));
854 return E_INVALIDARG;
855 }
856
857 CComVariant node_value;
858 hr = child_node->get_nodeValue(&node_value);
859 if (FAILED(hr)) {
860 CORE_LOG(LE, (_T("[get_nodeValue failed][0x%x]"), hr));
861 return hr;
862 }
863
864 if (node_value.vt != VT_BSTR) {
865 CORE_LOG(LE, (_T("[node_value.vt != VT_BSTR][%d]"), node_value.vt));
866 return E_INVALIDARG;
867 }
868
869 *value = V_BSTR(&node_value);
870 return S_OK;
871 }
872
873 } // namespace omaha
874
OLDNEW
« no previous file with comments | « base/xml_utils.h ('k') | base/xml_utils_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698