static HRESULT url_encode_size( const WCHAR *str, ULONG len, const char *except, ULONG *ret_len ) { ULONG i, len_utf8; BOOL convert = FALSE; unsigned char *utf8; *ret_len = 0; for (i = 0; i < len; i++) { if (str[i] > 159) { convert = TRUE; break; } *ret_len += escape_size( str[i], except ); } if (!convert) return S_OK; *ret_len = 0; if (!(utf8 = strdup_utf8( str, len, &len_utf8 ))) return E_OUTOFMEMORY; for (i = 0; i < len_utf8; i++) *ret_len += escape_size( utf8[i], except ); heap_free( utf8 ); return S_OK; }
static ULONG url_encode_byte( unsigned char byte, const char *except, WCHAR *buf ) { static const WCHAR hex[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; switch (escape_size( byte, except )) { case 3: buf[0] = '%'; buf[1] = hex[(byte >> 4) & 0xf]; buf[2] = hex[byte & 0xf]; return 3; case 1: buf[0] = byte; return 1; default: ERR( "unhandled escape size\n" ); return 0; } }
// Note that "s" may be NULL, in which case strings are not allocated // from the stack, and in which case the caller is responsible for // freeing any returned string. char * iks_string (ikstack *s, iks *x) { size_t size; int level, dir; iks *y, *z; char *ret, *t; if (!x) return NULL; if (x->type == IKS_CDATA) { if (s) { return iks_stack_strdup (s, IKS_CDATA_CDATA (x), IKS_CDATA_LEN (x)); } else { ret = iks_malloc (IKS_CDATA_LEN (x)); memcpy (ret, IKS_CDATA_CDATA (x), IKS_CDATA_LEN (x)); return ret; } } size = 0; level = 0; dir = 0; y = x; while (1) { if (dir==0) { if (y->type == IKS_TAG) { size++; size += strlen (IKS_TAG_NAME (y)); for (z = IKS_TAG_ATTRIBS (y); z; z = z->next) { size += 4 + strlen (IKS_ATTRIB_NAME (z)) + escape_size (IKS_ATTRIB_VALUE (z), strlen (IKS_ATTRIB_VALUE (z))); } if (IKS_TAG_CHILDREN (y)) { size++; y = IKS_TAG_CHILDREN (y); level++; continue; } else { size += 2; } } else { size += escape_size (IKS_CDATA_CDATA (y), IKS_CDATA_LEN (y)); } } z = y->next; if (z) { if (0 == level) { if (IKS_TAG_CHILDREN (y)) size += 3 + strlen (IKS_TAG_NAME (y)); break; } y = z; dir = 0; } else { y = y->parent; level--; if (level >= 0) size += 3 + strlen (IKS_TAG_NAME (y)); if (level < 1) break; dir = 1; } } if (s) ret = iks_stack_alloc (s, size + 1); else ret = iks_malloc (size + 1); if (!ret) return NULL; t = ret; level = 0; dir = 0; while (1) { if (dir==0) { if (x->type == IKS_TAG) { *t++ = '<'; t = my_strcat (t, IKS_TAG_NAME (x), 0); y = IKS_TAG_ATTRIBS (x); while (y) { *t++ = ' '; t = my_strcat (t, IKS_ATTRIB_NAME (y), 0); *t++ = '='; *t++ = '\''; t = escape (t, IKS_ATTRIB_VALUE (y), strlen (IKS_ATTRIB_VALUE (y))); *t++ = '\''; y = y->next; } if (IKS_TAG_CHILDREN (x)) { *t++ = '>'; x = IKS_TAG_CHILDREN (x); level++; continue; } else { *t++ = '/'; *t++ = '>'; } } else { t = escape (t, IKS_CDATA_CDATA (x), IKS_CDATA_LEN (x)); } } y = x->next; if (y) { if (0 == level) { if (IKS_TAG_CHILDREN (x)) { *t++ = '<'; *t++ = '/'; t = my_strcat (t, IKS_TAG_NAME (x), 0); *t++ = '>'; } break; } x = y; dir = 0; } else { x = x->parent; level--; if (level >= 0) { *t++ = '<'; *t++ = '/'; t = my_strcat (t, IKS_TAG_NAME (x), 0); *t++ = '>'; } if (level < 1) break; dir = 1; } } *t = '\0'; return ret; }