mirror of
https://github.com/genodelabs/genode.git
synced 2025-03-22 03:55:26 +00:00
parent
e590d90bf6
commit
6ecbc419c0
@ -87,6 +87,30 @@ class Genode::Xml_generator
|
||||
*/
|
||||
void append(char const *src) { append(src, strlen(src)); }
|
||||
|
||||
/**
|
||||
* Append character, sanitize it if needed
|
||||
*/
|
||||
void append_sanitized(char const c)
|
||||
{
|
||||
switch (c) {
|
||||
case 0: append("�"); break;
|
||||
case '>': append(">"); break;
|
||||
case '<': append("<"); break;
|
||||
case '&': append("&"); break;
|
||||
case '"': append("""); break;
|
||||
case '\'': append("'"); break;
|
||||
default: append(c); break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Append character buffer, sanitize characters if needed
|
||||
*/
|
||||
void append_sanitized(char const *src, size_t len)
|
||||
{
|
||||
for (; len--; append_sanitized(*src++));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return unused part of the buffer
|
||||
*/
|
||||
@ -192,7 +216,7 @@ class Genode::Xml_generator
|
||||
dst.append(' ');
|
||||
dst.append(name);
|
||||
dst.append("=\"");
|
||||
dst.append(value);
|
||||
dst.append(value, strlen(value));
|
||||
dst.append("\"");
|
||||
|
||||
_attr_offset += gap;
|
||||
@ -201,9 +225,14 @@ class Genode::Xml_generator
|
||||
void append(char const *src, size_t src_len)
|
||||
{
|
||||
Out_buffer content_buffer = _content_buffer(false);
|
||||
|
||||
content_buffer.append(src, src_len);
|
||||
_commit_content(content_buffer);
|
||||
}
|
||||
|
||||
void append_sanitized(char const *src, size_t src_len)
|
||||
{
|
||||
Out_buffer content_buffer = _content_buffer(false);
|
||||
content_buffer.append_sanitized(src, src_len);
|
||||
_commit_content(content_buffer);
|
||||
}
|
||||
|
||||
@ -300,6 +329,16 @@ class Genode::Xml_generator
|
||||
_curr_node->append(str, str_len == ~0UL ? strlen(str) : str_len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append sanitized content to XML node
|
||||
*
|
||||
* This method must not be followed by calls of 'attribute'.
|
||||
*/
|
||||
void append_sanitized(char const *str, size_t str_len = ~0UL)
|
||||
{
|
||||
_curr_node->append_sanitized(str, str_len == ~0UL ? strlen(str) : str_len);
|
||||
}
|
||||
|
||||
size_t used() const { return _out_buffer.used(); }
|
||||
};
|
||||
|
||||
|
@ -396,6 +396,66 @@ class Genode::Xml_node
|
||||
Token next_token() const { return _next; }
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper class to decode XML character entities
|
||||
*/
|
||||
struct Decoded_character
|
||||
{
|
||||
char character = 0;
|
||||
size_t encoded_len = 1;
|
||||
|
||||
struct Translation
|
||||
{
|
||||
char character;
|
||||
char const *seq;
|
||||
size_t seq_len;
|
||||
};
|
||||
|
||||
static Translation translate(char const *src, size_t src_len)
|
||||
{
|
||||
enum { NUM = 6 };
|
||||
static Translation translations[NUM] = {
|
||||
{ '>', ">", 4 },
|
||||
{ '<', "<", 4 },
|
||||
{ '&', "&", 5 },
|
||||
{ '"', """, 6 },
|
||||
{ '\'', "'", 6 },
|
||||
{ 0, "�", 6 }
|
||||
};
|
||||
|
||||
if (src_len == 0)
|
||||
return { 0, nullptr, 0 };
|
||||
|
||||
for (unsigned i = 0; i < NUM; i++) {
|
||||
|
||||
Translation const &translation = translations[i];
|
||||
|
||||
if (src_len < translation.seq_len
|
||||
|| memcmp(src, translation.seq, translation.seq_len))
|
||||
continue;
|
||||
|
||||
/* translation matches */
|
||||
return translation;
|
||||
}
|
||||
|
||||
/* sequence is not known, pass single character as is */
|
||||
return { *src, nullptr, 1 };
|
||||
}
|
||||
|
||||
Decoded_character(char const *src, size_t src_len)
|
||||
{
|
||||
if (*src != '&' || src_len == 0) {
|
||||
character = *src;
|
||||
return;
|
||||
}
|
||||
|
||||
Translation const translation = translate(src, src_len);
|
||||
|
||||
character = translation.character;
|
||||
encoded_len = translation.seq_len;
|
||||
}
|
||||
};
|
||||
|
||||
const char *_addr; /* first character of XML data */
|
||||
size_t _max_len; /* length of XML data in characters */
|
||||
int _num_sub_nodes; /* number of immediate sub nodes */
|
||||
@ -605,6 +665,47 @@ class Genode::Xml_node
|
||||
return _end_tag.token().start() - content_addr();
|
||||
}
|
||||
|
||||
/**
|
||||
* Export decoded node content from XML node
|
||||
*
|
||||
* \param dst destination buffer
|
||||
* \param dst_len size of destination buffer in bytes
|
||||
* \return number of bytes written to the destination buffer
|
||||
*
|
||||
* This function transforms XML character entities into their
|
||||
* respective characters.
|
||||
*/
|
||||
size_t decoded_content(char *dst, size_t dst_len) const
|
||||
{
|
||||
size_t result_len = 0;
|
||||
char const *src = content_base();
|
||||
size_t src_len = content_size();
|
||||
|
||||
for (; dst_len > 1 && src_len; result_len++) {
|
||||
|
||||
Decoded_character const decoded_character(src, src_len);
|
||||
|
||||
*dst++ = decoded_character.character;
|
||||
|
||||
src += decoded_character.encoded_len;
|
||||
src_len -= decoded_character.encoded_len;
|
||||
}
|
||||
|
||||
return result_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read decoded node content as Genode::String
|
||||
*/
|
||||
template <typename STRING>
|
||||
STRING decoded_content() const
|
||||
{
|
||||
char buf[STRING::capacity() + 1];
|
||||
size_t const len = decoded_content(buf, sizeof(buf));
|
||||
buf[min(len, STRING::capacity())] = 0;
|
||||
return STRING(buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of the XML node's immediate sub nodes
|
||||
*/
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
#include <base/printf.h>
|
||||
#include <util/xml_generator.h>
|
||||
#include <util/xml_node.h>
|
||||
|
||||
using Genode::size_t;
|
||||
|
||||
@ -68,6 +69,37 @@ int main(int argc, char **argv)
|
||||
catch (Genode::Xml_generator::Buffer_exceeded) {
|
||||
printf("buffer exceeded (expected error)\n"); }
|
||||
|
||||
/*
|
||||
* Test the sanitizing of XML node content
|
||||
*/
|
||||
{
|
||||
/* generate pattern that contains all possible byte values */
|
||||
char pattern[256];
|
||||
for (unsigned i = 0; i < sizeof(pattern); i++)
|
||||
pattern[i] = i;
|
||||
|
||||
/* generate XML with the pattern as content */
|
||||
Genode::Xml_generator xml(dst, sizeof(dst), "data", [&] () {
|
||||
xml.append_sanitized(pattern, sizeof(pattern)); });
|
||||
|
||||
/* parse the generated XML data */
|
||||
Genode::Xml_node node(dst);
|
||||
|
||||
/* obtain decoded node content */
|
||||
char decoded[sizeof(dst)];
|
||||
size_t const decoded_len = node.decoded_content(decoded, sizeof(decoded));
|
||||
|
||||
/* compare result with original pattern */
|
||||
if (decoded_len != sizeof(pattern)) {
|
||||
printf("decoded content has unexpected length %zd\n", decoded_len);
|
||||
return 1;
|
||||
}
|
||||
if (Genode::memcmp(decoded, pattern, sizeof(pattern))) {
|
||||
printf("decoded content does not match original pattern\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
printf("--- XML generator test finished ---\n");
|
||||
|
||||
return 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user