From 3d342c040232a7faa0de2e44ff2f3fe12b8e9c35 Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Wed, 29 Nov 2017 08:43:53 +0100 Subject: [PATCH 01/16] Fix license issues - Include rapidxml license (MIT) and install it with rpms - Merge 3 directories with rapidxml into one - Add missing license boilerplate (BSD) to include/include/tee_internal_api.h. The file comes from optee_os but it was apparently modified. - Install BSD license with devkit rpm - Update License tags in spec files - Install Apache license with all rpms (including hello world) Change-Id: I2c5ab649c4e81c469a138b04ec9be8a09c1f0ae4 --- TEEStub/CMakeLists.txt | 1 + TEEStub/PropertyAccess/TAProperty.cpp | 2 +- TEEStub/PropertyAccess/TEEProperty.cpp | 2 +- TEEStub/PropertyAccess/rapidxml/rapidxml.hpp | 2397 -------------------- .../PropertyAccess/rapidxml/rapidxml_iterators.hpp | 151 -- TEEStub/PropertyAccess/rapidxml/rapidxml_print.hpp | 426 ---- TEEStub/PropertyAccess/rapidxml/rapidxml_utils.hpp | 111 - include/include/LICENSE | 27 + include/include/tee_internal_api.h | 27 + packaging/tef-simulator-helloworld.spec | 3 +- packaging/tef-simulator.spec | 9 +- rapidxml/license.txt | 19 + .../rapidxml => rapidxml}/rapidxml.hpp | 2 +- .../rapidxml => rapidxml}/rapidxml_iterators.hpp | 0 .../rapidxml => rapidxml}/rapidxml_print.hpp | 0 .../rapidxml => rapidxml}/rapidxml_utils.hpp | 0 simulatordaemon/CMakeLists.txt | 1 + simulatordaemon/src/rapidxml/rapidxml.hpp | 2396 ------------------- 18 files changed, 88 insertions(+), 5486 deletions(-) delete mode 100644 TEEStub/PropertyAccess/rapidxml/rapidxml.hpp delete mode 100644 TEEStub/PropertyAccess/rapidxml/rapidxml_iterators.hpp delete mode 100644 TEEStub/PropertyAccess/rapidxml/rapidxml_print.hpp delete mode 100644 TEEStub/PropertyAccess/rapidxml/rapidxml_utils.hpp create mode 100644 include/include/LICENSE create mode 100644 rapidxml/license.txt rename {simulatordaemon/src/TABinaryManager/rapidxml => rapidxml}/rapidxml.hpp (99%) rename {simulatordaemon/src/TABinaryManager/rapidxml => rapidxml}/rapidxml_iterators.hpp (100%) rename {simulatordaemon/src/TABinaryManager/rapidxml => rapidxml}/rapidxml_print.hpp (100%) rename {simulatordaemon/src/TABinaryManager/rapidxml => rapidxml}/rapidxml_utils.hpp (100%) delete mode 100644 simulatordaemon/src/rapidxml/rapidxml.hpp diff --git a/TEEStub/CMakeLists.txt b/TEEStub/CMakeLists.txt index 536308d..921b0c0 100644 --- a/TEEStub/CMakeLists.txt +++ b/TEEStub/CMakeLists.txt @@ -54,6 +54,7 @@ ADD_LIBRARY(${TARGET_TEF_SIMULATOR_TEE_STUB} STATIC ) INCLUDE_DIRECTORIES( + ${TEF_SIMULATOR_ROOT_PATH} ${TEE_STUB_PATH} ${TEF_SIMULATOR_INCLUDE_PATH}/include ${OSAL_PATH} diff --git a/TEEStub/PropertyAccess/TAProperty.cpp b/TEEStub/PropertyAccess/TAProperty.cpp index 8cefc10..df4aea8 100644 --- a/TEEStub/PropertyAccess/TAProperty.cpp +++ b/TEEStub/PropertyAccess/TAProperty.cpp @@ -25,8 +25,8 @@ * Include files *-----------------------------------------------------------------------------*/ #include -#include #include +#include #include #include #include diff --git a/TEEStub/PropertyAccess/TEEProperty.cpp b/TEEStub/PropertyAccess/TEEProperty.cpp index de47826..ea431c2 100644 --- a/TEEStub/PropertyAccess/TEEProperty.cpp +++ b/TEEStub/PropertyAccess/TEEProperty.cpp @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include "log.h" diff --git a/TEEStub/PropertyAccess/rapidxml/rapidxml.hpp b/TEEStub/PropertyAccess/rapidxml/rapidxml.hpp deleted file mode 100644 index f1aa61e..0000000 --- a/TEEStub/PropertyAccess/rapidxml/rapidxml.hpp +++ /dev/null @@ -1,2397 +0,0 @@ -#ifndef RAPIDXML_HPP_INCLUDED -#define RAPIDXML_HPP_INCLUDED - -// Copyright (C) 2006, 2009 Marcin Kalicinski -// Version 1.13 -// Revision $DateTime: 2009/05/13 01:46:17 $ -//! \file rapidxml.hpp This file contains rapidxml parser and DOM implementation - -// If standard library is disabled, user must provide implementations of required functions and typedefs -#if !defined(RAPIDXML_NO_STDLIB) -#include // For std::size_t -#include // For assert -#include // For placement new -#endif - -// On MSVC, disable "conditional expression is constant" warning (level 4). -// This warning is almost impossible to avoid with certain types of templated code -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable:4127) // Conditional expression is constant -#endif - -/////////////////////////////////////////////////////////////////////////// -// RAPIDXML_PARSE_ERROR - -#if defined(RAPIDXML_NO_EXCEPTIONS) - -#define RAPIDXML_PARSE_ERROR(what, where) { parse_error_handler(what, where); assert(0); } - -namespace rapidxml -{ - //! When exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, - //! this function is called to notify user about the error. - //! It must be defined by the user. - //!

- //! This function cannot return. If it does, the results are undefined. - //!

- //! A very simple definition might look like that: - //!
-	//! void %rapidxml::%parse_error_handler(const char *what, void *where)
-	//! {
-	//!     LOGE(TEE_STUB, "Parse error: %s", what);
-	//!     std::abort();
-	//! }
-	//! 
- //! \param what Human readable description of the error. - //! \param where Pointer to character data where error was detected. - void parse_error_handler(const char *what, void *where); -} - -#else - -#include // For std::exception - -#define RAPIDXML_PARSE_ERROR(what, where) throw parse_error(what, where) - -namespace rapidxml { - -//! Parse error exception. -//! This exception is thrown by the parser when an error occurs. -//! Use what() function to get human-readable error message. -//! Use where() function to get a pointer to position within source text where error was detected. -//!

-//! If throwing exceptions by the parser is undesirable, -//! it can be disabled by defining RAPIDXML_NO_EXCEPTIONS macro before rapidxml.hpp is included. -//! This will cause the parser to call rapidxml::parse_error_handler() function instead of throwing an exception. -//! This function must be defined by the user. -//!

-//! This class derives from std::exception class. -class parse_error: - public std::exception { - -public: - - //! Constructs parse error - parse_error(const char *what, void *where) : - m_what(what), m_where(where) { - } - - //! Gets human readable description of error. - //! \return Pointer to null terminated description of the error. - virtual const char *what() const throw () { - return m_what; - } - - //! Gets pointer to character data where error happened. - //! Ch should be the same as char type of xml_document that produced the error. - //! \return Pointer to location within the parsed string where error occured. - template - Ch *where() const { - return reinterpret_cast(m_where); - } - -private: - - const char *m_what; - void *m_where; - -}; -} - -#endif - -/////////////////////////////////////////////////////////////////////////// -// Pool sizes - -#ifndef RAPIDXML_STATIC_POOL_SIZE -// Size of static memory block of memory_pool. -// Define RAPIDXML_STATIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value. -// No dynamic memory allocations are performed by memory_pool until static memory is exhausted. -#define RAPIDXML_STATIC_POOL_SIZE (64 * 1024) -#endif - -#ifndef RAPIDXML_DYNAMIC_POOL_SIZE -// Size of dynamic memory block of memory_pool. -// Define RAPIDXML_DYNAMIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value. -// After the static block is exhausted, dynamic blocks with approximately this size are allocated by memory_pool. -#define RAPIDXML_DYNAMIC_POOL_SIZE (64 * 1024) -#endif - -#ifndef RAPIDXML_ALIGNMENT -// Memory allocation alignment. -// Define RAPIDXML_ALIGNMENT before including rapidxml.hpp if you want to override the default value, which is the size of pointer. -// All memory allocations for nodes, attributes and strings will be aligned to this value. -// This must be a power of 2 and at least 1, otherwise memory_pool will not work. -#define RAPIDXML_ALIGNMENT sizeof(void *) -#endif - -namespace rapidxml { -// Forward declarations -template class xml_node; -template class xml_attribute; -template class xml_document; - -//! Enumeration listing all node types produced by the parser. -//! Use xml_node::type() function to query node type. -enum node_type { - node_document, //!< A document node. Name and value are empty. - node_element, //!< An element node. Name contains element name. Value contains text of first data node. - node_data, //!< A data node. Name is empty. Value contains data text. - node_cdata, //!< A CDATA node. Name is empty. Value contains data text. - node_comment, //!< A comment node. Name is empty. Value contains comment text. - node_declaration, //!< A declaration node. Name and value are empty. Declaration parameters (version, encoding and standalone) are in node attributes. - node_doctype, //!< A DOCTYPE node. Name is empty. Value contains DOCTYPE text. - node_pi //!< A PI node. Name contains target. Value contains instructions. -}; - -/////////////////////////////////////////////////////////////////////// -// Parsing flags - -//! Parse flag instructing the parser to not create data nodes. -//! Text of first data node will still be placed in value of parent element, unless rapidxml::parse_no_element_values flag is also specified. -//! Can be combined with other flags by use of | operator. -//!

-//! See xml_document::parse() function. -const int parse_no_data_nodes = 0x1; - -//! Parse flag instructing the parser to not use text of first data node as a value of parent element. -//! Can be combined with other flags by use of | operator. -//! Note that child data nodes of element node take precendence over its value when printing. -//! That is, if element has one or more child data nodes and a value, the value will be ignored. -//! Use rapidxml::parse_no_data_nodes flag to prevent creation of data nodes if you want to manipulate data using values of elements. -//!

-//! See xml_document::parse() function. -const int parse_no_element_values = 0x2; - -//! Parse flag instructing the parser to not place zero terminators after strings in the source text. -//! By default zero terminators are placed, modifying source text. -//! Can be combined with other flags by use of | operator. -//!

-//! See xml_document::parse() function. -const int parse_no_string_terminators = 0x4; - -//! Parse flag instructing the parser to not translate entities in the source text. -//! By default entities are translated, modifying source text. -//! Can be combined with other flags by use of | operator. -//!

-//! See xml_document::parse() function. -const int parse_no_entity_translation = 0x8; - -//! Parse flag instructing the parser to disable UTF-8 handling and assume plain 8 bit characters. -//! By default, UTF-8 handling is enabled. -//! Can be combined with other flags by use of | operator. -//!

-//! See xml_document::parse() function. -const int parse_no_utf8 = 0x10; - -//! Parse flag instructing the parser to create XML declaration node. -//! By default, declaration node is not created. -//! Can be combined with other flags by use of | operator. -//!

-//! See xml_document::parse() function. -const int parse_declaration_node = 0x20; - -//! Parse flag instructing the parser to create comments nodes. -//! By default, comment nodes are not created. -//! Can be combined with other flags by use of | operator. -//!

-//! See xml_document::parse() function. -const int parse_comment_nodes = 0x40; - -//! Parse flag instructing the parser to create DOCTYPE node. -//! By default, doctype node is not created. -//! Although W3C specification allows at most one DOCTYPE node, RapidXml will silently accept documents with more than one. -//! Can be combined with other flags by use of | operator. -//!

-//! See xml_document::parse() function. -const int parse_doctype_node = 0x80; - -//! Parse flag instructing the parser to create PI nodes. -//! By default, PI nodes are not created. -//! Can be combined with other flags by use of | operator. -//!

-//! See xml_document::parse() function. -const int parse_pi_nodes = 0x100; - -//! Parse flag instructing the parser to validate closing tag names. -//! If not set, name inside closing tag is irrelevant to the parser. -//! By default, closing tags are not validated. -//! Can be combined with other flags by use of | operator. -//!

-//! See xml_document::parse() function. -const int parse_validate_closing_tags = 0x200; - -//! Parse flag instructing the parser to trim all leading and trailing whitespace of data nodes. -//! By default, whitespace is not trimmed. -//! This flag does not cause the parser to modify source text. -//! Can be combined with other flags by use of | operator. -//!

-//! See xml_document::parse() function. -const int parse_trim_whitespace = 0x400; - -//! Parse flag instructing the parser to condense all whitespace runs of data nodes to a single space character. -//! Trimming of leading and trailing whitespace of data is controlled by rapidxml::parse_trim_whitespace flag. -//! By default, whitespace is not normalized. -//! If this flag is specified, source text will be modified. -//! Can be combined with other flags by use of | operator. -//!

-//! See xml_document::parse() function. -const int parse_normalize_whitespace = 0x800; - -// Compound flags - -//! Parse flags which represent default behaviour of the parser. -//! This is always equal to 0, so that all other flags can be simply ored together. -//! Normally there is no need to inconveniently disable flags by anding with their negated (~) values. -//! This also means that meaning of each flag is a negation of the default setting. -//! For example, if flag name is rapidxml::parse_no_utf8, it means that utf-8 is enabled by default, -//! and using the flag will disable it. -//!

-//! See xml_document::parse() function. -const int parse_default = 0; - -//! A combination of parse flags that forbids any modifications of the source text. -//! This also results in faster parsing. However, note that the following will occur: -//!
    -//!
  • names and values of nodes will not be zero terminated, you have to use xml_base::name_size() and xml_base::value_size() functions to determine where name and value ends
  • -//!
  • entities will not be translated
  • -//!
  • whitespace will not be normalized
  • -//!
-//! See xml_document::parse() function. -const int parse_non_destructive = parse_no_string_terminators - | parse_no_entity_translation; - -//! A combination of parse flags resulting in fastest possible parsing, without sacrificing important data. -//!

-//! See xml_document::parse() function. -const int parse_fastest = parse_non_destructive | parse_no_data_nodes; - -//! A combination of parse flags resulting in largest amount of data being extracted. -//! This usually results in slowest parsing. -//!

-//! See xml_document::parse() function. -const int parse_full = parse_declaration_node | parse_comment_nodes - | parse_doctype_node | parse_pi_nodes | parse_validate_closing_tags; - -/////////////////////////////////////////////////////////////////////// -// Internals - -//! \cond internal -namespace internal { - -// Struct that contains lookup tables for the parser -// It must be a template to allow correct linking (because it has static data members, which are defined in a header file). -template -struct lookup_tables { - static const unsigned char lookup_whitespace[256]; // Whitespace table - static const unsigned char lookup_node_name[256]; // Node name table - static const unsigned char lookup_text[256]; // Text table - static const unsigned char lookup_text_pure_no_ws[256]; // Text table - static const unsigned char lookup_text_pure_with_ws[256]; // Text table - static const unsigned char lookup_attribute_name[256]; // Attribute name table - static const unsigned char lookup_attribute_data_1[256]; // Attribute data table with single quote - static const unsigned char lookup_attribute_data_1_pure[256]; // Attribute data table with single quote - static const unsigned char lookup_attribute_data_2[256]; // Attribute data table with double quotes - static const unsigned char lookup_attribute_data_2_pure[256]; // Attribute data table with double quotes - static const unsigned char lookup_digits[256]; // Digits - static const unsigned char lookup_upcase[256]; // To uppercase conversion table for ASCII characters -}; - -// Find length of the string -template -inline std::size_t measure(const Ch *p) { - const Ch *tmp = p; - while (*tmp) - ++tmp; - return tmp - p; -} - -// Compare strings for equality -template -inline bool compare(const Ch *p1, std::size_t size1, const Ch *p2, - std::size_t size2, bool case_sensitive) { - if (size1 != size2) return false; - if (case_sensitive) { - for (const Ch *end = p1 + size1; p1 < end; ++p1, ++p2) - if (*p1 != *p2) return false; - } else { - for (const Ch *end = p1 + size1; p1 < end; ++p1, ++p2) - if (lookup_tables<0>::lookup_upcase[static_cast(*p1)] - != lookup_tables<0>::lookup_upcase[static_cast(*p2)]) - return false; - } - return true; -} -} -//! \endcond - -/////////////////////////////////////////////////////////////////////// -// Memory pool - -//! This class is used by the parser to create new nodes and attributes, without overheads of dynamic memory allocation. -//! In most cases, you will not need to use this class directly. -//! However, if you need to create nodes manually or modify names/values of nodes, -//! you are encouraged to use memory_pool of relevant xml_document to allocate the memory. -//! Not only is this faster than allocating them by using new operator, -//! but also their lifetime will be tied to the lifetime of document, -//! possibly simplyfing memory management. -//!

-//! Call allocate_node() or allocate_attribute() functions to obtain new nodes or attributes from the pool. -//! You can also call allocate_string() function to allocate strings. -//! Such strings can then be used as names or values of nodes without worrying about their lifetime. -//! Note that there is no free() function -- all allocations are freed at once when clear() function is called, -//! or when the pool is destroyed. -//!

-//! It is also possible to create a standalone memory_pool, and use it -//! to allocate nodes, whose lifetime will not be tied to any document. -//!

-//! Pool maintains RAPIDXML_STATIC_POOL_SIZE bytes of statically allocated memory. -//! Until static memory is exhausted, no dynamic memory allocations are done. -//! When static memory is exhausted, pool allocates additional blocks of memory of size RAPIDXML_DYNAMIC_POOL_SIZE each, -//! by using global new[] and delete[] operators. -//! This behaviour can be changed by setting custom allocation routines. -//! Use set_allocator() function to set them. -//!

-//! Allocations for nodes, attributes and strings are aligned at RAPIDXML_ALIGNMENT bytes. -//! This value defaults to the size of pointer on target architecture. -//!

-//! To obtain absolutely top performance from the parser, -//! it is important that all nodes are allocated from a single, contiguous block of memory. -//! Otherwise, cache misses when jumping between two (or more) disjoint blocks of memory can slow down parsing quite considerably. -//! If required, you can tweak RAPIDXML_STATIC_POOL_SIZE, RAPIDXML_DYNAMIC_POOL_SIZE and RAPIDXML_ALIGNMENT -//! to obtain best wasted memory to performance compromise. -//! To do it, define their values before rapidxml.hpp file is included. -//! \param Ch Character type of created nodes. -template -class memory_pool { - -public: - - //! \cond internal - typedef void *(alloc_func)(std::size_t); // Type of user-defined function used to allocate memory - typedef void (free_func)(void *); // Type of user-defined function used to free memory - //! \endcond - - //! Constructs empty pool with default allocator functions. - memory_pool() : - m_alloc_func(0), m_free_func(0) { - init(); - } - - //! Destroys pool and frees all the memory. - //! This causes memory occupied by nodes allocated by the pool to be freed. - //! Nodes allocated from the pool are no longer valid. - ~memory_pool() { - clear(); - } - - //! Allocates a new node from the pool, and optionally assigns name and value to it. - //! If the allocation request cannot be accomodated, this function will throw std::bad_alloc. - //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function - //! will call rapidxml::parse_error_handler() function. - //! \param type Type of node to create. - //! \param name Name to assign to the node, or 0 to assign no name. - //! \param value Value to assign to the node, or 0 to assign no value. - //! \param name_size Size of name to assign, or 0 to automatically calculate size from name string. - //! \param value_size Size of value to assign, or 0 to automatically calculate size from value string. - //! \return Pointer to allocated node. This pointer will never be NULL. - xml_node *allocate_node(node_type type, const Ch *name = 0, - const Ch *value = 0, std::size_t name_size = 0, - std::size_t value_size = 0) { - void *memory = allocate_aligned(sizeof(xml_node )); - xml_node *node = new (memory) xml_node(type); - if (name) { - if (name_size > 0) - node->name(name, name_size); - else node->name(name); - } - if (value) { - if (value_size > 0) - node->value(value, value_size); - else node->value(value); - } - return node; - } - - //! Allocates a new attribute from the pool, and optionally assigns name and value to it. - //! If the allocation request cannot be accomodated, this function will throw std::bad_alloc. - //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function - //! will call rapidxml::parse_error_handler() function. - //! \param name Name to assign to the attribute, or 0 to assign no name. - //! \param value Value to assign to the attribute, or 0 to assign no value. - //! \param name_size Size of name to assign, or 0 to automatically calculate size from name string. - //! \param value_size Size of value to assign, or 0 to automatically calculate size from value string. - //! \return Pointer to allocated attribute. This pointer will never be NULL. - xml_attribute *allocate_attribute(const Ch *name = 0, const Ch *value = 0, - std::size_t name_size = 0, std::size_t value_size = 0) { - void *memory = allocate_aligned(sizeof(xml_attribute )); - xml_attribute *attribute = new (memory) xml_attribute; - if (name) { - if (name_size > 0) - attribute->name(name, name_size); - else attribute->name(name); - } - if (value) { - if (value_size > 0) - attribute->value(value, value_size); - else attribute->value(value); - } - return attribute; - } - - //! Allocates a char array of given size from the pool, and optionally copies a given string to it. - //! If the allocation request cannot be accomodated, this function will throw std::bad_alloc. - //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function - //! will call rapidxml::parse_error_handler() function. - //! \param source String to initialize the allocated memory with, or 0 to not initialize it. - //! \param size Number of characters to allocate, or zero to calculate it automatically from source string length; if size is 0, source string must be specified and null terminated. - //! \return Pointer to allocated char array. This pointer will never be NULL. - Ch *allocate_string(const Ch *source = 0, std::size_t size = 0) { - assert(source || size); // Either source or size (or both) must be specified - if (size == 0) size = internal::measure(source) + 1; - Ch *result = static_cast(allocate_aligned(size * sizeof(Ch))); - if (source) for (std::size_t i = 0; i < size; ++i) - result[i] = source[i]; - return result; - } - - //! Clones an xml_node and its hierarchy of child nodes and attributes. - //! Nodes and attributes are allocated from this memory pool. - //! Names and values are not cloned, they are shared between the clone and the source. - //! Result node can be optionally specified as a second parameter, - //! in which case its contents will be replaced with cloned source node. - //! This is useful when you want to clone entire document. - //! \param source Node to clone. - //! \param result Node to put results in, or 0 to automatically allocate result node - //! \return Pointer to cloned node. This pointer will never be NULL. - xml_node *clone_node(const xml_node *source, - xml_node *result = 0) { - // Prepare result node - if (result) { - result->remove_all_attributes(); - result->remove_all_nodes(); - result->type(source->type()); - } else result = allocate_node(source->type()); - - // Clone name and value - result->name(source->name(), source->name_size()); - result->value(source->value(), source->value_size()); - - // Clone child nodes and attributes - for (xml_node *child = source->first_node(); child; - child = child->next_sibling()) - result->append_node(clone_node(child)); - for (xml_attribute *attr = source->first_attribute(); attr; - attr = attr->next_attribute()) - result->append_attribute( - allocate_attribute(attr->name(), attr->value(), attr->name_size(), - attr->value_size())); - - return result; - } - - //! Clears the pool. - //! This causes memory occupied by nodes allocated by the pool to be freed. - //! Any nodes or strings allocated from the pool will no longer be valid. - void clear() { - while (m_begin != m_static_memory) { - char *previous_begin = reinterpret_cast
(align(m_begin)) - ->previous_begin; - if (m_free_func) - m_free_func(m_begin); - else delete[] m_begin; - m_begin = previous_begin; - } - init(); - } - - //! Sets or resets the user-defined memory allocation functions for the pool. - //! This can only be called when no memory is allocated from the pool yet, otherwise results are undefined. - //! Allocation function must not return invalid pointer on failure. It should either throw, - //! stop the program, or use longjmp() function to pass control to other place of program. - //! If it returns invalid pointer, results are undefined. - //!

- //! User defined allocation functions must have the following forms: - //!
- //!
void *allocate(std::size_t size); - //!
void free(void *pointer); - //!

- //! \param af Allocation function, or 0 to restore default function - //! \param ff Free function, or 0 to restore default function - void set_allocator(alloc_func *af, free_func *ff) { - assert(m_begin == m_static_memory && m_ptr == align(m_begin)); // Verify that no memory is allocated yet - m_alloc_func = af; - m_free_func = ff; - } - -private: - - struct header { - char *previous_begin; - }; - - void init() { - m_begin = m_static_memory; - m_ptr = align(m_begin); - m_end = m_static_memory + sizeof(m_static_memory); - } - - char *align(char *ptr) { - std::size_t alignment = ((RAPIDXML_ALIGNMENT - - (std::size_t(ptr) & (RAPIDXML_ALIGNMENT - 1))) - & (RAPIDXML_ALIGNMENT - 1)); - return ptr + alignment; - } - - char *allocate_raw(std::size_t size) { - // Allocate - void *memory; - if (m_alloc_func) // Allocate memory using either user-specified allocation function or global operator new[] - { - memory = m_alloc_func(size); - assert(memory); // Allocator is not allowed to return 0, on failure it must either throw, stop the program or use longjmp - } else { - memory = new char[size]; -#ifdef RAPIDXML_NO_EXCEPTIONS - if (!memory) // If exceptions are disabled, verify memory allocation, because new will not be able to throw bad_alloc - RAPIDXML_PARSE_ERROR("out of memory", 0); -#endif - } - return static_cast(memory); - } - - void *allocate_aligned(std::size_t size) { - // Calculate aligned pointer - char *result = align(m_ptr); - - // If not enough memory left in current pool, allocate a new pool - if (result + size > m_end) { - // Calculate required pool size (may be bigger than RAPIDXML_DYNAMIC_POOL_SIZE) - std::size_t pool_size = RAPIDXML_DYNAMIC_POOL_SIZE; - if (pool_size < size) pool_size = size; - - // Allocate - std::size_t alloc_size = sizeof(header) + (2 * RAPIDXML_ALIGNMENT - 2) - + pool_size; // 2 alignments required in worst case: one for header, one for actual allocation - char *raw_memory = allocate_raw(alloc_size); - - // Setup new pool in allocated memory - char *pool = align(raw_memory); - header *new_header = reinterpret_cast
(pool); - new_header->previous_begin = m_begin; - m_begin = raw_memory; - m_ptr = pool + sizeof(header); - m_end = raw_memory + alloc_size; - - // Calculate aligned pointer again using new pool - result = align(m_ptr); - } - - // Update pool and return aligned pointer - m_ptr = result + size; - return result; - } - - char *m_begin; // Start of raw memory making up current pool - char *m_ptr; // First free byte in current pool - char *m_end; // One past last available byte in current pool - char m_static_memory[RAPIDXML_STATIC_POOL_SIZE]; // Static raw memory - alloc_func *m_alloc_func; // Allocator function, or 0 if default is to be used - free_func *m_free_func; // Free function, or 0 if default is to be used -}; - -/////////////////////////////////////////////////////////////////////////// -// XML base - -//! Base class for xml_node and xml_attribute implementing common functions: -//! name(), name_size(), value(), value_size() and parent(). -//! \param Ch Character type to use -template -class xml_base { - -public: - - /////////////////////////////////////////////////////////////////////////// - // Construction & destruction - - // Construct a base with empty name, value and parent - xml_base() : - m_name(0), m_value(0), m_name_size(0), m_value_size(0), m_parent(0) { - } - - /////////////////////////////////////////////////////////////////////////// - // Node data access - - //! Gets name of the node. - //! Interpretation of name depends on type of node. - //! Note that name will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse. - //!

- //! Use name_size() function to determine length of the name. - //! \return Name of node, or empty string if node has no name. - Ch *name() const { - return m_name ? m_name : nullstr(); - } - - //! Gets size of node name, not including terminator character. - //! This function works correctly irrespective of whether name is or is not zero terminated. - //! \return Size of node name, in characters. - std::size_t name_size() const { - return m_name ? m_name_size : 0; - } - - //! Gets value of node. - //! Interpretation of value depends on type of node. - //! Note that value will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse. - //!

- //! Use value_size() function to determine length of the value. - //! \return Value of node, or empty string if node has no value. - Ch *value() const { - return m_value ? m_value : nullstr(); - } - - //! Gets size of node value, not including terminator character. - //! This function works correctly irrespective of whether value is or is not zero terminated. - //! \return Size of node value, in characters. - std::size_t value_size() const { - return m_value ? m_value_size : 0; - } - - /////////////////////////////////////////////////////////////////////////// - // Node modification - - //! Sets name of node to a non zero-terminated string. - //! See \ref ownership_of_strings. - //!

- //! Note that node does not own its name or value, it only stores a pointer to it. - //! It will not delete or otherwise free the pointer on destruction. - //! It is reponsibility of the user to properly manage lifetime of the string. - //! The easiest way to achieve it is to use memory_pool of the document to allocate the string - - //! on destruction of the document the string will be automatically freed. - //!

- //! Size of name must be specified separately, because name does not have to be zero terminated. - //! Use name(const Ch *) function to have the length automatically calculated (string must be zero terminated). - //! \param name Name of node to set. Does not have to be zero terminated. - //! \param size Size of name, in characters. This does not include zero terminator, if one is present. - void name(const Ch *name, std::size_t size) { - m_name = const_cast(name); - m_name_size = size; - } - - //! Sets name of node to a zero-terminated string. - //! See also \ref ownership_of_strings and xml_node::name(const Ch *, std::size_t). - //! \param name Name of node to set. Must be zero terminated. - void name(const Ch *name) { - this->name(name, internal::measure(name)); - } - - //! Sets value of node to a non zero-terminated string. - //! See \ref ownership_of_strings. - //!

- //! Note that node does not own its name or value, it only stores a pointer to it. - //! It will not delete or otherwise free the pointer on destruction. - //! It is reponsibility of the user to properly manage lifetime of the string. - //! The easiest way to achieve it is to use memory_pool of the document to allocate the string - - //! on destruction of the document the string will be automatically freed. - //!

- //! Size of value must be specified separately, because it does not have to be zero terminated. - //! Use value(const Ch *) function to have the length automatically calculated (string must be zero terminated). - //!

