Skip to content

Commit

Permalink
Item12453:
Browse files Browse the repository at this point in the history
   * added outfile for named pdf exports
   * improved cleanup of non printable chars that sneak in via copy&paste 
   * don't use viewfile directly. let the http server decide
   * fixing http <-> https hassles loading resources
   



git-svn-id: http://svn.foswiki.org/trunk/GenPDFPrincePlugin@16634 0b4bb1d4-4e5a-0410-9cc4-b2b747904278
  • Loading branch information
MichaelDaum authored and MichaelDaum committed Mar 28, 2013
1 parent fe72338 commit c29052b
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 31 deletions.
13 changes: 11 additions & 2 deletions data/System/GenPDFPrincePlugin.txt
Expand Up @@ -19,9 +19,17 @@ server license with a specific sales discount granted to Foswiki users.

Get a PDF by adding =contenttype=application/pdf= to the view url like this:
<verbatim class="tml">
%SCRIPTURL{"view"}/%WEB%/%TOPIC%?contenttype=application/pdf
%SCRIPTURL{"view"}/%WEB%/%TOPIC%?contenttype=application/pdf&cover=print
</verbatim>

Optionally an url parameter =outfile= can be used to specifiy the target filename of the pdf being generated.
If not specified explicitly it defaults to =genpdf_%!TOPIC%.pdf=

<verbatim class="tml">
%SCRIPTURL{"view"}/%WEB%/%TOPIC%?contenttype=application/pdf&cover=print&outfile=myreport.pdf
</verbatim>


Here's the complete Foswiki documentation in [[%SCRIPTURL{"view"}%/%SYSTEMWEB%/CompleteDocumentation?contenttype=application/pdf][PDF]].

