From 4d44b94f49a5e2868f0e2b6c7fb4d806f9d70e3c Mon Sep 17 00:00:00 2001 From: Maxime Gervais Date: Thu, 18 Apr 2024 21:19:59 +0200 Subject: [PATCH 1/4] Update tfsxml Signed-off-by: Maxime Gervais --- Source/ThirdParty/tfsxml/tfsxml.c | 1088 ++++++++++++++++------------- Source/ThirdParty/tfsxml/tfsxml.h | 71 +- 2 files changed, 640 insertions(+), 519 deletions(-) diff --git a/Source/ThirdParty/tfsxml/tfsxml.c b/Source/ThirdParty/tfsxml/tfsxml.c index ff31dbcf..450c48a1 100644 --- a/Source/ThirdParty/tfsxml/tfsxml.c +++ b/Source/ThirdParty/tfsxml/tfsxml.c @@ -1,22 +1,24 @@ -/* Copyright (c) MediaArea.net SARL. All Rights Reserved. +/* Copyright (c) MediaArea.net SARL -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. +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: -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. -1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. +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. -(zlib license) +(MIT License) */ @@ -35,7 +37,7 @@ freely, subject to the following restrictions: /* * priv flags : * 0: is inside an element header - * 1: previous element is closed + * 1: previous element is open (potentially with sub elements) */ /* @@ -43,68 +45,68 @@ freely, subject to the following restrictions: * 0: must be decoded */ -static inline void set_flag(tfsxml_string* priv, int offset) -{ +static inline void set_flag(tfsxml_string* priv, int offset) { priv->flags |= (1 << offset); } -static inline int get_flag(tfsxml_string* priv, int offset) -{ +static inline int get_flag(tfsxml_string* priv, int offset) { return priv->flags & (1 << offset); } -static inline void unset_flag(tfsxml_string* priv, int offset) -{ +static inline void unset_flag(tfsxml_string* priv, int offset) { priv->flags &= ~(1 << offset); } -static inline void next_char(tfsxml_string* priv) +#define set_is_in_element_header() set_flag(priv, 0) +#define get_is_in_element_header() get_flag(priv, 0) +#define unset_is_in_element_header() unset_flag(priv, 0) +#define set_previous_element_is_open() set_flag(priv, 1) +#define get_previous_element_is_open() get_flag(priv, 1) +#define unset_previous_element_is_open() unset_flag(priv, 1) + +#define set_must_be_decoded() set_flag(v, 0) + +static inline void set_level(tfsxml_string* priv, int level) { - priv->buf++; - priv->len--; + const int offset = (sizeof(priv->flags) - 1) * 8; + priv->flags <<= 8; + priv->flags >>= 8; + priv->flags |= level << offset; } -static inline int tfsxml_leave_element_header(tfsxml_string* priv) +static inline void get_level(tfsxml_string* priv, unsigned* level) { - /* Skip attributes */ - tfsxml_string n, v; - while (!tfsxml_attr(priv, &n, &v)); - - return 0; + const int offset = (sizeof(priv->flags) - 1) * 8; + *level = priv->flags >> offset; } +static inline void next_char(tfsxml_string* priv) { + priv->buf++; + priv->len--; +} -static inline int tfsxml_has_value(tfsxml_string* v) -{ - int is_end = 0; - const char* buf = v->buf; - int len = v->len; - while (len && !is_end) - { - switch (*buf) - { - case '\n': - case '\t': - case '\r': - case ' ': - buf++; - len--; - break; - default: - is_end = 1; +static int tfsxml_leave_element_header(tfsxml_string* priv) { + /* Skip attributes */ + tfsxml_string n, v; + for (;;) { + int result = tfsxml_attr(priv, &n, &v); + switch (result) { + case -1: { + return 0; + } + case 1: { + return 1; + } + default: { + } } } - if (is_end) - return 0; - return -1; } -int tfsxml_strcmp_charp(tfsxml_string a, const char* b) -{ - /* Compare char per charand return the difference if chars are no equal */ - for (; a.len && *b; a.buf++, a.len--, b++) - { - char c = *a.buf - *b; +int tfsxml_strcmp_charp(tfsxml_string a, const char* b) { + /* Compare char per char and return the difference if chars are no equal */ + for (; a.len && *b; a.buf++, a.len--, b++) { + int c = *a.buf - *b; if (c) return c; } @@ -117,23 +119,26 @@ int tfsxml_strcmp_charp(tfsxml_string a, const char* b) return *a.buf; /* a is longer than b */ } -tfsxml_string tfsxml_strstr_charp(tfsxml_string a, const char* b) -{ +int tfsxml_strncmp_charp(tfsxml_string a, const char* b, unsigned n) { + tfsxml_string a2 = a; + if (a2.len > n) + a2.len = n; + return tfsxml_strcmp_charp(a2, b); +} + +tfsxml_string tfsxml_strstr_charp(tfsxml_string a, const char* b) { /* Iterate string to be scanned */ - for (; a.len; a.buf++, a.len--) - { + for (; a.len; a.buf++, a.len--) { const char* buf = a.buf; int len = a.len; const char* bb = b; /* Compare char per char */ - for (; len && *bb; buf++, len--, bb++) - { + for (; len && *bb; buf++, len--, bb++) { char c = *buf - *bb; if (c) break; } - if (!len || *bb) - { + if (!len || *bb) { return a; } } @@ -142,16 +147,18 @@ tfsxml_string tfsxml_strstr_charp(tfsxml_string a, const char* b) return a; } -int tfsxml_init(tfsxml_string* priv, const void* buf, int len) -{ +int tfsxml_init(tfsxml_string* priv, const void* buf, unsigned len, unsigned version) { const char* buf_8 = (const char*)buf; + if (version != 0) { + return -1; + } + /* BOM detection */ if (len > 3 && (unsigned char)buf_8[0] == 0xEF && (unsigned char)buf_8[1] == 0xBB - && (unsigned char)buf_8[2] == 0xBF) - { + && (unsigned char)buf_8[2] == 0xBF) { buf_8 += 3; len -= 3; } @@ -166,518 +173,578 @@ int tfsxml_init(tfsxml_string* priv, const void* buf, int len) priv->buf = (const char*)buf; priv->len = len; priv->flags = 0; - set_flag(priv, 1); return 0; } -int tfsxml_next(tfsxml_string* priv, tfsxml_string* n) -{ - int level; +int tfsxml_next(tfsxml_string* priv, tfsxml_string* n) { + tfsxml_string priv_bak; + unsigned level; + + get_level(priv, &level); /* Exiting previous element header analysis if needed */ - if (get_flag(priv, 0) && tfsxml_leave_element_header(priv)) - return -1; + if (!level && get_is_in_element_header()) { + int result = tfsxml_leave_element_header(priv); + if (result) { + return result; + } + } /* Leaving previous element content if needed */ - if (!get_flag(priv, 1) && tfsxml_leave(priv)) - return -1; + if (level || get_previous_element_is_open()) { + if (!level && get_previous_element_is_open()) { + level++; + } + level--; + set_level(priv, level); + int result = tfsxml_leave(priv); + if (result) { + return result; + } + get_level(priv, &level); + } - level = 0; - while (priv->len) - { - switch (*priv->buf) - { - case '<': - next_char(priv); - if (priv->len && *priv->buf == '?') - { - n->buf = priv->buf; - while (priv->len && *priv->buf != '>') - { - next_char(priv); - } - n->len = priv->buf - n->buf; - if (priv->len) - next_char(priv); - set_flag(priv, 1); - return 0; - } - if (priv->len && *priv->buf == '!') - { - unsigned long long probe = 0; - int i; - for (i = 1; i < 8; i++) - { - probe <<= 8; - probe |= priv->buf[i]; + priv_bak = *priv; + while (priv->len) { + switch (*priv->buf) { + case '<': { + if (priv->len == 1) { + *priv = priv_bak; + set_level(priv, level); + return 1; } - if (probe == 0x5B43444154415BULL) /* "[CDATA[" */ - { - probe = 0; - priv->buf += 9; - priv->len -= 9; - while (priv->len) - { - probe &= 0xFFFF; - probe <<= 8; - probe |= *priv->buf; - if (probe == 0x5D5D3EULL) /* "]]>" */ - break; - priv->buf++; - priv->len--; + if (priv->buf[1] == '/') { + while (priv->len && *priv->buf != '>') { + next_char(priv); } - break; - } - n->buf = priv->buf; - if (priv->len >= 3 && priv->buf[1] == '-' && priv->buf[2] == '-') - { - int len_sav = priv->len; - const char* buf = priv->buf + 3; - int len = priv->len - 3; - probe = 0; - while (len) - { - probe &= 0xFFFF; - probe <<= 8; - probe |= *buf; - if (probe == 0x2D2D3EULL) /* "-->" */ - break; - buf++; - len--; + if (!priv->len) { + *priv = priv_bak; + set_level(priv, level); + return 1; } - n->buf = priv->buf; - n->len = len_sav - len; - priv->buf += n->len; - priv->len -= n->len; - if (priv->len) + if (!level) { next_char(priv); - return 0; + unset_previous_element_is_open(); + set_level(priv, level); + return -1; + } + level--; + break; } - while (priv->len && *priv->buf != '>') + if (priv->buf[1] == '?') { next_char(priv); - n->len = priv->buf - n->buf; - if (priv->len) - next_char(priv); - set_flag(priv, 1); - return 0; - } - if (*priv->buf == '/') - { - while (priv->len && *priv->buf != '>') + n->buf = priv->buf; + while (priv->len && *priv->buf != '>') { + next_char(priv); + } + if (!priv->len) { + *priv = priv_bak; + set_level(priv, level); + return 1; + } + n->len = priv->buf - n->buf; next_char(priv); - next_char(priv); - if (!level) - { - n->buf = NULL; - n->len = 0; - set_flag(priv, 1); - return -1; + unset_previous_element_is_open(); + set_level(priv, 0); + return 0; } - level--; - break; - } - if (!level) - { - n->buf = priv->buf; - for (;;) - { - if (!priv->len) - return -1; - - switch (*priv->buf) - { - case '\n': - case '\t': - case '\r': - case ' ': - case '/': - case '>': + if (priv->buf[1] == '!') { + unsigned long long probe = 0; + int i; + if (priv->len <= 8) { + *priv = priv_bak; + set_level(priv, level); + return 1; + } + for (i = 2; i <= 8; i++) { + probe <<= 8; + probe |= priv->buf[i]; + } + if (probe == 0x5B43444154415BULL) { /* "buf += 9; + priv->len -= 9; + while (priv->len) { + probe &= 0xFFFF; + probe <<= 8; + probe |= *priv->buf; + if (probe == 0x5D5D3EULL) { /* "]]>" */ + break; + } + next_char(priv); + } + if (!priv->len) { + *priv = priv_bak; + set_level(priv, level); + return 1; + } + break; + } + if ((probe >> 40) == 0x2D2D) { /* "" */ + break; + next_char(priv); + } + if (!priv->len) { + *priv = priv_bak; + set_level(priv, level); + return 1; + } n->len = priv->buf - n->buf; - set_flag(priv, 0); - unset_flag(priv, 1); + next_char(priv); + unset_previous_element_is_open(); + set_level(priv, 0); return 0; - default:; } + while (priv->len && *priv->buf != '>') { + next_char(priv); + } + if (!priv->len) { + *priv = priv_bak; + set_level(priv, level); + return 1; + } + n->buf = priv_bak.buf; + n->len = priv->buf - n->buf; next_char(priv); + unset_previous_element_is_open(); + set_level(priv, 0); + return 0; } + if (!level) { + next_char(priv); + n->buf = priv->buf; + for (;;) { + if (!priv->len) { + *priv = priv_bak; + set_level(priv, level); + return 1; + } + + switch (*priv->buf) { + case '\n': + case '\t': + case '\r': + case ' ': + case '/': + case '>': + n->len = priv->buf - n->buf; + set_is_in_element_header(); + set_previous_element_is_open(); + set_level(priv, 0); + return 0; + default: { + } + } + next_char(priv); + } + } + level++; + break; + } + default: { } - level++; - break; - default:; } next_char(priv); } - n->buf = NULL; - n->len = 0; - unset_flag(priv, 0); - unset_flag(priv, 1); - return -1; + set_level(priv, level); + return 1; } -int tfsxml_attr(tfsxml_string* priv, tfsxml_string* n, tfsxml_string* v) -{ - if (!get_flag(priv, 0)) +int tfsxml_attr(tfsxml_string* priv, tfsxml_string* n, tfsxml_string* v) { + if (!get_is_in_element_header()) { return -1; + } v->flags = 0; - while (priv->len) - { - switch (*priv->buf) - { - case '\n': - case '\t': - case '\r': - case ' ': - break; - case '/': - set_flag(priv, 1); - break; - case '>': - next_char(priv); - n->buf = NULL; - n->len = 0; - v->buf = NULL; - v->len = 0; - v->flags = 0; - unset_flag(priv, 0); - return -1; - default: - { - /* Attribute */ - n->buf = priv->buf; - while (priv->len && *priv->buf != '=') - { - next_char(priv); + tfsxml_string priv_bak = *priv; + while (priv->len) { + switch (*priv->buf) { + case '/': { + unset_previous_element_is_open(); + //fall through + } + case '\n': + case '\t': + case '\r': + case ' ': { + break; } - n->len = priv->buf - n->buf; - if (!priv->len) + case '>': { + next_char(priv); + unset_is_in_element_header(); return -1; - next_char(priv); - } - { - /* Value */ - const char quote = *priv->buf; - next_char(priv); - v->buf = priv->buf; - while (priv->len && *priv->buf != quote) - { - if (*priv->buf == '&') - set_flag(v, 0); + } + default: { + if (!get_previous_element_is_open()) { + break; // Junk after "/", ignoring + } + + /* Attribute */ + n->buf = priv->buf; + while (priv->len && *priv->buf != '=') { + next_char(priv); + } + if (!priv->len) { + *priv = priv_bak; + return 1; + } + n->len = priv->buf - n->buf; next_char(priv); + + /* Value */ + const char quote = *priv->buf; + if (!priv->len) { + *priv = priv_bak; + return 1; + } + next_char(priv); + v->buf = priv->buf; + while (priv->len && *priv->buf != quote) { + if (*priv->buf == '&') { + set_flag(v, 0); + } + next_char(priv); + } + v->len = priv->buf - v->buf; + if (!priv->len) { + *priv = priv_bak; + return 1; + } + next_char(priv); + return 0; } - v->len = priv->buf - v->buf; - if (!priv->len) - return -1; - next_char(priv); - return 0; - } } next_char(priv); } - n->buf = NULL; - n->len = 0; - n->flags = 0; - v->buf = NULL; - v->len = 0; - v->flags = 0; - unset_flag(priv, 0); - return -1; + *priv = priv_bak; + return 1; } - -int tfsxml_value(tfsxml_string* priv, tfsxml_string* v) -{ - tfsxml_string priv_bak = *priv; - int len_sav; +int tfsxml_value(tfsxml_string* priv, tfsxml_string* v) { + tfsxml_string priv_bak; + unsigned len_sav; /* Exiting previous element header analysis if needed */ - int is_first = 0; - if (get_flag(priv, 0)) - { - if (tfsxml_leave_element_header(priv)) - return -1; - is_first = 1; - - /* Previous element must not be finished */ - if (get_flag(priv, 1)) - return -1; + if (get_is_in_element_header()) { + int result = tfsxml_leave_element_header(priv); + if (result) { + return result; + } } + /* Previous element must not be finished */ + if (!get_previous_element_is_open()) { + return -1; + } + + priv_bak = *priv; len_sav = priv->len; v->flags = 0; - while (priv->len) - { - switch (*priv->buf) - { - case '&': - set_flag(v, 0); - break; - case '<': - if (priv->len == len_sav && priv->len > 8) - { - unsigned long long probe = 0; - int i; - for (i = 1; i <= 8; i++) - { - probe <<= 8; - probe |= priv->buf[i]; + while (priv->len) { + switch (*priv->buf) { + case '&': { + set_must_be_decoded(); + break; + } + case '<': { + if (priv->len == 1) { + *priv = priv_bak; + return 1; } - if (probe == 0x215B43444154415BULL) /* "![CDATA[" */ - { - const char* buf = priv->buf + 9; - int len = priv->len - 9; - probe = 0; - while (len) - { - probe &= 0xFFFF; + if (priv->buf[1] == '!') { + if (priv->len <= 8) { + *priv = priv_bak; + return 1; + } + unsigned long long probe = 0; + int i; + for (i = 2; i <= 8; i++) { probe <<= 8; - probe |= *buf; - if (probe == 0x5D5D3EULL) /* "]]>" */ - break; - buf++; - len--; - } - v->buf = priv->buf; - v->len = len_sav - len; - if (v->len < priv->len) - v->len++; - priv->buf += v->len; - priv->len -= v->len; - v->buf += 9; - v->len -= 12; - return 0; + probe |= priv->buf[i]; + } + if (probe == 0x5B43444154415BULL) { /* "buf += 9; + priv->len -= 9; + while (priv->len) { + probe &= 0xFFFF; + probe <<= 8; + probe |= *priv->buf; + if (probe == 0x5D5D3EULL) { /* "]]>" */ + break; + } + next_char(priv); + } + if (!priv->len) { + *priv = priv_bak; + return 1; + } + break; + } } + v->len = len_sav - priv->len; + v->buf = priv->buf - v->len; + set_previous_element_is_open(); + set_level(priv, 0); + int result = tfsxml_leave(priv); + if (result) { + *priv = priv_bak; + return result; + } + return 0; } - v->len = len_sav - priv->len; - v->buf = priv->buf - v->len; - if (tfsxml_has_value(v)) - { - *priv = priv_bak; - return -1; - } - if (is_first) - { - unset_flag(priv, 1); - tfsxml_leave(priv); + default: { } - return 0; - default:; } next_char(priv); } - - v->len = len_sav; - v->buf = priv->buf - v->len; - v->flags = 0; - if (tfsxml_has_value(v)) - { - *priv = priv_bak; - return -1; - } - return 0; + *priv = priv_bak; + return 1; } -int tfsxml_enter(tfsxml_string* priv) -{ - /* Exiting previous element header analysis if needed */ - if (get_flag(priv, 0) && tfsxml_leave_element_header(priv)) - return -1; +int tfsxml_enter(tfsxml_string* priv) { + /* Exiting previous element header if needed */ + if (get_is_in_element_header()) { + int result = tfsxml_leave_element_header(priv); + if (result) { + return result; + } + } /* Previous element must not be finished */ - if (get_flag(priv, 1)) + if (!get_previous_element_is_open()) { return -1; + } - set_flag(priv, 1); + unset_previous_element_is_open(); return 0; } -int tfsxml_leave(tfsxml_string* priv) -{ - int level; +int tfsxml_leave(tfsxml_string* priv) { + tfsxml_string priv_bak; + unsigned level; + + get_level(priv, &level); + level++; /* Exiting previous element header analysis if needed */ - if (get_flag(priv, 0) && tfsxml_leave_element_header(priv)) - return -1; + if (get_is_in_element_header()) { + int result = tfsxml_leave_element_header(priv); + if (result) { + get_level(priv, &level); + set_level(priv, level - 1); + return result; + } + if (get_previous_element_is_open()) { + level++; + } + } - level = get_flag(priv, 1) ? 1 : 0; - while (priv->len) - { - switch (*priv->buf) - { - case '<': - next_char(priv); - if (priv->len && *priv->buf == '/') - { - if (!level) - { - while (priv->len && *priv->buf != '>') - next_char(priv); - next_char(priv); - set_flag(priv, 1); - return 0; - } - level--; - if (priv->len) - next_char(priv); - break; - } - if (priv->len && *priv->buf == '?') - { - while (priv->len && *priv->buf != '>') - { - next_char(priv); + set_previous_element_is_open(); + priv_bak = *priv; + while (priv->len) { + switch (*priv->buf) { + case '<': { + priv_bak = *priv; + if (priv->len == 1) { + *priv = priv_bak; + set_level(priv, level - 1); + return 1; } - if (priv->len) - next_char(priv); - set_flag(priv, 1); - break; - } - if (priv->len && *priv->buf == '!') - { - unsigned long long probe = 0; - int i; - for (i = 1; i < 8; i++) - { - probe <<= 8; - probe |= priv->buf[i]; + if (priv->buf[1] == '/') { + while (priv->len && *priv->buf != '>') { + next_char(priv); + } + if (!priv->len) { + *priv = priv_bak; + set_level(priv, level - 1); + return 1; + } + level--; + if (!level) { + next_char(priv); + unset_previous_element_is_open(); + set_level(priv, 0); + return 0; + } + priv_bak = *priv; + break; } - if (probe == 0x5B43444154415BULL) /* "[CDATA[" */ - { - probe = 0; - priv->buf += 9; - priv->len -= 9; - while (priv->len) - { - probe &= 0xFFFF; - probe <<= 8; - probe |= *priv->buf; - if (probe == 0x5D5D3EULL) /* "]]>" */ - break; - priv->buf++; - priv->len--; + if (priv->buf[1] == '?') { + while (priv->len && *priv->buf != '>') { + next_char(priv); + } + if (!priv->len) { + *priv = priv_bak; + set_level(priv, level - 1); + return 1; } + unset_previous_element_is_open(); break; } - if (priv->len >= 3 && priv->buf[1] == '-' && priv->buf[2] == '-') - { - const char* buf = priv->buf + 3; - int len_sav = priv->len; - int len = priv->len - 3; - probe = 0; - while (len) - { - probe &= 0xFFFF; + if (priv->buf[1] == '!') { + unsigned long long probe = 0; + int i; + if (priv->len <= 8) { + *priv = priv_bak; + set_level(priv, level - 1); + return 1; + } + for (i = 2; i <= 8; i++) { probe <<= 8; - probe |= *buf; - if (probe == 0x2D2D3EULL) /* "-->" */ - break; - buf++; - len--; + probe |= priv->buf[i]; + } + if (probe == 0x5B43444154415BULL) { /* "buf += 9; + priv->len -= 9; + while (priv->len) { + probe &= 0xFFFF; + probe <<= 8; + probe |= *priv->buf; + if (probe == 0x5D5D3EULL) { /* "]]>" */ + break; + } + next_char(priv); + } + if (!priv->len) { + *priv = priv_bak; + set_level(priv, level - 1); + return 1; + } + break; } - len = len_sav - len; - priv->buf += len; - priv->len -= len; - if (priv->len) + if ((probe >> 40) == 0x2D2D) { /* "" */ + break; + next_char(priv); + } + if (!priv->len) { + *priv = priv_bak; + set_level(priv, level - 1); + return 1; + } + break; + } + while (priv->len && *priv->buf != '>') { next_char(priv); + } + if (!priv->len) { + *priv = priv_bak; + set_level(priv, level - 1); + return 1; + } + next_char(priv); break; } - while (priv->len && *priv->buf != '>') + for (;;) { + int split; + + if (!priv->len) { + *priv = priv_bak; + set_level(priv, level - 1); + return 1; + } + + split = 0; + switch (*priv->buf) { + case '\n': + case '\t': + case '\r': + case ' ': + case '/': + case '>': { + set_is_in_element_header(); + set_previous_element_is_open(); + split = 1; + break; + } + default: { + } + } + if (split) + break; next_char(priv); - next_char(priv); - break; - } - for (;;) - { - int split; - - if (!priv->len) - return -1; - - split = 0; - switch (*priv->buf) - { - case '\n': - case '\t': - case '\r': - case ' ': - case '/': - case '>': - set_flag(priv, 0); - unset_flag(priv, 1); - split = 1; - break; - default:; } - if (split) - break; - next_char(priv); + int result = tfsxml_leave_element_header(priv); + if (result) { + set_is_in_element_header(); + set_previous_element_is_open(); + set_level(priv, level - 1); + return result; + } + if (get_previous_element_is_open()) { + level++; + set_previous_element_is_open(); + } + continue; + } + default: { } - if (tfsxml_leave_element_header(priv)) - return -1; - if (!get_flag(priv, 1)) - level++; - break; - default:; - next_char(priv); } + next_char(priv); } - - set_flag(priv, 1); - set_flag(priv, 3); - return 0; + set_level(priv, level - 1); + return 1; } -static const char* const tfsxml_decode_markup[2] = -{ +static const char* const tfsxml_decode_markup[2] = { "amp\0apos\0gt\0lt\0quot", "&'><\"", }; -void tfsxml_decode(void* s, const tfsxml_string* v, void (*func)(void*, const char*, int)) -{ +void tfsxml_decode(void* s, const tfsxml_string* v, void (*func)(void*, const char*, unsigned)) { const char* buf_begin; const char* buf = v->buf; - int len = v->len; + unsigned len = v->len; - if (!(v->flags & 1)) - { + if (!(v->flags & 1)) { func(s, buf, len); return; } buf_begin = buf; - while (len) - { - if (*buf == '&') - { + while (len) { + if (*buf == '&') { const char* buf_end = buf; int len_end = len; - while (len_end && *buf_end != ';') - { + while (len_end && *buf_end != ';') { buf_end++; len_end--; } - if (len_end) - { + if (len_end) { const char* buf_beg = buf + 1; - int len_beg = buf_end - buf_beg; - if (len_beg && *buf_beg == '#') - { + unsigned len_beg = buf_end - buf_beg; + if (len_beg && *buf_beg == '#') { unsigned long value = 0; buf_beg++; len_beg--; - if (*buf_beg == 'x' || *buf_beg == 'X') - { + if (*buf_beg == 'x' || *buf_beg == 'X') { buf_beg++; len_beg--; - while (len_beg) - { + while (len_beg) { char c = *buf_beg++; len_beg--; value <<= 4; - if (value >= 0x110000) - { + if (value >= 0x110000) { value = -1; break; } @@ -687,58 +754,48 @@ void tfsxml_decode(void* s, const tfsxml_string* v, void (*func)(void*, const ch value |= c - ('A' - 10); else if (c >= 'a' && c <= 'f') value |= c - ('a' - 10); - else - { + else { value = -1; break; } } } - else - { - while (len_beg) - { + else { + while (len_beg) { char c = *buf_beg++; len_beg--; - if (c < '0' || c > '9') - { + if (c < '0' || c > '9') { value = -1; break; } value *= 10; value += c - '0'; - if (value >= 0x110000) - { + if (value >= 0x110000) { value = -1; break; } } } - if (value != (unsigned long)-1) - { + if (value != (unsigned long)-1) { char utf8[4]; func(s, buf_begin, buf - buf_begin); - if (value < 0x0080) - { + if (value < 0x0080) { utf8[0] = (char)value; func(s, utf8, 1); } - else if (value < 0x0800) - { + else if (value < 0x0800) { utf8[0] = 0xC0 | (char)(value >> 6); utf8[1] = 0x80 | (char)(value & 0x3F); func(s, utf8, 2); } - else if (value < 0x10000) - { + else if (value < 0x10000) { utf8[0] = 0xE0 | (char)((value >> 12)); utf8[1] = 0x80 | (char)((value >> 6) & 0x3F); utf8[2] = 0x80 | (char)((value & 0x3F)); func(s, utf8, 3); } - else if (value < 0x110000) - { + else if (value < 0x110000) { utf8[0] = 0xF0 | (char)((value >> 18)); utf8[1] = 0x80 | (char)((value >> 12) & 0x3F); utf8[2] = 0x80 | (char)((value >> 6) & 0x3F); @@ -751,26 +808,23 @@ void tfsxml_decode(void* s, const tfsxml_string* v, void (*func)(void*, const ch buf_begin = buf_end + 1; } } - else - { + else { const char* const buf_beg_sav = buf_beg; const char* replaced = tfsxml_decode_markup[0]; const char* replace_bys = tfsxml_decode_markup[1]; - for (;;) - { + for (;;) { char replace_by = *replace_bys++; - if (!replace_by) + if (!replace_by) { break; + } - while (*replaced) - { + while (*replaced) { if (buf_beg == buf_end || !*replaced || *replaced != *buf_beg) break; replaced++; buf_beg++; } - if (buf_beg == buf_end && !*replaced) - { + if (buf_beg == buf_end && !*replaced) { func(s, buf_begin, buf - buf_begin); func(s, &replace_by, 1); len -= buf_end - buf; @@ -779,13 +833,41 @@ void tfsxml_decode(void* s, const tfsxml_string* v, void (*func)(void*, const ch break; } buf_beg = buf_beg_sav; - while (*replaced) + while (*replaced) { replaced++; + } replaced++; } } } } + if (*buf == '<' && len > 8) { + unsigned long long probe = 0; + int i; + for (i = 1; i <= 8; i++) { + probe <<= 8; + probe |= buf[i]; + } + if (probe == 0x215B43444154415BULL) { /* "" */ + break; + } + buf++; + len--; + } + func(s, buf_begin, buf - 2 - buf_begin); + buf_begin = buf + 1; + } + } buf++; len--; } diff --git a/Source/ThirdParty/tfsxml/tfsxml.h b/Source/ThirdParty/tfsxml/tfsxml.h index 0ca54f3b..321f804d 100644 --- a/Source/ThirdParty/tfsxml/tfsxml.h +++ b/Source/ThirdParty/tfsxml/tfsxml.h @@ -1,3 +1,27 @@ +/* Copyright (c) MediaArea.net SARL + +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. + +(MIT License) + +*/ + /* * Tiny Fast Streamable XML parser */ @@ -28,22 +52,22 @@ extern "C" * * @note after init, priv should not be directly used (data may be something else than a buf/len pair) */ - typedef struct tfsxml_string -{ +typedef struct tfsxml_string { const char* buf; - int len; - int flags; + unsigned len; + unsigned flags; } tfsxml_string; /** Initialize the parser * - * @param priv pointer to a tfsxml_string dedicated instance, private use by the parser - * @param buf pointer to start of the buffer - * @param len length of the buffer + * @param priv pointer to a tfsxml_string dedicated instance, private use by the parser + * @param buf pointer to start of the buffer + * @param len length of the buffer + * @param version API version supported by the client * * @note after init, priv should not be directly used (data may be something else than a buf/len pair) */ -int tfsxml_init(tfsxml_string* priv, const void* buf, int len); +int tfsxml_init(tfsxml_string* priv, const void* buf, unsigned len, unsigned version); /** Get next element or other content except an element value * @@ -52,6 +76,7 @@ int tfsxml_init(tfsxml_string* priv, const void* buf, int len); * * @return 0 if an element is available at the current level * -1 if no element is available at the current level + * 1 if need of more data */ int tfsxml_next(tfsxml_string* priv, tfsxml_string* n); @@ -63,6 +88,7 @@ int tfsxml_next(tfsxml_string* priv, tfsxml_string* n); * * @return 0 if an attribute is available for the current element * -1 if no more attribute is available for the current element + * 1 if need of more data */ int tfsxml_attr(tfsxml_string* priv, tfsxml_string* n, tfsxml_string* v); @@ -73,6 +99,7 @@ int tfsxml_attr(tfsxml_string* priv, tfsxml_string* n, tfsxml_string* v); * * @return 0 if a value is available for the current element * -1 if no value is available for the current element + * 1 if need of more data * * @note if this element has sub-elements, the whole content (all sub-elements) are provided */ @@ -84,6 +111,7 @@ int tfsxml_value(tfsxml_string* priv, tfsxml_string* v); * * @return 0 if it is possible to enter in an element * -1 if it is not possible to enter in an element + * 1 if need of more data */ int tfsxml_enter(tfsxml_string* priv); @@ -93,6 +121,7 @@ int tfsxml_enter(tfsxml_string* priv); * * @return 0 if it is possible to leave an element * -1 if it is not possible to leave an element + * 1 if need of more data */ int tfsxml_leave(tfsxml_string* priv); @@ -102,17 +131,17 @@ int tfsxml_leave(tfsxml_string* priv); /** Convert encoded XML block (attribute or value) to real content (encoded in UTF-8) * - * @param s opaque data transmitted to func - * @param b XML content to decode - * @param func function that will receive blocks of decoded content + * @param s opaque data transmitted to func + * @param v XML content to decode + * @param func append function that will receive blocks of decoded content * - * @param func_s s - * @param buf decoded content - * @param len length of the decoded content + * @param func_s string to append to + * @param func_buf decoded content + * @param func_len length of the decoded content * * @note see tfsxml_decode_string C++ function for an example of usage */ -void tfsxml_decode(void* s, const tfsxml_string* v, void (*func)(void* func_s, const char* func_buf, int func_len)); +void tfsxml_decode(void* s, const tfsxml_string* v, void (*func)(void* func_s, const char* func_buf, unsigned func_len)); /** ------------------------------------------------------------------------- Helper functions related to tfsxml_string @@ -127,6 +156,16 @@ void tfsxml_decode(void* s, const tfsxml_string* v, void (*func)(void* func_s, c */ int tfsxml_strcmp_charp(tfsxml_string a, const char* b); +/** Compare two strings + * + * @param a string to compare + * @param b string to compare + * @param n maximum number of characters to compare + * + * @note similar to C strncmp function + */ +int tfsxml_strncmp_charp(tfsxml_string a, const char* b, unsigned n); + /** Locate substring * * @param a string to be scanned @@ -141,7 +180,7 @@ tfsxml_string tfsxml_strstr_charp(tfsxml_string a, const char* b); #endif /* defined(__cplusplus) && !defined(TFSXML_NAMESPACE) */ #ifdef __cplusplus -static void tfsxml_decode_string(void* d, const char* buf, int len) { ((std::string*)d)->append(buf, len); } +static void tfsxml_decode_string(void* d, const char* buf, unsigned len) { ((std::string*)d)->append(buf, len); } /** Convert encoded XML block (attribute or value) to real content (encoded in UTF-8) * From 188a381c3bafb95d0bdaa58fa8db2dadc32a0a14 Mon Sep 17 00:00:00 2001 From: Maxime Gervais Date: Fri, 19 Apr 2024 15:46:13 +0200 Subject: [PATCH 2/4] Add fields compare in policy checker Signed-off-by: Maxime Gervais --- Source/Checker/Checker.cpp | 249 ++++++++++++++---- Source/Checker/Checker.h | 20 +- Source/Checker/Path.cpp | 5 +- Source/Common/DaemonClient.cpp | 17 ++ Source/Common/JS_Tree.cpp | 14 +- Source/Common/MediaConchLib.cpp | 15 +- Source/Common/MediaConchLib.h | 14 +- Source/Common/Policies.cpp | 8 + Source/Common/REST_API.cpp | 119 +++++++++ Source/Common/XsltPolicy.cpp | 135 +++++++++- Source/Common/XsltPolicy.h | 8 + .../ImplementationReportDisplayHtmlXsl.h | 31 ++- Source/Daemon/Daemon.cpp | 16 ++ Source/GUI/Qt/WebCommonPage.cpp | 99 ++++++- Source/GUI/Qt/WebCommonPage.h | 8 +- Source/Resource/displays/MediaConchHtml.xsl | 31 ++- Source/Resource/html/js/policy.js | 37 ++- Source/Resource/html/js/policyTree.js | 15 ++ Source/Resource/html/js/policyTreeRulesMI.js | 145 ++++++++-- Source/Resource/html/js/policyWebEngine.js | 82 ++++-- Source/Resource/html/js/policyWebKit.js | 59 ++++- .../html/js/publicPolicies/listPolicyTree.js | 22 +- Source/Resource/html/xslPolicy.html | 47 ++++ Source/Resource/mediaconch-js/MediaConch.js | 10 +- 24 files changed, 1062 insertions(+), 144 deletions(-) diff --git a/Source/Checker/Checker.cpp b/Source/Checker/Checker.cpp index fcc2a34e..4e2be86b 100644 --- a/Source/Checker/Checker.cpp +++ b/Source/Checker/Checker.cpp @@ -83,6 +83,40 @@ int tfsxml_next_named(tfsxml_string* tfsxml_priv, tfsxml_string* result, const c return -1; } +//--------------------------------------------------------------------------- +int tfsxml_hasvalue(tfsxml_string* priv) +{ + const char* buf = priv->buf; + unsigned len = priv->len; + while (len) + { + len--; + switch (*buf) + { + case '\n': + case '\t': + case '\r': + case ' ': + break; + case '<': + if (!len) + return 1; + buf++; + switch (*buf) + { + case '!': + case '/': + return 0; + default: + return -1; + } + default: + return 0; + } + } + return 1; +} + //--------------------------------------------------------------------------- std::string tokenize(const std::string& scope, const std::string& list, const std::string& delimiter) { @@ -246,13 +280,15 @@ std::string PolicyChecker::PolicyElement::to_string(size_t level, bool verbose) //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- -PolicyChecker::RuleElement::RuleElement() : resolved(false), pass(false), tracks(0) +PolicyChecker::RuleElement::RuleElement() : resolved(false), pass(false), tracks(0), source(NULL) { } //--------------------------------------------------------------------------- PolicyChecker::RuleElement::~RuleElement() { + if (source) + delete source; } //--------------------------------------------------------------------------- @@ -262,71 +298,73 @@ void PolicyChecker::RuleElement::reset() pass=false; tracks=0; values.clear(); + if (source) + source->values.clear(); } //--------------------------------------------------------------------------- -bool PolicyChecker::RuleElement::compare(const std::string& value) +bool PolicyChecker::RuleElement::compare(const std::string& v1, const std::string& v2) { bool to_return = false; char* val_end=NULL; - double val = strtod(value.c_str(), &val_end); + double val = strtod(v2.c_str(), &val_end); char* ref_end=NULL; - double ref = strtod(requested.c_str(), &ref_end); + double ref = strtod(v1.c_str(), &ref_end); if (operand=="starts with") { - to_return = value.rfind(requested, 0) == 0; + to_return = v2.rfind(v1, 0) == 0; } else if (operand=="must not start with") { - to_return = value.rfind(requested, 0) != 0; + to_return = v2.rfind(v1, 0) != 0; } else if (operand == "<") { if (!strlen(val_end) && !strlen(ref_end)) to_return = val < ref; else - to_return = strcmp(value.c_str(), requested.c_str()) < 0; + to_return = strcmp(v2.c_str(), v1.c_str()) < 0; } else if (operand == "<=") { if (!strlen(val_end) && !strlen(ref_end)) to_return = val <= ref; else - to_return = strcmp(value.c_str(), requested.c_str()) <= 0; + to_return = strcmp(v2.c_str(), v1.c_str()) <= 0; } else if (operand == "=") { if (!strlen(val_end) && !strlen(ref_end)) to_return = val == ref; else - to_return = strcmp(value.c_str(), requested.c_str()) == 0; + to_return = strcmp(v2.c_str(), v1.c_str()) == 0; } else if (operand == "!=") { if (!strlen(val_end) && !strlen(ref_end)) to_return = val != ref; else - to_return = strcmp(value.c_str(), requested.c_str()) != 0; + to_return = strcmp(v2.c_str(), v1.c_str()) != 0; } else if (operand == ">=") { if (!strlen(val_end) && !strlen(ref_end)) to_return = val >= ref; else - to_return = strcmp(value.c_str(), requested.c_str()) >= 0; + to_return = strcmp(v2.c_str(), v1.c_str()) >= 0; } else if (operand == ">") { if (!strlen(val_end) && !strlen(ref_end)) to_return = val > ref; else - to_return = strcmp(value.c_str(), requested.c_str()) > 0; + to_return = strcmp(v2.c_str(), v1.c_str()) > 0; } if (!to_return) - failing_values.push_back(value); + failing_values.push_back(v2); return to_return; } @@ -363,12 +401,48 @@ void PolicyChecker::RuleElement::resolve() } else if (operand=="starts with" || operand=="must not start with" || operand=="<" || operand=="<=" || operand=="=" || operand=="!=" || operand==">=" || operand==">") { - if (values.empty()) - pass = operand=="must not start with" ? true : false; - else if (occurrence=="all") - pass = std::all_of(values.begin(), values.end(), std::bind(&PolicyChecker::RuleElement::compare, this, std::placeholders::_1)); - else - pass = std::any_of(values.begin(), values.end(), std::bind(&PolicyChecker::RuleElement::compare, this, std::placeholders::_1)); + std::vector results; + + if (values.empty()) + pass=operand=="must not start with" ? true : false; + else + { + for (std::pair value : values) + { + if (source) + { + std::vector r2; + for (std::pair v2 : source->values) + { + if ((occurrence.empty() || occurrence=="any" || occurrence=="*" || + source->occurrence.empty() || source->occurrence=="all" || + source->occurrence=="any" || source->occurrence=="*") && + v2.first==value.first) + continue; + + r2.push_back(compare(v2.second, value.second)); + } + + if (r2.empty()) + continue; + + if (source->occurrence=="all") + results.push_back(std::all_of(r2.begin(), r2.end(), [this](bool result) { return result; })); + else + results.push_back(std::any_of(r2.begin(), r2.end(), [this](bool result) { return result; })); + } + else + results.push_back(compare(requested, value.second)); + } + + if (!results.empty()) + { + if (occurrence=="all") + pass=std::all_of(results.begin(), results.end(), [this](bool result) { return result; }); + else + pass=std::any_of(results.begin(), results.end(), [this](bool result) { return result; }); + } + } } resolved=true; @@ -414,18 +488,40 @@ std::string PolicyChecker::RuleElement::to_string(size_t level, bool verbose) if (result()>RESULT_PASS) value_str=failing_values.size() ? failing_values.front() : std::string(); else if (verbose) - value_str=values.size() ? values.front() : std::string(); + value_str=values.size() ? values.begin()->second : std::string(); ss << indent(level) << "level.empty()) ss << " level=\"" << xml_encode(this->level) << "\""; if (result()>RESULT_PASS || verbose) - ss << " requested=\"" << xml_encode(requested) << "\" actual=\"" << xml_encode(value_str) << "\""; - ss << " outcome=\"" << outcome_str << "\"/>" << std::endl; + ss << " requested=\"" + << (source && source->values.size() ? xml_encode(source->values.begin()->second) : xml_encode(requested)) + << "\" actual=\"" << xml_encode(value_str) << "\""; + ss << " outcome=\"" << outcome_str << "\""; + + if (source) + { + ss << ">" << std::endl; + + ss << indent(level +1) << "scope.empty()) + ss << " scope=\"" << xml_encode(source->scope) << "\""; + ss << " value=\"" << xml_encode(source->field) + << "\" tracktype=\"" << xml_encode(source->tracktype) + << "\" occurrence=\"" << (source->occurrence.size() ? xml_encode(source->occurrence) : "*") + << "\"/>" << std::endl; + + ss << indent(level) << "" << std::endl; + } + else + ss << "/>" << std::endl; return ss.str(); } @@ -487,27 +583,74 @@ PolicyChecker::RuleElement* PolicyChecker::parse_rule(tfsxml_string& tfsxml_priv rule->operand=tfsxml_decode(attribute_value); } - std::string occurrence=rule->occurrence; - if (occurrence.empty() || occurrence=="all" || occurrence=="any") - occurrence="*"; + if (!tfsxml_hasvalue(&tfsxml_priv)) + { + tfsxml_string value; + if (!tfsxml_value(&tfsxml_priv, &value)) + rule->requested = std::string(value.buf, value.len); + } + else + { + if (!tfsxml_enter(&tfsxml_priv)) + { + tfsxml_string value; + while (!tfsxml_next(&tfsxml_priv, &value)) + { + if (!tfsxml_strcmp_charp(value, "source")) + { + if (rule->source) + delete rule->source; + rule->source = new RuleElement::Source(); + while (!tfsxml_attr(&tfsxml_priv, &attribute_name, &attribute_value)) + { + if (!tfsxml_strcmp_charp(attribute_name, "scope")) + rule->source->scope=tfsxml_decode(attribute_value); + else if (!tfsxml_strcmp_charp(attribute_name, "value")) + rule->source->field=tfsxml_decode(attribute_value); + else if (!tfsxml_strcmp_charp(attribute_name, "tracktype")) + rule->source->tracktype=tfsxml_decode(attribute_value); + else if (!tfsxml_strcmp_charp(attribute_name, "occurrence")) + rule->source->occurrence=tfsxml_decode(attribute_value); + } - tfsxml_string value; - if (!tfsxml_value(&tfsxml_priv, &value)) - rule->requested=std::string(value.buf, value.len); + // Check for currently unsupported features + if (rule->scope=="mmt") + supported=false; + + if (rule->scope.empty() || rule->scope=="mi") + { + std::stringstream ss; + ss << "mi:MediaInfo/mi:track[@type='" + << rule->source->tracktype << "'][" + << ((rule->source->occurrence.empty() || rule->source->occurrence=="all" || rule->source->occurrence=="any") ? "*" : rule->source->occurrence) + << "]" + << tokenize(rule->source->scope, rule->source->field, "/"); + rule->source->path=parse_path(ss.str()); + } + break; + } + } + tfsxml_leave(&tfsxml_priv); + } + } // Check for presence of _StringX or TimeCode* element in policy size_t index=rule->field.find_last_not_of("0123456789"); if ((index!=std::string::npos && index>=6 && rule->field.substr(index-6, 7)=="_String") || rule->field.find("TimeCode")==0 || rule->field.rfind("_Total")==rule->field.size()-6) full=true; -// Check for currently unsupported features - if (rule->scope=="mmt" || rule->requested=="compare") + // Check for currently unsupported features + if (rule->scope=="mmt" || rule->requested =="compare") supported=false; if (rule->scope.empty() || rule->scope=="mi") { std::stringstream ss; - ss << "mi:MediaInfo/mi:track[@type='" << rule->tracktype << "'][" << occurrence << "]" << tokenize(rule->scope, rule->field, "/"); + ss << "mi:MediaInfo/mi:track[@type='" + << rule->tracktype + << "'][" + << ((rule->occurrence.empty() || rule->occurrence=="all" || rule->occurrence=="any") ? "*" : rule->occurrence) + << "]" << tokenize(rule->scope, rule->field, "/"); rule->xpath=ss.str(); rule->path=parse_path(rule->xpath); } @@ -569,7 +712,7 @@ void PolicyChecker::add_policy(const std::string& policy) tfsxml_string tfsxml_priv; tfsxml_string result; - tfsxml_init(&tfsxml_priv, (const void*)policy.c_str(), policy.size()); + tfsxml_init(&tfsxml_priv, (const void*)policy.c_str(), policy.size(), 0); while (!tfsxml_next(&tfsxml_priv, &result)) { if (!tfsxml_strcmp_charp(result, "policy")) @@ -583,12 +726,11 @@ void PolicyChecker::add_policy(const std::string& policy) } //--------------------------------------------------------------------------- -void PolicyChecker::parse_node(tfsxml_string& tfsxml_priv, std::vector rules, size_t level) +void PolicyChecker::parse_node(tfsxml_string& tfsxml_priv, std::vector rules, std::vector sources, size_t level) { - if (rules.empty()) + if (rules.empty() && sources.empty()) return; - tfsxml_string tfsxml_priv_save = tfsxml_priv; if (!tfsxml_enter(&tfsxml_priv)) { std::map occurrences; @@ -596,9 +738,9 @@ void PolicyChecker::parse_node(tfsxml_string& tfsxml_priv, std::vector matching_rules; - - std::string field = std::string(result.buf, result.len); + std::vector matching_sources; for (size_t pos = 0; pos < rules.size(); pos++) { if (level < rules[pos]->path.size() && path_is_matching(tfsxml_priv, result, rules[pos]->path[level], occurrences[&rules[pos]->path[level]])) @@ -606,23 +748,38 @@ void PolicyChecker::parse_node(tfsxml_string& tfsxml_priv, std::vectorscope.empty() || rules[pos]->scope == "mi")) // at track level rules[pos]->tracks++; - tfsxml_string tfsxml_priv_copy = tfsxml_priv; if (level == rules[pos]->path.size() - 1) { + tfsxml_string tfsxml_priv_copy = tfsxml_priv; tfsxml_string value; if (!tfsxml_value(&tfsxml_priv_copy, &value)) - rules[pos]->values.push_back(std::string(value.buf, value.len)); + rules[pos]->values[id] = std::string(value.buf, value.len); } else matching_rules.push_back(rules[pos]); } } - if (!matching_rules.empty()) - parse_node(tfsxml_priv, matching_rules, level + 1); + for (size_t pos = 0; pos < sources.size(); pos++) + { + if (sources[pos]->source && level < sources[pos]->source->path.size() && path_is_matching(tfsxml_priv, result, sources[pos]->source->path[level], occurrences[&sources[pos]->source->path[level]])) + { + if (level == sources[pos]->source->path.size() - 1) + { + tfsxml_string tfsxml_priv_copy = tfsxml_priv; + tfsxml_string value; + if (!tfsxml_value(&tfsxml_priv_copy, &value)) + sources[pos]->source->values[id] = std::string(value.buf, value.len); + } + else + matching_sources.push_back(sources[pos]); + } + } + + if (!matching_rules.empty() || !matching_sources.empty()) + parse_node(tfsxml_priv, matching_rules, matching_sources, level + 1); } } - tfsxml_priv=tfsxml_priv_save; } //--------------------------------------------------------------------------- @@ -636,7 +793,7 @@ int PolicyChecker::analyze(const std::string& report, bool verbose, std::string& ss << indent(level ) << "MediaConch" << std::endl; tfsxml_string tfsxml_priv; tfsxml_string result; - tfsxml_init(&tfsxml_priv, (const void*)report.c_str(), report.size()); + tfsxml_init(&tfsxml_priv, (const void*)report.c_str(), report.size(), 0); while (!tfsxml_next_named(&tfsxml_priv, &result, "MediaArea")) { if (!tfsxml_enter(&tfsxml_priv)) @@ -655,7 +812,7 @@ int PolicyChecker::analyze(const std::string& report, bool verbose, std::string& } ss << indent(level++) << "" << std::endl; - parse_node(tfsxml_priv, rules, 0); + parse_node(tfsxml_priv, rules, rules, 0); for (size_t pos=0; posto_string(level, verbose); ss << indent(--level) << "" << std::endl; diff --git a/Source/Checker/Checker.h b/Source/Checker/Checker.h index 9fb3289b..ce2aeee2 100644 --- a/Source/Checker/Checker.h +++ b/Source/Checker/Checker.h @@ -18,12 +18,13 @@ //--------------------------------------------------------------------------- #ifndef TFSXML_NAMESPACE #define TFSXML_NAMESPACE 1 -#endif // TFSXML_NAMESPACEs +#endif // TFSXML_NAMESPACE #include "ThirdParty/tfsxml/tfsxml.h" #include "Path.h" #include #include +#include //--------------------------------------------------------------------------- @@ -73,11 +74,21 @@ class PolicyChecker class RuleElement : public Element { public: + struct Source + { + std::vector path; + std::map values; + std::string scope; + std::string field; + std::string tracktype; + std::string occurrence; + }; + RuleElement(); ~RuleElement(); void reset(); - bool compare(const std::string& value); + bool compare(const std::string& v1, const std::string& v2); virtual void resolve(); virtual Result result(); @@ -93,8 +104,9 @@ class PolicyChecker std::string operand; std::string xpath; std::string requested; - std::vector values; + std::map values; std::vector failing_values; + Source* source; size_t tracks; private: @@ -129,7 +141,7 @@ class PolicyChecker RuleElement* parse_rule(tfsxml::tfsxml_string& tfsxml_priv); PolicyElement* parse_policy(tfsxml::tfsxml_string& tfsxml_priv); - void parse_node(tfsxml::tfsxml_string& tfsxml_priv, std::vector rules, size_t level); + void parse_node(tfsxml::tfsxml_string& tfsxml_priv, std::vector rules, std::vector sources, size_t level); std::vector policies; std::vector rules; diff --git a/Source/Checker/Path.cpp b/Source/Checker/Path.cpp index c527c586..aeec50e4 100644 --- a/Source/Checker/Path.cpp +++ b/Source/Checker/Path.cpp @@ -112,6 +112,7 @@ std::vector parse_path(const std::string& xpath) //--------------------------------------------------------------------------- bool path_is_matching(tfsxml_string& tfsxml_priv, tfsxml_string& node, PathElement path, size_t& occurrence) { + tfsxml_string tfsxml_priv_local = tfsxml_priv; tfsxml_string value; // compare names @@ -125,10 +126,8 @@ bool path_is_matching(tfsxml_string& tfsxml_priv, tfsxml_string& node, PathEleme tfsxml_string attribute_name; tfsxml_string attribute_value; - tfsxml_string tfsxml_priv_save=tfsxml_priv; - while (!tfsxml_attr(&tfsxml_priv, &attribute_name, &attribute_value)) + while (!tfsxml_attr(&tfsxml_priv_local, &attribute_name, &attribute_value)) attributes[std::string(attribute_name.buf, attribute_name.len)]=std::string(attribute_value.buf, attribute_value.len); - tfsxml_priv=tfsxml_priv_save; std::map::iterator it=path.attributes.begin(); while (it!=path.attributes.end()) diff --git a/Source/Common/DaemonClient.cpp b/Source/Common/DaemonClient.cpp index 2e79eee8..ed205c3c 100644 --- a/Source/Common/DaemonClient.cpp +++ b/Source/Common/DaemonClient.cpp @@ -1304,6 +1304,14 @@ XsltPolicyRule *DaemonClient::xslt_policy_rule_get(int user, int policy_id, int rule->occurrence = res->rule.occurrence; rule->ope = rule->ope; rule->value = res->rule.value; + if (res->rule.source) + { + rule->source = new XsltPolicyRule::Source; + rule->source->track_type = res->rule.source->tracktype; + rule->source->field = res->rule.source->field; + rule->source->scope = res->rule.source->scope; + rule->source->occurrence = res->rule.source->occurrence; + } } delete res; @@ -1327,8 +1335,17 @@ int DaemonClient::xslt_policy_rule_edit(int user, int policy_id, int rule_id, co req.rule.occurrence = rule->occurrence; req.rule.ope = rule->ope; req.rule.value = rule->value; + if (rule->source) + { + req.rule.source = new MediaConchLib::XSLT_Policy_Rule::Source; + req.rule.source->tracktype = rule->source->track_type; + req.rule.source->field = rule->source->field; + req.rule.source->scope = rule->source->scope; + req.rule.source->occurrence = rule->source->occurrence; + } req.user = user; + COMMON_HTTP_REQ_RES(xslt_policy_rule_edit, -1) int ret = -1; diff --git a/Source/Common/JS_Tree.cpp b/Source/Common/JS_Tree.cpp index eb567426..0dec66ed 100644 --- a/Source/Common/JS_Tree.cpp +++ b/Source/Common/JS_Tree.cpp @@ -700,8 +700,18 @@ int JsTree::rule_to_js_tree(MediaConchLib::XSLT_Policy_Rule* rule, std::string& ss << "\",\"level\":\"" << unified_json_value(rule->level); ss << "\",\"occurrence\":\"" << unified_json_value(rule->occurrence); ss << "\",\"ope\":\"" << unified_json_value(rule->ope); - ss << "\",\"value\":\"" << unified_json_value(rule->value); - ss <<"\"}}"; + if (rule->source) + { + ss << "\",\"source\":{"; + ss << "\"tracktype\":\"" << unified_json_value(rule->source->tracktype); + ss << "\",\"field\":\"" << unified_json_value(rule->source->field); + ss << "\",\"scope\":\"" << unified_json_value(rule->source->scope); + ss << "\",\"occurrence\":\"" << unified_json_value(rule->source->occurrence); + ss <<"\"}"; + } + else + ss << "\",\"value\":\"" << unified_json_value(rule->value) << "\""; + ss <<"}}"; json = ss.str(); return 0; diff --git a/Source/Common/MediaConchLib.cpp b/Source/Common/MediaConchLib.cpp index 1e8f1118..0a88082d 100644 --- a/Source/Common/MediaConchLib.cpp +++ b/Source/Common/MediaConchLib.cpp @@ -690,7 +690,20 @@ std::string MediaConchLib::XSLT_Policy_Rule::to_str() const out << ",occurrence:\"" << occurrence << "\""; if (ope.size()) out << ",\"ope\":\"" << ope << "\""; - if (value.size()) + if (source) + { + out << ",source:{"; + if (source->tracktype.size()) + out << ",\"tracktype\":\"" << source->tracktype << "\""; + if (source->field.size()) + out << ",\"field\":\"" << source->field << "\""; + if (source->scope.size()) + out << ",\"scope\":\"" << source->scope << "\""; + if (source->occurrence.size()) + out << ",occurrence:\"" << source->occurrence << "\""; + out << "}"; + } + else if (value.size()) out << ",\"value\":\"" << value << "\""; out << "}"; return out.str(); diff --git a/Source/Common/MediaConchLib.h b/Source/Common/MediaConchLib.h index 8e92faa7..3356b4bc 100644 --- a/Source/Common/MediaConchLib.h +++ b/Source/Common/MediaConchLib.h @@ -175,7 +175,18 @@ class MediaConchLib struct XSLT_Policy_Rule { - XSLT_Policy_Rule() : id(-1) {} + XSLT_Policy_Rule() : id(-1), source(NULL) {} + ~XSLT_Policy_Rule() { + if (source) + delete source; + } + + struct Source { + std::string tracktype; + std::string field; + std::string scope; + std::string occurrence; + }; int id; std::string name; @@ -186,6 +197,7 @@ class MediaConchLib std::string occurrence; std::string ope; std::string value; + Source* source; std::string to_str() const; }; diff --git a/Source/Common/Policies.cpp b/Source/Common/Policies.cpp index 3c0f7b92..4ee1afa6 100644 --- a/Source/Common/Policies.cpp +++ b/Source/Common/Policies.cpp @@ -448,6 +448,14 @@ MediaConchLib::XSLT_Policy_Rule* Policies::xslt_policy_rule_to_mcl_policy(XsltPo r->occurrence = rule->occurrence; r->ope = rule->ope; r->value = rule->value; + if (rule->source) + { + r->source = new MediaConchLib::XSLT_Policy_Rule::Source; + r->source->tracktype = rule->source->track_type; + r->source->field = rule->source->field; + r->source->scope = rule->source->scope; + r->source->occurrence = rule->source->occurrence; + } return r; } diff --git a/Source/Common/REST_API.cpp b/Source/Common/REST_API.cpp index 76f31a9c..51584390 100644 --- a/Source/Common/REST_API.cpp +++ b/Source/Common/REST_API.cpp @@ -2597,6 +2597,42 @@ int RESTAPI::serialize_xslt_policy_rule(MediaConchLib::XSLT_Policy_Rule& rule, C val.obj["value"] = value; } + if (rule.source) + { + Container::Value source, src_tracktype, src_field, src_scope, src_occurrence; + source.type = Container::Value::CONTAINER_TYPE_OBJECT; + + if (rule.source->tracktype.size()) + { + src_tracktype.type = Container::Value::CONTAINER_TYPE_STRING; + src_tracktype.s = rule.source->tracktype; + source.obj["tracktype"] = src_tracktype; + } + + if (rule.source->field.size()) + { + src_field.type = Container::Value::CONTAINER_TYPE_STRING; + src_field.s = rule.source->field; + source.obj["field"] = src_field; + } + + if (rule.source->scope.size()) + { + src_scope.type = Container::Value::CONTAINER_TYPE_STRING; + src_scope.s = rule.source->scope; + source.obj["scope"] = src_scope; + } + + if (rule.source->occurrence.size()) + { + src_occurrence.type = Container::Value::CONTAINER_TYPE_STRING; + src_occurrence.s = rule.source->occurrence; + source.obj["occurrence"] = src_occurrence; + } + + val.obj["source"] = source; + } + return 0; } @@ -5364,6 +5400,31 @@ int RESTAPI::parse_xslt_policy_rule(Container::Value *val, MediaConchLib::XSLT_P if (value && value->type == Container::Value::CONTAINER_TYPE_STRING) rule->value = value->s; + Container::Value *source = model->get_value_by_key(*val, "source"); + if (source && source->type == Container::Value::CONTAINER_TYPE_OBJECT) + { + if (rule->source) + delete rule->source; + + rule->source = new MediaConchLib::XSLT_Policy_Rule::Source; + + Container::Value *src_tracktype = model->get_value_by_key(*source, "tracktype"); + if (src_tracktype && src_tracktype->type == Container::Value::CONTAINER_TYPE_STRING) + rule->source->tracktype = src_tracktype->s; + + Container::Value *src_field = model->get_value_by_key(*source, "field"); + if (src_field && src_field->type == Container::Value::CONTAINER_TYPE_STRING) + rule->source->field = src_field->s; + + Container::Value *src_scope = model->get_value_by_key(*source, "scope"); + if (src_scope && src_scope->type == Container::Value::CONTAINER_TYPE_STRING) + rule->source->scope = src_scope->s; + + Container::Value *src_occurrence = model->get_value_by_key(*source, "occurrence"); + if (src_occurrence && src_occurrence->type == Container::Value::CONTAINER_TYPE_STRING) + rule->source->occurrence = src_occurrence->s; + } + return 0; } @@ -9421,6 +9482,42 @@ void RESTAPI::serialize_a_xslt_policy_rule(MediaConchLib::XSLT_Policy_Rule* rule value.s = rule->value; ok_v.obj["value"] = value; } + + if (rule->source) + { + Container::Value source, src_tracktype, src_field, src_scope, src_occurrence; + source.type = Container::Value::CONTAINER_TYPE_OBJECT; + + if (rule->source->tracktype.size()) + { + src_tracktype.type = Container::Value::CONTAINER_TYPE_STRING; + src_tracktype.s = rule->source->tracktype; + source.obj["tracktype"] = src_tracktype; + } + + if (rule->source->field.size()) + { + src_field.type = Container::Value::CONTAINER_TYPE_STRING; + src_field.s = rule->source->field; + source.obj["field"] = src_field; + } + + if (rule->source->scope.size()) + { + src_scope.type = Container::Value::CONTAINER_TYPE_STRING; + src_scope.s = rule->source->scope; + source.obj["scope"] = src_scope; + } + + if (rule->source->occurrence.size()) + { + src_occurrence.type = Container::Value::CONTAINER_TYPE_STRING; + src_occurrence.s = rule->source->occurrence; + source.obj["occurrence"] = src_occurrence; + } + + ok_v.obj["source"] = source; + } } //--------------------------------------------------------------------------- @@ -10188,6 +10285,28 @@ MediaConchLib::XSLT_Policy_Rule* RESTAPI::parse_a_xslt_policy_rule(Container::Va if (value && value->type == Container::Value::CONTAINER_TYPE_STRING) ok->value = value->s; + Container::Value *source = model->get_value_by_key(*rule, "source"); + if (source && source->type == Container::Value::CONTAINER_TYPE_OBJECT) + { + ok->source = new MediaConchLib::XSLT_Policy_Rule::Source; + + Container::Value *src_tracktype = model->get_value_by_key(*source, "tracktype"); + if (src_tracktype && src_tracktype->type == Container::Value::CONTAINER_TYPE_STRING) + ok->source->tracktype = src_tracktype->s; + + Container::Value *src_field = model->get_value_by_key(*source, "field"); + if (src_field && src_field->type == Container::Value::CONTAINER_TYPE_STRING) + ok->source->field = src_field->s; + + Container::Value *src_scope = model->get_value_by_key(*source, "scope"); + if (src_scope && src_scope->type == Container::Value::CONTAINER_TYPE_STRING) + ok->source->scope = src_scope->s; + + Container::Value *src_occurrence = model->get_value_by_key(*source, "occurrence"); + if (src_occurrence && src_occurrence->type == Container::Value::CONTAINER_TYPE_STRING) + ok->source->occurrence = src_occurrence->s; + } + return ok; } diff --git a/Source/Common/XsltPolicy.cpp b/Source/Common/XsltPolicy.cpp index f40536e5..70d2e051 100644 --- a/Source/Common/XsltPolicy.cpp +++ b/Source/Common/XsltPolicy.cpp @@ -68,11 +68,15 @@ size_t XsltPolicyRule::rule_id = 0; XsltPolicyRule::XsltPolicyRule() : XsltPolicyNode() { kind = XSLT_POLICY_RULE; + source = NULL; + } //--------------------------------------------------------------------------- XsltPolicyRule::~XsltPolicyRule() { + if (source) + delete source; } //--------------------------------------------------------------------------- @@ -89,6 +93,19 @@ XsltPolicyRule::XsltPolicyRule(const XsltPolicyRule* r) : XsltPolicyNode(r) this->level = r->level; this->occurrence = r->occurrence; this->value = r->value; + if (r->source) + { + if (this->source) + delete this->source; + + this->source = new Source; + this->source->track_type = r->source->track_type; + this->source->field = r->source->field; + this->source->scope = r->source->scope; + this->source->occurrence = r->source->occurrence; + } + else + this->source = NULL; } //--------------------------------------------------------------------------- @@ -105,6 +122,19 @@ XsltPolicyRule::XsltPolicyRule(const XsltPolicyRule& r) : XsltPolicyNode(r) this->level = r.level; this->occurrence = r.occurrence; this->value = r.value; + if (r.source) + { + if (this->source) + delete this->source; + + this->source = new Source; + this->source->track_type = r.source->track_type; + this->source->field = r.source->field; + this->source->scope = r.source->scope; + this->source->occurrence = r.source->occurrence; + } + else + this->source = NULL; } //--------------------------------------------------------------------------- @@ -118,6 +148,19 @@ int XsltPolicyRule::edit_policy_rule(const XsltPolicyRule* rule, std::string&) this->level = rule->level; this->occurrence = rule->occurrence; this->value = rule->value; + if (rule->source) + { + if (this->source) + delete this->source; + + this->source = new Source; + this->source->track_type = rule->source->track_type; + this->source->field = rule->source->field; + this->source->scope = rule->source->scope; + this->source->occurrence = rule->source->occurrence; + } + else + this->source = NULL; return 0; } @@ -274,7 +317,7 @@ int XsltPolicy::run_over_siblings_nodes(xmlNodePtr node, bool is_root, XsltPolic { switch (node->type) { - case XML_TEXT_NODE: + case XML_TEXT_NODE: case XML_COMMENT_NODE: continue; default:; @@ -482,14 +525,62 @@ int XsltPolicy::parse_policy_rule(xmlNodePtr node, bool is_root, XsltPolicy* cur xmlFree(occurrence); } - //Get value - xmlChar *value = xmlNodeGetContent(node); - if (value) + //Get source + for (xmlNodePtr child = node->children; child; child = child->next) { - r->value = std::string((const char*)value); - xmlFree(value); + if (child->type == XML_ELEMENT_NODE && child->name && std::string((const char*)child->name) == "source") + { + if (r->source) + delete r->source; + + r->source = new XsltPolicyRule::Source; + + //Get source trackType + xmlChar *track_type = xmlGetNoNsProp(child, (const unsigned char*)"tracktype"); + if (track_type) + { + r->source->track_type = std::string((const char*)track_type); + xmlFree(track_type); + } + + //Get source field + xmlChar *field = xmlGetNoNsProp(child, (const unsigned char*)"value"); + if (field) + { + r->source->field = std::string((const char*)field); + xmlFree(field); + } + + //Get source scope + xmlChar *scope = xmlGetNoNsProp(child, (const unsigned char*)"scope"); + if (scope) + { + r->source->scope = std::string((const char*)scope); + xmlFree(scope); + } + + //Get source occurrence + xmlChar *occurrence = xmlGetNoNsProp(child, (const unsigned char*)"occurrence"); + if (occurrence) + { + r->source->occurrence = std::string((const char*)occurrence); + xmlFree(occurrence); + } + break; + } } + //Get value + if (!r->source) + { + xmlChar *value = xmlNodeGetContent(node); + if (value) + { + r->value = std::string((const char*)value); + xmlFree(value); + } + } + return 0; } @@ -615,8 +706,36 @@ int XsltPolicy::create_node_rule_child(xmlNodePtr& node, XsltPolicyRule *current if (current->level.size()) xmlNewProp(node, (const xmlChar *)"level", (const xmlChar *)current->level.c_str()); - //value - if (current->value.size()) + //source or value + if (current->source) + { + xmlNodePtr child = xmlNewNode(NULL, (const xmlChar *)"source"); + if (!child) + { + error = "Cannot create the source children"; + return -1; + } + + //field + if (current->source->field.size()) + xmlNewProp(child, (const xmlChar *)"value", (const xmlChar *)current->source->field.c_str()); + + //track type + if (current->source->track_type.size()) + xmlNewProp(child, (const xmlChar *)"tracktype", (const xmlChar *)current->source->track_type.c_str()); + + + //scope + if (current->source->scope.size()) + xmlNewProp(child, (const xmlChar *)"scope", (const xmlChar *)current->source->scope.c_str()); + + //occurrence + if (current->source->occurrence.size()) + xmlNewProp(child, (const xmlChar *)"occurrence", (const xmlChar *)current->source->occurrence.c_str()); + + xmlAddChild(node, child); + } + else if (current->value.size()) xmlNodeSetContent(node, (const xmlChar*)current->value.c_str()); return 0; diff --git a/Source/Common/XsltPolicy.h b/Source/Common/XsltPolicy.h index 794b0188..7f1529ea 100644 --- a/Source/Common/XsltPolicy.h +++ b/Source/Common/XsltPolicy.h @@ -73,6 +73,13 @@ class XsltPolicyNode class XsltPolicyRule : public XsltPolicyNode { public: + struct Source { + std::string track_type; + std::string field; + std::string scope; + std::string occurrence; + }; + XsltPolicyRule(); virtual ~XsltPolicyRule(); XsltPolicyRule(const XsltPolicyRule*); @@ -88,6 +95,7 @@ class XsltPolicyRule : public XsltPolicyNode std::string scope; std::string level; std::string occurrence; + Source* source; std::string value; static size_t rule_id; diff --git a/Source/Common/generated/ImplementationReportDisplayHtmlXsl.h b/Source/Common/generated/ImplementationReportDisplayHtmlXsl.h index 5749d41b..6f05f63b 100644 --- a/Source/Common/generated/ImplementationReportDisplayHtmlXsl.h +++ b/Source/Common/generated/ImplementationReportDisplayHtmlXsl.h @@ -437,8 +437,8 @@ const char implementation_report_display_html_xsl[] = { ,'\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x3c','\x73','\x74','\x72','\x6f','\x6e','\x67','\x3e','\x54','\x72','\x61','\x63','\x6b','\x74','\x79','\x70','\x65','\x3a','\x20','\x3c','\x2f','\x73','\x74','\x72','\x6f','\x6e','\x67','\x3e','\x20','\x20','\x3c','\x78','\x73','\x6c','\x3a','\x76','\x61','\x6c','\x75','\x65','\x2d','\x6f','\x66','\x20','\x73','\x65','\x6c','\x65','\x63','\x74','\x3d','\x22','\x40','\x74','\x72','\x61','\x63','\x6b','\x74','\x79','\x70','\x65','\x22','\x2f','\x3e','\x0a' ,'\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x3c','\x62','\x72','\x2f','\x3e','\x0a' ,'\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x3c','\x2f','\x78','\x73','\x6c','\x3a','\x69','\x66','\x3e','\x0a' -,'\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x3c','\x78','\x73','\x6c','\x3a','\x69','\x66','\x20','\x74','\x65','\x73','\x74','\x3d','\x22','\x40','\x6f','\x63','\x63','\x75','\x72','\x65','\x6e','\x63','\x65','\x20','\x21','\x3d','\x20','\x27','\x27','\x22','\x3e','\x0a' -,'\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x3c','\x73','\x74','\x72','\x6f','\x6e','\x67','\x3e','\x4f','\x63','\x63','\x75','\x72','\x65','\x6e','\x63','\x65','\x3a','\x20','\x3c','\x2f','\x73','\x74','\x72','\x6f','\x6e','\x67','\x3e','\x20','\x20','\x3c','\x78','\x73','\x6c','\x3a','\x76','\x61','\x6c','\x75','\x65','\x2d','\x6f','\x66','\x20','\x73','\x65','\x6c','\x65','\x63','\x74','\x3d','\x22','\x40','\x6f','\x63','\x63','\x75','\x72','\x65','\x6e','\x63','\x65','\x22','\x2f','\x3e','\x0a' +,'\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x3c','\x78','\x73','\x6c','\x3a','\x69','\x66','\x20','\x74','\x65','\x73','\x74','\x3d','\x22','\x40','\x6f','\x63','\x63','\x75','\x72','\x72','\x65','\x6e','\x63','\x65','\x20','\x21','\x3d','\x20','\x27','\x27','\x22','\x3e','\x0a' +,'\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x3c','\x73','\x74','\x72','\x6f','\x6e','\x67','\x3e','\x4f','\x63','\x63','\x75','\x72','\x72','\x65','\x6e','\x63','\x65','\x3a','\x20','\x3c','\x2f','\x73','\x74','\x72','\x6f','\x6e','\x67','\x3e','\x20','\x20','\x3c','\x78','\x73','\x6c','\x3a','\x76','\x61','\x6c','\x75','\x65','\x2d','\x6f','\x66','\x20','\x73','\x65','\x6c','\x65','\x63','\x74','\x3d','\x22','\x40','\x6f','\x63','\x63','\x75','\x72','\x72','\x65','\x6e','\x63','\x65','\x22','\x2f','\x3e','\x0a' ,'\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x3c','\x62','\x72','\x2f','\x3e','\x0a' ,'\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x3c','\x2f','\x78','\x73','\x6c','\x3a','\x69','\x66','\x3e','\x0a' ,'\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x3c','\x78','\x73','\x6c','\x3a','\x69','\x66','\x20','\x74','\x65','\x73','\x74','\x3d','\x22','\x40','\x6f','\x70','\x65','\x72','\x61','\x74','\x6f','\x72','\x20','\x21','\x3d','\x20','\x27','\x27','\x22','\x3e','\x0a' @@ -463,9 +463,34 @@ const char implementation_report_display_html_xsl[] = { ,'\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x3c','\x2f','\x78','\x73','\x6c','\x3a','\x69','\x66','\x3e','\x0a' ,'\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x3c','\x73','\x74','\x72','\x6f','\x6e','\x67','\x3e','\x3c','\x78','\x73','\x6c','\x3a','\x74','\x65','\x78','\x74','\x3e','\x58','\x70','\x61','\x74','\x68','\x3a','\x20','\x20','\x3c','\x2f','\x78','\x73','\x6c','\x3a','\x74','\x65','\x78','\x74','\x3e','\x3c','\x2f','\x73','\x74','\x72','\x6f','\x6e','\x67','\x3e','\x0a' ,'\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x3c','\x78','\x73','\x6c','\x3a','\x76','\x61','\x6c','\x75','\x65','\x2d','\x6f','\x66','\x20','\x73','\x65','\x6c','\x65','\x63','\x74','\x3d','\x22','\x40','\x78','\x70','\x61','\x74','\x68','\x22','\x2f','\x3e','\x0a' +,'\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x3c','\x78','\x73','\x6c','\x3a','\x61','\x70','\x70','\x6c','\x79','\x2d','\x74','\x65','\x6d','\x70','\x6c','\x61','\x74','\x65','\x73','\x20','\x73','\x65','\x6c','\x65','\x63','\x74','\x3d','\x22','\x6d','\x63','\x3a','\x73','\x6f','\x75','\x72','\x63','\x65','\x22','\x2f','\x3e','\x0a' ,'\x20','\x20','\x20','\x20','\x20','\x20','\x3c','\x2f','\x64','\x69','\x76','\x3e','\x0a' +,'\x20','\x20','\x20','\x20','\x20','\x20','\x3c','\x2f','\x64','\x69','\x76','\x3e','\x0a' +,'\x20','\x20','\x20','\x20','\x3c','\x2f','\x64','\x69','\x76','\x3e','\x0a' +,'\x20','\x20','\x3c','\x2f','\x78','\x73','\x6c','\x3a','\x74','\x65','\x6d','\x70','\x6c','\x61','\x74','\x65','\x3e','\x0a' +,'\x20','\x20','\x3c','\x78','\x73','\x6c','\x3a','\x74','\x65','\x6d','\x70','\x6c','\x61','\x74','\x65','\x20','\x6d','\x61','\x74','\x63','\x68','\x3d','\x22','\x6d','\x63','\x3a','\x73','\x6f','\x75','\x72','\x63','\x65','\x22','\x3e','\x0a' +,'\x20','\x20','\x20','\x20','\x3c','\x62','\x72','\x2f','\x3e','\x0a' +,'\x20','\x20','\x20','\x20','\x3c','\x69','\x6e','\x70','\x75','\x74','\x20','\x69','\x64','\x3d','\x22','\x70','\x6f','\x6c','\x69','\x63','\x79','\x2d','\x61','\x72','\x72','\x6f','\x77','\x2d','\x7b','\x67','\x65','\x6e','\x65','\x72','\x61','\x74','\x65','\x2d','\x69','\x64','\x28','\x29','\x7d','\x22','\x20','\x63','\x6c','\x61','\x73','\x73','\x3d','\x22','\x61','\x72','\x72','\x6f','\x77','\x22','\x20','\x74','\x79','\x70','\x65','\x3d','\x22','\x63','\x68','\x65','\x63','\x6b','\x62','\x6f','\x78','\x22','\x2f','\x3e','\x0a' +,'\x20','\x20','\x20','\x20','\x3c','\x6c','\x61','\x62','\x65','\x6c','\x20','\x66','\x6f','\x72','\x3d','\x22','\x70','\x6f','\x6c','\x69','\x63','\x79','\x2d','\x61','\x72','\x72','\x6f','\x77','\x2d','\x7b','\x67','\x65','\x6e','\x65','\x72','\x61','\x74','\x65','\x2d','\x69','\x64','\x28','\x29','\x7d','\x22','\x3e','\x3c','\x2f','\x6c','\x61','\x62','\x65','\x6c','\x3e','\x0a' +,'\x20','\x20','\x20','\x20','\x3c','\x78','\x73','\x6c','\x3a','\x74','\x65','\x78','\x74','\x3e','\x20','\x3c','\x2f','\x78','\x73','\x6c','\x3a','\x74','\x65','\x78','\x74','\x3e','\x0a' +,'\x20','\x20','\x20','\x20','\x3c','\x73','\x74','\x72','\x6f','\x6e','\x67','\x3e','\x0a' +,'\x20','\x20','\x20','\x20','\x20','\x20','\x3c','\x73','\x70','\x61','\x6e','\x3e','\x53','\x6f','\x75','\x72','\x63','\x65','\x3c','\x2f','\x73','\x70','\x61','\x6e','\x3e','\x0a' +,'\x20','\x20','\x20','\x20','\x3c','\x2f','\x73','\x74','\x72','\x6f','\x6e','\x67','\x3e','\x0a' +,'\x20','\x20','\x20','\x20','\x3c','\x78','\x73','\x6c','\x3a','\x74','\x65','\x78','\x74','\x3e','\x20','\x3c','\x2f','\x78','\x73','\x6c','\x3a','\x74','\x65','\x78','\x74','\x3e','\x0a' +,'\x20','\x20','\x20','\x20','\x3c','\x64','\x69','\x76','\x20','\x63','\x6c','\x61','\x73','\x73','\x3d','\x22','\x65','\x78','\x74','\x72','\x61','\x22','\x3e','\x0a' +,'\x20','\x20','\x20','\x20','\x20','\x20','\x3c','\x78','\x73','\x6c','\x3a','\x69','\x66','\x20','\x74','\x65','\x73','\x74','\x3d','\x22','\x40','\x76','\x61','\x6c','\x75','\x65','\x20','\x21','\x3d','\x20','\x27','\x27','\x22','\x3e','\x0a' +,'\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x3c','\x73','\x74','\x72','\x6f','\x6e','\x67','\x3e','\x56','\x61','\x6c','\x75','\x65','\x3a','\x20','\x3c','\x2f','\x73','\x74','\x72','\x6f','\x6e','\x67','\x3e','\x20','\x20','\x3c','\x78','\x73','\x6c','\x3a','\x76','\x61','\x6c','\x75','\x65','\x2d','\x6f','\x66','\x20','\x73','\x65','\x6c','\x65','\x63','\x74','\x3d','\x22','\x40','\x76','\x61','\x6c','\x75','\x65','\x22','\x2f','\x3e','\x0a' +,'\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x3c','\x62','\x72','\x2f','\x3e','\x0a' +,'\x20','\x20','\x20','\x20','\x20','\x20','\x3c','\x2f','\x78','\x73','\x6c','\x3a','\x69','\x66','\x3e','\x0a' +,'\x20','\x20','\x20','\x20','\x20','\x20','\x3c','\x78','\x73','\x6c','\x3a','\x69','\x66','\x20','\x74','\x65','\x73','\x74','\x3d','\x22','\x40','\x74','\x72','\x61','\x63','\x6b','\x74','\x79','\x70','\x65','\x20','\x21','\x3d','\x20','\x27','\x27','\x22','\x3e','\x0a' +,'\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x3c','\x73','\x74','\x72','\x6f','\x6e','\x67','\x3e','\x54','\x72','\x61','\x63','\x6b','\x74','\x79','\x70','\x65','\x3a','\x20','\x3c','\x2f','\x73','\x74','\x72','\x6f','\x6e','\x67','\x3e','\x20','\x20','\x3c','\x78','\x73','\x6c','\x3a','\x76','\x61','\x6c','\x75','\x65','\x2d','\x6f','\x66','\x20','\x73','\x65','\x6c','\x65','\x63','\x74','\x3d','\x22','\x40','\x74','\x72','\x61','\x63','\x6b','\x74','\x79','\x70','\x65','\x22','\x2f','\x3e','\x0a' +,'\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x3c','\x62','\x72','\x2f','\x3e','\x0a' +,'\x20','\x20','\x20','\x20','\x20','\x20','\x3c','\x2f','\x78','\x73','\x6c','\x3a','\x69','\x66','\x3e','\x0a' +,'\x20','\x20','\x20','\x20','\x20','\x20','\x3c','\x78','\x73','\x6c','\x3a','\x69','\x66','\x20','\x74','\x65','\x73','\x74','\x3d','\x22','\x40','\x6f','\x63','\x63','\x75','\x72','\x72','\x65','\x6e','\x63','\x65','\x20','\x21','\x3d','\x20','\x27','\x27','\x22','\x3e','\x0a' +,'\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x3c','\x73','\x74','\x72','\x6f','\x6e','\x67','\x3e','\x4f','\x63','\x63','\x75','\x72','\x72','\x65','\x6e','\x63','\x65','\x3a','\x20','\x3c','\x2f','\x73','\x74','\x72','\x6f','\x6e','\x67','\x3e','\x20','\x20','\x3c','\x78','\x73','\x6c','\x3a','\x76','\x61','\x6c','\x75','\x65','\x2d','\x6f','\x66','\x20','\x73','\x65','\x6c','\x65','\x63','\x74','\x3d','\x22','\x40','\x6f','\x63','\x63','\x75','\x72','\x72','\x65','\x6e','\x63','\x65','\x22','\x2f','\x3e','\x0a' +,'\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x20','\x3c','\x62','\x72','\x2f','\x3e','\x0a' +,'\x20','\x20','\x20','\x20','\x20','\x20','\x3c','\x2f','\x78','\x73','\x6c','\x3a','\x69','\x66','\x3e','\x0a' ,'\x20','\x20','\x20','\x20','\x3c','\x2f','\x64','\x69','\x76','\x3e','\x0a' -,'\x20','\x20','\x3c','\x2f','\x64','\x69','\x76','\x3e','\x0a' ,'\x20','\x20','\x3c','\x2f','\x78','\x73','\x6c','\x3a','\x74','\x65','\x6d','\x70','\x6c','\x61','\x74','\x65','\x3e','\x0a' ,'\x3c','\x2f','\x78','\x73','\x6c','\x3a','\x73','\x74','\x79','\x6c','\x65','\x73','\x68','\x65','\x65','\x74','\x3e','\x0a' , '\0'}; diff --git a/Source/Daemon/Daemon.cpp b/Source/Daemon/Daemon.cpp index 257d8268..29c08d52 100644 --- a/Source/Daemon/Daemon.cpp +++ b/Source/Daemon/Daemon.cpp @@ -1533,6 +1533,14 @@ namespace MediaConch res.rule.occurrence = rule->occurrence; res.rule.ope = rule->ope; res.rule.value = rule->value; + if (rule->source) + { + res.rule.source = new MediaConchLib::XSLT_Policy_Rule::Source; + res.rule.source->tracktype = rule->source->track_type; + res.rule.source->field = rule->source->field; + res.rule.source->scope = rule->source->scope; + res.rule.source->occurrence = rule->source->occurrence; + } } FUN_CMD_END(XSLT_Policy_Rule_Get) @@ -1555,6 +1563,14 @@ namespace MediaConch rule.occurrence = req->rule.occurrence; rule.ope = req->rule.ope; rule.value = req->rule.value; + if (req->rule.source) + { + rule.source = new XsltPolicyRule::Source; + rule.source->track_type = req->rule.source->tracktype; + rule.source->field = req->rule.source->field; + rule.source->scope = req->rule.source->scope; + rule.source->occurrence = req->rule.source->occurrence; + } if (d->MCL->xslt_policy_rule_edit(req->user, req->policy_id, req->rule.id, &rule, err) < 0) FUN_CMD_NOK(res, err, -1) diff --git a/Source/GUI/Qt/WebCommonPage.cpp b/Source/GUI/Qt/WebCommonPage.cpp index 71dd90a9..dfdebde1 100644 --- a/Source/GUI/Qt/WebCommonPage.cpp +++ b/Source/GUI/Qt/WebCommonPage.cpp @@ -1088,6 +1088,53 @@ namespace MediaConch else rule_data += ",\"ope\":\"\""; + if (r->source) + { + rule_data += ",\"source\":{"; + + len = r->source->track_type.length(); + if (len > 0) + { + QString source_tracktype = QString().fromUtf8(r->source->track_type.c_str(), r->source->track_type.length()); + string_to_json(source_tracktype); + rule_data += QString("\"tracktype\":\"%1\"").arg(source_tracktype); + } + else + rule_data += "\"tracktype\":\"\""; + + len = r->source->field.length(); + if (len > 0) + { + QString source_field = QString().fromUtf8(r->source->field.c_str(), r->source->field.length()); + string_to_json(source_field); + rule_data += QString(",\"field\":\"%1\"").arg(source_field); + } + else + rule_data += ",\"field\":\"\""; + + len = r->source->occurrence.length(); + if (len > 0) + { + QString source_occurrence = QString().fromUtf8(r->source->occurrence.c_str(), r->source->occurrence.length()); + string_to_json(source_occurrence); + rule_data += QString(",\"occurrence\":\"%1\"").arg(source_occurrence); + } + else + rule_data += ",\"occurrence\":\"\""; + + len = r->source->scope.length(); + if (len > 0) + { + QString source_scope = QString().fromUtf8(r->source->scope.c_str(), r->source->scope.length()); + string_to_json(source_scope); + rule_data += QString(",\"scope\":\"%1\"").arg(source_scope); + } + else + rule_data += ",\"scope\":\"\""; + + rule_data += "}"; + } + len = r->value.length(); if (len > 0) { @@ -1521,7 +1568,9 @@ namespace MediaConch return json; } - QString WebCommonPage::xslt_policy_rule_edit(int rule_id, int policy_id, const QString& title, const QString& type, const QString& field, const QString& occurrence, const QString& ope, const QString& value, const QString& scope, const QString& level) + QString WebCommonPage::xslt_policy_rule_edit(int rule_id, int policy_id, const QString& title, const QString& type, + const QString& field, const QString& occurrence, const QString& ope, + const QString& value, const QString& scope, const QString& level) { QString err; QString json; @@ -1561,6 +1610,54 @@ namespace MediaConch return json; } + QString WebCommonPage::xslt_policy_rule_edit(int rule_id, int policy_id, const QString &title, const QString &type, + const QString &field, const QString &occurrence, const QString &ope, + const QJsonObject& source, const QString &scope, const QString &level) + { + QString err; + QString json; + + XsltPolicyRule rule; + rule.source = new XsltPolicyRule::Source; + + rule.node_name = title.toUtf8().data(); + rule.ope = ope.toUtf8().data(); + rule.track_type = type.toUtf8().data(); + rule.field = field.toUtf8().data(); + rule.occurrence = occurrence.toUtf8().data(); + rule.scope = scope.toUtf8().data(); + rule.level = level.toUtf8().data(); + + rule.source->track_type = source.value("tracktype").toString().toUtf8().data(); + rule.source->field = source.value("field").toString().toUtf8().data(); + rule.source->occurrence = source.value("occurrence").toString().toUtf8().data(); + rule.source->scope = source.value("scope").toString().toUtf8().data(); + + int code; + if ((code = mainwindow->xslt_policy_rule_edit(policy_id, rule_id, &rule, err)) < 0) + { + string_to_json(err); + json = QString("{\"error\":\"%1\"}").arg(err); + return json; + } + + mainwindow->policy_save(policy_id, err); + + XsltPolicyRule* r = mainwindow->xslt_policy_rule_get(policy_id, rule_id, err); + if (!r) + { + json = "{\"error\":\"Cannot get the policy rule edited\"}"; + return json; + } + + QString rule_data; + create_rule_tree(r, rule_data); + json = QString("{\"rule\":"); + json += rule_data; + json += "}"; + return json; + } + QString WebCommonPage::xslt_policy_rule_duplicate(int policy_id, int rule_id, int dst_policy_id) { //return: rule diff --git a/Source/GUI/Qt/WebCommonPage.h b/Source/GUI/Qt/WebCommonPage.h index 58e64a90..b5a3dc98 100644 --- a/Source/GUI/Qt/WebCommonPage.h +++ b/Source/GUI/Qt/WebCommonPage.h @@ -13,6 +13,7 @@ #include #include #include +#include #include #if defined(WEB_MACHINE_KIT) @@ -136,7 +137,12 @@ public Q_SLOTS: QString policy_edit(int id, const QString& name, const QString& description, const QStringList& tags, const QString& license, const QString& type, const QString& level, const QString& visibility); QString xslt_policy_rule_create(int policy_id); - QString xslt_policy_rule_edit(int rule_id, int policy_id, const QString& title, const QString& type, const QString& field, const QString& occurrence, const QString& ope, const QString& value, const QString& scope, const QString& level); + QString xslt_policy_rule_edit(int rule_id, int policy_id, const QString& title, const QString& type, + const QString& field, const QString& occurrence, const QString& ope, + const QString& value, const QString& scope, const QString& level); + QString xslt_policy_rule_edit(int rule_id, int policy_id, const QString& title, const QString& type, + const QString& field, const QString& occurrence, const QString& ope, + const QJsonObject& source, const QString& scope, const QString& level); QString xslt_policy_rule_duplicate(int policy_id, int rule_id, int dst_policy_id); QString xslt_policy_rule_move(int policy_id, int rule_id, int dst_policy_id); QString xslt_policy_rule_delete(int policy_id, int rule_id); diff --git a/Source/Resource/displays/MediaConchHtml.xsl b/Source/Resource/displays/MediaConchHtml.xsl index adb20e1f..42b56dc7 100644 --- a/Source/Resource/displays/MediaConchHtml.xsl +++ b/Source/Resource/displays/MediaConchHtml.xsl @@ -425,8 +425,8 @@ Tracktype:
- - Occurence: + + Occurrence:
@@ -451,8 +451,33 @@ Xpath: + + + + + +
+ + + + + Source + + +
+ + Value: +
+
+ + Tracktype: +
+
+ + Occurrence: +
+
-
diff --git a/Source/Resource/html/js/policy.js b/Source/Resource/html/js/policy.js index af1adb19..d8c2639f 100644 --- a/Source/Resource/html/js/policy.js +++ b/Source/Resource/html/js/policy.js @@ -30,6 +30,12 @@ function setSelect2Plugin() { minimumResultsForSearch: Infinity }); + $('#xslPolicyRule_sourceTrackType').select2({ + theme: 'bootstrap', + width: '100%', + minimumResultsForSearch: Infinity + }); + $('#xslPolicyRule_validator').select2({ theme: 'bootstrap', width: '100%', @@ -48,12 +54,24 @@ function setSelect2Plugin() { width: '100%' }); + $('#xslPolicyRule_sourceField').select2({ + tags: true, + theme: 'bootstrap', + width: '100%' + }); + $('#xslPolicyRule_occurrence').select2({ tags: true, theme: 'bootstrap', width: '100%' }); + $('#xslPolicyRule_sourceOccurrence').select2({ + tags: true, + theme: 'bootstrap', + width: '100%' + }); + $('#xslPolicyRule_level').select2({ theme: 'bootstrap', width: '100%', @@ -161,11 +179,23 @@ function formBindings() { var field = null; } else { - var field = $('#xslPolicyRule_field').val(); + var field = $('#xslPolicyRule_field'); } policyTreeRulesMI.loadFieldsList($('#xslPolicyRule_trackType').val(), field); - policyTreeRulesMI.displayOccurenceField($('#xslPolicyRule_trackType').val()); + policyTreeRulesMI.displayOccurrenceField($('#xslPolicyRule_trackType').val(), $('#xslPolicyRule_occurrence')); + }); + + $('#xslPolicyRule_sourceTrackType').on('change', function() { + if ('undefined' === $('#xslPolicyRule_sourceField').val()) { + var field = null; + } + else { + var field = $('#xslPolicyRule_sourceField'); + } + + policyTreeRulesMI.loadFieldsList($('#xslPolicyRule_sourceTrackType').val(), field); + policyTreeRulesMI.displayOccurrenceField($('#xslPolicyRule_sourceTrackType').val(), $('#xslPolicyRule_sourceOccurrence')); }); // Policy rule edit form field select list @@ -402,12 +432,15 @@ function policyRuleHelp() { // trackType addHelp('trackType', 'Specifies which section of the file the rule should target.', 'Track type'); + addHelp('sourceTrackType', 'Specifies which section of the file the rule should target.', 'Track type'); // Field addHelp('field', 'Specifies the field (within the track) that the rule should target.', 'Field'); + addHelp('sourceField', 'Specifies the field (within the track) that the rule should target.', 'Field'); // Occurrence addHelp('occurrence', 'Optional field to specify which track should be tested. Leaving this field blank will test all tracks.', 'Occurrence'); + addHelp('sourceOccurrence', 'Optional field to specify which track should be tested. Leaving this field blank will test all tracks.', 'Occurrence'); // Validator addHelp('validator', 'Applies the appropriate operator to the rule.', 'Validator'); diff --git a/Source/Resource/html/js/policyTree.js b/Source/Resource/html/js/policyTree.js index 975a6717..8874a573 100644 --- a/Source/Resource/html/js/policyTree.js +++ b/Source/Resource/html/js/policyTree.js @@ -531,6 +531,15 @@ var policyTree = (function() { selectedRule.data.value = (undefined == rule.value) ? '' : rule.value; selectedRule.data.scope = (undefined == rule.scope) ? '' : rule.scope; selectedRule.data.level = (undefined == rule.level) ? '' : rule.level; + if (undefined !== rule.source) { + selectedRule.data.source = { + tracktype: (undefined == rule.source.tracktype) ? '' : rule.source.tracktype, + field: (undefined == rule.source.field) ? '' : rule.source.field, + occurrence: (undefined == rule.source.occurrence) ? '' : rule.source.occurrence, + scope: (undefined == rule.source.scope) ? '' : rule.source.scope, + } + } + mcoMessage.success('Rule successfuly edited'); } @@ -570,6 +579,12 @@ var policyTree = (function() { value: (undefined == rule.value) ? '' : rule.value, scope: (undefined == rule.scope) ? '' : rule.scope, level: (undefined == rule.level) ? '' : rule.level, + source: (undefined == rule.source) ? undefined : { + tracktype: (undefined == rule.source.tracktype) ? '' : rule.source.tracktype, + field: (undefined == rule.source.field) ? '' : rule.source.field, + occurrence: (undefined == rule.source.occurrence) ? '' : rule.source.occurrence, + scope: (undefined == rule.source.scope) ? '' : rule.source.scope, + }, } } } diff --git a/Source/Resource/html/js/policyTreeRulesMI.js b/Source/Resource/html/js/policyTreeRulesMI.js index 11b218f7..985ec5f7 100644 --- a/Source/Resource/html/js/policyTreeRulesMI.js +++ b/Source/Resource/html/js/policyTreeRulesMI.js @@ -19,6 +19,7 @@ var policyTreeRulesMI = (function() { if (policyTreeRules.isRuleMI(node)) { $('#xslPolicyRule_occurrence option').remove(); + $('#xslPolicyRule_sourceOccurrence option').remove(); [ {name: '', value: ''}, {name: 'Any', value: 'any'}, @@ -41,6 +42,7 @@ var policyTreeRulesMI = (function() { {name: '16', value: '16'} ].forEach(element => { $('#xslPolicyRule_occurrence').append(''); + $('#xslPolicyRule_sourceOccurrence').append(''); }); if ($('#xslPolicyRule_occurrence option[value="' + node.data.occurrence + '"]').length) { $('#xslPolicyRule_occurrence option[value="' + node.data.occurrence + '"]').prop('selected', true); @@ -69,11 +71,47 @@ var policyTreeRulesMI = (function() { $('#xslPolicyRule_validator option[value="exists"]').prop('selected', true); } $('#xslPolicyRule_validator').trigger('change'); + if (undefined !== node.data.source) { + if ($('#xslPolicyRule_sourceOccurrence option[value="' + node.data.source.occurrence + '"]').length) { + $('#xslPolicyRule_sourceOccurrence option[value="' + node.data.source.occurrence + '"]').prop('selected', true); + } + else { + $('#xslPolicyRule_sourceOccurrence').append(''); + } + $('#xslPolicyRule_sourceField option').remove(); + $('#xslPolicyRule_sourceField').append(''); + $('#xslPolicyRule_sourceTrackType option[value="' + node.data.source.tracktype + '"]').prop('selected', true); + $('#xslPolicyRule_sourceTrackType').trigger('change'); + $('#xslPolicyRule_sourceOccurrence').parent().removeClass('hidden'); + $('#xslPolicyRule_sourceField').parent().removeClass('hidden'); + $('#xslPolicyRule_sourceTrackType').parent().removeClass('hidden'); + $('#xslPolicyRule_value').parent().addClass('hidden'); + $('#xslPolicyRule_sourceOccurrence').prop('required', 'required'); + $('#xslPolicyRule_sourceField').prop('required', 'required'); + $('#xslPolicyRule_sourceTrackType').prop('required', 'required'); + $('#xslPolicyRule_value').prop('required', false); + $('#xslPolicyRule_valueType').prop('checked', true); + } + else { + $('#xslPolicyRule_sourceOccurrence option[value=""]').prop('selected', true); + $('#xslPolicyRule_sourceField option[value=""]').prop('selected', true); + $('#xslPolicyRule_sourceTrackType option[value=""]').prop('selected', true); + $('#xslPolicyRule_sourceTrackType').trigger('change'); + $('#xslPolicyRule_sourceOccurrence').parent().addClass('hidden'); + $('#xslPolicyRule_sourceField').parent().addClass('hidden'); + $('#xslPolicyRule_sourceTrackType').parent().addClass('hidden'); + $('#xslPolicyRule_value').parent().removeClass('hidden'); + $('#xslPolicyRule_sourceOccurrence').prop('required', false); + $('#xslPolicyRule_sourceField').prop('required', false); + $('#xslPolicyRule_sourceTrackType').prop('required', false); + $('#xslPolicyRule_value').prop('required', 'required'); + $('#xslPolicyRule_valueType').prop('checked', false); + } } else { - $('#xslPolicyRule_occurence option').remove(); - $('#xslPolicyRule_occurence option[value=""]').prop('selected', true); - $('#xslPolicyRule_occurence').trigger('change'); + $('#xslPolicyRule_occurrence option').remove(); + $('#xslPolicyRule_occurrence option[value=""]').prop('selected', true); + $('#xslPolicyRule_occurrence').trigger('change'); $('#xslPolicyRule_field option').remove(); $('#xslPolicyRule_field option[value=""]').prop('selected', true); $('#xslPolicyRule_field').trigger('change'); @@ -87,6 +125,14 @@ var policyTreeRulesMI = (function() { $('#xslPolicyRule_trackType').trigger('change'); $('#xslPolicyRule_validator option[value="exists"]').prop('selected', true); $('#xslPolicyRule_validator').trigger('change'); + $('#xslPolicyRule_sourceOccurrence option').remove(); + $('#xslPolicyRule_sourceOccurrence option[value=""]').prop('selected', true); + $('#xslPolicyRule_sourceOccurrence').trigger('change'); + $('#xslPolicyRule_sourceField option').remove(); + $('#xslPolicyRule_sourceField option[value=""]').prop('selected', true); + $('#xslPolicyRule_sourceField').trigger('change'); + $('#xslPolicyRule_sourceTrackType option[value=""]').prop('selected', true); + $('#xslPolicyRule_sourceTrackType').trigger('change'); } if (system) { @@ -97,52 +143,69 @@ var policyTreeRulesMI = (function() { $('#xslPolicyRule_occurrence').prop('disabled', true); $('#xslPolicyRule_validator').prop('disabled', true); $('#xslPolicyRule_value').prop('disabled', true); - $('#xslPolicyRule_SaveRule').addClass('hidden'); - $('#xslPolicyRule_DuplicateRule').addClass('hidden'); - $('#xslPolicyRule_DeleteRule').addClass('hidden'); + $('#xslPolicyRule_valueType').prop('disabled', true); + $('#xslPolicyRule_sourceOccurrence').prop('disabled', true); + $('#xslPolicyRule_sourceField').prop('disabled', true); + $('#xslPolicyRule_sourceTrackType').prop('disabled', true); + $('#xslPolicyRule_SaveRule').parent().addClass('hidden'); + $('#xslPolicyRule_DuplicateRule').parent().addClass('hidden'); + $('#xslPolicyRule_DeleteRule').parent().addClass('hidden'); } else { $('#xslPolicyRule_title').prop('disabled', false); $('#xslPolicyRule_trackType').prop('disabled', false); $('#xslPolicyRule_field').prop('disabled', false); $('#xslPolicyRule_level').prop('disabled', false); - displayOccurenceField($('#xslPolicyRule_trackType').val()); + displayOccurrenceField($('#xslPolicyRule_trackType').val(), $('#xslPolicyRule_occurrence')); $('#xslPolicyRule_validator').prop('disabled', false); + $('#xslPolicyRule_valueType').prop('disabled', false); + displayOccurrenceField($('#xslPolicyRule_sourceTrackType').val(), $('#xslPolicyRule_sourceOccurrence')); + $('#xslPolicyRule_sourceField').prop('disabled', false); + $('#xslPolicyRule_sourceTrackType').prop('disabled', false); $('#xslPolicyRule_value').prop('disabled', false); - $('#xslPolicyRule_SaveRule').removeClass('hidden'); - $('#xslPolicyRule_DuplicateRule').removeClass('hidden'); - $('#xslPolicyRule_DeleteRule').removeClass('hidden'); + $('#xslPolicyRule_SaveRule').parent().removeClass('hidden'); + $('#xslPolicyRule_DuplicateRule').parent().removeClass('hidden'); + $('#xslPolicyRule_DeleteRule').parent().removeClass('hidden'); } $('#policyFix').affix('checkPosition'); } var loadFieldsList = function(trackType, field) { - policyTreeAjax.getFieldsList(trackType, field); + var value = field === null ? '' : field.val(); + policyTreeAjax.getFieldsList(trackType, field, value); - if (field) { - $('#xslPolicyRule_field').trigger('change'); + if (field !== null) { + field.trigger('change'); } } - var fieldsListOk = function(fields, field) { - $('#xslPolicyRule_field option').remove(); - $('#xslPolicyRule_field').append(''); + var fieldsListOk = function(fields, field, value) { + if (field === null) { + return; + } + + field.find('option').remove(); + field.append(''); $.each(fields, function(k, v) { - $('#xslPolicyRule_field').append(''); + field.append(''); }); - if (field) { - $('#xslPolicyRule_field option[value="' + field + '"]').prop('selected', true); + if (value) { + field.find('option[value="' + value + '"]').prop('selected', true); } } - var fieldsListError = function(field) { - $('#xslPolicyRule_field').html(''); - $('#xslPolicyRule_field').append(''); + var fieldsListError = function(field, value) { + if (field === null) { + return; + } + + field.html(''); + field.append(''); - if (field) { - $('#xslPolicyRule_field').append(''); + if (value) { + field.append(''); } } @@ -185,13 +248,36 @@ var policyTreeRulesMI = (function() { } } - var displayOccurenceField = function(trackType) { + var displayOccurrenceField = function(trackType, field) { if ('General' == trackType) { - $('#xslPolicyRule_occurrence').prop('disabled', true); - $('#xslPolicyRule_occurrence').val('*'); + field.prop('disabled', true); + field.val('*'); } else { - $('#xslPolicyRule_occurrence').prop('disabled', false); + field.prop('disabled', false); + } + } + + var displaySourceFields = function() { + if ($('#xslPolicyRule_valueType').is(':checked')) { + $('#xslPolicyRule_sourceOccurrence').parent().removeClass('hidden'); + $('#xslPolicyRule_sourceField').parent().removeClass('hidden'); + $('#xslPolicyRule_sourceTrackType').parent().removeClass('hidden'); + $('#xslPolicyRule_value').parent().addClass('hidden'); + $('#xslPolicyRule_sourceOccurrence').prop('required', 'required'); + $('#xslPolicyRule_sourceField').prop('required', 'required'); + $('#xslPolicyRule_sourceTrackType').prop('required', 'required'); + $('#xslPolicyRule_value').prop('required', false); + } + else { + $('#xslPolicyRule_sourceOccurrence').parent().addClass('hidden'); + $('#xslPolicyRule_sourceField').parent().addClass('hidden'); + $('#xslPolicyRule_sourceTrackType').parent().addClass('hidden'); + $('#xslPolicyRule_value').parent().removeClass('hidden'); + $('#xslPolicyRule_sourceOccurrence').prop('required', false); + $('#xslPolicyRule_sourceField').prop('required', false); + $('#xslPolicyRule_sourceTrackType').prop('required', false); + $('#xslPolicyRule_value').prop('required', 'required'); } } @@ -202,7 +288,8 @@ var policyTreeRulesMI = (function() { valuesListOk: valuesListOk, valuesListError: valuesListError, loadFieldsList: loadFieldsList, - displayOccurenceField: displayOccurenceField, + displayOccurrenceField: displayOccurrenceField, + displaySourceFields: displaySourceFields, loadValuesList: loadValuesList, displayValueField: displayValueField, } diff --git a/Source/Resource/html/js/policyWebEngine.js b/Source/Resource/html/js/policyWebEngine.js index 3df95420..3f45e714 100644 --- a/Source/Resource/html/js/policyWebEngine.js +++ b/Source/Resource/html/js/policyWebEngine.js @@ -212,7 +212,7 @@ var policyTreeAjax = (function() { * @param int policyId policy ID of the policy that will contain the rule * * @return json - * {"rule":{"tracktype":TRACKTYPE, "field":FIELD, "level" LEVEL, "id":RULE_ID, "name":NAME, "value":VALUE, "occurrence":OCCURENCE, "ope":OPERATOR}} + * {"rule":{"tracktype":TRACKTYPE, "field":FIELD, "level" LEVEL, "id":RULE_ID, "name":NAME, "value":VALUE, "occurrence":OCCURRENCE, "ope":OPERATOR}} */ webpage.xslt_policy_rule_create(policyNode.data.policyId, function(res){ data = JSON.parse(res); @@ -230,7 +230,7 @@ var policyTreeAjax = (function() { * @param int policyId policy ID of the policy that contain the rule * * @return json - * {"rule":{"tracktype":TRACKTYPE, "field":FIELD, "level" LEVEL, "id":RULE_ID, "name":NAME, "value":VALUE, "occurrence":OCCURENCE, "ope":OPERATOR}} + * {"rule":{"tracktype":TRACKTYPE, "field":FIELD, "level" LEVEL, "id":RULE_ID, "name":NAME, "value":VALUE, "occurrence":OCCURRENCE, "ope":OPERATOR}} */ var scope = ""; @@ -241,6 +241,11 @@ var policyTreeAjax = (function() { var occurrence = ""; var ope = ""; var value = ""; + var compare = false; + var src_tracktype = ""; + var src_field = ""; + var src_occurrence = ""; + var src_scope = ""; if ($(".ruleMediaTrace").hasClass("active")) scope = "mmt"; @@ -293,18 +298,55 @@ var policyTreeAjax = (function() { if (ope === null) ope = ""; - value = $("#xslPolicyRule_value").val(); - if (value === null) - value = ""; - } + compare = $("#xslPolicyRule_valueType").is(":checked"); + if (compare) + { + src_tracktype = $("#xslPolicyRule_sourceTrackType").val(); + if (src_tracktype === null) + src_tracktype = ""; - webpage.xslt_policy_rule_edit(ruleNode.data.ruleId, policyId, name, tracktype, field, occurrence, ope, value, scope, level, function(res){ - data = JSON.parse(res); - if (!data.error) - policyTree.ruleEdit(data.rule, ruleNode); + src_field = $("#xslPolicyRule_sourceField").val(); + if (src_field === null) + src_field = ""; + + src_occurrence = $("#xslPolicyRule_sourceOccurrence").val(); + if (src_occurrence === null) + src_occurrence = ""; + } else - mcoMessage.error(data.error); + { + value = $("#xslPolicyRule_value").val(); + if (value === null) + value = ""; + } + } + + if (compare) + { + var source = { + "tracktype": src_tracktype, + "field": src_field, + "scope": src_scope, + "occurrence": src_occurrence, + }; + webpage.xslt_policy_rule_edit(ruleNode.data.ruleId, policyId, name, tracktype, field, occurrence, ope, source, scope, level, function(res){ + data = JSON.parse(res); + if (!data.error) + policyTree.ruleEdit(data.rule, ruleNode); + else + mcoMessage.error(data.error); + }); + } + else + { + webpage.xslt_policy_rule_edit(ruleNode.data.ruleId, policyId, name, tracktype, field, occurrence, ope, value, scope, level, function(res){ + data = JSON.parse(res); + if (!data.error) + policyTree.ruleEdit(data.rule, ruleNode); + else + mcoMessage.error(data.error); }); + } } var ruleDelete = function(policyId, ruleNode) { @@ -333,7 +375,7 @@ var policyTreeAjax = (function() { * @param int dstPolicyId policy ID of the destination policy * * @return json - * {"rule":{"tracktype":TRACKTYPE, "field":FIELD, "level" LEVEL, "id":RULE_ID, "name":NAME, "value":VALUE, "occurrence":OCCURENCE, "ope":OPERATOR}} + * {"rule":{"tracktype":TRACKTYPE, "field":FIELD, "level" LEVEL, "id":RULE_ID, "name":NAME, "value":VALUE, "occurrence":OCCURRENCE, "ope":OPERATOR}} */ webpage.xslt_policy_rule_duplicate(policyId, ruleNode.data.ruleId, dstNode.data.policyId, function(res){ @@ -353,7 +395,7 @@ var policyTreeAjax = (function() { * @param int dstPolicyId policy ID of the destination policy * * @return json - * {"rule":{"tracktype":TRACKTYPE, "field":FIELD, "level" LEVEL, "id":RULE_ID, "name":NAME, "value":VALUE, "occurrence":OCCURENCE, "ope":OPERATOR}} + * {"rule":{"tracktype":TRACKTYPE, "field":FIELD, "level" LEVEL, "id":RULE_ID, "name":NAME, "value":VALUE, "occurrence":OCCURRENCE, "ope":OPERATOR}} */ webpage.xslt_policy_rule_move(policyId, ruleNode.data.ruleId, dstNode.data.policyId, function(res){ @@ -365,7 +407,7 @@ var policyTreeAjax = (function() { }); } - var getFieldsList = function(trackType, field) { + var getFieldsList = function(trackType, field, value) { /** * Get list of fields for a trackType (POST : type and field) * @@ -373,15 +415,17 @@ var policyTreeAjax = (function() { */ if (trackType === null) trackType = ""; - if (field === null) - field = ""; + if (value === null) + value = ""; + + console.debug(value); - webpage.get_fields_list(trackType, field, function(res){ + webpage.get_fields_list(trackType, value, function(res){ data = JSON.parse(res); if (!data.error) - policyTreeRulesMI.fieldsListOk(data.fields, field) + policyTreeRulesMI.fieldsListOk(data.fields, field, value) else - policyTreeRulesMI.fieldsListError(field); + policyTreeRulesMI.fieldsListError(field, value); }); } diff --git a/Source/Resource/html/js/policyWebKit.js b/Source/Resource/html/js/policyWebKit.js index 217b99fe..f058627d 100644 --- a/Source/Resource/html/js/policyWebKit.js +++ b/Source/Resource/html/js/policyWebKit.js @@ -202,7 +202,7 @@ var policyTreeAjax = (function() { * @param int policyId policy ID of the policy that will contain the rule * * @return json - * {"rule":{"tracktype":TRACKTYPE, "field":FIELD, "level" LEVEL, "id":RULE_ID, "name":NAME, "value":VALUE, "occurrence":OCCURENCE, "ope":OPERATOR}} + * {"rule":{"tracktype":TRACKTYPE, "field":FIELD, "level" LEVEL, "id":RULE_ID, "name":NAME, "value":VALUE, "occurrence":OCCURRENCE, "ope":OPERATOR}} */ res = webpage.xslt_policy_rule_create(policyNode.data.policyId); data = JSON.parse(res); @@ -219,7 +219,7 @@ var policyTreeAjax = (function() { * @param int policyId policy ID of the policy that contain the rule * * @return json - * {"rule":{"tracktype":TRACKTYPE, "field":FIEL, "level" LEVEL, "id":RULE_ID, "name":NAME, "value":VALUE, "occurrence":OCCURENCE, "ope":OPERATOR}} + * {"rule":{"tracktype":TRACKTYPE, "field":FIEL, "level" LEVEL, "id":RULE_ID, "name":NAME, "value":VALUE, "occurrence":OCCURRENCE, "ope":OPERATOR}} */ var scope = ""; @@ -230,6 +230,11 @@ var policyTreeAjax = (function() { var occurrence = ""; var ope = ""; var value = ""; + var compare = false; + var src_tracktype = ""; + var src_field = ""; + var src_occurrence = ""; + var src_scope = ""; if ($(".ruleMediaTrace").hasClass("active")) scope = "mmt"; @@ -282,12 +287,40 @@ var policyTreeAjax = (function() { if (ope === null) ope = ""; - value = $("#xslPolicyRule_value").val(); - if (value === null) - value = ""; + compare = $("#xslPolicyRule_valueType").is(":checked"); + if (compare) + { + src_tracktype = $("#xslPolicyRule_sourceTrackType").val(); + if (src_tracktype === null) + src_tracktype = ""; + + src_field = $("#xslPolicyRule_sourceField").val(); + if (src_field === null) + src_field = ""; + + src_occurrence = $("#xslPolicyRule_sourceOccurrence").val(); + if (src_occurrence === null) + src_occurrence = ""; + } + else + { + value = $("#xslPolicyRule_value").val(); + if (value === null) + value = ""; + } } - res = webpage.xslt_policy_rule_edit(ruleNode.data.ruleId, policyId, name, tracktype, field, occurrence, ope, value, scope, level); + if (compare) { + var source = { + "tracktype": src_tracktype, + "field": src_field, + "scope": src_scope, + "occurrence": src_occurrence, + }; + res = webpage.xslt_policy_rule_edit(ruleNode.data.ruleId, policyId, name, tracktype, field, occurrence, ope, source, scope, level); + } + else + res = webpage.xslt_policy_rule_edit(ruleNode.data.ruleId, policyId, name, tracktype, field, occurrence, ope, value, scope, level); data = JSON.parse(res); if (!data.error) policyTree.ruleEdit(data.rule, ruleNode); @@ -320,7 +353,7 @@ var policyTreeAjax = (function() { * @param int dstPolicyId policy ID of the destination policy * * @return json - * {"rule":{"tracktype":TRACKTYPE, "field":FIELD, "level" LEVEL, "id":RULE_ID, "name":NAME, "value":VALUE, "occurrence":OCCURENCE, "ope":OPERATOR}} + * {"rule":{"tracktype":TRACKTYPE, "field":FIELD, "level" LEVEL, "id":RULE_ID, "name":NAME, "value":VALUE, "occurrence":OCCURRENCE, "ope":OPERATOR}} */ res = webpage.xslt_policy_rule_duplicate(policyId, ruleNode.data.ruleId, dstNode.data.policyId); @@ -339,7 +372,7 @@ var policyTreeAjax = (function() { * @param int dstPolicyId policy ID of the destination policy * * @return json - * {"rule":{"tracktype":TRACKTYPE, "field":FIELD, "level" LEVEL, "id":RULE_ID, "name":NAME, "value":VALUE, "occurrence":OCCURENCE, "ope":OPERATOR}} + * {"rule":{"tracktype":TRACKTYPE, "field":FIELD, "level" LEVEL, "id":RULE_ID, "name":NAME, "value":VALUE, "occurrence":OCCURRENCE, "ope":OPERATOR}} */ res = webpage.xslt_policy_rule_move(policyId, ruleNode.data.ruleId, policyTree.getPolicyId(dstNode)); @@ -350,7 +383,7 @@ var policyTreeAjax = (function() { mcoMessage.error(data.error); } - var getFieldsList = function(trackType, field) { + var getFieldsList = function(trackType, field, value) { /** * Get list of fields for a trackType (POST : type and field) * @@ -358,15 +391,15 @@ var policyTreeAjax = (function() { */ if (trackType === null) trackType = ""; - if (field === null) - field = ""; + if (value === null) + value = ""; res = webpage.get_fields_list(trackType, field); data = JSON.parse(res); if (!data.error) - policyTreeRulesMI.fieldsListOk(data.fields, field) + policyTreeRulesMI.fieldsListOk(data.fields, field, value) else - policyTreeRulesMI.fieldsListError(field); + policyTreeRulesMI.fieldsListError(field, value); } var getValuesList = function(trackType, field, value) { diff --git a/Source/Resource/html/js/publicPolicies/listPolicyTree.js b/Source/Resource/html/js/publicPolicies/listPolicyTree.js index cc6be12d..77dd7894 100644 --- a/Source/Resource/html/js/publicPolicies/listPolicyTree.js +++ b/Source/Resource/html/js/publicPolicies/listPolicyTree.js @@ -130,17 +130,33 @@ var policyTree = (function() { } if (undefined == node.data.occurrence || '' == node.data.occurrence || '*' == node.data.occurrence) { - data += '
  • Occurence: *
  • '; + data += '
  • Occurrence: *
  • '; } else { - data += '
  • Occurence: ' + node.data.occurrence + '
  • '; + data += '
  • Occurrence: ' + node.data.occurrence + '
  • '; } if (undefined != node.data.ope) { data += '
  • Operator: ' + node.data.ope + '
  • '; } - if (undefined != node.data.value) { + if (undefined != node.data.source) { + if (undefined != node.data.source.tracktype) { + data += '
  • Source TrackType: ' + node.data.source.tracktype + '
  • '; + } + + if (undefined != node.data.source.field) { + data += '
  • Source Field: ' + node.data.source.field + '
  • '; + } + + if (undefined == node.data.source.occurrence || '' == node.data.source.occurrence || '*' == node.data.source.occurrence) { + data += '
  • Source Occurrence: *
  • '; + } + else { + data += '
  • Source Occurrence: ' + node.data.source.occurrence + '
  • '; + } + } + else if (undefined != node.data.value) { data += '
  • Value: ' + node.data.value + '
  • '; } data += ''; diff --git a/Source/Resource/html/xslPolicy.html b/Source/Resource/html/xslPolicy.html index ebbb875d..908b07f1 100644 --- a/Source/Resource/html/xslPolicy.html +++ b/Source/Resource/html/xslPolicy.html @@ -219,10 +219,57 @@

    Actions:

    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    diff --git a/Source/Resource/mediaconch-js/MediaConch.js b/Source/Resource/mediaconch-js/MediaConch.js index 1c5dc796..8746981b 100644 --- a/Source/Resource/mediaconch-js/MediaConch.js +++ b/Source/Resource/mediaconch-js/MediaConch.js @@ -241,10 +241,6 @@ var toReturn = ''; var outcome = true; - const policyXsltProc = new XSLTProcessor(); - policyXsltProc.setParameter(null, 'compare', ''); - policyXsltProc.setParameter(null, 'policy_verbosity', verbosity); - policyXsltProc.importStylesheet(policyTransformXmlXsl); const xmlSerializer = new XMLSerializer(); const parser = new DOMParser(); @@ -295,7 +291,7 @@ checker.add_policy(xmlSerializer.serializeToString(policy.xml)); }); - if(checker.full_parse()) { + if(checker.is_policy_supported()) { const temp = checker.analyze(xmlSerializer.serializeToString(mediainfoReport), verbosity); var report = parser.parseFromString(temp, 'application/xml'); @@ -342,6 +338,10 @@ toReturn += '\n\n'; } + const policyXsltProc = new XSLTProcessor(); + policyXsltProc.setParameter(null, 'compare', ''); + policyXsltProc.setParameter(null, 'policy_verbosity', verbosity); + policyXsltProc.importStylesheet(policyTransformXmlXsl); let policyXsl = policyXsltProc.transformToDocument(policy.xml); policyXsl = updatePrefixInPolicy(policyXsl); From 6677424352cbc4d6ddda6b7fc4234f2a2494f46b Mon Sep 17 00:00:00 2001 From: Maxime Gervais Date: Fri, 17 May 2024 23:35:07 +0200 Subject: [PATCH 3/4] Policies tests Signed-off-by: Maxime Gervais --- Project/GNU/CLI/Makefile.am | 3 +- Project/GNU/CLI/test/test_policy.sh | 45 ++++++++++++++++++++++++++++ Project/GNU/CLI/test/test_policy.txt | 7 +++++ 3 files changed, 54 insertions(+), 1 deletion(-) create mode 100755 Project/GNU/CLI/test/test_policy.sh create mode 100644 Project/GNU/CLI/test/test_policy.txt diff --git a/Project/GNU/CLI/Makefile.am b/Project/GNU/CLI/Makefile.am index 18eeec38..87d26fec 100644 --- a/Project/GNU/CLI/Makefile.am +++ b/Project/GNU/CLI/Makefile.am @@ -60,7 +60,8 @@ TESTS = \ test/simple.sh \ test/filename.sh \ test/test_mk.sh \ - test/test_ffv1.sh + test/test_ffv1.sh \ + test/test_policy.sh SAMPLES_DIR = test/SampleFiles diff --git a/Project/GNU/CLI/test/test_policy.sh b/Project/GNU/CLI/test/test_policy.sh new file mode 100755 index 00000000..8f921ef4 --- /dev/null +++ b/Project/GNU/CLI/test/test_policy.sh @@ -0,0 +1,45 @@ +#!/bin/bash + +PATH_SCRIPT=$(dirname "${0}") +. "${PATH_SCRIPT}/utils.sh" + +FILES_DIRECTORY="${PATH_SCRIPT}/SampleFiles/PolicyTestFiles" + +MC="${PWD}/mediaconch" + +RCODE=0 + +while read LINE ; do + POLICY="$(echo "${LINE}" | cut -d':' -f1)" + FILE="$(echo "${LINE}" | cut -d':' -f2)" + OUTCOME="$(echo "${LINE}" | cut -d':' -f3)" + TEST="${POLICY}:$(basename "${FILE}"):${OUTCOME}" + + if [ ! -e "${FILES_DIRECTORY}/Policy/${POLICY}" ] ; then + echo "NOK: ${TEST}/${POLICY}, file not found" >&9 + RCODE=1 + continue + fi + + if [ ! -e "${FILES_DIRECTORY}/${FILE}" ] ; then + echo "NOK: ${TEST}/${FILE}, file not found" >&9 + RCODE=1 + continue + fi + + pushd "${FILES_DIRECTORY}" >/dev/null 2>&1 + DATA="$(${MC} -p Policy/${POLICY} -fx ${FILE})" + + T1=`echo "${DATA}" | xmllint --xpath \ + "string(/*[local-name()='MediaConch']/*[local-name()='media']/*[local-name()='policy']/@outcome)" -` + + if [ "${T1}" == "${OUTCOME}" ] ; then + echo "OK: ${TEST}" >&9 + else + echo "NOK: ${TEST}, failed" >&9 + RCODE=1 + fi + popd >/dev/null 2>&1 +done < "${PATH_SCRIPT}/test_policy.txt" + +exit ${RCODE} diff --git a/Project/GNU/CLI/test/test_policy.txt b/Project/GNU/CLI/test/test_policy.txt new file mode 100644 index 00000000..28f557bd --- /dev/null +++ b/Project/GNU/CLI/test/test_policy.txt @@ -0,0 +1,7 @@ +value.xml:Matroska/videofirst.mkv:pass +value.xml:Matroska/audiofirst.mkv:fail +info.xml:Matroska/audiofirst.mkv:info +warn.xml:Matroska/audiofirst.mkv:warn +levelcap.xml:Matroska/audiofirst.mkv:info +operators.xml:Matroska/videofirst.mkv:pass +mmt.xml:Matroska/videofirst.mkv:pass From 87768ddde11b729df45ea57571528efe7ba3067b Mon Sep 17 00:00:00 2001 From: Maxime Gervais Date: Mon, 20 May 2024 13:00:13 +0200 Subject: [PATCH 4/4] Fix Ci Signed-off-by: Maxime Gervais --- .github/workflows/MediaConch_Checks.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/MediaConch_Checks.yml b/.github/workflows/MediaConch_Checks.yml index fab2eaa7..e2ef8eb6 100644 --- a/.github/workflows/MediaConch_Checks.yml +++ b/.github/workflows/MediaConch_Checks.yml @@ -26,7 +26,7 @@ jobs: pip --disable-pip-version-check install git+https://github.com/vi/mkvparse.git fi if [ "$RUNNER_OS" == "macOS" ]; then - brew install automake libxslt sqlite jansson libevent qt@5 sfk xmlstarlet ffmpeg + brew install libtool automake libxslt sqlite jansson libevent qt@5 sfk xmlstarlet ffmpeg sudo pip --disable-pip-version-check install --prefix /usr/local git+https://github.com/vi/mkvparse.git fi - name: Get ZenLib info @@ -89,8 +89,8 @@ jobs: - name: Configure GUI run: | cd Project/Qt - export PATH=/usr/local/opt/qt@5/bin:$PATH - ./prepare INCLUDEPATH+=/usr/local/include CONFIG+=c++11 -after QMAKE_MACOSX_DEPLOYMENT_TARGET=10.9 QMAKE_LFLAGS-=-Wl,-ld_classic + export PATH=/opt/homebrew/opt/qt@5/bin:$PATH + ./prepare CONFIG+=c++11 -after QMAKE_MACOSX_DEPLOYMENT_TARGET=10.9 QMAKE_LFLAGS-=-Wl,-ld_classic - name: Build GUI run: | cd Project/Qt