- //! If an element has a child node of type node_data, it will take precedence over element value when printing. - //! If you want to manipulate data of elements using values, use parser flag rapidxml::parse_no_data_nodes to prevent creation of data nodes by the parser. - //! \param value value of node to set. Does not have to be zero terminated. - //! \param size Size of value, in characters. This does not include zero terminator, if one is present. - void value(const Ch *value, std::size_t size) { - m_value = const_cast(value); - m_value_size = size; - } - - //! Sets value of node to a zero-terminated string. - //! See also \ref ownership_of_strings and xml_node::value(const Ch *, std::size_t). - //! \param value Vame of node to set. Must be zero terminated. - void value(const Ch *value) { - this->value(value, internal::measure(value)); - } - - /////////////////////////////////////////////////////////////////////////// - // Related nodes access - - //! Gets node parent. - //! \return Pointer to parent node, or 0 if there is no parent. - xml_node *parent() const { - return m_parent; - } - -protected: - - // Return empty string - static Ch *nullstr() { - static Ch zero = Ch('\0'); - return &zero; - } - - Ch *m_name; // Name of node, or 0 if no name - Ch *m_value; // Value of node, or 0 if no value - std::size_t m_name_size; // Length of node name, or undefined of no name - std::size_t m_value_size; // Length of node value, or undefined if no value - xml_node *m_parent; // Pointer to parent node, or 0 if none - -}; - -//! Class representing attribute node of XML document. -//! Each attribute has name and value strings, which are available through name() and value() functions (inherited from xml_base). -//! Note that after parse, both name and value of attribute will point to interior of source text used for parsing. -//! Thus, this text must persist in memory for the lifetime of attribute. -//! \param Ch Character type to use. -template -class xml_attribute: - public xml_base { - - friend class xml_node ; - -public: - - /////////////////////////////////////////////////////////////////////////// - // Construction & destruction - - //! Constructs an empty attribute with the specified type. - //! Consider using memory_pool of appropriate xml_document if allocating attributes manually. - xml_attribute() : m_prev_attribute(0), m_next_attribute(0) { - } - - /////////////////////////////////////////////////////////////////////////// - // Related nodes access - - //! Gets document of which attribute is a child. - //! \return Pointer to document that contains this attribute, or 0 if there is no parent document. - xml_document *document() const { - if (xml_node *node = this->parent()) { - while (node->parent()) - node = node->parent(); - return - node->type() == node_document ? - static_cast *>(node) : 0; - } else return 0; - } - - //! Gets previous attribute, optionally matching attribute name. - //! \param name Name of attribute to find, or 0 to return previous attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero - //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string - //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters - //! \return Pointer to found attribute, or 0 if not found. - xml_attribute *previous_attribute(const Ch *name = 0, - std::size_t name_size = 0, bool case_sensitive = true) const { - if (name) { - if (name_size == 0) name_size = internal::measure(name); - for (xml_attribute *attribute = m_prev_attribute; attribute; - attribute = attribute->m_prev_attribute) - if (internal::compare(attribute->name(), attribute->name_size(), name, - name_size, case_sensitive)) return attribute; - return 0; - } else return this->m_parent ? m_prev_attribute : 0; - } - - //! Gets next attribute, optionally matching attribute name. - //! \param name Name of attribute to find, or 0 to return next attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero - //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string - //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters - //! \return Pointer to found attribute, or 0 if not found. - xml_attribute *next_attribute(const Ch *name = 0, std::size_t name_size = - 0, bool case_sensitive = true) const { - if (name) { - if (name_size == 0) name_size = internal::measure(name); - for (xml_attribute *attribute = m_next_attribute; attribute; - attribute = attribute->m_next_attribute) - if (internal::compare(attribute->name(), attribute->name_size(), name, - name_size, case_sensitive)) return attribute; - return 0; - } else return this->m_parent ? m_next_attribute : 0; - } - -private: - - xml_attribute *m_prev_attribute; // Pointer to previous sibling of attribute, or 0 if none; only valid if parent is non-zero - xml_attribute *m_next_attribute; // Pointer to next sibling of attribute, or 0 if none; only valid if parent is non-zero - -}; - -/////////////////////////////////////////////////////////////////////////// -// XML node - -//! Class representing a node of XML document. -//! Each node may have associated name and value strings, which are available through name() and value() functions. -//! Interpretation of name and value depends on type of the node. -//! Type of node can be determined by using type() function. -//!

-//! Note that after parse, both name and value of node, if any, will point interior of source text used for parsing. -//! Thus, this text must persist in the memory for the lifetime of node. -//! \param Ch Character type to use. -template -class xml_node: - public xml_base { - -public: - - /////////////////////////////////////////////////////////////////////////// - // Construction & destruction - - //! Constructs an empty node with the specified type. - //! Consider using memory_pool of appropriate document to allocate nodes manually. - //! \param type Type of node to construct. - xml_node(node_type type) : - m_type(type), m_first_node(0), m_last_node(0), m_first_attribute(0), m_last_attribute(0), - m_prev_sibling(0), m_next_sibling(0) { - } - - /////////////////////////////////////////////////////////////////////////// - // Node data access - - //! Gets type of node. - //! \return Type of node. - node_type type() const { - return m_type; - } - - /////////////////////////////////////////////////////////////////////////// - // Related nodes access - - //! Gets document of which node is a child. - //! \return Pointer to document that contains this node, or 0 if there is no parent document. - xml_document *document() const { - xml_node *node = const_cast *>(this); - while (node->parent()) - node = node->parent(); - return - node->type() == node_document ? static_cast *>(node) : - 0; - } - - //! Gets first child node, optionally matching node name. - //! \param name Name of child to find, or 0 to return first child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero - //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string - //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters - //! \return Pointer to found child, or 0 if not found. - xml_node *first_node(const Ch *name = 0, std::size_t name_size = 0, - bool case_sensitive = true) const { - if (name) { - if (name_size == 0) name_size = internal::measure(name); - for (xml_node *child = m_first_node; child; - child = child->next_sibling()) - if (internal::compare(child->name(), child->name_size(), name, - name_size, case_sensitive)) return child; - return 0; - } else return m_first_node; - } - - //! Gets last child node, optionally matching node name. - //! Behaviour is undefined if node has no children. - //! Use first_node() to test if node has children. - //! \param name Name of child to find, or 0 to return last child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero - //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string - //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters - //! \return Pointer to found child, or 0 if not found. - xml_node *last_node(const Ch *name = 0, std::size_t name_size = 0, - bool case_sensitive = true) const { - assert(m_first_node); // Cannot query for last child if node has no children - if (name) { - if (name_size == 0) name_size = internal::measure(name); - for (xml_node *child = m_last_node; child; - child = child->previous_sibling()) - if (internal::compare(child->name(), child->name_size(), name, - name_size, case_sensitive)) return child; - return 0; - } else return m_last_node; - } - - //! Gets previous sibling node, optionally matching node name. - //! Behaviour is undefined if node has no parent. - //! Use parent() to test if node has a parent. - //! \param name Name of sibling to find, or 0 to return previous sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero - //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string - //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters - //! \return Pointer to found sibling, or 0 if not found. - xml_node *previous_sibling(const Ch *name = 0, std::size_t name_size = 0, - bool case_sensitive = true) const { - assert(this->m_parent); // Cannot query for siblings if node has no parent - if (name) { - if (name_size == 0) name_size = internal::measure(name); - for (xml_node *sibling = m_prev_sibling; sibling; - sibling = sibling->m_prev_sibling) - if (internal::compare(sibling->name(), sibling->name_size(), name, - name_size, case_sensitive)) return sibling; - return 0; - } else return m_prev_sibling; - } - - //! Gets next sibling node, optionally matching node name. - //! Behaviour is undefined if node has no parent. - //! Use parent() to test if node has a parent. - //! \param name Name of sibling to find, or 0 to return next sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero - //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string - //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters - //! \return Pointer to found sibling, or 0 if not found. - xml_node *next_sibling(const Ch *name = 0, std::size_t name_size = 0, - bool case_sensitive = true) const { - assert(this->m_parent); // Cannot query for siblings if node has no parent - if (name) { - if (name_size == 0) name_size = internal::measure(name); - for (xml_node *sibling = m_next_sibling; sibling; - sibling = sibling->m_next_sibling) - if (internal::compare(sibling->name(), sibling->name_size(), name, - name_size, case_sensitive)) return sibling; - return 0; - } else return m_next_sibling; - } - - //! Gets first attribute of node, optionally matching attribute name. - //! \param name Name of attribute to find, or 0 to return first attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero - //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string - //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters - //! \return Pointer to found attribute, or 0 if not found. - xml_attribute *first_attribute(const Ch *name = 0, std::size_t name_size = - 0, bool case_sensitive = true) const { - if (name) { - if (name_size == 0) name_size = internal::measure(name); - for (xml_attribute *attribute = m_first_attribute; attribute; - attribute = attribute->m_next_attribute) - if (internal::compare(attribute->name(), attribute->name_size(), name, - name_size, case_sensitive)) return attribute; - return 0; - } else return m_first_attribute; - } - - //! Gets last attribute of node, optionally matching attribute name. - //! \param name Name of attribute to find, or 0 to return last attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero - //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string - //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters - //! \return Pointer to found attribute, or 0 if not found. - xml_attribute *last_attribute(const Ch *name = 0, std::size_t name_size = - 0, bool case_sensitive = true) const { - if (name) { - if (name_size == 0) name_size = internal::measure(name); - for (xml_attribute *attribute = m_last_attribute; attribute; - attribute = attribute->m_prev_attribute) - if (internal::compare(attribute->name(), attribute->name_size(), name, - name_size, case_sensitive)) return attribute; - return 0; - } else return m_first_attribute ? m_last_attribute : 0; - } - - /////////////////////////////////////////////////////////////////////////// - // Node modification - - //! Sets type of node. - //! \param type Type of node to set. - void type(node_type type) { - m_type = type; - } - - /////////////////////////////////////////////////////////////////////////// - // Node manipulation - - //! Prepends a new child node. - //! The prepended child becomes the first child, and all existing children are moved one position back. - //! \param child Node to prepend. - void prepend_node(xml_node *child) { - assert(child && !child->parent() && child->type() != node_document); - if (first_node()) { - child->m_next_sibling = m_first_node; - m_first_node->m_prev_sibling = child; - } else { - child->m_next_sibling = 0; - m_last_node = child; - } - m_first_node = child; - child->m_parent = this; - child->m_prev_sibling = 0; - } - - //! Appends a new child node. - //! The appended child becomes the last child. - //! \param child Node to append. - void append_node(xml_node *child) { - assert(child && !child->parent() && child->type() != node_document); - if (first_node()) { - child->m_prev_sibling = m_last_node; - m_last_node->m_next_sibling = child; - } else { - child->m_prev_sibling = 0; - m_first_node = child; - } - m_last_node = child; - child->m_parent = this; - child->m_next_sibling = 0; - } - - //! Inserts a new child node at specified place inside the node. - //! All children after and including the specified node are moved one position back. - //! \param where Place where to insert the child, or 0 to insert at the back. - //! \param child Node to insert. - void insert_node(xml_node *where, xml_node *child) { - assert(!where || where->parent() == this); - assert(child && !child->parent() && child->type() != node_document); - if (where == m_first_node) - prepend_node(child); - else if (where == 0) - append_node(child); - else { - child->m_prev_sibling = where->m_prev_sibling; - child->m_next_sibling = where; - where->m_prev_sibling->m_next_sibling = child; - where->m_prev_sibling = child; - child->m_parent = this; - } - } - - //! Removes first child node. - //! If node has no children, behaviour is undefined. - //! Use first_node() to test if node has children. - void remove_first_node() { - assert(first_node()); - xml_node *child = m_first_node; - m_first_node = child->m_next_sibling; - if (child->m_next_sibling) - child->m_next_sibling->m_prev_sibling = 0; - else m_last_node = 0; - child->m_parent = 0; - } - - //! Removes last child of the node. - //! If node has no children, behaviour is undefined. - //! Use first_node() to test if node has children. - void remove_last_node() { - assert(first_node()); - xml_node *child = m_last_node; - if (child->m_prev_sibling) { - m_last_node = child->m_prev_sibling; - child->m_prev_sibling->m_next_sibling = 0; - } else m_first_node = 0; - child->m_parent = 0; - } - - //! Removes specified child from the node - // \param where Pointer to child to be removed. - void remove_node(xml_node *where) { - assert(where && where->parent() == this); - assert(first_node()); - if (where == m_first_node) - remove_first_node(); - else if (where == m_last_node) - remove_last_node(); - else { - where->m_prev_sibling->m_next_sibling = where->m_next_sibling; - where->m_next_sibling->m_prev_sibling = where->m_prev_sibling; - where->m_parent = 0; - } - } - - //! Removes all child nodes (but not attributes). - void remove_all_nodes() { - for (xml_node *node = first_node(); node; node = node->m_next_sibling) - node->m_parent = 0; - m_first_node = 0; - } - - //! Prepends a new attribute to the node. - //! \param attribute Attribute to prepend. - void prepend_attribute(xml_attribute *attribute) { - assert(attribute && !attribute->parent()); - if (first_attribute()) { - attribute->m_next_attribute = m_first_attribute; - m_first_attribute->m_prev_attribute = attribute; - } else { - attribute->m_next_attribute = 0; - m_last_attribute = attribute; - } - m_first_attribute = attribute; - attribute->m_parent = this; - attribute->m_prev_attribute = 0; - } - - //! Appends a new attribute to the node. - //! \param attribute Attribute to append. - void append_attribute(xml_attribute *attribute) { - assert(attribute && !attribute->parent()); - if (first_attribute()) { - attribute->m_prev_attribute = m_last_attribute; - m_last_attribute->m_next_attribute = attribute; - } else { - attribute->m_prev_attribute = 0; - m_first_attribute = attribute; - } - m_last_attribute = attribute; - attribute->m_parent = this; - attribute->m_next_attribute = 0; - } - - //! Inserts a new attribute at specified place inside the node. - //! All attributes after and including the specified attribute are moved one position back. - //! \param where Place where to insert the attribute, or 0 to insert at the back. - //! \param attribute Attribute to insert. - void insert_attribute(xml_attribute *where, - xml_attribute *attribute) { - assert(!where || where->parent() == this); - assert(attribute && !attribute->parent()); - if (where == m_first_attribute) - prepend_attribute(attribute); - else if (where == 0) - append_attribute(attribute); - else { - attribute->m_prev_attribute = where->m_prev_attribute; - attribute->m_next_attribute = where; - where->m_prev_attribute->m_next_attribute = attribute; - where->m_prev_attribute = attribute; - attribute->m_parent = this; - } - } - - //! Removes first attribute of the node. - //! If node has no attributes, behaviour is undefined. - //! Use first_attribute() to test if node has attributes. - void remove_first_attribute() { - assert(first_attribute()); - xml_attribute *attribute = m_first_attribute; - if (attribute->m_next_attribute) { - attribute->m_next_attribute->m_prev_attribute = 0; - } else m_last_attribute = 0; - attribute->m_parent = 0; - m_first_attribute = attribute->m_next_attribute; - } - - //! Removes last attribute of the node. - //! If node has no attributes, behaviour is undefined. - //! Use first_attribute() to test if node has attributes. - void remove_last_attribute() { - assert(first_attribute()); - xml_attribute *attribute = m_last_attribute; - if (attribute->m_prev_attribute) { - attribute->m_prev_attribute->m_next_attribute = 0; - m_last_attribute = attribute->m_prev_attribute; - } else m_first_attribute = 0; - attribute->m_parent = 0; - } - - //! Removes specified attribute from node. - //! \param where Pointer to attribute to be removed. - void remove_attribute(xml_attribute *where) { - assert(first_attribute() && where->parent() == this); - if (where == m_first_attribute) - remove_first_attribute(); - else if (where == m_last_attribute) - remove_last_attribute(); - else { - where->m_prev_attribute->m_next_attribute = where->m_next_attribute; - where->m_next_attribute->m_prev_attribute = where->m_prev_attribute; - where->m_parent = 0; - } - } - - //! Removes all attributes of node. - void remove_all_attributes() { - for (xml_attribute *attribute = first_attribute(); attribute; - attribute = attribute->m_next_attribute) - attribute->m_parent = 0; - m_first_attribute = 0; - } - -private: - - /////////////////////////////////////////////////////////////////////////// - // Restrictions - - // No copying - xml_node(const xml_node &); - void operator =(const xml_node &); - - /////////////////////////////////////////////////////////////////////////// - // Data members - - // Note that some of the pointers below have UNDEFINED values if certain other pointers are 0. - // This is required for maximum performance, as it allows the parser to omit initialization of - // unneded/redundant values. - // - // The rules are as follows: - // 1. first_node and first_attribute contain valid pointers, or 0 if node has no children/attributes respectively - // 2. last_node and last_attribute are valid only if node has at least one child/attribute respectively, otherwise they contain garbage - // 3. prev_sibling and next_sibling are valid only if node has a parent, otherwise they contain garbage - - node_type m_type; // Type of node; always valid - xml_node *m_first_node; // Pointer to first child node, or 0 if none; always valid - xml_node *m_last_node; // Pointer to last child node, or 0 if none; this value is only valid if m_first_node is non-zero - xml_attribute *m_first_attribute; // Pointer to first attribute of node, or 0 if none; always valid - xml_attribute *m_last_attribute; // Pointer to last attribute of node, or 0 if none; this value is only valid if m_first_attribute is non-zero - xml_node *m_prev_sibling; // Pointer to previous sibling of node, or 0 if none; this value is only valid if m_parent is non-zero - xml_node *m_next_sibling; // Pointer to next sibling of node, or 0 if none; this value is only valid if m_parent is non-zero - -}; - -/////////////////////////////////////////////////////////////////////////// -// XML document - -//! This class represents root of the DOM hierarchy. -//! It is also an xml_node and a memory_pool through public inheritance. -//! Use parse() function to build a DOM tree from a zero-terminated XML text string. -//! parse() function allocates memory for nodes and attributes by using functions of xml_document, -//! which are inherited from memory_pool. -//! To access root node of the document, use the document itself, as if it was an xml_node. -//! \param Ch Character type to use. -template -class xml_document: - public xml_node, public memory_pool { - -public: - - //! Constructs empty XML document - xml_document() : - xml_node(node_document) { - } - - //! Parses zero-terminated XML string according to given flags. - //! Passed string will be modified by the parser, unless rapidxml::parse_non_destructive flag is used. - //! The string must persist for the lifetime of the document. - //! In case of error, rapidxml::parse_error exception will be thrown. - //!

- //! If you want to parse contents of a file, you must first load the file into the memory, and pass pointer to its beginning. - //! Make sure that data is zero-terminated. - //!

