148 lines
4.1 KiB
Perl
148 lines
4.1 KiB
Perl
package WebGUI::Content::PDFGenerator;
|
|
|
|
use warnings;
|
|
use strict;
|
|
|
|
use List::Util qw(first);
|
|
use Scope::Guard qw(guard);
|
|
use WebGUI::Session;
|
|
use WebGUI::Content::Asset;
|
|
use WebGUI::Cache;
|
|
|
|
=head1 NAME
|
|
|
|
WebGUI::Content::PDFGenerator
|
|
|
|
=head1 DESCRIPTION
|
|
|
|
Generates a PDF of the requested URL when op=generatePdf.
|
|
|
|
=head1 PREREQUISITES
|
|
|
|
This handler depends on wkpdftohtml, which does not ship with WebGUI and is,
|
|
as of this writing, still in active development. This handler was written for
|
|
version 0.9.9. It is available from http://code.google.com/p/wkhtmltopdf/.
|
|
Compiling is rather difficult, but static binaries are available for the most
|
|
popular platforms.
|
|
|
|
=head1 INSTALLATION
|
|
|
|
Enable this content handler in your WebGUI config file, placing it somewhere
|
|
before WebGUI::Content::Operation, and add a pdfGen section to your config
|
|
file at the top level. This must contain the path to your wkhtmltopdf
|
|
executable, a cache timeout (how many seconds to cache the pdf), and
|
|
optionally the userId of a user to view the page as (defaults to Visitor). It
|
|
can also contain additional command line arguments to pass to wkhtmltopdf.
|
|
|
|
"pdfGen" : {
|
|
"exe" : "/usr/local/bin/wkhtmltopdf",
|
|
"args" : "--orientation Landscape",
|
|
"userId" : "_f7d61hs6djh0fjnxqw21",
|
|
"cacheTimeout" : 3600 # 1 hour cache timeout
|
|
},
|
|
"contentHandlers" : [
|
|
#...
|
|
"WebGUI::Content::PDFGenerator",
|
|
#...
|
|
"WebGUI::Content::Operation",
|
|
#...
|
|
"WebGUI::Content::NotFound"
|
|
],
|
|
|
|
=cut
|
|
|
|
#-------------------------------------------------------------------
|
|
# Return the cached pdf, generating if necessary.
|
|
|
|
=head2 cache ($asset)
|
|
|
|
Returns the cached PDF for an asset, if necessary
|
|
|
|
=cut
|
|
|
|
sub cache {
|
|
my $asset = shift;
|
|
my $session = $asset->session;
|
|
my $key = [
|
|
'PDFGen', $session->url->getRequestedUrl, $asset->get('revisionDate'),
|
|
];
|
|
my $cache = WebGUI::Cache->new($session, $key);
|
|
my $content = $cache->get;
|
|
unless ($content) {
|
|
$content = generate($asset);
|
|
$cache->set($content, $session->config->get('pdfGen/cacheTimeout'));
|
|
}
|
|
return $content;
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
# Generate the pdf unconditionally and return it as a string.
|
|
|
|
=head2 generate ($asset)
|
|
|
|
Generate the pdf unconditionally and return it as a string.
|
|
|
|
=cut
|
|
|
|
sub generate {
|
|
my $asset = shift;
|
|
my $session = $asset->session;
|
|
my $url = $session->url;
|
|
my $c = $session->config;
|
|
my $o = $c->get('pdfGen');
|
|
my $login = WebGUI::Session->open($c->getWebguiRoot, $c->getFilename);
|
|
my $guard = guard { $login->var->end; $login->close };
|
|
$login->user({ userId => $o->{userId} || 1 });
|
|
my @args = (
|
|
$o->{exe}, @{$o->{args} || []},
|
|
'--cookie', $c->get('cookieName'), $login->getId,
|
|
$url->getSiteURL . $url->gateway($url->getRequestedUrl),
|
|
'-'
|
|
);
|
|
|
|
# We're using backticks because trying to run external programs from a
|
|
# mod_perl process is extremely tricky any other way, but TODO: figure out
|
|
# use a real call and pass an array of args, as that would be safer.
|
|
my $cmd = join ' ', @args;
|
|
`$cmd`;
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 cache ($asset)
|
|
|
|
Figure out which asset we need to check permissions for
|
|
|
|
=cut
|
|
|
|
sub getRequestedAsset {
|
|
my $session = shift;
|
|
my $assetUrl = $session->url->getRequestedUrl;
|
|
my $perms = WebGUI::Content::Asset::getUrlPermutations($assetUrl);
|
|
foreach my $url (@$perms) {
|
|
if (my $asset = WebGUI::Content::Asset::getAsset($session, $url)) {
|
|
return $asset;
|
|
}
|
|
}
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
# Top-level handler.
|
|
|
|
=head2 handler ($session)
|
|
|
|
Top-level handler
|
|
|
|
=cut
|
|
|
|
sub handler {
|
|
my $session = shift;
|
|
my $op = $session->form->get('op');
|
|
return undef unless $op && $op eq 'generatePdf';
|
|
my $asset = getRequestedAsset($session);
|
|
return $session->privilege->noAccess unless $asset->canView;
|
|
$session->http->setMimeType('application/pdf');
|
|
return cache($asset);
|
|
}
|
|
|
|
1;
|