---++ Installation
Expand All @@ -45,11 +53,12 @@ Note, that !ZonePlugin is not required anymore in newer Foswiki engines > 1.1.0.
* Set SHORTDESCRIPTION = 'Generate PDF using Prince XML';
-->
| Author: | Foswiki:Main.MichaelDaum |
| Copyright: | &copy; 2009-2012, Michael Daum http://michaeldaumconsulting.com |
| Copyright: | &copy; 2009-2013, Michael Daum http://michaeldaumconsulting.com |
| License: | GPL ([[http://www.gnu.org/copyleft/gpl.html][GNU General Public License]]) |
| Release: | %$RELEASE% |
| Version: | %$VERSION% |
| Change History: | <!-- versions below in reverse order -->&nbsp; |
| 18 Mar 2013 | added outfile url param to specify the file name of the pdf being generated |
| 08 Mar 2012 | fixed encoding of charset fed to prince xml; \
rewrite img urls from http: to file: urls while prince works on the local filesystem generating pdf |
| 17 Nov 2010 | using legacy interface =mkpath= to =make_path= to please older perl versions |
Expand Down
72 changes: 43 additions & 29 deletions lib/Foswiki/Plugins/GenPDFPrincePlugin.pm
@@ -1,6 +1,6 @@
# Plugin for Foswiki - The Free and Open Source Wiki, http://foswiki.org/
#
# Copyright (C) 2009-2012 Michael Daum http://michaeldaumconsulting.com
# Copyright (C) 2009-2013 Michael Daum http://michaeldaumconsulting.com
#
# This license applies to GenPDFPrincePlugin *and also to any derivatives*
#
Expand All @@ -19,15 +19,16 @@
package Foswiki::Plugins::GenPDFPrincePlugin;

use strict;
use warnings;

use Foswiki::Func ();
use Foswiki::Plugins ();
use Error qw(:try);
use File::Path ();
use Encode ();

our $VERSION = '$Rev: 4419 (2009-07-03) $';
our $RELEASE = '1.32';
our $VERSION = '1.40';
our $RELEASE = '1.40';
our $SHORTDESCRIPTION = 'Generate PDF using Prince XML';
our $NO_PREFS_IN_TOPIC = 1;
our $baseTopic;
Expand Down Expand Up @@ -66,48 +67,58 @@ sub completePageHandler {
require File::Temp;
require Foswiki::Sandbox;

my $content = Encode::decode($Foswiki::cfg{Site}{CharSet}, $_[0]);

# remove left-overs
$_[0] =~ s/([\t ]?)[ \t]*<\/?(nop|noautolink)\/?>/$1/gis;
$content =~ s/([\t ]?)[ \t]*<\/?(nop|noautolink)\/?>/$1/gis;
$content =~ s/<!--.*?-->//g;
$content =~ s/[\0-\x08\x0B\x0C\x0E-\x1F\x7F]+/ /g;

# clean url params in anchors as prince can't generate proper xrefs otherwise;
# hope this gets fixed in prince at some time
$_[0] =~ s/(href=["'])\?.*(#[^"'\s])+/$1$2/g;
$content =~ s/(href=["'])\?.*(#[^"'\s])+/$1$2/g;

# rewrite some urls to use file://..
#$_[0] =~ s/(<link[^>]+href=["'])([^"']+)(["'])/$1.toFileUrl($2).$3/ge;
$_[0] =~ s/(<img[^>]+src=["'])([^"']+)(["'])/$1.toFileUrl($2).$3/ge;
#$content =~ s/(<link[^>]+href=["'])([^"']+)(["'])/$1.toFileUrl($2).$3/ge;
$content =~ s/(<img[^>]+src=["'])([^"']+)(["'])/$1.toFileUrl($2).$3/ge;

# create temp files
my $htmlFile = new File::Temp(SUFFIX => '.html', UNLINK => (DEBUG?0:1));
my $errorFile = new File::Temp(SUFFIX => '.log', UNLINK => (DEBUG?0:1));
my $htmlFile = new File::Temp(SUFFIX => '.html', UNLINK => (DEBUG ? 0 : 1));
my $errorFile = new File::Temp(SUFFIX => '.log', UNLINK => (DEBUG ? 0 : 1));

# create output filename
my ($pdfFilePath, $pdfFile) = getFileName($baseWeb, $baseTopic);

# creater html file
my $content = Encode::decode($Foswiki::cfg{Site}{CharSet}, $_[0]);
$content = Encode::encode($Foswiki::cfg{Site}{CharSet}, $content);

binmode($htmlFile);
print $htmlFile $content;
writeDebug("htmlFile=".$htmlFile->filename);
writeDebug("htmlFile=" . $htmlFile->filename);

# create prince command
my $session = $Foswiki::Plugins::SESSION;
my $pubUrl = $session->getPubUrl(1); # SMELL: unofficial api
my $princeCmd = $Foswiki::cfg{GenPDFPrincePlugin}{PrinceCmd} ||
'/usr/bin/prince --baseurl %BASEURL|U% -i html -o %OUTFILE|F% %INFILE|F% --log=%ERROR|F%';
my $pubUrl = $session->getPubUrl(1); # SMELL: unofficial api
my $princeCmd = $Foswiki::cfg{GenPDFPrincePlugin}{PrinceCmd}
|| '/usr/bin/prince --baseurl %BASEURL|U% -i html -o %OUTFILE|F% %INFILE|F% --log=%ERROR|F%';

writeDebug("princeCmd=$princeCmd");
writeDebug("BASEURL=$pubUrl");

# execute
my ($output, $exit) = Foswiki::Sandbox->sysCommand(
$princeCmd,
BASEURL => $pubUrl,
OUTFILE => $pdfFilePath,
INFILE => $htmlFile->filename,
ERROR => $errorFile->filename,
);
$princeCmd,
BASEURL => $pubUrl,
OUTFILE => $pdfFilePath,
INFILE => $htmlFile->filename,
ERROR => $errorFile->filename,
);

local $/ = undef;

writeDebug("errorFile=" . $errorFile->filename);
writeDebug("htmlFile=" . $htmlFile->filename);

my $error = '';
if ($exit || DEBUG) {
$error = <$errorFile>;
Expand All @@ -117,17 +128,19 @@ sub completePageHandler {
writeDebug("GenPDFPrincePlugin - output=$output");

if ($exit) {
my $html = $_[0];
my $html = $content;
my $line = 1;
$html = '00000: '.$html;
$html = '00000: ' . $html;
$html =~ s/\n/"\n".(sprintf "\%05d", $line++).": "/ge;
throw Error::Simple("execution of prince failed ($exit): \n\n$error\n\n$html");
}

my $url = Foswiki::Func::getScriptUrl($baseWeb, $baseTopic, 'viewfile',
filename=>$pdfFile,
t=>time(),
);
# not using viewfile to let the web server decide how to deliver the static file
#my $url = Foswiki::Func::getScriptUrl($baseWeb, $baseTopic, 'viewfile',
# filename=>$pdfFile,
# t=>time(),
#);
my $url = $Foswiki::cfg{PubUrlPath} . '/' . $baseWeb . '/' . $baseTopic . '/' . $pdfFile . '?t=' . time();

Foswiki::Func::redirectCgiQuery($query, $url);
}
Expand All @@ -136,7 +149,9 @@ sub completePageHandler {
sub getFileName {
my ($web, $topic) = @_;

my $fileName = $topic;
my $query = Foswiki::Func::getCgiQuery();
my $fileName = $query->param("outfile") || 'genpdf_'.$topic.'.pdf';

$fileName =~ s{[\\/]+$}{};
$fileName =~ s!^.*[\\/]!!;
$fileName =~ s/$Foswiki::regex{filenameInvalidCharRegex}//go;
Expand All @@ -145,7 +160,6 @@ sub getFileName {
my $filePath = Foswiki::Func::getPubDir().'/'.$web.'/'.$topic;
File::Path::mkpath($filePath);

$fileName = 'genpdf_'.$fileName.'.pdf';
$filePath .= '/'.$fileName;

return ($filePath, $fileName);
Expand All @@ -157,7 +171,7 @@ sub toFileUrl {

my $fileUrl = $url;

if ($fileUrl =~ /^(?:https?:\/\/$Foswiki::cfg{DefaultUrlHost})?$Foswiki::cfg{PubUrlPath}(.*)$/) {
if ($fileUrl =~ /^(?:$Foswiki::cfg{DefaultUrlHost})?$Foswiki::cfg{PubUrlPath}(.*)$/) {
$fileUrl = $1;
$fileUrl =~ s/\?.*$//;
if ($fileUrl =~ /^\/(.*)\/([^\/]+)\/[^\/]+$/) {
Expand Down

0 comments on commit c29052b

Please sign in to comment.