Log::Log4perl: one appender to the file in UTF-8 and another to the screen in CP866 on win32 - encoding

I have Log::Log4perl config with two appenders to file and screen, like this:
log4perl.logger.bc_log = INFO, bc_log, console
log4perl.appender.bc_log = Log::Log4perl::Appender::File
log4perl.appender.bc_log.filename = bc.log
log4perl.appender.bc_log.layout = Log::Log4perl::Layout::PatternLayout
log4perl.appender.bc_log.layout.ConversionPattern = %d{ISO8601}%d{Z} %H %m%n
log4perl.appender.console = Log::Log4perl::Appender::Screen
log4perl.appender.console.stderr = 1
log4perl.appender.console.layout = Log::Log4perl::Layout::PatternLayout
log4perl.appender.console.layout.ConversionPattern = %m%n
In my program all output explicitly converted to utf8 (from cp1251 for example) and somewhere in my program:
my $bc_log = Log::Log4perl->get_logger('bc_log');
$bc_log->info('Some-utf8-encoded-string');
So message goes in utf8 both to file and console, but I would like
utf8 for file and cp866 for console in one shot.
I can't figure out is it possible in Log::Log4perl?
Looks like Log::Log4perl::Appender::File has no encoding options.

I created a new appender module (by copy original Log::Log4perl::Appender::Screen) with decoding/encoding added and use it insteed of Log::Log4perl::Appender::Screen in my code.

Related

Monolog rotating log not formatted correctly

Using monolog (3.2) with rotating logs handler.
Everything works fine BUT, the rotated logs don't use the log format I set.
The main log is fine; the dated logs use the default output format instead.
It looks like the RotatingFileHandler should inherit format from parent, but for some reason it isn't. I'm mystified.
$log = $dir . '/today.log';
$outputFormat = "[%datetime%] %level_name% > %message% %context% %extra%\n";
$dateFormat = 'Y-m-d H:i';
$line_format = new LineFormatter($outputFormat, $dateFormat);
$stream = new StreamHandler($log, Level::Debug);
$stream->setFormatter($line_format);
// u\echor($stream,'stream',STOP);
$logger -> pushHandler($stream);
$fileHandler = new RotatingFileHandler($log,5);
$logger->pushHandler($fileHandler);
...

Text::CSV_XS No such file or directory at

on my webapp (with Mojolicious), a user can upload a csv file, but i am unable to "save" it in a state variable, error:
[2019-03-08 11:06:07.40615] [2095] [error] test1 ;test2;test 3;Test4;"TES;T5"
10;20;30;40;"asd;asd,asd"
11;12;13;14;15
100;95;90;85;80
: No such file or directory at /media/sf_projects/my_app/script/../lib/MyApp/Plugin/Csv.pm line 15.
so as we can see, the error also shows the content of my csv...
Bizarrely it works, when i load a csv file from my hdd (w/o the webapp).
code of the sub that's called by the post method:
return $self->redirect_to('/') unless my $newCsv = $self->req->upload('fileToUpload')->slurp;
$self->csv_load($newCsv);
"csv_load" is in a mojo plugin (the plugin of the error message Plugin/Csv.pm) which calls the following sub:
sub _loadCsv {
my $controller = shift;
my $fileLocation = shift;
my $file = csv( in => $fileLocation, #this is line 15 of the error
headers => 'auto',
sep => ';');
$controller->csvModel->set_array($file);
}
You are sending the contents of the CSV file as an argument to the _loadCsv, which expects the file location to be the argument.

Read meta information from PDF using Perl module Image::ExifTool

I would like to read meta information from PDF using Perl module Image::ExifTool. I need to process PDFs using cross reference streams (as of PDF 1.5), and the other well established modules like PDF::API2 and CAM::PDF seem not to support them or have limited support.
Anyway, Image::ExifTool reads apparently a number of PDF tags, but if I run the following code:
use Image::ExifTool qw(:Public);
my $file = 'file.pdf';
my $exifTool = new Image::ExifTool;
$exifTool->ExtractInfo($file);
my #tagList = $exifTool->GetFoundTags('File');
for (#tagList){
print "$_\n"
}
I do not seem to be able to get more then these tags:
ExifToolVersion
FileName
Directory
FileSize
FileModifyDate
FileAccessDate
FileCreateDate
FilePermissions
FileType
FileTypeExtension
MIMEType
PDFVersion
Linearized
Author
CreateDate
Creator (1)
ModifyDate
Producer (1)
Subject
Title (1)
XMPToolkit
CreateDate (1)
CreatorTool
ModifyDate (1)
MetadataDate
Producer
Format
Title
Description
Creator
DocumentID
InstanceID
PageLayout
PageMode
PageCount
In particular, I would like to get e.g. the PDF document catalog (Root tag). However running a code like this doesn't return any value:
my $tag = 'Root';
my $exifTool = new Image::ExifTool;
my $info = $exifTool->ImageInfo($file, $tag);
for (sort keys %$info) {
print "$_ => $$info{$_}\n";
}
Help please :-)
To see the parsing enable verbose mode: $exifTool->Options(Verbose => 1); It shows that the Root is indeed being parsed.
7) Root (SubDirectory) -->
+ [Root directory with 7 entries]
| 0) Metadata (SubDirectory) -->
| + [Metadata directory with 3 entries]
I'm unsure what data you need from the root tag, but it's possible to get with the internal API: my $roottag = Image::ExifTool::GetTagTable('Image::ExifTool::PDF::Root');
From Image::ExifTool:
exports not part of the public API, but used by ExifTool modules:

