diff --git a/dlls/msxml3/node.c b/dlls/msxml3/node.c index 47f5401c7c2..eadd4e96486 100644 --- a/dlls/msxml3/node.c +++ b/dlls/msxml3/node.c @@ -953,6 +953,15 @@ inline BYTE hex_to_byte(xmlChar c) return c-'a'+10; } +inline BYTE base64_to_byte(xmlChar c) +{ + if(c == '+') return 62; + if(c == '/') return 63; + if(c <= '9') return c-'0'+52; + if(c <= 'Z') return c-'A'; + return c-'a'+26; +} + inline HRESULT VARIANT_from_xmlChar(xmlChar *str, VARIANT *v, BSTR type) { if(!type || !lstrcmpiW(type, szString) || @@ -1041,6 +1050,37 @@ inline HRESULT VARIANT_from_xmlChar(xmlChar *str, VARIANT *v, BSTR type) ((BYTE*)V_ARRAY(v)->pvData)[i] = (hex_to_byte(str[2*i])<<4) + hex_to_byte(str[2*i+1]); } + else if(!lstrcmpiW(type, szBinBase64)) + { + SAFEARRAYBOUND sab; + int i, len; + + len = xmlStrlen(str); + if(str[len-2] == '=') i = 2; + else if(str[len-1] == '=') i = 1; + else i = 0; + + sab.lLbound = 0; + sab.cElements = len/4*3-i; + + V_VT(v) = (VT_ARRAY|VT_UI1); + V_ARRAY(v) = SafeArrayCreate(VT_UI1, 1, &sab); + + if(!V_ARRAY(v)) + return E_OUTOFMEMORY; + + for(i=0; ipvData)[3*i] = (base64_to_byte(str[4*i])<<2) + + (base64_to_byte(str[4*i+1])>>4); + if(3*i+1 < sab.cElements) + ((BYTE*)V_ARRAY(v)->pvData)[3*i+1] = (base64_to_byte(str[4*i+1])<<4) + + (base64_to_byte(str[4*i+2])>>2); + if(3*i+2 < sab.cElements) + ((BYTE*)V_ARRAY(v)->pvData)[3*i+2] = (base64_to_byte(str[4*i+2])<<6) + + base64_to_byte(str[4*i+3]); + } + } else { VARIANT src; diff --git a/dlls/msxml3/tests/domdoc.c b/dlls/msxml3/tests/domdoc.c index d2203564d4b..d72452deb33 100644 --- a/dlls/msxml3/tests/domdoc.c +++ b/dlls/msxml3/tests/domdoc.c @@ -172,6 +172,7 @@ static const CHAR szTypeValueXML[] = " 41221.421\n" " 333C7BC4-460F-11D0-BC04-0080C7055a83\n" " fffca012003c\n" +" YmFzZTY0IHRlc3Q=\n" ""; static const CHAR szBasicTransformSSXMLPart1[] = @@ -4308,6 +4309,23 @@ static void test_NodeTypeValue(void) IXMLDOMNode_Release(pNode); } + + hr = IXMLDOMDocument2_selectSingleNode(doc, _bstr_("root/binbase64"), &pNode); + ok(hr == S_OK, "ret %08x\n", hr ); + if(hr == S_OK) + { + BYTE bytes[] = {0x62,0x61,0x73,0x65,0x36,0x34,0x20,0x74,0x65,0x73,0x74}; + + hr = IXMLDOMNode_get_nodeTypedValue(pNode, &v); + ok(hr == S_OK, "ret %08x\n", hr ); + ok(V_VT(&v) == (VT_ARRAY|VT_UI1), "incorrect type\n"); + ok(V_ARRAY(&v)->rgsabound[0].cElements == 11, "incorrect array size\n"); + if(V_ARRAY(&v)->rgsabound[0].cElements == 11) + ok(!memcmp(bytes, V_ARRAY(&v)->pvData, sizeof(bytes)), "incorrect value\n"); + VariantClear(&v); + + IXMLDOMNode_Release(pNode); + } } IXMLDOMDocument2_Release(doc);