- //! Document can be parsed into multiple times. - //! Each new call to parse removes previous nodes and attributes (if any), but does not clear memory pool. - //! \param text XML data to parse; pointer is non-const to denote fact that this data may be modified by the parser. - template - void parse(Ch *text) { - assert(text); - - // Remove current contents - this->remove_all_nodes(); - this->remove_all_attributes(); - - // Parse BOM, if any - parse_bom(text); - - // Parse children - while (1) { - // Skip whitespace before node - skip(text); - if (*text == 0) break; - - // Parse and append new child - if (*text == Ch('<')) { - ++text; // Skip '<' - if (xml_node *node = parse_node(text)) - this->append_node(node); - } else - RAPIDXML_PARSE_ERROR("expected <", text); - } - - } - - //! Clears the document by deleting all nodes and clearing the memory pool. - //! All nodes owned by document pool are destroyed. - void clear() { - this->remove_all_nodes(); - this->remove_all_attributes(); - memory_pool::clear(); - } - -private: - - /////////////////////////////////////////////////////////////////////// - // Internal character utility functions - - // Detect whitespace character - struct whitespace_pred { - static unsigned char test(Ch ch) { - return internal::lookup_tables<0>::lookup_whitespace[static_cast(ch)]; - } - }; - - // Detect node name character - struct node_name_pred { - static unsigned char test(Ch ch) { - return internal::lookup_tables<0>::lookup_node_name[static_cast(ch)]; - } - }; - - // Detect attribute name character - struct attribute_name_pred { - static unsigned char test(Ch ch) { - return internal::lookup_tables<0>::lookup_attribute_name[static_cast(ch)]; - } - }; - - // Detect text character (PCDATA) - struct text_pred { - static unsigned char test(Ch ch) { - return internal::lookup_tables<0>::lookup_text[static_cast(ch)]; - } - }; - - // Detect text character (PCDATA) that does not require processing - struct text_pure_no_ws_pred { - static unsigned char test(Ch ch) { - return internal::lookup_tables<0>::lookup_text_pure_no_ws[static_cast(ch)]; - } - }; - - // Detect text character (PCDATA) that does not require processing - struct text_pure_with_ws_pred { - static unsigned char test(Ch ch) { - return internal::lookup_tables<0>::lookup_text_pure_with_ws[static_cast(ch)]; - } - }; - - // Detect attribute value character - template - struct attribute_value_pred { - static unsigned char test(Ch ch) { - if (Quote == Ch('\'')) - return internal::lookup_tables<0>::lookup_attribute_data_1[static_cast(ch)]; - if (Quote == Ch('\"')) - return internal::lookup_tables<0>::lookup_attribute_data_2[static_cast(ch)]; - return 0; // Should never be executed, to avoid warnings on Comeau - } - }; - - // Detect attribute value character - template - struct attribute_value_pure_pred { - static unsigned char test(Ch ch) { - if (Quote == Ch('\'')) - return internal::lookup_tables<0>::lookup_attribute_data_1_pure[static_cast(ch)]; - if (Quote == Ch('\"')) - return internal::lookup_tables<0>::lookup_attribute_data_2_pure[static_cast(ch)]; - return 0; // Should never be executed, to avoid warnings on Comeau - } - }; - - // Insert coded character, using UTF8 or 8-bit ASCII - template - static void insert_coded_character(Ch *&text, unsigned long code) { - if (Flags & parse_no_utf8) { - // Insert 8-bit ASCII character - // Todo: possibly verify that code is less than 256 and use replacement char otherwise? - text[0] = static_cast(code); - text += 1; - } else { - // Insert UTF8 sequence - if (code < 0x80) // 1 byte sequence - { - text[0] = static_cast(code); - text += 1; - } else if (code < 0x800) // 2 byte sequence - { - text[1] = static_cast((code | 0x80) & 0xBF); - code >>= 6; - text[0] = static_cast(code | 0xC0); - text += 2; - } else if (code < 0x10000) // 3 byte sequence - { - text[2] = static_cast((code | 0x80) & 0xBF); - code >>= 6; - text[1] = static_cast((code | 0x80) & 0xBF); - code >>= 6; - text[0] = static_cast(code | 0xE0); - text += 3; - } else if (code < 0x110000) // 4 byte sequence - { - text[3] = static_cast((code | 0x80) & 0xBF); - code >>= 6; - text[2] = static_cast((code | 0x80) & 0xBF); - code >>= 6; - text[1] = static_cast((code | 0x80) & 0xBF); - code >>= 6; - text[0] = static_cast(code | 0xF0); - text += 4; - } else // Invalid, only codes up to 0x10FFFF are allowed in Unicode - { - RAPIDXML_PARSE_ERROR("invalid numeric character entity", text); - } - } - } - - // Skip characters until predicate evaluates to true - template - static void skip(Ch *&text) { - Ch *tmp = text; - while (StopPred::test(*tmp)) - ++tmp; - text = tmp; - } - - // Skip characters until predicate evaluates to true while doing the following: - // - replacing XML character entity references with proper characters (' & " < > &#...;) - // - condensing whitespace sequences to single space character - template - static Ch *skip_and_expand_character_refs(Ch *&text) { - // If entity translation, whitespace condense and whitespace trimming is disabled, use plain skip - if (Flags & parse_no_entity_translation - && !(Flags & parse_normalize_whitespace) - && !(Flags & parse_trim_whitespace)) { - skip(text); - return text; - } - - // Use simple skip until first modification is detected - skip(text); - - // Use translation skip - Ch *src = text; - Ch *dest = src; - while (StopPred::test(*src)) { - // If entity translation is enabled - if (!(Flags & parse_no_entity_translation)) { - // Test if replacement is needed - if (src[0] == Ch('&')) { - switch (src[1]) { - - // & ' - case Ch('a'): - if (src[2] == Ch('m') && src[3] == Ch('p') && src[4] == Ch(';')) { - *dest = Ch('&'); - ++dest; - src += 5; - continue; - } - if (src[2] == Ch('p') && src[3] == Ch('o') && src[4] == Ch('s') - && src[5] == Ch(';')) { - *dest = Ch('\''); - ++dest; - src += 6; - continue; - } - break; - - // " - case Ch('q'): - if (src[2] == Ch('u') && src[3] == Ch('o') && src[4] == Ch('t') - && src[5] == Ch(';')) { - *dest = Ch('"'); - ++dest; - src += 6; - continue; - } - break; - - // > - case Ch('g'): - if (src[2] == Ch('t') && src[3] == Ch(';')) { - *dest = Ch('>'); - ++dest; - src += 4; - continue; - } - break; - - // < - case Ch('l'): - if (src[2] == Ch('t') && src[3] == Ch(';')) { - *dest = Ch('<'); - ++dest; - src += 4; - continue; - } - break; - - // &#...; - assumes ASCII - case Ch('#'): - if (src[2] == Ch('x')) { - unsigned long code = 0; - src += 3; // Skip &#x - while (1) { - unsigned char digit = - internal::lookup_tables<0>::lookup_digits[static_cast(*src)]; - if (digit == 0xFF) break; - code = code * 16 + digit; - ++src; - } - insert_coded_character(dest, code); // Put character in output - } else { - unsigned long code = 0; - src += 2; // Skip &# - while (1) { - unsigned char digit = - internal::lookup_tables<0>::lookup_digits[static_cast(*src)]; - if (digit == 0xFF) break; - code = code * 10 + digit; - ++src; - } - insert_coded_character(dest, code); // Put character in output - } - if (*src == Ch(';')) - ++src; - else - RAPIDXML_PARSE_ERROR("expected ;", src); - continue; - - // Something else - default: - // Ignore, just copy '&' verbatim - break; - - } - } - } - - // If whitespace condensing is enabled - if (Flags & parse_normalize_whitespace) { - // Test if condensing is needed - if (whitespace_pred::test(*src)) { - *dest = Ch(' '); - ++dest; // Put single space in dest - ++src; // Skip first whitespace char - // Skip remaining whitespace chars - while (whitespace_pred::test(*src)) - ++src; - continue; - } - } - - // No replacement, only copy character - *dest++ = *src++; - - } - - // Return new end - text = src; - return dest; - - } - - /////////////////////////////////////////////////////////////////////// - // Internal parsing functions - - // Parse BOM, if any - template - void parse_bom(Ch *&text) { - // UTF-8? - if (static_cast(text[0]) == 0xEF - && static_cast(text[1]) == 0xBB - && static_cast(text[2]) == 0xBF) { - text += 3; // Skup utf-8 bom - } - } - - // Parse XML declaration ( - xml_node *parse_xml_declaration(Ch *&text) { - // If parsing of declaration is disabled - if (!(Flags & parse_declaration_node)) { - // Skip until end of declaration - while (text[0] != Ch('?') || text[1] != Ch('>')) { - if (!text[0]) - RAPIDXML_PARSE_ERROR("unexpected end of data", text); - ++text; - } - text += 2; // Skip '?>' - return 0; - } - - // Create declaration - xml_node *declaration = this->allocate_node(node_declaration); - - // Skip whitespace before attributes or ?> - skip(text); - - // Parse declaration attributes - parse_node_attributes(text, declaration); - - // Skip ?> - if (text[0] != Ch('?') || text[1] != Ch('>')) - RAPIDXML_PARSE_ERROR("expected ?>", text); - text += 2; - - return declaration; - } - - // Parse XML comment (' - return 0; // Do not produce comment node - } - - // Remember value start - Ch *value = text; - - // Skip until end of comment - while (text[0] != Ch('-') || text[1] != Ch('-') || text[2] != Ch('>')) { - if (!text[0]) - RAPIDXML_PARSE_ERROR("unexpected end of data", text); - ++text; - } - - // Create comment node - xml_node *comment = this->allocate_node(node_comment); - comment->value(value, text - value); - - // Place zero terminator after comment value - if (!(Flags & parse_no_string_terminators)) *text = Ch('\0'); - - text += 3; // Skip '-->' - return comment; - } - - // Parse DOCTYPE - template - xml_node *parse_doctype(Ch *&text) { - // Remember value start - Ch *value = text; - - // Skip to > - while (*text != Ch('>')) { - // Determine character type - switch (*text) { - - // If '[' encountered, scan for matching ending ']' using naive algorithm with depth - // This works for all W3C test files except for 2 most wicked - case Ch('['): { - ++text; // Skip '[' - int depth = 1; - while (depth > 0) { - switch (*text) { - case Ch('['): - ++depth; - break; - case Ch(']'): - --depth; - break; - case 0: - RAPIDXML_PARSE_ERROR("unexpected end of data", text); - } - ++text; - } - break; - } - - // Error on end of text - case Ch('\0'): - RAPIDXML_PARSE_ERROR("unexpected end of data", text); - - // Other character, skip it - default: - ++text; - - } - } - - // If DOCTYPE nodes enabled - if (Flags & parse_doctype_node) { - // Create a new doctype node - xml_node *doctype = this->allocate_node(node_doctype); - doctype->value(value, text - value); - - // Place zero terminator after value - if (!(Flags & parse_no_string_terminators)) *text = Ch('\0'); - - text += 1; // skip '>' - return doctype; - } else { - text += 1; // skip '>' - return 0; - } - - } - - // Parse PI - template - xml_node *parse_pi(Ch *&text) { - // If creation of PI nodes is enabled - if (Flags & parse_pi_nodes) { - // Create pi node - xml_node *pi = this->allocate_node(node_pi); - - // Extract PI target name - Ch *name = text; - skip(text); - if (text == name) - RAPIDXML_PARSE_ERROR("expected PI target", text); - pi->name(name, text - name); - - // Skip whitespace between pi target and pi - skip(text); - - // Remember start of pi - Ch *value = text; - - // Skip to '?>' - while (text[0] != Ch('?') || text[1] != Ch('>')) { - if (*text == Ch('\0')) - RAPIDXML_PARSE_ERROR("unexpected end of data", text); - ++text; - } - - // Set pi value (verbatim, no entity expansion or whitespace normalization) - pi->value(value, text - value); - - // Place zero terminator after name and value - if (!(Flags & parse_no_string_terminators)) { - pi->name()[pi->name_size()] = Ch('\0'); - pi->value()[pi->value_size()] = Ch('\0'); - } - - text += 2; // Skip '?>' - return pi; - } else { - // Skip to '?>' - while (text[0] != Ch('?') || text[1] != Ch('>')) { - if (*text == Ch('\0')) - RAPIDXML_PARSE_ERROR("unexpected end of data", text); - ++text; - } - text += 2; // Skip '?>' - return 0; - } - } - - // Parse and append data - // Return character that ends data. - // This is necessary because this character might have been overwritten by a terminating 0 - template - Ch parse_and_append_data(xml_node *node, Ch *&text, Ch *contents_start) { - // Backup to contents start if whitespace trimming is disabled - if (!(Flags & parse_trim_whitespace)) text = contents_start; - - // Skip until end of data - Ch *value = text, *end; - if (Flags & parse_normalize_whitespace) - end = skip_and_expand_character_refs(text); - else end = skip_and_expand_character_refs(text); - - // Trim trailing whitespace if flag is set; leading was already trimmed by whitespace skip after > - if (Flags & parse_trim_whitespace) { - if (Flags & parse_normalize_whitespace) { - // Whitespace is already condensed to single space characters by skipping function, so just trim 1 char off the end - if (*(end - 1) == Ch(' ')) --end; - } else { - // Backup until non-whitespace character is found - while (whitespace_pred::test(*(end - 1))) - --end; - } - } - - // If characters are still left between end and value (this test is only necessary if normalization is enabled) - // Create new data node - if (!(Flags & parse_no_data_nodes)) { - xml_node *data = this->allocate_node(node_data); - data->value(value, end - value); - node->append_node(data); - } - - // Add data to parent node if no data exists yet - if (!(Flags & parse_no_element_values)) - if (*node->value() == Ch('\0')) node->value(value, end - value); - - // Place zero terminator after value - if (!(Flags & parse_no_string_terminators)) { - Ch ch = *text; - *end = Ch('\0'); - return ch; // Return character that ends data; this is required because zero terminator overwritten it - } - - // Return character that ends data - return *text; - } - - // Parse CDATA - template - xml_node *parse_cdata(Ch *&text) { - // If CDATA is disabled - if (Flags & parse_no_data_nodes) { - // Skip until end of cdata - while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>')) { - if (!text[0]) - RAPIDXML_PARSE_ERROR("unexpected end of data", text); - ++text; - } - text += 3; // Skip ]]> - return 0; // Do not produce CDATA node - } - - // Skip until end of cdata - Ch *value = text; - while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>')) { - if (!text[0]) - RAPIDXML_PARSE_ERROR("unexpected end of data", text); - ++text; - } - - // Create new cdata node - xml_node *cdata = this->allocate_node(node_cdata); - cdata->value(value, text - value); - - // Place zero terminator after value - if (!(Flags & parse_no_string_terminators)) *text = Ch('\0'); - - text += 3; // Skip ]]> - return cdata; - } - - // Parse element node - template - xml_node *parse_element(Ch *&text) { - // Create element node - xml_node *element = this->allocate_node(node_element); - - // Extract element name - Ch *name = text; - skip(text); - if (text == name) - RAPIDXML_PARSE_ERROR("expected element name", text); - element->name(name, text - name); - - // Skip whitespace between element name and attributes or > - skip(text); - - // Parse attributes, if any - parse_node_attributes(text, element); - - // Determine ending type - if (*text == Ch('>')) { - ++text; - parse_node_contents(text, element); - } else if (*text == Ch('/')) { - ++text; - if (*text != Ch('>')) - RAPIDXML_PARSE_ERROR("expected >", text); - ++text; - } else - RAPIDXML_PARSE_ERROR("expected >", text); - - // Place zero terminator after name - if (!(Flags & parse_no_string_terminators)) - element->name()[element->name_size()] = Ch('\0'); - - // Return parsed element - return element; - } - - // Determine node type, and parse it - template - xml_node *parse_node(Ch *&text) { - // Parse proper node type - switch (text[0]) { - - // <... - default: - // Parse and append element node - return parse_element(text); - - // (text); - } else { - // Parse PI - return parse_pi(text); - } - - // (text); - } - break; - - // (text); - } - break; - - // (text); - } - - } // switch - - // Attempt to skip other, unrecognized node types starting with ')) { - if (*text == 0) - RAPIDXML_PARSE_ERROR("unexpected end of data", text); - ++text; - } - ++text; // Skip '>' - return 0; // No node recognized - - } - } - - // Parse contents of the node - children, data etc. - template - void parse_node_contents(Ch *&text, xml_node *node) { - // For all children and text - while (1) { - // Skip whitespace between > and node contents - Ch *contents_start = text; // Store start of node contents before whitespace is skipped - skip(text); - Ch next_char = *text; - - // After data nodes, instead of continuing the loop, control jumps here. - // This is because zero termination inside parse_and_append_data() function - // would wreak havoc with the above code. - // Also, skipping whitespace after data nodes is unnecessary. - after_data_node: - - // Determine what comes next: node closing, child node, data node, or 0? - switch (next_char) { - - // Node closing or child node - case Ch('<'): - if (text[1] == Ch('/')) { - // Node closing - text += 2; // Skip '(text); - if (!internal::compare(node->name(), node->name_size(), - closing_name, text - closing_name, true)) - RAPIDXML_PARSE_ERROR("invalid closing tag name", text); - } else { - // No validation, just skip name - skip(text); - } - // Skip remaining whitespace after node name - skip(text); - if (*text != Ch('>')) - RAPIDXML_PARSE_ERROR("expected >", text); - ++text; // Skip '>' - return; // Node closed, finished parsing contents - } else { - // Child node - ++text; // Skip '<' - if (xml_node *child = parse_node(text)) - node->append_node(child); - } - break; - - // End of data - error - case Ch('\0'): - RAPIDXML_PARSE_ERROR("unexpected end of data", text); - - // Data node - default: - next_char = parse_and_append_data(node, text, contents_start); - goto after_data_node; - // Bypass regular processing after data nodes - - } - } - } - - // Parse XML attributes of the node - template - void parse_node_attributes(Ch *&text, xml_node *node) { - // For all attributes - while (attribute_name_pred::test(*text)) { - // Extract attribute name - Ch *name = text; - ++text; // Skip first character of attribute name - skip(text); - if (text == name) - RAPIDXML_PARSE_ERROR("expected attribute name", name); - - // Create new attribute - xml_attribute *attribute = this->allocate_attribute(); - attribute->name(name, text - name); - node->append_attribute(attribute); - - // Skip whitespace after attribute name - skip(text); - - // Skip = - if (*text != Ch('=')) - RAPIDXML_PARSE_ERROR("expected =", text); - ++text; - - // Add terminating zero after name - if (!(Flags & parse_no_string_terminators)) - attribute->name()[attribute->name_size()] = 0; - - // Skip whitespace after = - skip(text); - - // Skip quote and remember if it was ' or " - Ch quote = *text; - if (quote != Ch('\'') && quote != Ch('"')) - RAPIDXML_PARSE_ERROR("expected ' or \"", text); - ++text; - - // Extract attribute value and expand char refs in it - Ch *value = text, *end; - const int AttFlags = Flags & ~parse_normalize_whitespace; // No whitespace normalization in attributes - if (quote == Ch('\'')) - end = skip_and_expand_character_refs, - attribute_value_pure_pred, AttFlags>(text); - else end = skip_and_expand_character_refs, - attribute_value_pure_pred, AttFlags>(text); - - // Set attribute value - attribute->value(value, end - value); - - // Make sure that end quote is present - if (*text != quote) - RAPIDXML_PARSE_ERROR("expected ' or \"", text); - ++text; // Skip quote - - // Add terminating zero after value - if (!(Flags & parse_no_string_terminators)) - attribute->value()[attribute->value_size()] = 0; - - // Skip whitespace after attribute value - skip(text); - } - } - -}; - -//! \cond internal -namespace internal { - -// Whitespace (space \n \r \t) -template -const unsigned char lookup_tables::lookup_whitespace[256] = { -// 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, // 0 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1 - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 5 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 7 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // C - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // D - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // E - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // F - }; - -// Node name (anything but space \n \r \t / > ? \0) -template -const unsigned char lookup_tables::lookup_node_name[256] = { -// 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 2 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, // 3 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F - }; - -// Text (i.e. PCDATA) (anything but < \0) -template -const unsigned char lookup_tables::lookup_text[256] = { -// 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F - }; - -// Text (i.e. PCDATA) that does not require processing when ws normalization is disabled -// (anything but < \0 &) -template -const unsigned char lookup_tables::lookup_text_pure_no_ws[256] = { -// 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 - 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F - }; - -// Text (i.e. PCDATA) that does not require processing when ws normalizationis is enabled -// (anything but < \0 & space \n \r \t) -template -const unsigned char lookup_tables::lookup_text_pure_with_ws[256] = { -// 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 - 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F - }; - -// Attribute name (anything but space \n \r \t / < > = ? ! \0) -template -const unsigned char lookup_tables::lookup_attribute_name[256] = { -// 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 - 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 2 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, // 3 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F - }; - -// Attribute data with single quote (anything but ' \0) -template -const unsigned char lookup_tables::lookup_attribute_data_1[256] = { -// 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 - 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, // 2 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F - }; - -// Attribute data with single quote that does not require processing (anything but ' \0 &) -template -const unsigned char lookup_tables::lookup_attribute_data_1_pure[256] = { -// 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 - 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, // 2 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F - }; - -// Attribute data with double quote (anything but " \0) -template -const unsigned char lookup_tables::lookup_attribute_data_2[256] = { -// 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 - 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F - }; - -// Attribute data with double quote that does not require processing (anything but " \0 &) -template -const unsigned char lookup_tables::lookup_attribute_data_2_pure[256] = { -// 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 - 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F - }; - -// Digits (dec and hex, 255 denotes end of numeric character reference) -template -const unsigned char lookup_tables::lookup_digits[256] = { - // 0 1 2 3 4 5 6 7 8 9 A B C D E F - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, // 0 - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, // 1 - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, // 2 - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, - 255, // 3 - 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, - 255, // 4 - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, // 5 - 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, - 255, // 6 - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, // 7 - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, // 8 - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, // 9 - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, // A - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, // B - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, // C - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, // D - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, // E - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255 // F - }; - -// Upper case conversion -template -const unsigned char lookup_tables::lookup_upcase[256] = { - // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A B C D E F - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, // 0 - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 31, // 1 - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, - 47, // 2 - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, - 63, // 3 - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, - 79, // 4 - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, - 95, // 5 - 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, - 79, // 6 - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123, 124, 125, 126, - 127, // 7 - 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, - 143, // 8 - 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, - 159, // 9 - 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, - 175, // A - 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, - 191, // B - 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, - 207, // C - 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, - 223, // D - 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, - 239, // E - 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, - 255 // F - }; -} -//! \endcond - -} - -// Undefine internal macros -#undef RAPIDXML_PARSE_ERROR - -// On MSVC, restore warnings state -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#endif diff --git a/TEEStub/PropertyAccess/rapidxml/rapidxml_iterators.hpp b/TEEStub/PropertyAccess/rapidxml/rapidxml_iterators.hpp deleted file mode 100644 index 379dcf7..0000000 --- a/TEEStub/PropertyAccess/rapidxml/rapidxml_iterators.hpp +++ /dev/null @@ -1,151 +0,0 @@ -#ifndef RAPIDXML_ITERATORS_HPP_INCLUDED -#define RAPIDXML_ITERATORS_HPP_INCLUDED - -// Copyright (C) 2006, 2009 Marcin Kalicinski -// Version 1.13 -// Revision $DateTime: 2009/05/13 01:46:17 $ -//! \file rapidxml_iterators.hpp This file contains rapidxml iterators - -#include "rapidxml.hpp" - -namespace rapidxml { - -//! Iterator of child nodes of xml_node -template -class node_iterator { - -public: - - typedef typename xml_node value_type; - typedef typename xml_node &reference; - typedef typename xml_node *pointer; - typedef std::ptrdiff_t difference_type; - typedef std::bidirectional_iterator_tag iterator_category; - - node_iterator() : - m_node(0) { - } - - node_iterator(xml_node *node) : - m_node(node->first_node()) { - } - - reference operator *() const { - assert(m_node); - return *m_node; - } - - pointer operator->() const { - assert(m_node); - return m_node; - } - - node_iterator& operator++() { - assert(m_node); - m_node = m_node->next_sibling(); - return *this; - } - - node_iterator operator++(int) { - node_iterator tmp = *this; - ++this; - return tmp; - } - - node_iterator& operator--() { - assert(m_node && m_node->previous_sibling()); - m_node = m_node->previous_sibling(); - return *this; - } - - node_iterator operator--(int) { - node_iterator tmp = *this; - ++this; - return tmp; - } - - bool operator ==(const node_iterator &rhs) { - return m_node == rhs.m_node; - } - - bool operator !=(const node_iterator &rhs) { - return m_node != rhs.m_node; - } - -private: - - xml_node *m_node; - -}; - -//! Iterator of child attributes of xml_node -template -class attribute_iterator { - -public: - - typedef typename xml_attribute value_type; - typedef typename xml_attribute &reference; - typedef typename xml_attribute *pointer; - typedef std::ptrdiff_t difference_type; - typedef std::bidirectional_iterator_tag iterator_category; - - attribute_iterator() : - m_attribute(0) { - } - - attribute_iterator(xml_node *node) : - m_attribute(node->first_attribute()) { - } - - reference operator *() const { - assert(m_attribute); - return *m_attribute; - } - - pointer operator->() const { - assert(m_attribute); - return m_attribute; - } - - attribute_iterator& operator++() { - assert(m_attribute); - m_attribute = m_attribute->next_attribute(); - return *this; - } - - attribute_iterator operator++(int) { - attribute_iterator tmp = *this; - ++this; - return tmp; - } - - attribute_iterator& operator--() { - assert(m_attribute && m_attribute->previous_attribute()); - m_attribute = m_attribute->previous_attribute(); - return *this; - } - - attribute_iterator operator--(int) { - attribute_iterator tmp = *this; - ++this; - return tmp; - } - - bool operator ==(const attribute_iterator &rhs) { - return m_attribute == rhs.m_attribute; - } - - bool operator !=(const attribute_iterator &rhs) { - return m_attribute != rhs.m_attribute; - } - -private: - - xml_attribute *m_attribute; - -}; - -} - -#endif diff --git a/TEEStub/PropertyAccess/rapidxml/rapidxml_print.hpp b/TEEStub/PropertyAccess/rapidxml/rapidxml_print.hpp deleted file mode 100644 index 8a627e5..0000000 --- a/TEEStub/PropertyAccess/rapidxml/rapidxml_print.hpp +++ /dev/null @@ -1,426 +0,0 @@ -#ifndef RAPIDXML_PRINT_HPP_INCLUDED -#define RAPIDXML_PRINT_HPP_INCLUDED - -// Copyright (C) 2006, 2009 Marcin Kalicinski -// Version 1.13 -// Revision $DateTime: 2009/05/13 01:46:17 $ -//! \file rapidxml_print.hpp This file contains rapidxml printer implementation - -#include "rapidxml.hpp" - -// Only include streams if not disabled -#ifndef RAPIDXML_NO_STREAMS -#include -#include -#endif - -namespace rapidxml { - -/////////////////////////////////////////////////////////////////////// -// Printing flags - -const int print_no_indenting = 0x1; //!< Printer flag instructing the printer to suppress indenting of XML. See print() function. - -/////////////////////////////////////////////////////////////////////// -// Internal - -//! \cond internal -namespace internal { - -/////////////////////////////////////////////////////////////////////////// -// Internal character operations - -// Copy characters from given range to given output iterator -template -inline OutIt copy_chars(const Ch *begin, const Ch *end, OutIt out) { - while (begin != end) - *out++ = *begin++; - return out; -} - -// Copy characters from given range to given output iterator and expand -// characters into references (< > ' " &) -template -inline OutIt copy_and_expand_chars(const Ch *begin, const Ch *end, Ch noexpand, - OutIt out) { - while (begin != end) { - if (*begin == noexpand) { - *out++ = *begin; // No expansion, copy character - } else { - switch (*begin) { - case Ch('<'): - *out++ = Ch('&'); - *out++ = Ch('l'); - *out++ = Ch('t'); - *out++ = Ch(';'); - break; - case Ch('>'): - *out++ = Ch('&'); - *out++ = Ch('g'); - *out++ = Ch('t'); - *out++ = Ch(';'); - break; - case Ch('\''): - *out++ = Ch('&'); - *out++ = Ch('a'); - *out++ = Ch('p'); - *out++ = Ch('o'); - *out++ = Ch('s'); - *out++ = Ch(';'); - break; - case Ch('"'): - *out++ = Ch('&'); - *out++ = Ch('q'); - *out++ = Ch('u'); - *out++ = Ch('o'); - *out++ = Ch('t'); - *out++ = Ch(';'); - break; - case Ch('&'): - *out++ = Ch('&'); - *out++ = Ch('a'); - *out++ = Ch('m'); - *out++ = Ch('p'); - *out++ = Ch(';'); - break; - default: - *out++ = *begin; // No expansion, copy character - } - } - ++begin; // Step to next character - } - return out; -} - -// Fill given output iterator with repetitions of the same character -template -inline OutIt fill_chars(OutIt out, int n, Ch ch) { - for (int i = 0; i < n; ++i) - *out++ = ch; - return out; -} - -// Find character -template -inline bool find_char(const Ch *begin, const Ch *end) { - while (begin != end) - if (*begin++ == ch) return true; - return false; -} - -/////////////////////////////////////////////////////////////////////////// -// Internal printing operations - -// Print node -template -inline OutIt print_node(OutIt out, const xml_node *node, int flags, - int indent) { - // Print proper node type - switch (node->type()) { - - // Document - case node_document: - out = print_children(out, node, flags, indent); - break; - - // Element - case node_element: - out = print_element_node(out, node, flags, indent); - break; - - // Data - case node_data: - out = print_data_node(out, node, flags, indent); - break; - - // CDATA - case node_cdata: - out = print_cdata_node(out, node, flags, indent); - break; - - // Declaration - case node_declaration: - out = print_declaration_node(out, node, flags, indent); - break; - - // Comment - case node_comment: - out = print_comment_node(out, node, flags, indent); - break; - - // Doctype - case node_doctype: - out = print_doctype_node(out, node, flags, indent); - break; - - // Pi - case node_pi: - out = print_pi_node(out, node, flags, indent); - break; - - // Unknown - default: - assert(0); - break; - } - - // If indenting not disabled, add line break after node - if (!(flags & print_no_indenting)) *out = Ch('\n'), ++out; - - // Return modified iterator - return out; -} - -// Print children of the node -template -inline OutIt print_children(OutIt out, const xml_node *node, int flags, - int indent) { - for (xml_node *child = node->first_node(); child; - child = child->next_sibling()) - out = print_node(out, child, flags, indent); - return out; -} - -// Print attributes of the node -template -inline OutIt print_attributes(OutIt out, const xml_node *node, int flags) { - for (xml_attribute *attribute = node->first_attribute(); attribute; - attribute = attribute->next_attribute()) { - if (attribute->name() && attribute->value()) { - // Print attribute name - *out = Ch(' '), ++out; - out = copy_chars(attribute->name(), - attribute->name() + attribute->name_size(), out); - *out = Ch('='), ++out; - // Print attribute value using appropriate quote type - if (find_char(attribute->value(), - attribute->value() + attribute->value_size())) { - *out = Ch('\''), ++out; - out = copy_and_expand_chars(attribute->value(), - attribute->value() + attribute->value_size(), Ch('"'), out); - *out = Ch('\''), ++out; - } else { - *out = Ch('"'), ++out; - out = copy_and_expand_chars(attribute->value(), - attribute->value() + attribute->value_size(), Ch('\''), out); - *out = Ch('"'), ++out; - } - } - } - return out; -} - -// Print data node -template -inline OutIt print_data_node(OutIt out, const xml_node *node, int flags, - int indent) { - assert(node->type() == node_data); - if (!(flags & print_no_indenting)) out = fill_chars(out, indent, Ch('\t')); - out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), - Ch(0), out); - return out; -} - -// Print data node -template -inline OutIt print_cdata_node(OutIt out, const xml_node *node, int flags, - int indent) { - assert(node->type() == node_cdata); - if (!(flags & print_no_indenting)) out = fill_chars(out, indent, Ch('\t')); - *out = Ch('<'); - ++out; - *out = Ch('!'); - ++out; - *out = Ch('['); - ++out; - *out = Ch('C'); - ++out; - *out = Ch('D'); - ++out; - *out = Ch('A'); - ++out; - *out = Ch('T'); - ++out; - *out = Ch('A'); - ++out; - *out = Ch('['); - ++out; - out = copy_chars(node->value(), node->value() + node->value_size(), out); - *out = Ch(']'); - ++out; - *out = Ch(']'); - ++out; - *out = Ch('>'); - ++out; - return out; -} - -// Print element node -template -inline OutIt print_element_node(OutIt out, const xml_node *node, int flags, - int indent) { - assert(node->type() == node_element); - - // Print element name and attributes, if any - if (!(flags & print_no_indenting)) out = fill_chars(out, indent, Ch('\t')); - *out = Ch('<'), ++out; - out = copy_chars(node->name(), node->name() + node->name_size(), out); - out = print_attributes(out, node, flags); - - // If node is childless - if (node->value_size() == 0 && !node->first_node()) { - // Print childless node tag ending - *out = Ch('/'), ++out; - *out = Ch('>'), ++out; - } else { - // Print normal node tag ending - *out = Ch('>'), ++out; - - // Test if node contains a single data node only (and no other nodes) - xml_node *child = node->first_node(); - if (!child) { - // If node has no children, only print its value without indenting - out = copy_and_expand_chars(node->value(), - node->value() + node->value_size(), Ch(0), out); - } else if (child->next_sibling() == 0 && child->type() == node_data) { - // If node has a sole data child, only print its value without indenting - out = copy_and_expand_chars(child->value(), - child->value() + child->value_size(), Ch(0), out); - } else { - // Print all children with full indenting - if (!(flags & print_no_indenting)) *out = Ch('\n'), ++out; - out = print_children(out, node, flags, indent + 1); - if (!(flags & print_no_indenting)) - out = fill_chars(out, indent, Ch('\t')); - } - - // Print node end - *out = Ch('<'), ++out; - *out = Ch('/'), ++out; - out = copy_chars(node->name(), node->name() + node->name_size(), out); - *out = Ch('>'), ++out; - } - return out; -} - -// Print declaration node -template -inline OutIt print_declaration_node(OutIt out, const xml_node *node, - int flags, int indent) { - // Print declaration start - if (!(flags & print_no_indenting)) out = fill_chars(out, indent, Ch('\t')); - *out = Ch('<'), ++out; - *out = Ch('?'), ++out; - *out = Ch('x'), ++out; - *out = Ch('m'), ++out; - *out = Ch('l'), ++out; - - // Print attributes - out = print_attributes(out, node, flags); - - // Print declaration end - *out = Ch('?'), ++out; - *out = Ch('>'), ++out; - - return out; -} - -// Print comment node -template -inline OutIt print_comment_node(OutIt out, const xml_node *node, int flags, - int indent) { - assert(node->type() == node_comment); - if (!(flags & print_no_indenting)) out = fill_chars(out, indent, Ch('\t')); - *out = Ch('<'), ++out; - *out = Ch('!'), ++out; - *out = Ch('-'), ++out; - *out = Ch('-'), ++out; - out = copy_chars(node->value(), node->value() + node->value_size(), out); - *out = Ch('-'), ++out; - *out = Ch('-'), ++out; - *out = Ch('>'), ++out; - return out; -} - -// Print doctype node -template -inline OutIt print_doctype_node(OutIt out, const xml_node *node, int flags, - int indent) { - assert(node->type() == node_doctype); - if (!(flags & print_no_indenting)) out = fill_chars(out, indent, Ch('\t')); - *out = Ch('<'), ++out; - *out = Ch('!'), ++out; - *out = Ch('D'), ++out; - *out = Ch('O'), ++out; - *out = Ch('C'), ++out; - *out = Ch('T'), ++out; - *out = Ch('Y'), ++out; - *out = Ch('P'), ++out; - *out = Ch('E'), ++out; - *out = Ch(' '), ++out; - out = copy_chars(node->value(), node->value() + node->value_size(), out); - *out = Ch('>'), ++out; - return out; -} - -// Print pi node -template -inline OutIt print_pi_node(OutIt out, const xml_node *node, int flags, - int indent) { - assert(node->type() == node_pi); - if (!(flags & print_no_indenting)) out = fill_chars(out, indent, Ch('\t')); - *out = Ch('<'), ++out; - *out = Ch('?'), ++out; - out = copy_chars(node->name(), node->name() + node->name_size(), out); - *out = Ch(' '), ++out; - out = copy_chars(node->value(), node->value() + node->value_size(), out); - *out = Ch('?'), ++out; - *out = Ch('>'), ++out; - return out; -} - -} -//! \endcond - -/////////////////////////////////////////////////////////////////////////// -// Printing - -//! Prints XML to given output iterator. -//! \param out Output iterator to print to. -//! \param node Node to be printed. Pass xml_document to print entire document. -//! \param flags Flags controlling how XML is printed. -//! \return Output iterator pointing to position immediately after last character of printed text. -template -inline OutIt print(OutIt out, const xml_node &node, int flags = 0) { - return internal::print_node(out, &node, flags, 0); -} - -#ifndef RAPIDXML_NO_STREAMS - -//! Prints XML to given output stream. -//! \param out Output stream to print to. -//! \param node Node to be printed. Pass xml_document to print entire document. -//! \param flags Flags controlling how XML is printed. -//! \return Output stream. -template -inline std::basic_ostream &print(std::basic_ostream &out, - const xml_node &node, int flags = 0) { - print(std::ostream_iterator < Ch > (out), node, flags); - return out; -} - -//! Prints formatted XML to given output stream. Uses default printing flags. Use print() function to customize printing process. -//! \param out Output stream to print to. -//! \param node Node to be printed. -//! \return Output stream. -template -inline std::basic_ostream &operator <<(std::basic_ostream &out, - const xml_node &node) { - return print(out, node); -} - -#endif - -} - -#endif diff --git a/TEEStub/PropertyAccess/rapidxml/rapidxml_utils.hpp b/TEEStub/PropertyAccess/rapidxml/rapidxml_utils.hpp deleted file mode 100644 index c95e1e5..0000000 --- a/TEEStub/PropertyAccess/rapidxml/rapidxml_utils.hpp +++ /dev/null @@ -1,111 +0,0 @@ -#ifndef RAPIDXML_UTILS_HPP_INCLUDED -#define RAPIDXML_UTILS_HPP_INCLUDED - -// Copyright (C) 2006, 2009 Marcin Kalicinski -// Version 1.13 -// Revision $DateTime: 2009/05/13 01:46:17 $ -//! \file rapidxml_utils.hpp This file contains high-level rapidxml utilities that can be useful -//! in certain simple scenarios. They should probably not be used if maximizing performance is the main objective. - -#include "rapidxml.hpp" -#include -#include -#include -#include - -namespace rapidxml { - -//! Represents data loaded from a file -template -class file { - -public: - - //! Loads file into the memory. Data will be automatically destroyed by the destructor. - //! \param filename Filename to load. - file(const char *filename) { - using namespace std; - - // Open stream - basic_ifstream stream(filename, ios::binary); - if (!stream) throw runtime_error(string("cannot open file ") + filename); - stream.unsetf(ios::skipws); - - // Determine stream size - stream.seekg(0, ios::end); - size_t size = stream.tellg(); - stream.seekg(0); - - // Load data and add terminating 0 - m_data.resize(size + 1); - stream.read(&m_data.front(), static_cast(size)); - m_data[size] = 0; - } - - //! Loads file into the memory. Data will be automatically destroyed by the destructor - //! \param stream Stream to load from - file(std::basic_istream &stream) { - using namespace std; - - // Load data and add terminating 0 - stream.unsetf(ios::skipws); - m_data.assign(istreambuf_iterator < Ch > (stream), - istreambuf_iterator()); - if (stream.fail() || stream.bad()) - throw runtime_error("error reading stream"); - m_data.push_back(0); - } - - //! Gets file data. - //! \return Pointer to data of file. - Ch *data() { - return &m_data.front(); - } - - //! Gets file data. - //! \return Pointer to data of file. - const Ch *data() const { - return &m_data.front(); - } - - //! Gets file data size. - //! \return Size of file data, in characters. - std::size_t size() const { - return m_data.size(); - } - -private: - - std::vector m_data; // File data - -}; - -//! Counts children of node. Time complexity is O(n). -//! \return Number of children of node -template -inline std::size_t count_children(xml_node *node) { - xml_node *child = node->first_node(); - std::size_t count = 0; - while (child) { - ++count; - child = child->next_sibling(); - } - return count; -} - -//! Counts attributes of node. Time complexity is O(n). -//! \return Number of attributes of node -template -inline std::size_t count_attributes(xml_node *node) { - xml_attribute *attr = node->first_attribute(); - std::size_t count = 0; - while (attr) { - ++count; - attr = attr->next_attribute(); - } - return count; -} - -} - -#endif diff --git a/include/include/LICENSE b/include/include/LICENSE new file mode 100644 index 0000000..76c5d00 --- /dev/null +++ b/include/include/LICENSE @@ -0,0 +1,27 @@ +Unless it has its own copyright/license embedded in its body, each source file +is subject to the following license terms: + +Copyright (c) 2015, Linaro Limited +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/include/include/tee_internal_api.h b/include/include/tee_internal_api.h index 9456e2e..976c665 100644 --- a/include/include/tee_internal_api.h +++ b/include/include/tee_internal_api.h @@ -1,3 +1,30 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + /** * Copyright (c) 2011-2017 Samsung Electronics Co., Ltd All Rights Reserved * diff --git a/packaging/tef-simulator-helloworld.spec b/packaging/tef-simulator-helloworld.spec index e4a8b4a..6f1d9a5 100644 --- a/packaging/tef-simulator-helloworld.spec +++ b/packaging/tef-simulator-helloworld.spec @@ -3,7 +3,7 @@ Summary: Hello World application for TEF TrustZone simulator Version: 0.0.1 Release: 1 Group: Security -License: Apache-2.0 and BSD-3-Clause +License: Apache-2.0 Source0: %{name}-%{version}.tar.gz ExcludeArch: armv6l armv7hl armv7l aarch64 BuildRequires: cmake @@ -49,5 +49,6 @@ make install %postun %files -n %{name} +%license LICENSE %attr(111,security_fw,security_fw) %{bin_dir}/tef-simulator-helloworld %attr(444,security_fw,security_fw) %{tastore_dir}/00000000000000000000112233445566 diff --git a/packaging/tef-simulator.spec b/packaging/tef-simulator.spec index 81f67c7..dc363d8 100644 --- a/packaging/tef-simulator.spec +++ b/packaging/tef-simulator.spec @@ -3,7 +3,7 @@ Summary: TEF TrustZone simulator and it's utilities Version: 0.0.1 Release: 1 Group: Security -License: Apache-2.0 +License: Apache-2.0 and MIT and BSD Source0: %{name}-%{version}.tar.gz Source1: %{name}.manifest ExcludeArch: armv6l armv7hl armv7l aarch64 @@ -91,6 +91,8 @@ make %{?jobs:-j%jobs} %install make install +cp rapidxml/license.txt LICENSE.MIT +cp include/include/LICENSE LICENSE.BSD %pre @@ -107,6 +109,8 @@ if [ $1 = 0 ] ; then fi %files -n %{name} +%license LICENSE +%license LICENSE.MIT %manifest tef-simulator.manifest %attr(111,security_fw,security_fw) %{bin_dir}/tef-simulator-daemon %{lib_dir}/libtef-simulator-ssflib.so @@ -116,6 +120,9 @@ fi %attr(755,security_fw,security_fw) %{lib_dir}/tef/simulator/libteec.so %files -n %{name}-devkit +%license LICENSE +%license LICENSE.MIT +%license LICENSE.BSD %{bin_dir}/TA_PackageBuilder.sh %{bin_dir}/TAPackageMaker %{lib_dir}/libTEEStub.a diff --git a/rapidxml/license.txt b/rapidxml/license.txt new file mode 100644 index 0000000..41ea486 --- /dev/null +++ b/rapidxml/license.txt @@ -0,0 +1,19 @@ +Copyright (c) 2006, 2007 Marcin Kalicinski + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. \ No newline at end of file diff --git a/simulatordaemon/src/TABinaryManager/rapidxml/rapidxml.hpp b/rapidxml/rapidxml.hpp similarity index 99% rename from simulatordaemon/src/TABinaryManager/rapidxml/rapidxml.hpp rename to rapidxml/rapidxml.hpp index 0cb3162..bc428f4 100644 --- a/simulatordaemon/src/TABinaryManager/rapidxml/rapidxml.hpp +++ b/rapidxml/rapidxml.hpp @@ -39,7 +39,7 @@ namespace rapidxml //!
 	//! void %rapidxml::%parse_error_handler(const char *what, void *where)
 	//! {
-	//!     LOGD(SIM_DAEMON, "Parse error: %s", what);
+	//!     std::cout << "Parse error: " << what << "\n";
 	//!     std::abort();
 	//! }
 	//! 
