I have a mailing script to send colored output, but I can't use it on a Unix machine as the MIME::Lite module is not installed on it.
Can anyone suggest an alternative to get the desired output in color?
use MIME::Lite;
my (#page_html, #sujet);
my $file = 'rpt.html';
open my $ifh, '<', $file
or die "Cannot open '$file' for reading: $!";
local $/ = "";
my $contents = <$ifh>;
close( $ifh );
my $msg = new MIME::Lite;
Output:
<tr><td>test1</td><td bgcolor=red>NOK</td></tr>
<tr><td>test2</td><td bgcolor=green>OK</td></tr>
<tr><td>test3</td><td bgcolor=green>OK</td></tr>
OK Should be in green
NOK should be red
The coloured output seems to be a complete red herring (hah!) here. You have a file which you want to send as an attachment to a MIME email.
If you're going to be using Perl, then you need to be in an environment where you can install modules from CPAN. Without CPAN, you're missing most of the power of modern Perl. I suggest that it's worth having whatever discussions you need to have in order to remove that major block to your Perl programming career.
If you really can't install modules into the system libraries, then you can install them into your home directory and use use lib or PERL5LIB to adjust the Perl library path as appropriate.
When you've solved the problem of how to use CPAN modules, can we talk about your choice of modules? MIME::Lite isn't exactly deprecated, but there have been better alternatives available for over ten years. Take a look at Email::Stuffer.
But if you're determined not to have the CPAN module installation discussion, the other approach is to use the command-line program mailx to send your message.
$ mailx -a rpt.html someone#example.com
Related
This simple .pl script is supposed to grab all of the images in a directory and output an HTML — that when opened in a browser — displays all of the images in that dir at their natural dimensions.
From the mac command line, I want to just say perl myscript.pl and have it run.
… It used to run on apache in /cgi-bin.
#!/usr/bin/perl -wT
# myscript.pl
use strict;
use CGI;
use Image::Size;
my $q = new CGI;
my $imageDir = "./";
my #images;
opendir DIR, "$imageDir" or die "Can't open $imageDir $!";
#images = grep { /\.(?:png|gif|jpg)$/i } readdir DIR;
closedir DIR;
print $q->header("text/html"),
$q->start_html("Images in $imageDir"),
$q->p("Here are all the images in $imageDir");
foreach my $image (#images) {
my ($width, $height) = imgsize("$image");
print $q->p(
$q->a({-href=>$image},
$q->img({-src=>$image,
-width=>$width,
-height=>$height})
)
);
}
print $q->end_html;
Perl used to include the CGI module in the Standard Library, but it was removed in v5.22 (see The Long Death of CGI.pm). Lots of older code assumed that it would always be there, but now you have to install it yourself:
$ cpan CGI
Perl used to include the CGI module in the Standard Library, but it was removed in v5.22. Lots of older code assumed that it would always be there, but now you have to install it yourself.
The corelist program that comes with Perl is handy for checking these things:
$ corelist CGI
Data for 2020-03-07
CGI was first released with perl 5.004, deprecated (will be CPAN-only) in v5.19.7 and removed from v5.21.0
I handle this sort of thing by using the extract_modules program from my Module::Extract::Use module. Otherwise, I end up installing one module, then run again and discover another one to install, and so on:
$ extract_modules some_script.pl | xargs cpan
There's another interesting point for module writers. For a long time, we'd only list the external prerequisites in Makefile.PL. You should list even the internal ones now that Perl has a precedent for kicking modules out of the Standard Library. Along with that, specify a dependency for any module you actually use rather than relying it being in a particular distribution.
And, I was moving legacy programs around so much that I wrote a small tool, scriptdist to wrap the module infrastructure around single-file programs so I could install them as modules. The big win there is that cpan and similar tools install the prereqs for you. I haven't used it in a long time since I now just start programs as regular Perl distributions.
I am looking for ways to get file checksums in Perl but not by executing the system command cksum -- would like to do it in Perl itself because the script needs to be portable between UNIX and Windows. cksum <FILENAME> | awk '{ print $1 }' works on UNIX but obviously not in Windows. I have explored MD5 but it seems like getting a file handle is necessary and generally it doesn't seem like a very compact way to get that data (one-liner preferable).
Is there a better way?
Here are three different ways depending on which modules you have available:
use Digest::MD5 qw(md5_hex);
use File::Slurp;
print md5_hex(read_file("filename")), "\n";
use IO::All;
print md5_hex(io("filename")->all), "\n";
use IO::File;
print md5_hex(do { local $/; IO::File->new("filename")->getline }), "\n";
Not completely one-line but pretty close.
Replace Digest::MD5 with any hash algorithm you want, e.g. SHA1.
IO::File is in core and should be available everywhere, but that's the solution I personally dislike the most. Anyway, it works.
I couldn't make any of the above work for me in windows, I would always get an incorrect MD5. I got suspicious that it was being caused by differences in linebreak, but converting the file to DOS or to unix made no difference. The same code with the same file would give me the right answer on linux and the wrong one in windows. Reading the documentation, I finally found something that would work both in windows and linux:
use Digest::MD5;
open ($fh, '<myfile.txt');
binmode ($fh);
print Digest::MD5->new->addfile($fh)->hexdigest;
I hope this helps other people having difficulty in windows, I find it so weird that I didn't find any mentions to problems on windows...
This also works:
use Digest::MD5 qw(md5_base64);
...
open(HANDLE, "<", $dirItemPath);
my $cksum = md5_base64(<HANDLE>);
print "\nFile checksum = ".$cksum;
I am looking for ways to get file checksums in Perl but not by executing the system command cksum -- would like to do it in Perl itself because the script needs to be portable between UNIX and Windows. cksum <FILENAME> | awk '{ print $1 }' works on UNIX but obviously not in Windows. I have explored MD5 but it seems like getting a file handle is necessary and generally it doesn't seem like a very compact way to get that data (one-liner preferable).
Is there a better way?
Here are three different ways depending on which modules you have available:
use Digest::MD5 qw(md5_hex);
use File::Slurp;
print md5_hex(read_file("filename")), "\n";
use IO::All;
print md5_hex(io("filename")->all), "\n";
use IO::File;
print md5_hex(do { local $/; IO::File->new("filename")->getline }), "\n";
Not completely one-line but pretty close.
Replace Digest::MD5 with any hash algorithm you want, e.g. SHA1.
IO::File is in core and should be available everywhere, but that's the solution I personally dislike the most. Anyway, it works.
I couldn't make any of the above work for me in windows, I would always get an incorrect MD5. I got suspicious that it was being caused by differences in linebreak, but converting the file to DOS or to unix made no difference. The same code with the same file would give me the right answer on linux and the wrong one in windows. Reading the documentation, I finally found something that would work both in windows and linux:
use Digest::MD5;
open ($fh, '<myfile.txt');
binmode ($fh);
print Digest::MD5->new->addfile($fh)->hexdigest;
I hope this helps other people having difficulty in windows, I find it so weird that I didn't find any mentions to problems on windows...
This also works:
use Digest::MD5 qw(md5_base64);
...
open(HANDLE, "<", $dirItemPath);
my $cksum = md5_base64(<HANDLE>);
print "\nFile checksum = ".$cksum;
Am just started working for exporting excel spread sheet in PERL,
Before start i want confirmation, that is, is excel spread sheet realted plug is enabled or not,
Advise some simple PERL syntax ,
Thanks
If you are using a module from CPAN such as Excel::Writer::XLSX then you can just use a simple script to test if the module is installed:
#!/usr/bin/perl
use Excel::Writer::XLSX;
And run that script. You'll get an error about
Can't locate Excel/Writer/XLSX.pm in #INC
if the module is not installed on your system.
If by "excel plugin" you mean a CPAN module, then the solution is to try to load it and see what happens. If you wrap the loading attempt in an "eval" statement then your program won't die if it fails.
Something like this:
eval 'use Spreadsheet::ParseExcel';
my $have_module = ! $#;
This method is a little imprecise as I'm just looking to see if $# has been given a value. For more control, you might want to check the contents of $# for specific error message. You're looking for one that starts "Can't locate ...".
Assuming you mean:
How can I tell if an Excel document delivered from my webserver to a browser will open in a browser plugin (as opposed to being saved or opened in a standalone application)?
Then you can't. Browsers don't send that information to the server, so no server side process (written in Perl or otherwise) can tell.
perl -MExcel::Writer::XLSX -e "print 'ok'"
If it prints 'ok' then you're good. If you get a can't locate ... in #INC then you need to install it.
How can I check if a Perl module is part of the core - i.e. it is part of the standard installation?
I'm looking for:
a command-line command:
a Perl subroutine/function to check within code
Perhaps the question should be: How can I tell what modules were originally provided with the specific Perl installation on a machine? (Actually, it is now asked as How can I tell what modules were originally provided with the specific Perl installation on a machine?.)
Given that there now appears to not to be an overall Perl standard installation, at least the answer to this new question will tell me what I originally had in the installation when it was first installed.
With that knowledge and if I keep the original installer image/package OR know how to get the exact thing again online, then I have a repeatable Perl installation for several machines with the knowledge of what modules will be present and what modules will not.
To clarify further: I am looking at what came with the installation originally, what modules were provided as part of that installation, and what was built-in. NOT what has been installed since then.
And I want to be able to do this on the machine that has the installation. So for this I would be relying upon the installation to have a record in some form as to what it has originally.
I asked spin-off question:
How can I tell what modules were originally provided with the specific Perl installation on a machine? (How can I tell what modules were originally provided with the specific Perl installation on a machine?)
The corelist command from the Module::CoreList module will determine if a module is Core or not.
> corelist Carp
Carp was first release with perl 5
> corelist XML::Twig
XML::Twig was not in CORE (or so I think)
Here is one way to use it in a script. The Module::CoreList POD is too terse -- you have to go hunting through the source code to find what methods to call:
use strict;
use warnings;
use Module::CoreList;
my $mod = 'Carp';
#my $mod = 'XML::Twig';
my #ms = Module::CoreList->find_modules(qr/^$mod$/);
if (#ms) {
print "$mod in core\n";
}
else {
print "$mod not in core\n";
}
__END__
Carp in core
You could check perlmodlib in a sub:
my %_stdmod;
sub is_standard_module {
my($module) = #_;
unless (keys %_stdmod) {
chomp(my $perlmodlib = `perldoc -l perlmodlib`);
die "cannot locate perlmodlib\n" unless $perlmodlib;
open my $fh, "<", $perlmodlib
or die "$0: open $perlmodlib: $!\n";
while (<$fh>) {
next unless /^=head\d\s+Pragmatic\s+Modules/ ..
/^=head\d\s+CPAN/;
if (/^=item\s+(\w+(::\w+)*)/) {
++$_stdmod{ lc $1 };
}
}
}
exists $_stdmod{ lc $module } ? $module : ();
}
Example usage:
die "Usage: $0 module..\n" unless #ARGV;
foreach my $mod (#ARGV) {
my $stdmod = is_standard_module $mod;
print "$0: $mod is ", ($stdmod ? "" : "not "), "standard\n";
}
Output:
$ ./isstdmod threads::shared AnyDBM_File CGI LWP::Simple
./isstdmod: threads::shared is standard
./isstdmod: AnyDBM_File is standard
./isstdmod: CGI is standard
./isstdmod: LWP::Simple is not standard
perldoc is most definitely part of the Perl's true core and standard installation. The source distribution for perl-5.10.1, for example, contains
perldoc.PL, generates perldoc as part of the standard installation
perlmodlib.PL, generates perlmodlib.pod as part of the standard installation
This is not a new addition. Perl-5.6.0, about ten years old, had perlmodlib as part of its true-core, standard installation.
Installations that do not contain these items are non-standard. Yes, I appreciate that it may seem academic from your perspective, but your vendor's packaging permitted a non-standard installation that breaks otherwise working programs.
With Debian's package manager, you can get the standard Perl installation with
$ apt-get --install-recommends install perl
There really is no such thing as "core" any more. There used to be a standard Perl distribution, but a lot of people don't have a standard Perl distribution. Operating system distributions modify it by either adding or removing modules, changing modules, and so on. You can't rely on the standard distribution being actually standard. Some Linux distributions don't even include the Perl documentation as part of the base Perl installation.
You mention that you can't use Module::CoreList because it isn't core, but if you can create files, you can install the module. You can even pretend that you wrote it yourself.
For the really lazy, there's the Core Modules list on the perldoc.perl.org website.
You can use (for example, search for Net::FTP):
perl -MNet::FTP -e 1
If it doesn't have output, then it's installed.
Other resources
perldoc perlmodlib
perldoc perllocal
A node from perlmonks
In a response to a comment of Gbacon's, you say that you want the answer to be platform neutral. I don't know of such a solution, but I wonder if it's even the right way to go.
If your goal is to find out on specific machines, I would use the tools that come with the platform. On Debian, that would include dpkg (pre-installed on any Debian system) or apt-file (not pre-installed necessarily) or other APT tools.
As an example, take a look at the output of this:
dpkg-query -L perl | less
You would obviously need to parse the output, but it strikes me as a start precisely because it is specific to the machine in question.
From the command-line:
Let's say that you want to know
whether module Tie::Hash is
installed.
To find out, execute
the following from the command line:
perl -MTie::Hash -e 1
If you don't get any output from the above command then the module is installed; if you get an error, it's not installed.
For making this check from within the script you can make use of Module::Load::Conditional.