Could not open file perl

I am trying to convert a plist files into a JUnit style XMLs. I have a xsl stylesheet which converts the plist to JUnit/ANT XML.
Here is the perl code which I run to convert the plist to XML:
my $parser = XML::LibXML->new();
my $xslt = XML::LibXSLT->new();
my $stylesheet = $xslt->parse_stylesheet_file("\\\~/Hudson/build/workspace/ui-automation/automation\\\ test\\\ suite/plist2junit.xsl");
my $counter = 1;
my #plistFiles = glob('Logs/*/*.plist');
foreach (#plistFiles){
#Escape the file path and specify abosulte path
my $plistFile = $_;
$plistFile =~ s/([ ()])/\\$1/g;
$path2plist = "\\\~/Hudson/build/workspace/ui-automation/automation\\\ test\\\ suite/$plistFile";
#transform the plist file to xml
my $source = $parser->parse_file($path2plist);
my $results = $stylesheet->transform($source);
my $resultsFile = "\\\~/Hudson/build/workspace/ui-automation/automation\\\ test\\\ suite/JUnit/results$counter.xml";
#create the output file
unless(open FILE, '>'.$resultsFile) {
# Die with error message
die "\nUnable to create $file\n";
}
# Write results to the file.
$stylesheet->output_file($results, FILE);
close FILE;
$counter++;
}
After running the perl script on Hudson/Jenkins, it outputs this error message:
Couldn't open ~/Hudson/build/workspace/ui-automation/automation\ test\ suite/Logs/Run\ 1/Automation\ Results.plist: No such
file or directory
The error is caused by my $source = $parser->parse_file($path2plist); in the code. I am unable to figure out why it cannot find/read the file.
Anyone know what might be causing the error?
There are three obvious error in the path mentioned in the error message.
~/Hudson/build/workspace/ui-automation/automation\ test\ suite/Logs/Run\ 1/Automation\ Results.plist
Those are:
There's no directory named ~ in the current directory. Perhaps you meant to use the value of $ENV{HOME} there?
There's no directory named automation\ test\ suite anywhere on your disk, but there is probably one named automation test suite.
Similarly, there's no directory named Run\ 1 anywhere on your disk, but there is probably one named Run 1.

First 8 bytes are always wrong when downloading a file from my script

I have a Mojolicious Lite script that "gives out" an executable file (user can download the file from the script's URL). I keep encoded data in an inline template in DATA section, then encode it and render_data.
get '/download' => sub {
my $self = shift;
my $hex_data = $self->render_partial( 'TestEXE' );
my $bin_data;
while( $hex_data =~ /([^\n]+)\n?/g ) {
$bin_data .= pack "H".(length $1), $1;
}
my $headers = Mojo::Headers->new;
$headers->add( 'Content-Type', 'application/x-download;name=Test.exe' );
$headers->add( 'Content-Disposition', 'attachment;filename=Test.exe' );
$headers->add( 'Content-Description', 'File Transfer');
$self->res->content->headers($headers);
$self->render_data( $bin_data );
};
__DATA__
## TestEXE.html.ep
4d5a90000300000004000000ffff0000b8000000000000004000000000000000
00000000000000000000000000000000000000000000000000000000b0000000
0e1fba0e00b409cd21b8014ccd21546836362070726f6772616d2063616e6e6f
....
When I run this locally (via built in webserver on http://127.0.0.1:3000/, Win7) I get the correct file (size and contents). But when I run it in CGI mode on shared hosting (Linux), it comes back with correct size, but first 8 bytes of the file are always incorrect (and always different). The rest of the file is correct.
If in my sub i specify $hex_data instead of $bin_data I get what suppose to be there.
I'm at lost.
render_partial isn't what you want.
First, re-encode the executable in base64 format, and specify that the template is base64 encoded (This is assuming hex is not a requirement for your app):
## template-name (base64)
Also, you don't actually need a controller method at all. Mojolicious will handle the process for you - all you have to do is appropriately name the template.
use Mojolicious::Lite;
app->start;
__DATA__
## Test.exe (base64)
...
http://127.0.0.1:3000/Test.exe will then download the file.
-
If you still want to use a controller method for app-specific concerns, get the data template specifically:
use Mojolicious::Lite;
get '/download' => sub {
my $self = shift;
# http://mojolicio.us/perldoc/Mojolicious/Renderer.pm#get_data_template
my $data = $self->app->renderer->get_data_template({}, 'Test.exe');
# Replace content-disposition instead of adding it,
# to prevent duplication from elsewhere in the app
$self->res->headers->header(
'Content-Disposition', 'attachment;filename=name.exe');
$self->render_data($data);
};
app->start;
__DATA__
## Test.exe (base64)
...
http://127.0.0.1:3000/download will get the template, set the header, and then download it as name.exe.