diff --git a/simulatordaemon/src/TABinaryManager/rapidxml/rapidxml_iterators.hpp b/rapidxml/rapidxml_iterators.hpp similarity index 100% rename from simulatordaemon/src/TABinaryManager/rapidxml/rapidxml_iterators.hpp rename to rapidxml/rapidxml_iterators.hpp diff --git a/simulatordaemon/src/TABinaryManager/rapidxml/rapidxml_print.hpp b/rapidxml/rapidxml_print.hpp similarity index 100% rename from simulatordaemon/src/TABinaryManager/rapidxml/rapidxml_print.hpp rename to rapidxml/rapidxml_print.hpp diff --git a/simulatordaemon/src/TABinaryManager/rapidxml/rapidxml_utils.hpp b/rapidxml/rapidxml_utils.hpp similarity index 100% rename from simulatordaemon/src/TABinaryManager/rapidxml/rapidxml_utils.hpp rename to rapidxml/rapidxml_utils.hpp diff --git a/simulatordaemon/CMakeLists.txt b/simulatordaemon/CMakeLists.txt index 21b789b..0774429 100644 --- a/simulatordaemon/CMakeLists.txt +++ b/simulatordaemon/CMakeLists.txt @@ -77,6 +77,7 @@ ADD_DEPENDENCIES(${TARGET_TEF_SIMULATOR_DAEMON} ) INCLUDE_DIRECTORIES( + ${TEF_SIMULATOR_ROOT_PATH} ${DAEMON_PATH}/inc ${DAEMON_PATH}/inc/ClientCommands ${DAEMON_PATH}/inc/ResponseCommands diff --git a/simulatordaemon/src/rapidxml/rapidxml.hpp b/simulatordaemon/src/rapidxml/rapidxml.hpp deleted file mode 100644 index 234f577..0000000 --- a/simulatordaemon/src/rapidxml/rapidxml.hpp +++ /dev/null @@ -1,2396 +0,0 @@ -#ifndef RAPIDXML_HPP_INCLUDED -#define RAPIDXML_HPP_INCLUDED - -// Copyright (C) 2006, 2009 Marcin Kalicinski -// Version 1.13 -// Revision $DateTime: 2009/05/13 01:46:17 $ -//! \file rapidxml.hpp This file contains rapidxml parser and DOM implementation - -// If standard library is disabled, user must provide implementations of required functions and typedefs -#if !defined(RAPIDXML_NO_STDLIB) -#include // For std::size_t -#include // For assert -#include // For placement new -#endif - -// On MSVC, disable "conditional expression is constant" warning (level 4). -// This warning is almost impossible to avoid with certain types of templated code -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable:4127) // Conditional expression is constant -#endif - -/////////////////////////////////////////////////////////////////////////// -// RAPIDXML_PARSE_ERROR - -#if defined(RAPIDXML_NO_EXCEPTIONS) - -#define RAPIDXML_PARSE_ERROR(what, where) { parse_error_handler(what, where); assert(0); } - -namespace rapidxml -{ - //! When exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, - //! this function is called to notify user about the error. - //! It must be defined by the user. - //!

- //! This function cannot return. If it does, the results are undefined. - //!

- //! A very simple definition might look like that: - //!
-	//! void %rapidxml::%parse_error_handler(const char *what, void *where)
-	//! {
-	//!     LOGE(SIM_DAEMON, "Parse error: %s", what);
-	//!     std::abort();
-	//! }
-	//! 
- //! \param what Human readable description of the error. - //! \param where Pointer to character data where error was detected. - void parse_error_handler(const char *what, void *where); -} - -#else - -#include // For std::exception - -#define RAPIDXML_PARSE_ERROR(what, where) throw parse_error(what, where) - -namespace rapidxml { - -//! Parse error exception. -//! This exception is thrown by the parser when an error occurs. -//! Use what() function to get human-readable error message. -//! Use where() function to get a pointer to position within source text where error was detected. -//!

-//! If throwing exceptions by the parser is undesirable, -//! it can be disabled by defining RAPIDXML_NO_EXCEPTIONS macro before rapidxml.hpp is included. -//! This will cause the parser to call rapidxml::parse_error_handler() function instead of throwing an exception. -//! This function must be defined by the user. -//!

-//! This class derives from std::exception class. -class parse_error: - public std::exception { - -public: - - //! Constructs parse error - parse_error(const char *what, void *where) : - m_what(what), m_where(where) { - } - - //! Gets human readable description of error. - //! \return Pointer to null terminated description of the error. - virtual const char *what() const throw () { - return m_what; - } - - //! Gets pointer to character data where error happened. - //! Ch should be the same as char type of xml_document that produced the error. - //! \return Pointer to location within the parsed string where error occured. - template - Ch *where() const { - return reinterpret_cast(m_where); - } - -private: - - const char *m_what; - void *m_where; - -}; -} - -#endif - -/////////////////////////////////////////////////////////////////////////// -// Pool sizes - -#ifndef RAPIDXML_STATIC_POOL_SIZE -// Size of static memory block of memory_pool. -// Define RAPIDXML_STATIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value. -// No dynamic memory allocations are performed by memory_pool until static memory is exhausted. -#define RAPIDXML_STATIC_POOL_SIZE (64 * 1024) -#endif - -#ifndef RAPIDXML_DYNAMIC_POOL_SIZE -// Size of dynamic memory block of memory_pool. -// Define RAPIDXML_DYNAMIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value. -// After the static block is exhausted, dynamic blocks with approximately this size are allocated by memory_pool. -#define RAPIDXML_DYNAMIC_POOL_SIZE (64 * 1024) -#endif - -#ifndef RAPIDXML_ALIGNMENT -// Memory allocation alignment. -// Define RAPIDXML_ALIGNMENT before including rapidxml.hpp if you want to override the default value, which is the size of pointer. -// All memory allocations for nodes, attributes and strings will be aligned to this value. -// This must be a power of 2 and at least 1, otherwise memory_pool will not work. -#define RAPIDXML_ALIGNMENT sizeof(void *) -#endif - -namespace rapidxml { -// Forward declarations -template class xml_node; -template class xml_attribute; -template class xml_document; - -//! Enumeration listing all node types produced by the parser. -//! Use xml_node::type() function to query node type. -enum node_type { - node_document, //!< A document node. Name and value are empty. - node_element, //!< An element node. Name contains element name. Value contains text of first data node. - node_data, //!< A data node. Name is empty. Value contains data text. - node_cdata, //!< A CDATA node. Name is empty. Value contains data text. - node_comment, //!< A comment node. Name is empty. Value contains comment text. - node_declaration, //!< A declaration node. Name and value are empty. Declaration parameters (version, encoding and standalone) are in node attributes. - node_doctype, //!< A DOCTYPE node. Name is empty. Value contains DOCTYPE text. - node_pi //!< A PI node. Name contains target. Value contains instructions. -}; - -/////////////////////////////////////////////////////////////////////// -// Parsing flags - -//! Parse flag instructing the parser to not create data nodes. -//! Text of first data node will still be placed in value of parent element, unless rapidxml::parse_no_element_values flag is also specified. -//! Can be combined with other flags by use of | operator. -//!

-//! See xml_document::parse() function. -const int parse_no_data_nodes = 0x1; - -//! Parse flag instructing the parser to not use text of first data node as a value of parent element. -//! Can be combined with other flags by use of | operator. -//! Note that child data nodes of element node take precendence over its value when printing. -//! That is, if element has one or more child data nodes and a value, the value will be ignored. -//! Use rapidxml::parse_no_data_nodes flag to prevent creation of data nodes if you want to manipulate data using values of elements. -//!

-//! See xml_document::parse() function. -const int parse_no_element_values = 0x2; - -//! Parse flag instructing the parser to not place zero terminators after strings in the source text. -//! By default zero terminators are placed, modifying source text. -//! Can be combined with other flags by use of | operator. -//!

-//! See xml_document::parse() function. -const int parse_no_string_terminators = 0x4; - -//! Parse flag instructing the parser to not translate entities in the source text. -//! By default entities are translated, modifying source text. -//! Can be combined with other flags by use of | operator. -//!

-//! See xml_document::parse() function. -const int parse_no_entity_translation = 0x8; - -//! Parse flag instructing the parser to disable UTF-8 handling and assume plain 8 bit characters. -//! By default, UTF-8 handling is enabled. -//! Can be combined with other flags by use of | operator. -//!

-//! See xml_document::parse() function. -const int parse_no_utf8 = 0x10; - -//! Parse flag instructing the parser to create XML declaration node. -//! By default, declaration node is not created. -//! Can be combined with other flags by use of | operator. -//!

-//! See xml_document::parse() function. -const int parse_declaration_node = 0x20; - -//! Parse flag instructing the parser to create comments nodes. -//! By default, comment nodes are not created. -//! Can be combined with other flags by use of | operator. -//!

-//! See xml_document::parse() function. -const int parse_comment_nodes = 0x40; - -//! Parse flag instructing the parser to create DOCTYPE node. -//! By default, doctype node is not created. -//! Although W3C specification allows at most one DOCTYPE node, RapidXml will silently accept documents with more than one. -//! Can be combined with other flags by use of | operator. -//!

-//! See xml_document::parse() function. -const int parse_doctype_node = 0x80; - -//! Parse flag instructing the parser to create PI nodes. -//! By default, PI nodes are not created. -//! Can be combined with other flags by use of | operator. -//!

-//! See xml_document::parse() function. -const int parse_pi_nodes = 0x100; - -//! Parse flag instructing the parser to validate closing tag names. -//! If not set, name inside closing tag is irrelevant to the parser. -//! By default, closing tags are not validated. -//! Can be combined with other flags by use of | operator. -//!

-//! See xml_document::parse() function. -const int parse_validate_closing_tags = 0x200; - -//! Parse flag instructing the parser to trim all leading and trailing whitespace of data nodes. -//! By default, whitespace is not trimmed. -//! This flag does not cause the parser to modify source text. -//! Can be combined with other flags by use of | operator. -//!

-//! See xml_document::parse() function. -const int parse_trim_whitespace = 0x400; - -//! Parse flag instructing the parser to condense all whitespace runs of data nodes to a single space character. -//! Trimming of leading and trailing whitespace of data is controlled by rapidxml::parse_trim_whitespace flag. -//! By default, whitespace is not normalized. -//! If this flag is specified, source text will be modified. -//! Can be combined with other flags by use of | operator. -//!

-//! See xml_document::parse() function. -const int parse_normalize_whitespace = 0x800; - -// Compound flags - -//! Parse flags which represent default behaviour of the parser. -//! This is always equal to 0, so that all other flags can be simply ored together. -//! Normally there is no need to inconveniently disable flags by anding with their negated (~) values. -//! This also means that meaning of each flag is a negation of the default setting. -//! For example, if flag name is rapidxml::parse_no_utf8, it means that utf-8 is enabled by default, -//! and using the flag will disable it. -//!

-//! See xml_document::parse() function. -const int parse_default = 0; - -//! A combination of parse flags that forbids any modifications of the source text. -//! This also results in faster parsing. However, note that the following will occur: -//!
    -//!
  • names and values of nodes will not be zero terminated, you have to use xml_base::name_size() and xml_base::value_size() functions to determine where name and value ends
  • -//!
  • entities will not be translated
  • -//!
  • whitespace will not be normalized
  • -//!
-//! See xml_document::parse() function. -const int parse_non_destructive = parse_no_string_terminators - | parse_no_entity_translation; - -//! A combination of parse flags resulting in fastest possible parsing, without sacrificing important data. -//!

-//! See xml_document::parse() function. -const int parse_fastest = parse_non_destructive | parse_no_data_nodes; - -//! A combination of parse flags resulting in largest amount of data being extracted. -//! This usually results in slowest parsing. -//!

-//! See xml_document::parse() function. -const int parse_full = parse_declaration_node | parse_comment_nodes - | parse_doctype_node | parse_pi_nodes | parse_validate_closing_tags; - -/////////////////////////////////////////////////////////////////////// -// Internals - -//! \cond internal -namespace internal { - -// Struct that contains lookup tables for the parser -// It must be a template to allow correct linking (because it has static data members, which are defined in a header file). -template -struct lookup_tables { - static const unsigned char lookup_whitespace[256]; // Whitespace table - static const unsigned char lookup_node_name[256]; // Node name table - static const unsigned char lookup_text[256]; // Text table - static const unsigned char lookup_text_pure_no_ws[256]; // Text table - static const unsigned char lookup_text_pure_with_ws[256]; // Text table - static const unsigned char lookup_attribute_name[256]; // Attribute name table - static const unsigned char lookup_attribute_data_1[256]; // Attribute data table with single quote - static const unsigned char lookup_attribute_data_1_pure[256]; // Attribute data table with single quote - static const unsigned char lookup_attribute_data_2[256]; // Attribute data table with double quotes - static const unsigned char lookup_attribute_data_2_pure[256]; // Attribute data table with double quotes - static const unsigned char lookup_digits[256]; // Digits - static const unsigned char lookup_upcase[256]; // To uppercase conversion table for ASCII characters -}; - -// Find length of the string -template -inline std::size_t measure(const Ch *p) { - const Ch *tmp = p; - while (*tmp) - ++tmp; - return tmp - p; -} - -// Compare strings for equality -template -inline bool compare(const Ch *p1, std::size_t size1, const Ch *p2, - std::size_t size2, bool case_sensitive) { - if (size1 != size2) return false; - if (case_sensitive) { - for (const Ch *end = p1 + size1; p1 < end; ++p1, ++p2) - if (*p1 != *p2) return false; - } else { - for (const Ch *end = p1 + size1; p1 < end; ++p1, ++p2) - if (lookup_tables<0>::lookup_upcase[static_cast(*p1)] - != lookup_tables<0>::lookup_upcase[static_cast(*p2)]) - return false; - } - return true; -} -} -//! \endcond - -/////////////////////////////////////////////////////////////////////// -// Memory pool - -//! This class is used by the parser to create new nodes and attributes, without overheads of dynamic memory allocation. -//! In most cases, you will not need to use this class directly. -//! However, if you need to create nodes manually or modify names/values of nodes, -//! you are encouraged to use memory_pool of relevant xml_document to allocate the memory. -//! Not only is this faster than allocating them by using new operator, -//! but also their lifetime will be tied to the lifetime of document, -//! possibly simplyfing memory management. -//!

-//! Call allocate_node() or allocate_attribute() functions to obtain new nodes or attributes from the pool. -//! You can also call allocate_string() function to allocate strings. -//! Such strings can then be used as names or values of nodes without worrying about their lifetime. -//! Note that there is no free() function -- all allocations are freed at once when clear() function is called, -//! or when the pool is destroyed. -//!

-//! It is also possible to create a standalone memory_pool, and use it -//! to allocate nodes, whose lifetime will not be tied to any document. -//!

-//! Pool maintains RAPIDXML_STATIC_POOL_SIZE bytes of statically allocated memory. -//! Until static memory is exhausted, no dynamic memory allocations are done. -//! When static memory is exhausted, pool allocates additional blocks of memory of size RAPIDXML_DYNAMIC_POOL_SIZE each, -//! by using global new[] and delete[] operators. -//! This behaviour can be changed by setting custom allocation routines. -//! Use set_allocator() function to set them. -//!

-//! Allocations for nodes, attributes and strings are aligned at RAPIDXML_ALIGNMENT bytes. -//! This value defaults to the size of pointer on target architecture. -//!

-//! To obtain absolutely top performance from the parser, -//! it is important that all nodes are allocated from a single, contiguous block of memory. -//! Otherwise, cache misses when jumping between two (or more) disjoint blocks of memory can slow down parsing quite considerably. -//! If required, you can tweak RAPIDXML_STATIC_POOL_SIZE, RAPIDXML_DYNAMIC_POOL_SIZE and RAPIDXML_ALIGNMENT -//! to obtain best wasted memory to performance compromise. -//! To do it, define their values before rapidxml.hpp file is included. -//! \param Ch Character type of created nodes. -template -class memory_pool { - -public: - - //! \cond internal - typedef void *(alloc_func)(std::size_t); // Type of user-defined function used to allocate memory - typedef void (free_func)(void *); // Type of user-defined function used to free memory - //! \endcond - - //! Constructs empty pool with default allocator functions. - memory_pool() : - m_alloc_func(0), m_free_func(0) { - init(); - } - - //! Destroys pool and frees all the memory. - //! This causes memory occupied by nodes allocated by the pool to be freed. - //! Nodes allocated from the pool are no longer valid. - ~memory_pool() { - clear(); - } - - //! Allocates a new node from the pool, and optionally assigns name and value to it. - //! If the allocation request cannot be accomodated, this function will throw std::bad_alloc. - //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function - //! will call rapidxml::parse_error_handler() function. - //! \param type Type of node to create. - //! \param name Name to assign to the node, or 0 to assign no name. - //! \param value Value to assign to the node, or 0 to assign no value. - //! \param name_size Size of name to assign, or 0 to automatically calculate size from name string. - //! \param value_size Size of value to assign, or 0 to automatically calculate size from value string. - //! \return Pointer to allocated node. This pointer will never be NULL. - xml_node *allocate_node(node_type type, const Ch *name = 0, - const Ch *value = 0, std::size_t name_size = 0, - std::size_t value_size = 0) { - void *memory = allocate_aligned(sizeof(xml_node )); - xml_node *node = new (memory) xml_node(type); - if (name) { - if (name_size > 0) - node->name(name, name_size); - else node->name(name); - } - if (value) { - if (value_size > 0) - node->value(value, value_size); - else node->value(value); - } - return node; - } - - //! Allocates a new attribute from the pool, and optionally assigns name and value to it. - //! If the allocation request cannot be accomodated, this function will throw std::bad_alloc. - //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function - //! will call rapidxml::parse_error_handler() function. - //! \param name Name to assign to the attribute, or 0 to assign no name. - //! \param value Value to assign to the attribute, or 0 to assign no value. - //! \param name_size Size of name to assign, or 0 to automatically calculate size from name string. - //! \param value_size Size of value to assign, or 0 to automatically calculate size from value string. - //! \return Pointer to allocated attribute. This pointer will never be NULL. - xml_attribute *allocate_attribute(const Ch *name = 0, const Ch *value = 0, - std::size_t name_size = 0, std::size_t value_size = 0) { - void *memory = allocate_aligned(sizeof(xml_attribute )); - xml_attribute *attribute = new (memory) xml_attribute; - if (name) { - if (name_size > 0) - attribute->name(name, name_size); - else attribute->name(name); - } - if (value) { - if (value_size > 0) - attribute->value(value, value_size); - else attribute->value(value); - } - return attribute; - } - - //! Allocates a char array of given size from the pool, and optionally copies a given string to it. - //! If the allocation request cannot be accomodated, this function will throw std::bad_alloc. - //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function - //! will call rapidxml::parse_error_handler() function. - //! \param source String to initialize the allocated memory with, or 0 to not initialize it. - //! \param size Number of characters to allocate, or zero to calculate it automatically from source string length; if size is 0, source string must be specified and null terminated. - //! \return Pointer to allocated char array. This pointer will never be NULL. - Ch *allocate_string(const Ch *source = 0, std::size_t size = 0) { - assert(source || size); // Either source or size (or both) must be specified - if (size == 0) size = internal::measure(source) + 1; - Ch *result = static_cast(allocate_aligned(size * sizeof(Ch))); - if (source) for (std::size_t i = 0; i < size; ++i) - result[i] = source[i]; - return result; - } - - //! Clones an xml_node and its hierarchy of child nodes and attributes. - //! Nodes and attributes are allocated from this memory pool. - //! Names and values are not cloned, they are shared between the clone and the source. - //! Result node can be optionally specified as a second parameter, - //! in which case its contents will be replaced with cloned source node. - //! This is useful when you want to clone entire document. - //! \param source Node to clone. - //! \param result Node to put results in, or 0 to automatically allocate result node - //! \return Pointer to cloned node. This pointer will never be NULL. - xml_node *clone_node(const xml_node *source, - xml_node *result = 0) { - // Prepare result node - if (result) { - result->remove_all_attributes(); - result->remove_all_nodes(); - result->type(source->type()); - } else result = allocate_node(source->type()); - - // Clone name and value - result->name(source->name(), source->name_size()); - result->value(source->value(), source->value_size()); - - // Clone child nodes and attributes - for (xml_node *child = source->first_node(); child; - child = child->next_sibling()) - result->append_node(clone_node(child)); - for (xml_attribute *attr = source->first_attribute(); attr; - attr = attr->next_attribute()) - result->append_attribute( - allocate_attribute(attr->name(), attr->value(), attr->name_size(), - attr->value_size())); - - return result; - } - - //! Clears the pool. - //! This causes memory occupied by nodes allocated by the pool to be freed. - //! Any nodes or strings allocated from the pool will no longer be valid. - void clear() { - while (m_begin != m_static_memory) { - char *previous_begin = reinterpret_cast
(align(m_begin)) - ->previous_begin; - if (m_free_func) - m_free_func(m_begin); - else delete[] m_begin; - m_begin = previous_begin; - } - init(); - } - - //! Sets or resets the user-defined memory allocation functions for the pool. - //! This can only be called when no memory is allocated from the pool yet, otherwise results are undefined. - //! Allocation function must not return invalid pointer on failure. It should either throw, - //! stop the program, or use longjmp() function to pass control to other place of program. - //! If it returns invalid pointer, results are undefined. - //!

- //! User defined allocation functions must have the following forms: - //!
- //!
void *allocate(std::size_t size); - //!
void free(void *pointer); - //!

- //! \param af Allocation function, or 0 to restore default function - //! \param ff Free function, or 0 to restore default function - void set_allocator(alloc_func *af, free_func *ff) { - assert(m_begin == m_static_memory && m_ptr == align(m_begin)); // Verify that no memory is allocated yet - m_alloc_func = af; - m_free_func = ff; - } - -private: - - struct header { - char *previous_begin; - }; - - void init() { - m_begin = m_static_memory; - m_ptr = align(m_begin); - m_end = m_static_memory + sizeof(m_static_memory); - } - - char *align(char *ptr) { - std::size_t alignment = ((RAPIDXML_ALIGNMENT - - (std::size_t(ptr) & (RAPIDXML_ALIGNMENT - 1))) - & (RAPIDXML_ALIGNMENT - 1)); - return ptr + alignment; - } - - char *allocate_raw(std::size_t size) { - // Allocate - void *memory; - if (m_alloc_func) // Allocate memory using either user-specified allocation function or global operator new[] - { - memory = m_alloc_func(size); - assert(memory); // Allocator is not allowed to return 0, on failure it must either throw, stop the program or use longjmp - } else { - memory = new char[size]; -#ifdef RAPIDXML_NO_EXCEPTIONS - if (!memory) // If exceptions are disabled, verify memory allocation, because new will not be able to throw bad_alloc - RAPIDXML_PARSE_ERROR("out of memory", 0); -#endif - } - return static_cast(memory); - } - - void *allocate_aligned(std::size_t size) { - // Calculate aligned pointer - char *result = align(m_ptr); - - // If not enough memory left in current pool, allocate a new pool - if (result + size > m_end) { - // Calculate required pool size (may be bigger than RAPIDXML_DYNAMIC_POOL_SIZE) - std::size_t pool_size = RAPIDXML_DYNAMIC_POOL_SIZE; - if (pool_size < size) pool_size = size; - - // Allocate - std::size_t alloc_size = sizeof(header) + (2 * RAPIDXML_ALIGNMENT - 2) - + pool_size; // 2 alignments required in worst case: one for header, one for actual allocation - char *raw_memory = allocate_raw(alloc_size); - - // Setup new pool in allocated memory - char *pool = align(raw_memory); - header *new_header = reinterpret_cast
(pool); - new_header->previous_begin = m_begin; - m_begin = raw_memory; - m_ptr = pool + sizeof(header); - m_end = raw_memory + alloc_size; - - // Calculate aligned pointer again using new pool - result = align(m_ptr); - } - - // Update pool and return aligned pointer - m_ptr = result + size; - return result; - } - - char *m_begin; // Start of raw memory making up current pool - char *m_ptr; // First free byte in current pool - char *m_end; // One past last available byte in current pool - char m_static_memory[RAPIDXML_STATIC_POOL_SIZE]; // Static raw memory - alloc_func *m_alloc_func; // Allocator function, or 0 if default is to be used - free_func *m_free_func; // Free function, or 0 if default is to be used -}; - -/////////////////////////////////////////////////////////////////////////// -// XML base - -//! Base class for xml_node and xml_attribute implementing common functions: -//! name(), name_size(), value(), value_size() and parent(). -//! \param Ch Character type to use -template -class xml_base { - -public: - - /////////////////////////////////////////////////////////////////////////// - // Construction & destruction - - // Construct a base with empty name, value and parent - xml_base() : - m_name(0), m_value(0), m_parent(0) { - } - - /////////////////////////////////////////////////////////////////////////// - // Node data access - - //! Gets name of the node. - //! Interpretation of name depends on type of node. - //! Note that name will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse. - //!

- //! Use name_size() function to determine length of the name. - //! \return Name of node, or empty string if node has no name. - Ch *name() const { - return m_name ? m_name : nullstr(); - } - - //! Gets size of node name, not including terminator character. - //! This function works correctly irrespective of whether name is or is not zero terminated. - //! \return Size of node name, in characters. - std::size_t name_size() const { - return m_name ? m_name_size : 0; - } - - //! Gets value of node. - //! Interpretation of value depends on type of node. - //! Note that value will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse. - //!

- //! Use value_size() function to determine length of the value. - //! \return Value of node, or empty string if node has no value. - Ch *value() const { - return m_value ? m_value : nullstr(); - } - - //! Gets size of node value, not including terminator character. - //! This function works correctly irrespective of whether value is or is not zero terminated. - //! \return Size of node value, in characters. - std::size_t value_size() const { - return m_value ? m_value_size : 0; - } - - /////////////////////////////////////////////////////////////////////////// - // Node modification - - //! Sets name of node to a non zero-terminated string. - //! See \ref ownership_of_strings. - //!

- //! Note that node does not own its name or value, it only stores a pointer to it. - //! It will not delete or otherwise free the pointer on destruction. - //! It is reponsibility of the user to properly manage lifetime of the string. - //! The easiest way to achieve it is to use memory_pool of the document to allocate the string - - //! on destruction of the document the string will be automatically freed. - //!

- //! Size of name must be specified separately, because name does not have to be zero terminated. - //! Use name(const Ch *) function to have the length automatically calculated (string must be zero terminated). - //! \param name Name of node to set. Does not have to be zero terminated. - //! \param size Size of name, in characters. This does not include zero terminator, if one is present. - void name(const Ch *name, std::size_t size) { - m_name = const_cast(name); - m_name_size = size; - } - - //! Sets name of node to a zero-terminated string. - //! See also \ref ownership_of_strings and xml_node::name(const Ch *, std::size_t). - //! \param name Name of node to set. Must be zero terminated. - void name(const Ch *name) { - this->name(name, internal::measure(name)); - } - - //! Sets value of node to a non zero-terminated string. - //! See \ref ownership_of_strings. - //!

- //! Note that node does not own its name or value, it only stores a pointer to it. - //! It will not delete or otherwise free the pointer on destruction. - //! It is reponsibility of the user to properly manage lifetime of the string. - //! The easiest way to achieve it is to use memory_pool of the document to allocate the string - - //! on destruction of the document the string will be automatically freed. - //!

- //! Size of value must be specified separately, because it does not have to be zero terminated. - //! Use value(const Ch *) function to have the length automatically calculated (string must be zero terminated). - //!

- //! If an element has a child node of type node_data, it will take precedence over element value when printing. - //! If you want to manipulate data of elements using values, use parser flag rapidxml::parse_no_data_nodes to prevent creation of data nodes by the parser. - //! \param value value of node to set. Does not have to be zero terminated. - //! \param size Size of value, in characters. This does not include zero terminator, if one is present. - void value(const Ch *value, std::size_t size) { - m_value = const_cast(value); - m_value_size = size; - } - - //! Sets value of node to a zero-terminated string. - //! See also \ref ownership_of_strings and xml_node::value(const Ch *, std::size_t). - //! \param value Vame of node to set. Must be zero terminated. - void value(const Ch *value) { - this->value(value, internal::measure(value)); - } - - /////////////////////////////////////////////////////////////////////////// - // Related nodes access - - //! Gets node parent. - //! \return Pointer to parent node, or 0 if there is no parent. - xml_node *parent() const { - return m_parent; - } - -protected: - - // Return empty string - static Ch *nullstr() { - static Ch zero = Ch('\0'); - return &zero; - } - - Ch *m_name; // Name of node, or 0 if no name - Ch *m_value; // Value of node, or 0 if no value - std::size_t m_name_size; // Length of node name, or undefined of no name - std::size_t m_value_size; // Length of node value, or undefined if no value - xml_node *m_parent; // Pointer to parent node, or 0 if none - -}; - -//! Class representing attribute node of XML document. -//! Each attribute has name and value strings, which are available through name() and value() functions (inherited from xml_base). -//! Note that after parse, both name and value of attribute will point to interior of source text used for parsing. -//! Thus, this text must persist in memory for the lifetime of attribute. -//! \param Ch Character type to use. -template -class xml_attribute: - public xml_base { - - friend class xml_node ; - -public: - - /////////////////////////////////////////////////////////////////////////// - // Construction & destruction - - //! Constructs an empty attribute with the specified type. - //! Consider using memory_pool of appropriate xml_document if allocating attributes manually. - xml_attribute() { - } - - /////////////////////////////////////////////////////////////////////////// - // Related nodes access - - //! Gets document of which attribute is a child. - //! \return Pointer to document that contains this attribute, or 0 if there is no parent document. - xml_document *document() const { - if (xml_node *node = this->parent()) { - while (node->parent()) - node = node->parent(); - return - node->type() == node_document ? - static_cast *>(node) : 0; - } else return 0; - } - - //! Gets previous attribute, optionally matching attribute name. - //! \param name Name of attribute to find, or 0 to return previous attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero - //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string - //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters - //! \return Pointer to found attribute, or 0 if not found. - xml_attribute *previous_attribute(const Ch *name = 0, - std::size_t name_size = 0, bool case_sensitive = true) const { - if (name) { - if (name_size == 0) name_size = internal::measure(name); - for (xml_attribute *attribute = m_prev_attribute; attribute; - attribute = attribute->m_prev_attribute) - if (internal::compare(attribute->name(), attribute->name_size(), name, - name_size, case_sensitive)) return attribute; - return 0; - } else return this->m_parent ? m_prev_attribute : 0; - } - - //! Gets next attribute, optionally matching attribute name. - //! \param name Name of attribute to find, or 0 to return next attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero - //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string - //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters - //! \return Pointer to found attribute, or 0 if not found. - xml_attribute *next_attribute(const Ch *name = 0, std::size_t name_size = - 0, bool case_sensitive = true) const { - if (name) { - if (name_size == 0) name_size = internal::measure(name); - for (xml_attribute *attribute = m_next_attribute; attribute; - attribute = attribute->m_next_attribute) - if (internal::compare(attribute->name(), attribute->name_size(), name, - name_size, case_sensitive)) return attribute; - return 0; - } else return this->m_parent ? m_next_attribute : 0; - } - -private: - - xml_attribute *m_prev_attribute; // Pointer to previous sibling of attribute, or 0 if none; only valid if parent is non-zero - xml_attribute *m_next_attribute; // Pointer to next sibling of attribute, or 0 if none; only valid if parent is non-zero - -}; - -/////////////////////////////////////////////////////////////////////////// -// XML node - -//! Class representing a node of XML document. -//! Each node may have associated name and value strings, which are available through name() and value() functions. -//! Interpretation of name and value depends on type of the node. -//! Type of node can be determined by using type() function. -//!

