Merge branch 'ent-11341-fallos-en-la-recoleccion-de-logs' into 'develop'

Encode log data to base64 to prevent it from breaking XML data files.

See merge request artica/pandorafms!5975
This commit is contained in:
Daniel Rodriguez 2023-05-31 11:16:23 +00:00
commit cd01584ce9
5 changed files with 134 additions and 17 deletions

View File

@ -22,6 +22,11 @@
use strict; use strict;
use File::Basename; use File::Basename;
use Scalar::Util qw(looks_like_number); use Scalar::Util qw(looks_like_number);
BEGIN {
eval {
require MIME::Base64;
};
}
# Output format (module or log_module). # Output format (module or log_module).
my $Output = 'module'; my $Output = 'module';
@ -65,6 +70,37 @@ if ( (defined ($ENV{GREP_LOG_TMP})) && (-d $ENV{GREP_LOG_TMP}) ) {
$Idx_dir=$ENV{GREP_LOG_TMP}; $Idx_dir=$ENV{GREP_LOG_TMP};
} }
# Define encode_base64 if it is not available via MIME::Base64.
my $encode_sub = defined(&MIME::Base64::encode_base64) ? \&MIME::Base64::encode_base64 : sub {
my ($str, $endl) = @_;
my @ALPHABET = ('A'..'Z', 'a'..'z', 0..9, '+', '/');
my $str_len = length($str);
my $str_base64 = '';
for (my $i = 0; $i < $str_len; $i += 3) {
my $chunk = substr($str, $i, 3);
my $chunk_len = length($chunk);
my $num = 0;
$num |= ord(substr($chunk, 0, 1)) << 16 if ($chunk_len >= 1);
$num |= ord(substr($chunk, 1, 1)) << 8 if ($chunk_len >= 2);
$num |= ord(substr($chunk, 2, 1)) if ($chunk_len == 3);
my $enc_1 = ($num & 0xfc0000) >> 18;
my $enc_2 = ($num & 0x03f000) >> 12;
my $enc_3 = ($num & 0x000fc0) >> 6;
my $enc_4 = ($num & 0x00003f);
$str_base64 .= $ALPHABET[$enc_1];
$str_base64 .= $ALPHABET[$enc_2];
$str_base64 .= $chunk_len >= 2 ? $ALPHABET[$enc_3] : '=';
$str_base64 .= $chunk_len == 3 ? $ALPHABET[$enc_4] : '=';
}
return $str_base64;
};
######################################################################################## ########################################################################################
# Erase blank spaces before and after the string # Erase blank spaces before and after the string
######################################################################################## ########################################################################################
@ -335,11 +371,13 @@ sub print_log ($) {
my $output = "<log_module>\n"; my $output = "<log_module>\n";
$output .= "<source><![CDATA[" . $Module_name . "]]></source>\n"; $output .= "<source><![CDATA[" . $Module_name . "]]></source>\n";
$output .= "<data><![CDATA["; $output .= "<data><![CDATA[";
my $tmp = '';
foreach my $line (@kdata) { foreach my $line (@kdata) {
my $processed_line = $line; foreach my $content (@{$data->{$line}}) {
$processed_line =~ s/\]\]/]]]]><![CDATA[/g; $tmp .= $content;
$output .= $processed_line;
} }
}
$output .= &$encode_sub($tmp, '');
$output .= "]]></data>"; $output .= "]]></data>";
$output .= "</log_module>\n"; $output .= "</log_module>\n";

View File

