#
#
# encoding utilities
#
#
#
# option_info_to_json_type()
# encode_json()
# add_json()
# close_json()
#
# string_to_html()
# html_to_html()
# get_formatted_html_column_value()
#
#
#
#
#
#
#
#
# option_info_to_json_type()
#
#
#
subroutine(option_info_to_json_type(
string option_info_type), (
# This converts an option_info type to the type used in JSON (add_json()).
# I.e., "integer" is converted to "int", etc.
string json_type;
if (option_info_type eq "boolean" or option_info_type eq "bool") then (
json_type = "bool";
)
else if (option_info_type eq "integer" or option_info_type eq "int") then (
json_type = "int";
)
else if (option_info_type eq "float") then (
json_type = "float";
)
else if (option_info_type eq "bytes") then (
# bytes become "int" because the byte unit becomes separated from the number.
json_type = "int";
)
else (
# Everything else is string, i.e. "string", "charset", "permissions", "", etc.
json_type = "string";
);
# Return
json_type;
));
#
#
#
# encode_json()
#
#
#
subroutine(encode_json(string s), (
if (matches_regular_expression(s, "[\\'\"\$()=%\s]")) then (
s = replace_all(s, "\\", "\u005C");
s = replace_all(s, "'", "\u0027");
s = replace_all(s, '"', "\u0022");
s = replace_all(s, "$", "\u0024");
# KHP 20/Aug/2010 escape braces to avoid execution of javascript expressions
s = replace_all(s, "(", "\u0028");
s = replace_all(s, ")", "\u0029");
# We escape any expression brace to make sure that the value does not become expanded upon display.
# We make that simpler by escaping the equal sign only!
s = replace_all(s, '=', "\u003d");
# handle %0 (Null) value or other none escaped values
s = replace_all(s, "%0", "\u00250");
s = replace_all(s, "\0", "\u0000");
s = replace_all(s, "\t", "\u0009");
s = replace_all(s, "\n", "\u000A");
s = replace_all(s, "\v", "\u000B");
s = replace_all(s, "\f", "\u000C");
s = replace_all(s, "\r", "\u000D");
# debug_message("#### encoded json string: " . s . "\n");
);
s;
));
#
#
#
# add_json()
#
#
#
subroutine(add_json(
string item_name,
string item_value,
string type), (
# This adds a JSON property name and value.
# type is: string, int, float, bool or obj
# For security reasons we also encode int, float and bool. Item values of type obj
# are already encoded, they must not be encoded again!
if (type eq "string") then (
# string
'"' . item_name . '":"' . encode_json(item_value) . '",';
)
else if (type ne "obj") then (
# int, float or bool
# Encode for security reasons
# KHP 01/Jun/2011 - be more tolerate with empty values
# by defining a default, otherwise we have an invalid
# JSON string
if (item_value eq "") then (
if (type eq "bool") then (
item_value = "false";
)
else (
item_value = "0";
);
);
'"' . item_name . '":' . encode_json(item_value) . ',';
)
else (
# This is an object, don't encode
'"' . item_name . '":' . item_value . ',';
);
));
#
#
#
# close_json()
#
#
#
subroutine(close_json(string s), (
# replaces the last comma of add_json() wih a curved brace
s = replace_last(s, ",", "}");
s;
));
#
#
#
# string_to_html()
#
#
#
subroutine(string_to_html(string s), (
if (matches_regular_expression(s, "[&<>\"'()=\$\\%]")) then (
s = replace_all(s, "&", "&");
s = replace_all(s, "<", "<");
s = replace_all(s, ">", ">");
s = replace_all(s, '"', """);
s = replace_all(s, "'", "'");
s = replace_all(s, "(", "(");
s = replace_all(s, ")", ")");
s = replace_all(s, "=", "="); # We escape "=" so that we don't get any executable code in curley braces!
s = replace_all(s, "$", "$");
# We escape any expression brace to make sure that the value does not become expanded upon display.
# We already escape the equal character, so we don't need to replace the curly braces!s
# s = replace_all(s, '{', "{");
# s = replace_all(s, '}', "}");
# s = replace_all(s, "\\", "\"); # Escpace backslash so that they don't escape anything upon -dp
# handle %0 (Null) value or other none escaped values
s = replace_all(s, "%0", "%0");
# Make sure there is no more % character followed by hex numbers
s = replace_all(s, "%", "%");
);
s;
));
#
#
#
# html_to_html()
#
#
#
subroutine(html_to_html(string s), (
# This converts a string which may already contain HTML elements to HTML display,
# this means we only escape critical characters such as "$".
# This is used for example in headers and footers where users define custom HTML elements.
# debug_message("#### html_to_html() s ori: " . s . "\n");
if (matches_regular_expression(s, "[\$%]")) then (
s = replace_all(s, "$", "$");
# handle %0 (Null) value or other none escaped values
s = replace_all(s, "%0", "%0");
);
# debug_message("#### html_to_html() s escaped: " . s . "\n");
s;
));
#
#
#
# get_formatted_html_column_value()
#
#
#
# Applies text formatting (breaks and truncates text)
# and escapes HTML markup and Salang code.
#
# Note, % escapes are displayed as such since version 8,
# i.e. %20 in the query result is displayed as %20 in the table.
#
# To return a string in full length define:
# max_text_length: 0
# max_continuous_text_length: 0
# max_continuous_text_length_offset: 0
subroutine(get_formatted_html_column_value(
string column_value,
string display_format_type,
node text_info), (
int max_text_length = @text_info{"maximum_text_length"};
int max_continuous_text_length = @text_info{"maximum_continuous_text_length"};
int max_continuous_text_length_offset = @text_info{"maximum_continuous_text_length_offset"};
bool dash_breaks = @text_info{"dash_breaks"};
string break_entity = @text_info{"break_entity"};
# debug_message("\n\n#### get_formatted_html_column_value START \n\n");
# debug_message("\n#### Column value ori: " . replace_all(column_value, "$", "__ESCAPED_DOLLAR_IN_DEBUG_MESSAGE__") . "\n");
#
#
# Format the column value
#
#
if (display_format_type ne "") then (
column_value = format(column_value, display_format_type);
);
#
#
# Truncate string
#
#
if (max_text_length > 0) then (
int string_length = length(column_value);
if (string_length > max_text_length) then (
# debug_message("#### Truncate string is active\n");
column_value = substr(column_value, 0, max_text_length);
column_value .= "...";
);
);
#
#
# Break string
#
#
# A string in a html table will automatically break if the string
# conatins a space or dash. Note, a dash breaks in IE, Safari and Opera,
# it does not break in Mozilla or might not break in other browsers.
# As Mozilla is a minor browser start using the dash for breaks from now
# and imoplement web browser specific breaking later, i.e. break with
# spaces for Mozilla and Netscape web browsers only.
subroutine(break_string(
string ori_string,
int string_length,
int max_continuous_text_length,
int max_continuous_text_length_offset), (
int number_of_substrings = (string_length / max_continuous_text_length);
if ((string_length % max_continuous_text_length) > 0) then (
number_of_substrings++;
);
int length_of_last_substring = string_length - (max_continuous_text_length * (number_of_substrings - 1));
# if length of last substring is equal or smaller max_continuous_text_length_offset then don't break the last substring!
bool break_last_substring = true;
if (length_of_last_substring <= max_continuous_text_length_offset) then (
break_last_substring = false;
);
# debug_message("#### Number of substrings modulo: " . number_of_substrings . "\n");
string new_string = "";
int substring_index = 0;
for (int i = 1; i <= number_of_substrings; i++) (
if (i < (number_of_substrings - 1)) then (
new_string .= substr(ori_string, substring_index, max_continuous_text_length) . "__html__break__escape__variable__";
)
else if (i == (number_of_substrings - 1)) then (
if (break_last_substring) then (
new_string .= substr(ori_string, substring_index, max_continuous_text_length) . "__html__break__escape__variable__";
)
else (
new_string .= substr(ori_string, substring_index, max_continuous_text_length);
);
)
else (
new_string .= substr(ori_string, substring_index, max_continuous_text_length);
);
substring_index += max_continuous_text_length;
);
new_string;
));
subroutine(split_special(
string ori_string,
string main_divider,
string destination_node,
bool dash_breaks), (
string sub_divider;
if (main_divider eq " ") then (
sub_divider = "-";
)
else (
sub_divider = " ";
);
if (node_exists("volatile.temp.split_result")) then (
delete_node("volatile.temp.split_result");
);
split(ori_string, main_divider, "volatile.temp.split_result");
node item;
string substring;
int number_of_substrings = num_subnodes("volatile.temp.split_result");
int count = 0;
# populate destination node by inserting a divider string node into the original split
foreach item "volatile.temp.split_result" (
destination_node . "." . count = node_value(item);
if ((count + 1) < number_of_substrings) then (
destination_node . "." . count . "_divider" = main_divider;
);
count++;
);
if (dash_breaks) then (
foreach item destination_node (
substring = node_value(item);
if (contains(substring, sub_divider)) then (
# split the substring into substrings
split_special(substring, sub_divider, item . ".subsubstrings", false);
);
);
); # if dash_breaks
));
subroutine(combine_special(
int max_continuous_text_length,
int max_continuous_text_length_offset,
string substrings_node), (
string new_string;
string substring;
string next_character;
int substring_length;
node item;
foreach item substrings_node (
if (!node_exists(item . ".subsubstrings")) then (
substring = node_value(item);
substring_length = length(substring);
# debug_message("#### substring_length: " . substring_length . "\n");
if (substring_length > max_continuous_text_length) then (
substring = break_string(substring, substring_length, max_continuous_text_length, max_continuous_text_length_offset);
# debug_message("#### returned substring after break: " . substring . "\n");
);
new_string = node_value("volatile.temp.recombined_string");
new_string .= substring;
volatile.temp.recombined_string = new_string;
)
else (
combine_special(max_continuous_text_length, max_continuous_text_length_offset, item . ".subsubstrings");
);
);
));
if (max_continuous_text_length > 0) then (
# debug_message("#### Break string is active\n");
# debug_message("#### Intact string: " . column_value . "\n");
int string_length = length(column_value);
if (string_length > max_continuous_text_length) then (
bool contains_spaces = contains(column_value, " ");
bool contains_dashes = contains(column_value, "-");
if ((contains_spaces or contains_dashes) and dash_breaks) then (
# ----------------------------------------------------
# break substrings only, divide by space and/or dashes
# ----------------------------------------------------
if (node_exists("volatile.temp.substrings")) then (
delete_node("volatile.temp.substrings");
);
if (contains_spaces) then (
# split by spaces first
split_special(column_value, " ", "volatile.temp.substrings", true);
)
else (
# split by dashes
split_special(column_value, "-", "volatile.temp.substrings", false);
);
# debug_message("\n\noriginal string: " . column_value . "\n");
# debug_message(node_as_string("volatile.temp.substrings") . "\n");
volatile.temp.recombined_string = "";
combine_special(max_continuous_text_length, max_continuous_text_length_offset, "volatile.temp.substrings");
column_value = volatile.temp.recombined_string;
# debug_message("new string: " . column_value . "\n\n");
)
else if (contains_spaces) then (
# -------------------------------------------
# break substrings only, divide by space only
# -------------------------------------------
if (node_exists("volatile.temp.substrings")) then (
delete_node("volatile.temp.substrings");
);
split_special(column_value, " ", "volatile.temp.substrings", false);
volatile.temp.recombined_string = "";
combine_special(max_continuous_text_length, max_continuous_text_length_offset, "volatile.temp.substrings");
column_value = volatile.temp.recombined_string;
)
else (
# -----------------------
# break the single string
# -----------------------
column_value = break_string(column_value, string_length, max_continuous_text_length, max_continuous_text_length_offset);
);
);
);
#
#
# Escape string for html presentation
#
#
# debug_message("\n#### column_value before string_to_html:" . column_value . "\n");
column_value = string_to_html(column_value);
# debug_message("#### column_value after string_to_html:" . column_value . "\n\n");
#*
if (contains(column_value, "&")) then (
column_value = replace_all(column_value, "&", "&");
);
if (contains(column_value, "<")) then (
column_value = replace_all(column_value, "<", "<");
);
if (contains(column_value, ">")) then (
column_value = replace_all(column_value, ">", ">");
);
if (contains(column_value, "$")) then (
column_value = replace_all(column_value, "$", "$");
);
if (contains(column_value, "%")) then (
column_value = replace_all(column_value, "%", "%");
);
*#
#
#
# If string has been broken then replace __html__break__escape__variable__ with break_entity
#
#
# break_entity depends on user agent and is defined in report_builder_standard
# possible values are: , , or
if (contains(column_value, "__html__break__escape__variable__")) then (
column_value = replace_all(column_value, "__html__break__escape__variable__", break_entity);
);
# debug_message("#### Column value final: " . column_value . "\n\n");
column_value;
));