-//! Note that after parse, both name and value of node, if any, will point interior of source text used for parsing. -//! Thus, this text must persist in the memory for the lifetime of node. -//! \param Ch Character type to use. -template -class xml_node: - public xml_base { - -public: - - /////////////////////////////////////////////////////////////////////////// - // Construction & destruction - - //! Constructs an empty node with the specified type. - //! Consider using memory_pool of appropriate document to allocate nodes manually. - //! \param type Type of node to construct. - xml_node(node_type type) : - m_type(type), m_first_node(0), m_first_attribute(0) { - } - - /////////////////////////////////////////////////////////////////////////// - // Node data access - - //! Gets type of node. - //! \return Type of node. - node_type type() const { - return m_type; - } - - /////////////////////////////////////////////////////////////////////////// - // Related nodes access - - //! Gets document of which node is a child. - //! \return Pointer to document that contains this node, or 0 if there is no parent document. - xml_document *document() const { - xml_node *node = const_cast *>(this); - while (node->parent()) - node = node->parent(); - return - node->type() == node_document ? static_cast *>(node) : - 0; - } - - //! Gets first child node, optionally matching node name. - //! \param name Name of child to find, or 0 to return first child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero - //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string - //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters - //! \return Pointer to found child, or 0 if not found. - xml_node *first_node(const Ch *name = 0, std::size_t name_size = 0, - bool case_sensitive = true) const { - if (name) { - if (name_size == 0) name_size = internal::measure(name); - for (xml_node *child = m_first_node; child; - child = child->next_sibling()) - if (internal::compare(child->name(), child->name_size(), name, - name_size, case_sensitive)) return child; - return 0; - } else return m_first_node; - } - - //! Gets last child node, optionally matching node name. - //! Behaviour is undefined if node has no children. - //! Use first_node() to test if node has children. - //! \param name Name of child to find, or 0 to return last child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero - //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string - //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters - //! \return Pointer to found child, or 0 if not found. - xml_node *last_node(const Ch *name = 0, std::size_t name_size = 0, - bool case_sensitive = true) const { - assert(m_first_node); // Cannot query for last child if node has no children - if (name) { - if (name_size == 0) name_size = internal::measure(name); - for (xml_node *child = m_last_node; child; - child = child->previous_sibling()) - if (internal::compare(child->name(), child->name_size(), name, - name_size, case_sensitive)) return child; - return 0; - } else return m_last_node; - } - - //! Gets previous sibling node, optionally matching node name. - //! Behaviour is undefined if node has no parent. - //! Use parent() to test if node has a parent. - //! \param name Name of sibling to find, or 0 to return previous sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero - //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string - //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters - //! \return Pointer to found sibling, or 0 if not found. - xml_node *previous_sibling(const Ch *name = 0, std::size_t name_size = 0, - bool case_sensitive = true) const { - assert(this->m_parent); // Cannot query for siblings if node has no parent - if (name) { - if (name_size == 0) name_size = internal::measure(name); - for (xml_node *sibling = m_prev_sibling; sibling; - sibling = sibling->m_prev_sibling) - if (internal::compare(sibling->name(), sibling->name_size(), name, - name_size, case_sensitive)) return sibling; - return 0; - } else return m_prev_sibling; - } - - //! Gets next sibling node, optionally matching node name. - //! Behaviour is undefined if node has no parent. - //! Use parent() to test if node has a parent. - //! \param name Name of sibling to find, or 0 to return next sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero - //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string - //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters - //! \return Pointer to found sibling, or 0 if not found. - xml_node *next_sibling(const Ch *name = 0, std::size_t name_size = 0, - bool case_sensitive = true) const { - assert(this->m_parent); // Cannot query for siblings if node has no parent - if (name) { - if (name_size == 0) name_size = internal::measure(name); - for (xml_node *sibling = m_next_sibling; sibling; - sibling = sibling->m_next_sibling) - if (internal::compare(sibling->name(), sibling->name_size(), name, - name_size, case_sensitive)) return sibling; - return 0; - } else return m_next_sibling; - } - - //! Gets first attribute of node, optionally matching attribute name. - //! \param name Name of attribute to find, or 0 to return first attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero - //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string - //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters - //! \return Pointer to found attribute, or 0 if not found. - xml_attribute *first_attribute(const Ch *name = 0, std::size_t name_size = - 0, bool case_sensitive = true) const { - if (name) { - if (name_size == 0) name_size = internal::measure(name); - for (xml_attribute *attribute = m_first_attribute; attribute; - attribute = attribute->m_next_attribute) - if (internal::compare(attribute->name(), attribute->name_size(), name, - name_size, case_sensitive)) return attribute; - return 0; - } else return m_first_attribute; - } - - //! Gets last attribute of node, optionally matching attribute name. - //! \param name Name of attribute to find, or 0 to return last attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero - //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string - //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters - //! \return Pointer to found attribute, or 0 if not found. - xml_attribute *last_attribute(const Ch *name = 0, std::size_t name_size = - 0, bool case_sensitive = true) const { - if (name) { - if (name_size == 0) name_size = internal::measure(name); - for (xml_attribute *attribute = m_last_attribute; attribute; - attribute = attribute->m_prev_attribute) - if (internal::compare(attribute->name(), attribute->name_size(), name, - name_size, case_sensitive)) return attribute; - return 0; - } else return m_first_attribute ? m_last_attribute : 0; - } - - /////////////////////////////////////////////////////////////////////////// - // Node modification - - //! Sets type of node. - //! \param type Type of node to set. - void type(node_type type) { - m_type = type; - } - - /////////////////////////////////////////////////////////////////////////// - // Node manipulation - - //! Prepends a new child node. - //! The prepended child becomes the first child, and all existing children are moved one position back. - //! \param child Node to prepend. - void prepend_node(xml_node *child) { - assert(child && !child->parent() && child->type() != node_document); - if (first_node()) { - child->m_next_sibling = m_first_node; - m_first_node->m_prev_sibling = child; - } else { - child->m_next_sibling = 0; - m_last_node = child; - } - m_first_node = child; - child->m_parent = this; - child->m_prev_sibling = 0; - } - - //! Appends a new child node. - //! The appended child becomes the last child. - //! \param child Node to append. - void append_node(xml_node *child) { - assert(child && !child->parent() && child->type() != node_document); - if (first_node()) { - child->m_prev_sibling = m_last_node; - m_last_node->m_next_sibling = child; - } else { - child->m_prev_sibling = 0; - m_first_node = child; - } - m_last_node = child; - child->m_parent = this; - child->m_next_sibling = 0; - } - - //! Inserts a new child node at specified place inside the node. - //! All children after and including the specified node are moved one position back. - //! \param where Place where to insert the child, or 0 to insert at the back. - //! \param child Node to insert. - void insert_node(xml_node *where, xml_node *child) { - assert(!where || where->parent() == this); - assert(child && !child->parent() && child->type() != node_document); - if (where == m_first_node) - prepend_node(child); - else if (where == 0) - append_node(child); - else { - child->m_prev_sibling = where->m_prev_sibling; - child->m_next_sibling = where; - where->m_prev_sibling->m_next_sibling = child; - where->m_prev_sibling = child; - child->m_parent = this; - } - } - - //! Removes first child node. - //! If node has no children, behaviour is undefined. - //! Use first_node() to test if node has children. - void remove_first_node() { - assert(first_node()); - xml_node *child = m_first_node; - m_first_node = child->m_next_sibling; - if (child->m_next_sibling) - child->m_next_sibling->m_prev_sibling = 0; - else m_last_node = 0; - child->m_parent = 0; - } - - //! Removes last child of the node. - //! If node has no children, behaviour is undefined. - //! Use first_node() to test if node has children. - void remove_last_node() { - assert(first_node()); - xml_node *child = m_last_node; - if (child->m_prev_sibling) { - m_last_node = child->m_prev_sibling; - child->m_prev_sibling->m_next_sibling = 0; - } else m_first_node = 0; - child->m_parent = 0; - } - - //! Removes specified child from the node - // \param where Pointer to child to be removed. - void remove_node(xml_node *where) { - assert(where && where->parent() == this); - assert(first_node()); - if (where == m_first_node) - remove_first_node(); - else if (where == m_last_node) - remove_last_node(); - else { - where->m_prev_sibling->m_next_sibling = where->m_next_sibling; - where->m_next_sibling->m_prev_sibling = where->m_prev_sibling; - where->m_parent = 0; - } - } - - //! Removes all child nodes (but not attributes). - void remove_all_nodes() { - for (xml_node *node = first_node(); node; node = node->m_next_sibling) - node->m_parent = 0; - m_first_node = 0; - } - - //! Prepends a new attribute to the node. - //! \param attribute Attribute to prepend. - void prepend_attribute(xml_attribute *attribute) { - assert(attribute && !attribute->parent()); - if (first_attribute()) { - attribute->m_next_attribute = m_first_attribute; - m_first_attribute->m_prev_attribute = attribute; - } else { - attribute->m_next_attribute = 0; - m_last_attribute = attribute; - } - m_first_attribute = attribute; - attribute->m_parent = this; - attribute->m_prev_attribute = 0; - } - - //! Appends a new attribute to the node. - //! \param attribute Attribute to append. - void append_attribute(xml_attribute *attribute) { - assert(attribute && !attribute->parent()); - if (first_attribute()) { - attribute->m_prev_attribute = m_last_attribute; - m_last_attribute->m_next_attribute = attribute; - } else { - attribute->m_prev_attribute = 0; - m_first_attribute = attribute; - } - m_last_attribute = attribute; - attribute->m_parent = this; - attribute->m_next_attribute = 0; - } - - //! Inserts a new attribute at specified place inside the node. - //! All attributes after and including the specified attribute are moved one position back. - //! \param where Place where to insert the attribute, or 0 to insert at the back. - //! \param attribute Attribute to insert. - void insert_attribute(xml_attribute *where, - xml_attribute *attribute) { - assert(!where || where->parent() == this); - assert(attribute && !attribute->parent()); - if (where == m_first_attribute) - prepend_attribute(attribute); - else if (where == 0) - append_attribute(attribute); - else { - attribute->m_prev_attribute = where->m_prev_attribute; - attribute->m_next_attribute = where; - where->m_prev_attribute->m_next_attribute = attribute; - where->m_prev_attribute = attribute; - attribute->m_parent = this; - } - } - - //! Removes first attribute of the node. - //! If node has no attributes, behaviour is undefined. - //! Use first_attribute() to test if node has attributes. - void remove_first_attribute() { - assert(first_attribute()); - xml_attribute *attribute = m_first_attribute; - if (attribute->m_next_attribute) { - attribute->m_next_attribute->m_prev_attribute = 0; - } else m_last_attribute = 0; - attribute->m_parent = 0; - m_first_attribute = attribute->m_next_attribute; - } - - //! Removes last attribute of the node. - //! If node has no attributes, behaviour is undefined. - //! Use first_attribute() to test if node has attributes. - void remove_last_attribute() { - assert(first_attribute()); - xml_attribute *attribute = m_last_attribute; - if (attribute->m_prev_attribute) { - attribute->m_prev_attribute->m_next_attribute = 0; - m_last_attribute = attribute->m_prev_attribute; - } else m_first_attribute = 0; - attribute->m_parent = 0; - } - - //! Removes specified attribute from node. - //! \param where Pointer to attribute to be removed. - void remove_attribute(xml_attribute *where) { - assert(first_attribute() && where->parent() == this); - if (where == m_first_attribute) - remove_first_attribute(); - else if (where == m_last_attribute) - remove_last_attribute(); - else { - where->m_prev_attribute->m_next_attribute = where->m_next_attribute; - where->m_next_attribute->m_prev_attribute = where->m_prev_attribute; - where->m_parent = 0; - } - } - - //! Removes all attributes of node. - void remove_all_attributes() { - for (xml_attribute *attribute = first_attribute(); attribute; - attribute = attribute->m_next_attribute) - attribute->m_parent = 0; - m_first_attribute = 0; - } - -private: - - /////////////////////////////////////////////////////////////////////////// - // Restrictions - - // No copying - xml_node(const xml_node &); - void operator =(const xml_node &); - - /////////////////////////////////////////////////////////////////////////// - // Data members - - // Note that some of the pointers below have UNDEFINED values if certain other pointers are 0. - // This is required for maximum performance, as it allows the parser to omit initialization of - // unneded/redundant values. - // - // The rules are as follows: - // 1. first_node and first_attribute contain valid pointers, or 0 if node has no children/attributes respectively - // 2. last_node and last_attribute are valid only if node has at least one child/attribute respectively, otherwise they contain garbage - // 3. prev_sibling and next_sibling are valid only if node has a parent, otherwise they contain garbage - - node_type m_type; // Type of node; always valid - xml_node *m_first_node; // Pointer to first child node, or 0 if none; always valid - xml_node *m_last_node; // Pointer to last child node, or 0 if none; this value is only valid if m_first_node is non-zero - xml_attribute *m_first_attribute; // Pointer to first attribute of node, or 0 if none; always valid - xml_attribute *m_last_attribute; // Pointer to last attribute of node, or 0 if none; this value is only valid if m_first_attribute is non-zero - xml_node *m_prev_sibling; // Pointer to previous sibling of node, or 0 if none; this value is only valid if m_parent is non-zero - xml_node *m_next_sibling; // Pointer to next sibling of node, or 0 if none; this value is only valid if m_parent is non-zero - -}; - -/////////////////////////////////////////////////////////////////////////// -// XML document - -//! This class represents root of the DOM hierarchy. -//! It is also an xml_node and a memory_pool through public inheritance. -//! Use parse() function to build a DOM tree from a zero-terminated XML text string. -//! parse() function allocates memory for nodes and attributes by using functions of xml_document, -//! which are inherited from memory_pool. -//! To access root node of the document, use the document itself, as if it was an xml_node. -//! \param Ch Character type to use. -template -class xml_document: - public xml_node, public memory_pool { - -public: - - //! Constructs empty XML document - xml_document() : - xml_node(node_document) { - } - - //! Parses zero-terminated XML string according to given flags. - //! Passed string will be modified by the parser, unless rapidxml::parse_non_destructive flag is used. - //! The string must persist for the lifetime of the document. - //! In case of error, rapidxml::parse_error exception will be thrown. - //!

- //! If you want to parse contents of a file, you must first load the file into the memory, and pass pointer to its beginning. - //! Make sure that data is zero-terminated. - //!