@ -22,6 +22,11 @@
use strict; use strict;
use File::Basename; use File::Basename;
BEGIN {
eval {
require MIME::Base64;
};
}
# Output format (module or log_module). # Output format (module or log_module).
my $Output = 'log_module'; my $Output = 'log_module';
@ -53,6 +58,37 @@ my $Idx_size = 0;
# Regular expression to be matched # Regular expression to be matched
my $Reg_exp = ''; my $Reg_exp = '';
# Define encode_base64 if it is not available via MIME::Base64.
my $encode_sub = defined(&MIME::Base64::encode_base64) ? \&MIME::Base64::encode_base64 : sub {
my ($str, $endl) = @_;
my @ALPHABET = ('A'..'Z', 'a'..'z', 0..9, '+', '/');
my $str_len = length($str);
my $str_base64 = '';
for (my $i = 0; $i < $str_len; $i += 3) {
my $chunk = substr($str, $i, 3);
my $chunk_len = length($chunk);
my $num = 0;
$num |= ord(substr($chunk, 0, 1)) << 16 if ($chunk_len >= 1);
$num |= ord(substr($chunk, 1, 1)) << 8 if ($chunk_len >= 2);
$num |= ord(substr($chunk, 2, 1)) if ($chunk_len == 3);
my $enc_1 = ($num & 0xfc0000) >> 18;
my $enc_2 = ($num & 0x03f000) >> 12;
my $enc_3 = ($num & 0x000fc0) >> 6;
my $enc_4 = ($num & 0x00003f);
$str_base64 .= $ALPHABET[$enc_1];
$str_base64 .= $ALPHABET[$enc_2];
$str_base64 .= $chunk_len >= 2 ? $ALPHABET[$enc_3] : '=';
$str_base64 .= $chunk_len == 3 ? $ALPHABET[$enc_4] : '=';
}
return $str_base64;
};
############################################################################### ###############################################################################
# SUB error_msg # SUB error_msg
# Print an error message and exit. # Print an error message and exit.
@ -213,11 +249,9 @@ sub print_log (@) {
if ($Output eq 'log_module') { if ($Output eq 'log_module') {
my $output = "<log_module>\n"; my $output = "<log_module>\n";
$output .= "<source><![CDATA[" . $Module_name . "]]></source>\n"; $output .= "<source><![CDATA[" . $Module_name . "]]></source>\n";
$output .= "<encoding>base64</encoding>\n";
$output .= "<data><![CDATA["; $output .= "<data><![CDATA[";
foreach my $line (@data) { $output .= &$encode_sub(join('', @data), '');
$line =~ s/\]\]/]]]]><![CDATA[/g;
$output .= $line;
}
$output .= "]]></data>"; $output .= "]]></data>";
$output .= "</log_module>\n"; $output .= "</log_module>\n";

View File

@ -520,7 +520,7 @@ Pandora_Module::getXml () {
if (this->module_type == TYPE_LOG) { if (this->module_type == TYPE_LOG) {
module_xml = "<log_module>\n\t<source><![CDATA["; module_xml = "<log_module>\n\t<source><![CDATA[";
module_xml += this->module_name; module_xml += this->module_name;
module_xml += "]]></source>\n\t<data><![CDATA["; module_xml += "]]></source>\n\t<encoding>base64</encoding>\n\t<data><![CDATA[";
if (this->data_list && this->data_list->size () > 1) { if (this->data_list && this->data_list->size () > 1) {
list<Pandora_Data *>::iterator iter; list<Pandora_Data *>::iterator iter;
@ -532,25 +532,19 @@ Pandora_Module::getXml () {
data = *iter; data = *iter;
try { try {
data_clean = strreplace (this->getDataOutput (data), data_clean += this->getDataOutput(data);
"%", "%%" );
data_clean = strreplace (data_clean, "]]>", "]]><![CDATA[");
} catch (Module_Exception e) { } catch (Module_Exception e) {
continue; continue;
} }
module_xml += data_clean;
} }
} else { } else {
data = data_list->front (); data = data_list->front ();
try { try {
data_clean = strreplace (this->getDataOutput (data), "%", "%%" ); data_clean = this->getDataOutput (data);
data_clean = strreplace (data_clean, "]]>", "]]><![CDATA[");
module_xml += data_clean;
} catch (Module_Exception e) { } catch (Module_Exception e) {
} }
} }
module_xml += base64Encode(data_clean);
module_xml += "]]></data></log_module>"; module_xml += "]]></data></log_module>";
/* Clean up */ /* Clean up */

View File

@ -24,6 +24,8 @@
#include <sstream> #include <sstream>
#include <stdexcept> #include <stdexcept>
#include <cstring> // for strchr #include <cstring> // for strchr
#include <vector>
#include <iterator>
using namespace Pandora; using namespace Pandora;
@ -56,6 +58,54 @@ Pandora_Strutils::trim (const string str) {
return result; return result;
} }
/**
* Encode the given string to base64.
* Based on: https://en.wikibooks.org/wiki/Algorithm_Implementation/Miscellaneous/Base64
*
* @param str String to be encoded.
*
* @return The base64 encoded string.
*/
string
Pandora_Strutils::base64Encode(string str) {
string base64_str;
std::uint32_t temp;
const static char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
std::vector<std::uint8_t> buffer(begin(str), end(str));
base64_str.reserve(((buffer.size() / 3) + (buffer.size() % 3 > 0)) * 4);
std::vector<std::uint8_t>::iterator cursor = buffer.begin();
for(size_t idx = 0; idx < buffer.size() / 3; idx++) {
temp = (*cursor++) << 16;
temp += (*cursor++) << 8;
temp += (*cursor++);
base64_str.append(1, alphabet[(temp & 0x00FC0000) >> 18]);
base64_str.append(1, alphabet[(temp & 0x0003F000) >> 12]);
base64_str.append(1, alphabet[(temp & 0x00000FC0) >> 6]);
base64_str.append(1, alphabet[(temp & 0x0000003F)]);
}
switch(buffer.size() % 3){
case 1:
temp = (*cursor++) << 16;
base64_str.append(1, alphabet[(temp & 0x00FC0000) >> 18]);
base64_str.append(1, alphabet[(temp & 0x0003F000) >> 12]);
base64_str.append(2, '=');
break;
case 2:
temp = (*cursor++) << 16;
temp += (*cursor++) << 8;
base64_str.append(1, alphabet[(temp & 0x00FC0000) >> 18]);
base64_str.append(1, alphabet[(temp & 0x0003F000) >> 12]);
base64_str.append(1, alphabet[(temp & 0x00000FC0) >> 6]);
base64_str.append(1, '=');
break;
}
return base64_str;
}
/** /**
* Convert an unicode string to a ANSI string. * Convert an unicode string to a ANSI string.
* *

View File

@ -44,6 +44,7 @@ namespace Pandora_Strutils {
string trim (const string str); string trim (const string str);
string base64Encode(string str);
string strUnicodeToAnsi (LPCWSTR s); string strUnicodeToAnsi (LPCWSTR s);
wstring strAnsiToUnicode (LPCSTR s); wstring strAnsiToUnicode (LPCSTR s);
string inttostr (const int i); string inttostr (const int i);