18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * UPnP XML helper routines 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2000-2003 Intel Corporation 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2006-2007 Sony Corporation 58d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2008-2009 Atheros Communications 68d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2009, Jouni Malinen <j@w1.fi> 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * See wps_upnp.c for more details on licensing and code history. 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "base64.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "http.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "upnp_xml.h" 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * XML parsing and formatting 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * XML is a markup language based on unicode; usually (and in our case, 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * always!) based on utf-8. utf-8 uses a variable number of bytes per 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * character. utf-8 has the advantage that all non-ASCII unicode characters are 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * represented by sequences of non-ascii (high bit set) bytes, whereas ASCII 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * characters are single ascii bytes, thus we can use typical text processing. 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * (One other interesting thing about utf-8 is that it is possible to look at 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * any random byte and determine if it is the first byte of a character as 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * versus a continuation byte). 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * The base syntax of XML uses a few ASCII punctionation characters; any 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * characters that would appear in the payload data are rewritten using 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * sequences, e.g., & for ampersand(&) and < for left angle bracket (<). 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Five such escapes total (more can be defined but that does not apply to our 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * case). Thus we can safely parse for angle brackets etc. 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * XML describes tree structures of tagged data, with each element beginning 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * with an opening tag <label> and ending with a closing tag </label> with 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * matching label. (There is also a self-closing tag <label/> which is supposed 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to be equivalent to <label></label>, i.e., no payload, but we are unlikely 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to see it for our purpose). 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Actually the opening tags are a little more complicated because they can 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * contain "attributes" after the label (delimited by ascii space or tab chars) 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * of the form attribute_label="value" or attribute_label='value'; as it turns 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * out we do not have to read any of these attributes, just ignore them. 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Labels are any sequence of chars other than space, tab, right angle bracket 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * (and ?), but may have an inner structure of <namespace><colon><plain_label>. 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * As it turns out, we can ignore the namespaces, in fact we can ignore the 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * entire tree hierarchy, because the plain labels we are looking for will be 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * unique (not in general, but for this application). We do however have to be 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * careful to skip over the namespaces. 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * In generating XML we have to be more careful, but that is easy because 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * everything we do is pretty canned. The only real care to take is to escape 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * any special chars in our payload. 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * xml_next_tag - Advance to next tag 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @in: Input 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @out: OUT: start of tag just after '<' 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @out_tagname: OUT: start of name of tag, skipping namespace 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @end: OUT: one after tag 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, 1 on failure 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * A tag has form: 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * <left angle bracket><...><right angle bracket> 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Within the angle brackets, there is an optional leading forward slash (which 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * makes the tag an ending tag), then an optional leading label (followed by 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * colon) and then the tag name itself. 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Note that angle brackets present in the original data must have been encoded 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * as < and > so they will not trouble us. 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint xml_next_tag(const char *in, const char **out, 791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const char **out_tagname, const char **end) 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (*in && *in != '<') 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt in++; 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*in != '<') 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *out = ++in; 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*in == '/') 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt in++; 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *out_tagname = in; /* maybe */ 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (isalnum(*in) || *in == '-') 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt in++; 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*in == ':') 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *out_tagname = ++in; 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (*in && *in != '>') 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt in++; 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*in != '>') 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *end = ++in; 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* xml_data_encode -- format data for xml file, escaping special characters. 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Note that we assume we are using utf8 both as input and as output! 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * In utf8, characters may be classed as follows: 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 0xxxxxxx(2) -- 1 byte ascii char 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 11xxxxxx(2) -- 1st byte of multi-byte char w/ unicode value >= 0x80 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 110xxxxx(2) -- 1st byte of 2 byte sequence (5 payload bits here) 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 1110xxxx(2) -- 1st byte of 3 byte sequence (4 payload bits here) 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 11110xxx(2) -- 1st byte of 4 byte sequence (3 payload bits here) 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 10xxxxxx(2) -- extension byte (6 payload bits per byte) 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Some values implied by the above are however illegal because they 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * do not represent unicode chars or are not the shortest encoding. 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Actually, we can almost entirely ignore the above and just do 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * text processing same as for ascii text. 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * XML is written with arbitrary unicode characters, except that five 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * characters have special meaning and so must be escaped where they 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * appear in payload data... which we do here. 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid xml_data_encode(struct wpabuf *buf, const char *data, int len) 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i; 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < len; i++) { 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 c = ((u8 *) data)[i]; 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (c == '<') { 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "<"); 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (c == '>') { 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, ">"); 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (c == '&') { 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "&"); 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (c == '\'') { 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, "'"); 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (c == '"') { 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_str(buf, """); 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * We could try to represent control characters using the 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * sequence: &#x; where x is replaced by a hex numeral, but not 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * clear why we would do this. 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(buf, c); 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* xml_add_tagged_data -- format tagged data as a new xml line. 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * tag must not have any special chars. 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * data may have special chars, which are escaped. 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid xml_add_tagged_data(struct wpabuf *buf, const char *tag, const char *data) 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_printf(buf, "<%s>", tag); 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt xml_data_encode(buf, data, os_strlen(data)); 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_printf(buf, "</%s>\n", tag); 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* A POST body looks something like (per upnp spec): 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * <?xml version="1.0"?> 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * <s:Envelope 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * <s:Body> 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * <u:actionName xmlns:u="urn:schemas-upnp-org:service:serviceType:v"> 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * <argumentName>in arg value</argumentName> 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * other in args and their values go here, if any 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * </u:actionName> 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * </s:Body> 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * </s:Envelope> 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * where : 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * s: might be some other namespace name followed by colon 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * u: might be some other namespace name followed by colon 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * actionName will be replaced according to action requested 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * schema following actionName will be WFA scheme instead 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * argumentName will be actual argument name 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * (in arg value) will be actual argument value 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtchar * xml_get_first_item(const char *doc, const char *item) 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *match = item; 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int match_len = os_strlen(item); 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *tag, *tagname, *end; 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *value; 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This is crude: ignore any possible tag name conflicts and go right 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to the first tag of this name. This should be ok for the limited 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * domain of UPnP messages. 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (;;) { 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (xml_next_tag(doc, &tag, &tagname, &end)) 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt doc = end; 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!os_strncasecmp(tagname, match, match_len) && 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *tag != '/' && 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (tagname[match_len] == '>' || 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !isgraph(tagname[match_len]))) { 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = doc; 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (*end && *end != '<') 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end++; 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt value = os_zalloc(1 + (end - doc)); 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (value == NULL) 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(value, doc, end - doc); 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return value; 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * xml_get_base64_item(const char *data, const char *name, 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum http_reply_code *ret) 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *msg; 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *buf; 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned char *decoded; 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = xml_get_first_item(data, name); 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == NULL) { 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *ret = UPNP_ARG_VALUE_INVALID; 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt decoded = base64_decode((unsigned char *) msg, os_strlen(msg), &len); 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(msg); 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (decoded == NULL) { 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *ret = UPNP_OUT_OF_MEMORY; 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = wpabuf_alloc_ext_data(decoded, len); 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) { 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(decoded); 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *ret = UPNP_OUT_OF_MEMORY; 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return buf; 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 253