- //! Document can be parsed into multiple times. - //! Each new call to parse removes previous nodes and attributes (if any), but does not clear memory pool. - //! \param text XML data to parse; pointer is non-const to denote fact that this data may be modified by the parser. - template - void parse(Ch *text) { - assert(text); - - // Remove current contents - this->remove_all_nodes(); - this->remove_all_attributes(); - - // Parse BOM, if any - parse_bom(text); - - // Parse children - while (1) { - // Skip whitespace before node - skip(text); - if (*text == 0) break; - - // Parse and append new child - if (*text == Ch('<')) { - ++text; // Skip '<' - if (xml_node *node = parse_node(text)) - this->append_node(node); - } else - RAPIDXML_PARSE_ERROR("expected <", text); - } - - } - - //! Clears the document by deleting all nodes and clearing the memory pool. - //! All nodes owned by document pool are destroyed. - void clear() { - this->remove_all_nodes(); - this->remove_all_attributes(); - memory_pool::clear(); - } - -private: - - /////////////////////////////////////////////////////////////////////// - // Internal character utility functions - - // Detect whitespace character - struct whitespace_pred { - static unsigned char test(Ch ch) { - return internal::lookup_tables<0>::lookup_whitespace[static_cast(ch)]; - } - }; - - // Detect node name character - struct node_name_pred { - static unsigned char test(Ch ch) { - return internal::lookup_tables<0>::lookup_node_name[static_cast(ch)]; - } - }; - - // Detect attribute name character - struct attribute_name_pred { - static unsigned char test(Ch ch) { - return internal::lookup_tables<0>::lookup_attribute_name[static_cast(ch)]; - } - }; - - // Detect text character (PCDATA) - struct text_pred { - static unsigned char test(Ch ch) { - return internal::lookup_tables<0>::lookup_text[static_cast(ch)]; - } - }; - - // Detect text character (PCDATA) that does not require processing - struct text_pure_no_ws_pred { - static unsigned char test(Ch ch) { - return internal::lookup_tables<0>::lookup_text_pure_no_ws[static_cast(ch)]; - } - }; - - // Detect text character (PCDATA) that does not require processing - struct text_pure_with_ws_pred { - static unsigned char test(Ch ch) { - return internal::lookup_tables<0>::lookup_text_pure_with_ws[static_cast(ch)]; - } - }; - - // Detect attribute value character - template - struct attribute_value_pred { - static unsigned char test(Ch ch) { - if (Quote == Ch('\'')) - return internal::lookup_tables<0>::lookup_attribute_data_1[static_cast(ch)]; - if (Quote == Ch('\"')) - return internal::lookup_tables<0>::lookup_attribute_data_2[static_cast(ch)]; - return 0; // Should never be executed, to avoid warnings on Comeau - } - }; - - // Detect attribute value character - template - struct attribute_value_pure_pred { - static unsigned char test(Ch ch) { - if (Quote == Ch('\'')) - return internal::lookup_tables<0>::lookup_attribute_data_1_pure[static_cast(ch)]; - if (Quote == Ch('\"')) - return internal::lookup_tables<0>::lookup_attribute_data_2_pure[static_cast(ch)]; - return 0; // Should never be executed, to avoid warnings on Comeau - } - }; - - // Insert coded character, using UTF8 or 8-bit ASCII - template - static void insert_coded_character(Ch *&text, unsigned long code) { - if (Flags & parse_no_utf8) { - // Insert 8-bit ASCII character - // Todo: possibly verify that code is less than 256 and use replacement char otherwise? - text[0] = static_cast(code); - text += 1; - } else { - // Insert UTF8 sequence - if (code < 0x80) // 1 byte sequence - { - text[0] = static_cast(code); - text += 1; - } else if (code < 0x800) // 2 byte sequence - { - text[1] = static_cast((code | 0x80) & 0xBF); - code >>= 6; - text[0] = static_cast(code | 0xC0); - text += 2; - } else if (code < 0x10000) // 3 byte sequence - { - text[2] = static_cast((code | 0x80) & 0xBF); - code >>= 6; - text[1] = static_cast((code | 0x80) & 0xBF); - code >>= 6; - text[0] = static_cast(code | 0xE0); - text += 3; - } else if (code < 0x110000) // 4 byte sequence - { - text[3] = static_cast((code | 0x80) & 0xBF); - code >>= 6; - text[2] = static_cast((code | 0x80) & 0xBF); - code >>= 6; - text[1] = static_cast((code | 0x80) & 0xBF); - code >>= 6; - text[0] = static_cast(code | 0xF0); - text += 4; - } else // Invalid, only codes up to 0x10FFFF are allowed in Unicode - { - RAPIDXML_PARSE_ERROR("invalid numeric character entity", text); - } - } - } - - // Skip characters until predicate evaluates to true - template - static void skip(Ch *&text) { - Ch *tmp = text; - while (StopPred::test(*tmp)) - ++tmp; - text = tmp; - } - - // Skip characters until predicate evaluates to true while doing the following: - // - replacing XML character entity references with proper characters (' & " < > &#...;) - // - condensing whitespace sequences to single space character - template - static Ch *skip_and_expand_character_refs(Ch *&text) { - // If entity translation, whitespace condense and whitespace trimming is disabled, use plain skip - if (Flags & parse_no_entity_translation - && !(Flags & parse_normalize_whitespace) - && !(Flags & parse_trim_whitespace)) { - skip(text); - return text; - } - - // Use simple skip until first modification is detected - skip(text); - - // Use translation skip - Ch *src = text; - Ch *dest = src; - while (StopPred::test(*src)) { - // If entity translation is enabled - if (!(Flags & parse_no_entity_translation)) { - // Test if replacement is needed - if (src[0] == Ch('&')) { - switch (src[1]) { - - // & ' - case Ch('a'): - if (src[2] == Ch('m') && src[3] == Ch('p') && src[4] == Ch(';')) { - *dest = Ch('&'); - ++dest; - src += 5; - continue; - } - if (src[2] == Ch('p') && src[3] == Ch('o') && src[4] == Ch('s') - && src[5] == Ch(';')) { - *dest = Ch('\''); - ++dest; - src += 6; - continue; - } - break; - - // " - case Ch('q'): - if (src[2] == Ch('u') && src[3] == Ch('o') && src[4] == Ch('t') - && src[5] == Ch(';')) { - *dest = Ch('"'); - ++dest; - src += 6; - continue; - } - break; - - // > - case Ch('g'): - if (src[2] == Ch('t') && src[3] == Ch(';')) { - *dest = Ch('>'); - ++dest; - src += 4; - continue; - } - break; - - // < - case Ch('l'): - if (src[2] == Ch('t') && src[3] == Ch(';')) { - *dest = Ch('<'); - ++dest; - src += 4; - continue; - } - break; - - // &#...; - assumes ASCII - case Ch('#'): - if (src[2] == Ch('x')) { - unsigned long code = 0; - src += 3; // Skip &#x - while (1) { - unsigned char digit = - internal::lookup_tables<0>::lookup_digits[static_cast(*src)]; - if (digit == 0xFF) break; - code = code * 16 + digit; - ++src; - } - insert_coded_character(dest, code); // Put character in output - } else { - unsigned long code = 0; - src += 2; // Skip &# - while (1) { - unsigned char digit = - internal::lookup_tables<0>::lookup_digits[static_cast(*src)]; - if (digit == 0xFF) break; - code = code * 10 + digit; - ++src; - } - insert_coded_character(dest, code); // Put character in output - } - if (*src == Ch(';')) - ++src; - else - RAPIDXML_PARSE_ERROR("expected ;", src); - continue; - - // Something else - default: - // Ignore, just copy '&' verbatim - break; - - } - } - } - - // If whitespace condensing is enabled - if (Flags & parse_normalize_whitespace) { - // Test if condensing is needed - if (whitespace_pred::test(*src)) { - *dest = Ch(' '); - ++dest; // Put single space in dest - ++src; // Skip first whitespace char - // Skip remaining whitespace chars - while (whitespace_pred::test(*src)) - ++src; - continue; - } - } - - // No replacement, only copy character - *dest++ = *src++; - - } - - // Return new end - text = src; - return dest; - - } - - /////////////////////////////////////////////////////////////////////// - // Internal parsing functions - - // Parse BOM, if any - template - void parse_bom(Ch *&text) { - // UTF-8? - if (static_cast(text[0]) == 0xEF - && static_cast(text[1]) == 0xBB - && static_cast(text[2]) == 0xBF) { - text += 3; // Skup utf-8 bom - } - } - - // Parse XML declaration ( - xml_node *parse_xml_declaration(Ch *&text) { - // If parsing of declaration is disabled - if (!(Flags & parse_declaration_node)) { - // Skip until end of declaration - while (text[0] != Ch('?') || text[1] != Ch('>')) { - if (!text[0]) - RAPIDXML_PARSE_ERROR("unexpected end of data", text); - ++text; - } - text += 2; // Skip '?>' - return 0; - } - - // Create declaration - xml_node *declaration = this->allocate_node(node_declaration); - - // Skip whitespace before attributes or ?> - skip(text); - - // Parse declaration attributes - parse_node_attributes(text, declaration); - - // Skip ?> - if (text[0] != Ch('?') || text[1] != Ch('>')) - RAPIDXML_PARSE_ERROR("expected ?>", text); - text += 2; - - return declaration; - } - - // Parse XML comment (' - return 0; // Do not produce comment node - } - - // Remember value start - Ch *value = text; - - // Skip until end of comment - while (text[0] != Ch('-') || text[1] != Ch('-') || text[2] != Ch('>')) { - if (!text[0]) - RAPIDXML_PARSE_ERROR("unexpected end of data", text); - ++text; - } - - // Create comment node - xml_node *comment = this->allocate_node(node_comment); - comment->value(value, text - value); - - // Place zero terminator after comment value - if (!(Flags & parse_no_string_terminators)) *text = Ch('\0'); - - text += 3; // Skip '-->' - return comment; - } - - // Parse DOCTYPE - template - xml_node *parse_doctype(Ch *&text) { - // Remember value start - Ch *value = text; - - // Skip to > - while (*text != Ch('>')) { - // Determine character type - switch (*text) { - - // If '[' encountered, scan for matching ending ']' using naive algorithm with depth - // This works for all W3C test files except for 2 most wicked - case Ch('['): { - ++text; // Skip '[' - int depth = 1; - while (depth > 0) { - switch (*text) { - case Ch('['): - ++depth; - break; - case Ch(']'): - --depth; - break; - case 0: - RAPIDXML_PARSE_ERROR("unexpected end of data", text); - } - ++text; - } - break; - } - - // Error on end of text - case Ch('\0'): - RAPIDXML_PARSE_ERROR("unexpected end of data", text); - - // Other character, skip it - default: - ++text; - - } - } - - // If DOCTYPE nodes enabled - if (Flags & parse_doctype_node) { - // Create a new doctype node - xml_node *doctype = this->allocate_node(node_doctype); - doctype->value(value, text - value); - - // Place zero terminator after value - if (!(Flags & parse_no_string_terminators)) *text = Ch('\0'); - - text += 1; // skip '>' - return doctype; - } else { - text += 1; // skip '>' - return 0; - } - - } - - // Parse PI - template - xml_node *parse_pi(Ch *&text) { - // If creation of PI nodes is enabled - if (Flags & parse_pi_nodes) { - // Create pi node - xml_node *pi = this->allocate_node(node_pi); - - // Extract PI target name - Ch *name = text; - skip(text); - if (text == name) - RAPIDXML_PARSE_ERROR("expected PI target", text); - pi->name(name, text - name); - - // Skip whitespace between pi target and pi - skip(text); - - // Remember start of pi - Ch *value = text; - - // Skip to '?>' - while (text[0] != Ch('?') || text[1] != Ch('>')) { - if (*text == Ch('\0')) - RAPIDXML_PARSE_ERROR("unexpected end of data", text); - ++text; - } - - // Set pi value (verbatim, no entity expansion or whitespace normalization) - pi->value(value, text - value); - - // Place zero terminator after name and value - if (!(Flags & parse_no_string_terminators)) { - pi->name()[pi->name_size()] = Ch('\0'); - pi->value()[pi->value_size()] = Ch('\0'); - } - - text += 2; // Skip '?>' - return pi; - } else { - // Skip to '?>' - while (text[0] != Ch('?') || text[1] != Ch('>')) { - if (*text == Ch('\0')) - RAPIDXML_PARSE_ERROR("unexpected end of data", text); - ++text; - } - text += 2; // Skip '?>' - return 0; - } - } - - // Parse and append data - // Return character that ends data. - // This is necessary because this character might have been overwritten by a terminating 0 - template - Ch parse_and_append_data(xml_node *node, Ch *&text, Ch *contents_start) { - // Backup to contents start if whitespace trimming is disabled - if (!(Flags & parse_trim_whitespace)) text = contents_start; - - // Skip until end of data - Ch *value = text, *end; - if (Flags & parse_normalize_whitespace) - end = skip_and_expand_character_refs(text); - else end = skip_and_expand_character_refs(text); - - // Trim trailing whitespace if flag is set; leading was already trimmed by whitespace skip after > - if (Flags & parse_trim_whitespace) { - if (Flags & parse_normalize_whitespace) { - // Whitespace is already condensed to single space characters by skipping function, so just trim 1 char off the end - if (*(end - 1) == Ch(' ')) --end; - } else { - // Backup until non-whitespace character is found - while (whitespace_pred::test(*(end - 1))) - --end; - } - } - - // If characters are still left between end and value (this test is only necessary if normalization is enabled) - // Create new data node - if (!(Flags & parse_no_data_nodes)) { - xml_node *data = this->allocate_node(node_data); - data->value(value, end - value); - node->append_node(data); - } - - // Add data to parent node if no data exists yet - if (!(Flags & parse_no_element_values)) - if (*node->value() == Ch('\0')) node->value(value, end - value); - - // Place zero terminator after value - if (!(Flags & parse_no_string_terminators)) { - Ch ch = *text; - *end = Ch('\0'); - return ch; // Return character that ends data; this is required because zero terminator overwritten it - } - - // Return character that ends data - return *text; - } - - // Parse CDATA - template - xml_node *parse_cdata(Ch *&text) { - // If CDATA is disabled - if (Flags & parse_no_data_nodes) { - // Skip until end of cdata - while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>')) { - if (!text[0]) - RAPIDXML_PARSE_ERROR("unexpected end of data", text); - ++text; - } - text += 3; // Skip ]]> - return 0; // Do not produce CDATA node - } - - // Skip until end of cdata - Ch *value = text; - while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>')) { - if (!text[0]) - RAPIDXML_PARSE_ERROR("unexpected end of data", text); - ++text; - } - - // Create new cdata node - xml_node *cdata = this->allocate_node(node_cdata); - cdata->value(value, text - value); - - // Place zero terminator after value - if (!(Flags & parse_no_string_terminators)) *text = Ch('\0'); - - text += 3; // Skip ]]> - return cdata; - } - - // Parse element node - template - xml_node *parse_element(Ch *&text) { - // Create element node - xml_node *element = this->allocate_node(node_element); - - // Extract element name - Ch *name = text; - skip(text); - if (text == name) - RAPIDXML_PARSE_ERROR("expected element name", text); - element->name(name, text - name); - - // Skip whitespace between element name and attributes or > - skip(text); - - // Parse attributes, if any - parse_node_attributes(text, element); - - // Determine ending type - if (*text == Ch('>')) { - ++text; - parse_node_contents(text, element); - } else if (*text == Ch('/')) { - ++text; - if (*text != Ch('>')) - RAPIDXML_PARSE_ERROR("expected >", text); - ++text; - } else - RAPIDXML_PARSE_ERROR("expected >", text); - - // Place zero terminator after name - if (!(Flags & parse_no_string_terminators)) - element->name()[element->name_size()] = Ch('\0'); - - // Return parsed element - return element; - } - - // Determine node type, and parse it - template - xml_node *parse_node(Ch *&text) { - // Parse proper node type - switch (text[0]) { - - // <... - default: - // Parse and append element node - return parse_element(text); - - // (text); - } else { - // Parse PI - return parse_pi(text); - } - - // (text); - } - break; - - // (text); - } - break; - - // (text); - } - - } // switch - - // Attempt to skip other, unrecognized node types starting with ')) { - if (*text == 0) - RAPIDXML_PARSE_ERROR("unexpected end of data", text); - ++text; - } - ++text; // Skip '>' - return 0; // No node recognized - - } - } - - // Parse contents of the node - children, data etc. - template - void parse_node_contents(Ch *&text, xml_node *node) { - // For all children and text - while (1) { - // Skip whitespace between > and node contents - Ch *contents_start = text; // Store start of node contents before whitespace is skipped - skip(text); - Ch next_char = *text; - - // After data nodes, instead of continuing the loop, control jumps here. - // This is because zero termination inside parse_and_append_data() function - // would wreak havoc with the above code. - // Also, skipping whitespace after data nodes is unnecessary. - after_data_node: - - // Determine what comes next: node closing, child node, data node, or 0? - switch (next_char) { - - // Node closing or child node - case Ch('<'): - if (text[1] == Ch('/')) { - // Node closing - text += 2; // Skip '(text); - if (!internal::compare(node->name(), node->name_size(), - closing_name, text - closing_name, true)) - RAPIDXML_PARSE_ERROR("invalid closing tag name", text); - } else { - // No validation, just skip name - skip(text); - } - // Skip remaining whitespace after node name - skip(text); - if (*text != Ch('>')) - RAPIDXML_PARSE_ERROR("expected >", text); - ++text; // Skip '>' - return; // Node closed, finished parsing contents - } else { - // Child node - ++text; // Skip '<' - if (xml_node *child = parse_node(text)) - node->append_node(child); - } - break; - - // End of data - error - case Ch('\0'): - RAPIDXML_PARSE_ERROR("unexpected end of data", text); - - // Data node - default: - next_char = parse_and_append_data(node, text, contents_start); - goto after_data_node; - // Bypass regular processing after data nodes - - } - } - } - - // Parse XML attributes of the node - template - void parse_node_attributes(Ch *&text, xml_node *node) { - // For all attributes - while (attribute_name_pred::test(*text)) { - // Extract attribute name - Ch *name = text; - ++text; // Skip first character of attribute name - skip(text); - if (text == name) - RAPIDXML_PARSE_ERROR("expected attribute name", name); - - // Create new attribute - xml_attribute *attribute = this->allocate_attribute(); - attribute->name(name, text - name); - node->append_attribute(attribute); - - // Skip whitespace after attribute name - skip(text); - - // Skip = - if (*text != Ch('=')) - RAPIDXML_PARSE_ERROR("expected =", text); - ++text; - - // Add terminating zero after name - if (!(Flags & parse_no_string_terminators)) - attribute->name()[attribute->name_size()] = 0; - - // Skip whitespace after = - skip(text); - - // Skip quote and remember if it was ' or " - Ch quote = *text; - if (quote != Ch('\'') && quote != Ch('"')) - RAPIDXML_PARSE_ERROR("expected ' or \"", text); - ++text; - - // Extract attribute value and expand char refs in it - Ch *value = text, *end; - const int AttFlags = Flags & ~parse_normalize_whitespace; // No whitespace normalization in attributes - if (quote == Ch('\'')) - end = skip_and_expand_character_refs, - attribute_value_pure_pred, AttFlags>(text); - else end = skip_and_expand_character_refs, - attribute_value_pure_pred, AttFlags>(text); - - // Set attribute value - attribute->value(value, end - value); - - // Make sure that end quote is present - if (*text != quote) - RAPIDXML_PARSE_ERROR("expected ' or \"", text); - ++text; // Skip quote - - // Add terminating zero after value - if (!(Flags & parse_no_string_terminators)) - attribute->value()[attribute->value_size()] = 0; - - // Skip whitespace after attribute value - skip(text); - } - } - -}; - -//! \cond internal -namespace internal { - -// Whitespace (space \n \r \t) -template -const unsigned char lookup_tables::lookup_whitespace[256] = { -// 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, // 0 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1 - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 5 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 7 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // C - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // D - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // E - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // F - }; - -// Node name (anything but space \n \r \t / > ? \0) -template -const unsigned char lookup_tables::lookup_node_name[256] = { -// 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 2 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, // 3 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F - }; - -// Text (i.e. PCDATA) (anything but < \0) -template -const unsigned char lookup_tables::lookup_text[256] = { -// 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F - }; - -// Text (i.e. PCDATA) that does not require processing when ws normalization is disabled -// (anything but < \0 &) -template -const unsigned char lookup_tables::lookup_text_pure_no_ws[256] = { -// 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 - 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F - }; - -// Text (i.e. PCDATA) that does not require processing when ws normalizationis is enabled -// (anything but < \0 & space \n \r \t) -template -const unsigned char lookup_tables::lookup_text_pure_with_ws[256] = { -// 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 - 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F - }; - -// Attribute name (anything but space \n \r \t / < > = ? ! \0) -template -const unsigned char lookup_tables::lookup_attribute_name[256] = { -// 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 - 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 2 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, // 3 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F - }; - -// Attribute data with single quote (anything but ' \0) -template -const unsigned char lookup_tables::lookup_attribute_data_1[256] = { -// 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 - 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, // 2 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F - }; - -// Attribute data with single quote that does not require processing (anything but ' \0 &) -template -const unsigned char lookup_tables::lookup_attribute_data_1_pure[256] = { -// 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 - 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, // 2 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F - }; - -// Attribute data with double quote (anything but " \0) -template -const unsigned char lookup_tables::lookup_attribute_data_2[256] = { -// 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 - 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F - }; - -// Attribute data with double quote that does not require processing (anything but " \0 &) -template -const unsigned char lookup_tables::lookup_attribute_data_2_pure[256] = { -// 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 - 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F - }; - -// Digits (dec and hex, 255 denotes end of numeric character reference) -template -const unsigned char lookup_tables::lookup_digits[256] = { - // 0 1 2 3 4 5 6 7 8 9 A B C D E F - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, // 0 - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, // 1 - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, // 2 - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, - 255, // 3 - 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, - 255, // 4 - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, // 5 - 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, - 255, // 6 - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, // 7 - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, // 8 - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, // 9 - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, // A - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, // B - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, // C - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, // D - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, // E - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255 // F - }; - -// Upper case conversion -template -const unsigned char lookup_tables::lookup_upcase[256] = { - // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A B C D E F - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, // 0 - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 31, // 1 - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, - 47, // 2 - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, - 63, // 3 - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, - 79, // 4 - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, - 95, // 5 - 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, - 79, // 6 - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123, 124, 125, 126, - 127, // 7 - 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, - 143, // 8 - 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, - 159, // 9 - 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, - 175, // A - 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, - 191, // B - 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, - 207, // C - 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, - 223, // D - 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, - 239, // E - 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, - 255 // F - }; -} -//! \endcond - -} - -// Undefine internal macros -#undef RAPIDXML_PARSE_ERROR - -// On MSVC, restore warnings state -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#endif -- 2.7.4 From 0c0bd38459875531019f80eb3701c26bc8b30139 Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Fri, 1 Dec 2017 14:27:42 +0100 Subject: [PATCH 02/16] Add Kerberos MIT license for cc_sha1.c Change-Id: I90800e874a7a0fba35d9410abf90349a01461907 --- LICENSE.Krb5-MIT | 86 ++++++++++++++++++++++++++++++++++++++++++++ packaging/tef-simulator.spec | 1 + 2 files changed, 87 insertions(+) create mode 100644 LICENSE.Krb5-MIT diff --git a/LICENSE.Krb5-MIT b/LICENSE.Krb5-MIT new file mode 100644 index 0000000..8fd7b88 --- /dev/null +++ b/LICENSE.Krb5-MIT @@ -0,0 +1,86 @@ +Copyright (C) 1985-2017 by the Massachusetts Institute of Technology. + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Downloading of this software may constitute an export of cryptographic +software from the United States of America that is subject to the +United States Export Administration Regulations (EAR), 15 CFR 730-774. +Additional laws or regulations may apply. It is the responsibility of +the person or entity contemplating export to comply with all +applicable export laws and regulations, including obtaining any +required license from the U.S. government. + +The U.S. government prohibits export of encryption source code to +certain countries and individuals, including, but not limited to, the +countries of Cuba, Iran, North Korea, Sudan, Syria, and residents and +nationals of those countries. + +Documentation components of this software distribution are licensed +under a Creative Commons Attribution-ShareAlike 3.0 Unported License. +(http://creativecommons.org/licenses/by-sa/3.0/) + +Individual source code files are copyright MIT, Cygnus Support, +Novell, OpenVision Technologies, Oracle, Red Hat, Sun Microsystems, +FundsXpress, and others. + +Project Athena, Athena, Athena MUSE, Discuss, Hesiod, Kerberos, Moira, +and Zephyr are trademarks of the Massachusetts Institute of Technology +(MIT). No commercial use of these trademarks may be made without +prior written permission of MIT. + +"Commercial use" means use of a name in a product or other for-profit +manner. It does NOT prevent a commercial firm from referring to the +MIT trademarks in order to convey information (although in doing so, +recognition of their trademark status should be given). + +====================================================================== + +Portions of "ssflib/dep/cryptocore/source/base/cc_sha1.c" have the following copyright: + + Copyright (C) 1998 by the FundsXpress, INC. + + All rights reserved. + + Export of this software from the United States of America may + require a specific license from the United States Government. + It is the responsibility of any person or organization + contemplating export to obtain such a license before exporting. + + WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + distribute this software and its documentation for any purpose and + without fee is hereby granted, provided that the above copyright + notice appear in all copies and that both that copyright notice and + this permission notice appear in supporting documentation, and that + the name of FundsXpress. not be used in advertising or publicity + pertaining to distribution of the software without specific, + written prior permission. FundsXpress makes no representations + about the suitability of this software for any purpose. It is + provided "as is" without express or implied warranty. + + THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + diff --git a/packaging/tef-simulator.spec b/packaging/tef-simulator.spec index dc363d8..2be2c70 100644 --- a/packaging/tef-simulator.spec +++ b/packaging/tef-simulator.spec @@ -111,6 +111,7 @@ fi %files -n %{name} %license LICENSE %license LICENSE.MIT +%license LICENSE.Krb5-MIT %manifest tef-simulator.manifest %attr(111,security_fw,security_fw) %{bin_dir}/tef-simulator-daemon %{lib_dir}/libtef-simulator-ssflib.so -- 2.7.4 From 176434ac0a51d5356ad218991c57b49c0f186177 Mon Sep 17 00:00:00 2001 From: Krzysztof Dynowski Date: Thu, 7 Dec 2017 16:32:46 +0100 Subject: [PATCH 03/16] fix simulator libteec link options Change-Id: I7ef51f6bd117f86b353d201b6f4af4ea14022eca --- TEECLib/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/TEECLib/CMakeLists.txt b/TEECLib/CMakeLists.txt index c153bfa..c5dd7e2 100644 --- a/TEECLib/CMakeLists.txt +++ b/TEECLib/CMakeLists.txt @@ -33,6 +33,7 @@ ADD_LIBRARY(${TARGET_TEF_SIMULATOR_TEEC_LIB} SHARED ${TEEC_LIB_SOURCES} ) SET_TARGET_PROPERTIES(${TARGET_TEF_SIMULATOR_TEEC_LIB} PROPERTIES LIBRARY_OUTPUT_NAME teec) +SET_PROPERTY(TARGET ${TARGET_TEF_SIMULATOR_TEEC_LIB} APPEND PROPERTY LINK_FLAGS "-Wl,-Bsymbolic") ADD_DEPENDENCIES(${TARGET_TEF_SIMULATOR_TEEC_LIB} ${TARGET_TEF_SIMULATOR_OSAL} -- 2.7.4 From 7aec1bcbc9e9c4b067dc0602908a071d73f0e5a8 Mon Sep 17 00:00:00 2001 From: Krzysztof Dynowski Date: Mon, 4 Dec 2017 17:49:08 +0100 Subject: [PATCH 04/16] fix TA paths, use unique_ptr for memory managment Using unique_ptr requires -std=c++1y compiler flag Change-Id: I463ed5616e623f4362906e469e134fee3679f7a2 --- CMakeLists.txt | 2 +- TEECLib/src/teec_api.c | 12 +++--- TEECLib/src/teec_connection.c | 8 ++-- TEEStub/PropertyAccess/TEEProperty.cpp | 2 +- TEEStub/teestubmain.cpp | 5 ++- include/include/config.h | 19 ++++----- packaging/tef-simulator.spec | 7 +++- simulatordaemon/inc/SecurityContext.h | 2 +- simulatordaemon/src/TABinaryManager/Config.h | 31 -------------- .../src/TABinaryManager/TABinaryManager.cpp | 10 ++--- simulatordaemon/src/TABinaryManager/TAUnpack.cpp | 47 +++++++++++++--------- simulatordaemon/src/TAInstance.cpp | 2 +- ssflib/dep/swdss/source/secure_file.cpp | 5 +-- ssflib/src/ssf_client.cpp | 8 ++-- 14 files changed, 71 insertions(+), 89 deletions(-) delete mode 100644 simulatordaemon/src/TABinaryManager/Config.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 133c2ca..d0f1ceb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,7 +40,7 @@ ADD_DEFINITIONS("-DBOOST_ASIO_DISABLE_STD_ARRAY") ADD_DEFINITIONS("-D_GNU_SOURCE") -SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1y") # Set compiler warning flags # TODO uncomment these when it's cleanup time diff --git a/TEECLib/src/teec_api.c b/TEECLib/src/teec_api.c index 91f5185..e269e02 100644 --- a/TEECLib/src/teec_api.c +++ b/TEECLib/src/teec_api.c @@ -330,9 +330,11 @@ static TEEC_Result preProcessOperation(TEEC_Session *session, uint32_t i, type; // Check if Session is valid - if (session) - context = ((TEEC_SessionImp *)session->imp)->context; - else return TEEC_ERROR_BAD_PARAMETERS; + if (!session) { + LOGE(TEEC_LIB, "Bad parameters"); + return TEEC_ERROR_BAD_PARAMETERS; + } + context = ((TEEC_SessionImp *)session->imp)->context; // Check if output Operation structure is valid if (!op) @@ -377,8 +379,7 @@ static TEEC_Result preProcessOperation(TEEC_Session *session, op->paramTypes |= type << (8 * i); if (!tmpSharedMem[i]) { - result = tempSharedMemAllocate(&tmpSharedMem[i], type, - ((TEEC_SessionImp *)session->imp)->context, operation->params[i]); + result = tempSharedMemAllocate(&tmpSharedMem[i], type, context, operation->params[i]); if (result != TEEC_SUCCESS) goto cleanup; } @@ -442,6 +443,7 @@ static TEEC_Result preProcessOperation(TEEC_Session *session, break; default: + LOGE(TEEC_LIB, "Bad parameters"); result = TEEC_ERROR_BAD_PARAMETERS; goto cleanup; } diff --git a/TEECLib/src/teec_connection.c b/TEECLib/src/teec_connection.c index 8aadfc1..a5feaa4 100644 --- a/TEECLib/src/teec_connection.c +++ b/TEECLib/src/teec_connection.c @@ -25,11 +25,11 @@ * Include files *-----------------------------------------------------------------------------*/ #include "teec_connection.h" +#include /*----------------------------------------------------------------------------- * Macros *-----------------------------------------------------------------------------*/ -#define SOCKPATH "/tmp/simdaemon" /*----------------------------------------------------------------------------- * TEST MACROS @@ -61,15 +61,15 @@ int32_t connecttoServer(void) daemonsock.sun_family = AF_UNIX; - sock_path_len = strlen(SOCKPATH); - strncpy(daemonsock.sun_path, SOCKPATH, sock_path_len + 1); + sock_path_len = strlen(SIMDAEMON_SOCK_PATH); + strncpy(daemonsock.sun_path, SIMDAEMON_SOCK_PATH, sock_path_len + 1); socklen = sizeof(daemonsock); sockptr = (struct sockaddr *)&daemonsock; // Connect to Simulator Daemon if (connect(serverSocket, sockptr, socklen) == -1) { - LOGE(TEEC_LIB, "connection to simdaemon failed"); + LOGE(TEEC_LIB, "connection to simdaemon(%s) failed errno=%d", SIMDAEMON_SOCK_PATH, errno); close(serverSocket); return -1; } diff --git a/TEEStub/PropertyAccess/TEEProperty.cpp b/TEEStub/PropertyAccess/TEEProperty.cpp index ea431c2..1d3e1e2 100644 --- a/TEEStub/PropertyAccess/TEEProperty.cpp +++ b/TEEStub/PropertyAccess/TEEProperty.cpp @@ -115,7 +115,7 @@ bool TEEProperty::getNextProperty() { * @return true if property file successfully read else false */ bool TEEProperty::start() { - bool ret = readPropertyFile(string(TEE_PROP_FILE)); + bool ret = readPropertyFile(string(TEE_PROP_PATH)); currentItr = propertiesMap.begin(); return ret; } diff --git a/TEEStub/teestubmain.cpp b/TEEStub/teestubmain.cpp index 2f1f604..3b1cd3b 100644 --- a/TEEStub/teestubmain.cpp +++ b/TEEStub/teestubmain.cpp @@ -30,6 +30,7 @@ #include "TEEStubServer/TEEStubServer.h" #include #include +#include #include "log.h" /*----------------------------------------------------------------------------- @@ -49,7 +50,7 @@ boost::asio::io_service io_service; ///< io_service provides OS abstraction for void StartServer(string socketName) { try { ::unlink(socketName.c_str()); - LOGD(TEE_STUB, "Waiting on socket"); + LOGD(TEE_STUB, "Waiting on socket %s", socketName.c_str()); TEEStubServer s(io_service, socketName.c_str()); io_service.run(); } catch (std::exception& e) { @@ -107,7 +108,7 @@ int main(int argc, char* argv[]) { // Once the server is started, it exits only after the // connection is lost or gracefully disconnected. - StartServer(string("/tmp/") + string(argv[1])); + StartServer(string(TEE_TASOCK_ROOT) + string(argv[1])); LOGD(TEE_STUB, "Exiting TEEStub\n"); // Deallocate property objects if (TEE_SUCCESS == initStatus) DeInitPropertyModule(); diff --git a/include/include/config.h b/include/include/config.h index b72f61f..51752fe 100644 --- a/include/include/config.h +++ b/include/include/config.h @@ -22,14 +22,15 @@ #ifndef INCLUDE_CONFIG_H_ #define INCLUDE_CONFIG_H_ -#define TEE_PROP_FILE "/usr/bin/GPD_TEE_PROP" -#define TA_ROOT "/tmp/" -#if _ARCH_ == 32 - #define TEE_TASTORE_ROOT "/usr/lib/tastore/" -#elif _ARCH_ == 64 - #define TEE_TASTORE_ROOT "/usr/lib64/tastore/" -#else - #error "Invalid architecture was set!" -#endif +//this is ln -s to /usr/lib/tastore or /usr/lib64/tastore (see spec file) +#define TEE_TASTORE_ROOT "/opt/tastore/" + +//TEEStub must have write access in this directory (creating socket per TA) +#define TEE_TASOCK_ROOT "/tmp/" + +#define SHM_PATH "/tmp/shm" +#define SIMDAEMON_SOCK_PATH "/tmp/simdaemon" + +#define TEE_PROP_PATH "/usr/bin/GPD_TEE_PROP" #endif /* INCLUDE_CONFIG_H_ */ diff --git a/packaging/tef-simulator.spec b/packaging/tef-simulator.spec index 2be2c70..83a8df9 100644 --- a/packaging/tef-simulator.spec +++ b/packaging/tef-simulator.spec @@ -25,8 +25,8 @@ PreReq: tef-libteec %define lib_dir %{?TZ_SYS_LIB:%TZ_SYS_LIB}%{!?TZ_SYS_LIB:%_libdir} %define data_dir %{?TZ_SYS_RO_SHARE:%TZ_SYS_RO_SHARE}%{!?TZ_SYS_RO_SHARE:%_datadir} %define include_dir %{?TZ_SYS_INCLUDE:%TZ_SYS_INCLUDE}%{!?TZ_SYS_INCLUDE:%_includedir} -%define tastore_dir /opt/tastore -%define link_tastore_dir %{lib_dir}/tastore +%define tastore_dir %{lib_dir}/tastore +%define link_tastore_dir /opt/tastore %define build_bin_dir %{buildroot}%{bin_dir} %define build_lib_dir %{buildroot}%{lib_dir} @@ -97,6 +97,9 @@ cp include/include/LICENSE LICENSE.BSD %pre %post +rm -f %{link_tastore_dir} +mkdir -p %{link_tastore_dir} +rmdir %{link_tastore_dir} ln -sf %{tastore_dir} %{link_tastore_dir} tef-update.sh simulator systemctl enable tef-simulator diff --git a/simulatordaemon/inc/SecurityContext.h b/simulatordaemon/inc/SecurityContext.h index 2008a57..645a110 100644 --- a/simulatordaemon/inc/SecurityContext.h +++ b/simulatordaemon/inc/SecurityContext.h @@ -26,7 +26,7 @@ #include #include "log.h" -#include "config.h" +#include #include #define TA_LOCAL_PATH "/res/tee" diff --git a/simulatordaemon/src/TABinaryManager/Config.h b/simulatordaemon/src/TABinaryManager/Config.h deleted file mode 100644 index 0bd4c64..0000000 --- a/simulatordaemon/src/TABinaryManager/Config.h +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Copyright (c) 2015-2017 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file - * @author CHERYL (cb) (cheryl.b@samsung.com) - * @brief Configuration details - */ - -#ifndef CONFIG_H_ -#define CONFIG_H_ - -/*----------------------------------------------------------------------------- - * MACROS - *-----------------------------------------------------------------------------*/ -#define TA_STORE_PATH "/usr/lib/tastore/" - -#endif /* CONFIG_H_ */ diff --git a/simulatordaemon/src/TABinaryManager/TABinaryManager.cpp b/simulatordaemon/src/TABinaryManager/TABinaryManager.cpp index 4561b2e..298a76d 100644 --- a/simulatordaemon/src/TABinaryManager/TABinaryManager.cpp +++ b/simulatordaemon/src/TABinaryManager/TABinaryManager.cpp @@ -25,7 +25,7 @@ * Include files *-----------------------------------------------------------------------------*/ #include "TABinaryManager.h" -#include "Config.h" +#include #include #include #include @@ -167,7 +167,7 @@ bool TABinaryManager::initTA(const string &uuid) { bool res = false; StructBinaryInfo info; - if (boost::filesystem::exists(TA_STORE_PATH + uuid)) { + if (boost::filesystem::exists(TEE_TASTORE_ROOT + uuid)) { pthread_mutex_lock(&taLock); try { if (unpackBinary(uuid, info)) { @@ -248,11 +248,11 @@ void TABinaryManager::decryptImage(StructBinaryInfo& info) { bool TABinaryManager::unpackBinary(const string &uuid, StructBinaryInfo& info) { TAUnpack* unpacker = TAUnpack::getInstance(); bool ret = false; - if (0 == unpacker->unpackTA(string(TA_STORE_PATH), uuid)) { + if (0 == unpacker->unpackTA(string(TEE_TASTORE_ROOT), uuid)) { LOGD(SIM_DAEMON, "Unpacked, filling info"); // 1. Set binary info - info.path = string(TA_STORE_PATH)+ uuid; - info.extractpath = string(TA_STORE_PATH) + uuid + "-ext/"; + info.path = string(TEE_TASTORE_ROOT)+ uuid; + info.extractpath = string(TEE_TASTORE_ROOT) + uuid + "-ext/"; info.imagePath = info.extractpath + uuid + ".image"; info.manifestPath = info.extractpath + uuid + ".manifest"; // 2. Parse manifest and store results diff --git a/simulatordaemon/src/TABinaryManager/TAUnpack.cpp b/simulatordaemon/src/TABinaryManager/TAUnpack.cpp index 01a4a32..5279024 100644 --- a/simulatordaemon/src/TABinaryManager/TAUnpack.cpp +++ b/simulatordaemon/src/TABinaryManager/TAUnpack.cpp @@ -27,10 +27,12 @@ #include "TAUnpack.h" #include #include +#include #include #include #include #include +#include #include using namespace std; @@ -88,40 +90,45 @@ int TAUnpack::unpackTA(string path, string uuid) { } // 2. Verify header if (SECURITY_HEADER_MAGIC1 == packageHeader.magic1 && - SECURITY_HEADER_MAGIC2 == packageHeader.magic2) { + SECURITY_HEADER_MAGIC2 == packageHeader.magic2) { + string imageFile = extract_dir_path + uuid + ".image"; + string manifestFile = extract_dir_path + uuid + ".manifest"; + unlink(imageFile.c_str()); + unlink(manifestFile.c_str()); + // 3. Read image and write to FS tapackage.seekg(packageHeader.image_offset); - char *imagedump = new char[packageHeader.image_size]; - tapackage.read(imagedump, packageHeader.image_size); + auto imagedump = std::make_unique(packageHeader.image_size); + tapackage.read(imagedump.get(), packageHeader.image_size); if (tapackage.fail()) { LOGE(SIM_DAEMON, "Read failed"); return -1; } - string removeImage = "rm -f " + extract_dir_path + uuid + ".image"; - int result = system(removeImage.c_str()); - if (result != 0) { - LOGE(SIM_DAEMON, "Failed to remove existing TA image"); - } - ofstream image((extract_dir_path + uuid + ".image").c_str(), - ios::out | ios::binary); - ofstream manifest((extract_dir_path + uuid + ".manifest").c_str(), - ios::out | ios::binary); - image.write(imagedump, packageHeader.image_size); - image.flush(); - delete[] imagedump; + ofstream image(imageFile.c_str(), ios::out | ios::binary); + if (image.fail()) { + LOGE(SIM_DAEMON, "Open failed %s %s", imageFile.c_str(), strerror(errno)); + return -1; + } + image.write(imagedump.get(), packageHeader.image_size); + image.close(); // 4. Read manifest and write to FS tapackage.seekg(packageHeader.manifest_offset); - char *manifestdump = new char[packageHeader.manifest_size]; - tapackage.read(manifestdump, packageHeader.manifest_size); + auto manifestdump = std::make_unique(packageHeader.manifest_size); + tapackage.read(manifestdump.get(), packageHeader.manifest_size); if (tapackage.fail()) { LOGE(SIM_DAEMON, "Read failed"); return -1; } - manifest.write(manifestdump, packageHeader.manifest_size); - manifest.flush(); - delete[] manifestdump; + + ofstream manifest(manifestFile.c_str(), ios::out | ios::binary); + if (manifest.fail()) { + LOGE(SIM_DAEMON, "Open failed %s %s", manifestFile.c_str(), strerror(errno)); + return -1; + } + manifest.write(manifestdump.get(), packageHeader.manifest_size); + manifest.close(); } else { LOGE(SIM_DAEMON, "Header verification failed"); return -1; diff --git a/simulatordaemon/src/TAInstance.cpp b/simulatordaemon/src/TAInstance.cpp index be1f6a3..afa5ad7 100644 --- a/simulatordaemon/src/TAInstance.cpp +++ b/simulatordaemon/src/TAInstance.cpp @@ -177,7 +177,7 @@ TEEC_Result TAInstance::connecttoTA(std::stringstream& str) { unsigned long int retry_count = 0; try { boost::system::error_code error = boost::asio::error::host_not_found; - stream_protocol::endpoint ep(string("/tmp/") + str.str()); + stream_protocol::endpoint ep(string(TEE_TASOCK_ROOT) + str.str()); LOGD(SIM_DAEMON, "Connect to TEEStub %s", str.str().c_str()); // Try to connect to TA RETRY_COUNT number of times diff --git a/ssflib/dep/swdss/source/secure_file.cpp b/ssflib/dep/swdss/source/secure_file.cpp index 0ab45f6..96c89e7 100644 --- a/ssflib/dep/swdss/source/secure_file.cpp +++ b/ssflib/dep/swdss/source/secure_file.cpp @@ -21,11 +21,10 @@ #include "ss_misc.h" #include "OsaLinuxUser.h" #include +#include #ifdef _SECOS_SIM_ #include "file_op.h" -#define SWD_SS_ROOT "/tmp/tastore2/" - #endif // this is RNG SEED for mask @@ -1706,7 +1705,7 @@ int secure_file::get_data_name(char* data_name, int maxlen, bool is_dir) { char* ptr = data_name; int remain = maxlen; - strncpy(ptr, SWD_SS_ROOT, remain); + strncpy(ptr, TEE_TASTORE_ROOT, remain); if (ptr[remain - 1] != '\0') return -1; ptr += strlen(ptr); diff --git a/ssflib/src/ssf_client.cpp b/ssflib/src/ssf_client.cpp index 2c89207..edec1cc 100644 --- a/ssflib/src/ssf_client.cpp +++ b/ssflib/src/ssf_client.cpp @@ -30,11 +30,11 @@ #include #include "ssf_client.h" #include +#include /*----------------------------------------------------------------------------- * MACROS *-----------------------------------------------------------------------------*/ -#define SOCKPATH "/tmp/simdaemon" //path to be updated /*----------------------------------------------------------------------------- @@ -58,13 +58,13 @@ int32_t connecttoServer(void) { } daemonsock.sun_family = AF_UNIX; - sock_path_len = strlen(SOCKPATH); - strncpy(daemonsock.sun_path, SOCKPATH, sock_path_len+1); + sock_path_len = strlen(SIMDAEMON_SOCK_PATH); + strncpy(daemonsock.sun_path, SIMDAEMON_SOCK_PATH, sock_path_len+1); socklen = sizeof(daemonsock); sockptr = (struct sockaddr*)&daemonsock; if (connect(serverSocket, sockptr, socklen) == -1) { - LOGE(SSF_LIB, "connection to simdaemon failed"); + LOGE(SSF_LIB, "connection to simdaemon failed (s=%s)", SIMDAEMON_SOCK_PATH); close(serverSocket); return -1; } -- 2.7.4 From 45bf1569e185628168134446b3168f958089ae8d Mon Sep 17 00:00:00 2001 From: Krzysztof Dynowski Date: Thu, 7 Dec 2017 16:34:10 +0100 Subject: [PATCH 05/16] remove postProc when preProc failed, minor optimalizations Change-Id: I831e26f8c237b675f668d4a13002b5cd88dd7411 --- TEECLib/src/teec_api.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/TEECLib/src/teec_api.c b/TEECLib/src/teec_api.c index e269e02..e4cb0c2 100644 --- a/TEECLib/src/teec_api.c +++ b/TEECLib/src/teec_api.c @@ -270,13 +270,13 @@ static uint32_t checkContext(TEEC_Context *context) TEEC_Result tempSharedMemAllocate(TEEC_SharedMemory** tmpSharedMem, uint32_t type, TEEC_Context* context, TEEC_Parameter param) { + LOGD(TEEC_LIB, "Entry"); TEEC_Result result; *tmpSharedMem = (TEEC_SharedMemory *)OsaMalloc(sizeof(TEEC_SharedMemory)); if (!*tmpSharedMem) return TEEC_ERROR_OUT_OF_MEMORY; (*tmpSharedMem)->size = param.tmpref.size; (*tmpSharedMem)->buffer = param.tmpref.buffer; - (*tmpSharedMem)->flags = type & (TEEC_MEM_INPUT | TEEC_MEM_OUTPUT); result = TEEC_RegisterSharedMemory(context, *tmpSharedMem); @@ -321,9 +321,8 @@ static TEEC_Result preProcessOperation(TEEC_Session *session, TEEC_Operation *operation, OperationData *op, TEEC_SharedMemory *tmpSharedMem[4]) { - TEEC_Context *context = NULL; - LOGD(TEEC_LIB, "Entry"); + TEEC_Context *context = NULL; TEEC_RegisteredMemoryReference *memref; TEEC_SharedMemoryImp *memref_imp; TEEC_Result result = TEEC_SUCCESS; @@ -334,12 +333,13 @@ static TEEC_Result preProcessOperation(TEEC_Session *session, LOGE(TEEC_LIB, "Bad parameters"); return TEEC_ERROR_BAD_PARAMETERS; } - context = ((TEEC_SessionImp *)session->imp)->context; // Check if output Operation structure is valid if (!op) return TEEC_ERROR_GENERIC; + context = ((TEEC_SessionImp *)session->imp)->context; + // Initialize output Operation structure paramtypes to NONE op->paramTypes = (TEE_PARAM_TYPE_NONE << 24) | (TEE_PARAM_TYPE_NONE << 16) | (TEE_PARAM_TYPE_NONE << 8) | TEE_PARAM_TYPE_NONE; @@ -377,7 +377,6 @@ static TEEC_Result preProcessOperation(TEEC_Session *session, * specifications, so assign them without modifications. */ op->paramTypes |= type << (8 * i); - if (!tmpSharedMem[i]) { result = tempSharedMemAllocate(&tmpSharedMem[i], type, context, operation->params[i]); if (result != TEEC_SUCCESS) @@ -740,7 +739,7 @@ TEEC_Result TEEC_RegisterSharedMemory(TEEC_Context *context, // Check if the context is initialized if (!checkContext(context)) { - LOGE(TEEC_LIB, "Invalid context"); + LOGE(TEEC_LIB, "Invalid context %p", context); return TEEC_ERROR_BAD_PARAMETERS; } @@ -770,7 +769,7 @@ TEEC_Result TEEC_RegisterSharedMemory(TEEC_Context *context, * TEEC_CONFIG_SHAREDMEM_MAX_SIZE and less than PAGE_SIZE. */ if (sharedMem->size > TEEC_CONFIG_SHAREDMEM_MAX_SIZE) { - LOGE(TEEC_LIB, "Shared Memory size is too large 0x%x", sharedMem->size); + LOGE(TEEC_LIB, "Shared Memory size is too large %u > %u", sharedMem->size, TEEC_CONFIG_SHAREDMEM_MAX_SIZE); return TEEC_ERROR_BAD_PARAMETERS; } @@ -1089,9 +1088,10 @@ TEEC_Result TEEC_OpenSession(TEEC_Context *context, TEEC_Session *session, OpenSessionData os; OperationData op; TEEC_SharedMemory *tmpSharedMem[4]; - memset(tmpSharedMem, 0x0, sizeof(TEEC_SharedMemory *) * 4); uint32_t i; + memset(tmpSharedMem, 0x0, sizeof(tmpSharedMem)); + // Check if the context, session and UUID is valid if (!session || !context || !destination) { LOGE(TEEC_LIB, "Invalid input parameters"); @@ -1165,8 +1165,6 @@ TEEC_Result TEEC_OpenSession(TEEC_Context *context, TEEC_Session *session, OsaFree(session_imp); session->imp = NULL; - if (operation) postProcessOperation(operation, &op, tmpSharedMem); - /* temp memref cleanup & release */ for (i = 0; i < 4; i++) { if (tmpSharedMem[i]) { @@ -1343,9 +1341,10 @@ TEEC_Result TEEC_InvokeCommand(TEEC_Session *session, uint32_t commandID, InvokeCommandData ic; OperationData op; TEEC_SharedMemory *tmpSharedMem[4]; - memset(tmpSharedMem, 0x0, sizeof(TEEC_SharedMemory *) * 4); uint32_t i; + memset(tmpSharedMem, 0x0, sizeof(tmpSharedMem)); + // Check if Session is valid if (!session) { LOGE(TEEC_LIB, "NULL session"); @@ -1386,8 +1385,6 @@ TEEC_Result TEEC_InvokeCommand(TEEC_Session *session, uint32_t commandID, if (result != TEEC_SUCCESS) { LOGE(TEEC_LIB, "preProcessOperation failed"); - if (operation) postProcessOperation(operation, &op, tmpSharedMem); - /* temp memref cleanup & release */ for (i = 0; i < 4; i++) { if (tmpSharedMem[i]) { -- 2.7.4 From 3c954212889b24376419ee647a7d14cf7878b390 Mon Sep 17 00:00:00 2001 From: Lukasz Kostyra Date: Thu, 26 Oct 2017 17:08:08 +0200 Subject: [PATCH 06/16] Redirect TA output to file before posix_spawn (append mode) Change-Id: Ic9e8853b86029badee226a6b263254102b98dc1c --- include/include/config.h | 1 + simulatordaemon/src/TAFactory.cpp | 24 +++++++++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/include/include/config.h b/include/include/config.h index 51752fe..e5cd6c9 100644 --- a/include/include/config.h +++ b/include/include/config.h @@ -27,6 +27,7 @@ //TEEStub must have write access in this directory (creating socket per TA) #define TEE_TASOCK_ROOT "/tmp/" +#define TEE_TALOG_ROOT "/tmp/" #define SHM_PATH "/tmp/shm" #define SIMDAEMON_SOCK_PATH "/tmp/simdaemon" diff --git a/simulatordaemon/src/TAFactory.cpp b/simulatordaemon/src/TAFactory.cpp index 4c5bcbe..0ab0067 100644 --- a/simulatordaemon/src/TAFactory.cpp +++ b/simulatordaemon/src/TAFactory.cpp @@ -400,8 +400,30 @@ bool TAFactory::launchTA(string TAUUID, std::stringstream& str, bool debug, argv[2] = NULL; envp[0] = NULL; + // redirect TA output to file + posix_spawn_file_actions_t child_fd_actions; + int ret = posix_spawn_file_actions_init(&child_fd_actions); + if (ret != 0) { + LOGE(SIM_DAEMON, "posix_spawn_file_actions_init failed"); + return false; + } + + ret = posix_spawn_file_actions_addopen(&child_fd_actions, 1, + (TEE_TALOG_ROOT + TAUUID + ".log").c_str(), + O_WRONLY | O_CREAT | O_APPEND | O_SYNC, 0644); + if (ret != 0) { + LOGE(SIM_DAEMON, "posix_spawn_file_actions_addopen failed"); + return false; + } + + ret = posix_spawn_file_actions_adddup2(&child_fd_actions, 1, 2); + if (ret != 0) { + LOGE(SIM_DAEMON, "posix_spawn_file_actions_adddup2 failed"); + return false; + } + // Spawn TA - result = posix_spawn(&pid, argv[0], NULL, NULL, argv, envp); + result = posix_spawn(&pid, argv[0], &child_fd_actions, NULL, argv, envp); if (result == 0) { LOGD(SIM_DAEMON, "TA pid: %i\n", pid); LOGD(SIM_DAEMON, "Launched Trusted Application"); -- 2.7.4 From 3fc1c1ab7a7ece0cdfbe998555d214aa5d4fa581 Mon Sep 17 00:00:00 2001 From: Krzysztof Dynowski Date: Wed, 3 Jan 2018 11:50:25 +0100 Subject: [PATCH 07/16] fix: check context before use (where missing) Change-Id: I6494cffdfb77bda7cc191a0be76f350b79322568 --- TEECLib/src/teec_api.c | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/TEECLib/src/teec_api.c b/TEECLib/src/teec_api.c index e4cb0c2..132f4d9 100644 --- a/TEECLib/src/teec_api.c +++ b/TEECLib/src/teec_api.c @@ -739,7 +739,7 @@ TEEC_Result TEEC_RegisterSharedMemory(TEEC_Context *context, // Check if the context is initialized if (!checkContext(context)) { - LOGE(TEEC_LIB, "Invalid context %p", context); + LOGE(TEEC_LIB, "Invalid context"); return TEEC_ERROR_BAD_PARAMETERS; } @@ -876,7 +876,7 @@ TEEC_Result TEEC_AllocateSharedMemory(TEEC_Context *context, // Check if the Context is initialized if (!checkContext(context)) { - LOGE(TEEC_LIB, "context is not found"); + LOGE(TEEC_LIB, "Invalid context"); return TEEC_ERROR_BAD_PARAMETERS; } @@ -1016,6 +1016,13 @@ void TEEC_ReleaseSharedMemory(TEEC_SharedMemory *sharedMem) return; } + // Check if the Context is initialized + if (!checkContext(context)) { + LOGE(TEEC_LIB, "Invalid context"); + return; + } + + // Check if the Context imp structure is valid context_imp = (TEEC_ContextImp *)context->imp; @@ -1098,6 +1105,12 @@ TEEC_Result TEEC_OpenSession(TEEC_Context *context, TEEC_Session *session, return TEEC_ERROR_BAD_PARAMETERS; } + // Check if the context is initialized + if (!checkContext(context)) { + LOGE(TEEC_LIB, "Invalid context"); + return TEEC_ERROR_BAD_PARAMETERS; + } + // Check if the context imp is valid TEEC_ContextImp *context_imp = (TEEC_ContextImp *)context->imp; @@ -1279,6 +1292,12 @@ void TEEC_CloseSession(TEEC_Session *session) return; } + // Check if the context is initialized + if (!checkContext(session_imp->context)) { + LOGE(TEEC_LIB, "Invalid context"); + return; + } + // Check if Context imp is valid TEEC_ContextImp *context_imp = (TEEC_ContextImp *)session_imp->context->imp; @@ -1359,6 +1378,12 @@ TEEC_Result TEEC_InvokeCommand(TEEC_Session *session, uint32_t commandID, return TEEC_ERROR_BAD_PARAMETERS; } + // Check if the context is initialized + if (!checkContext(session_imp->context)) { + LOGE(TEEC_LIB, "Invalid context"); + return TEEC_ERROR_BAD_PARAMETERS; + } + // Check if Context imp is valid TEEC_ContextImp *context_imp = (TEEC_ContextImp *)session_imp->context->imp; @@ -1507,6 +1532,12 @@ void TEEC_RequestCancellation(TEEC_Operation *operation) return; } + // Check if the context is initialized + if (!checkContext(session_imp->context)) { + LOGE(TEEC_LIB, "Invalid context"); + return; + } + // Check if Context imp is valid TEEC_ContextImp *context_imp = (TEEC_ContextImp *)session_imp->context->imp; -- 2.7.4 From 6925d644eec8cc17d65bf0b00ba2a95c63872712 Mon Sep 17 00:00:00 2001 From: leejungkyuen Date: Wed, 26 Jul 2017 15:58:50 +0900 Subject: [PATCH 08/16] Delete duplicate macros, move them to one config.h Change-Id: Idbebaec899d491786402172e5e9a554a72e8e45c --- TEECLib/src/teec_api.c | 3 +- TEEStub/teestubmain.cpp | 4 ++- include/include/config.h | 4 ++- simulatordaemon/inc/path.h | 36 ---------------------- simulatordaemon/src/SimulatorDaemon.cpp | 7 ++--- .../src/TABinaryManager/TABinaryManager.cpp | 4 +-- simulatordaemon/src/TABinaryManager/TestMain.cpp | 7 +++-- simulatordaemon/src/TAInstance.cpp | 1 + ssflib/dep/swdss/source/secure_file.cpp | 2 +- ssflib/src/ssf_client.cpp | 1 - 10 files changed, 18 insertions(+), 51 deletions(-) delete mode 100644 simulatordaemon/inc/path.h diff --git a/TEECLib/src/teec_api.c b/TEECLib/src/teec_api.c index 132f4d9..c46c933 100644 --- a/TEECLib/src/teec_api.c +++ b/TEECLib/src/teec_api.c @@ -191,8 +191,7 @@ static void freeSharedMemory(TEEC_SharedMemory *shm) return; } - ret = snprintf(shm_name, sizeof(shm_name), SHM_NAME_TEMPLATE, - sharedMem_imp->shmKey); + ret = snprintf(shm_name, sizeof(shm_name), SHM_NAME_TEMPLATE, sharedMem_imp->shmKey); if (ret == sizeof(shm_name)) { LOGE(TEE_STUB, "the shm object name is too long"); diff --git a/TEEStub/teestubmain.cpp b/TEEStub/teestubmain.cpp index 3b1cd3b..b66cd4e 100644 --- a/TEEStub/teestubmain.cpp +++ b/TEEStub/teestubmain.cpp @@ -108,7 +108,9 @@ int main(int argc, char* argv[]) { // Once the server is started, it exits only after the // connection is lost or gracefully disconnected. - StartServer(string(TEE_TASOCK_ROOT) + string(argv[1])); + std::string sock = string(TEE_TASOCK_ROOT) + argv[1]; + LOGD(TEE_STUB, "StartServer on %s\n", sock.c_str()); + StartServer(sock); LOGD(TEE_STUB, "Exiting TEEStub\n"); // Deallocate property objects if (TEE_SUCCESS == initStatus) DeInitPropertyModule(); diff --git a/include/include/config.h b/include/include/config.h index e5cd6c9..19c251c 100644 --- a/include/include/config.h +++ b/include/include/config.h @@ -25,13 +25,15 @@ //this is ln -s to /usr/lib/tastore or /usr/lib64/tastore (see spec file) #define TEE_TASTORE_ROOT "/opt/tastore/" +#define SIMDAEMON_SOCK_PATH "/tmp/simdaemon" //TEEStub must have write access in this directory (creating socket per TA) #define TEE_TASOCK_ROOT "/tmp/" #define TEE_TALOG_ROOT "/tmp/" #define SHM_PATH "/tmp/shm" -#define SIMDAEMON_SOCK_PATH "/tmp/simdaemon" #define TEE_PROP_PATH "/usr/bin/GPD_TEE_PROP" +#define TEE_SS_ROOT "/tmp/tastore2/" + #endif /* INCLUDE_CONFIG_H_ */ diff --git a/simulatordaemon/inc/path.h b/simulatordaemon/inc/path.h deleted file mode 100644 index 37a528f..0000000 --- a/simulatordaemon/inc/path.h +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Copyright (c) 2015-2017 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file - * @author CHERYL (cb) (cheryl.b@samsung.com) - * @brief Path detail - */ - - -#if !defined(_PATH_H) -#define _PATH_H - -/*----------------------------------------------------------------------------- - * MACROS - *-----------------------------------------------------------------------------*/ - -// shm path to be created for Shared memory functionality support -#define SHM_PATH "/tmp/shm" -// socket path for connection with Simulator Daemon -#define SIMDAEMON_PATH "/tmp/simdaemon" - -#endif //_PATH_H diff --git a/simulatordaemon/src/SimulatorDaemon.cpp b/simulatordaemon/src/SimulatorDaemon.cpp index f5928f1..70dd279 100644 --- a/simulatordaemon/src/SimulatorDaemon.cpp +++ b/simulatordaemon/src/SimulatorDaemon.cpp @@ -24,10 +24,9 @@ /*----------------------------------------------------------------------------- * Include files *-----------------------------------------------------------------------------*/ -#include "path.h" #include "SimulatorDaemonServer.h" - #include +#include /*----------------------------------------------------------------------------- * Local functions @@ -108,7 +107,7 @@ int main() { LOGD(SIM_DAEMON, "Entry"); uint32_t result = 0; try { - int sockFD = getSystemdSocket(SIMDAEMON_PATH); + int sockFD = getSystemdSocket(SIMDAEMON_SOCK_PATH); //initializeShm(); if (sockFD > 0) { @@ -117,7 +116,7 @@ int main() { startServer(ioService::getInstance()); } else { LOGI(SIM_DAEMON, "No systemd socket available - creating own one"); - SimulatorDaemonServer s(ioService::getInstance(), SIMDAEMON_PATH); + SimulatorDaemonServer s(ioService::getInstance(), SIMDAEMON_SOCK_PATH); startServer(ioService::getInstance()); } diff --git a/simulatordaemon/src/TABinaryManager/TABinaryManager.cpp b/simulatordaemon/src/TABinaryManager/TABinaryManager.cpp index 298a76d..18910d7 100644 --- a/simulatordaemon/src/TABinaryManager/TABinaryManager.cpp +++ b/simulatordaemon/src/TABinaryManager/TABinaryManager.cpp @@ -25,7 +25,6 @@ * Include files *-----------------------------------------------------------------------------*/ #include "TABinaryManager.h" -#include #include #include #include @@ -36,6 +35,7 @@ #include #include #include +#include /*----------------------------------------------------------------------------- * Globals *-----------------------------------------------------------------------------*/ @@ -251,7 +251,7 @@ bool TABinaryManager::unpackBinary(const string &uuid, StructBinaryInfo& info) { if (0 == unpacker->unpackTA(string(TEE_TASTORE_ROOT), uuid)) { LOGD(SIM_DAEMON, "Unpacked, filling info"); // 1. Set binary info - info.path = string(TEE_TASTORE_ROOT)+ uuid; + info.path = string(TEE_TASTORE_ROOT) + uuid; info.extractpath = string(TEE_TASTORE_ROOT) + uuid + "-ext/"; info.imagePath = info.extractpath + uuid + ".image"; info.manifestPath = info.extractpath + uuid + ".manifest"; diff --git a/simulatordaemon/src/TABinaryManager/TestMain.cpp b/simulatordaemon/src/TABinaryManager/TestMain.cpp index f66443d..b0b322a 100644 --- a/simulatordaemon/src/TABinaryManager/TestMain.cpp +++ b/simulatordaemon/src/TABinaryManager/TestMain.cpp @@ -26,7 +26,8 @@ #include "TABinaryManager.h" #include "TAManifest.h" #include "TAUnpack.h" -#include "Config.h" +#include + using namespace std; int test_main() { @@ -49,7 +50,7 @@ int test_main() { // Unpack TA case 1: { TAUnpack *unpacker = TAUnpack::getInstance(); - unpacker->unpackTA(TA_STORE_PATH, "0000-0000-0000-0000000000c7"); + unpacker->unpackTA(TEE_TASTORE_ROOT, "0000-0000-0000-0000000000c7"); break; } // Manifest test @@ -57,7 +58,7 @@ int test_main() { TAManifest manifest; manifest.processXML( string( - TA_STORE_PATH"0000-0000-0000-0000000000c7-ext/0000-0000-0000-0000000000c7.manifest")); + TEE_TASTORE_ROOT"0000-0000-0000-0000000000c7-ext/0000-0000-0000-0000000000c7.manifest")); manifest.printProcessedData(); break; } diff --git a/simulatordaemon/src/TAInstance.cpp b/simulatordaemon/src/TAInstance.cpp index afa5ad7..15da04e 100644 --- a/simulatordaemon/src/TAInstance.cpp +++ b/simulatordaemon/src/TAInstance.cpp @@ -26,6 +26,7 @@ *-----------------------------------------------------------------------------*/ #include "TAInstance.h" #include "ResponseCommands/ResMakeCommand.h" +#include /*----------------------------------------------------------------------------- * Member functions diff --git a/ssflib/dep/swdss/source/secure_file.cpp b/ssflib/dep/swdss/source/secure_file.cpp index 96c89e7..c2de76f 100644 --- a/ssflib/dep/swdss/source/secure_file.cpp +++ b/ssflib/dep/swdss/source/secure_file.cpp @@ -1705,7 +1705,7 @@ int secure_file::get_data_name(char* data_name, int maxlen, bool is_dir) { char* ptr = data_name; int remain = maxlen; - strncpy(ptr, TEE_TASTORE_ROOT, remain); + strncpy(ptr, TEE_SS_ROOT, remain); if (ptr[remain - 1] != '\0') return -1; ptr += strlen(ptr); diff --git a/ssflib/src/ssf_client.cpp b/ssflib/src/ssf_client.cpp index edec1cc..8094a29 100644 --- a/ssflib/src/ssf_client.cpp +++ b/ssflib/src/ssf_client.cpp @@ -36,7 +36,6 @@ * MACROS *-----------------------------------------------------------------------------*/ - /*----------------------------------------------------------------------------- * local functions *-----------------------------------------------------------------------------*/ -- 2.7.4 From c6356470d4dd1ad73fbd8572c9248376c64659b9 Mon Sep 17 00:00:00 2001 From: Krzysztof Dynowski Date: Thu, 11 Jan 2018 16:37:10 +0100 Subject: [PATCH 09/16] fix SHM path, remove unused code, replace system wih boost API (for simple cases) Change-Id: I1a3e868fe11de69cae5ac6740ebe75b64ff4297e --- TEECLib/src/teec_api.c | 17 ++++---- TEECLib/src/teec_connection.c | 16 +++++--- TEEStub/PropertyAccess/TEEProperty.cpp | 2 +- TEEStub/TACommands/SharedMemoryMap.cpp | 2 +- include/include/config.h | 7 ++-- simulatordaemon/src/SimulatorDaemon.cpp | 14 ------- .../src/TABinaryManager/TABinaryManager.cpp | 45 ++++++++++++---------- 7 files changed, 48 insertions(+), 55 deletions(-) diff --git a/TEECLib/src/teec_api.c b/TEECLib/src/teec_api.c index c46c933..085f57a 100644 --- a/TEECLib/src/teec_api.c +++ b/TEECLib/src/teec_api.c @@ -32,6 +32,7 @@ #include #include #include +#include /*----------------------------------------------------------------------------- * MACROS @@ -40,7 +41,6 @@ #define PAGE_MASK (~(PAGE_SIZE - 1)) #define SHM_MAX_ID INT32_MAX -#define SHM_NAME_TEMPLATE "/teec_shm%d" #define SHM_FILE_MODE 0660 /*----------------------------------------------------------------------------- * Globals @@ -102,15 +102,13 @@ static int32_t allocateSharedMemory(TEEC_SharedMemory *shm) int res; do { - res = snprintf(shm_name, sizeof(shm_name), SHM_NAME_TEMPLATE, memKey); - + res = snprintf(shm_name, sizeof(shm_name), SHM_NAME_PREFIX "%d", memKey); if (res == sizeof(shm_name)) { LOGE(TEEC_LIB, "the shm object name is too long"); return TEEC_ERROR_GENERIC; } fd_shm = shm_open(shm_name, O_RDWR | O_CREAT | O_EXCL, SHM_FILE_MODE); - if (fd_shm >= 0) { res = fchmod(fd_shm, SHM_FILE_MODE); @@ -127,8 +125,8 @@ static int32_t allocateSharedMemory(TEEC_SharedMemory *shm) } if (errno != EEXIST) { - LOGE(TEEC_LIB, "Cannot create shared memory object, error: %s", - strerror(errno)); + LOGE(TEEC_LIB, "Cannot create shared memory object '%s', error: %s", + shm_name, strerror(errno)); return TEEC_ERROR_GENERIC; } @@ -191,15 +189,14 @@ static void freeSharedMemory(TEEC_SharedMemory *shm) return; } - ret = snprintf(shm_name, sizeof(shm_name), SHM_NAME_TEMPLATE, sharedMem_imp->shmKey); - + ret = snprintf(shm_name, sizeof(shm_name), SHM_NAME_PREFIX "%d", sharedMem_imp->shmKey); if (ret == sizeof(shm_name)) { - LOGE(TEE_STUB, "the shm object name is too long"); + LOGE(TEEC_LIB, "the shm object name is too long"); return; } if (shm_unlink(shm_name) == -1) { - LOGE(TEE_STUB, "shm_unlink failed for %s, error: %s", shm_name, + LOGE(TEEC_LIB, "shm_unlink failed for %s, error: %s", shm_name, strerror(errno)); return; } diff --git a/TEECLib/src/teec_connection.c b/TEECLib/src/teec_connection.c index a5feaa4..dbfff73 100644 --- a/TEECLib/src/teec_connection.c +++ b/TEECLib/src/teec_connection.c @@ -49,21 +49,25 @@ int32_t connecttoServer(void) { LOGD(TEEC_LIB, "Entry"); int32_t serverSocket, socklen; - size_t sock_path_len = 0; struct sockaddr *sockptr; struct sockaddr_un daemonsock; + daemonsock.sun_family = AF_UNIX; + daemonsock.sun_path[sizeof(daemonsock.sun_path)-1] = 0; + strncpy(daemonsock.sun_path, SIMDAEMON_SOCK_PATH, sizeof(daemonsock.sun_path)); + + // Check simulator socket name length is valid + if (daemonsock.sun_path[sizeof(daemonsock.sun_path)-1] != 0) { + LOGE(TEEC_LIB, "Socket name too long: ", daemonsock.sun_path); + return -1; + } + // Get socket decriptor if ((serverSocket = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { LOGE(TEEC_LIB, "No socket for simdaemon"); return -1; } - daemonsock.sun_family = AF_UNIX; - - sock_path_len = strlen(SIMDAEMON_SOCK_PATH); - strncpy(daemonsock.sun_path, SIMDAEMON_SOCK_PATH, sock_path_len + 1); - socklen = sizeof(daemonsock); sockptr = (struct sockaddr *)&daemonsock; diff --git a/TEEStub/PropertyAccess/TEEProperty.cpp b/TEEStub/PropertyAccess/TEEProperty.cpp index 1d3e1e2..d82af16 100644 --- a/TEEStub/PropertyAccess/TEEProperty.cpp +++ b/TEEStub/PropertyAccess/TEEProperty.cpp @@ -115,7 +115,7 @@ bool TEEProperty::getNextProperty() { * @return true if property file successfully read else false */ bool TEEProperty::start() { - bool ret = readPropertyFile(string(TEE_PROP_PATH)); + bool ret = readPropertyFile(TEE_PROP_PATH); currentItr = propertiesMap.begin(); return ret; } diff --git a/TEEStub/TACommands/SharedMemoryMap.cpp b/TEEStub/TACommands/SharedMemoryMap.cpp index 44e5ac4..1ee9c87 100644 --- a/TEEStub/TACommands/SharedMemoryMap.cpp +++ b/TEEStub/TACommands/SharedMemoryMap.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include "log.h" using namespace std; @@ -48,7 +49,6 @@ using namespace std; #define PAGE_MASK (~(PAGE_SIZE - 1)) #define SHM_MAX_ID INT32_MAX -#define SHM_NAME_PREFIX "/teec_shm" map SharedMemoryMap::shmMap; diff --git a/include/include/config.h b/include/include/config.h index 19c251c..07404a1 100644 --- a/include/include/config.h +++ b/include/include/config.h @@ -24,16 +24,17 @@ //this is ln -s to /usr/lib/tastore or /usr/lib64/tastore (see spec file) #define TEE_TASTORE_ROOT "/opt/tastore/" +#define TEE_SS_ROOT "/opt/tastore/" #define SIMDAEMON_SOCK_PATH "/tmp/simdaemon" //TEEStub must have write access in this directory (creating socket per TA) #define TEE_TASOCK_ROOT "/tmp/" #define TEE_TALOG_ROOT "/tmp/" -#define SHM_PATH "/tmp/shm" +// from manpages: For portable use, a shared memory object +// should be identified by a name of the form /somename +#define SHM_NAME_PREFIX "/teec_shm" #define TEE_PROP_PATH "/usr/bin/GPD_TEE_PROP" -#define TEE_SS_ROOT "/tmp/tastore2/" - #endif /* INCLUDE_CONFIG_H_ */ diff --git a/simulatordaemon/src/SimulatorDaemon.cpp b/simulatordaemon/src/SimulatorDaemon.cpp index 70dd279..a8bd820 100644 --- a/simulatordaemon/src/SimulatorDaemon.cpp +++ b/simulatordaemon/src/SimulatorDaemon.cpp @@ -31,19 +31,6 @@ /*----------------------------------------------------------------------------- * Local functions *-----------------------------------------------------------------------------*/ -/** - * Create shm file for shared memory implementation (IPC) - */ -void initializeShm() { - LOGD(SIM_DAEMON, "Entry"); - ::unlink(SHM_PATH); - int fd = creat(SHM_PATH, S_IRWXU); - if (-1 == fd) { - LOGE(SIM_DAEMON, "shm file creation failed"); - exit(0); - } - close(fd); -} /** * Starts the Simulator Daemon as server which listens for connection from @@ -109,7 +96,6 @@ int main() { try { int sockFD = getSystemdSocket(SIMDAEMON_SOCK_PATH); - //initializeShm(); if (sockFD > 0) { LOGI(SIM_DAEMON, "Using existing systemd socket %d", sockFD); SimulatorDaemonServer s(ioService::getInstance(), sockFD); diff --git a/simulatordaemon/src/TABinaryManager/TABinaryManager.cpp b/simulatordaemon/src/TABinaryManager/TABinaryManager.cpp index 18910d7..dbb6b1e 100644 --- a/simulatordaemon/src/TABinaryManager/TABinaryManager.cpp +++ b/simulatordaemon/src/TABinaryManager/TABinaryManager.cpp @@ -163,9 +163,8 @@ bool TABinaryManager::initTA(const string &uuid) { LOGD(SIM_DAEMON, "Entry"); pthread_rwlock_wrlock(&binaryMapLock); - StructBinaryInfo value; - bool res = false; StructBinaryInfo info; + bool res = false; if (boost::filesystem::exists(TEE_TASTORE_ROOT + uuid)) { pthread_mutex_lock(&taLock); @@ -207,31 +206,34 @@ void TABinaryManager::decryptImage(StructBinaryInfo& info) { myfile.close(); } + boost::filesystem::path decName = info.imagePath + "_dec"; // hash of Keydata is not required. string dec_command = "openssl enc " + cipher + " -d -nopad -nosalt -K " + secret - + " -in " + info.imagePath + " -out " + info.imagePath - + "_dec -iv 0000000000000000"; + + " -in " + info.imagePath + " -out " + decName.string() + + + " -iv 0000000000000000"; result = system(dec_command.c_str()); if (result != 0) { LOGE(SIM_DAEMON, "Image decryption failed"); } - string removeEncImage = "rm -f " + info.imagePath; - result = system(removeEncImage.c_str()); - if (result != 0) { - LOGE(SIM_DAEMON, "Post decryption operations failed"); + boost::system::error_code ec; + boost::filesystem::remove(boost::filesystem::path(info.imagePath), ec); + if (ec) { + LOGE(SIM_DAEMON, "Post decryption failed: unlink %s : %s", info.imagePath.c_str(), + ec.message()); } - string renameDecImage = "mv " + info.imagePath + "_dec " + info.imagePath; - result = system(renameDecImage.c_str()); - if (result != 0) { - LOGE(SIM_DAEMON, "Post decryption operations failed"); + boost::filesystem::rename(decName, boost::filesystem::path(info.imagePath), ec); + if (ec) { + LOGE(SIM_DAEMON, "Post decryption failed: rename %s -> %s : %s", + decName.string().c_str(), info.imagePath.c_str(), + ec.message()); } - string removeKeyHash = "rm -f " + keyhashFilename; - result = system(removeKeyHash.c_str()); - if (result != 0) { - LOGE(SIM_DAEMON, "Post decryption operations failed"); + boost::filesystem::remove(boost::filesystem::path(keyhashFilename), ec); + if (ec) { + LOGE(SIM_DAEMON, "Post decryption failed: unlink %s : %s", keyhashFilename.c_str(), + ec.message()); } } @@ -261,12 +263,15 @@ bool TABinaryManager::unpackBinary(const string &uuid, StructBinaryInfo& info) { LOGD(SIM_DAEMON, "Decrypting"); // 3. Decrypt image using secret value in manifest if (info.manifest.properties.extension.launchMode == "debug") - decryptImage(info); + decryptImage(info); - string s = "chmod +x " + info.imagePath; - int result = system(s.c_str()); + struct stat st; + int result = stat(info.imagePath.c_str(), &st); + if (result == 0) { + result = chmod(info.imagePath.c_str(), st.st_mode|S_IXUSR|S_IXGRP|S_IXOTH); + } if (result != 0) { - LOGE(SIM_DAEMON, "Unpacking executable TA failed"); + LOGE(SIM_DAEMON, "Unpacking executable TA failed: %s", strerror(errno)); } ret = true; -- 2.7.4 From c0728663605794c11644ea329c44dd136d0dc44c Mon Sep 17 00:00:00 2001 From: Krzysztof Dynowski Date: Tue, 16 Jan 2018 12:30:17 +0100 Subject: [PATCH 10/16] Initialize shared->buffer with NULL Change-Id: Ia6bf28f88d9ec05cfdb941f82687f9d061312b1e --- TEECLib/src/teec_api.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/TEECLib/src/teec_api.c b/TEECLib/src/teec_api.c index 085f57a..813f46d 100644 --- a/TEECLib/src/teec_api.c +++ b/TEECLib/src/teec_api.c @@ -864,6 +864,10 @@ TEEC_Result TEEC_AllocateSharedMemory(TEEC_Context *context, TEEC_ContextImp *context_imp; RegSharedMemData regmem; + if (sharedMem) { + sharedMem->buffer = NULL; + } + // Check if the Context is valid if (!context) { LOGE(TEEC_LIB, "context is NULL"); @@ -921,7 +925,6 @@ TEEC_Result TEEC_AllocateSharedMemory(TEEC_Context *context, return TEE_ERROR_OUT_OF_MEMORY; TEEC_SharedMemoryImp *sharedMem_imp = (TEEC_SharedMemoryImp *)sharedMem->imp; - sharedMem->buffer = NULL; sharedMem_imp->context = context; /* Allocate shared memory and get the Shared Memory key to be shared with -- 2.7.4 From 55abe3746c624e999f07eac5a2061f2be9019a0f Mon Sep 17 00:00:00 2001 From: Krzysztof Dynowski Date: Tue, 16 Jan 2018 15:02:25 +0100 Subject: [PATCH 11/16] Return error TEEC_ERROR_OUT_OF_MEMORY if requested size too large Change-Id: Ia1f87109c2a1444f7491489b84e0d2633c07b61e --- TEECLib/src/teec_api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TEECLib/src/teec_api.c b/TEECLib/src/teec_api.c index 813f46d..cb77a74 100644 --- a/TEECLib/src/teec_api.c +++ b/TEECLib/src/teec_api.c @@ -907,7 +907,7 @@ TEEC_Result TEEC_AllocateSharedMemory(TEEC_Context *context, */ if (sharedMem->size > TEEC_CONFIG_SHAREDMEM_MAX_SIZE) { LOGE(TEEC_LIB, "Shared Memory size is too large 0x%x", sharedMem->size); - return TEEC_ERROR_BAD_PARAMETERS; + return TEEC_ERROR_OUT_OF_MEMORY; } // Check if the Shared memory flags are valid -- 2.7.4 From ea0b3ea706fb26092ece1c8d3f5ad8bef22fe594 Mon Sep 17 00:00:00 2001 From: Krzysztof Dynowski Date: Tue, 16 Jan 2018 12:28:37 +0100 Subject: [PATCH 12/16] Change sock/log to /var/{run,log}, tastore/storage to /opt/usr/apps/ta_sdk/{tee,data} Change-Id: Ieb32041f41e71db5e8f6b8bf39d2287a43a5c4c7 --- CMakeLists.txt | 3 +++ include/include/config.h | 28 +++++++++++++++++----- log/CMakeLists.txt | 1 + packaging/tef-simulator.spec | 26 +++++++++++++------- simulatordaemon/CMakeLists.txt | 3 ++- .../src/TABinaryManager/TABinaryManager.cpp | 2 ++ simulatordaemon/src/TABinaryManager/TAUnpack.cpp | 2 +- simulatordaemon/src/TAFactory.cpp | 4 +++- simulatordaemon/src/TAInstance.cpp | 5 ++-- systemd/tef-simulator.socket | 2 +- 10 files changed, 56 insertions(+), 20 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d0f1ceb..5e3144b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,6 +49,9 @@ ADD_DEFINITIONS("-Werror") # Make all warnings into errors. #ADD_DEFINITIONS("-Wextra") # Generate even more extra warnings ADD_DEFINITIONS("-D_ARCH_=${ARCH}") +ADD_DEFINITIONS(-DTEE_TASTORE_ROOT="${TASTORE_DIR}/") +ADD_DEFINITIONS(-DTEE_SS_ROOT="${STORAGE_DIR}/") +ADD_DEFINITIONS(-DTEE_TALOG_ROOT="${TALOG_DIR}/") # Enable tizen-specific preprocessor defines IF(DEFINED TIZEN) diff --git a/include/include/config.h b/include/include/config.h index 07404a1..a037025 100644 --- a/include/include/config.h +++ b/include/include/config.h @@ -22,14 +22,30 @@ #ifndef INCLUDE_CONFIG_H_ #define INCLUDE_CONFIG_H_ -//this is ln -s to /usr/lib/tastore or /usr/lib64/tastore (see spec file) -#define TEE_TASTORE_ROOT "/opt/tastore/" -#define TEE_SS_ROOT "/opt/tastore/" +#ifndef TEE_TASTORE_ROOT +//keep in sync ln -s to /usr/lib/tastore or /usr/lib64/tastore in packaging/tef-simulator.spec +#if _ARCH_ == 32 + #define TEE_TASTORE_ROOT "/opt/usr/apps/ta_sdk/tee/" +#elif _ARCH_ == 64 + #define TEE_TASTORE_ROOT "/opt/usr/apps/ta_sdk/tee64/" +#else + #error "Invalid architecture was set!" +#endif +#endif + +#ifndef TEE_SS_ROOT +#define TEE_SS_ROOT "/opt/usr/apps/ta_sdk/data/" +#endif + +#ifndef TEE_TALOG_ROOT +#define TEE_TALOG_ROOT "/var/log/ta/" +#endif + +//keep in sync with systemd/tef-simulator.socket +#define SIMDAEMON_SOCK_PATH "/var/run/simdaemon" -#define SIMDAEMON_SOCK_PATH "/tmp/simdaemon" //TEEStub must have write access in this directory (creating socket per TA) -#define TEE_TASOCK_ROOT "/tmp/" -#define TEE_TALOG_ROOT "/tmp/" +#define TEE_TASOCK_ROOT "/var/run/" // from manpages: For portable use, a shared memory object // should be identified by a name of the form /somename diff --git a/log/CMakeLists.txt b/log/CMakeLists.txt index 1a67c56..81382ec 100644 --- a/log/CMakeLists.txt +++ b/log/CMakeLists.txt @@ -24,3 +24,4 @@ SET(LOG_SOURCES ADD_LIBRARY(${TARGET_TEF_SIMULATOR_LOG} ${LOG_SOURCES}) INSTALL(TARGETS ${TARGET_TEF_SIMULATOR_LOG} DESTINATION ${LIB_DIR}) +INSTALL(DIRECTORY DESTINATION ${BUILD_ROOT}${TALOG_DIR}) diff --git a/packaging/tef-simulator.spec b/packaging/tef-simulator.spec index 83a8df9..33645b4 100644 --- a/packaging/tef-simulator.spec +++ b/packaging/tef-simulator.spec @@ -25,14 +25,19 @@ PreReq: tef-libteec %define lib_dir %{?TZ_SYS_LIB:%TZ_SYS_LIB}%{!?TZ_SYS_LIB:%_libdir} %define data_dir %{?TZ_SYS_RO_SHARE:%TZ_SYS_RO_SHARE}%{!?TZ_SYS_RO_SHARE:%_datadir} %define include_dir %{?TZ_SYS_INCLUDE:%TZ_SYS_INCLUDE}%{!?TZ_SYS_INCLUDE:%_includedir} -%define tastore_dir %{lib_dir}/tastore -%define link_tastore_dir /opt/tastore +%define link_tastore_dir %{lib_dir}/tastore +%if %{__isa_bits} == 64 +%define tastore_dir /opt/usr/apps/ta_sdk/tee64 +%else +%define tastore_dir /opt/usr/apps/ta_sdk/tee +%endif +%define storage_dir /opt/usr/apps/ta_sdk/data +%define talog_dir /var/log/ta %define build_bin_dir %{buildroot}%{bin_dir} %define build_lib_dir %{buildroot}%{lib_dir} -%define build_data_dir %{buildroot}%{data_dir} %define build_include_dir %{buildroot}%{include_dir} -%define build_tastore_dir %{buildroot}%{tastore_dir} +%define build_data_dir %{buildroot}%{data_dir} %define build_unit_dir %{buildroot}%{_unitdir} %define smack_domain_name System @@ -74,11 +79,14 @@ cp %{SOURCE1} . # cannot call cmake rpmbuild macro because of scripts removing libTEEStub.a, which is a part of devkit cmake . \ -DCMAKE_BUILD_TYPE=%{?build_type:%build_type}%{!?build_type:RELEASE} \ + -DBUILD_ROOT=%{buildroot} \ -DBIN_DIR=%{build_bin_dir} \ -DLIB_DIR=%{build_lib_dir} \ -DDATA_DIR=%{build_data_dir} \ -DINCLUDE_DIR=%{build_include_dir} \ - -DTASTORE_DIR=%{build_tastore_dir} \ + -DTASTORE_DIR=%{tastore_dir} \ + -DSTORAGE_DIR=%{storage_dir} \ + -DTALOG_DIR=%{talog_dir} \ -DSYSTEMD_UNIT_DIR=%{build_unit_dir} \ -DSYSTEMD_CFG_BIN_DIR=%{bin_dir} \ -DPKGCFG_LIB_DIR=%{lib_dir} \ @@ -97,9 +105,9 @@ cp include/include/LICENSE LICENSE.BSD %pre %post -rm -f %{link_tastore_dir} -mkdir -p %{link_tastore_dir} -rmdir %{link_tastore_dir} +systemctl stop tef-simulator +rm -rf %{link_tastore_dir} +mkdir -p `dirname %{link_tastore_dir}` ln -sf %{tastore_dir} %{link_tastore_dir} tef-update.sh simulator systemctl enable tef-simulator @@ -122,6 +130,8 @@ fi %attr(444,security_fw,security_fw) %{_unitdir}/tef-simulator.service %attr(444,security_fw,security_fw) %{_unitdir}/tef-simulator.socket %attr(755,security_fw,security_fw) %{lib_dir}/tef/simulator/libteec.so +%attr(770,root,security_fw) %{talog_dir} +%attr(770,root,security_fw) %{storage_dir} %files -n %{name}-devkit %license LICENSE diff --git a/simulatordaemon/CMakeLists.txt b/simulatordaemon/CMakeLists.txt index 0774429..e57cc44 100644 --- a/simulatordaemon/CMakeLists.txt +++ b/simulatordaemon/CMakeLists.txt @@ -104,4 +104,5 @@ TARGET_LINK_LIBRARIES(${TARGET_TEF_SIMULATOR_DAEMON} INSTALL(TARGETS ${TARGET_TEF_SIMULATOR_DAEMON} DESTINATION ${BIN_DIR}) -INSTALL(DIRECTORY DESTINATION ${TASTORE_DIR}) +INSTALL(DIRECTORY DESTINATION ${BUILD_ROOT}${TASTORE_DIR}) +INSTALL(DIRECTORY DESTINATION ${BUILD_ROOT}${STORAGE_DIR}) diff --git a/simulatordaemon/src/TABinaryManager/TABinaryManager.cpp b/simulatordaemon/src/TABinaryManager/TABinaryManager.cpp index dbb6b1e..52fba75 100644 --- a/simulatordaemon/src/TABinaryManager/TABinaryManager.cpp +++ b/simulatordaemon/src/TABinaryManager/TABinaryManager.cpp @@ -177,6 +177,8 @@ bool TABinaryManager::initTA(const string &uuid) { res = false; } pthread_mutex_unlock(&taLock); + } else { + LOGD(SIM_DAEMON, "TA not exist %s", (TEE_TASTORE_ROOT + uuid).c_str()); } pthread_rwlock_unlock(&binaryMapLock); return res; diff --git a/simulatordaemon/src/TABinaryManager/TAUnpack.cpp b/simulatordaemon/src/TABinaryManager/TAUnpack.cpp index 5279024..cce3913 100644 --- a/simulatordaemon/src/TABinaryManager/TAUnpack.cpp +++ b/simulatordaemon/src/TABinaryManager/TAUnpack.cpp @@ -73,7 +73,7 @@ int TAUnpack::unpackTA(string path, string uuid) { struct stat info; if (stat(extract_dir_path.c_str(), &info) != 0) { if (0 != mkdir(extract_dir_path.c_str(), 0777)) { - LOGE(SIM_DAEMON, "mkdir failed"); + LOGE(SIM_DAEMON, "mkdir failed %s %s", extract_dir_path.c_str(), strerror(errno)); return -1; } } diff --git a/simulatordaemon/src/TAFactory.cpp b/simulatordaemon/src/TAFactory.cpp index 0ab0067..272b912 100644 --- a/simulatordaemon/src/TAFactory.cpp +++ b/simulatordaemon/src/TAFactory.cpp @@ -422,13 +422,15 @@ bool TAFactory::launchTA(string TAUUID, std::stringstream& str, bool debug, return false; } + LOGD(SIM_DAEMON, "spawn TA %s %s", argv[0], argv[1]); // Spawn TA result = posix_spawn(&pid, argv[0], &child_fd_actions, NULL, argv, envp); if (result == 0) { LOGD(SIM_DAEMON, "TA pid: %i\n", pid); LOGD(SIM_DAEMON, "Launched Trusted Application"); } else { - LOGE(SIM_DAEMON, "Launching Trusted Application FAILED"); + ret = errno; + LOGE(SIM_DAEMON, "Launching Trusted Application FAILED %s(%d)", strerror(ret), ret); pthread_mutex_unlock(&TABin->taLock); return false; } diff --git a/simulatordaemon/src/TAInstance.cpp b/simulatordaemon/src/TAInstance.cpp index 15da04e..8eca010 100644 --- a/simulatordaemon/src/TAInstance.cpp +++ b/simulatordaemon/src/TAInstance.cpp @@ -178,9 +178,10 @@ TEEC_Result TAInstance::connecttoTA(std::stringstream& str) { unsigned long int retry_count = 0; try { boost::system::error_code error = boost::asio::error::host_not_found; - stream_protocol::endpoint ep(string(TEE_TASOCK_ROOT) + str.str()); + string tasock = string(TEE_TASOCK_ROOT) + str.str(); + stream_protocol::endpoint ep(tasock); - LOGD(SIM_DAEMON, "Connect to TEEStub %s", str.str().c_str()); + LOGD(SIM_DAEMON, "Connect to TEEStub %s", tasock.c_str()); // Try to connect to TA RETRY_COUNT number of times while (error && (retry_count < RETRY_COUNT)) { #if 0 diff --git a/systemd/tef-simulator.socket b/systemd/tef-simulator.socket index 09ecd71..f4295d2 100644 --- a/systemd/tef-simulator.socket +++ b/systemd/tef-simulator.socket @@ -1,5 +1,5 @@ [Socket] -ListenStream=/tmp/simdaemon +ListenStream=/var/run/simdaemon SocketMode=0777 SmackLabelIPIn=* SmackLabelIPOut=@ -- 2.7.4 From 3fdc864a361c0c3566a534f007e023aaa3b5d4d4 Mon Sep 17 00:00:00 2001 From: Krzysztof Dynowski Date: Tue, 13 Feb 2018 10:15:32 +0100 Subject: [PATCH 13/16] Separate extract path support Change-Id: I0741a959e01858941e3e5a23e5f032f237af2a33 --- CMakeLists.txt | 1 + TEEStub/PropertyAccess/PropertyApi.cpp | 2 +- include/include/config.h | 5 +++++ packaging/tef-simulator.spec | 3 +++ simulatordaemon/CMakeLists.txt | 1 + simulatordaemon/src/TABinaryManager/TABinaryManager.cpp | 4 ++-- simulatordaemon/src/TABinaryManager/TAUnpack.cpp | 15 ++++++++------- simulatordaemon/src/TABinaryManager/TAUnpack.h | 2 +- 8 files changed, 22 insertions(+), 11 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5e3144b..147e771 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,6 +50,7 @@ ADD_DEFINITIONS("-Werror") # Make all warnings into errors. ADD_DEFINITIONS("-D_ARCH_=${ARCH}") ADD_DEFINITIONS(-DTEE_TASTORE_ROOT="${TASTORE_DIR}/") +ADD_DEFINITIONS(-DTEE_EXTRACT_ROOT="${EXTRACT_DIR}/") ADD_DEFINITIONS(-DTEE_SS_ROOT="${STORAGE_DIR}/") ADD_DEFINITIONS(-DTEE_TALOG_ROOT="${TALOG_DIR}/") diff --git a/TEEStub/PropertyAccess/PropertyApi.cpp b/TEEStub/PropertyAccess/PropertyApi.cpp index 50e3a99..da9da5e 100644 --- a/TEEStub/PropertyAccess/PropertyApi.cpp +++ b/TEEStub/PropertyAccess/PropertyApi.cpp @@ -326,7 +326,7 @@ void TEE_StartPropertyEnumerator(TEE_PropSetHandle enumerator, switch ((uintptr_t)propSet) { case TEE_PROPSET_CURRENT_TA: { newEnumHandle->property = new TAProperty( - string(TEE_TASTORE_ROOT) + thisTAUUIDGlobal + "-ext/" + string(TEE_EXTRACT_ROOT) + thisTAUUIDGlobal + "-ext/" + thisTAUUIDGlobal + ".manifest"); break; } diff --git a/include/include/config.h b/include/include/config.h index a037025..97abb4b 100644 --- a/include/include/config.h +++ b/include/include/config.h @@ -33,6 +33,10 @@ #endif #endif +#ifndef TEE_EXTRACT_ROOT +#define TEE_EXTRACT_ROOT "/opt/usr/apps/ta_sdk/extract/" +#endif + #ifndef TEE_SS_ROOT #define TEE_SS_ROOT "/opt/usr/apps/ta_sdk/data/" #endif @@ -41,6 +45,7 @@ #define TEE_TALOG_ROOT "/var/log/ta/" #endif + //keep in sync with systemd/tef-simulator.socket #define SIMDAEMON_SOCK_PATH "/var/run/simdaemon" diff --git a/packaging/tef-simulator.spec b/packaging/tef-simulator.spec index 33645b4..8cab70e 100644 --- a/packaging/tef-simulator.spec +++ b/packaging/tef-simulator.spec @@ -32,6 +32,7 @@ PreReq: tef-libteec %define tastore_dir /opt/usr/apps/ta_sdk/tee %endif %define storage_dir /opt/usr/apps/ta_sdk/data +%define extract_dir /opt/usr/apps/ta_sdk/extract %define talog_dir /var/log/ta %define build_bin_dir %{buildroot}%{bin_dir} @@ -85,6 +86,7 @@ cmake . \ -DDATA_DIR=%{build_data_dir} \ -DINCLUDE_DIR=%{build_include_dir} \ -DTASTORE_DIR=%{tastore_dir} \ + -DEXTRACT_DIR=%{extract_dir} \ -DSTORAGE_DIR=%{storage_dir} \ -DTALOG_DIR=%{talog_dir} \ -DSYSTEMD_UNIT_DIR=%{build_unit_dir} \ @@ -132,6 +134,7 @@ fi %attr(755,security_fw,security_fw) %{lib_dir}/tef/simulator/libteec.so %attr(770,root,security_fw) %{talog_dir} %attr(770,root,security_fw) %{storage_dir} +%attr(770,root,security_fw) %{extract_dir} %files -n %{name}-devkit %license LICENSE diff --git a/simulatordaemon/CMakeLists.txt b/simulatordaemon/CMakeLists.txt index e57cc44..f330065 100644 --- a/simulatordaemon/CMakeLists.txt +++ b/simulatordaemon/CMakeLists.txt @@ -105,4 +105,5 @@ TARGET_LINK_LIBRARIES(${TARGET_TEF_SIMULATOR_DAEMON} INSTALL(TARGETS ${TARGET_TEF_SIMULATOR_DAEMON} DESTINATION ${BIN_DIR}) INSTALL(DIRECTORY DESTINATION ${BUILD_ROOT}${TASTORE_DIR}) +INSTALL(DIRECTORY DESTINATION ${BUILD_ROOT}${EXTRACT_DIR}) INSTALL(DIRECTORY DESTINATION ${BUILD_ROOT}${STORAGE_DIR}) diff --git a/simulatordaemon/src/TABinaryManager/TABinaryManager.cpp b/simulatordaemon/src/TABinaryManager/TABinaryManager.cpp index 52fba75..c609831 100644 --- a/simulatordaemon/src/TABinaryManager/TABinaryManager.cpp +++ b/simulatordaemon/src/TABinaryManager/TABinaryManager.cpp @@ -252,11 +252,11 @@ void TABinaryManager::decryptImage(StructBinaryInfo& info) { bool TABinaryManager::unpackBinary(const string &uuid, StructBinaryInfo& info) { TAUnpack* unpacker = TAUnpack::getInstance(); bool ret = false; - if (0 == unpacker->unpackTA(string(TEE_TASTORE_ROOT), uuid)) { + if (0 == unpacker->unpackTA(TEE_TASTORE_ROOT, uuid)) { LOGD(SIM_DAEMON, "Unpacked, filling info"); // 1. Set binary info info.path = string(TEE_TASTORE_ROOT) + uuid; - info.extractpath = string(TEE_TASTORE_ROOT) + uuid + "-ext/"; + info.extractpath = string(TEE_EXTRACT_ROOT) + uuid + "-ext/"; info.imagePath = info.extractpath + uuid + ".image"; info.manifestPath = info.extractpath + uuid + ".manifest"; // 2. Parse manifest and store results diff --git a/simulatordaemon/src/TABinaryManager/TAUnpack.cpp b/simulatordaemon/src/TABinaryManager/TAUnpack.cpp index cce3913..28c906a 100644 --- a/simulatordaemon/src/TABinaryManager/TAUnpack.cpp +++ b/simulatordaemon/src/TABinaryManager/TAUnpack.cpp @@ -61,15 +61,13 @@ TAUnpack* TAUnpack::getInstance() { * @param uuid uuid of package * @return -1 on error otherwise 0 */ -int TAUnpack::unpackTA(string path, string uuid) { +int TAUnpack::unpackTA(const string& path, const string& uuid) { LOGD(SIM_DAEMON, ""); TAPackageHeaderV2 packageHeader; memset(&packageHeader, 0, sizeof(TAPackageHeaderV2)); - // Open file - string path_to_file = path + uuid; - ifstream tapackage(path_to_file.c_str(), ios::in | ios::binary); - // Create directory for UUID - string extract_dir_path = path + uuid + "-ext/"; + + // Create directory for TA extracted files + string extract_dir_path = TEE_EXTRACT_ROOT + uuid + "-ext/"; struct stat info; if (stat(extract_dir_path.c_str(), &info) != 0) { if (0 != mkdir(extract_dir_path.c_str(), 0777)) { @@ -78,8 +76,11 @@ int TAUnpack::unpackTA(string path, string uuid) { } } + // Open TA package file + string path_to_file = path + uuid; + ifstream tapackage(path_to_file.c_str(), ios::in | ios::binary); if (!tapackage.is_open()) { - LOGE(SIM_DAEMON, "Already open - failed"); + LOGE(SIM_DAEMON, "Cannot open ta: %s", path_to_file.c_str()); return -1; //> unable to open file } // 1. Read header diff --git a/simulatordaemon/src/TABinaryManager/TAUnpack.h b/simulatordaemon/src/TABinaryManager/TAUnpack.h index a598e0a..b701d67 100644 --- a/simulatordaemon/src/TABinaryManager/TAUnpack.h +++ b/simulatordaemon/src/TABinaryManager/TAUnpack.h @@ -78,7 +78,7 @@ private: unsigned int paddedSize); public: static TAUnpack* getInstance(); - int unpackTA(string path, string uuid); + int unpackTA(const string& path, const string& uuid); virtual ~TAUnpack(); }; -- 2.7.4 From 03b793c1505364376be9148fecea5b3faab49b21 Mon Sep 17 00:00:00 2001 From: Krzysztof Dynowski Date: Tue, 13 Feb 2018 10:15:32 +0100 Subject: [PATCH 14/16] Fix TA file names, remove dash (-) Change-Id: Iec46e9fd2012b1e2c7c135b139db27c937b2f7b3 --- simulatordaemon/src/TABinaryManager/TestMain.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/simulatordaemon/src/TABinaryManager/TestMain.cpp b/simulatordaemon/src/TABinaryManager/TestMain.cpp index b0b322a..0882888 100644 --- a/simulatordaemon/src/TABinaryManager/TestMain.cpp +++ b/simulatordaemon/src/TABinaryManager/TestMain.cpp @@ -50,7 +50,7 @@ int test_main() { // Unpack TA case 1: { TAUnpack *unpacker = TAUnpack::getInstance(); - unpacker->unpackTA(TEE_TASTORE_ROOT, "0000-0000-0000-0000000000c7"); + unpacker->unpackTA(TEE_TASTORE_ROOT, "0000000000000000000000c7"); break; } // Manifest test @@ -58,7 +58,7 @@ int test_main() { TAManifest manifest; manifest.processXML( string( - TEE_TASTORE_ROOT"0000-0000-0000-0000000000c7-ext/0000-0000-0000-0000000000c7.manifest")); + TEE_EXTRACT_ROOT"0000000000000000000000c7-ext/0000000000000000000000c7.manifest")); manifest.printProcessedData(); break; } @@ -72,15 +72,15 @@ int test_main() { std::cout << "[SIM_DAEMON] Binary Manager successfully initialized" << std::endl; std::cout - << "[SIM_DAEMON] Image Path of 0000-0000-0000-0000000000c7: " - << bm->getImagePath("0000-0000-0000-0000000000c7") << std::endl; + << "[SIM_DAEMON] Image Path of 0000000000000000000000c7: " + << bm->getImagePath("0000000000000000000000c7") << std::endl; std::cout - << "[SIM_DAEMON] Image Path of 0000-0000-0000-0000001234d5: " - << bm->getImagePath("0000-0000-0000-0000001234d5") << std::endl; + << "[SIM_DAEMON] Image Path of 0000000000000000001234d5: " + << bm->getImagePath("0000000000000000001234d5") << std::endl; std::cout - << "[SIM_DAEMON] Image Path of 0000-0000-0000-0000004567c8: " - << bm->getImagePath("0000-0000-0000-0000004567c8") << std::endl; - bm->getManifest("0000-0000-0000-0000004567c8")->printProcessedData(); + << "[SIM_DAEMON] Image Path of 0000000000000000004567c8: " + << bm->getImagePath("0000000000000000004567c8") << std::endl; + bm->getManifest("0000000000000000004567c8")->printProcessedData(); break; } -- 2.7.4 From 02a289075046cb82bf001fee02c26f27fe0b791a Mon Sep 17 00:00:00 2001 From: Krzysztof Dynowski Date: Tue, 13 Feb 2018 10:17:13 +0100 Subject: [PATCH 15/16] Fix return origin in invoke command Change-Id: If392e598ff6f3accec83c639a868eb3ba895c09c --- TEECLib/src/teec_api.c | 14 ++++++++------ TEEStub/TACommands/CommandInvoke.cpp | 8 ++++---- simulatordaemon/src/ConnectionSession.cpp | 5 +---- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/TEECLib/src/teec_api.c b/TEECLib/src/teec_api.c index cb77a74..3ceee06 100644 --- a/TEECLib/src/teec_api.c +++ b/TEECLib/src/teec_api.c @@ -1363,6 +1363,11 @@ TEEC_Result TEEC_InvokeCommand(TEEC_Session *session, uint32_t commandID, memset(tmpSharedMem, 0x0, sizeof(tmpSharedMem)); + // Set returnOrigin + if (returnOrigin) { + *returnOrigin = TEEC_ORIGIN_API; + } + // Check if Session is valid if (!session) { LOGE(TEEC_LIB, "NULL session"); @@ -1396,12 +1401,7 @@ TEEC_Result TEEC_InvokeCommand(TEEC_Session *session, uint32_t commandID, */ memset(&ic, 0x00, sizeof(InvokeCommandData)); memset(&op, 0x00, sizeof(OperationData)); - - // Set returnOrigin - if (returnOrigin) { - *returnOrigin = TEEC_ORIGIN_API; - ic.returnOrigin = *returnOrigin; - } else ic.returnOrigin = 0x00; + ic.returnOrigin = TEEC_ORIGIN_API; if (operation) { result = preProcessOperation(session, operation, &op, tmpSharedMem); @@ -1454,6 +1454,8 @@ TEEC_Result TEEC_InvokeCommand(TEEC_Session *session, uint32_t commandID, return result; } + LOGE(TEEC_LIB, "sendCommand to Simulator Daemon succes, origin=%d", ic.returnOrigin); + if (returnOrigin) *returnOrigin = ic.returnOrigin; result = ic.returnValue; diff --git a/TEEStub/TACommands/CommandInvoke.cpp b/TEEStub/TACommands/CommandInvoke.cpp index 1844bb6..0bd908a 100644 --- a/TEEStub/TACommands/CommandInvoke.cpp +++ b/TEEStub/TACommands/CommandInvoke.cpp @@ -57,19 +57,19 @@ TEE_Result CommandInvoke::execute() { bool sharedResult = true; TOGGLE_PROPERTY_ACCESS; + data.returnOrigin = TEE_ORIGIN_TEE; sharedResult = SharedMemoryMap::allocateSharedMemory(data.op); if (sharedResult) { + data.returnOrigin = TEE_ORIGIN_TRUSTED_APP; data.returnValue = TA_InvokeCommandEntryPoint(sessionContext, data.commandID, data.op.paramTypes, data.op.params); - LOGD(TEE_STUB, "TA_InvokeCommandEntryPoint done"); + LOGD(TEE_STUB, "TA_InvokeCommandEntryPoint done, data.origin = %d", data.returnOrigin); } else { - data.returnOrigin = TEE_ORIGIN_TRUSTED_APP; data.returnValue = TEE_ERROR_OUT_OF_MEMORY; } sharedResult = SharedMemoryMap::deleteSharedMemory(data.op); if (!sharedResult) { - data.returnOrigin = TEE_ORIGIN_TRUSTED_APP; - data.returnValue = TEE_ERROR_OUT_OF_MEMORY; + LOGE(TEE_STUB, "deleteSharedMemory failed"); } TOGGLE_PROPERTY_ACCESS; diff --git a/simulatordaemon/src/ConnectionSession.cpp b/simulatordaemon/src/ConnectionSession.cpp index 8fadf2f..97d7304 100644 --- a/simulatordaemon/src/ConnectionSession.cpp +++ b/simulatordaemon/src/ConnectionSession.cpp @@ -160,10 +160,7 @@ void ConnectionSession::handleRead(const boost::system::error_code& error, } //case } //switch } else { - LOGE(SIM_DAEMON, "Error in reading from CA"); - LOGE(SIM_DAEMON, "Response returned with error code %d", error.value()); - LOGE(SIM_DAEMON, "Response returned with error code %s", - error.category().name()); + LOGE(SIM_DAEMON, "Error in reading from CA %s(%d)", error.category().name(), error.value()); // Call the TEEContext object to cleanup FinalizeContextData data; data.contextID = 0; -- 2.7.4 From 5da48e810589e93c7d7487e567af46b6ab93470b Mon Sep 17 00:00:00 2001 From: Krzysztof Dynowski Date: Wed, 14 Feb 2018 14:07:58 +0100 Subject: [PATCH 16/16] Embedded path configuration Change-Id: I7ae530892a878a5009cab75e0610056c42f4ce59 --- include/include/config.h | 2 + .../src/TABinaryManager/TABinaryManager.cpp | 56 ++++++++++++++-------- .../src/TABinaryManager/TABinaryManager.h | 2 +- simulatordaemon/src/TABinaryManager/TAUnpack.cpp | 20 +++++--- 4 files changed, 52 insertions(+), 28 deletions(-) diff --git a/include/include/config.h b/include/include/config.h index 97abb4b..e10eb5c 100644 --- a/include/include/config.h +++ b/include/include/config.h @@ -33,6 +33,8 @@ #endif #endif +#define TEE_EMBEDDED_TASTORE_ROOT "/usr/apps/tee/" + #ifndef TEE_EXTRACT_ROOT #define TEE_EXTRACT_ROOT "/opt/usr/apps/ta_sdk/extract/" #endif diff --git a/simulatordaemon/src/TABinaryManager/TABinaryManager.cpp b/simulatordaemon/src/TABinaryManager/TABinaryManager.cpp index c609831..1a37cfb 100644 --- a/simulatordaemon/src/TABinaryManager/TABinaryManager.cpp +++ b/simulatordaemon/src/TABinaryManager/TABinaryManager.cpp @@ -36,6 +36,8 @@ #include #include #include + +namespace fs = boost::filesystem; /*----------------------------------------------------------------------------- * Globals *-----------------------------------------------------------------------------*/ @@ -162,24 +164,38 @@ TABinaryManager* TABinaryManager::getInstance() { bool TABinaryManager::initTA(const string &uuid) { LOGD(SIM_DAEMON, "Entry"); - pthread_rwlock_wrlock(&binaryMapLock); + string tapath; + const char * paths[] = { TEE_TASTORE_ROOT, TEE_EMBEDDED_TASTORE_ROOT, NULL }; + + for (int i = 0; paths[i] != NULL; ++i) { + if (*paths[i] == '\0') continue; // ignore empty paths + string path_to_file = paths[i] + uuid; + boost::system::error_code ec; + if (fs::exists(path_to_file, ec)) { + tapath = paths[i]; + break; + } + } + + if (tapath.empty()) { + LOGE(SIM_DAEMON, "Cannot find TA: %s", uuid.c_str()); + return false; + } + StructBinaryInfo info; bool res = false; - if (boost::filesystem::exists(TEE_TASTORE_ROOT + uuid)) { - pthread_mutex_lock(&taLock); - try { - if (unpackBinary(uuid, info)) { - binaryMap[uuid] = info; - res = true; - } - } catch (...) { - res = false; + pthread_rwlock_wrlock(&binaryMapLock); + pthread_mutex_lock(&taLock); + try { + if (unpackBinary(uuid, tapath, info)) { + binaryMap[uuid] = info; + res = true; } - pthread_mutex_unlock(&taLock); - } else { - LOGD(SIM_DAEMON, "TA not exist %s", (TEE_TASTORE_ROOT + uuid).c_str()); + } catch (...) { + res = false; } + pthread_mutex_unlock(&taLock); pthread_rwlock_unlock(&binaryMapLock); return res; } @@ -208,7 +224,7 @@ void TABinaryManager::decryptImage(StructBinaryInfo& info) { myfile.close(); } - boost::filesystem::path decName = info.imagePath + "_dec"; + fs::path decName = info.imagePath + "_dec"; // hash of Keydata is not required. string dec_command = "openssl enc " + cipher + " -d -nopad -nosalt -K " + secret + " -in " + info.imagePath + " -out " + decName.string() + @@ -219,20 +235,20 @@ void TABinaryManager::decryptImage(StructBinaryInfo& info) { } boost::system::error_code ec; - boost::filesystem::remove(boost::filesystem::path(info.imagePath), ec); + fs::remove(fs::path(info.imagePath), ec); if (ec) { LOGE(SIM_DAEMON, "Post decryption failed: unlink %s : %s", info.imagePath.c_str(), ec.message()); } - boost::filesystem::rename(decName, boost::filesystem::path(info.imagePath), ec); + fs::rename(decName, fs::path(info.imagePath), ec); if (ec) { LOGE(SIM_DAEMON, "Post decryption failed: rename %s -> %s : %s", decName.string().c_str(), info.imagePath.c_str(), ec.message()); } - boost::filesystem::remove(boost::filesystem::path(keyhashFilename), ec); + fs::remove(fs::path(keyhashFilename), ec); if (ec) { LOGE(SIM_DAEMON, "Post decryption failed: unlink %s : %s", keyhashFilename.c_str(), ec.message()); @@ -249,13 +265,13 @@ void TABinaryManager::decryptImage(StructBinaryInfo& info) { * It is very important to check for return value from this function. */ -bool TABinaryManager::unpackBinary(const string &uuid, StructBinaryInfo& info) { +bool TABinaryManager::unpackBinary(const string &uuid, const string& tapath, StructBinaryInfo& info) { TAUnpack* unpacker = TAUnpack::getInstance(); bool ret = false; - if (0 == unpacker->unpackTA(TEE_TASTORE_ROOT, uuid)) { + if (0 == unpacker->unpackTA(tapath, uuid)) { LOGD(SIM_DAEMON, "Unpacked, filling info"); // 1. Set binary info - info.path = string(TEE_TASTORE_ROOT) + uuid; + info.path = tapath + uuid; info.extractpath = string(TEE_EXTRACT_ROOT) + uuid + "-ext/"; info.imagePath = info.extractpath + uuid + ".image"; info.manifestPath = info.extractpath + uuid + ".manifest"; diff --git a/simulatordaemon/src/TABinaryManager/TABinaryManager.h b/simulatordaemon/src/TABinaryManager/TABinaryManager.h index 108fff0..b2b471d 100644 --- a/simulatordaemon/src/TABinaryManager/TABinaryManager.h +++ b/simulatordaemon/src/TABinaryManager/TABinaryManager.h @@ -64,7 +64,7 @@ private: // map < string uuid, StructBinaryInfo> map binaryMap; TABinaryManager(); - bool unpackBinary(const string &uuid, StructBinaryInfo& info); + bool unpackBinary(const string &uuid, const string& tapath, StructBinaryInfo& info); template std::string IntToHex(T i, int width = sizeof(T) * 2) { std::stringstream stream; diff --git a/simulatordaemon/src/TABinaryManager/TAUnpack.cpp b/simulatordaemon/src/TABinaryManager/TAUnpack.cpp index 28c906a..bda56dc 100644 --- a/simulatordaemon/src/TABinaryManager/TAUnpack.cpp +++ b/simulatordaemon/src/TABinaryManager/TAUnpack.cpp @@ -28,14 +28,17 @@ #include #include #include +#include #include #include #include #include #include +#include #include using namespace std; +namespace fs = boost::filesystem; /*----------------------------------------------------------------------------- * Globals @@ -66,14 +69,17 @@ int TAUnpack::unpackTA(const string& path, const string& uuid) { TAPackageHeaderV2 packageHeader; memset(&packageHeader, 0, sizeof(TAPackageHeaderV2)); - // Create directory for TA extracted files + // Re-create directory for TA extracted files string extract_dir_path = TEE_EXTRACT_ROOT + uuid + "-ext/"; - struct stat info; - if (stat(extract_dir_path.c_str(), &info) != 0) { - if (0 != mkdir(extract_dir_path.c_str(), 0777)) { - LOGE(SIM_DAEMON, "mkdir failed %s %s", extract_dir_path.c_str(), strerror(errno)); - return -1; - } + boost::system::error_code ec; + fs::remove_all(extract_dir_path, ec); + if (ec != 0){ + LOGE(SIM_DAEMON, "remove_all failed %s %s (trying to continue)", extract_dir_path.c_str(), ec.message().c_str()); + } + fs::create_directory(extract_dir_path, ec); + if (ec != 0){ + LOGE(SIM_DAEMON, "create_directory failed %s %s", extract_dir_path.c_str(), ec.message().c_str()); + return -1; } // Open TA package file -- 2.7.4